Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 /* 00002 * MOAB, a Mesh-Oriented datABase, is a software component for creating, 00003 * storing and accessing finite element mesh data. 00004 * 00005 * Copyright 2007 Sandia Corporation. Under the terms of Contract 00006 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 00007 * retains certain rights in this software. 00008 * 00009 * This library is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 2.1 of the License, or (at your option) any later version. 00013 * 00014 */ 00015 00016 /**\class moab::SplitVertices 00017 *\brief A dictionary of new vertices. 00018 * 00019 * An array of existing vertex ids used as a key in a dictionary of new vertices. 00020 */ 00021 #ifndef MOAB_SPLIT_VERTICES_HPP 00022 #define MOAB_SPLIT_VERTICES_HPP 00023 00024 #include "moab/Types.hpp" 00025 #include "ProcessSet.hpp" 00026 #include "MBTagConventions.hpp" 00027 00028 #include <map> 00029 #include <vector> 00030 #include <algorithm> 00031 00032 #undef MB_DEBUG 00033 00034 namespace moab 00035 { 00036 00037 class RefinerTagManager; 00038 00039 template < int _n > 00040 class SplitVertexIndex 00041 { 00042 public: 00043 SplitVertexIndex() {} 00044 SplitVertexIndex( const int* src ) 00045 { 00046 for( int i = 0; i < _n; ++i ) 00047 this->ids[i] = src[i]; 00048 std::sort( this->ids, this->ids + _n ); 00049 } 00050 SplitVertexIndex( const SplitVertexIndex< _n >& src ) 00051 { 00052 for( int i = 0; i < _n; ++i ) 00053 this->ids[i] = src.ids[i]; 00054 this->process_set = src.process_set; 00055 } 00056 SplitVertexIndex& operator=( const SplitVertexIndex< _n >& src ) 00057 { 00058 for( int i = 0; i < _n; ++i ) 00059 this->ids[i] = src.ids[i]; 00060 this->process_set = src.process_set; 00061 return *this; 00062 } 00063 00064 void set_common_processes( const ProcessSet& procs ) 00065 { 00066 this->process_set = procs; 00067 } 00068 ProcessSet& common_processes() 00069 { 00070 return this->process_set; 00071 } 00072 const ProcessSet& common_processes() const 00073 { 00074 return this->process_set; 00075 } 00076 00077 bool operator<( const SplitVertexIndex< _n >& other ) const 00078 { 00079 // Ignore the process set. Only program errors lead to mismatched process sets with 00080 // identical ids. 00081 for( int i = 0; i < _n; ++i ) 00082 if( this->ids[i] < other.ids[i] ) 00083 return true; 00084 else if( this->ids[i] > other.ids[i] ) 00085 return false; 00086 return false; 00087 } 00088 00089 int ids[_n + 1]; 00090 ProcessSet process_set; 00091 }; 00092 00093 template < int _n > 00094 std::ostream& operator<<( std::ostream& os, const SplitVertexIndex< _n >& idx ) 00095 { 00096 for( int i = 0; i < _n; ++i ) 00097 { 00098 os << idx.ids[i] << " "; 00099 } 00100 os << "(" << idx.process_set << ")"; 00101 return os; 00102 } 00103 00104 class EntitySourceRecord 00105 { 00106 public: 00107 EntitySourceRecord() {} 00108 EntitySourceRecord( int nc, EntityHandle ent, const ProcessSet& procs ) 00109 { 00110 this->ids.resize( nc ); 00111 this->handle = ent; 00112 this->process_set = procs; 00113 } 00114 EntitySourceRecord( const EntitySourceRecord& src ) 00115 { 00116 this->handle = src.handle; 00117 this->process_set = src.process_set; 00118 this->ids = src.ids; 00119 } 00120 EntitySourceRecord& operator=( const EntitySourceRecord& src ) 00121 { 00122 this->handle = src.handle; 00123 this->process_set = src.process_set; 00124 this->ids = src.ids; 00125 return *this; 00126 } 00127 00128 void set_common_processes( const ProcessSet& procs ) 00129 { 00130 this->process_set = procs; 00131 } 00132 ProcessSet& common_processes() 00133 { 00134 return this->process_set; 00135 } 00136 const ProcessSet& common_processes() const 00137 { 00138 return this->process_set; 00139 } 00140 00141 bool operator<( const EntitySourceRecord& other ) const 00142 { 00143 // assert( this->ids.size() == other.ids.size() ); 00144 std::vector< int >::size_type N = this->ids.size(); 00145 std::vector< int >::size_type i; 00146 // Ignore the process set. Only program errors lead to mismatched process sets with 00147 // identical ids. 00148 for( i = 0; i < N; ++i ) 00149 if( this->ids[i] < other.ids[i] ) 00150 return true; 00151 else if( this->ids[i] > other.ids[i] ) 00152 return false; 00153 return false; 00154 } 00155 00156 std::vector< int > ids; 00157 ProcessSet process_set; 00158 EntityHandle handle; 00159 }; 00160 00161 /** A non-templated base class that the SplitVertices template subclasses all share. 00162 * 00163 * All methods that need to be accessed by other classes should be 00164 * declared by the base class so that no knowledge of template parameters 00165 * is required. 00166 */ 00167 class SplitVerticesBase 00168 { 00169 public: 00170 SplitVerticesBase( RefinerTagManager* tag_mgr ); 00171 virtual ~SplitVerticesBase(); 00172 00173 virtual bool find_or_create( const EntityHandle* split_src, 00174 const double* coords, 00175 EntityHandle& vert_handle, 00176 std::map< ProcessSet, int >& proc_partition_counts, 00177 bool handles_on_output_mesh ) = 0; 00178 00179 virtual void assign_global_ids( std::map< ProcessSet, int >& gids ) = 0; 00180 00181 Interface* mesh_out; // Output mesh. Needed for new vertex set in vert_handle 00182 RefinerTagManager* tag_manager; 00183 std::vector< int > split_gids; // Used to hold global IDs of split vertices 00184 ProcessSet common_shared_procs; // Holds intersection of several shared_procs_ins. 00185 }; 00186 00187 /** A vector of pre-existing entities to a new mesh entity. 00188 * 00189 * This is used as a dictionary to determine whether a new vertex should be 00190 * created on the given n-simplex (n being the template parameter) or whether 00191 * it has already been created as part of the refinement of a neighboring entity. 00192 */ 00193 class EntitySource : public std::vector< EntitySourceRecord > 00194 { 00195 public: 00196 typedef std::vector< EntitySourceRecord > VecType; 00197 typedef std::vector< EntitySourceRecord >::iterator VecIteratorType; 00198 00199 EntitySource( int num_corners, RefinerTagManager* tag_mgr ); 00200 ~EntitySource(); 00201 bool create_element( EntityType etyp, 00202 int nconn, 00203 const EntityHandle* split_src, 00204 EntityHandle& elem_handle, 00205 std::map< ProcessSet, int >& proc_partition_counts ); 00206 00207 void assign_global_ids( std::map< ProcessSet, int >& gids ); 00208 00209 Interface* mesh_out; // Output mesh. Needed for new vertex set in vert_handle 00210 RefinerTagManager* tag_manager; 00211 ProcessSet common_shared_procs; // Holds intersection of several shared_procs_ins. 00212 int num_corners; 00213 }; 00214 00215 /** A map from a set of pre-existing vertices to a new mesh vertex. 00216 * 00217 * This is used as a dictionary to determine whether a new vertex should be 00218 * created on the given n-simplex (n being the template parameter) or whether 00219 * it has already been created as part of the refinement of a neighboring entity. 00220 */ 00221 template < int _n > 00222 class SplitVertices : public std::map< SplitVertexIndex< _n >, EntityHandle >, public SplitVerticesBase 00223 { 00224 public: 00225 typedef std::map< SplitVertexIndex< _n >, EntityHandle > MapType; 00226 typedef typename std::map< SplitVertexIndex< _n >, EntityHandle >::iterator MapIteratorType; 00227 00228 SplitVertices( RefinerTagManager* tag_mgr ); 00229 virtual ~SplitVertices(); 00230 virtual bool find_or_create( const EntityHandle* split_src, 00231 const double* coords, 00232 EntityHandle& vert_handle, 00233 std::map< ProcessSet, int >& proc_partition_counts, 00234 bool handles_on_output_mesh ); 00235 00236 virtual void assign_global_ids( std::map< ProcessSet, int >& gids ); 00237 }; 00238 00239 // ------------------------- Template member definitions ---------------------- 00240 template < int _n > 00241 SplitVertices< _n >::SplitVertices( RefinerTagManager* tag_mgr ) : SplitVerticesBase( tag_mgr ) 00242 { 00243 this->split_gids.resize( _n ); 00244 } 00245 00246 template < int _n > 00247 SplitVertices< _n >::~SplitVertices() 00248 { 00249 } 00250 00251 template < int _n > 00252 bool SplitVertices< _n >::find_or_create( const EntityHandle* split_src, 00253 const double* coords, 00254 EntityHandle& vert_handle, 00255 std::map< ProcessSet, int >& proc_partition_counts, 00256 bool handles_on_output_mesh ) 00257 { 00258 // Get the global IDs of the input vertices 00259 if( handles_on_output_mesh ) 00260 { 00261 this->tag_manager->get_output_gids( _n, split_src, this->split_gids ); 00262 } 00263 else 00264 { 00265 this->tag_manager->get_input_gids( _n, split_src, this->split_gids ); 00266 } 00267 SplitVertexIndex< _n > key( &this->split_gids[0] ); 00268 MapIteratorType it = this->find( key ); 00269 if( it == this->end() ) 00270 { 00271 #ifdef MB_DEBUG 00272 std::cout << " wrt output: " << handles_on_output_mesh << " "; 00273 #endif // MB_DEBUG 00274 this->tag_manager->get_common_processes( _n, split_src, this->common_shared_procs, handles_on_output_mesh ); 00275 proc_partition_counts[this->common_shared_procs]++; 00276 key.set_common_processes( this->common_shared_procs ); 00277 if( this->mesh_out->create_vertex( coords + 3, vert_handle ) != MB_SUCCESS ) 00278 { 00279 return false; 00280 } 00281 ( *this )[key] = vert_handle; 00282 this->tag_manager->set_sharing( vert_handle, this->common_shared_procs ); 00283 return true; 00284 } 00285 vert_handle = it->second; 00286 return false; 00287 } 00288 00289 template < int _n > 00290 void SplitVertices< _n >::assign_global_ids( std::map< ProcessSet, int >& gids ) 00291 { 00292 typename std::map< SplitVertexIndex< _n >, EntityHandle >::iterator it; 00293 for( it = this->begin(); it != this->end(); ++it ) 00294 { 00295 int gid = gids[it->first.process_set]++; 00296 this->tag_manager->set_gid( it->second, gid ); 00297 #ifdef MB_DEBUG 00298 std::cout << "Assigning entity: " << it->first << " GID: " << gid << "\n"; 00299 #endif // MB_DEBUG 00300 } 00301 } 00302 00303 } // namespace moab 00304 00305 #endif /* MOAB_SPLIT_VERTICES_HPP */