MOAB: Mesh Oriented datABase  (version 5.4.0)
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,
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines