MOAB: Mesh Oriented datABase
(version 5.2.1)
|
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, const double* coords, EntityHandle& vert_handle, 00174 std::map< ProcessSet, int >& proc_partition_counts, bool handles_on_output_mesh ) = 0; 00175 00176 virtual void assign_global_ids( std::map< ProcessSet, int >& gids ) = 0; 00177 00178 Interface* mesh_out; // Output mesh. Needed for new vertex set in vert_handle 00179 RefinerTagManager* tag_manager; 00180 std::vector< int > split_gids; // Used to hold global IDs of split vertices 00181 ProcessSet common_shared_procs; // Holds intersection of several shared_procs_ins. 00182 }; 00183 00184 /** A vector of pre-existing entities to a new mesh entity. 00185 * 00186 * This is used as a dictionary to determine whether a new vertex should be 00187 * created on the given n-simplex (n being the template parameter) or whether 00188 * it has already been created as part of the refinement of a neighboring entity. 00189 */ 00190 class EntitySource : public std::vector< EntitySourceRecord > 00191 { 00192 public: 00193 typedef std::vector< EntitySourceRecord > VecType; 00194 typedef std::vector< EntitySourceRecord >::iterator VecIteratorType; 00195 00196 EntitySource( int num_corners, RefinerTagManager* tag_mgr ); 00197 ~EntitySource(); 00198 bool create_element( EntityType etyp, int nconn, const EntityHandle* split_src, EntityHandle& elem_handle, 00199 std::map< ProcessSet, int >& proc_partition_counts ); 00200 00201 void assign_global_ids( std::map< ProcessSet, int >& gids ); 00202 00203 Interface* mesh_out; // Output mesh. Needed for new vertex set in vert_handle 00204 RefinerTagManager* tag_manager; 00205 ProcessSet common_shared_procs; // Holds intersection of several shared_procs_ins. 00206 int num_corners; 00207 }; 00208 00209 /** A map from a set of pre-existing vertices to a new mesh vertex. 00210 * 00211 * This is used as a dictionary to determine whether a new vertex should be 00212 * created on the given n-simplex (n being the template parameter) or whether 00213 * it has already been created as part of the refinement of a neighboring entity. 00214 */ 00215 template < int _n > 00216 class SplitVertices : public std::map< SplitVertexIndex< _n >, EntityHandle >, public SplitVerticesBase 00217 { 00218 public: 00219 typedef std::map< SplitVertexIndex< _n >, EntityHandle > MapType; 00220 typedef typename std::map< SplitVertexIndex< _n >, EntityHandle >::iterator MapIteratorType; 00221 00222 SplitVertices( RefinerTagManager* tag_mgr ); 00223 virtual ~SplitVertices(); 00224 virtual bool find_or_create( const EntityHandle* split_src, const double* coords, EntityHandle& vert_handle, 00225 std::map< ProcessSet, int >& proc_partition_counts, bool handles_on_output_mesh ); 00226 00227 virtual void assign_global_ids( std::map< ProcessSet, int >& gids ); 00228 }; 00229 00230 // ------------------------- Template member definitions ---------------------- 00231 template < int _n > 00232 SplitVertices< _n >::SplitVertices( RefinerTagManager* tag_mgr ) : SplitVerticesBase( tag_mgr ) 00233 { 00234 this->split_gids.resize( _n ); 00235 } 00236 00237 template < int _n > 00238 SplitVertices< _n >::~SplitVertices() 00239 { 00240 } 00241 00242 template < int _n > 00243 bool SplitVertices< _n >::find_or_create( const EntityHandle* split_src, const double* coords, 00244 EntityHandle& vert_handle, std::map< ProcessSet, int >& proc_partition_counts, 00245 bool handles_on_output_mesh ) 00246 { 00247 // Get the global IDs of the input vertices 00248 if( handles_on_output_mesh ) { this->tag_manager->get_output_gids( _n, split_src, this->split_gids ); } 00249 else 00250 { 00251 this->tag_manager->get_input_gids( _n, split_src, this->split_gids ); 00252 } 00253 SplitVertexIndex< _n > key( &this->split_gids[0] ); 00254 MapIteratorType it = this->find( key ); 00255 if( it == this->end() ) 00256 { 00257 #ifdef MB_DEBUG 00258 std::cout << " wrt output: " << handles_on_output_mesh << " "; 00259 #endif // MB_DEBUG 00260 this->tag_manager->get_common_processes( _n, split_src, this->common_shared_procs, handles_on_output_mesh ); 00261 proc_partition_counts[this->common_shared_procs]++; 00262 key.set_common_processes( this->common_shared_procs ); 00263 if( this->mesh_out->create_vertex( coords + 3, vert_handle ) != MB_SUCCESS ) { return false; } 00264 ( *this )[key] = vert_handle; 00265 this->tag_manager->set_sharing( vert_handle, this->common_shared_procs ); 00266 return true; 00267 } 00268 vert_handle = it->second; 00269 return false; 00270 } 00271 00272 template < int _n > 00273 void SplitVertices< _n >::assign_global_ids( std::map< ProcessSet, int >& gids ) 00274 { 00275 typename std::map< SplitVertexIndex< _n >, EntityHandle >::iterator it; 00276 for( it = this->begin(); it != this->end(); ++it ) 00277 { 00278 int gid = gids[it->first.process_set]++; 00279 this->tag_manager->set_gid( it->second, gid ); 00280 #ifdef MB_DEBUG 00281 std::cout << "Assigning entity: " << it->first << " GID: " << gid << "\n"; 00282 #endif // MB_DEBUG 00283 } 00284 } 00285 00286 } // namespace moab 00287 00288 #endif /* MOAB_SPLIT_VERTICES_HPP */