Branch data Line data Source code
1 : : /* *****************************************************************
2 : : MESQUITE -- The Mesh Quality Improvement Toolkit
3 : :
4 : : Copyright 2004 Sandia Corporation and Argonne National
5 : : Laboratory. Under the terms of Contract DE-AC04-94AL85000
6 : : with Sandia Corporation, the U.S. Government retains certain
7 : : rights in this software.
8 : :
9 : : This library is free software; you can redistribute it and/or
10 : : modify it under the terms of the GNU Lesser General Public
11 : : License as published by the Free Software Foundation; either
12 : : version 2.1 of the License, or (at your option) any later version.
13 : :
14 : : This library is distributed in the hope that it will be useful,
15 : : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : : Lesser General Public License for more details.
18 : :
19 : : You should have received a copy of the GNU Lesser General Public License
20 : : (lgpl.txt) along with this library; if not, write to the Free Software
21 : : Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 : :
23 : : [email protected], [email protected], [email protected],
24 : : [email protected], [email protected], [email protected]
25 : :
26 : : ***************************************************************** */
27 : : #ifndef MESQUITE_PATCHDATA_HPP
28 : : #define MESQUITE_PATCHDATA_HPP
29 : : /*!
30 : : \file PatchData.hpp
31 : : \brief This file contains the PatchData class and its associated mementos.
32 : :
33 : :
34 : : The PatchData class provides the mesh information and functionality to Mesquite.
35 : : The PatchDataVerticesMemento class allows the state of a PatchData object to be saved
36 : : in order to later restore that object to its previous state.
37 : :
38 : : \author Thomas Leurent
39 : : \author Michael Brewer
40 : : \date 2002-01-17
41 : : */
42 : :
43 : : #include "Mesquite.hpp"
44 : : #include "MsqVertex.hpp"
45 : : #include "MsqMeshEntity.hpp"
46 : : #include "MsqVertex.hpp"
47 : : #include "MeshInterface.hpp"
48 : : #include "MsqError.hpp"
49 : : #include "Settings.hpp"
50 : : #include "NodeSet.hpp"
51 : : #include "MappingFunction.hpp"
52 : :
53 : : #include <cstddef>
54 : : #include <cstdlib>
55 : : #include <map>
56 : : #include <vector>
57 : : #include <iosfwd>
58 : :
59 : : namespace MBMesquite
60 : : {
61 : : class ExtraData;
62 : : class PatchDataVerticesMemento;
63 : : class Mesh;
64 : : class Settings;
65 : :
66 : : /*!
67 : : Contains all the mesh information necessary for
68 : : one iteration of the optimization algorithms over a
69 : : local mesh patch. */
70 : : class PatchData
71 : : {
72 : : public:
73 : : // Constructor/Destructor
74 : : MESQUITE_EXPORT PatchData();
75 : : MESQUITE_EXPORT ~PatchData();
76 : :
77 : 1239 : MESQUITE_EXPORT void attach_settings( const Settings* p_settings )
78 : : {
79 : 1239 : mSettings = p_settings;
80 : 1239 : }
81 : : MESQUITE_EXPORT const Settings* settings() const
82 : : {
83 : : return mSettings;
84 : : }
85 : :
86 : : /**\brief For use by testing code -- create patch explicitly
87 : : *
88 : : * Create a patch containing elements of the same type and
89 : : * without any higher-order nodes.
90 : : *
91 : : *\param num_vertex Number of vertices in patch
92 : : *\param vtx_coords Array of vertex coords. Length must be 3*num_vertex
93 : : *\param type Element type
94 : : *\param connectivity Element connectivity, specified as a list
95 : : * of vertex numbers, beginning with zero.
96 : : *\param vertex_fixed_flags Optional array to specify which vertices
97 : : * are to be marked as fixed. If not specified,
98 : : * no vertices are fixed.
99 : : */
100 : : MESQUITE_EXPORT
101 : : void fill( size_t num_vertex, const double* vtx_coords, size_t num_elem, EntityTopology type,
102 : : const size_t* connectivity, const bool* vertex_fixed_flags, MsqError& err );
103 : :
104 : : /**\brief For use by testing code -- create patch explicitly
105 : : *
106 : : * Create a patch containing elements without any higher-order nodes.
107 : : *
108 : : *\param num_vertex Number of vertices in patch
109 : : *\param vtx_coords Array of vertex coords. Length must be 3*num_vertex
110 : : *\param elem_types The type of each element
111 : : *\param connectivity Element connectivity, specified as a list
112 : : * of vertex numbers, beginning with zero.
113 : : *\param vertex_fixed_flags Optional array to specify which vertices
114 : : * are to be marked as fixed. If NULL,
115 : : * no vertices are fixed.
116 : : */
117 : : MESQUITE_EXPORT
118 : : void fill( size_t num_vertex, const double* vtx_coords, size_t num_elem, const EntityTopology* elem_types,
119 : : const size_t* connectivity, const bool* vertex_fixed_flags, MsqError& err );
120 : :
121 : : /**\brief For use by testing code -- create patch explicitly
122 : : *
123 : : * Most general form of fill function. Works for polygons,
124 : : * elements with higher-order nodes, etc.
125 : : *
126 : : *\param num_vertex Number of vertices in patch
127 : : *\param vtx_coords Array of vertex coords. Length must be 3*num_vertex
128 : : *\param elem_types The type of each element
129 : : *\param vertex_per_elem The length of the connectivity list for each element.
130 : : *\param connectivity Element connectivity, specified as a list
131 : : * of vertex numbers, beginning with zero.
132 : : *\param vertex_fixed_flags Optional array to specify which vertices
133 : : * are to be marked as fixed. If NULL,
134 : : * no vertices are fixed.
135 : : */
136 : : MESQUITE_EXPORT
137 : : void fill( size_t num_vertex, const double* vtx_coords, size_t num_elem, const EntityTopology* elem_types,
138 : : const size_t* vertex_per_elem, const size_t* elem_connectivity, const bool* vertex_fixed_flags,
139 : : MsqError& err );
140 : :
141 : : /**\brief Create global patch
142 : : *
143 : : * Create a global patch - mesh should be initialized first.
144 : : */
145 : : MESQUITE_EXPORT
146 : : void fill_global_patch( MsqError& err );
147 : :
148 : : MESQUITE_EXPORT
149 : : void set_mesh_entities( std::vector< Mesh::ElementHandle >& patch_elems,
150 : : std::vector< Mesh::VertexHandle >& free_vertices, MsqError& err );
151 : :
152 : : private:
153 : : //! Doesn't allow PatchData to be copied implicitly.
154 : : //! Mementos such as PatchDataVerticesMemento should be used when necessary.
155 : : PatchData( const PatchData& pd );
156 : : //! Doesn't allow a PatchData object to be assigned to another.
157 : : //! Mementos such as PatchDataVerticesMemento should be used when necessary.
158 : : PatchData& operator=( const PatchData& pd );
159 : :
160 : : public:
161 : : enum ComputedInfo
162 : : {
163 : : MIN_UNSIGNED_AREA = 0, //!< minimum volume or area out of all elements in the patch
164 : : MAX_UNSIGNED_AREA, //!< maximum volume or area out of all elements in the patch
165 : : MIN_EDGE_LENGTH, //!< minimum edge length in the patch
166 : : MAX_EDGE_LENGTH, //!< maximum edge length in the patch
167 : : MINMAX_SIGNED_DET2D, //!< minimum and maximum corner area out of all elements in the patch
168 : : MINMAX_SIGNED_DET3D, //!< minimum and maximum corner volume out of all elements in the
169 : : //!< patch
170 : : AVERAGE_DET3D, //!< average corner determinant out of all elements in the patch
171 : : MAX_COMPUTED_INFO_ENUM
172 : : };
173 : :
174 : : //! This function clears the patch information such as maximum volume, etc ...
175 : : MESQUITE_EXPORT
176 : : void clear_computed_info()
177 : : {
178 : : haveComputedInfos = 0;
179 : : }
180 : :
181 : : MESQUITE_EXPORT
182 : 0 : bool have_computed_info( ComputedInfo info ) const
183 : : {
184 : 0 : return 0 != ( haveComputedInfos & ( 1 << info ) );
185 : : }
186 : :
187 : : //! Returns the maximum volume or area out of all the elements in the patch
188 : : //! This information is stored in the patch and should not decrease performance
189 : : //! when used properly. See also PatchData::clear_computed_info() .
190 : : MESQUITE_EXPORT
191 : : void get_minmax_element_unsigned_area( double& min, double& max, MsqError& err );
192 : :
193 : : MESQUITE_EXPORT
194 : : void get_minmax_edge_length( double& min, double& max ) const;
195 : :
196 : : //! Returns average corner determinant over all corners in the patch
197 : : //! This information is stored in the patch and should not decrease performance
198 : : //! when used properly. See also PatchData::clear_computed_info() .
199 : : // double get_average_Lambda_3d(MsqError &err);
200 : :
201 : : //! Removes data
202 : : MESQUITE_EXPORT
203 : : void clear();
204 : : //! Reorders the mesh data
205 : : MESQUITE_EXPORT
206 : : void reorder();
207 : :
208 : : //! number of vertices in the patch.
209 : 9838453 : MESQUITE_EXPORT size_t num_nodes() const
210 : : {
211 : 9838453 : return vertexArray.size();
212 : : }
213 : 95744212 : MESQUITE_EXPORT size_t num_free_vertices() const
214 : : {
215 : 95744212 : return numFreeVertices;
216 : : }
217 : 1289796 : MESQUITE_EXPORT size_t num_slave_vertices() const
218 : : {
219 : 1289796 : return numSlaveVertices;
220 : : }
221 : : MESQUITE_EXPORT size_t num_fixed_vertices() const
222 : : {
223 : : return num_nodes() - num_free_vertices() - num_slave_vertices();
224 : : }
225 : : //! number of elements in the Patch.
226 : 2875356 : MESQUITE_EXPORT size_t num_elements() const
227 : : {
228 : 2875356 : return elementArray.size();
229 : : }
230 : :
231 : : MESQUITE_EXPORT bool is_vertex_free( size_t index ) const
232 : : {
233 : : return index < numFreeVertices;
234 : : }
235 : : MESQUITE_EXPORT bool is_vertex_not_free( size_t index ) const
236 : : {
237 : : return index >= numFreeVertices;
238 : : }
239 : 20574 : MESQUITE_EXPORT bool is_vertex_slave( size_t index ) const
240 : : {
241 [ + + ][ + + ]: 20574 : return index >= numFreeVertices && ( index - numFreeVertices ) < numSlaveVertices;
242 : : }
243 : : MESQUITE_EXPORT bool is_vertex_fixed( size_t index ) const
244 : : {
245 : : return index >= numFreeVertices + numSlaveVertices;
246 : : }
247 : :
248 : : //! number of element corners (number of vertex uses) in patch
249 : : MESQUITE_EXPORT size_t num_corners() const;
250 : :
251 : : //! Returns a pointer to the start of the vertex array.
252 : : MESQUITE_EXPORT const MsqVertex* get_vertex_array( MsqError& err ) const;
253 : : // MsqVertex* get_vertex_array(MsqError &err);
254 : 0 : MESQUITE_EXPORT const MsqVertex* get_vertex_array() const
255 : : {
256 : 0 : return arrptr( vertexArray );
257 : : }
258 : : // MsqVertex* get_vertex_array() { return arrptr(vertexArray); }
259 : :
260 : : //! Returns a pointer to the start of the element array.
261 : : MESQUITE_EXPORT const MsqMeshEntity* get_element_array( MsqError& err ) const;
262 : : MESQUITE_EXPORT MsqMeshEntity* get_element_array( MsqError& err );
263 : :
264 : 0 : MESQUITE_EXPORT size_t* get_connectivity_array()
265 : : {
266 : 0 : return arrptr( elemConnectivityArray );
267 : : }
268 : :
269 : 150306 : MESQUITE_EXPORT Mesh::ElementHandle* get_element_handles_array()
270 : : {
271 : 150306 : return arrptr( elementHandlesArray );
272 : : }
273 : :
274 : 6510181 : MESQUITE_EXPORT Mesh::VertexHandle* get_vertex_handles_array()
275 : : {
276 : 6510181 : return arrptr( vertexHandlesArray );
277 : : }
278 : :
279 : : //! Returns the start of the vertex->element array.
280 : : //! For each vertex in the patch, this array holds
281 : : //! the number of elements the vertex is attached to,
282 : : //! followed by the indices of those elements.
283 : : // const size_t* get_vertex_to_elem_array(MsqError &err);
284 : : //! Returns the start of the vertex->element offset
285 : : //! array (v2e_o). For vertex i, v2e_o[i] is the
286 : : //! index into the vertex->element array (v2e) where
287 : : //! vertex i's data begins. So, v2e[v2e_o[i]] gives
288 : : //! you the number of elements vertex i is attached
289 : : //! to, and v2e[v2e_o[i]+1] gives you the index of
290 : : //! the first element attached to vertex i.
291 : : // const size_t* get_vertex_to_elem_offset(MsqError &err);
292 : :
293 : : // MsqVertex& vertex_by_index(size_t index);
294 : : MESQUITE_EXPORT const MsqVertex& vertex_by_index( size_t index ) const;
295 : : MESQUITE_EXPORT MsqMeshEntity& element_by_index( size_t index );
296 : : MESQUITE_EXPORT const MsqMeshEntity& element_by_index( size_t index ) const;
297 : : MESQUITE_EXPORT size_t get_vertex_index( MsqVertex* vertex );
298 : : MESQUITE_EXPORT size_t get_element_index( MsqMeshEntity* element );
299 : :
300 : : //! Get the coordinates of vertices attached to the specified element
301 : : MESQUITE_EXPORT
302 : : void get_element_vertex_coordinates( size_t elem_index, std::vector< Vector3D >& coords, MsqError& err );
303 : : /*! Get the indices of vertices of specified element. !inefficient!*/
304 : : MESQUITE_EXPORT
305 : : void get_element_vertex_indices( size_t elem_index, std::vector< size_t >& vertex_indices, MsqError& err );
306 : : /*! Get the indices of the elements attached to the specified vertex. */
307 : : MESQUITE_EXPORT
308 : : void get_vertex_element_indices( size_t vertex_index, std::vector< size_t >& elem_indices, MsqError& err );
309 : :
310 : : /** Get the indices of elements adjacent to the specified vertex,
311 : : * and having the specified dimension */
312 : : MESQUITE_EXPORT
313 : : void get_vertex_element_indices( size_t vertex_index, unsigned element_dimension,
314 : : std::vector< size_t >& elem_indices, MsqError& err );
315 : :
316 : : /*! Get indices of elements attached to specified vertex */
317 : : MESQUITE_EXPORT
318 : : const size_t* get_vertex_element_adjacencies( size_t vertex_index, size_t& array_len_out, MsqError& err );
319 : :
320 : : /*! Get the indices of vertices that are attached to vertex (given by
321 : : vertex_index) by an element edge.
322 : : */
323 : : MESQUITE_EXPORT
324 : : void get_adjacent_vertex_indices( size_t vertex_index, std::vector< size_t >& vert_indices, MsqError& err ) const;
325 : :
326 : : /*! \brief Get the indices of entities attached to entity
327 : : (given by ent_ind).
328 : : adj_ents is filled with the indices into the entity array of elements
329 : : adjacent to the given element via an n-dimensional entity.
330 : :
331 : : */
332 : : MESQUITE_EXPORT
333 : : void get_adjacent_entities_via_n_dim( int n, size_t ent_ind, std::vector< size_t >& adj_ents, MsqError& err );
334 : :
335 : : /*! Create the arrays that store which elements are attached
336 : : to each node. If you know how many total vertex uses there are,
337 : : pass it in. Otherwise the PatchData will calculate that number.
338 : : */
339 : : MESQUITE_EXPORT
340 : : void generate_vertex_to_element_data();
341 : :
342 : : /*!
343 : : */
344 : : MESQUITE_EXPORT
345 : : void set_vertex_coordinates( const Vector3D& coords, size_t index, MsqError& err );
346 : : /*! Add delta to the index-th free vertex in the patch
347 : : */
348 : : MESQUITE_EXPORT
349 : : void move_vertex( const Vector3D& delta, size_t index, MsqError& err );
350 : :
351 : : /*! Adjust the position of the specified vertex so that it
352 : : lies on its constraining domain. The actual domain constraint
353 : : is managed by the MeshSet's MeshDomain object.
354 : : */
355 : : MESQUITE_EXPORT
356 : : void snap_vertex_to_domain( size_t vertex_index, MsqError& err );
357 : :
358 : : /*! Returns whether a domain is associated with the MeshSet from which
359 : : the Patch originates.
360 : : If false, you cannot ask for a surface normal. */
361 : : MESQUITE_EXPORT
362 : 30433203 : bool domain_set() const
363 : : {
364 : 30433203 : return 0 != myDomain;
365 : : }
366 : :
367 : : /*\brief Get domain normal at vertex location
368 : : *
369 : : * Get the normal of the domain associated with the passed
370 : : * element handle at the location of the specified vertex.
371 : : *\param vert_index The index of the vertex in this PatchData
372 : : *\param elem_handle The handle of the element passed to the domain
373 : : *\param normal_out The resulting domain normal
374 : : *\param err Error flag. Possible error conditions include:
375 : : * invalid input data, no domain associated with
376 : : * element, no domain at all, etc.
377 : : */
378 : : MESQUITE_EXPORT
379 : : void get_domain_normal_at_vertex( size_t vert_index, Mesh::ElementHandle element, Vector3D& normal_out,
380 : : MsqError& err );
381 : :
382 : : /*! Get the normal to the domain at the centroid (projected to the
383 : : domain) of a given element.
384 : : Normal is returned in Vector3D &surf_norm. If the normal cannot
385 : : be determined, or if the underlying domain is not a surface,
386 : : the normal will be set to (0,0,0).
387 : : Check PatchData::domain_set() is not false first.
388 : : */
389 : : MESQUITE_EXPORT
390 : : void get_domain_normal_at_element( size_t elem_index, Vector3D& surf_norm, MsqError& err );
391 : :
392 : : /** Get surface normals at element corners.
393 : : * normals_out must be of sufficient size to hold
394 : : * the normals of all the corners.
395 : : **/
396 : : MESQUITE_EXPORT
397 : : void get_domain_normals_at_corners( size_t element_index, Vector3D normals_out[], MsqError& err );
398 : :
399 : : MESQUITE_EXPORT
400 : : void get_domain_normal_at_corner( size_t elemen_index, unsigned corner, Vector3D& normal, MsqError& err );
401 : :
402 : : MESQUITE_EXPORT
403 : : void get_domain_normal_at_mid_edge( size_t element_index, unsigned edge_number, Vector3D& normal, MsqError& err );
404 : :
405 : : //! Alternative signature. Same functionality.
406 : : MESQUITE_EXPORT
407 : 18784 : void get_domain_normal_at_element( const MsqMeshEntity* elem_ptr, Vector3D& surf_norm, MsqError& err )
408 : : {
409 : 18784 : get_domain_normal_at_element( size_t( elem_ptr - &( elementArray[0] ) ), surf_norm, err );
410 : 18784 : }
411 : :
412 : : MESQUITE_EXPORT
413 : 12893064 : void get_domain_normal_at_sample( size_t element_index, Sample location, Vector3D& surf_norm, MsqError& err )
414 : : {
415 [ + + + - ]: 12893064 : switch( location.dimension )
416 : : {
417 : : case 0:
418 : 12680254 : get_domain_normal_at_corner( element_index, location.number, surf_norm, err );
419 : 12680254 : break;
420 : : case 1:
421 : 33686 : get_domain_normal_at_mid_edge( element_index, location.number, surf_norm, err );
422 : 33686 : break;
423 : : case 2:
424 [ - + ]: 179124 : assert( location.number == 0 );
425 : 179124 : get_domain_normal_at_element( element_index, surf_norm, err );
426 : 179124 : break;
427 : : default:
428 : : MSQ_SETERR( err )
429 [ # # ]: 0 : ( "Invalid dimension for surface element subentity.\n", MsqError::INVALID_ARG );
430 : : }
431 : 12893064 : }
432 : :
433 : : //! Moves free vertices and then snaps the free vertices to the domain.
434 : : /*\param dk an array of directions, ordered like the vertices in
435 : : the PatchData.
436 : : \param nb_vtx number of vertices.
437 : : \param step_size a scalar that multiplies the vectors given in dk.
438 : : */
439 : : MESQUITE_EXPORT
440 : : void move_free_vertices_constrained( Vector3D dk[], size_t nb_vtx, double step_size, MsqError& err );
441 : :
442 : : /*! Moves free vertices from a memento position along a certain direction
443 : : and then snaps the free vertices to the domain.
444 : : \param dk an array of directions, ordered like the vertices in
445 : : the PatchData.
446 : : \param nb_vtx number of vertices.
447 : : \param step_size a scalar that multiplies the vectors given in dk.
448 : : */
449 : : MESQUITE_EXPORT
450 : : void set_free_vertices_constrained( PatchDataVerticesMemento* memento, Vector3D dk[], size_t nb_vtx,
451 : : double step_size, MsqError& err );
452 : :
453 : : //! Project gradient vector terms onto geometric domain
454 : : MESQUITE_EXPORT
455 : : void project_gradient( std::vector< Vector3D >& gradient, MsqError& err );
456 : :
457 : : //! Calculates the distance each vertex has moved from its original
458 : : //! position as defined by the PatchDataVerticesMememnto.
459 : : MESQUITE_EXPORT
460 : : double get_max_vertex_movement_squared( PatchDataVerticesMemento* memento, MsqError& err );
461 : :
462 : : //! Updates the underlying mesh (the MBMesquite::Mesh implementation) with
463 : : //! new node coordinates and flag values.
464 : : //!\param tag If non-null, store vertex coords in tag rather than
465 : : //! updating the coords in the mesh database. Used for
466 : : //! Jacobi optimizations.
467 : : MESQUITE_EXPORT
468 : : void update_mesh( MsqError& err, const TagHandle* tag = 0 );
469 : :
470 : : //! Calculate new location for all slave higher-order nodes using
471 : : //! mapping function. Called by update_mesh().
472 : : MESQUITE_EXPORT
473 : : void update_slave_node_coordinates( MsqError& err );
474 : : MESQUITE_EXPORT
475 : : void update_slave_node_coordinates( const size_t* elem_indices, size_t num_elem, MsqError& err );
476 : :
477 : : //! Remove the soft_fixed flag from all vertices in the patch.
478 : : MESQUITE_EXPORT
479 : : void set_all_vertices_soft_free( MsqError& err );
480 : : //! Add a soft_fixed flag to all vertices in the patch.
481 : : MESQUITE_EXPORT
482 : : void set_all_vertices_soft_fixed( MsqError& err );
483 : : //! Add a soft_fixed flag to all free vertices in the patch.
484 : : MESQUITE_EXPORT
485 : : void set_free_vertices_soft_fixed( MsqError& err );
486 : :
487 : : //! Mark vertex as culled (soft fixed)
488 : : MESQUITE_EXPORT
489 : 0 : void set_vertex_culled( size_t vtx_index )
490 : : {
491 : 0 : vertexArray[vtx_index].flags() |= MsqVertex::MSQ_CULLED;
492 : 0 : }
493 : : //! Mark vertex as culled (soft fixed)
494 : : MESQUITE_EXPORT
495 : : void clear_vertex_culled( size_t vtx_index )
496 : : {
497 : : vertexArray[vtx_index].flags() &= ~MsqVertex::MSQ_CULLED;
498 : : }
499 : : //! check if vertex is culled
500 : : MESQUITE_EXPORT
501 : : int check_vertex_culled( size_t vtx_index ) const
502 : : {
503 : : return vertexArray[vtx_index].get_flags() | MsqVertex::MSQ_CULLED;
504 : : }
505 : :
506 : : //! Fills a PatchData with the elements attached to a center vertex.
507 : : //! Note that all entities in the sub-patch are copies of the entities
508 : : //! in 'this' patch. As such, moving a vertex in the sub-patch
509 : : //! won't move the corresponding vertex in the source patch. Also,
510 : : //! calling 'update_mesh()' on the sub-patch WILL modify the TSTT
511 : : //! mesh, but the source patch won't see the changes.
512 : : MESQUITE_EXPORT
513 : : void get_subpatch( size_t center_vertex_index, unsigned num_adj_elem_layers, PatchData& pd_to_fill, MsqError& err );
514 : :
515 : : MESQUITE_EXPORT
516 : : void get_free_vertex_coordinates( std::vector< Vector3D >& coords_out ) const;
517 : :
518 : : //! Creates a memento that holds the current
519 : : //! state of the PatchData coordinates.
520 : : MESQUITE_EXPORT
521 : : PatchDataVerticesMemento* create_vertices_memento( MsqError& err );
522 : :
523 : : //! reinstantiates a memento to holds the current
524 : : //! state of the PatchData coordinates. Improves memory management.
525 : : MESQUITE_EXPORT
526 : : void recreate_vertices_memento( PatchDataVerticesMemento* memento, MsqError& err );
527 : :
528 : : //! Restore the PatchData coordinates to the state
529 : : //! contained in the memento.
530 : : MESQUITE_EXPORT
531 : : void set_to_vertices_memento( PatchDataVerticesMemento* memento, MsqError& err );
532 : :
533 : : //! Sets the originating meshSet. This is normally done in MeshSet::get_next_patch().
534 : : //! This function is only for tests purposes.
535 : : MESQUITE_EXPORT
536 : : void set_mesh( Mesh* ms );
537 : :
538 : : //! Returns the originating meshSet.
539 : : MESQUITE_EXPORT
540 : 5791592 : Mesh* get_mesh() const
541 : : {
542 : 5791592 : return myMesh;
543 : : }
544 : :
545 : : MESQUITE_EXPORT
546 : : void set_domain( MeshDomain* dm );
547 : :
548 : : MESQUITE_EXPORT
549 : 2364486 : MeshDomain* get_domain() const
550 : : {
551 : 2364486 : return myDomain;
552 : : }
553 : :
554 : : MESQUITE_EXPORT
555 : : const Settings* get_settings() const
556 : : {
557 : : return mSettings;
558 : : }
559 : : MESQUITE_EXPORT
560 : 6681 : const MappingFunction* get_mapping_function( EntityTopology type ) const
561 : : {
562 : 6681 : return mSettings->get_mapping_function( type );
563 : : }
564 : : MESQUITE_EXPORT
565 : 20205940 : const MappingFunction2D* get_mapping_function_2D( EntityTopology type ) const
566 : : {
567 : 20205940 : return mSettings->get_mapping_function_2D( type );
568 : : }
569 : : MESQUITE_EXPORT
570 : 7808570 : const MappingFunction3D* get_mapping_function_3D( EntityTopology type ) const
571 : : {
572 : 7808570 : return mSettings->get_mapping_function_3D( type );
573 : : }
574 : :
575 : : //! Get R^3 coordinates for logical sample location.
576 : : MESQUITE_EXPORT
577 : : void get_sample_location( size_t element_index, Sample sample, Vector3D& result, MsqError& err ) const;
578 : :
579 : : //! This function returns a NodeSet indicating which
580 : : //! nodes in the specified element are not slaved.
581 : : MESQUITE_EXPORT
582 : : NodeSet non_slave_node_set( size_t elem_idx ) const;
583 : :
584 : : MESQUITE_EXPORT
585 : 8118664 : NodeSet get_samples( size_t element, NodeSet non_slave_nodes ) const
586 : : {
587 : : // If we have a mapping function, use it
588 : 8118664 : const EntityTopology type = element_by_index( element ).get_element_type();
589 : : const MappingFunction* f;
590 [ + - ][ + - ]: 8118664 : if( mSettings && ( f = mSettings->get_mapping_function( type ) ) ) return f->sample_points( non_slave_nodes );
[ + - ]
591 : : // Otherwise default to sampling at all non-slave nodes
592 : 0 : non_slave_nodes.set_all_corner_nodes( type );
593 : 0 : return non_slave_nodes;
594 : : }
595 : :
596 : : MESQUITE_EXPORT
597 : 8118664 : NodeSet get_samples( size_t element ) const
598 : : {
599 : 8118664 : return get_samples( element, non_slave_node_set( element ) );
600 : : }
601 : :
602 : : MESQUITE_EXPORT
603 : : void get_samples( size_t element, std::vector< Sample >& samples_out, MsqError& err ) const;
604 : :
605 : : //! Display the coordinates and connectivity information
606 : : friend std::ostream& operator<<( std::ostream&, const PatchData& );
607 : :
608 : : private:
609 : : /* allow access to the following to functions */
610 : : friend class MBMesquite::ExtraData;
611 : : /**\brief Attach an ExtraData object to this PatchData */
612 : : bool attach_extra_data( ExtraData* data );
613 : : /**\brief Remove an ExtraData object from this PatchData */
614 : : bool remove_extra_data( ExtraData* data );
615 : :
616 : : /**\brief notify all attached ExtraData instances that patch contents have changed */
617 : : void notify_new_patch();
618 : : /**\brief notify all attached ExtraData instances that a subpatch is being initalized
619 : : *\param sub_patch The new, already populated subpatch
620 : : *\param vertex_index_map For the i-th vertex in the subpatch, the
621 : : * i-th entry in this list is the corresponding index in
622 : : * this patch.
623 : : *\param element_index_map For the i-th element in the subpatch, the
624 : : * i-th entry in this list is the corresponding index in
625 : : * this patch.
626 : : */
627 : : void notify_sub_patch( PatchData& sub_patch, const size_t* vertex_index_map, const size_t* element_index_map,
628 : : MsqError& err );
629 : : /**\brief notify all attached ExtraData instances that this patch is being destroyed */
630 : : void notify_patch_destroyed();
631 : :
632 : : /** Call before initialize_data to change vertex_flags for
633 : : * higher-order nodes to MSQ_DEPENDENT.
634 : : */
635 : : void enslave_higher_order_nodes( const size_t* element_offset_array, unsigned char* vertex_flags,
636 : : MsqError& err ) const;
637 : :
638 : : /** Call after filling vertex handle and connectivity arrays to
639 : : * finish initializing the PatchData. Reorders vertex handles array
640 : : * such that all higher-order nodes are at end of array, updates
641 : : * element connectivity array appropriately, initalizes numCornerVertices,
642 : : * and per-element vertex and node counts.
643 : : *
644 : : * NOTE: If the patch contains higher-order elements, this function
645 : : * will re-order the nodes in the vertex array. Do *NOT* assume
646 : : * vertex indices are the same after calling this function!
647 : : *
648 : : * NOTE: This function expects the following data to be initalized:
649 : : * vertexHandlesArray
650 : : * elemConnectivityArray
651 : : * the topology type for all elements in elementArray
652 : : * The function assumes the following data has not been
653 : : * initialized and therefore does not need to be updated:
654 : : * vertexArray
655 : : *
656 : : * \param elem_offset_array Offset into connectivity array for each element
657 : : */
658 : : void initialize_data( size_t* elem_offset_array, unsigned char* vertex_flags, MsqError& err );
659 : :
660 : : /** Code common to misc. methods for populating patch data.
661 : : * Remove duplicates from an array of handles.
662 : : *\param handles The array of handles to uniquify.
663 : : *\param count As input, the lenght of the #handles
664 : : * array. As output, the number of unique
665 : : * handles remaining in the array.
666 : : *\param index_map If non-null, this must be an array of the
667 : : * same length as the handles array. If this
668 : : * array is passed, the entry cooresponding
669 : : * to each handle in the input #handles array will
670 : : * be set to the index of that handle in the output
671 : : * array.
672 : : */
673 : : static void make_handles_unique( Mesh::EntityHandle* handles, size_t& count, size_t* index_map = 0 );
674 : :
675 : : /*\brief Note that the passed info has been calculated and stored */
676 : 0 : void note_have_info( ComputedInfo info )
677 : : {
678 : 0 : haveComputedInfos |= ( 1 << info );
679 : 0 : }
680 : :
681 : : /*\brief Update cached domain normal data */
682 : : void update_cached_normals( MsqError& );
683 : :
684 : : Mesh* myMesh; //!< The Mesh used to fill this PatchData [may be NULL]
685 : : MeshDomain* myDomain; //!< The geometric domain of the mesh [may be NULL]
686 : :
687 : : //! Cached data for vertices in PatchData::vertexHandlesArray,
688 : : //! or vertex data for a temporary patch.
689 : : std::vector< MsqVertex > vertexArray;
690 : : //! The list of handles for the vertices in this patch
691 : : //! May be empty if PatchData::myMesh is NULL
692 : : std::vector< Mesh::VertexHandle > vertexHandlesArray;
693 : : //! The number of vertices in PatchData::vertexArray that are
694 : : //! free vertices. The vertex array is sorted such that
695 : : //! free vertices are first in the array. This value
696 : : //! is therefore the offset at which slave vertices begin
697 : : //! in the array.
698 : : size_t numFreeVertices;
699 : : //! The number of slave vertices in vertexArray. The
700 : : //! vertices are ordered such that all fixed vertices occur
701 : : //! after the slave vertices. Therefore the offset at which
702 : : //! the fixed vertices begin is numFreeVertices+numSlaveVertices
703 : : size_t numSlaveVertices;
704 : : //! Cached data for elements in PatchData::elementHandlesArray
705 : : //! or element data for a temporary patch.
706 : : std::vector< MsqMeshEntity > elementArray;
707 : : //! The hist of handles for elements in this patch.
708 : : //! May be empty if PatchData::myMesh is NULL
709 : : std::vector< Mesh::ElementHandle > elementHandlesArray;
710 : : //! Element connectivity data. The concatenation of the
711 : : //! connectivity list of each element in PatchData::elementArray.
712 : : //! Each element in PatchData::elementArray has a pointer into
713 : : //! this array at the correct offset for that element's connectivity data.
714 : : std::vector< size_t > elemConnectivityArray;
715 : : //! The concatenation of the adjacency lists of all the vertices
716 : : //! in PatchData::vertexArray. Each value in the array is an index into
717 : : //! PatchData::elementArray indicating that the corresponding element uses
718 : : //! the vertex. May be empty if vertex adjacency data has not been
719 : : //! requested.
720 : : std::vector< size_t > vertAdjacencyArray;
721 : : //! This array is indexed by vertex indices and specifies the
722 : : //! offset in \vertAdjacencyArray at which the adjacency list
723 : : //! for the corresponding vertex begins. May be empty if vertex
724 : : //! adjacency data has not been requested.
725 : : std::vector< size_t > vertAdjacencyOffsets;
726 : : //! Index into normalData at which the normal for the corresponding
727 : : //! vertex index is located. Only vertices constrained to a single
728 : : //! domain with a topological dimension of 2 have a unique domain
729 : : //! normal.
730 : : std::vector< unsigned > vertexNormalIndices;
731 : : //! Storage space for cached domain normal data. Pointers in
732 : : //! PatchData::vertexNormalPointers point into this list.
733 : : std::vector< Vector3D > normalData;
734 : : //! Storage space for cached domain DOF for vertices. IF
735 : : //! a domain exists and PatchData::normalData is not empty, but
736 : : //! this array is, it may be assumed that all vertices have
737 : : //! have a DOF == 2.
738 : : std::vector< unsigned short > vertexDomainDOF;
739 : :
740 : : // Arrays in which to store temporary data
741 : : // (avoids reallocation of temp space)
742 : : std::vector< size_t > offsetArray;
743 : : std::vector< unsigned char > byteArray;
744 : : mutable std::vector< bool > bitMap;
745 : :
746 : : // Patch Computed Information (maxs, mins, etc ... )
747 : : double computedInfos[MAX_COMPUTED_INFO_ENUM];
748 : : // Bit map indicating which values in PatchData::computedInfos
749 : : // are valud (which values have been calculated.)
750 : : unsigned haveComputedInfos;
751 : :
752 : : ExtraData* dataList;
753 : :
754 : : const Settings* mSettings;
755 : : static const Settings defaultSettings;
756 : : };
757 : :
758 : : void print_patch_data( const PatchData& pd );
759 : :
760 : : /*! \brief Contains a copy of the coordinates of a PatchData.
761 : :
762 : : Use PatchDataVerticesMemento when you want to change the coordinates
763 : : of a PatchData object but also have the option to restore them.
764 : : This class can only be instantiated through PatchData::create_vertices_memento().
765 : : */
766 : 115908 : class PatchDataVerticesMemento
767 : : {
768 : : public:
769 : : void clear()
770 : : {
771 : : originator = 0;
772 : : vertices.clear();
773 : : normalData.clear();
774 : : }
775 : :
776 : : private:
777 : : // Constructor accessible only to originator (i.e. PatchData)
778 : : friend class PatchData;
779 [ + - ]: 57976 : PatchDataVerticesMemento() : originator( 0 ) {}
780 : :
781 : : PatchData* originator; //!< PatchData whose state is kept
782 : : std::vector< MsqVertex > vertices;
783 : : std::vector< Vector3D > normalData;
784 : : };
785 : :
786 : 0 : inline void PatchData::clear()
787 : : {
788 : 0 : vertexArray.clear();
789 : 0 : vertexHandlesArray.clear();
790 : 0 : elementArray.clear();
791 : 0 : elementHandlesArray.clear();
792 : 0 : elemConnectivityArray.clear();
793 : 0 : vertAdjacencyArray.clear();
794 : 0 : vertAdjacencyOffsets.clear();
795 : 0 : vertexNormalIndices.clear();
796 : 0 : normalData.clear();
797 : : // vertexDomainDOF.clear();
798 : 0 : numFreeVertices = 0;
799 : 0 : numSlaveVertices = 0;
800 : 0 : haveComputedInfos = 0;
801 : 0 : myMesh = 0;
802 : 0 : myDomain = 0;
803 : 0 : }
804 : :
805 : : /*! \brief Returns an array of all vertices in the PatchData.
806 : : */
807 : 5542006 : inline const MsqVertex* PatchData::get_vertex_array( MsqError& err ) const
808 : : {
809 [ - + ][ # # ]: 5542006 : if( vertexArray.empty() ) MSQ_SETERR( err )( "No vertex array defined", MsqError::INVALID_STATE );
810 : 5542006 : return arrptr( vertexArray );
811 : : }
812 : :
813 : : /*! \brief Returns the PatchData element array.
814 : : */
815 : : inline const MsqMeshEntity* PatchData::get_element_array( MsqError& err ) const
816 : : {
817 : : if( elementArray.empty() ) MSQ_SETERR( err )( "No element array defined", MsqError::INVALID_STATE );
818 : : return arrptr( elementArray );
819 : : }
820 : 62 : inline MsqMeshEntity* PatchData::get_element_array( MsqError& err )
821 : : {
822 [ - + ][ # # ]: 62 : if( elementArray.empty() ) MSQ_SETERR( err )( "No element array defined", MsqError::INVALID_STATE );
823 : 62 : return arrptr( elementArray );
824 : : }
825 : :
826 : : /*! \brief set the coordinates of the index-th vertex in the raw array
827 : : */
828 : 14031558 : inline void PatchData::set_vertex_coordinates( const Vector3D& coords, size_t index, MsqError& err )
829 : : {
830 [ - + ]: 14031558 : if( index >= vertexArray.size() )
831 : : {
832 [ # # ]: 0 : MSQ_SETERR( err )( "Index bigger than numVertices.", MsqError::INVALID_ARG );
833 : 0 : return;
834 : : }
835 : :
836 : 14031558 : vertexArray[index] = coords;
837 : :
838 [ - + ]: 14031558 : if( numSlaveVertices )
839 : : {
840 : : size_t num_elem;
841 : : const size_t* indices;
842 [ # # ][ # # ]: 14031558 : indices = get_vertex_element_adjacencies( index, num_elem, err );MSQ_ERRRTN( err );
[ # # ][ # # ]
[ # # ][ # # ]
843 [ # # ][ # # ]: 0 : update_slave_node_coordinates( indices, num_elem, err );MSQ_ERRRTN( err );
[ # # ][ # # ]
[ # # ][ # # ]
844 : : }
845 : : }
846 : : /*! \brief increment the coordinates of the index-th vertex in the raw array
847 : : */
848 : 62926 : inline void PatchData::move_vertex( const Vector3D& delta, size_t index, MsqError& err )
849 : : {
850 [ - + ]: 62926 : if( index >= vertexArray.size() )
851 : : {
852 [ # # ]: 0 : MSQ_SETERR( err )( "Index bigger than numVertices.", MsqError::INVALID_ARG );
853 : 0 : return;
854 : : }
855 : :
856 : 62926 : vertexArray[index] += delta;
857 : :
858 [ - + ]: 62926 : if( numSlaveVertices )
859 : : {
860 : : size_t num_elem;
861 : : const size_t* indices;
862 [ # # ][ # # ]: 62926 : indices = get_vertex_element_adjacencies( index, num_elem, err );MSQ_ERRRTN( err );
[ # # ][ # # ]
[ # # ][ # # ]
863 [ # # ][ # # ]: 0 : update_slave_node_coordinates( indices, num_elem, err );MSQ_ERRRTN( err );
[ # # ][ # # ]
[ # # ][ # # ]
864 : : }
865 : : }
866 : :
867 : : // inline MsqVertex& PatchData::vertex_by_index(size_t index)
868 : : //{
869 : : // return vertexArray[index];
870 : : //}
871 : :
872 : 158285268 : inline const MsqVertex& PatchData::vertex_by_index( size_t index ) const
873 : : {
874 [ - + ]: 158285268 : assert( index < vertexArray.size() );
875 : 158285268 : return vertexArray[index];
876 : : }
877 : :
878 : 81306309 : inline MsqMeshEntity& PatchData::element_by_index( size_t index )
879 : : {
880 [ - + ]: 81306309 : assert( index < elementArray.size() );
881 : 81306309 : return elementArray[index];
882 : : }
883 : :
884 : 54609034 : inline const MsqMeshEntity& PatchData::element_by_index( size_t index ) const
885 : : {
886 [ - + ]: 54609034 : assert( index < elementArray.size() );
887 : 54609034 : return elementArray[index];
888 : : }
889 : :
890 : : /*! gets the index of a vertex in the PatchData vertex array,
891 : : given a pointer to the vertex. */
892 : : inline size_t PatchData::get_vertex_index( MsqVertex* vertex )
893 : : {
894 : : return vertex - arrptr( vertexArray );
895 : : }
896 : :
897 : 4578473 : inline size_t PatchData::get_element_index( MsqMeshEntity* element )
898 : : {
899 : 4578473 : return element - arrptr( elementArray );
900 : : }
901 : :
902 : 0 : inline void PatchData::get_free_vertex_coordinates( std::vector< Vector3D >& coords_out ) const
903 : : {
904 : 0 : coords_out.resize( num_free_vertices() );
905 [ # # ][ # # ]: 0 : std::copy( vertexArray.begin(), vertexArray.begin() + num_free_vertices(), coords_out.begin() );
906 : 0 : }
907 : :
908 : : /*!
909 : : This function instantiate PatchDataVerticesMemento object and returns a pointer to it.
910 : : The PatchDataVerticesMemento contains the current state of the PatchData coordinates.
911 : : It can be used to restore the same PatchData object to those coordinates.
912 : :
913 : : It is the responsibility of the caller to discard the PatchDataVerticesMemento
914 : : when not needed any more.
915 : : */
916 : 57976 : inline PatchDataVerticesMemento* PatchData::create_vertices_memento( MsqError& err )
917 : : {
918 [ + - ]: 57976 : PatchDataVerticesMemento* memento = new PatchDataVerticesMemento;
919 : 57976 : recreate_vertices_memento( memento, err );
920 [ - + ][ # # ]: 57976 : if( MSQ_CHKERR( err ) )
[ - + ]
921 : : {
922 [ # # ]: 0 : delete memento;
923 : 0 : return 0;
924 : : }
925 : 57976 : return memento;
926 : : }
927 : :
928 : : /*!
929 : : This function reuses an existing PatchDataVerticesMemento object.
930 : : The PatchDataVerticesMemento contains the current state of the PatchData coordinates.
931 : : It can be used to restore the same PatchData object to those coordinates.
932 : :
933 : : It is the responsibility of the caller to delete the PatchDataVerticesMemento
934 : : when it is no longer needed.
935 : : */
936 : 946847 : inline void PatchData::recreate_vertices_memento( PatchDataVerticesMemento* memento, MsqError& /*err*/ )
937 : : {
938 : 946847 : memento->originator = this;
939 : :
940 : 946847 : size_t num_vtx = num_free_vertices() + num_slave_vertices();
941 : :
942 : 946847 : memento->vertices.resize( num_vtx );
943 [ + - ][ + - ]: 946847 : std::copy( vertexArray.begin(), vertexArray.begin() + num_vtx, memento->vertices.begin() );
944 : :
945 : : int num_normal;
946 [ + + ]: 946847 : if( normalData.empty() )
947 : 773150 : num_normal = 0;
948 [ + + ]: 173697 : else if( vertexNormalIndices.empty() )
949 : 173646 : num_normal = num_vtx;
950 : : else
951 : : {
952 : 51 : num_normal = num_vtx;
953 [ + + ][ + + ]: 92 : while( num_normal != 0 && vertexNormalIndices[--num_normal] >= normalData.size() )
[ + + ]
954 : : ;
955 [ + - ]: 51 : if( num_normal == 0 )
956 : : {
957 [ + + ]: 51 : if( vertexNormalIndices[0] < normalData.size() ) num_normal = vertexNormalIndices[0] + 1;
958 : : }
959 : : else
960 : 0 : num_normal = vertexNormalIndices[num_normal] + 1;
961 : : }
962 : :
963 : 946847 : memento->normalData.resize( num_normal );
964 [ + - ][ + - ]: 946847 : std::copy( normalData.begin(), normalData.begin() + num_normal, memento->normalData.begin() );
965 : 946847 : }
966 : :
967 : : /*!
968 : : This function restores a PatchData object coordinates to a previous state hold in
969 : : a PatchDataVerticesMemento object (see create_vertices_memento() ).
970 : :
971 : : The function checks whether the memento originates from this particular PatchData object.
972 : : The function does not destroy the memento object: this is the caller responsibility.
973 : : */
974 : 342584 : inline void PatchData::set_to_vertices_memento( PatchDataVerticesMemento* memento, MsqError& err )
975 : : {
976 [ - + ]: 342584 : if( memento->originator != this )
977 : : {
978 : : MSQ_SETERR( err )
979 : : ( "Memento may only be used to restore the PatchData "
980 : : "object from which it was created.",
981 [ # # ]: 0 : MsqError::INVALID_ARG );
982 : 0 : return;
983 : : }
984 : :
985 [ - + ]: 342584 : if( memento->vertices.size() != num_free_vertices() + num_slave_vertices() )
986 : : {
987 : : MSQ_SETERR( err )
988 : : ( "Unable to restore patch coordinates. Number of "
989 : : "vertices in PatchData has changed.",
990 [ # # ]: 0 : MsqError::INVALID_STATE );
991 : 0 : return;
992 : : }
993 : :
994 : : // copies the memento array into the PatchData array.
995 : 342584 : std::copy( memento->vertices.begin(), memento->vertices.end(), vertexArray.begin() );
996 : 342584 : std::copy( memento->normalData.begin(), memento->normalData.end(), normalData.begin() );
997 : : }
998 : :
999 : : } // namespace MBMesquite
1000 : :
1001 : : #endif
|