MOAB: Mesh Oriented datABase  (version 5.2.1)
SplitVertices.hpp
Go to the documentation of this file.
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 */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines