moab
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 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 */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines