MOAB: Mesh Oriented datABase  (version 5.4.0)
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,
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 */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines