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