[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