MOAB: Mesh Oriented datABase  (version 5.2.1)
PatchData.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines