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

dcthomp at mcs.anl.gov dcthomp at mcs.anl.gov
Wed Dec 26 22:29:03 CST 2007


Author: dcthomp
Date: 2007-12-26 22:28:59 -0600 (Wed, 26 Dec 2007)
New Revision: 1488

Added:
   MOAB/trunk/refiner/MBSimplexTemplateRefiner.cpp
Modified:
   MOAB/trunk/refiner/CMakeLists.txt
   MOAB/trunk/refiner/MBEntityRefiner.cpp
   MOAB/trunk/refiner/MBEntityRefiner.hpp
   MOAB/trunk/refiner/MBSimplexTemplateRefiner.hpp
Log:
ENH: Checkpoint on refiner work.


Modified: MOAB/trunk/refiner/CMakeLists.txt
===================================================================
--- MOAB/trunk/refiner/CMakeLists.txt	2007-12-26 21:41:52 UTC (rev 1487)
+++ MOAB/trunk/refiner/CMakeLists.txt	2007-12-27 04:28:59 UTC (rev 1488)
@@ -3,6 +3,7 @@
   MBEdgeSizeSimpleImplicit.cpp
   MBEntityRefiner.cpp
   MBMeshRefiner.cpp
+  MBSimplexTemplateRefiner.cpp
   )
 
 add_library( MOABrefiner

Modified: MOAB/trunk/refiner/MBEntityRefiner.cpp
===================================================================
--- MOAB/trunk/refiner/MBEntityRefiner.cpp	2007-12-26 21:41:52 UTC (rev 1487)
+++ MOAB/trunk/refiner/MBEntityRefiner.cpp	2007-12-27 04:28:59 UTC (rev 1488)
@@ -1,24 +1,181 @@
 #include "MBEntityRefiner.hpp"
 
+#include "MBEdgeSizeEvaluator.hpp"
 #include "MBInterface.hpp"
 
+/// Construct an entity refiner.
 MBEntityRefiner::MBEntityRefiner( MBInterface* parentMesh )
 {  
   this->mesh = parentMesh;
   this->edge_size_evaluator = 0;
+  // By default, allow at most one subdivision per edge
+  this->minimum_number_of_subdivisions = 0;
+  this->maximum_number_of_subdivisions = 1;
 }
 
+/// Destruction is virtual so subclasses may clean up after refinement.
 MBEntityRefiner::~MBEntityRefiner()
 {
+  if ( this->edge_size_evaluator )
+    delete this->edge_size_evaluator;
 }
 
+/**\fn bool MBEntityRefiner::refine_entity( MBEntityHandle )
+  *\brief Method implemented by subclasses to create decompositions of entities using edge subdivisions.
+  */
+
+/**\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.).
+  */
+
+/**\brief Set the object that specifies which edges of a given entity should be subdivided.
+  *
+  * The entity refiner takes ownership of edge size evaluator and will delete it when
+  * a new value is set or when the entity refiner is destroyed.
+  *
+  * @param ese The new edge size evaluator object.
+  * @retval Returns true if the value was changed and false otherwise.
+  */
 bool MBEntityRefiner::set_edge_size_evaluator( MBEdgeSizeEvaluator* ese )
 {
-  if ( ! ese ) return false;
+  if ( ! ese || ese == this->edge_size_evaluator )
+    return false;
 
+  if ( this->edge_size_evaluator )
+    {
+    delete this->edge_size_evaluator;
+    }
   this->edge_size_evaluator = ese;
+  this->update_heap_size();
 
   return true;
 }
 
+/**\fn MBEdgeSizeEvaluator* MBEntityRefiner::get_edge_size_evaluator()
+  *\brief Return a pointer to the object that specifies which edges of a given entity should be subdivided.
+  *
+  * This may return NULL if no value has been previously specified.
+  *
+  * @retval A pointer to an edge size evaluator object or NULL.
+  */
 
+/**\brief Set the minimum number of recursive subdivisions that should occur, regardless of the edge_size_evaluator's response.
+  *
+  * This is useful for forcing global refinement.
+  *
+  * @retval True if the number of subdivisions was changed; false otherwise.
+  */
+bool MBEntityRefiner::set_minimum_number_of_subdivisions( int mn )
+{
+  if ( mn < 0 || mn == this->minimum_number_of_subdivisions )
+    {
+    return false;
+    }
+
+  this->minimum_number_of_subdivisions = mn;
+  return true;
+}
+
+/**\fn int MBEntityRefiner::get_minimum_number_of_subdivisions() const
+  *\brief Return the minimum number of recursive edge subdivisions guaranteed to take place, regardless of the edge size evaluator.
+  *
+  * This may any non-negative integer.
+  *
+  * @retval The guaranteed minimum number of subdivisions that will take place on each and every edge of the mesh.
+  */
+
+/**\brief Set the maximum number of recursive subdivisions that should occur, regardless of the edge_size_evaluator's response.
+  *
+  * This is useful for preventing infinite recursion.
+  * A value of 0 is allowed although not terribly practical.
+  *
+  * @retval True if the number of subdivisions was changed; false otherwise.
+  */
+bool MBEntityRefiner::set_maximum_number_of_subdivisions( int mx )
+{
+  if ( mx < 0 || mx == this->maximum_number_of_subdivisions )
+    {
+    return false;
+    }
+
+  this->maximum_number_of_subdivisions = mx;
+  this->update_heap_size();
+  return true;
+}
+
+/**\fn int MBEntityRefiner::get_maximum_number_of_subdivisions() const
+  *\brief Return the maximum number of recursive edge subdivisions guaranteed to take place, regardless of the edge size evaluator.
+  *
+  * This may any non-negative integer.
+  *
+  * @retval The guaranteed maximum number of subdivisions that will take place on each and every edge of the mesh.
+  */
+
+/**\brief This is called when the edge size evaluator or maximum number of subdivisions is changed
+  *       to make sure the heaps are properly sized.
+  *
+  * Tag heap size cannot be computed if the edge_size_evaluator is NULL.
+  */
+void MBEntityRefiner::update_heap_size()
+{
+  unsigned long n = this->get_heap_size_bound( this->maximum_number_of_subdivisions );
+  this->coord_heap.reserve( 6 * n );
+  if ( this->edge_size_evaluator )
+    {
+    unsigned long m = this->edge_size_evaluator->get_vertex_tag_size();
+    this->tag_heap.reserve( m * n );
+    }
+}
+
+/**\brief Subclasses should call this on entry to refine_entity().
+  *
+  * When called, future calls to heap_coord_storage() and heap_tag_storage() will
+  * re-use the allocated storage starting from the beginning.
+  */
+void MBEntityRefiner::reset_heap_pointers()
+{
+  this->current_coord = this->coord_heap.begin();
+  this->current_tag = this->tag_heap.begin();
+}
+
+/**\brief Return a pointer to temporary storage for edge midpoint vertex coordinates inside refine_entity().
+  *
+  * The returned pointer references 6 uninitialized double values to hold parametric coordinates and world coordinates.
+  */
+double* MBEntityRefiner::heap_coord_storage()
+{
+  double* rval;
+  if ( this->current_coord != this->coord_heap.end() )
+    {
+    rval = &(*this->current_coord);
+    this->current_coord += 6;
+    }
+  else
+    {
+    rval = 0;
+    }
+  return rval;
+}
+
+/**\brief Return a pointer to temporary storage for edge midpoint vertex coordinates inside refine_entity().
+  *
+  * The returned pointer references enough bytes to store all the tags for a vertex as reported by the
+  * current edge size evaluator's MBEdgeSizeEvaluator::get_vertex_tag_size().
+  */
+char* MBEntityRefiner::heap_tag_storage()
+{
+  char* rval;
+  if ( this->edge_size_evaluator && this->current_tag != this->tag_heap.end() )
+    {
+    rval = &(*this->current_tag);
+    this->current_tag += this->edge_size_evaluator->get_vertex_tag_size();
+    }
+  else
+    {
+    rval = 0;
+    }
+  return rval;
+}
+

Modified: MOAB/trunk/refiner/MBEntityRefiner.hpp
===================================================================
--- MOAB/trunk/refiner/MBEntityRefiner.hpp	2007-12-26 21:41:52 UTC (rev 1487)
+++ MOAB/trunk/refiner/MBEntityRefiner.hpp	2007-12-27 04:28:59 UTC (rev 1488)
@@ -15,10 +15,30 @@
 
 /** \class MBEntityRefiner
   *
-  * This is an abstract class that contains the method used for per-entity
-  * refinement
-  * Subclasses must implement the pure virtual refine_entity() function.
+  * This is an abstract class that contains the method used for per-entity refinement.
+  * Subclasses must implement the pure virtual refine_entity() function and
+  * may implement the vertices_per_split() function.
+  * This class constructor requires a non-NULL pointer to a mesh so that, given an
+  * entity handle, it can look up vertex coordinates and tags to prepare arguments for
+  * the refine_entity() method.
   *
+  * Although the MBMeshRefiner class may not initially support it, entity refiners
+  * are required to support some level of recursion.
+  * The maximum number of recursive calls allowed may be set with
+  * MBEntityRefiner::set_maximum_number_of_subdivisions().
+  * As a convenience, some of the framework for recursion is provided by the
+  * MBEntityRefiner class.
+  *
+  * Specifically, MBEntityRefiner stores a pair of heap arrays
+  * to hold edge midpoint vertex coordinates and tag values pre-allocated to the
+  * maximum recursion depth so that no repeated allocation and deallocation
+  * needs to take place during refinement.
+  * To use these heaps, subclasses should call reset_heap_pointers() upon entry to
+  * MBEntityRefiner::refine_entity().
+  * Then, when the edge size evaluator requires an edge to be split, subclasses
+  * should call heap_coord_storage() and heap_tag_storage() to obtain pointers as
+  * required.
+  *
   * \author David Thompson
   * \author Philippe Pebay
   *
@@ -37,19 +57,35 @@
 class MB_DLL_EXPORT MBEntityRefiner
 {
 public:
-  /// Construct an entity refiner.
   MBEntityRefiner( MBInterface* );
-  /// Destruction is virtual so subclasses may clean up after refinement.
   virtual ~MBEntityRefiner();
 
   virtual bool refine_entity( MBEntityHandle ) = 0;
+  virtual unsigned long get_heap_size_bound( int max_recursions ) const = 0;
 
-  bool set_edge_size_evaluator( MBEdgeSizeEvaluator* );
-  MBEdgeSizeEvaluator* get_edge_size_evaluator() { return this->edge_size_evaluator; };
+  virtual bool set_edge_size_evaluator( MBEdgeSizeEvaluator* );
+  MBEdgeSizeEvaluator* get_edge_size_evaluator() { return this->edge_size_evaluator; }
 
+  virtual bool set_minimum_number_of_subdivisions( int mn );
+  int get_minimum_number_of_subdivisions() const { return this->minimum_number_of_subdivisions; }
+
+  virtual bool set_maximum_number_of_subdivisions( int mx );
+  int get_maximum_number_of_subdivisions() const { return this->maximum_number_of_subdivisions; }
+
 protected:
   MBInterface* mesh;
   MBEdgeSizeEvaluator* edge_size_evaluator;
+  int minimum_number_of_subdivisions;
+  int maximum_number_of_subdivisions;
+  std::vector<double> coord_heap;
+  std::vector<double>::iterator current_coord;
+  std::vector<char> tag_heap;
+  std::vector<char>::iterator current_tag;
+
+  void update_heap_size();
+  void reset_heap_pointers();
+  double* heap_coord_storage();
+  char* heap_tag_storage();
 };
 
 #endif // MB_ENTITYREFINER_H

Added: MOAB/trunk/refiner/MBSimplexTemplateRefiner.cpp
===================================================================
--- MOAB/trunk/refiner/MBSimplexTemplateRefiner.cpp	                        (rev 0)
+++ MOAB/trunk/refiner/MBSimplexTemplateRefiner.cpp	2007-12-27 04:28:59 UTC (rev 1488)
@@ -0,0 +1,118 @@
+#include "MBSimplexTemplateRefiner.hpp"
+
+#include "MBInterface.hpp"
+
+#include <iostream>
+
+/// Construct a template refiner.
+MBSimplexTemplateRefiner::MBSimplexTemplateRefiner( MBInterface* mesh )
+  : MBEntityRefiner( mesh )
+{
+}
+
+/// Empty destructor for good form.
+MBSimplexTemplateRefiner::~MBSimplexTemplateRefiner()
+{
+}
+
+bool MBSimplexTemplateRefiner::refine_entity( MBEntityHandle entity )
+{
+  this->reset_heap_pointers();
+  bool rval = true;
+  switch ( this->mesh->type_from_handle( entity ) )
+    {
+    case MBVERTEX:
+      this->refine_0_simplex();
+      rval = false;
+      break;
+    case MBEDGE:
+      rval = this->refine_1_simplex();
+      break;
+    case MBTRI:
+      rval = this->refine_2_simplex();
+      break;
+    case MBQUAD:
+      std::cerr << "Quadrilaterals not handled yet\n";
+      rval = false;
+      break;
+    case MBPOLYGON:
+      std::cerr << "Polygons not handled yet\n";
+      rval = false;
+      break;
+    case MBTET:
+      rval = this->refine_3_simplex();
+      break;
+    case MBPYRAMID:
+      std::cerr << "Pyramid schemes not handled yet\n";
+      rval = false;
+      break;
+    case MBPRISM:
+      std::cerr << "Prisms not handled yet\n";
+      rval = false;
+      break;
+    case MBKNIFE:
+      std::cerr << "Knifahedra not handled yet\n";
+      rval = false;
+      break;
+    case MBHEX:
+      std::cerr << "Hexahedra not handled yet\n";
+      rval = false;
+      break;
+    case MBPOLYHEDRON:
+      std::cerr << "Polyhedra not handled yet\n";
+      rval = false;
+      break;
+    case MBENTITYSET:
+      std::cerr <<
+        "How should entity sets be handled? We might iterate over its entries or skip it."
+        "Must coordinate with MBMeshRefiner's loop over entities...\n";
+      rval = false;
+      break;
+    case MBMAXTYPE:
+      rval = false;
+      break;
+    }
+  return rval;
+}
+
+/**\fn unsigned long MBSimplexTemplateRefiner::get_heap_size_bound( int max_recursions ) const
+  *\brief Bound on the number of new vertices used to allocate the heap.
+  *
+  * This bound is based on a hexahedron that is divided into 48 tetrahedra (a point is added to
+  * the center of each face so that compatible boundaries are guaranteed on neighboring hexahedra),
+  * each of which has 4 edges.
+  */
+
+/**\brief "Refine" a vertex by passing it through to the output.
+  *
+  * FIXME: There is some question as to whether this should pass vertices through
+  * since there does not appear to be a distinction between vertices as points
+  * in space and vertices as degrees-of-freedom in a mesh (i.e. a vertex that is
+  * treated as a lumped-parameter model).
+  */
+void MBSimplexTemplateRefiner::refine_0_simplex()
+{
+}
+
+/**\brief Refine an edge.
+  */
+bool MBSimplexTemplateRefiner::refine_1_simplex()
+{
+  return true;
+}
+
+/**\brief Refine a triangle.
+  */
+bool MBSimplexTemplateRefiner::refine_2_simplex()
+{
+  return true;
+}
+
+/**\brief Refine a tetrahedron.
+  */
+bool MBSimplexTemplateRefiner::refine_3_simplex()
+{
+  return true;
+}
+
+

Modified: MOAB/trunk/refiner/MBSimplexTemplateRefiner.hpp
===================================================================
--- MOAB/trunk/refiner/MBSimplexTemplateRefiner.hpp	2007-12-26 21:41:52 UTC (rev 1487)
+++ MOAB/trunk/refiner/MBSimplexTemplateRefiner.hpp	2007-12-27 04:28:59 UTC (rev 1488)
@@ -17,6 +17,9 @@
   *
   * This is a concrete subclass of MBEntityRefiner that implements
   * refinement using templates applied to simplices.
+  * Entities that are not simplices are divided into tetrahedra,
+  * triangles, or lines before being processed.
+  * Points are passed through unchanged.
   *
   * \author David Thompson
   * \author Philippe Pebay
@@ -26,21 +29,25 @@
 #ifndef MB_SIMPLEXTEMPLATEREFINER_H
 #define MB_SIMPLEXTEMPLATEREFINER_H
 
-#include "MBEntityRefiner.h"
+#include "MBEntityRefiner.hpp"
 
 class MB_DLL_EXPORT MBSimplexTemplateRefiner : public MBEntityRefiner
 {
 public:
-  /// Construct a template refiner.
-  MBSimplexTemplateRefiner();
-  /// Destruction is virtual so subclasses may clean up after refinement.
+  MBSimplexTemplateRefiner( MBInterface* mesh );
   virtual ~MBSimplexTemplateRefiner();
 
-  virtual bool refine_entity( MBEntityHandle );
+  virtual bool refine_entity( MBEntityHandle entity );
+  virtual unsigned long get_heap_size_bound( int max_recursions ) const { return 48 * 4 * ( 1 << max_recursions ); }
 
 protected:
   static int* template_index;
   static int* templates;
+
+  void refine_0_simplex();
+  bool refine_1_simplex();
+  bool refine_2_simplex();
+  bool refine_3_simplex();
 };
 #endif // MB_SIMPLEXTEMPLATEREFINER_H
 




More information about the moab-dev mailing list