Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
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