moab
|
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 Coroporation, 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 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 class RefinerTagManager; 00037 00038 template< int _n > 00039 class SplitVertexIndex 00040 { 00041 public: 00042 SplitVertexIndex() { } 00043 SplitVertexIndex( const int* src ) 00044 { for ( int i = 0; i < _n; ++ i ) this->ids[i] = src[i]; std::sort( this->ids, this->ids + _n ); } 00045 SplitVertexIndex( const SplitVertexIndex<_n>& src ) 00046 { for ( int i = 0; i < _n; ++ i ) this->ids[i] = src.ids[i]; this->process_set = src.process_set; } 00047 SplitVertexIndex& operator = ( const SplitVertexIndex<_n>& src ) 00048 { for ( int i = 0; i < _n; ++ i ) this->ids[i] = src.ids[i]; this->process_set = src.process_set; return *this; } 00049 00050 void set_common_processes( const ProcessSet& procs ) 00051 { this->process_set = procs; } 00052 ProcessSet& common_processes() 00053 { return this->process_set; } 00054 const ProcessSet& common_processes() const 00055 { return this->process_set; } 00056 00057 bool operator < ( const SplitVertexIndex<_n>& other ) const 00058 { 00059 // Ignore the process set. Only program errors lead to mismatched process sets with identical ids. 00060 for ( int i = 0; i < _n; ++ i ) 00061 if ( this->ids[i] < other.ids[i] ) 00062 return true; 00063 else if ( this->ids[i] > other.ids[i] ) 00064 return false; 00065 return false; 00066 } 00067 00068 int ids[_n + 1]; 00069 ProcessSet process_set; 00070 }; 00071 00072 template< int _n > 00073 std::ostream& operator << ( std::ostream& os, const SplitVertexIndex<_n>& idx ) 00074 { 00075 for ( int i = 0; i < _n; ++ i ) 00076 { 00077 os << idx.ids[i] << " "; 00078 } 00079 os << "(" << idx.process_set << ")"; 00080 return os; 00081 } 00082 00083 class EntitySourceRecord 00084 { 00085 public: 00086 EntitySourceRecord() { } 00087 EntitySourceRecord( int nc, EntityHandle ent, const ProcessSet& procs ) 00088 { this->ids.resize( nc ); this->handle = ent; this->process_set = procs; } 00089 EntitySourceRecord( const EntitySourceRecord& src ) 00090 { this->handle = src.handle; this->process_set = src.process_set; this->ids = src.ids; } 00091 EntitySourceRecord& operator = ( const EntitySourceRecord& src ) 00092 { this->handle = src.handle; this->process_set = src.process_set; this->ids = src.ids; return *this; } 00093 00094 void set_common_processes( const ProcessSet& procs ) 00095 { this->process_set = procs; } 00096 ProcessSet& common_processes() 00097 { return this->process_set; } 00098 const ProcessSet& common_processes() const 00099 { return this->process_set; } 00100 00101 bool operator < ( const EntitySourceRecord& other ) const 00102 { 00103 //assert( this->ids.size() == other.ids.size() ); 00104 std::vector<int>::size_type N = this->ids.size(); 00105 std::vector<int>::size_type i; 00106 // Ignore the process set. Only program errors lead to mismatched process sets with identical ids. 00107 for ( i = 0; i < N; ++ i ) 00108 if ( this->ids[i] < other.ids[i] ) 00109 return true; 00110 else if ( this->ids[i] > other.ids[i] ) 00111 return false; 00112 return false; 00113 } 00114 00115 std::vector<int> ids; 00116 ProcessSet process_set; 00117 EntityHandle handle; 00118 }; 00119 00120 00127 class SplitVerticesBase 00128 { 00129 public: 00130 SplitVerticesBase( RefinerTagManager* tag_mgr ); 00131 virtual ~SplitVerticesBase(); 00132 00133 virtual bool find_or_create( 00134 const EntityHandle* split_src, const double* coords, EntityHandle& vert_handle, 00135 std::map<ProcessSet,int>& proc_partition_counts, bool handles_on_output_mesh ) = 0; 00136 00137 virtual void assign_global_ids( std::map<ProcessSet,int>& gids ) = 0; 00138 00139 Interface* mesh_out; // Output mesh. Needed for new vertex set in vert_handle 00140 RefinerTagManager* tag_manager; 00141 std::vector<int> split_gids; // Used to hold global IDs of split vertices 00142 ProcessSet common_shared_procs; // Holds intersection of several shared_procs_ins. 00143 }; 00144 00151 class EntitySource : public std::vector<EntitySourceRecord> 00152 { 00153 public: 00154 typedef std::vector<EntitySourceRecord> VecType; 00155 typedef std::vector<EntitySourceRecord>::iterator VecIteratorType; 00156 00157 EntitySource( int num_corners, RefinerTagManager* tag_mgr ); 00158 ~EntitySource(); 00159 bool create_element( 00160 EntityType etyp, int nconn, const EntityHandle* split_src, EntityHandle& elem_handle, 00161 std::map<ProcessSet,int>& proc_partition_counts ); 00162 00163 void assign_global_ids( std::map<ProcessSet,int>& gids ); 00164 00165 Interface* mesh_out; // Output mesh. Needed for new vertex set in vert_handle 00166 RefinerTagManager* tag_manager; 00167 ProcessSet common_shared_procs; // Holds intersection of several shared_procs_ins. 00168 int num_corners; 00169 }; 00170 00171 00178 template< int _n > 00179 class SplitVertices : public std::map<SplitVertexIndex<_n>,EntityHandle>, public SplitVerticesBase 00180 { 00181 public: 00182 typedef std::map<SplitVertexIndex<_n>,EntityHandle> MapType; 00183 typedef typename std::map<SplitVertexIndex<_n>,EntityHandle>::iterator MapIteratorType; 00184 00185 SplitVertices( RefinerTagManager* tag_mgr ); 00186 virtual ~SplitVertices(); 00187 virtual bool find_or_create( 00188 const EntityHandle* split_src, const double* coords, EntityHandle& vert_handle, 00189 std::map<ProcessSet,int>& proc_partition_counts, bool handles_on_output_mesh ); 00190 00191 virtual void assign_global_ids( std::map<ProcessSet,int>& gids ); 00192 }; 00193 00194 // ------------------------- Template member definitions ---------------------- 00195 template< int _n > 00196 SplitVertices<_n>::SplitVertices( RefinerTagManager* tag_mgr ) 00197 : SplitVerticesBase( tag_mgr ) 00198 { 00199 this->split_gids.resize( _n ); 00200 } 00201 00202 template< int _n > 00203 SplitVertices<_n>::~SplitVertices() 00204 { 00205 } 00206 00207 template< int _n > 00208 bool SplitVertices<_n>::find_or_create( 00209 const EntityHandle* split_src, const double* coords, EntityHandle& vert_handle, 00210 std::map<ProcessSet,int>& proc_partition_counts, bool handles_on_output_mesh ) 00211 { 00212 // Get the global IDs of the input vertices 00213 if ( handles_on_output_mesh ) 00214 { 00215 this->tag_manager->get_output_gids( _n, split_src, this->split_gids ); 00216 } 00217 else 00218 { 00219 this->tag_manager->get_input_gids( _n, split_src, this->split_gids ); 00220 } 00221 SplitVertexIndex<_n> key( &this->split_gids[0] ); 00222 MapIteratorType it = this->find( key ); 00223 if ( it == this->end() ) 00224 { 00225 #ifdef MB_DEBUG 00226 std::cout << " wrt output: " << handles_on_output_mesh << " "; 00227 #endif // MB_DEBUG 00228 this->tag_manager->get_common_processes( _n, split_src, this->common_shared_procs, handles_on_output_mesh ); 00229 proc_partition_counts[this->common_shared_procs]++; 00230 key.set_common_processes( this->common_shared_procs ); 00231 if ( this->mesh_out->create_vertex( coords + 3, vert_handle ) != MB_SUCCESS ) 00232 { 00233 return false; 00234 } 00235 (*this)[key] = vert_handle; 00236 this->tag_manager->set_sharing( vert_handle, this->common_shared_procs ); 00237 return true; 00238 } 00239 vert_handle = it->second; 00240 return false; 00241 } 00242 00243 template< int _n > 00244 void SplitVertices<_n>::assign_global_ids( std::map<ProcessSet,int>& gids ) 00245 { 00246 typename std::map<SplitVertexIndex<_n>,EntityHandle>::iterator it; 00247 for ( it = this->begin(); it != this->end(); ++ it ) 00248 { 00249 int gid = gids[it->first.process_set] ++; 00250 this->tag_manager->set_gid( it->second, gid ); 00251 #ifdef MB_DEBUG 00252 std::cout << "Assigning entity: " << it->first << " GID: " << gid << "\n"; 00253 #endif // MB_DEBUG 00254 } 00255 } 00256 00257 } // namespace moab 00258 00259 #endif /* MOAB_SPLIT_VERTICES_HPP */