MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 /* ***************************************************************** 00002 MESQUITE -- The Mesh Quality Improvement Toolkit 00003 00004 Copyright 2004 Sandia Corporation and Argonne National 00005 Laboratory. Under the terms of Contract DE-AC04-94AL85000 00006 with Sandia Corporation, the U.S. Government retains certain 00007 rights in this software. 00008 00009 This library is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU Lesser General Public 00011 License as published by the Free Software Foundation; either 00012 version 2.1 of the License, or (at your option) any later version. 00013 00014 This library is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License 00020 (lgpl.txt) along with this library; if not, write to the Free Software 00021 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 00023 [email protected], [email protected], [email protected], 00024 [email protected], [email protected], [email protected] 00025 00026 ***************************************************************** */ 00027 #ifndef MESQUITE_PATCHDATA_HPP 00028 #define MESQUITE_PATCHDATA_HPP 00029 /*! 00030 \file PatchData.hpp 00031 \brief This file contains the PatchData class and its associated mementos. 00032 00033 00034 The PatchData class provides the mesh information and functionality to Mesquite. 00035 The PatchDataVerticesMemento class allows the state of a PatchData object to be saved 00036 in order to later restore that object to its previous state. 00037 00038 \author Thomas Leurent 00039 \author Michael Brewer 00040 \date 2002-01-17 00041 */ 00042 00043 #include "Mesquite.hpp" 00044 #include "MsqVertex.hpp" 00045 #include "MsqMeshEntity.hpp" 00046 #include "MsqVertex.hpp" 00047 #include "MeshInterface.hpp" 00048 #include "MsqError.hpp" 00049 #include "Settings.hpp" 00050 #include "NodeSet.hpp" 00051 #include "MappingFunction.hpp" 00052 00053 #include <cstddef> 00054 #include <cstdlib> 00055 #include <map> 00056 #include <vector> 00057 #include <iosfwd> 00058 00059 namespace MBMesquite 00060 { 00061 class ExtraData; 00062 class PatchDataVerticesMemento; 00063 class Mesh; 00064 class Settings; 00065 00066 /*! 00067 Contains all the mesh information necessary for 00068 one iteration of the optimization algorithms over a 00069 local mesh patch. */ 00070 class PatchData 00071 { 00072 public: 00073 // Constructor/Destructor 00074 MESQUITE_EXPORT PatchData(); 00075 MESQUITE_EXPORT ~PatchData(); 00076 00077 MESQUITE_EXPORT void attach_settings( const Settings* p_settings ) 00078 { 00079 mSettings = p_settings; 00080 } 00081 MESQUITE_EXPORT const Settings* settings() const 00082 { 00083 return mSettings; 00084 } 00085 00086 /**\brief For use by testing code -- create patch explicitly 00087 * 00088 * Create a patch containing elements of the same type and 00089 * without any higher-order nodes. 00090 * 00091 *\param num_vertex Number of vertices in patch 00092 *\param vtx_coords Array of vertex coords. Length must be 3*num_vertex 00093 *\param type Element type 00094 *\param connectivity Element connectivity, specified as a list 00095 * of vertex numbers, beginning with zero. 00096 *\param vertex_fixed_flags Optional array to specify which vertices 00097 * are to be marked as fixed. If not specified, 00098 * no vertices are fixed. 00099 */ 00100 MESQUITE_EXPORT 00101 void fill( size_t num_vertex, 00102 const double* vtx_coords, 00103 size_t num_elem, 00104 EntityTopology type, 00105 const size_t* connectivity, 00106 const bool* vertex_fixed_flags, 00107 MsqError& err ); 00108 00109 /**\brief For use by testing code -- create patch explicitly 00110 * 00111 * Create a patch containing elements without any higher-order nodes. 00112 * 00113 *\param num_vertex Number of vertices in patch 00114 *\param vtx_coords Array of vertex coords. Length must be 3*num_vertex 00115 *\param elem_types The type of each element 00116 *\param connectivity Element connectivity, specified as a list 00117 * of vertex numbers, beginning with zero. 00118 *\param vertex_fixed_flags Optional array to specify which vertices 00119 * are to be marked as fixed. If NULL, 00120 * no vertices are fixed. 00121 */ 00122 MESQUITE_EXPORT 00123 void fill( size_t num_vertex, 00124 const double* vtx_coords, 00125 size_t num_elem, 00126 const EntityTopology* elem_types, 00127 const size_t* connectivity, 00128 const bool* vertex_fixed_flags, 00129 MsqError& err ); 00130 00131 /**\brief For use by testing code -- create patch explicitly 00132 * 00133 * Most general form of fill function. Works for polygons, 00134 * elements with higher-order nodes, etc. 00135 * 00136 *\param num_vertex Number of vertices in patch 00137 *\param vtx_coords Array of vertex coords. Length must be 3*num_vertex 00138 *\param elem_types The type of each element 00139 *\param vertex_per_elem The length of the connectivity list for each element. 00140 *\param connectivity Element connectivity, specified as a list 00141 * of vertex numbers, beginning with zero. 00142 *\param vertex_fixed_flags Optional array to specify which vertices 00143 * are to be marked as fixed. If NULL, 00144 * no vertices are fixed. 00145 */ 00146 MESQUITE_EXPORT 00147 void fill( size_t num_vertex, 00148 const double* vtx_coords, 00149 size_t num_elem, 00150 const EntityTopology* elem_types, 00151 const size_t* vertex_per_elem, 00152 const size_t* elem_connectivity, 00153 const bool* vertex_fixed_flags, 00154 MsqError& err ); 00155 00156 /**\brief Create global patch 00157 * 00158 * Create a global patch - mesh should be initialized first. 00159 */ 00160 MESQUITE_EXPORT 00161 void fill_global_patch( MsqError& err ); 00162 00163 MESQUITE_EXPORT 00164 void set_mesh_entities( std::vector< Mesh::ElementHandle >& patch_elems, 00165 std::vector< Mesh::VertexHandle >& free_vertices, 00166 MsqError& err ); 00167 00168 private: 00169 //! Doesn't allow PatchData to be copied implicitly. 00170 //! Mementos such as PatchDataVerticesMemento should be used when necessary. 00171 PatchData( const PatchData& pd ); 00172 //! Doesn't allow a PatchData object to be assigned to another. 00173 //! Mementos such as PatchDataVerticesMemento should be used when necessary. 00174 PatchData& operator=( const PatchData& pd ); 00175 00176 public: 00177 enum ComputedInfo 00178 { 00179 MIN_UNSIGNED_AREA = 0, //!< minimum volume or area out of all elements in the patch 00180 MAX_UNSIGNED_AREA, //!< maximum volume or area out of all elements in the patch 00181 MIN_EDGE_LENGTH, //!< minimum edge length in the patch 00182 MAX_EDGE_LENGTH, //!< maximum edge length in the patch 00183 MINMAX_SIGNED_DET2D, //!< minimum and maximum corner area out of all elements in the patch 00184 MINMAX_SIGNED_DET3D, //!< minimum and maximum corner volume out of all elements in the 00185 //!< patch 00186 AVERAGE_DET3D, //!< average corner determinant out of all elements in the patch 00187 MAX_COMPUTED_INFO_ENUM 00188 }; 00189 00190 //! This function clears the patch information such as maximum volume, etc ... 00191 MESQUITE_EXPORT 00192 void clear_computed_info() 00193 { 00194 haveComputedInfos = 0; 00195 } 00196 00197 MESQUITE_EXPORT 00198 bool have_computed_info( ComputedInfo info ) const 00199 { 00200 return 0 != ( haveComputedInfos & ( 1 << info ) ); 00201 } 00202 00203 //! Returns the maximum volume or area out of all the elements in the patch 00204 //! This information is stored in the patch and should not decrease performance 00205 //! when used properly. See also PatchData::clear_computed_info() . 00206 MESQUITE_EXPORT 00207 void get_minmax_element_unsigned_area( double& min, double& max, MsqError& err ); 00208 00209 MESQUITE_EXPORT 00210 void get_minmax_edge_length( double& min, double& max ) const; 00211 00212 //! Returns average corner determinant over all corners in the patch 00213 //! This information is stored in the patch and should not decrease performance 00214 //! when used properly. See also PatchData::clear_computed_info() . 00215 // double get_average_Lambda_3d(MsqError &err); 00216 00217 //! Removes data 00218 MESQUITE_EXPORT 00219 void clear(); 00220 //! Reorders the mesh data 00221 MESQUITE_EXPORT 00222 void reorder(); 00223 00224 //! number of vertices in the patch. 00225 MESQUITE_EXPORT size_t num_nodes() const 00226 { 00227 return vertexArray.size(); 00228 } 00229 MESQUITE_EXPORT size_t num_free_vertices() const 00230 { 00231 return numFreeVertices; 00232 } 00233 MESQUITE_EXPORT size_t num_slave_vertices() const 00234 { 00235 return numSlaveVertices; 00236 } 00237 MESQUITE_EXPORT size_t num_fixed_vertices() const 00238 { 00239 return num_nodes() - num_free_vertices() - num_slave_vertices(); 00240 } 00241 //! number of elements in the Patch. 00242 MESQUITE_EXPORT size_t num_elements() const 00243 { 00244 return elementArray.size(); 00245 } 00246 00247 MESQUITE_EXPORT bool is_vertex_free( size_t index ) const 00248 { 00249 return index < numFreeVertices; 00250 } 00251 MESQUITE_EXPORT bool is_vertex_not_free( size_t index ) const 00252 { 00253 return index >= numFreeVertices; 00254 } 00255 MESQUITE_EXPORT bool is_vertex_slave( size_t index ) const 00256 { 00257 return index >= numFreeVertices && ( index - numFreeVertices ) < numSlaveVertices; 00258 } 00259 MESQUITE_EXPORT bool is_vertex_fixed( size_t index ) const 00260 { 00261 return index >= numFreeVertices + numSlaveVertices; 00262 } 00263 00264 //! number of element corners (number of vertex uses) in patch 00265 MESQUITE_EXPORT size_t num_corners() const; 00266 00267 //! Returns a pointer to the start of the vertex array. 00268 MESQUITE_EXPORT const MsqVertex* get_vertex_array( MsqError& err ) const; 00269 // MsqVertex* get_vertex_array(MsqError &err); 00270 MESQUITE_EXPORT const MsqVertex* get_vertex_array() const 00271 { 00272 return arrptr( vertexArray ); 00273 } 00274 // MsqVertex* get_vertex_array() { return arrptr(vertexArray); } 00275 00276 //! Returns a pointer to the start of the element array. 00277 MESQUITE_EXPORT const MsqMeshEntity* get_element_array( MsqError& err ) const; 00278 MESQUITE_EXPORT MsqMeshEntity* get_element_array( MsqError& err ); 00279 00280 MESQUITE_EXPORT size_t* get_connectivity_array() 00281 { 00282 return arrptr( elemConnectivityArray ); 00283 } 00284 00285 MESQUITE_EXPORT Mesh::ElementHandle* get_element_handles_array() 00286 { 00287 return arrptr( elementHandlesArray ); 00288 } 00289 00290 MESQUITE_EXPORT Mesh::VertexHandle* get_vertex_handles_array() 00291 { 00292 return arrptr( vertexHandlesArray ); 00293 } 00294 00295 //! Returns the start of the vertex->element array. 00296 //! For each vertex in the patch, this array holds 00297 //! the number of elements the vertex is attached to, 00298 //! followed by the indices of those elements. 00299 // const size_t* get_vertex_to_elem_array(MsqError &err); 00300 //! Returns the start of the vertex->element offset 00301 //! array (v2e_o). For vertex i, v2e_o[i] is the 00302 //! index into the vertex->element array (v2e) where 00303 //! vertex i's data begins. So, v2e[v2e_o[i]] gives 00304 //! you the number of elements vertex i is attached 00305 //! to, and v2e[v2e_o[i]+1] gives you the index of 00306 //! the first element attached to vertex i. 00307 // const size_t* get_vertex_to_elem_offset(MsqError &err); 00308 00309 // MsqVertex& vertex_by_index(size_t index); 00310 MESQUITE_EXPORT const MsqVertex& vertex_by_index( size_t index ) const; 00311 MESQUITE_EXPORT MsqMeshEntity& element_by_index( size_t index ); 00312 MESQUITE_EXPORT const MsqMeshEntity& element_by_index( size_t index ) const; 00313 MESQUITE_EXPORT size_t get_vertex_index( MsqVertex* vertex ); 00314 MESQUITE_EXPORT size_t get_element_index( MsqMeshEntity* element ); 00315 00316 //! Get the coordinates of vertices attached to the specified element 00317 MESQUITE_EXPORT 00318 void get_element_vertex_coordinates( size_t elem_index, std::vector< Vector3D >& coords, MsqError& err ); 00319 /*! Get the indices of vertices of specified element. !inefficient!*/ 00320 MESQUITE_EXPORT 00321 void get_element_vertex_indices( size_t elem_index, std::vector< size_t >& vertex_indices, MsqError& err ); 00322 /*! Get the indices of the elements attached to the specified vertex. */ 00323 MESQUITE_EXPORT 00324 void get_vertex_element_indices( size_t vertex_index, std::vector< size_t >& elem_indices, MsqError& err ); 00325 00326 /** Get the indices of elements adjacent to the specified vertex, 00327 * and having the specified dimension */ 00328 MESQUITE_EXPORT 00329 void get_vertex_element_indices( size_t vertex_index, 00330 unsigned element_dimension, 00331 std::vector< size_t >& elem_indices, 00332 MsqError& err ); 00333 00334 /*! Get indices of elements attached to specified vertex */ 00335 MESQUITE_EXPORT 00336 const size_t* get_vertex_element_adjacencies( size_t vertex_index, size_t& array_len_out, MsqError& err ); 00337 00338 /*! Get the indices of vertices that are attached to vertex (given by 00339 vertex_index) by an element edge. 00340 */ 00341 MESQUITE_EXPORT 00342 void get_adjacent_vertex_indices( size_t vertex_index, std::vector< size_t >& vert_indices, MsqError& err ) const; 00343 00344 /*! \brief Get the indices of entities attached to entity 00345 (given by ent_ind). 00346 adj_ents is filled with the indices into the entity array of elements 00347 adjacent to the given element via an n-dimensional entity. 00348 00349 */ 00350 MESQUITE_EXPORT 00351 void get_adjacent_entities_via_n_dim( int n, size_t ent_ind, std::vector< size_t >& adj_ents, MsqError& err ); 00352 00353 /*! Create the arrays that store which elements are attached 00354 to each node. If you know how many total vertex uses there are, 00355 pass it in. Otherwise the PatchData will calculate that number. 00356 */ 00357 MESQUITE_EXPORT 00358 void generate_vertex_to_element_data(); 00359 00360 /*! 00361 */ 00362 MESQUITE_EXPORT 00363 void set_vertex_coordinates( const Vector3D& coords, size_t index, MsqError& err ); 00364 /*! Add delta to the index-th free vertex in the patch 00365 */ 00366 MESQUITE_EXPORT 00367 void move_vertex( const Vector3D& delta, size_t index, MsqError& err ); 00368 00369 /*! Adjust the position of the specified vertex so that it 00370 lies on its constraining domain. The actual domain constraint 00371 is managed by the MeshSet's MeshDomain object. 00372 */ 00373 MESQUITE_EXPORT 00374 void snap_vertex_to_domain( size_t vertex_index, MsqError& err ); 00375 00376 /*! Returns whether a domain is associated with the MeshSet from which 00377 the Patch originates. 00378 If false, you cannot ask for a surface normal. */ 00379 MESQUITE_EXPORT 00380 bool domain_set() const 00381 { 00382 return 0 != myDomain; 00383 } 00384 00385 /*\brief Get domain normal at vertex location 00386 * 00387 * Get the normal of the domain associated with the passed 00388 * element handle at the location of the specified vertex. 00389 *\param vert_index The index of the vertex in this PatchData 00390 *\param elem_handle The handle of the element passed to the domain 00391 *\param normal_out The resulting domain normal 00392 *\param err Error flag. Possible error conditions include: 00393 * invalid input data, no domain associated with 00394 * element, no domain at all, etc. 00395 */ 00396 MESQUITE_EXPORT 00397 void get_domain_normal_at_vertex( size_t vert_index, 00398 Mesh::ElementHandle element, 00399 Vector3D& normal_out, 00400 MsqError& err ); 00401 00402 /*! Get the normal to the domain at the centroid (projected to the 00403 domain) of a given element. 00404 Normal is returned in Vector3D &surf_norm. If the normal cannot 00405 be determined, or if the underlying domain is not a surface, 00406 the normal will be set to (0,0,0). 00407 Check PatchData::domain_set() is not false first. 00408 */ 00409 MESQUITE_EXPORT 00410 void get_domain_normal_at_element( size_t elem_index, Vector3D& surf_norm, MsqError& err ); 00411 00412 /** Get surface normals at element corners. 00413 * normals_out must be of sufficient size to hold 00414 * the normals of all the corners. 00415 **/ 00416 MESQUITE_EXPORT 00417 void get_domain_normals_at_corners( size_t element_index, Vector3D normals_out[], MsqError& err ); 00418 00419 MESQUITE_EXPORT 00420 void get_domain_normal_at_corner( size_t elemen_index, unsigned corner, Vector3D& normal, MsqError& err ); 00421 00422 MESQUITE_EXPORT 00423 void get_domain_normal_at_mid_edge( size_t element_index, unsigned edge_number, Vector3D& normal, MsqError& err ); 00424 00425 //! Alternative signature. Same functionality. 00426 MESQUITE_EXPORT 00427 void get_domain_normal_at_element( const MsqMeshEntity* elem_ptr, Vector3D& surf_norm, MsqError& err ) 00428 { 00429 get_domain_normal_at_element( size_t( elem_ptr - &( elementArray[0] ) ), surf_norm, err ); 00430 } 00431 00432 MESQUITE_EXPORT 00433 void get_domain_normal_at_sample( size_t element_index, Sample location, Vector3D& surf_norm, MsqError& err ) 00434 { 00435 switch( location.dimension ) 00436 { 00437 case 0: 00438 get_domain_normal_at_corner( element_index, location.number, surf_norm, err ); 00439 break; 00440 case 1: 00441 get_domain_normal_at_mid_edge( element_index, location.number, surf_norm, err ); 00442 break; 00443 case 2: 00444 assert( location.number == 0 ); 00445 get_domain_normal_at_element( element_index, surf_norm, err ); 00446 break; 00447 default: 00448 MSQ_SETERR( err ) 00449 ( "Invalid dimension for surface element subentity.\n", MsqError::INVALID_ARG ); 00450 } 00451 } 00452 00453 //! Moves free vertices and then snaps the free vertices to the domain. 00454 /*\param dk an array of directions, ordered like the vertices in 00455 the PatchData. 00456 \param nb_vtx number of vertices. 00457 \param step_size a scalar that multiplies the vectors given in dk. 00458 */ 00459 MESQUITE_EXPORT 00460 void move_free_vertices_constrained( Vector3D dk[], size_t nb_vtx, double step_size, MsqError& err ); 00461 00462 /*! Moves free vertices from a memento position along a certain direction 00463 and then snaps the free vertices to the domain. 00464 \param dk an array of directions, ordered like the vertices in 00465 the PatchData. 00466 \param nb_vtx number of vertices. 00467 \param step_size a scalar that multiplies the vectors given in dk. 00468 */ 00469 MESQUITE_EXPORT 00470 void set_free_vertices_constrained( PatchDataVerticesMemento* memento, 00471 Vector3D dk[], 00472 size_t nb_vtx, 00473 double step_size, 00474 MsqError& err ); 00475 00476 //! Project gradient vector terms onto geometric domain 00477 MESQUITE_EXPORT 00478 void project_gradient( std::vector< Vector3D >& gradient, MsqError& err ); 00479 00480 //! Calculates the distance each vertex has moved from its original 00481 //! position as defined by the PatchDataVerticesMememnto. 00482 MESQUITE_EXPORT 00483 double get_max_vertex_movement_squared( PatchDataVerticesMemento* memento, MsqError& err ); 00484 00485 //! Updates the underlying mesh (the MBMesquite::Mesh implementation) with 00486 //! new node coordinates and flag values. 00487 //!\param tag If non-null, store vertex coords in tag rather than 00488 //! updating the coords in the mesh database. Used for 00489 //! Jacobi optimizations. 00490 MESQUITE_EXPORT 00491 void update_mesh( MsqError& err, const TagHandle* tag = 0 ); 00492 00493 //! Calculate new location for all slave higher-order nodes using 00494 //! mapping function. Called by update_mesh(). 00495 MESQUITE_EXPORT 00496 void update_slave_node_coordinates( MsqError& err ); 00497 MESQUITE_EXPORT 00498 void update_slave_node_coordinates( const size_t* elem_indices, size_t num_elem, MsqError& err ); 00499 00500 //! Remove the soft_fixed flag from all vertices in the patch. 00501 MESQUITE_EXPORT 00502 void set_all_vertices_soft_free( MsqError& err ); 00503 //! Add a soft_fixed flag to all vertices in the patch. 00504 MESQUITE_EXPORT 00505 void set_all_vertices_soft_fixed( MsqError& err ); 00506 //! Add a soft_fixed flag to all free vertices in the patch. 00507 MESQUITE_EXPORT 00508 void set_free_vertices_soft_fixed( MsqError& err ); 00509 00510 //! Mark vertex as culled (soft fixed) 00511 MESQUITE_EXPORT 00512 void set_vertex_culled( size_t vtx_index ) 00513 { 00514 vertexArray[vtx_index].flags() |= MsqVertex::MSQ_CULLED; 00515 } 00516 //! Mark vertex as culled (soft fixed) 00517 MESQUITE_EXPORT 00518 void clear_vertex_culled( size_t vtx_index ) 00519 { 00520 vertexArray[vtx_index].flags() &= ~MsqVertex::MSQ_CULLED; 00521 } 00522 //! check if vertex is culled 00523 MESQUITE_EXPORT 00524 int check_vertex_culled( size_t vtx_index ) const 00525 { 00526 return vertexArray[vtx_index].get_flags() | MsqVertex::MSQ_CULLED; 00527 } 00528 00529 //! Fills a PatchData with the elements attached to a center vertex. 00530 //! Note that all entities in the sub-patch are copies of the entities 00531 //! in 'this' patch. As such, moving a vertex in the sub-patch 00532 //! won't move the corresponding vertex in the source patch. Also, 00533 //! calling 'update_mesh()' on the sub-patch WILL modify the TSTT 00534 //! mesh, but the source patch won't see the changes. 00535 MESQUITE_EXPORT 00536 void get_subpatch( size_t center_vertex_index, unsigned num_adj_elem_layers, PatchData& pd_to_fill, MsqError& err ); 00537 00538 MESQUITE_EXPORT 00539 void get_free_vertex_coordinates( std::vector< Vector3D >& coords_out ) const; 00540 00541 //! Creates a memento that holds the current 00542 //! state of the PatchData coordinates. 00543 MESQUITE_EXPORT 00544 PatchDataVerticesMemento* create_vertices_memento( MsqError& err ); 00545 00546 //! reinstantiates a memento to holds the current 00547 //! state of the PatchData coordinates. Improves memory management. 00548 MESQUITE_EXPORT 00549 void recreate_vertices_memento( PatchDataVerticesMemento* memento, MsqError& err ); 00550 00551 //! Restore the PatchData coordinates to the state 00552 //! contained in the memento. 00553 MESQUITE_EXPORT 00554 void set_to_vertices_memento( PatchDataVerticesMemento* memento, MsqError& err ); 00555 00556 //! Sets the originating meshSet. This is normally done in MeshSet::get_next_patch(). 00557 //! This function is only for tests purposes. 00558 MESQUITE_EXPORT 00559 void set_mesh( Mesh* ms ); 00560 00561 //! Returns the originating meshSet. 00562 MESQUITE_EXPORT 00563 Mesh* get_mesh() const 00564 { 00565 return myMesh; 00566 } 00567 00568 MESQUITE_EXPORT 00569 void set_domain( MeshDomain* dm ); 00570 00571 MESQUITE_EXPORT 00572 MeshDomain* get_domain() const 00573 { 00574 return myDomain; 00575 } 00576 00577 MESQUITE_EXPORT 00578 const Settings* get_settings() const 00579 { 00580 return mSettings; 00581 } 00582 MESQUITE_EXPORT 00583 const MappingFunction* get_mapping_function( EntityTopology type ) const 00584 { 00585 return mSettings->get_mapping_function( type ); 00586 } 00587 MESQUITE_EXPORT 00588 const MappingFunction2D* get_mapping_function_2D( EntityTopology type ) const 00589 { 00590 return mSettings->get_mapping_function_2D( type ); 00591 } 00592 MESQUITE_EXPORT 00593 const MappingFunction3D* get_mapping_function_3D( EntityTopology type ) const 00594 { 00595 return mSettings->get_mapping_function_3D( type ); 00596 } 00597 00598 //! Get R^3 coordinates for logical sample location. 00599 MESQUITE_EXPORT 00600 void get_sample_location( size_t element_index, Sample sample, Vector3D& result, MsqError& err ) const; 00601 00602 //! This function returns a NodeSet indicating which 00603 //! nodes in the specified element are not slaved. 00604 MESQUITE_EXPORT 00605 NodeSet non_slave_node_set( size_t elem_idx ) const; 00606 00607 MESQUITE_EXPORT 00608 NodeSet get_samples( size_t element, NodeSet non_slave_nodes ) const 00609 { 00610 // If we have a mapping function, use it 00611 const EntityTopology type = element_by_index( element ).get_element_type(); 00612 const MappingFunction* f; 00613 if( mSettings && ( f = mSettings->get_mapping_function( type ) ) ) return f->sample_points( non_slave_nodes ); 00614 // Otherwise default to sampling at all non-slave nodes 00615 non_slave_nodes.set_all_corner_nodes( type ); 00616 return non_slave_nodes; 00617 } 00618 00619 MESQUITE_EXPORT 00620 NodeSet get_samples( size_t element ) const 00621 { 00622 return get_samples( element, non_slave_node_set( element ) ); 00623 } 00624 00625 MESQUITE_EXPORT 00626 void get_samples( size_t element, std::vector< Sample >& samples_out, MsqError& err ) const; 00627 00628 //! Display the coordinates and connectivity information 00629 friend std::ostream& operator<<( std::ostream&, const PatchData& ); 00630 00631 private: 00632 /* allow access to the following to functions */ 00633 friend class MBMesquite::ExtraData; 00634 /**\brief Attach an ExtraData object to this PatchData */ 00635 bool attach_extra_data( ExtraData* data ); 00636 /**\brief Remove an ExtraData object from this PatchData */ 00637 bool remove_extra_data( ExtraData* data ); 00638 00639 /**\brief notify all attached ExtraData instances that patch contents have changed */ 00640 void notify_new_patch(); 00641 /**\brief notify all attached ExtraData instances that a subpatch is being initalized 00642 *\param sub_patch The new, already populated subpatch 00643 *\param vertex_index_map For the i-th vertex in the subpatch, the 00644 * i-th entry in this list is the corresponding index in 00645 * this patch. 00646 *\param element_index_map For the i-th element in the subpatch, the 00647 * i-th entry in this list is the corresponding index in 00648 * this patch. 00649 */ 00650 void notify_sub_patch( PatchData& sub_patch, 00651 const size_t* vertex_index_map, 00652 const size_t* element_index_map, 00653 MsqError& err ); 00654 /**\brief notify all attached ExtraData instances that this patch is being destroyed */ 00655 void notify_patch_destroyed(); 00656 00657 /** Call before initialize_data to change vertex_flags for 00658 * higher-order nodes to MSQ_DEPENDENT. 00659 */ 00660 void enslave_higher_order_nodes( const size_t* element_offset_array, 00661 unsigned char* vertex_flags, 00662 MsqError& err ) const; 00663 00664 /** Call after filling vertex handle and connectivity arrays to 00665 * finish initializing the PatchData. Reorders vertex handles array 00666 * such that all higher-order nodes are at end of array, updates 00667 * element connectivity array appropriately, initalizes numCornerVertices, 00668 * and per-element vertex and node counts. 00669 * 00670 * NOTE: If the patch contains higher-order elements, this function 00671 * will re-order the nodes in the vertex array. Do *NOT* assume 00672 * vertex indices are the same after calling this function! 00673 * 00674 * NOTE: This function expects the following data to be initalized: 00675 * vertexHandlesArray 00676 * elemConnectivityArray 00677 * the topology type for all elements in elementArray 00678 * The function assumes the following data has not been 00679 * initialized and therefore does not need to be updated: 00680 * vertexArray 00681 * 00682 * \param elem_offset_array Offset into connectivity array for each element 00683 */ 00684 void initialize_data( size_t* elem_offset_array, unsigned char* vertex_flags, MsqError& err ); 00685 00686 /** Code common to misc. methods for populating patch data. 00687 * Remove duplicates from an array of handles. 00688 *\param handles The array of handles to uniquify. 00689 *\param count As input, the lenght of the #handles 00690 * array. As output, the number of unique 00691 * handles remaining in the array. 00692 *\param index_map If non-null, this must be an array of the 00693 * same length as the handles array. If this 00694 * array is passed, the entry cooresponding 00695 * to each handle in the input #handles array will 00696 * be set to the index of that handle in the output 00697 * array. 00698 */ 00699 static void make_handles_unique( Mesh::EntityHandle* handles, size_t& count, size_t* index_map = 0 ); 00700 00701 /*\brief Note that the passed info has been calculated and stored */ 00702 void note_have_info( ComputedInfo info ) 00703 { 00704 haveComputedInfos |= ( 1 << info ); 00705 } 00706 00707 /*\brief Update cached domain normal data */ 00708 void update_cached_normals( MsqError& ); 00709 00710 Mesh* myMesh; //!< The Mesh used to fill this PatchData [may be NULL] 00711 MeshDomain* myDomain; //!< The geometric domain of the mesh [may be NULL] 00712 00713 //! Cached data for vertices in PatchData::vertexHandlesArray, 00714 //! or vertex data for a temporary patch. 00715 std::vector< MsqVertex > vertexArray; 00716 //! The list of handles for the vertices in this patch 00717 //! May be empty if PatchData::myMesh is NULL 00718 std::vector< Mesh::VertexHandle > vertexHandlesArray; 00719 //! The number of vertices in PatchData::vertexArray that are 00720 //! free vertices. The vertex array is sorted such that 00721 //! free vertices are first in the array. This value 00722 //! is therefore the offset at which slave vertices begin 00723 //! in the array. 00724 size_t numFreeVertices; 00725 //! The number of slave vertices in vertexArray. The 00726 //! vertices are ordered such that all fixed vertices occur 00727 //! after the slave vertices. Therefore the offset at which 00728 //! the fixed vertices begin is numFreeVertices+numSlaveVertices 00729 size_t numSlaveVertices; 00730 //! Cached data for elements in PatchData::elementHandlesArray 00731 //! or element data for a temporary patch. 00732 std::vector< MsqMeshEntity > elementArray; 00733 //! The hist of handles for elements in this patch. 00734 //! May be empty if PatchData::myMesh is NULL 00735 std::vector< Mesh::ElementHandle > elementHandlesArray; 00736 //! Element connectivity data. The concatenation of the 00737 //! connectivity list of each element in PatchData::elementArray. 00738 //! Each element in PatchData::elementArray has a pointer into 00739 //! this array at the correct offset for that element's connectivity data. 00740 std::vector< size_t > elemConnectivityArray; 00741 //! The concatenation of the adjacency lists of all the vertices 00742 //! in PatchData::vertexArray. Each value in the array is an index into 00743 //! PatchData::elementArray indicating that the corresponding element uses 00744 //! the vertex. May be empty if vertex adjacency data has not been 00745 //! requested. 00746 std::vector< size_t > vertAdjacencyArray; 00747 //! This array is indexed by vertex indices and specifies the 00748 //! offset in \vertAdjacencyArray at which the adjacency list 00749 //! for the corresponding vertex begins. May be empty if vertex 00750 //! adjacency data has not been requested. 00751 std::vector< size_t > vertAdjacencyOffsets; 00752 //! Index into normalData at which the normal for the corresponding 00753 //! vertex index is located. Only vertices constrained to a single 00754 //! domain with a topological dimension of 2 have a unique domain 00755 //! normal. 00756 std::vector< unsigned > vertexNormalIndices; 00757 //! Storage space for cached domain normal data. Pointers in 00758 //! PatchData::vertexNormalPointers point into this list. 00759 std::vector< Vector3D > normalData; 00760 //! Storage space for cached domain DOF for vertices. IF 00761 //! a domain exists and PatchData::normalData is not empty, but 00762 //! this array is, it may be assumed that all vertices have 00763 //! have a DOF == 2. 00764 std::vector< unsigned short > vertexDomainDOF; 00765 00766 // Arrays in which to store temporary data 00767 // (avoids reallocation of temp space) 00768 std::vector< size_t > offsetArray; 00769 std::vector< unsigned char > byteArray; 00770 mutable std::vector< bool > bitMap; 00771 00772 // Patch Computed Information (maxs, mins, etc ... ) 00773 double computedInfos[MAX_COMPUTED_INFO_ENUM]; 00774 // Bit map indicating which values in PatchData::computedInfos 00775 // are valud (which values have been calculated.) 00776 unsigned haveComputedInfos; 00777 00778 ExtraData* dataList; 00779 00780 const Settings* mSettings; 00781 static const Settings defaultSettings; 00782 }; 00783 00784 void print_patch_data( const PatchData& pd ); 00785 00786 /*! \brief Contains a copy of the coordinates of a PatchData. 00787 00788 Use PatchDataVerticesMemento when you want to change the coordinates 00789 of a PatchData object but also have the option to restore them. 00790 This class can only be instantiated through PatchData::create_vertices_memento(). 00791 */ 00792 class PatchDataVerticesMemento 00793 { 00794 public: 00795 void clear() 00796 { 00797 originator = 0; 00798 vertices.clear(); 00799 normalData.clear(); 00800 } 00801 00802 private: 00803 // Constructor accessible only to originator (i.e. PatchData) 00804 friend class PatchData; 00805 PatchDataVerticesMemento() : originator( 0 ) {} 00806 00807 PatchData* originator; //!< PatchData whose state is kept 00808 std::vector< MsqVertex > vertices; 00809 std::vector< Vector3D > normalData; 00810 }; 00811 00812 inline void PatchData::clear() 00813 { 00814 vertexArray.clear(); 00815 vertexHandlesArray.clear(); 00816 elementArray.clear(); 00817 elementHandlesArray.clear(); 00818 elemConnectivityArray.clear(); 00819 vertAdjacencyArray.clear(); 00820 vertAdjacencyOffsets.clear(); 00821 vertexNormalIndices.clear(); 00822 normalData.clear(); 00823 // vertexDomainDOF.clear(); 00824 numFreeVertices = 0; 00825 numSlaveVertices = 0; 00826 haveComputedInfos = 0; 00827 myMesh = 0; 00828 myDomain = 0; 00829 } 00830 00831 /*! \brief Returns an array of all vertices in the PatchData. 00832 */ 00833 inline const MsqVertex* PatchData::get_vertex_array( MsqError& err ) const 00834 { 00835 if( vertexArray.empty() ) MSQ_SETERR( err )( "No vertex array defined", MsqError::INVALID_STATE ); 00836 return arrptr( vertexArray ); 00837 } 00838 00839 /*! \brief Returns the PatchData element array. 00840 */ 00841 inline const MsqMeshEntity* PatchData::get_element_array( MsqError& err ) const 00842 { 00843 if( elementArray.empty() ) MSQ_SETERR( err )( "No element array defined", MsqError::INVALID_STATE ); 00844 return arrptr( elementArray ); 00845 } 00846 inline MsqMeshEntity* PatchData::get_element_array( MsqError& err ) 00847 { 00848 if( elementArray.empty() ) MSQ_SETERR( err )( "No element array defined", MsqError::INVALID_STATE ); 00849 return arrptr( elementArray ); 00850 } 00851 00852 /*! \brief set the coordinates of the index-th vertex in the raw array 00853 */ 00854 inline void PatchData::set_vertex_coordinates( const Vector3D& coords, size_t index, MsqError& err ) 00855 { 00856 if( index >= vertexArray.size() ) 00857 { 00858 MSQ_SETERR( err )( "Index bigger than numVertices.", MsqError::INVALID_ARG ); 00859 return; 00860 } 00861 00862 vertexArray[index] = coords; 00863 00864 if( numSlaveVertices ) 00865 { 00866 size_t num_elem; 00867 const size_t* indices; 00868 indices = get_vertex_element_adjacencies( index, num_elem, err );MSQ_ERRRTN( err ); 00869 update_slave_node_coordinates( indices, num_elem, err );MSQ_ERRRTN( err ); 00870 } 00871 } 00872 /*! \brief increment the coordinates of the index-th vertex in the raw array 00873 */ 00874 inline void PatchData::move_vertex( const Vector3D& delta, size_t index, MsqError& err ) 00875 { 00876 if( index >= vertexArray.size() ) 00877 { 00878 MSQ_SETERR( err )( "Index bigger than numVertices.", MsqError::INVALID_ARG ); 00879 return; 00880 } 00881 00882 vertexArray[index] += delta; 00883 00884 if( numSlaveVertices ) 00885 { 00886 size_t num_elem; 00887 const size_t* indices; 00888 indices = get_vertex_element_adjacencies( index, num_elem, err );MSQ_ERRRTN( err ); 00889 update_slave_node_coordinates( indices, num_elem, err );MSQ_ERRRTN( err ); 00890 } 00891 } 00892 00893 // inline MsqVertex& PatchData::vertex_by_index(size_t index) 00894 //{ 00895 // return vertexArray[index]; 00896 //} 00897 00898 inline const MsqVertex& PatchData::vertex_by_index( size_t index ) const 00899 { 00900 assert( index < vertexArray.size() ); 00901 return vertexArray[index]; 00902 } 00903 00904 inline MsqMeshEntity& PatchData::element_by_index( size_t index ) 00905 { 00906 assert( index < elementArray.size() ); 00907 return elementArray[index]; 00908 } 00909 00910 inline const MsqMeshEntity& PatchData::element_by_index( size_t index ) const 00911 { 00912 assert( index < elementArray.size() ); 00913 return elementArray[index]; 00914 } 00915 00916 /*! gets the index of a vertex in the PatchData vertex array, 00917 given a pointer to the vertex. */ 00918 inline size_t PatchData::get_vertex_index( MsqVertex* vertex ) 00919 { 00920 return vertex - arrptr( vertexArray ); 00921 } 00922 00923 inline size_t PatchData::get_element_index( MsqMeshEntity* element ) 00924 { 00925 return element - arrptr( elementArray ); 00926 } 00927 00928 inline void PatchData::get_free_vertex_coordinates( std::vector< Vector3D >& coords_out ) const 00929 { 00930 coords_out.resize( num_free_vertices() ); 00931 std::copy( vertexArray.begin(), vertexArray.begin() + num_free_vertices(), coords_out.begin() ); 00932 } 00933 00934 /*! 00935 This function instantiate PatchDataVerticesMemento object and returns a pointer to it. 00936 The PatchDataVerticesMemento contains the current state of the PatchData coordinates. 00937 It can be used to restore the same PatchData object to those coordinates. 00938 00939 It is the responsibility of the caller to discard the PatchDataVerticesMemento 00940 when not needed any more. 00941 */ 00942 inline PatchDataVerticesMemento* PatchData::create_vertices_memento( MsqError& err ) 00943 { 00944 PatchDataVerticesMemento* memento = new PatchDataVerticesMemento; 00945 recreate_vertices_memento( memento, err ); 00946 if( MSQ_CHKERR( err ) ) 00947 { 00948 delete memento; 00949 return 0; 00950 } 00951 return memento; 00952 } 00953 00954 /*! 00955 This function reuses an existing PatchDataVerticesMemento object. 00956 The PatchDataVerticesMemento contains the current state of the PatchData coordinates. 00957 It can be used to restore the same PatchData object to those coordinates. 00958 00959 It is the responsibility of the caller to delete the PatchDataVerticesMemento 00960 when it is no longer needed. 00961 */ 00962 inline void PatchData::recreate_vertices_memento( PatchDataVerticesMemento* memento, MsqError& /*err*/ ) 00963 { 00964 memento->originator = this; 00965 00966 size_t num_vtx = num_free_vertices() + num_slave_vertices(); 00967 00968 memento->vertices.resize( num_vtx ); 00969 std::copy( vertexArray.begin(), vertexArray.begin() + num_vtx, memento->vertices.begin() ); 00970 00971 int num_normal; 00972 if( normalData.empty() ) 00973 num_normal = 0; 00974 else if( vertexNormalIndices.empty() ) 00975 num_normal = num_vtx; 00976 else 00977 { 00978 num_normal = num_vtx; 00979 while( num_normal != 0 && vertexNormalIndices[--num_normal] >= normalData.size() ) 00980 ; 00981 if( num_normal == 0 ) 00982 { 00983 if( vertexNormalIndices[0] < normalData.size() ) num_normal = vertexNormalIndices[0] + 1; 00984 } 00985 else 00986 num_normal = vertexNormalIndices[num_normal] + 1; 00987 } 00988 00989 memento->normalData.resize( num_normal ); 00990 std::copy( normalData.begin(), normalData.begin() + num_normal, memento->normalData.begin() ); 00991 } 00992 00993 /*! 00994 This function restores a PatchData object coordinates to a previous state hold in 00995 a PatchDataVerticesMemento object (see create_vertices_memento() ). 00996 00997 The function checks whether the memento originates from this particular PatchData object. 00998 The function does not destroy the memento object: this is the caller responsibility. 00999 */ 01000 inline void PatchData::set_to_vertices_memento( PatchDataVerticesMemento* memento, MsqError& err ) 01001 { 01002 if( memento->originator != this ) 01003 { 01004 MSQ_SETERR( err ) 01005 ( "Memento may only be used to restore the PatchData " 01006 "object from which it was created.", 01007 MsqError::INVALID_ARG ); 01008 return; 01009 } 01010 01011 if( memento->vertices.size() != num_free_vertices() + num_slave_vertices() ) 01012 { 01013 MSQ_SETERR( err ) 01014 ( "Unable to restore patch coordinates. Number of " 01015 "vertices in PatchData has changed.", 01016 MsqError::INVALID_STATE ); 01017 return; 01018 } 01019 01020 // copies the memento array into the PatchData array. 01021 std::copy( memento->vertices.begin(), memento->vertices.end(), vertexArray.begin() ); 01022 std::copy( memento->normalData.begin(), memento->normalData.end(), normalData.begin() ); 01023 } 01024 01025 } // namespace MBMesquite 01026 01027 #endif