[MOAB-dev] r1538 - MOAB/trunk/refiner

dcthomp at mcs.anl.gov dcthomp at mcs.anl.gov
Thu Jan 17 19:04:45 CST 2008


Author: dcthomp
Date: 2008-01-17 19:04:45 -0600 (Thu, 17 Jan 2008)
New Revision: 1538

Modified:
   MOAB/trunk/refiner/MBEntityRefiner.cpp
   MOAB/trunk/refiner/MBMeshRefiner.cpp
   MOAB/trunk/refiner/MBSimplexTemplateRefiner.cpp
   MOAB/trunk/refiner/MBSimplexTemplateRefiner.hpp
Log:
STYLE: Added some documentation.
ENH: Force the tag assigner to be non-NULL for the lifetime
     of the entity refiner.
PERF: Make the coordinate and tag storage used for corner vertices
      in MBEntityRefiner::refine_entity() member variables to avoid
      repeated allocation/deallocation.


Modified: MOAB/trunk/refiner/MBEntityRefiner.cpp
===================================================================
--- MOAB/trunk/refiner/MBEntityRefiner.cpp	2008-01-17 20:09:23 UTC (rev 1537)
+++ MOAB/trunk/refiner/MBEntityRefiner.cpp	2008-01-18 01:04:45 UTC (rev 1538)
@@ -30,7 +30,9 @@
 /**\fn int MBEntityRefiner::get_heap_size_bound( int max_recursions ) const
   *\brief When an entity is refined, what is the maximum number of new vertices that will be created?
   *
-  * This must be the maximum number of vertices for any entity type (tetrahedra, hexahedra, etc.).
+  * This must be the maximum number of initial corner vertices for any entity type (hex, tet, etc.)
+  * to be processed plus the maximum number of new vertices that might be created at edge or face
+  * mid-points during the refinement of a single entity.
   */
 
 /**\brief Set the object that specifies which edges of a given entity should be subdivided.
@@ -149,7 +151,7 @@
 void MBEntityRefiner::update_heap_size()
 {
   unsigned long n = this->get_heap_size_bound( this->maximum_number_of_subdivisions );
-  this->coord_heap.resize( 6 * n + 8 );
+  this->coord_heap.resize( 6 * n );
   if ( this->edge_size_evaluator )
     {
     unsigned long m = this->edge_size_evaluator->get_vertex_tag_size();

Modified: MOAB/trunk/refiner/MBMeshRefiner.cpp
===================================================================
--- MOAB/trunk/refiner/MBMeshRefiner.cpp	2008-01-17 20:09:23 UTC (rev 1537)
+++ MOAB/trunk/refiner/MBMeshRefiner.cpp	2008-01-18 01:04:45 UTC (rev 1538)
@@ -1,7 +1,94 @@
 #include "MBMeshRefiner.hpp"
 
+#include "MBEntityRefiner.hpp"
 #include "MBInterface.hpp"
 
+#ifdef USE_MPI
+#include <mpi.h>
+#else // USE_MPI
+typedef int MPI_Comm;
+#endif // USE_MPI
+
+#include <map>
+
+class MBRefinerPartition;
+
+struct MBEdgeIndex
+{
+  MBEntityHandle corners[2];
+};
+
+struct MBFaceIndex
+{
+  MBEntityHandle corners[3];
+};
+
+/// A record of data to be sent to and received from a remote process in order to merge a refined mesh.
+class MBRefinerPartition
+{
+public:
+  /// Rank of the local process
+  int local_process;
+  /// Rank of the remote process to which this data belongs.
+  int remote_process;
+  /// A list of locally-owned vertices that are shared with the remote process associated with this object
+  std::vector<MBEntityHandle> vertex_list_local;
+  /// A list of remotely-owned vertices that are shared with the remote process associated with this object
+  std::vector<MBEntityHandle> vertex_list_remote;
+  /// A list of locally-owned global vertex IDs that are shared with the remote process associated with this object
+  std::vector<int> global_ids_local;
+  /// A list of remotely-owned global vertex IDs that are shared with the remote process associated with this object
+  std::vector<int> global_ids_remote;
+  /// Queue asynchronous sends and receives to merge data. You are responsible for calling MPI_Barrier() afterwards.
+  void queue_merge( MPI_Comm communicator )
+    {
+#ifdef USE_MPI
+    MPI_Request rq;
+    int sz;
+    sz = this->vertex_list_local.size();
+    if ( sz )
+      {
+      MPI_Isend( (void*)&global_ids_local[0], sz, MB_MPI_ENTITY_HANDLE_TYPE,
+        this->remote, this->local_rank, communicator, 0 /*request*/ );
+      }
+    sz = this->vertex_list_remote.size();
+    if ( sz )
+      {
+      MPI_Irecv( (void*)&global_ids_remote[0], sz, MB_MPI_ENTITY_HANDLE_TYPE,
+        this->remote, this->local_rank, communicator, 0 /*request*/ );
+      }
+#endif // USE_MPI
+    }
+  /// Perform the merge using the data. You must have called queue_merge() followed by MPI_Barrier() previous to this function.
+  void perform_merge()
+    {
+    // Now the remote global IDs have been properly transferred from the remote process... assign them to the vertices
+
+    }
+};
+
+class MBMeshRefinerOutputFunctor : public MBEntityRefinerOutputFunctor
+{
+public:
+  /// Mesh to hold output (may/may not be same as input mesh)
+  MBInterface* mesh;
+  /// Hash table of newly-created vertices at edge midpoints
+  std::map<MBEdgeIndex, MBEntityHandle> edge_vertices;
+  /// Hash table of newly-created vertices interior to triangle faces
+  std::map<MBFaceIndex, MBEntityHandle> face_vertices;
+  /// Storage allocated for interprocess communication of vertex global IDs
+  std::map<int,MBRefinerPartition*> partitions;
+
+  virtual ~MBMeshRefinerOutputFunctor() { }
+  virtual void operator () ( const double* vcoords, const void* vtags )
+    {
+    // Assume that vtags contains the proper global ID for the vertex (assigned by the TagAssigner)
+    }
+  virtual void operator () ( MBEntityType etyp )
+    {
+    }
+};
+
 MBMeshRefiner::MBMeshRefiner( MBInterface* parentMesh )
 {  
   this->mesh = parentMesh;

Modified: MOAB/trunk/refiner/MBSimplexTemplateRefiner.cpp
===================================================================
--- MOAB/trunk/refiner/MBSimplexTemplateRefiner.cpp	2008-01-17 20:09:23 UTC (rev 1537)
+++ MOAB/trunk/refiner/MBSimplexTemplateRefiner.cpp	2008-01-18 01:04:45 UTC (rev 1538)
@@ -25,13 +25,18 @@
   : MBEntityRefiner( mesh )
 {
   this->tag_assigner = new MBSimplexTemplateTagAssigner( this );
+  this->corner_coords.resize( 6 * 8 ); // Hex has 8 verts w/ 6 coordinates each
+  this->corner_tags.resize( 8 ); // Hex has 8 verts (this is a pointer, not the actual tag data)
 }
 
 /// Empty destructor for good form.
 MBSimplexTemplateRefiner::~MBSimplexTemplateRefiner()
 {
+  delete this->tag_assigner;
 }
 
+/**\brief Stream a single mesh entity through the refiner.
+  */
 bool MBSimplexTemplateRefiner::refine_entity( MBEntityHandle entity )
 {
   this->reset_heap_pointers();
@@ -42,50 +47,50 @@
     {
     return false;
     }
-  std::vector<double> entity_coords;
-  std::vector<void*> entity_tags;
-  entity_coords.resize( 6 * num_nodes );
-  entity_tags.resize( num_nodes );
+  this->corner_coords.resize( 6 * num_nodes );
+  this->corner_tags.resize( num_nodes );
 
   MBEntityType etyp = this->mesh->type_from_handle( entity );
   // Have to make num_nodes calls to get_coords() because we need xyz interleaved with rst coords.
   MBTag tag_handle;
   int tag_offset;
+  void* tag_data;
   for ( int n = 0; n < num_nodes; ++ n )
     {
-    if ( this->mesh->get_coords( &conn[n], 1, &entity_coords[6 * n + 3] ) != MB_SUCCESS )
+    if ( this->mesh->get_coords( &conn[n], 1, &corner_coords[6 * n + 3] ) != MB_SUCCESS )
       {
       return false;
       }
-    entity_tags[n] = this->heap_tag_storage();
+    tag_data = this->heap_tag_storage();
     for ( int i = 0; i < this->edge_size_evaluator->get_number_of_vertex_tags(); ++ i )
       {
       this->edge_size_evaluator->get_vertex_tag( i, tag_handle, tag_offset );
-      if ( this->mesh->tag_get_data( tag_handle, &conn[n], 1, (char*)( entity_tags[n] ) + tag_offset ) != MB_SUCCESS )
+      if ( this->mesh->tag_get_data( tag_handle, &conn[n], 1, (char*)tag_data + tag_offset ) != MB_SUCCESS )
         {
         return false;
         }
       }
+    this->corner_tags[n] = tag_data;
     }
 
   switch ( etyp )
     {
     case MBVERTEX:
-      this->assign_parametric_coordinates( 1, MBVertexParametric, &entity_coords[0] );
-      this->refine_0_simplex( &entity_coords[0], entity_tags[0] );
+      this->assign_parametric_coordinates( 1, MBVertexParametric, &this->corner_coords[0] );
+      this->refine_0_simplex( &this->corner_coords[0], this->corner_tags[0] );
       rval = false;
       break;
     case MBEDGE:
-      this->assign_parametric_coordinates( 2, MBEdgeParametric, &entity_coords[0] );
+      this->assign_parametric_coordinates( 2, MBEdgeParametric, &this->corner_coords[0] );
       rval = this->refine_1_simplex( this->maximum_number_of_subdivisions,
-        &entity_coords[0], entity_tags[0],  &entity_coords[6], entity_tags[1] );
+        &this->corner_coords[0], this->corner_tags[0],  &this->corner_coords[6], this->corner_tags[1] );
       break;
     case MBTRI:
-      this->assign_parametric_coordinates( 3, MBTriParametric, &entity_coords[0] );
+      this->assign_parametric_coordinates( 3, MBTriParametric, &this->corner_coords[0] );
       rval = this->refine_2_simplex( this->maximum_number_of_subdivisions, 7,
-        &entity_coords[ 0], entity_tags[0],
-        &entity_coords[ 6], entity_tags[1],
-        &entity_coords[12], entity_tags[2] );
+        &this->corner_coords[ 0], this->corner_tags[0],
+        &this->corner_coords[ 6], this->corner_tags[1],
+        &this->corner_coords[12], this->corner_tags[2] );
       break;
     case MBQUAD:
       std::cerr << "Quadrilaterals not handled yet\n";
@@ -96,7 +101,7 @@
       rval = false;
       break;
     case MBTET:
-      this->assign_parametric_coordinates( 4, MBTetParametric, &entity_coords[0] );
+      this->assign_parametric_coordinates( 4, MBTetParametric, &this->corner_coords[0] );
       rval = this->refine_3_simplex( 0, 0, 0, 0, 0, 0, 0, 0, 0 ); // FIXME
       break;
     case MBPYRAMID:
@@ -132,25 +137,30 @@
   return rval;
 }
 
+/**\brief Set the function object used to decide which tag values an edge or face midpoint is assigned.
+  *
+  * This will change the tag assigner's edge size evaluator to match the refiner's.
+  * @param[in] ta The new tag assigner. This must be non-NULL.
+  * @retval True if the tag assigner was changed and false otherwise.
+  */
 bool MBSimplexTemplateRefiner::set_tag_assigner( MBSimplexTemplateTagAssigner* ta )
 { 
-  if ( ta == this->tag_assigner )
+  if ( ! ta || ta == this->tag_assigner )
     return false;
+
   this->tag_assigner = ta; 
-  if ( ta )
-    this->tag_assigner->set_edge_size_evaluator( this->edge_size_evaluator );
+  this->tag_assigner->set_edge_size_evaluator( this->edge_size_evaluator );
   return true;
 }
 
 
+/**\brief Set the function object used to decide whether an edge is subdivided or not.
+  */
 bool MBSimplexTemplateRefiner::set_edge_size_evaluator( MBEdgeSizeEvaluator* es ) 
 { 
   if ( this->MBEntityRefiner::set_edge_size_evaluator( es ) )
     {
-    if ( this->tag_assigner )
-      {
-      this->tag_assigner->set_edge_size_evaluator( es );
-      }
+    this->tag_assigner->set_edge_size_evaluator( es );
     return true;
     }
   return false;

Modified: MOAB/trunk/refiner/MBSimplexTemplateRefiner.hpp
===================================================================
--- MOAB/trunk/refiner/MBSimplexTemplateRefiner.hpp	2008-01-17 20:09:23 UTC (rev 1537)
+++ MOAB/trunk/refiner/MBSimplexTemplateRefiner.hpp	2008-01-18 01:04:45 UTC (rev 1538)
@@ -41,7 +41,7 @@
   virtual ~MBSimplexTemplateRefiner();
 
   virtual bool refine_entity( MBEntityHandle entity );
-  virtual unsigned long get_heap_size_bound( int max_recursions ) const { return 48 * 4 * ( 1 << max_recursions ); }
+  virtual unsigned long get_heap_size_bound( int max_recursions ) const { return 48 * 4 * ( 1 << max_recursions ) + 8; }
 
   virtual bool set_tag_assigner( MBSimplexTemplateTagAssigner* ta );
   MBSimplexTemplateTagAssigner* get_tag_assigner() const { return this->tag_assigner; }
@@ -50,6 +50,9 @@
 
 protected:
   MBSimplexTemplateTagAssigner* tag_assigner;
+  std::vector<double> corner_coords;
+  std::vector<void*> corner_tags;
+
   static int template_index[64][2];
   static int permutations_from_index[24][14];
   static int templates[];




More information about the moab-dev mailing list