![]() |
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