![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 #ifndef __smoab_FaceSets_h
00002 #define __smoab_FaceSets_h
00003
00004 #include "CellSets.h"
00005 #include
00006
00007 namespace smoab
00008 {
00009 //----------------------------------------------------------------------------
00010 class FaceCellSet : public CellSet
00011 {
00012 public:
00013 FaceCellSet( int id, smoab::EntityHandle p, const smoab::Range& cells ) : CellSet( p, cells ), ID( id ) {}
00014
00015 int faceId() const
00016 {
00017 return ID;
00018 }
00019 void overrideFaceId( int i )
00020 {
00021 ID = i;
00022 } //USE AT YOUR OWN RISK
00023
00024 private:
00025 int ID;
00026 };
00027
00028 //----------------------------------------------------------------------------
00029 typedef std::vector< FaceCellSet > FaceCellSets;
00030
00031 //----------------------------------------------------------------------------
00032 //class that store the regions that a faces is adjacent too
00033 struct FacesAdjRegions
00034 {
00035 FacesAdjRegions( int f, smoab::EntityHandle r0, smoab::EntityHandle r1 ) : FaceId( f ), Region0( r0 ), Region1( r1 )
00036 {
00037 if( r0 > r1 )
00038 {
00039 std::swap( this->Region0, this->Region1 );
00040 }
00041 }
00042
00043 FacesAdjRegions( int f ) : FaceId( f ), Region0( -3 ), Region1( -2 ) {}
00044
00045 bool operator<( const FacesAdjRegions& other ) const
00046 {
00047 return ( this->FaceId < other.FaceId );
00048 }
00049
00050 smoab::EntityHandle otherId( smoab::EntityHandle other ) const
00051 {
00052 if( other == Region0 )
00053 {
00054 return Region1;
00055 }
00056 return Region0;
00057 }
00058
00059 int FaceId;
00060 smoab::EntityHandle Region0;
00061 smoab::EntityHandle Region1;
00062 };
00063 //----------------------------------------------------------------------------
00064 smoab::FaceCellSets findFaceSets( smoab::CellSets shells,
00065 smoab::CellSets boundaries,
00066 std::set< smoab::FacesAdjRegions >& faceMaps )
00067 {
00068 typedef smoab::CellSets::iterator iterator;
00069 typedef smoab::FaceCellSets::iterator faceIterator;
00070 typedef std::set< smoab::FacesAdjRegions >::const_iterator FaceAdjIterator;
00071
00072 //we need to properly label each unique face in shells
00073 //we do this by intersecting each shell with each other shell
00074 //to find shell on shell contact, and than we intersect each
00075 //resulting shell with the boundary conditions
00076 //the end result of these intersections will be the new modelfaces
00077 int faceId = 1;
00078 smoab::FaceCellSets shellFaces;
00079
00080 //first intersect each shell with each other shell
00081 std::set< smoab::FacesAdjRegions > shellFaceContacts;
00082 for( iterator i = shells.begin(); i != shells.end(); ++i )
00083 {
00084 //copy the cells so we can add a face that represents
00085 //all the cells of the region that aren't shared with another region
00086 int numCells = i->cells().size(); //size() on range is slow, so cache it
00087 for( iterator j = i + 1; j != shells.end() && numCells > 0; ++j )
00088 {
00089 //intersect i and j to make a new face
00090 smoab::Range intersection = smoab::intersect( i->cells(), j->cells() );
00091 if( !intersection.empty() )
00092 {
00093 //don't want to increment faceId when the intersection is empty
00094 smoab::FaceCellSet face( faceId++, i->entity(), intersection );
00095 shellFaces.push_back( face );
00096 i->erase( intersection );
00097 j->erase( intersection );
00098 numCells -= intersection.size();
00099
00100 //add this to the face map
00101 smoab::FacesAdjRegions faceInfo( faceId - 1, i->entity(), j->entity() );
00102 shellFaceContacts.insert( faceInfo );
00103 }
00104 }
00105 //if all the cells for shell i are used, don't add a new
00106 //empty face
00107 if( numCells > 0 )
00108 {
00109 smoab::FaceCellSet face( faceId++, i->entity(), i->cells() );
00110 shellFaces.push_back( face );
00111
00112 //add this to the face map
00113 smoab::FacesAdjRegions faceInfo( faceId - 1, -1, i->entity() );
00114 shellFaceContacts.insert( faceInfo );
00115 }
00116 }
00117
00118 //now we have all the faces that match shell on shell contact
00119 //we know process all the new faces to see if they intersect
00120 //with any boundary sets. A boundary set can span multiple
00121 //shells so we want to process it as a second loop
00122
00123 //store the end before we start adding boundary faces, which
00124 //we don't need to check agianst other boundaries
00125 faceId = 1; //reset the faced id
00126
00127 //store in a new face set, expanding the current one causes incorrect results
00128 smoab::FaceCellSets faces;
00129 for( faceIterator i = shellFaces.begin(); i != shellFaces.end(); ++i )
00130 {
00131 //determine from the shell faces if the new face we are creating
00132 //is bounded by two regions or just one
00133 smoab::FacesAdjRegions idToSearchFor( i->faceId() );
00134 FaceAdjIterator adjRegions = shellFaceContacts.find( idToSearchFor );
00135 smoab::EntityHandle otherRegionId = adjRegions->otherId( i->entity() );
00136
00137 int numCells = i->cells().size(); //size() on range is slow, so cache it
00138 for( iterator j = boundaries.begin(); j != boundaries.end(); ++j )
00139 {
00140 smoab::Range intersect = smoab::intersect( i->cells(), j->cells() );
00141 if( !intersect.empty() )
00142 {
00143 //don't want to increment faceId when the intersection is empty
00144 smoab::FaceCellSet face( faceId++, j->entity(), intersect );
00145 faces.push_back( face );
00146 i->erase( intersect );
00147 numCells -= intersect.size();
00148 smoab::FacesAdjRegions faceInfo( faceId - 1, i->entity(), otherRegionId );
00149 faceMaps.insert( faceInfo );
00150 }
00151 }
00152 if( numCells > 0 )
00153 {
00154 smoab::FaceCellSet face( faceId++, i->entity(), i->cells() );
00155 faces.push_back( face );
00156 smoab::FacesAdjRegions faceInfo( faceId - 1, i->entity(), otherRegionId );
00157 faceMaps.insert( faceInfo );
00158 }
00159 }
00160 return faces;
00161 }
00162
00163 //----------------------------------------------------------------------------
00164 template < typename T >
00165 std::vector< T > faceIdsPerCell( const smoab::FaceCellSets& faces )
00166 {
00167 typedef smoab::FaceCellSets::const_iterator iterator;
00168 typedef std::vector< smoab::EntityHandle >::const_iterator EntityHandleIterator;
00169 typedef smoab::Range::const_iterator RangeIterator;
00170
00171 //find all the cells that are in the faceCellSet, and than map
00172 //the proper face id to that relative position, here comes lower_bounds!
00173 std::vector< smoab::EntityHandle > searchableCells;
00174 smoab::Range faceRange = smoab::getAllCells( faces );
00175 smoab::RangeToVector( faceRange, searchableCells );
00176
00177 //faceIds will be the resulting array
00178 std::vector< T > faceIds( searchableCells.size() );
00179
00180 //construct the start and end iterators for the lower bounds call
00181
00182 EntityHandleIterator s_begin = searchableCells.begin();
00183 EntityHandleIterator s_end = searchableCells.end();
00184
00185 //search the face cell sets
00186 for( iterator i = faces.begin(); i != faces.end(); ++i )
00187 {
00188 T value = static_cast< T >( i->faceId() );
00189 const smoab::Range& entitiesCells = i->cells();
00190 for( RangeIterator j = entitiesCells.begin(); j != entitiesCells.end(); ++j )
00191 {
00192 EntityHandleIterator result = std::lower_bound( s_begin, s_end, *j );
00193 std::size_t newId = std::distance( s_begin, result );
00194 faceIds[newId] = value;
00195 }
00196 }
00197 return faceIds;
00198 }
00199
00200 //----------------------------------------------------------------------------
00201 //given a face adjacency, determine the regions spare tag values
00202 template < typename T >
00203 std::pair< T, T > FaceAdjRegionValues( const smoab::FacesAdjRegions& faceAdj,
00204 smoab::Tag* t,
00205 const smoab::Interface& interface )
00206 {
00207 std::pair< T, T > returnValue;
00208 const int defaultValue = interface.getDefaultTagVaue< int >( *t );
00209
00210 /*
00211 * IF A REGION IS SET TO -1 WE NEED TO PUSH THAT VALUE DOWN
00212 * AS THE MATERIAL, SINCE THE MOAB DEFAULT TAG VALUE WILL
00213 * BE CONSIDIERED A REGION, AND WE WANT TO SAY IT BOUNDS THE
00214 * VOID REGION
00215 */
00216 int tagValue = defaultValue; //use tagValue to pass in default value
00217 if( faceAdj.Region0 != -1 )
00218 {
00219 tagValue = interface.getTagData( *t, faceAdj.Region0, tagValue );
00220 }
00221 else
00222 {
00223 tagValue = -1;
00224 }
00225
00226 //set the first region tag value into the pair we are returing
00227 returnValue.first = static_cast< T >( tagValue );
00228
00229 tagValue = defaultValue; //use tagValue to pass in default value
00230 tagValue = interface.getTagData( *t, faceAdj.Region1, tagValue );
00231 if( faceAdj.Region1 != -1 )
00232 {
00233 tagValue = interface.getTagData( *t, faceAdj.Region1, tagValue );
00234 }
00235 else
00236 {
00237 tagValue = -1;
00238 }
00239 returnValue.second = static_cast< T >( tagValue );
00240
00241 return returnValue;
00242 }
00243
00244 } // namespace smoab
00245
00246 #endif