MOAB: Mesh Oriented datABase  (version 5.4.1)
EntityRefiner.cpp
Go to the documentation of this file.
00001 #include "EntityRefiner.hpp"
00002 
00003 #include "EdgeSizeEvaluator.hpp"
00004 #include "moab/Interface.hpp"
00005 
00006 namespace moab
00007 {
00008 
00009 /// Construct an entity refiner.
00010 EntityRefiner::EntityRefiner()
00011 {
00012     this->mesh_in             = 0;
00013     this->edge_size_evaluator = 0;
00014     this->output_functor      = 0;
00015     // By default, allow at most one subdivision per edge
00016     this->minimum_number_of_subdivisions = 0;
00017     this->maximum_number_of_subdivisions = 1;
00018 }
00019 
00020 /// Destruction is virtual so subclasses may clean up after refinement.
00021 EntityRefiner::~EntityRefiner()
00022 {
00023     if( this->edge_size_evaluator ) delete this->edge_size_evaluator;
00024 }
00025 
00026 /**\brief Prepare to start refining entities on a given mesh.
00027  * This is called once before refine_entity() is ever invoked.
00028  * The tag manager specifies the input and output meshes upon which the refiner will act.
00029  *
00030  * This function returns false if calling refine_entity() immediately
00031  * afterwards would cause a failure (due, for example, to a NULL edge_size_evaluator).
00032  * Otherwise it returns true.
00033  */
00034 bool EntityRefiner::prepare( RefinerTagManager* tmgr, EntityRefinerOutputFunctor* ofunc )
00035 {
00036     bool rval = true;
00037     if( this->edge_size_evaluator )
00038     {
00039         this->edge_size_evaluator->set_tag_manager( tmgr );
00040     }
00041     else
00042     {
00043         rval = false;
00044     }
00045     this->set_output_functor( ofunc );
00046     this->mesh_in = tmgr->get_input_mesh();
00047     this->update_heap_size();
00048     return rval;
00049 }
00050 
00051 /**\fn bool EntityRefiner::refine_entity( EntityHandle )
00052  *\brief Method implemented by subclasses to create decompositions of entities using edge
00053  *subdivisions.
00054  */
00055 
00056 /**\fn int EntityRefiner::get_heap_size_bound( int max_recursions ) const
00057  *\brief When an entity is refined, what is the maximum number of new vertices that will be created?
00058  *
00059  * This must be the maximum number of initial corner vertices for any entity type (hex, tet, etc.)
00060  * to be processed plus the maximum number of new vertices that might be created at edge or face
00061  * mid-points during the refinement of a single entity.
00062  */
00063 
00064 /**\brief Set the object that specifies which edges of a given entity should be subdivided.
00065  *
00066  * The entity refiner takes ownership of edge size evaluator and will delete it when
00067  * a new value is set or when the entity refiner is destroyed.
00068  *
00069  * @param ese The new edge size evaluator object.
00070  * @retval Returns true if the value was changed and false otherwise.
00071  */
00072 bool EntityRefiner::set_edge_size_evaluator( EdgeSizeEvaluator* ese )
00073 {
00074     if( !ese || ese == this->edge_size_evaluator ) return false;
00075 
00076     if( this->edge_size_evaluator )
00077     {
00078         delete this->edge_size_evaluator;
00079     }
00080     this->edge_size_evaluator = ese;
00081 
00082     return true;
00083 }
00084 
00085 /**\fn EdgeSizeEvaluator* EntityRefiner::get_edge_size_evaluator()
00086  *\brief Return a pointer to the object that specifies which edges of a given entity should be
00087  *subdivided.
00088  *
00089  * This may return NULL if no value has been previously specified.
00090  *
00091  * @retval A pointer to an edge size evaluator object or NULL.
00092  */
00093 
00094 /**\brief Set the functor through which output entities are streamed.
00095  *
00096  * Any previously assigned functor will be deleted when a new functor is set.
00097  *
00098  * @retvalReturns true if the value was changed and false otherwise.
00099  */
00100 bool EntityRefiner::set_output_functor( EntityRefinerOutputFunctor* func_obj )
00101 {
00102     if( !func_obj || func_obj == this->output_functor ) return false;
00103 
00104     if( this->output_functor )
00105     {
00106         delete this->output_functor;
00107     }
00108     this->output_functor = func_obj;
00109     return true;
00110 }
00111 
00112 /**\fn EntityRefinerOutputFunctor* EntityRefiner::get_output_functor()
00113  *\brief Return the functor used to stream output.
00114  *
00115  * @retval A pointer to the functor. This may be NULL.
00116  */
00117 
00118 /**\brief Set the minimum number of recursive subdivisions that should occur, regardless of the
00119  * edge_size_evaluator's response.
00120  *
00121  * This is useful for forcing global refinement.
00122  *
00123  * @retval True if the number of subdivisions was changed; false otherwise.
00124  */
00125 bool EntityRefiner::set_minimum_number_of_subdivisions( int mn )
00126 {
00127     if( mn < 0 || mn == this->minimum_number_of_subdivisions )
00128     {
00129         return false;
00130     }
00131 
00132     this->minimum_number_of_subdivisions = mn;
00133     return true;
00134 }
00135 
00136 /**\fn int EntityRefiner::get_minimum_number_of_subdivisions() const
00137  *\brief Return the minimum number of recursive edge subdivisions guaranteed to take place,
00138  *regardless of the edge size evaluator.
00139  *
00140  * This may any non-negative integer.
00141  *
00142  * @retval The guaranteed minimum number of subdivisions that will take place on each and every edge
00143  *of the mesh.
00144  */
00145 
00146 /**\brief Set the maximum number of recursive subdivisions that should occur, regardless of the
00147  * edge_size_evaluator's response.
00148  *
00149  * This is useful for preventing infinite recursion.
00150  * A value of 0 is allowed although not terribly practical.
00151  *
00152  * @retval True if the number of subdivisions was changed; false otherwise.
00153  */
00154 bool EntityRefiner::set_maximum_number_of_subdivisions( int mx )
00155 {
00156     if( mx < 0 || mx == this->maximum_number_of_subdivisions )
00157     {
00158         return false;
00159     }
00160 
00161     this->maximum_number_of_subdivisions = mx;
00162     this->update_heap_size();
00163     return true;
00164 }
00165 
00166 /**\fn int EntityRefiner::get_maximum_number_of_subdivisions() const
00167  *\brief Return the maximum number of recursive edge subdivisions guaranteed to take place,
00168  *regardless of the edge size evaluator.
00169  *
00170  * This may any non-negative integer.
00171  *
00172  * @retval The guaranteed maximum number of subdivisions that will take place on each and every edge
00173  *of the mesh.
00174  */
00175 
00176 /**\brief This is called when the edge size evaluator or maximum number of subdivisions is changed
00177  *       to make sure the heaps are properly sized.
00178  *
00179  * Tag heap size cannot be computed if the edge_size_evaluator is NULL.
00180  */
00181 void EntityRefiner::update_heap_size()
00182 {
00183     unsigned long n = this->get_heap_size_bound( this->maximum_number_of_subdivisions );
00184     this->coord_heap.resize( 6 * n );
00185     if( this->edge_size_evaluator )
00186     {
00187         unsigned long m = this->edge_size_evaluator->get_tag_manager()->get_vertex_tag_size();
00188         this->tag_heap.resize( m * n );
00189     }
00190 }
00191 
00192 /**\brief Subclasses should call this on entry to refine_entity().
00193  *
00194  * When called, future calls to heap_coord_storage() and heap_tag_storage() will
00195  * re-use the allocated storage starting from the beginning.
00196  */
00197 void EntityRefiner::reset_heap_pointers()
00198 {
00199     this->current_coord = this->coord_heap.begin();
00200     this->current_tag   = this->tag_heap.begin();
00201 }
00202 
00203 /**\brief Return a pointer to temporary storage for edge midpoint vertex coordinates inside
00204  * refine_entity().
00205  *
00206  * The returned pointer references 6 uninitialized double values to hold parametric coordinates and
00207  * world coordinates.
00208  */
00209 double* EntityRefiner::heap_coord_storage()
00210 {
00211     double* rval;
00212     if( this->current_coord != this->coord_heap.end() )
00213     {
00214         rval = &( *this->current_coord );
00215         this->current_coord += 6;
00216     }
00217     else
00218     {
00219         rval = 0;
00220     }
00221     return rval;
00222 }
00223 
00224 /**\brief Return a pointer to temporary storage for edge midpoint vertex coordinates inside
00225  * refine_entity().
00226  *
00227  * The returned pointer references enough bytes to store all the tags for a vertex as reported by
00228  * the current edge size evaluator's EdgeSizeEvaluator::get_vertex_tag_size().
00229  */
00230 void* EntityRefiner::heap_tag_storage()
00231 {
00232     void* rval;
00233     if( this->edge_size_evaluator && this->current_tag != this->tag_heap.end() )
00234     {
00235         rval = (void*)&( *this->current_tag );
00236         this->current_tag += this->edge_size_evaluator->get_tag_manager()->get_vertex_tag_size();
00237     }
00238     else
00239     {
00240         rval = 0;
00241     }
00242     return rval;
00243 }
00244 
00245 }  // namespace moab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines