MOAB: Mesh Oriented datABase
(version 5.2.1)
|
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 ) { this->edge_size_evaluator->set_tag_manager( tmgr ); } 00038 else 00039 { 00040 rval = false; 00041 } 00042 this->set_output_functor( ofunc ); 00043 this->mesh_in = tmgr->get_input_mesh(); 00044 this->update_heap_size(); 00045 return rval; 00046 } 00047 00048 /**\fn bool EntityRefiner::refine_entity( EntityHandle ) 00049 *\brief Method implemented by subclasses to create decompositions of entities using edge 00050 *subdivisions. 00051 */ 00052 00053 /**\fn int EntityRefiner::get_heap_size_bound( int max_recursions ) const 00054 *\brief When an entity is refined, what is the maximum number of new vertices that will be created? 00055 * 00056 * This must be the maximum number of initial corner vertices for any entity type (hex, tet, etc.) 00057 * to be processed plus the maximum number of new vertices that might be created at edge or face 00058 * mid-points during the refinement of a single entity. 00059 */ 00060 00061 /**\brief Set the object that specifies which edges of a given entity should be subdivided. 00062 * 00063 * The entity refiner takes ownership of edge size evaluator and will delete it when 00064 * a new value is set or when the entity refiner is destroyed. 00065 * 00066 * @param ese The new edge size evaluator object. 00067 * @retval Returns true if the value was changed and false otherwise. 00068 */ 00069 bool EntityRefiner::set_edge_size_evaluator( EdgeSizeEvaluator* ese ) 00070 { 00071 if( !ese || ese == this->edge_size_evaluator ) return false; 00072 00073 if( this->edge_size_evaluator ) { delete this->edge_size_evaluator; } 00074 this->edge_size_evaluator = ese; 00075 00076 return true; 00077 } 00078 00079 /**\fn EdgeSizeEvaluator* EntityRefiner::get_edge_size_evaluator() 00080 *\brief Return a pointer to the object that specifies which edges of a given entity should be 00081 *subdivided. 00082 * 00083 * This may return NULL if no value has been previously specified. 00084 * 00085 * @retval A pointer to an edge size evaluator object or NULL. 00086 */ 00087 00088 /**\brief Set the functor through which output entities are streamed. 00089 * 00090 * Any previously assigned functor will be deleted when a new functor is set. 00091 * 00092 * @retvalReturns true if the value was changed and false otherwise. 00093 */ 00094 bool EntityRefiner::set_output_functor( EntityRefinerOutputFunctor* func_obj ) 00095 { 00096 if( !func_obj || func_obj == this->output_functor ) return false; 00097 00098 if( this->output_functor ) { delete this->output_functor; } 00099 this->output_functor = func_obj; 00100 return true; 00101 } 00102 00103 /**\fn EntityRefinerOutputFunctor* EntityRefiner::get_output_functor() 00104 *\brief Return the functor used to stream output. 00105 * 00106 * @retval A pointer to the functor. This may be NULL. 00107 */ 00108 00109 /**\brief Set the minimum number of recursive subdivisions that should occur, regardless of the 00110 * edge_size_evaluator's response. 00111 * 00112 * This is useful for forcing global refinement. 00113 * 00114 * @retval True if the number of subdivisions was changed; false otherwise. 00115 */ 00116 bool EntityRefiner::set_minimum_number_of_subdivisions( int mn ) 00117 { 00118 if( mn < 0 || mn == this->minimum_number_of_subdivisions ) { return false; } 00119 00120 this->minimum_number_of_subdivisions = mn; 00121 return true; 00122 } 00123 00124 /**\fn int EntityRefiner::get_minimum_number_of_subdivisions() const 00125 *\brief Return the minimum number of recursive edge subdivisions guaranteed to take place, 00126 *regardless of the edge size evaluator. 00127 * 00128 * This may any non-negative integer. 00129 * 00130 * @retval The guaranteed minimum number of subdivisions that will take place on each and every edge 00131 *of the mesh. 00132 */ 00133 00134 /**\brief Set the maximum number of recursive subdivisions that should occur, regardless of the 00135 * edge_size_evaluator's response. 00136 * 00137 * This is useful for preventing infinite recursion. 00138 * A value of 0 is allowed although not terribly practical. 00139 * 00140 * @retval True if the number of subdivisions was changed; false otherwise. 00141 */ 00142 bool EntityRefiner::set_maximum_number_of_subdivisions( int mx ) 00143 { 00144 if( mx < 0 || mx == this->maximum_number_of_subdivisions ) { return false; } 00145 00146 this->maximum_number_of_subdivisions = mx; 00147 this->update_heap_size(); 00148 return true; 00149 } 00150 00151 /**\fn int EntityRefiner::get_maximum_number_of_subdivisions() const 00152 *\brief Return the maximum number of recursive edge subdivisions guaranteed to take place, 00153 *regardless of the edge size evaluator. 00154 * 00155 * This may any non-negative integer. 00156 * 00157 * @retval The guaranteed maximum number of subdivisions that will take place on each and every edge 00158 *of the mesh. 00159 */ 00160 00161 /**\brief This is called when the edge size evaluator or maximum number of subdivisions is changed 00162 * to make sure the heaps are properly sized. 00163 * 00164 * Tag heap size cannot be computed if the edge_size_evaluator is NULL. 00165 */ 00166 void EntityRefiner::update_heap_size() 00167 { 00168 unsigned long n = this->get_heap_size_bound( this->maximum_number_of_subdivisions ); 00169 this->coord_heap.resize( 6 * n ); 00170 if( this->edge_size_evaluator ) 00171 { 00172 unsigned long m = this->edge_size_evaluator->get_tag_manager()->get_vertex_tag_size(); 00173 this->tag_heap.resize( m * n ); 00174 } 00175 } 00176 00177 /**\brief Subclasses should call this on entry to refine_entity(). 00178 * 00179 * When called, future calls to heap_coord_storage() and heap_tag_storage() will 00180 * re-use the allocated storage starting from the beginning. 00181 */ 00182 void EntityRefiner::reset_heap_pointers() 00183 { 00184 this->current_coord = this->coord_heap.begin(); 00185 this->current_tag = this->tag_heap.begin(); 00186 } 00187 00188 /**\brief Return a pointer to temporary storage for edge midpoint vertex coordinates inside 00189 * refine_entity(). 00190 * 00191 * The returned pointer references 6 uninitialized double values to hold parametric coordinates and 00192 * world coordinates. 00193 */ 00194 double* EntityRefiner::heap_coord_storage() 00195 { 00196 double* rval; 00197 if( this->current_coord != this->coord_heap.end() ) 00198 { 00199 rval = &( *this->current_coord ); 00200 this->current_coord += 6; 00201 } 00202 else 00203 { 00204 rval = 0; 00205 } 00206 return rval; 00207 } 00208 00209 /**\brief Return a pointer to temporary storage for edge midpoint vertex coordinates inside 00210 * refine_entity(). 00211 * 00212 * The returned pointer references enough bytes to store all the tags for a vertex as reported by 00213 * the current edge size evaluator's EdgeSizeEvaluator::get_vertex_tag_size(). 00214 */ 00215 void* EntityRefiner::heap_tag_storage() 00216 { 00217 void* rval; 00218 if( this->edge_size_evaluator && this->current_tag != this->tag_heap.end() ) 00219 { 00220 rval = (void*)&( *this->current_tag ); 00221 this->current_tag += this->edge_size_evaluator->get_tag_manager()->get_vertex_tag_size(); 00222 } 00223 else 00224 { 00225 rval = 0; 00226 } 00227 return rval; 00228 } 00229 00230 } // namespace moab