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

dcthomp at mcs.anl.gov dcthomp at mcs.anl.gov
Thu Jun 12 20:30:49 CDT 2008


Author: dcthomp
Date: 2008-06-12 20:30:49 -0500 (Thu, 12 Jun 2008)
New Revision: 1892

Added:
   MOAB/trunk/refiner/MBRefinerTagManager.cpp
   MOAB/trunk/refiner/MBRefinerTagManager.hpp
Modified:
   MOAB/trunk/refiner/CMakeLists.txt
   MOAB/trunk/refiner/MBEdgeSizeEvaluator.cpp
   MOAB/trunk/refiner/MBEdgeSizeEvaluator.hpp
   MOAB/trunk/refiner/MBEdgeSizeSimpleImplicit.cpp
   MOAB/trunk/refiner/MBEdgeSizeSimpleImplicit.hpp
   MOAB/trunk/refiner/MBMeshRefiner.cpp
   MOAB/trunk/refiner/MBSimplexTemplateRefiner.cpp
   MOAB/trunk/refiner/MBSimplexTemplateTagAssigner.cpp
   MOAB/trunk/refiner/test_mesh_refiner.cpp
Log:
ENH: Broke MBRefinerTagManager out of MBEdgeSizeEvaluator.
ENH: Added state to MBRefinerTagManager for case when input
     is not output mesh, plus a routine to create tags as
     required on the output mesh.
ENH: Work on a more general way to store vertex handles
     indexed by the corners of their parent (unrefined)
     entity.


Modified: MOAB/trunk/refiner/CMakeLists.txt
===================================================================
--- MOAB/trunk/refiner/CMakeLists.txt	2008-06-11 19:08:53 UTC (rev 1891)
+++ MOAB/trunk/refiner/CMakeLists.txt	2008-06-13 01:30:49 UTC (rev 1892)
@@ -3,6 +3,7 @@
   MBEdgeSizeSimpleImplicit.cpp
   MBEntityRefiner.cpp
   MBMeshRefiner.cpp
+  MBRefinerTagManager.cpp
   MBSimplexTemplateRefiner.cpp
   MBSimplexTemplateTagAssigner.cpp
   )

Modified: MOAB/trunk/refiner/MBEdgeSizeEvaluator.cpp
===================================================================
--- MOAB/trunk/refiner/MBEdgeSizeEvaluator.cpp	2008-06-11 19:08:53 UTC (rev 1891)
+++ MOAB/trunk/refiner/MBEdgeSizeEvaluator.cpp	2008-06-13 01:30:49 UTC (rev 1892)
@@ -5,12 +5,9 @@
 #include <assert.h>
 
 /// Construct an evaluator.
-MBEdgeSizeEvaluator::MBEdgeSizeEvaluator( MBInterface* parentMesh )
+MBEdgeSizeEvaluator::MBEdgeSizeEvaluator( MBInterface* mesh_in, MBInterface* mesh_out )
+  : MBRefinerTagManager( mesh_in, mesh_out )
 {
-  assert( parentMesh );
-
-  this->mesh = parentMesh;
-  this->reset_vertex_tags();
 }
 
 /// Destruction is virtual so subclasses may clean up after refinement.
@@ -36,61 +33,3 @@
   * populate vertex_tags before evaluate_edge() is called.
   */
 
-/// Clear the list of tag values that will appear past the vertex coordinates in \a p0, \a p1, and \a p2.
-void MBEdgeSizeEvaluator::reset_vertex_tags()
-{
-  this->vertex_size = 0;
-  this->vertex_tags.clear();
-}
-
-/** Add a tag to the list of tag values that will appear past the vertex coordinates.
-  * The return value is the offset into each vertex coordinate pointer (\a p0, \a p1, \a p2) where the
-  * tag value(s) will be stored.
-  */
-int MBEdgeSizeEvaluator::add_vertex_tag( MBTag tag_handle )
-{
-  int offset = this->vertex_size; // old size is offset of tag being added
-  int tag_size;
-  MBTagType tagType;
-  if ( this->mesh->tag_get_size( tag_handle, tag_size ) != MB_SUCCESS )
-    return -1;
-
-  if ( this->mesh->tag_get_type( tag_handle, tagType ) != MB_SUCCESS )
-    return -1;
-
-  if ( tagType == MB_TAG_BIT )
-    {
-    // Pad any bit tags to a size in full bytes.
-    tag_size = ( tag_size % 8 ? 1 : 0 ) + ( tag_size / 8 );
-    }
-
-  // Now pad so that the next tag will be word-aligned:
-  while ( tag_size % sizeof(int) )
-    ++tag_size;
-
-  this->vertex_size += tag_size;
-
-  this->vertex_tags.push_back( std::pair< MBTag, int >( tag_handle, offset ) );
-  return offset;
-}
-
-/**\fn int MBEdgeSizeEvaluator::get_vertex_tag_size()
-  *\brief Return the number of bytes to allocate for tag data per point.
-  */
-
-/**\fn int MBEdgeSizeEvaluator::get_number_of_vertex_tags() const
-  *\brief Return the number of tags that will be output with each new vertex.
-  */
-
-/**\brief Return the tag handle and its offset in the array of tag data of each vertex.
-  *
-  * @param[in] i An index into the list of tags for the vertex.
-  * @param[out] tag The tag handle for the $i$-th vertex tag.
-  * @param[out] byte_offset The offset (in bytes) of the start of this tag's data in a vertex tag record.
-  */
-void MBEdgeSizeEvaluator::get_vertex_tag( int i, MBTag& tag, int& byte_offset )
-{
-  std::vector< std::pair< MBTag, int > >::iterator it = this->vertex_tags.begin() + i;
-  tag = it->first;
-  byte_offset = it->second;
-}

Modified: MOAB/trunk/refiner/MBEdgeSizeEvaluator.hpp
===================================================================
--- MOAB/trunk/refiner/MBEdgeSizeEvaluator.hpp	2008-06-11 19:08:53 UTC (rev 1891)
+++ MOAB/trunk/refiner/MBEdgeSizeEvaluator.hpp	2008-06-13 01:30:49 UTC (rev 1892)
@@ -26,34 +26,18 @@
 #ifndef MB_EDGESIZEEVALUATOR_H
 #define MB_EDGESIZEEVALUATOR_H
 
-#include "MBTypes.h" // for MB_DLL_EXPORT
+#include "MBRefinerTagManager.hpp"
 
-#include <vector>
-
-class MBInterface;
-
-class MB_DLL_EXPORT MBEdgeSizeEvaluator
+class MB_DLL_EXPORT MBEdgeSizeEvaluator : public MBRefinerTagManager
 {
 public:
-  MBEdgeSizeEvaluator( MBInterface* );
+  MBEdgeSizeEvaluator( MBInterface*, MBInterface* );
   virtual ~MBEdgeSizeEvaluator();
 
   virtual bool evaluate_edge(
     const double* p0, const void* t0,
     double* p1, void* t1,
     const double* p2, const void* t2 ) = 0;
-
-  void reset_vertex_tags();
-  int add_vertex_tag( MBTag tag_handle );
-  int get_vertex_tag_size() const { return this->vertex_size; }
-
-  int get_number_of_vertex_tags() const { return this->vertex_tags.size(); }
-  void get_vertex_tag( int i, MBTag& tag, int& byte_offset );
-
-protected:
-  std::vector< std::pair< MBTag, int > > vertex_tags;
-  int vertex_size;
-  MBInterface* mesh;
 };
 
 #endif // MB_EDGESIZEEVALUATOR_H

Modified: MOAB/trunk/refiner/MBEdgeSizeSimpleImplicit.cpp
===================================================================
--- MOAB/trunk/refiner/MBEdgeSizeSimpleImplicit.cpp	2008-06-11 19:08:53 UTC (rev 1891)
+++ MOAB/trunk/refiner/MBEdgeSizeSimpleImplicit.cpp	2008-06-13 01:30:49 UTC (rev 1892)
@@ -1,7 +1,7 @@
 #include "MBEdgeSizeSimpleImplicit.hpp"
 
-MBEdgeSizeSimpleImplicit::MBEdgeSizeSimpleImplicit( MBInterface* parentMesh )
-  : MBEdgeSizeEvaluator( parentMesh )
+MBEdgeSizeSimpleImplicit::MBEdgeSizeSimpleImplicit( MBInterface* mesh_in, MBInterface* mesh_out )
+  : MBEdgeSizeEvaluator( mesh_in, mesh_out )
 {
   int i;
   // Default to the plane: x = 0.

Modified: MOAB/trunk/refiner/MBEdgeSizeSimpleImplicit.hpp
===================================================================
--- MOAB/trunk/refiner/MBEdgeSizeSimpleImplicit.hpp	2008-06-11 19:08:53 UTC (rev 1891)
+++ MOAB/trunk/refiner/MBEdgeSizeSimpleImplicit.hpp	2008-06-13 01:30:49 UTC (rev 1892)
@@ -36,7 +36,7 @@
 {
 public:
   /// Construct an evaluator.
-  MBEdgeSizeSimpleImplicit( MBInterface* );
+  MBEdgeSizeSimpleImplicit( MBInterface*, MBInterface* );
   /// Destruction is virtual so subclasses may clean up after refinement.
   virtual ~MBEdgeSizeSimpleImplicit();
 

Modified: MOAB/trunk/refiner/MBMeshRefiner.cpp
===================================================================
--- MOAB/trunk/refiner/MBMeshRefiner.cpp	2008-06-11 19:08:53 UTC (rev 1891)
+++ MOAB/trunk/refiner/MBMeshRefiner.cpp	2008-06-13 01:30:49 UTC (rev 1892)
@@ -113,7 +113,7 @@
     int tag_offset;
     for ( int i = 0; i < num_tags; ++i )
       {
-      this->edge_size_evaluator->get_vertex_tag( i, tag_handle, tag_offset );
+      this->edge_size_evaluator->get_output_vertex_tag( i, tag_handle, tag_offset );
       this->mesh->tag_set_data( tag_handle, &vertex_handle, 1, (char*)vtags + tag_offset );
       }
     return vertex_handle;
@@ -133,7 +133,7 @@
     int tag_offset;
     for ( int i = 0; i < num_tags; ++i )
       {
-      this->edge_size_evaluator->get_vertex_tag( i, tag_handle, tag_offset );
+      this->edge_size_evaluator->get_output_vertex_tag( i, tag_handle, tag_offset );
       this->mesh->tag_set_data( tag_handle, &hv, 1, (char*)vtags + tag_offset );
       }
     return hv;

Added: MOAB/trunk/refiner/MBRefinerTagManager.cpp
===================================================================
--- MOAB/trunk/refiner/MBRefinerTagManager.cpp	                        (rev 0)
+++ MOAB/trunk/refiner/MBRefinerTagManager.cpp	2008-06-13 01:30:49 UTC (rev 1892)
@@ -0,0 +1,165 @@
+#include "MBRefinerTagManager.hpp"
+
+#include "MBInterface.hpp"
+
+#include <iostream>
+#include <assert.h>
+
+/// Construct an evaluator.
+MBRefinerTagManager::MBRefinerTagManager( MBInterface* in_mesh, MBInterface* out_mesh )
+{
+  assert( in_mesh );
+  if ( ! out_mesh )
+    out_mesh = in_mesh;
+
+  this->input_mesh = in_mesh;
+  this->output_mesh = out_mesh;
+  this->reset_vertex_tags();
+}
+
+/// Destruction is virtual so subclasses may clean up after refinement.
+MBRefinerTagManager::~MBRefinerTagManager()
+{
+}
+
+/**\fn bool MBRefinerTagManager::evaluate_edge( \
+  *         const double* p0, const void* t0, double* p1, void* t1, const double* p2, const void* t2 )
+  *\brief Returns true if the edge \a p0 - \a p2 should be subdivided, false otherwise.
+  *
+  * The arguments \a p0, \a p1, and \a p2 are all pointers to arrays of 6 doubles each
+  * while the arguments \a t0, \a t1, and \a t2 are all pointers to arrays of tag data
+  * defined at the corresponding point. While the endpoints \a p0 and \a p2 are
+  * immutable, the mid-edge point coordinates \a p1 and tag data \a t1 may be altered by
+  * evaluate_edge(). Altered values will be ignored if evaluate_edge() returns false.
+  * Be careful to ensure that all calls to evaluate_edge() perform identical modifications
+  * given identical input values!
+  *
+  * A list of tags passed in \a t0, \a t1, and \a t2 is stored in the \a input_vertex_tags member.
+  * (for tag handles defined on the input mesh) and the \a output_vertex_tags (for the same tag handles
+  * defined on the output mesh).
+  * The vertex_size member stores the total length of data associated with each pointer (in bytes).
+  * Subclasses may access input_vertex_tags, output_vertex_tags, and vertex_size directly;
+  * the refiner uses public methods to set them before any entities are evaluated for subdivision.
+  * The output_vertex_tags member is populated when the refiner calls create_output_tags().
+  * When the input mesh and output mesh pointers are identical, this simply copies input_vertex_tags
+  * to output_vertex_tags.
+  * When the pointers are distinct, tags are created on the output mesh.
+  */
+
+/// Clear the list of tag values that will appear past the vertex coordinates in \a p0, \a p1, and \a p2.
+void MBRefinerTagManager::reset_vertex_tags()
+{
+  this->vertex_size = 0;
+  this->input_vertex_tags.clear();
+  this->output_vertex_tags.clear();
+}
+
+/** Add a tag to the list of tag values that will appear past the vertex coordinates.
+  * The return value is the offset into each vertex coordinate pointer (\a p0, \a p1, \a p2) where the
+  * tag value(s) will be stored.
+  */
+int MBRefinerTagManager::add_vertex_tag( MBTag tag_handle )
+{
+  int offset = this->vertex_size; // old size is offset of tag being added
+  int tag_size;
+  MBTagType tagType;
+  if ( this->input_mesh->tag_get_size( tag_handle, tag_size ) != MB_SUCCESS )
+    return -1;
+
+  if ( this->input_mesh->tag_get_type( tag_handle, tagType ) != MB_SUCCESS )
+    return -1;
+
+  if ( tagType == MB_TAG_BIT )
+    {
+    // Pad any bit tags to a size in full bytes.
+    tag_size = ( tag_size % 8 ? 1 : 0 ) + ( tag_size / 8 );
+    }
+
+  // Now pad so that the next tag will be word-aligned:
+  while ( tag_size % sizeof(int) )
+    ++tag_size;
+
+  this->vertex_size += tag_size;
+
+  this->input_vertex_tags.push_back( std::pair< MBTag, int >( tag_handle, offset ) );
+  return offset;
+}
+
+/**\fn int MBRefinerTagManager::get_vertex_tag_size()
+  *\brief Return the number of bytes to allocate for tag data per point.
+  */
+
+/**\fn int MBRefinerTagManager::get_number_of_vertex_tags() const
+  *\brief Return the number of tags that will be output with each new vertex.
+  */
+
+/**\brief Populate the list of output tags to match the list of input tags.
+  *
+  * When the input mesh and output mesh pointers are identical, this simply copies the list of input tags.
+  * When the two meshes are distinct, the corresponding tags are created on the output mesh.
+  */
+void MBRefinerTagManager::create_output_tags()
+{
+  if ( this->input_mesh == this->output_mesh )
+    {
+    this->output_vertex_tags = this->input_vertex_tags;
+    return;
+    }
+
+  std::pair< MBTag, int > tag_rec;
+  std::vector< std::pair< MBTag, int > >::iterator it;
+  std::vector< char > tag_default;
+  std::string tag_name;
+  MBTagType tag_type;
+  MBDataType tag_data_type;
+  int tag_size;
+  for ( it = this->input_vertex_tags.begin(); it != this->output_vertex_tags.end(); ++ it )
+    {
+    MBTag tag_in = it->first;
+    tag_rec.second = it->second;
+    this->input_mesh->tag_get_name( tag_in, tag_name );
+    this->input_mesh->tag_get_size( tag_in, tag_size );
+    this->input_mesh->tag_get_type( tag_in, tag_type );
+    this->input_mesh->tag_get_data_type( tag_in, tag_data_type );
+    this->input_mesh->tag_get_default_value( tag_in, (void*) &tag_default[0] );
+    tag_default.resize( tag_size );
+    MBErrorCode res = this->output_mesh->tag_create(
+      tag_name.c_str(), tag_size, tag_type, tag_data_type, tag_rec.first, (void*) &tag_default[0], true );
+    if ( res == MB_FAILURE )
+      {
+      std::cerr
+        << "Could not create output tag name: \"" << tag_name.c_str() << "\" type: "
+        << tag_type << " data type: " << tag_data_type << "\n";
+      }
+    else
+      {
+      this->output_vertex_tags.push_back( tag_rec );
+      }
+    }
+}
+
+/**\brief Return the tag handle and its offset in the array of tag data of each vertex.
+  *
+  * @param[in] i An index into the list of tags for the vertex.
+  * @param[out] tag The tag handle on the input mesh for the $i$-th vertex tag.
+  * @param[out] byte_offset The offset (in bytes) of the start of this tag's data in a vertex tag record.
+  */
+void MBRefinerTagManager::get_input_vertex_tag( int i, MBTag& tag, int& byte_offset )
+{
+  std::vector< std::pair< MBTag, int > >::iterator it = this->input_vertex_tags.begin() + i;
+  tag = it->first;
+  byte_offset = it->second;
+}
+
+/**\brief Return the tag handle and its offset in the array of tag data of each vertex.
+  *
+  * @param[in] i An index into the list of tags for the vertex.
+  * @param[out] tag The tag handle on the output mesh for the $i$-th vertex tag.
+  * @param[out] byte_offset The offset (in bytes) of the start of this tag's data in a vertex tag record.
+  */
+void MBRefinerTagManager::get_output_vertex_tag( int i, MBTag& tag, int& byte_offset )
+{
+  std::vector< std::pair< MBTag, int > >::iterator it = this->output_vertex_tags.begin() + i;
+  tag = it->first;
+  byte_offset = it->second;
+}

Added: MOAB/trunk/refiner/MBRefinerTagManager.hpp
===================================================================
--- MOAB/trunk/refiner/MBRefinerTagManager.hpp	                        (rev 0)
+++ MOAB/trunk/refiner/MBRefinerTagManager.hpp	2008-06-13 01:30:49 UTC (rev 1892)
@@ -0,0 +1,59 @@
+/**
+ * MOAB, a Mesh-Oriented datABase, is a software component for creating,
+ * storing and accessing finite element mesh data.
+ * 
+ * Copyright 2004 Sandia Corporation.  Under the terms of Contract
+ * DE-AC04-94AL85000 with Sandia Coroporation, the U.S. Government
+ * retains certain rights in this software.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ */
+
+/** \class MBRefinerTagManager
+  *
+  * This a class that manages which tags an edge refiner should include
+  * on output vertices created during mesh refinement.
+  * The 
+  *
+  * \author David Thompson
+  *
+  * \date 12 June 2008
+  */
+#ifndef MB_REFINERTAGMANAGER_H
+#define MB_REFINERTAGMANAGER_H
+
+#include "MBTypes.h" // for MB_DLL_EXPORT
+
+#include <vector>
+
+class MBInterface;
+
+class MB_DLL_EXPORT MBRefinerTagManager
+{
+public:
+  MBRefinerTagManager( MBInterface* in_mesh, MBInterface* out_mesh );
+  virtual ~MBRefinerTagManager();
+
+  void reset_vertex_tags();
+  int add_vertex_tag( MBTag tag_handle );
+  int get_vertex_tag_size() const { return this->vertex_size; }
+  int get_number_of_vertex_tags() const { return this->input_vertex_tags.size(); }
+
+  void create_output_tags();
+
+  void get_input_vertex_tag( int i, MBTag& tag, int& byte_offset );
+  void get_output_vertex_tag( int i, MBTag& tag, int& byte_offset );
+
+protected:
+  std::vector< std::pair< MBTag, int > > input_vertex_tags;
+  std::vector< std::pair< MBTag, int > > output_vertex_tags;
+  int vertex_size;
+  MBInterface* input_mesh;
+  MBInterface* output_mesh;
+};
+
+#endif // MB_REFINERTAGMANAGER_H

Modified: MOAB/trunk/refiner/MBSimplexTemplateRefiner.cpp
===================================================================
--- MOAB/trunk/refiner/MBSimplexTemplateRefiner.cpp	2008-06-11 19:08:53 UTC (rev 1891)
+++ MOAB/trunk/refiner/MBSimplexTemplateRefiner.cpp	2008-06-13 01:30:49 UTC (rev 1892)
@@ -67,7 +67,7 @@
     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 );
+      this->edge_size_evaluator->get_input_vertex_tag( i, tag_handle, tag_offset );
       if ( this->mesh->tag_get_data( tag_handle, &conn[n], 1, (char*)tag_data + tag_offset ) != MB_SUCCESS )
         {
         return false;

Modified: MOAB/trunk/refiner/MBSimplexTemplateTagAssigner.cpp
===================================================================
--- MOAB/trunk/refiner/MBSimplexTemplateTagAssigner.cpp	2008-06-11 19:08:53 UTC (rev 1891)
+++ MOAB/trunk/refiner/MBSimplexTemplateTagAssigner.cpp	2008-06-13 01:30:49 UTC (rev 1892)
@@ -61,7 +61,7 @@
   int tag_offset;
   for ( int i = 0; i < num_tags; ++i )
     {
-    this->edge_size_evaluator->get_vertex_tag( i, tag_handle, tag_offset );
+    this->edge_size_evaluator->get_input_vertex_tag( i, tag_handle, tag_offset );
     this->mesh_refiner->get_mesh()->tag_get_data_type( tag_handle, data_type );
     this->mesh_refiner->get_mesh()->tag_get_size( tag_handle, tag_size );
     

Modified: MOAB/trunk/refiner/test_mesh_refiner.cpp
===================================================================
--- MOAB/trunk/refiner/test_mesh_refiner.cpp	2008-06-11 19:08:53 UTC (rev 1891)
+++ MOAB/trunk/refiner/test_mesh_refiner.cpp	2008-06-13 01:30:49 UTC (rev 1892)
@@ -10,21 +10,100 @@
 #endif // USE_MPI
 
 #include <iostream>
+#include <map>
 
-class MBTestOutputFunctor : public MBEntityRefinerOutputFunctor
+template< int _n >
+class MBSplitVertexIndex
 {
 public:
-  typedef std::vector<MBEntityHandle> node_list_t;
-  typedef std::pair<MBEntityHandle,MBEntityHandle> node_pair_t;
-  typedef std::map<MBEntityHandle,MBEntityHandle> node_hash_t;
-  typedef std::map<node_pair_t,MBEntityHandle> edge_hash_t;
+  MBSplitVertexIndex() { }
+  MBSplitVertexIndex( const MBEntityHandle* src )
+    { for ( int i = 0; i < _n; ++ i ) this->handles[i] = src[i]; std::sort( this->handles, this->handles + _n ); }
+  MBSplitVertexIndex( const MBSplitVertexIndex<_n>& src )
+    { for ( int i = 0; i < _n; ++ i ) this->handles[i] = src.handles[i]; }
+  MBSplitVertexIndex& operator = ( const MBSplitVertexIndex<_n>& src )
+    { for ( int i = 0; i < _n; ++ i ) this->handles[i] = src.handles[i]; return *this; }
 
+  virtual bool operator < ( const MBSplitVertexIndex<_n>& other ) const
+    {
+    for ( int i = 0; i < _n; ++ i )
+      if ( this->handles[i] < other.handles[i] )
+        return true;
+      else if ( this->handles[i] > other.handles[i] )
+        return false;
+    return true;
+    }
+
+  MBEntityHandle handles[_n];
+};
+
+class MBSplitVerticesBase
+{
+public:
+  MBSplitVerticesBase( MBInterface* m )
+    {
+    this->mesh = m;
+    }
+  virtual bool find_or_create( const MBEntityHandle* split_src, const double* coords, MBEntityHandle& vert_handle ) = 0;
   MBInterface* mesh;
+};
+
+template< int _n >
+class MBSplitVertices : public std::map<MBSplitVertexIndex<_n>,MBEntityHandle>, public MBSplitVerticesBase
+{
+public:
+  typedef std::map<MBSplitVertexIndex<_n>,MBEntityHandle> MapType;
+  typedef typename std::map<MBSplitVertexIndex<_n>,MBEntityHandle>::iterator MapIteratorType;
+
+  MBSplitVertices( MBInterface* m )
+    : MBSplitVerticesBase( m )
+    {
+    }
+  virtual bool find_or_create( const MBEntityHandle* split_src, const double* coords, MBEntityHandle& vert_handle )
+    {
+    MapIteratorType it = this->find( MBSplitVertexIndex<_n>( split_src ) );
+    if ( it == this->end() )
+      {
+      if ( this->mesh->create_vertex( coords, vert_handle ) != MB_SUCCESS )
+        {
+        return false;
+        }
+      return true;
+      }
+    vert_handle = it->second;
+    return false;
+    }
+};
+
+
+class MBTestOutputFunctor : public MBEntityRefinerOutputFunctor
+{
+public:
+  MBInterface* mesh;
   bool input_is_output;
-  node_hash_t node_hash;
-  edge_hash_t edge_hash;
-  node_list_t elem_vert;
+  std::vector<MBSplitVerticesBase*> split_vertices;
+  std::vector<MBEntityHandle> elem_vert;
+  MBEdgeSizeEvaluator* edge_size_evaluator;
 
+  MBTestOutputFunctor( MBInterface* imesh, MBInterface* omesh, MBEdgeSizeEvaluator* size_eval )
+    {
+    this->mesh = omesh;
+    this->input_is_output = ( imesh == omesh );
+    this->edge_size_evaluator = size_eval;
+
+    this->split_vertices.resize( 4 );
+    this->split_vertices[0] = 0; // Vertices (0-faces) cannot be split
+    this->split_vertices[1] = new MBSplitVertices<1>( this->mesh );
+    this->split_vertices[2] = new MBSplitVertices<2>( this->mesh );
+    this->split_vertices[3] = new MBSplitVertices<3>( this->mesh );
+    }
+
+  ~MBTestOutputFunctor()
+    {
+    for ( int i = 0; i < 4; ++ i )
+      delete this->split_vertices[i];
+    }
+
   void print_vert_crud( MBEntityHandle vout, int nvhash, MBEntityHandle* vhash, const double* vcoords, const void* vtags )
     {
     std::cout << "+ {";
@@ -46,6 +125,21 @@
     std::cout << " >\n";
     }
 
+  void assign_tags( MBEntityHandle vhandle, const void* vtags )
+    {
+    if ( ! vhandle )
+      return; // Ignore bad vertices
+
+    int num_tags = this->edge_size_evaluator->get_number_of_vertex_tags();
+    MBTag tag_handle;
+    int tag_offset;
+    for ( int i = 0; i < num_tags; ++i )
+      {
+      this->edge_size_evaluator->get_output_vertex_tag( i, tag_handle, tag_offset );
+      this->mesh->tag_set_data( tag_handle, &vhandle, 1, vtags );
+      }
+    }
+
   virtual MBEntityHandle operator () ( MBEntityHandle vhash, const double* vcoords, const void* vtags )
     {
     if ( this->input_is_output )
@@ -58,6 +152,7 @@
       {
       std::cerr << "Could not insert mid-edge vertex!\n";
       }
+    this->assign_tags( vertex_handle, vtags );
     this->print_vert_crud( vertex_handle, 1, &vhash, vcoords, vtags );
     return vertex_handle;
     }
@@ -69,39 +164,23 @@
       {
       vertex_handle = (*this)( *vhash, vcoords, vtags );
       }
-    else if ( nvhash == 2 )
+    else if ( nvhash < 4 )
       {
-      node_pair_t pr;
-      if ( vhash[0] < vhash[1] )
+      bool newly_created = this->split_vertices[nvhash]->find_or_create( vhash, vcoords, vertex_handle );
+      if ( newly_created )
         {
-        pr.first = vhash[0];
-        pr.second = vhash[1];
+        this->assign_tags( vertex_handle, vtags );
         }
-      else
+      if ( ! vertex_handle )
         {
-        pr.first = vhash[1];
-        pr.second = vhash[0];
+        std::cerr << "Could not insert mid-edge vertex!\n";
         }
-      edge_hash_t::iterator it = this->edge_hash.find( pr );
-      if ( it == this->edge_hash.end() )
-        {
-        if ( this->mesh->create_vertex( vcoords + 3, vertex_handle ) != MB_SUCCESS )
-          {
-          std::cerr << "Could not insert mid-edge vertex!\n";
-          }
-        this->edge_hash[pr] = vertex_handle;
-        }
-      else
-        {
-        vertex_handle = it->second;
-        }
-      this->print_vert_crud( vertex_handle, 2, vhash, vcoords, vtags );
+      this->print_vert_crud( vertex_handle, nvhash, vhash, vcoords, vtags );
       }
     else
       {
-      vertex_handle = -1;
-      std::cerr << "Not handling mid-face vertices yet.\n";
-      // FIXME: Handle face midpoint.
+      vertex_handle = 0;
+      std::cerr << "Not handling splits on faces with " << nvhash << " corners yet.\n";
       }
     return vertex_handle;
     }
@@ -137,14 +216,11 @@
   rank = 0;
 #endif // USE_MPI
 
-  MBInterface* iface = new MBCore;
-  MBEdgeSizeSimpleImplicit* eval = new MBEdgeSizeSimpleImplicit( iface );
+  bool input_is_output = ( argc > 1 && ! strcmp( argv[1], "-new-mesh" ) ) ? false : true;
+  MBInterface* imesh = new MBCore;
+  MBInterface* omesh = input_is_output ? imesh : new MBCore;
+  MBEdgeSizeSimpleImplicit* eval = new MBEdgeSizeSimpleImplicit( imesh, omesh );
 
-  double p0[6] = { 0.0, 0.0, 0.0,  0.0, 0.0, 0.0 };
-  double p1[6] = { 0.5, 0.0, 0.0,  0.5, 0.0, 0.0 };
-  double p2[6] = { 1.0, 0.0, 0.0,  1.0, 0.0, 0.0 };
-  double p3[6] = { 0.6, 2.0, 0.0,  0.6, 2.0, 0.0 };
-
   double coords[][6] = {
     {  0. ,  0.0,  0. ,  0. ,  0.0,  0.  }, // 0
     { -1. ,  0.0,  0.5, -1. ,  0.0,  0.5 }, // 1
@@ -207,50 +283,55 @@
   MBEntityHandle tri_handle;
 
   MBTag tag_floatular;
-  iface->tag_create( "floatular", 2 * sizeof( double ), MB_TAG_DENSE, MB_TYPE_DOUBLE, tag_floatular, default_floatular );
+  imesh->tag_create( "floatular", 2 * sizeof( double ), MB_TAG_DENSE, MB_TYPE_DOUBLE, tag_floatular, default_floatular );
 
   MBTag tag_intular;
-  iface->tag_create( "intular", 4 * sizeof( int ), MB_TAG_DENSE, MB_TYPE_INTEGER, tag_intular, default_intular );
+  imesh->tag_create( "intular", 4 * sizeof( int ), MB_TAG_DENSE, MB_TYPE_INTEGER, tag_intular, default_intular );
 
   MBTag tag_gid;
-  iface->tag_create( PARALLEL_GID_TAG_NAME, sizeof( int ), MB_TAG_DENSE, MB_TYPE_INTEGER, tag_gid, default_gid );
+  imesh->tag_create( PARALLEL_GID_TAG_NAME, sizeof( int ), MB_TAG_DENSE, MB_TYPE_INTEGER, tag_gid, default_gid );
 
+  MBTag tag_spr;
+  imesh->tag_create( PARALLEL_SHARED_PROCS_TAG_NAME, 4 * sizeof( int ), MB_TAG_DENSE, MB_TYPE_INTEGER, tag_spr, default_gid );
+
   void const* iptrs[4];
   void const* fptrs[4];
   void const* gptrs[4];
+  void const* sptrs[4];
   for ( int i = 0; i < 4; ++ i )
     {
-    iface->create_vertex( coords[proc_nodes[rank][i]], node_handles[i] );
+    imesh->create_vertex( coords[proc_nodes[rank][i]], node_handles[i] );
     iptrs[i] = (void const*) intular_values[proc_nodes[rank][i]];
     fptrs[i] = (void const*) floatular_values[proc_nodes[rank][i]];
     gptrs[i] = (void const*) &gid_values[proc_nodes[rank][i]];
+    sptrs[i] = (void const*) &node_procs[proc_nodes[rank][i]];
     }
 
-  iface->tag_set_data( tag_floatular, node_handles, 4, fptrs, 0 );
+  imesh->tag_set_data( tag_floatular, node_handles, 4, fptrs, 0 );
   eval->add_vertex_tag( tag_floatular );
 
-  iface->tag_set_data( tag_intular, node_handles, 4, iptrs, 0 );
+  imesh->tag_set_data( tag_intular, node_handles, 4, iptrs, 0 );
   eval->add_vertex_tag( tag_intular );
 
-  iface->tag_set_data( tag_gid, node_handles, 4, gptrs, 0 );
+  imesh->tag_set_data( tag_gid, node_handles, 4, gptrs, 0 );
+  imesh->tag_set_data( tag_spr, node_handles, 4, sptrs, 0 );
 
-  iface->create_element( MBTET, node_handles, 4, tet_handle );
-  iface->tag_set_data( tag_gid, &tet_handle, 1, gid_values + 6 + rank );
-  iface->list_entities( 0, 1 );
+  imesh->create_element( MBTET, node_handles, 4, tet_handle );
+  imesh->tag_set_data( tag_gid, &tet_handle, 1, gid_values + 6 + rank );
+  imesh->list_entities( 0, 1 );
 
-  MBSimplexTemplateRefiner eref( iface );
-  MBTestOutputFunctor* ofunc = new MBTestOutputFunctor;
-  ofunc->input_is_output = ( argc > 1 && ! strcmp( argv[1], "-new-mesh" ) ) ? false : true;
-  ofunc->mesh = ofunc->input_is_output ? iface : new MBCore;
+  MBSimplexTemplateRefiner eref( imesh );
+  MBTestOutputFunctor* ofunc = new MBTestOutputFunctor( imesh, omesh, eval );
   eref.set_edge_size_evaluator( eval );
   eref.set_output_functor( ofunc );
+  eval->create_output_tags();
   eref.refine_entity( tet_handle );
 
   ofunc->mesh->list_entities( 0, 1 );
 
   if ( ! ofunc->input_is_output )
     delete ofunc->mesh;
-  delete iface;
+  delete imesh;
 
 #ifdef USE_MPI
   err = MPI_Barrier( MPI_COMM_WORLD );




More information about the moab-dev mailing list