Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Mesh/PatchData.cpp
Go to the documentation of this file.
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  diachin2@llnl.gov, djmelan@sandia.gov, mbrewer@sandia.gov,
24  pknupp@sandia.gov, tleurent@mcs.anl.gov, tmunson@mcs.anl.gov
25 
26  ***************************************************************** */
35 #include "PatchData.hpp"
36 #include "MsqMeshEntity.hpp"
38 #include "MeshSet.hpp"
39 #include "MsqTimer.hpp"
40 #include "MsqDebug.hpp"
41 #include "TargetMatrix.hpp"
42 #include "TargetCalculator.hpp"
43 
44 #ifdef MSQ_USE_OLD_STD_HEADERS
45 # include <list.h>
46 # include <vector.h>
47 # include <map.h>
48 #else
49 # include <list>
50 # include <vector>
51 # include <map>
52  using std::list;
53  using std::map;
54  using std::vector;
55 #endif
56 
57 #ifdef MSQ_USE_OLD_IO_HEADERS
58 # include <iostream.h>
59 #else
60 # include <iostream>
61  using std::ostream;
62  using std::endl;
63 #endif
64 
65 namespace Mesquite {
66 
68  : targetMatrices( "MSQ_TARGET_MATRIX", Mesh::DOUBLE ),
69  meshSet(0),
70  domainSet(false),
71  domainHint(NO_DOMAIN_HINT),
72  mType(UNDEFINED_PATCH_TYPE),
73  numCornerVertices(0),
74  haveComputedInfos(0)
75 
76 {
77 }
78 
79 
80 // Destructor
82 {
83 }
84 
85 
87 {
90  {
91  max=0;
92  min=MSQ_DBL_MAX;
93  size_t count = num_elements();
94  for (size_t i=0; i<count; ++i) {
95  double vol;
96  vol = elementArray[i].compute_unsigned_area(*this, err); MSQ_ERRRTN(err);
97  if (vol > max)
98  max = vol;
99  if (vol < min)
100  min = vol;
101  }
106  }
107  else
108  {
111  }
112 
113  if (max <= 0 || min < 0 || min == MSQ_DBL_MAX)
115 }
116 
118 {
119  double result;
121  {
123  }
124  else
125  {
126  double min= MSQ_DBL_MAX;
127  double max=-MSQ_DBL_MAX;
128  size_t count = num_elements();
129  for (size_t i=0; i<count; ++i) {
131  size_t nve = elementArray[i].vertex_count();
132  elementArray[i].compute_corner_matrices(*this, A, nve, err);
133  MSQ_ERRZERO(err);
134  for (size_t j=0; j<nve; ++j) {
135  min = det(A[j]) < min ? det(A[j]) : min;
136  max = det(A[j]) > max ? det(A[j]) : max;
137  }
138  }
139 
140  if (max <= 0) {
141  MSQ_SETERR(err)("Sigma_max is not positive.", MsqError::INVALID_MESH);
142  return 0;
143  }
144  //We set delta to zero if everything in the initial mesh is valid.
145  // This causes metrics with a barrier between valid and inverted
146  // meshes to retain that barrier. If there is a negative jacobian
147  // corner in the mesh, we set delta to a small fraction of the
148  // maximum jacobian in the mesh.
149  result = (min<=MSQ_MIN) ? 0.001 * max : 0;
152  }
153 
154  return result;
155 }
156 
157 
159 {
160  double avg;
162  {
164  }
165  else
166  {
167  avg =0.;
168  int total_num_corners =0;
170  for (size_t i=0; i<elementArray.size(); ++i) {
171  int nve = elementArray[i].vertex_count();
172  elementArray[i].compute_corner_matrices(*this, A, nve, err);
173  MSQ_ERRZERO(err);
174  total_num_corners += nve;
175  for (int c=0; c<nve; ++c) {
176  avg += TargetCalculator::compute_Lambda(A[c], err);
177  MSQ_ERRZERO(err);
178  }
179  }
180 
181  avg = avg / total_num_corners;
184  }
185  return avg;
186 }
187 
188 
189 
197 {
198  const size_t numv = num_vertices();
199  const size_t nume = num_elements();
200 
201  size_t *vtx;
202  size_t *tmp;
203 
204  size_t *sta = new size_t[numv + 1];
205  size_t *vte;
206  size_t *ord = new size_t[numv];
207  size_t *per = new size_t[numv];
208  size_t *pel;
209  size_t *que1 = new size_t[numv];
210  size_t *que2 = new size_t[numv];
211 
212  //MsqVertex *v2a;
213  //Mesh::VertexHandle *v2h;
214  //MsqMeshEntity *e2a;
215  //Mesh::ElementHandle *e2h;
216  // Copy arrays so higher-order nodes get copied
221 
222  double val, max;
223 
224  size_t toc;
225  size_t vtc;
226  size_t idx;
227  size_t loc;
228  size_t i, j;
229  size_t q1l, q2l, q;
230  size_t st, en;
231 
232  // Step -1: Clear any data that will be invalidated by this
233  clear_tag_data();
234 
235  // Step 0: Make sure patch data is valid.
236 
237  // Step 1: Find the length of the element to vertex list for each
238  // individual vertex.
239 
240  memset(sta, 0, (numv+1)*sizeof(size_t));
241  for (i = 0; i < nume; ++i) {
242  vtc = elementArray[i].vertex_count();
243  vtx = elementArray[i].get_vertex_index_array();
244 
245  for (j = 0; j < vtc; ++j) {
246  ++sta[vtx[j]];
247  }
248  }
249 
250  // Step 2: Compute the offsets, total length of the element to vertex
251  // list, and allocate the data.
252 
253  toc = sta[0];
254  sta[0] = 0;
255  for (i = 1; i <= numv; ++i) {
256  j = sta[i];
257  sta[i] = toc;
258  toc += j;
259  }
260 
261  vte = new size_t[toc];
262 
263  // Step 3: Finish constructing the vertex to element list.
264 
265  for (i = 0; i < nume; ++i) {
266  vtc = elementArray[i].vertex_count();
267  vtx = elementArray[i].get_vertex_index_array();
268 
269  for (j = 0; j < vtc; ++j) {
270  vte[sta[vtx[j]]++] = i;
271  }
272  }
273 
274  for (i = numv; i > 0; --i) {
275  sta[i] = sta[i-1];
276  }
277  sta[i] = 0;
278 
279  // Step 4: Begin the reodering by computing the vertex furthest from the
280  // origin.
281 
282  max = -1.0;
283  idx = 0;
284 
285  for (i = 0; i < numv; ++i) {
286  val = vertexArray[i].length_squared();
287  if (val > max) {
288  max = val;
289  idx = i+1;
290  }
291  }
292 
293  // Step 5: Perform a breadth first search to find the ordering.
294 
295  memset(per, 0, numv*sizeof(size_t));
296 
297  loc = 0;
298  while (idx > 0) {
299  // The vertex referenced by idx has not been visited yet. Insert it
300  // into the queue for processing.
301  --idx;
302 
303  q1l = 1;
304  que1[0] = idx;
305  per[idx] = 1;
306 
307  while (q1l) {
308  q = 0;
309  q2l = 0;
310 
311  while (q < q1l) {
312  idx = que1[q++];
313  ord[loc++] = idx;
314 
315  st = sta[idx];
316  en = sta[idx+1];
317  while (st < en) {
318  vtc = elementArray[vte[st]].vertex_count();
319  vtx = elementArray[vte[st]].get_vertex_index_array();
320  ++st;
321 
322  for (j = 0; j < vtc; ++j) {
323  idx = vtx[j];
324  if (!per[idx]) {
325  que2[q2l++] = idx;
326  per[idx] = 1;
327  }
328  }
329  }
330  }
331 
332  q1l = q2l;
333 
334  tmp = que1;
335  que1 = que2;
336  que2 = tmp;
337  }
338 
339  if (loc >= numv) {
340  break;
341  }
342 
343  // The mesh is not connected. There is another piece with some vertices
344  // remaining. Repeat the breadth-first search algorithm on the new
345  // mesh component.
346 
347  max = -1.0;
348  idx = 0;
349  for (i = 0; i < numv; ++i) {
350  if (!per[i]) {
351  val = vertexArray[i].length_squared();
352  if (val > max) {
353  max = val;
354  idx = i+1;
355  }
356  }
357  }
358  }
359 
360  delete[] que1;
361  delete[] que2;
362 
363  // Step 6: Compute the permutation vectors
364 
365  pel = new size_t[nume];
366  for (i = 0; i < nume; ++i) {
367  pel[i] = nume;
368  }
369 
370  toc = 0;
371  for (i = 0; i < numv; ++i) {
372  loc = ord[numv-1-i];
373 
374  per[loc] = i;
375 
376  st = sta[loc];
377  en = sta[loc+1];
378  while (st < en) {
379  loc = vte[st++];
380  if (nume == pel[loc]) {
381  pel[loc] = toc++;
382  }
383  }
384  }
385 
386  delete[] ord;
387  delete[] vte;
388  delete[] sta;
389 
390  // Step 7: Permute the vertices
391 
392  //v2a = new MsqVertex[vertexArraySize];
393  //v2h = new Mesh::VertexHandle[vertexArraySize];
394 
395  for (i = 0; i < numv; ++i) {
396  loc = per[i];
397  v2a[loc] = vertexArray[i];
398  v2h[loc] = vertexHandlesArray[i];
399  }
400 
401  if (!vertexNormals.empty() && domainHint != PLANAR_DOMAIN) {
402  PatchDataMem<Vector3D> v2n(numv);
403  for (i = 0; i < numv; ++i) {
404  loc = per[i];
405  v2n[loc] = vertexNormals[i];
406  }
407  vertexNormals = v2n;
408  }
409 
410  //delete[] vertexArray;
411  //delete[] vertexHandlesArray;
412 
413  vertexArray = v2a;
414  vertexHandlesArray = v2h;
415 
416  // Step 8: Permute the elements and vertex indices for the elements
417 
418  //e2a = new MsqMeshEntity[elemArraySize];
419  //e2h = new Mesh::ElementHandle[elemArraySize];
420 
421  for (i = 0; i < nume; ++i) {
422  vtc = elementArray[i].vertex_count();
423  vtx = elementArray[i].get_vertex_index_array();
424 
425  for (j = 0; j < vtc; ++j) {
426  vtx[j] = per[vtx[j]];
427  }
428 
429  loc = pel[i];
430  e2a[loc] = elementArray[i];
431  e2h[loc] = elementHandlesArray[i];
432  }
433 
434  //delete[] elementArray;
435  //delete[] elementHandlesArray;
436 
437  elementArray = e2a;
438  elementHandlesArray = e2h;
439 
440  // Step 9: Finish by deleting allocated memory
441 
442  delete[] per;
443  delete[] pel;
444 
445  // Step 10: Recompute vertex to element mapping if it existed.
446 
447  if (vertAdjacencyOffsets.size()) {
451  }
452  return;
453 }
454 
459 {
460  int num_free_vertices=0;
461 
462  size_t count = num_vertices();
463  for (size_t i = 0; i < count; ++i)
464  if (vertexArray[i].is_free_vertex())
466 
467  return num_free_vertices;
468 }
469 
471 {
472  unsigned result = 0;
473  size_t count = num_nodes();
474  for (size_t i = 0; i < count; ++i)
475  if (vertexArray[i].is_free_vertex())
476  ++result;
477  return result;
478 }
479 
480 
481 // #undef __FUNC__
482 // #define __FUNC__ "PatchData::add_element"
483 // /*! \fn PatchData::add_element(TSTT::Mesh_Handle mh, TSTT::Entity_Handle eh, int* vertex_indices, EntityTopology topo, MsqError &err)
484 
485 // \param int* vertex_indices ... those indices corresponds to the indices of
486 // the element's vertices in the PatchData arrays -- see output
487 // of the add_vertex function.
488 // */
489 // int PatchData::add_element(TSTT::Mesh_Handle mh, TSTT::Entity_Handle eh,
490 // size_t* vertex_indices, EntityTopology topo,
491 // MsqError &err)
492 // {
493 // int num_verts = MsqMeshEntity::vertex_count(topo);
494 // if (!num_verts)
495 // err.set_msg("Attempting to add unknown element type to PatchData.");
496 // else if (numElements >= elemArraySize)
497 // err.set_msg("No space available. Use reserve_element_capacity().");
498 // else
499 // {
500 // // Set the element's type
501 // elementArray[numElements].set_element_type(topo);
502 // elementHandlesArray[numElements].mesh = mh;
503 // elementHandlesArray[numElements].entity = eh;
504 // // Go through each vertex
505 // for (int n=0; n<num_verts; ++n)
506 // {
507 // // Make sure it's a valid index
508 // if (vertex_indices[n]>=numVertices)
509 // err.set_msg("invalid vertex indices");
510 // // Set the element's vertex indices
511 // elementArray[numElements].set_vertex_index(n, vertex_indices[n]);
512 // }
513 // return numElements++;
514 // }
515 // return -1;
516 // }
517 
518 // #undef __FUNC__
519 // #define __FUNC__ "PatchData::add_triangle"
520 // /*! \fn PatchData::add_triangle(TSTT::Mesh_Handle mh, TSTT::Entity_Handle eh, size_t index_vtx1, size_t index_vtx2, size_t index_vtx3, MsqError &err)
521 
522 // \brief adds a triangle element to the PatchData object.
523 
524 // \param int index_vertex1 ... those 3 indices corresponds to the indices of
525 // the triangle's vertices in the PatchData arrays -- see output
526 // of the add_vertex function.
527 // */
528 // void PatchData::add_triangle(TSTT::Mesh_Handle mh, TSTT::Entity_Handle eh,
529 // size_t index_vtx1,
530 // size_t index_vtx2,
531 // size_t index_vtx3,
532 // MsqError &err)
533 // {
534 // // make sure we've got space to add this element
535 // if (elemArraySize == numElements)
536 // {
537 // err.set_msg("No more space in PatchData element array");
538 // return;
539 // }
540 
541 // // checks the indices are valid
542 // if (index_vtx1>=numVertices || // index_vtx1<0 ||
543 // index_vtx2>=numVertices || // index_vtx2<0 ||
544 // index_vtx3>=numVertices // || index_vtx3<0
545 // )
546 // err.set_msg("invalid vertex indices");
547 
548 // elementHandlesArray[numElements].mesh = mh;
549 // elementHandlesArray[numElements].entity = eh;
550 // elementArray[numElements].set_element_type(TRIANGLE);
551 // elementArray[numElements].set_vertex_index(0, index_vtx1);
552 // elementArray[numElements].set_vertex_index(1, index_vtx2);
553 // elementArray[numElements].set_vertex_index(2, index_vtx3);
554 // ++numElements;
555 
556 // return;
557 // }
558 
559 
581  double step_size, MsqError &err)
582 {
583  if (nb_vtx != num_vertices())
584  {
585  MSQ_SETERR(err)("The directional vector must be of length numVertices.",
587  return;
588  }
589 
590  MsqFreeVertexIndexIterator free_iter(this, err);
591  free_iter.reset();
592  while (free_iter.next())
593  {
594  vertexArray[free_iter.value()] += (step_size * dk[free_iter.value()]);
595  snap_vertex_to_domain(free_iter.value(), err);
596  MSQ_ERRRTN(err);
597  }
598 
599  // Checks that moving direction is zero for fixed vertices.
600  if (MSQ_DBG(3)) {
601  for (size_t m=0; m<num_vertices(); ++m) {
602  Vector3D zero_3d(0.,0.,0.);
603  if (!vertexArray[m].is_free_vertex()
604  && dk[m] != zero_3d
605  && dk[m] != -zero_3d )
606  {
607  MSQ_DBGOUT(3) << "dk["<<m<<"]: " << dk[m] << endl;
608  MSQ_DBGOUT(3) << "moving a fixed vertex." << endl;
609  }
610  }
611  }
612 }
613 
614 
631  Vector3D dk[],
632  size_t nb_vtx,
633  double step_size,
634  MsqError &err)
635 {
636  if (nb_vtx != memento->numVertices)
637  {
639  return;
640  }
641 
642  size_t m=0;
643  MsqFreeVertexIndexIterator free_iter(this, err);
644  MSQ_ERRRTN(err);
645  free_iter.reset();
646  while (free_iter.next())
647  {
648  m=free_iter.value();
649  vertexArray[m] = memento->vertices[m] + (step_size * dk[m]);
650  snap_vertex_to_domain(m, err);
651  MSQ_ERRRTN(err);
652  }
653 
654  // Checks that moving direction is zero for fixed vertices.
655  if (MSQ_DBG(3)) {
656  for (m=0; m<num_vertices(); ++m)
657  {
658  Vector3D zero_3d(0.,0.,0.);
659  if ( ! vertexArray[m].is_free_vertex()
660  && ( dk[m] != zero_3d && dk[m] != -zero_3d) )
661  {
662  MSQ_DBGOUT(3) << "dk["<<m<<"]: " << dk[m] << endl;
663  MSQ_DBGOUT(3) <<"moving a fixed vertex." << endl;
664  }
665  }
666  }
667 }
668 
669 
680  memento,
681  MsqError &err)
682 {
683  int m=0;
684  Vector3D temp_vec;
685  double temp_dist=0.0;
686  double max_dist=0.0;
687  MsqFreeVertexIndexIterator free_iter(this, err); MSQ_ERRZERO(err);
688  free_iter.reset();
689  while (free_iter.next())
690  {
691  m=free_iter.value();
692  temp_vec=vertexArray[m] - memento->vertices[m];
693  temp_dist=temp_vec.length_squared();
694  if(temp_dist>max_dist)
695  {
696  max_dist=temp_dist;
697  }
698  }
699  return max_dist;
700 }
701 
705 {
706  for(size_t i=0;i<num_vertices();++i)
707  vertexArray[i].set_soft_fixed_flag();
708 }
709 
713 {
714  for(size_t i=0;i<num_vertices();++i){
715  if(vertexArray[i].is_free_vertex())
716  vertexArray[i].set_soft_fixed_flag();
717  }
718 }
719 
723  {
724  for(size_t i=0;i<num_vertices();++i)
725  vertexArray[i].remove_soft_fixed_flag();
726  }
727 
735  size_t elem_index,
736  vector<Vector3D> &coords,
737  MsqError& /*err*/)
738 {
739  // Check index
740  if (elem_index >= num_elements())
741  return;
742 
743  // Ask the element for its vertex indices
744  const size_t *vertex_indices = elementArray[elem_index].get_vertex_index_array();
745 
746  // Get the coords for each indicated vertex
747  size_t num_verts = elementArray[elem_index].vertex_count();
748  coords.reserve(coords.size() + num_verts);
749  for (size_t i = 0; i < num_verts; i++)
750  coords.push_back(Vector3D(vertexArray[vertex_indices[i]]));
751 }
752 
759  size_t elem_index,
760  vector<size_t> &vertex_indices,
761  MsqError& /*err*/)
762 {
763  // Ask the element for its vertex indices
764  elementArray[elem_index].get_vertex_indices(vertex_indices);
765 }
766 
767 
768 void PatchData::get_vertex_element_indices(size_t vertex_index,
769  vector<size_t> &elem_indices,
770  MsqError &err)
771 {
772  size_t count, *ptr;
773  ptr = get_vertex_element_adjacencies( vertex_index, count, err );
774  elem_indices.resize( count );
775  memcpy( &elem_indices[0], ptr, count * sizeof(size_t) );
776 }
777 
778 size_t* PatchData::get_vertex_element_adjacencies( size_t vertex_index,
779  size_t& array_len_out,
780  MsqError& err )
781 {
782  // Make sure we've got the data
784  {
786  }
787 
788  const size_t begin = vertAdjacencyOffsets[vertex_index];
789  const size_t end = vertAdjacencyOffsets[vertex_index+1];
790  array_len_out = end - begin;
791  return &vertAdjacencyArray[begin];
792 }
793 
794 
803 void PatchData::get_adjacent_vertex_indices(size_t vertex_index,
804  vector<size_t> &vert_indices,
805  MsqError &err)
806 {
807  //First get elems attached to vertex[vertex_index]
808  vector<size_t> elem_indices;
809  vector<size_t> temp_vert_indices;
810  msq_std::vector<size_t>::iterator iter;
811  size_t cur_vert;
812  int found=0;
813  get_vertex_element_indices(vertex_index, elem_indices,err);
814  MSQ_ERRRTN(err);
815  MsqMeshEntity* elems=get_element_array(err);
816  MSQ_ERRRTN(err);
817  //get nodes attached to vertex_index... with some duplication
818  while(!elem_indices.empty()){
819  elems[elem_indices.back()].get_connected_vertices(vertex_index, temp_vert_indices,err);
820  MSQ_ERRRTN(err);
821  elem_indices.pop_back();
822  }
823  //eliminate duplication.
824  while(!temp_vert_indices.empty()){
825  cur_vert=temp_vert_indices.back();
826  temp_vert_indices.pop_back();
827  iter=vert_indices.begin();
828  found=0;
829  while(iter!=vert_indices.end() && !found){
830  if(*(iter)==cur_vert)
831  found=1;
832  ++iter;
833  }
834  if(!found)
835  vert_indices.push_back(cur_vert);
836  }
837 }
838 
850 void PatchData::get_adjacent_entities_via_n_dim(int n, size_t ent_ind,
851  vector<size_t> &adj_ents,
852  MsqError &err)
853 {
854  //reset the vector
855  adj_ents.clear();
856  //vertices of this entity (given by ent_ind)
857  vector<size_t> verts;
858  //vector to store elements attached to the vertices in verts
859  vector<size_t> elem_on_vert[MSQ_MAX_NUM_VERT_PER_ENT];
860  //length of above vectos
861  int length_elem_on_vert[MSQ_MAX_NUM_VERT_PER_ENT];
862  //get verts on this element
863  get_element_vertex_indices(ent_ind, verts, err);
864  int num_vert=verts.size();
865  int i=0;
866  int j=0;
867  for(i=0;i<num_vert;++i){
868  //get elements on the vertices in verts and the number of vertices
869  get_vertex_element_indices(verts[i],elem_on_vert[i],err);
870  MSQ_ERRRTN(err);
871  length_elem_on_vert[i]=elem_on_vert[i].size();
872  }
873  //this_ent is the index for an entity which is a candidate to be placed
874  //into adj_ents
875  size_t this_ent;
876  //num of times this_ent has been found in the vectors of entity indices
877  int counter=0;
878  i = 0;
879  //loop of each vert on ent_ind
880  while(i<num_vert){
881  //loop over each ent connected to vert
882  j=0;
883  while(j<length_elem_on_vert[i]){
884  //get candidate element
885  this_ent=elem_on_vert[i][j];
886  //if we haven't already consider this ent
887  if(this_ent!=ent_ind){
888  //if this_ent occurred earlier we would have already considered it
889  //so start at i and j+1
890  int k1=i;
891  int k2=j+1;
892  //this_ent has occured once so far
893  counter=1;
894  //while k1 < num_vert
895  while(k1<num_vert){
896  //loop over entries in the elem on vert vector
897  while(k2<length_elem_on_vert[k1]){
898  //if it matches this_ent
899  if(elem_on_vert[k1][k2]==this_ent){
900  //mark it as 'seen', by making it the same as ent_ind
901  //i.e., the entity passed to us.
902  elem_on_vert[k1][k2]=ent_ind;
903  ++counter;
904  //do not look at remaining elems in this vector
905  k2+=length_elem_on_vert[k1];
906  }
907  else
908  ++k2;
909  }
910  ++k1;
911  k2=0;
912 
913  }
914  //if this_ent occured enough times and isn't ent_ind
915  if(counter>n && this_ent!=ent_ind){
916  adj_ents.push_back(this_ent);
917  }
918  }
919  ++j;
920  }
921  ++i;
922  }
923 }
924 
925 
926 
927 
928 
936 {
937  if (!meshSet)
938  return;
939 
940  meshSet->update_mesh(*this, err);
941  MSQ_CHKERR(err);
942 }
943 
945 {
946  MSQ_FUNCTION_TIMER( "PatchData::generate_vertex_to_element_data" );
947 
948  // Skip if data already exists
949  if (!vertAdjacencyArray.empty())
950  return;
951 
952  // Allocate offset array
954  memset( &vertAdjacencyOffsets[0], 0, sizeof(size_t)*vertAdjacencyOffsets.size() );
955 
956  // Temporarily use offsets array to hold per-vertex element count
959  for (elem_iter = elementArray.begin(); elem_iter != elem_end; ++elem_iter)
960  {
961  size_t* conn_iter = elem_iter->get_vertex_index_array();
962  const size_t* conn_end = conn_iter + elem_iter->node_count();
963  for ( ; conn_iter != conn_end; ++conn_iter )
964  ++vertAdjacencyOffsets[*conn_iter];
965  }
966 
967  // Convert counts to end indices.
968  // When done, vertAdjacencyOffsets will contain, for each vertex,
969  // one more than the *last* index for that vertex's data in the
970  // adjacency array. This is *not* the final state for this data.
971  // See comments for next loop.
974  size_t prev = *off_iter;
975  ++off_iter;
976  for ( ; off_iter != off_end; ++off_iter)
977  {
978  prev += *off_iter;
979  *off_iter = prev;
980  }
981 
982  // Allocate space for element numbers
983  const size_t num_vert_uses = vertAdjacencyOffsets[num_nodes()-1];
984  assert( num_vert_uses == elemConnectivityArray.size() );
985  vertAdjacencyArray.resize( num_vert_uses );
986 
987  // Fill vertAdjacencyArray, using the indices in vertAdjacencyOffsets
988  // as the location to insert the next element number in
989  // vertAdjacencyArray. When done, vertAdjacenyOffsets will contain
990  // the start index for each vertex, rather than one past the last
991  // index.
992  for (size_t i = 0; i < elementArray.size(); ++i)
993  {
994  size_t* conn_iter = elementArray[i].get_vertex_index_array();
995  const size_t* conn_end = conn_iter + elementArray[i].node_count();
996  for ( ; conn_iter != conn_end; ++conn_iter )
997  {
998  const size_t array_index = --vertAdjacencyOffsets[*conn_iter];
999  vertAdjacencyArray[array_index] = i;
1000  }
1001  }
1002 
1003  // Last entry should be number of vertex uses (one past the
1004  // last index of the last vertex.)
1005  vertAdjacencyOffsets[num_nodes()] = num_vert_uses;
1006 }
1007 
1008 void PatchData::get_subpatch(size_t center_vertex_index,
1009  PatchData &subpatch,
1010  MsqError &err)
1011 {
1012  // Make sure we're in range
1013  if (center_vertex_index >= num_vertices())
1014  {
1015  MSQ_SETERR(err)("Invalid index for center vertex",MsqError::INVALID_ARG);
1016  return;
1017  }
1018 
1019  // Map vertex indices from this patch data to indices in new patch data
1020  msq_std::map<size_t, size_t> vertex_index_map;
1021 
1022  size_t num_elems;
1023  const size_t* vertex_adjacencies;
1024  vertex_adjacencies = get_vertex_element_adjacencies( center_vertex_index,
1025  num_elems, err );
1026  MSQ_ERRRTN(err);
1027 
1028  // Loop through each element, populating vertex_index_map.
1029  size_t which_elem, which_vert, vertex_count = 0;
1030  size_t vertex_uses = 0;
1031  for (which_elem = 0; which_elem < num_elems; ++which_elem )
1032  {
1033  size_t elem_index = vertex_adjacencies[which_elem];
1034  MsqMeshEntity& elem = elementArray[elem_index];
1035  for (which_vert = elem.node_count(); which_vert--; )
1036  {
1037  size_t vert_index = elem.get_vertex_index(which_vert);
1038  if (vertex_index_map.find(vert_index) != vertex_index_map.end())
1039  vertex_index_map[vert_index] = vertex_count++;
1040  }
1041  vertex_uses += elem.node_count();
1042  }
1043 
1044  // Allocate storage in subpatch
1045  subpatch.vertexHandlesArray.resize( vertex_count );
1046  subpatch.elementArray.resize( num_elems );
1047  subpatch.elementHandlesArray.resize( num_elems );
1048  subpatch.elemConnectivityArray.resize( vertex_uses );
1049 
1050  // For now, put reverse of index map into handles array (such that
1051  // the handles array in the subpatch contains the index in this
1052  // patch for each vertex.) When PatchData::initalize_data re-orders
1053  // the vertices, we can then use this array to determine which vertices
1054  // where placed where.
1055  msq_std::map<size_t,size_t>::iterator iter;
1056  for (iter = vertex_index_map.begin(); iter != vertex_index_map.end(); ++iter)
1057  subpatch.vertexHandlesArray[iter->second] = (Mesh::VertexHandle)(iter->first);
1058 
1059  // Store elements with updated connectivity list in subpatch
1060  msq_std::vector<size_t> elem_conn_offsets(vertex_uses);
1061  size_t* elem_connectivity = &(subpatch.elemConnectivityArray[0]);
1062  size_t elem_conn_index = 0;
1063  for (which_elem = 0; which_elem < num_elems; ++which_elem)
1064  {
1065  size_t elem_index = vertex_adjacencies[which_elem];
1066  MsqMeshEntity& elem = elementArray[elem_index];
1067  elem_conn_offsets[which_elem] = elem_conn_index;
1068  for (which_vert = 0; which_vert < elem.node_count(); which_vert++ )
1069  {
1070  size_t vert_index = elem.get_vertex_index(which_vert);
1071 
1072  // Add this vertex to the new element's array
1073  elem_connectivity[elem_conn_index++] = vertex_index_map[vert_index];
1074  }
1075  subpatch.elementArray[which_elem].set_element_type( elem.get_element_type() );
1076  }
1077 
1078  // Re-order vertices and initialize other data in subpatch
1079  subpatch.initialize_data( &elem_conn_offsets[0], err ); MSQ_ERRRTN(err);
1080 
1081  // Copy vertex data into subpatch. subpatch.vertexHandlesArray contains
1082  // the indices into this PatchData for each vertex
1083  subpatch.vertexArray.resize( vertex_count );
1084  for (which_vert = 0; which_vert < vertex_count; ++which_vert)
1085  {
1086  size_t vert_index = (size_t)(subpatch.vertexHandlesArray[which_vert]);
1087  subpatch.vertexHandlesArray[which_vert] = vertexHandlesArray[vert_index];
1088  subpatch.vertexArray[which_vert] = vertexArray[vert_index];
1089  }
1090 }
1091 
1095 void PatchData::snap_vertex_to_domain(size_t vertex_index, MsqError &err)
1096 {
1098  {
1099  if (domainHint == SMOOTH_DOMAIN && !vertexNormals.empty())
1100  {
1102  vertexHandlesArray[vertex_index],
1103  Vector3D(vertexArray[vertex_index]),
1104  vertexArray[vertex_index],
1105  vertexNormals[vertex_index],
1106  err ); MSQ_ERRRTN(err);
1107  }
1108  else
1109  {
1111  vertexArray[vertex_index]);
1112  }
1113  }
1114 }
1115 
1116 
1118  bool normalize,
1119  Vector3D &surf_norm,
1120  MsqError &err)
1121 {
1122  if (domainHint != NO_DOMAIN_HINT)
1123  {
1124  if (vertexNormals.empty())
1125  {
1126  update_cached_normals( err ); MSQ_ERRRTN(err);
1127  }
1128 
1129  if (domainHint == PLANAR_DOMAIN)
1130  vertex_index = 0;
1131  surf_norm = vertexNormals[vertex_index];
1132  }
1133  else
1134  {
1135  MeshDomain* domain = meshSet ? meshSet->get_domain_constraint() : 0;
1136  if (!domain)
1137  {
1138  MSQ_SETERR(err)( "No domain constraint set.", MsqError::INVALID_STATE );
1139  return;
1140  }
1141 
1142  surf_norm = vertexArray[vertex_index];
1143  domain->normal_at( vertexHandlesArray[vertex_index], surf_norm );
1144  }
1145 
1146  if (normalize)
1147  surf_norm.normalize();
1148 }
1149 
1150 
1152 {
1153  MeshDomain* domain = meshSet ? meshSet->get_domain_constraint() : 0;
1154  if (!domain)
1155  {
1156  MSQ_SETERR(err)( "No domain constraint set.", MsqError::INVALID_STATE );
1157  vertexNormals.clear();
1158  return;
1159  }
1160 
1161  if (domainHint == PLANAR_DOMAIN)
1162  {
1163  vertexNormals.resize(1);
1165  domain->normal_at( elementHandlesArray[0], vertexNormals[0] );
1166  }
1167 
1168  else
1169  {
1170  vertexNormals.resize( num_vertices() );
1171  for ( unsigned i = 0; i < num_vertices(); ++i)
1172  {
1174  norm = vertexArray[i];
1175  domain->normal_at( vertexHandlesArray[i], norm );
1176  //norm.normalize();
1177  //if (!finite(norm.x()) || !finite(norm.y()) || !finite(norm.z()))
1178  // norm.set(0,0,0);
1179  }
1180  }
1181 }
1182 
1183 
1185  Vector3D &surf_norm,
1186  MsqError &err) const
1187 {
1189  {
1190  elementArray[elem_index].get_centroid(surf_norm, *this, err);
1191  MSQ_ERRRTN(err);
1193  elementHandlesArray[elem_index],
1194  surf_norm);
1195  }
1196  else
1197  MSQ_SETERR(err)( "No domain constraint set.", MsqError::INVALID_STATE );
1198 }
1199 /*
1200 void PatchData::get_domain_normal_at_corner( size_t elem_index,
1201  size_t elem_corner,
1202  Vector3D& normal_out,
1203  MsqError& err ) const
1204 {
1205  size_t vert_index;
1206 
1207  if (meshSet && meshSet->get_domain_constraint())
1208  {
1209  vert_index = elementArray[elem_index].get_vertex_index_array()[elem_corner];
1210  normal_out = vertexArray[ vert_index ];
1211  meshSet->get_domain_constraint()->normal_at( elementHandlesArray[elem_index],
1212  normal_out );
1213  }
1214  else
1215  {
1216  MSQ_SETERR(err)("No domain constraint set.", MsqError::INVALID_STATE );
1217  }
1218 }
1219 */
1220 
1222  Vector3D normals_out[],
1223  MsqError& err )
1224 {
1225  const MsqMeshEntity& elem = elementArray[elem_index];
1226  const unsigned count = elem.vertex_count();
1227  const size_t* const vertex_indices = elem.get_vertex_index_array();
1228 
1229  if (domainHint != NO_DOMAIN_HINT)
1230  {
1231  if (vertexNormals.empty())
1232  {
1233  update_cached_normals( err ); MSQ_ERRRTN(err);
1234  }
1235 
1236  if (domainHint == PLANAR_DOMAIN)
1237  {
1238  for (unsigned i = 0; i < count; ++i)
1239  normals_out[i] = vertexNormals[0];
1240  }
1241  else
1242  {
1243  for (unsigned i = 0; i < count; ++i)
1244  normals_out[i] = vertexNormals[vertex_indices[i]];
1245  }
1246  }
1247  else
1248  {
1249  MeshDomain* domain = meshSet ? meshSet->get_domain_constraint() : 0;
1250  if (!domain)
1251  {
1252  MSQ_SETERR(err)( "No domain constraint set.", MsqError::INVALID_STATE );
1253  return;
1254  }
1255 
1256  for (unsigned i = 0; i < count; ++i)
1257  normals_out[i] = vertexArray[ vertex_indices[i] ];
1258 
1259  domain->normal_at( elementHandlesArray[elem_index],
1260  normals_out, count,
1261  err ); MSQ_CHKERR(err);
1262  }
1263 }
1264 
1265 
1267 { meshSet = ms;
1268  if (ms->get_domain_constraint()!=NULL) domainSet = true; }
1269 
1270 ostream& operator<<( ostream& stream, const PatchData& pd )
1271 {
1272  size_t i;
1273 
1274  stream << "Vertices: " << endl;
1275  for (i = 0; i < pd.num_nodes(); ++i)
1276  {
1277  if (i == pd.num_vertices())
1278  stream << "Higher-Order Nodes: " << endl;
1279 
1280  stream << i << ". ("
1281  << pd.vertexArray[i].x() << ","
1282  << pd.vertexArray[i].y() << ","
1283  << pd.vertexArray[i].z()
1284  << ") ";
1285  if (pd.vertexArray[i].is_flag_set( MsqVertex::MSQ_SOFT_FIXED ))
1286  stream << "S";
1287  if (pd.vertexArray[i].is_flag_set( MsqVertex::MSQ_HARD_FIXED ))
1288  stream << "H";
1289  if (pd.vertexArray[i].is_flag_set( MsqVertex::MSQ_COORDS_CHANGED ))
1290  stream << "C";
1291 
1292  if (pd.vertAdjacencyArray.size())
1293  {
1294  size_t j = pd.vertAdjacencyOffsets[i];
1295  size_t end = pd.vertAdjacencyOffsets[i+1];
1296  for ( ; j < end; ++j )
1297  stream << " " << pd.vertAdjacencyArray[j];
1298  }
1299 
1300  stream << endl;
1301  }
1302 
1303  stream << "Elements: " << endl;
1304  for (i = 0; i < pd.num_elements(); ++i)
1305  {
1306  stream << i << ". ";
1307  switch (pd.elementArray[i].get_element_type()) {
1308  case POLYGON: stream << "Polygon"; break;
1309  case TRIANGLE: stream << "Tri"; break;
1310  case QUADRILATERAL: stream << "Quad"; break;
1311  case POLYHEDRON: stream << "Polyhedron"; break;
1312  case TETRAHEDRON: stream << "Tet"; break;
1313  case HEXAHEDRON: stream << "Hex"; break;
1314  case PRISM: stream << "Wedge"; break;
1315  case PYRAMID: stream << "Pyr"; break;
1316  default: stream << "Unknown"; break;
1317  }
1318  stream << pd.elementArray[i].node_count() << ": ";
1319  for (size_t j = 0; j < pd.elementArray[i].node_count(); ++j)
1320  stream << pd.elementArray[i].get_vertex_index_array()[j] << " ";
1321  stream << endl;
1322  }
1323  stream << endl;
1324 
1325  stream << "MeshSet: " << (pd.meshSet?"yes":"no") << endl;
1326  stream << "domainSet: " << (pd.domainSet?"true":"false") << endl;
1327  stream << "mType: " << (pd.mType==PatchData::VERTICES_ON_VERTEX_PATCH?"vert-on-vert":
1328  pd.mType==PatchData::ELEMENTS_ON_VERTEX_PATCH?"elem-on-vert":
1329  pd.mType==PatchData::GLOBAL_PATCH?"global":"unknown") << endl;
1330 
1331  if (pd.haveComputedInfos)
1332  {
1333  stream << "ComputedInfos:" << endl;
1335  stream << "\t MIN_UNSINGED_AREA = " << pd.computedInfos[PatchData::MIN_UNSIGNED_AREA] << endl;
1337  stream << "\t MAX_UNSIGNED_AREA = " << pd.computedInfos[PatchData::MAX_UNSIGNED_AREA] << endl;
1339  stream << "\t MIN_EDGE_LENGTH = " << pd.computedInfos[PatchData::MIN_EDGE_LENGTH] << endl;
1341  stream << "\t MAX_EDGE_LENGTH = " << pd.computedInfos[PatchData::MAX_EDGE_LENGTH] << endl;
1343  stream << "\t MINMAX_SIGNED_DET2D = " << pd.computedInfos[PatchData::MINMAX_SIGNED_DET2D] << endl;
1345  stream << "\t MINMAX_SIGNED_DET3D = " << pd.computedInfos[PatchData::MINMAX_SIGNED_DET3D] << endl;
1347  stream << "\t AVERAGE_DET3D = " << pd.computedInfos[PatchData::AVERAGE_DET3D] << endl;
1348  }
1349 
1350  return stream << endl;
1351 }
1352 
1353 
1354 void PatchData::initialize_data( size_t* elem_offset_array, MsqError& err )
1355 {
1356  if (numCornerVertices)
1357  {
1359  return;
1360  }
1361 
1362  // Clear out data specific to patch
1363  clear_tag_data();
1364  if (domainHint != PLANAR_DOMAIN)
1365  vertexNormals.clear();
1366 
1367  // Clear any vertex->element adjacency data. It
1368  // is probably invalid, and certainly will be by the time
1369  // this function completes if the mesh contains higher-order
1370  // elements.
1373 
1374  // Initialize connectivity data in each element
1375  size_t i, j;
1376  bool higher_order = false;
1377  for (i = 0; i < elementArray.size(); ++i)
1378  {
1379  size_t start = elem_offset_array[i];
1380  size_t conn_len = elem_offset_array[i+1] - start;
1381  assert(conn_len > 0);
1382  elementArray[i].set_connectivity( &elemConnectivityArray[start], conn_len );
1383  if (conn_len != elementArray[i].vertex_count())
1384  higher_order = true;
1385  }
1386 
1387  // If no higher-order elements, then we're done
1388  if (!higher_order)
1389  {
1390  // All nodes are corner vertices
1392  return;
1393  }
1394 
1395  // Need to move higher-order nodes to end of list.
1396 
1397  // Use vertAdjacencyOffsets array as temporary storage.
1399  size_t* vertex_index_map = &vertAdjacencyOffsets[0];
1400 
1401  // Note which are mid-nodes (1) and which are corner vertices (0)
1402  for (i = 0; i < elementArray.size(); ++i)
1403  {
1404  MsqMeshEntity& elem = elementArray[i];
1405  size_t* conn_array = elem.get_vertex_index_array();
1406  size_t num_vertices = elem.vertex_count();
1407  size_t num_nodes = elem.node_count();
1408  for (j = 0; j < num_vertices; ++j)
1409  vertex_index_map[ conn_array[j] ] = 0;
1410  for ( ; j < num_nodes; ++j)
1411  vertex_index_map[ conn_array[j] ] = 1;
1412  }
1413 
1414  // Shuffle nodes around such that all higher-order nodes
1415  // are at the end of the array.
1416  // Store new index for each node in index_map, replacing
1417  // flag value currently there for each node.
1418  i = 0;
1419  j = vertexHandlesArray.size() - 1;
1420  while (i < j)
1421  {
1422  if (!vertex_index_map[i])
1423  {
1424  // Is a corner vertex in first part of array, skip it.
1425  vertex_index_map[i] = i;
1426  ++i;
1427  }
1428  else if (vertex_index_map[j])
1429  {
1430  // Is a mid-node in latter part of array, skip it
1431  vertex_index_map[j] = j;
1432  --j;
1433  }
1434  else
1435  {
1436  // Swap mid-node from first part of array with
1437  // corner vertex from latter part of array.
1439 
1440  vertex_index_map[i] = j;
1441  vertex_index_map[j] = i;
1442  ++i;
1443  --j;
1444  }
1445  }
1446 
1447  // Finish up - set numCornerVertices to indicate
1448  // where corner vertices end and mid-nodes begin in
1449  // vertexArray, and get the handle remaining vertex
1450  // if missed in the above loop.
1451  if (i > j)
1452  {
1453  numCornerVertices = i;
1454  }
1455  else // (i == j)
1456  {
1457  if (vertex_index_map[i])
1458  numCornerVertices = i;
1459  else
1460  numCornerVertices = i+1;
1461  vertex_index_map[i] = i;
1462  }
1463 
1464  // Update element connectivity data for new vertex indices
1465  for (i = 0; i < elemConnectivityArray.size(); ++i)
1466  elemConnectivityArray[i] = vertex_index_map[elemConnectivityArray[i]];
1467 
1469 }
1470 
1471 void PatchData::allocate_storage( size_t vertex_count,
1472  size_t element_count,
1473  size_t vertex_use_count,
1474  MsqError& err )
1475 {
1476  vertexArray.resize( vertex_count );
1477  vertexHandlesArray.resize( vertex_count );
1478  elementArray.resize( element_count );
1479  elementHandlesArray.resize( element_count );
1480  elemConnectivityArray.resize( vertex_use_count );
1481  clear_tag_data();
1482  numCornerVertices = 0;
1483 }
1484 
1486 {
1487  targetMatrices.clear();
1488 }
1489 
1490 
1492 {
1493  size_t result = 0;
1494  for (unsigned i = 0; i < elementArray.size(); ++i)
1495  result += elementArray[i].vertex_count();
1496  return result;
1497 }
1498 
1499 
1500 } // namespace Mesquite
void update_mesh(MsqError &err)
Updates the underlying mesh (the Mesquite::Mesh implementation) with new node coordinates and flag va...
if(dy > dx)
msq_stdc::size_t get_vertex_index(msq_stdc::size_t vertex_in_element) const
void set_free_vertices_soft_fixed(MsqError &err)
Add a soft_fixed flag to all free vertices in the patch.
void swap(int &a, int &b)
Definition: buildface.cpp:88
#define MSQ_ERRZERO(err)
Return zero/NULL on error.
#define MSQ_DBG(flag)
Check if a debug flag is activated - evaluates to a bool.
double get_max_vertex_movement_squared(PatchDataVerticesMemento *memento, MsqError &err)
Calculates the distance each vertex has moved from its original position as defined by the PatchDataV...
size_t value()
Returns an index corresponding to a free vertex.
PatchDataMem< MsqVertex > vertexArray
void set_all_vertices_soft_free(MsqError &err)
Remove the soft_fixed flag from all vertices in the patch.
MsqVertex & vertex_by_index(size_t index)
Returns the start of the vertex-&gt;element array.
Mesquite::MeshDomain * get_domain_constraint()
Returns the domain associated with the MeshSet from which the Patch originates.
CornerTag< TargetMatrix > targetMatrices
Target matrix data.
Used to hold the error state and return it to the application.
virtual void closest_point(Mesh::EntityHandle handle, const Vector3D &position, Vector3D &closest, Vector3D &normal, MsqError &err) const =0
evaluate closest point and normal
void get_domain_normals_at_corners(size_t element_index, Vector3D normals_out[], MsqError &err)
Get surface normal at a point where the surface is the domain of an element and the point is the loca...
Vector_n max(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:354
const double MSQ_DBL_MAX
Definition: Mesquite.hpp:170
EntityHandle VertexHandle
vertex is fixed. This flag can be set on and off.
void allocate_storage(size_t vertex_count, size_t element_count, size_t vertex_use_count, MsqError &err)
Used by test code when creating a PatchData directly.
void get_vertex_element_indices(size_t vertex_index, msq_std::vector< size_t > &elem_indices, MsqError &err)
MsqMeshEntity is the Mesquite object that stores information about the elements in the mesh...
Vector3D is the object that effeciently stores information about about three-deminsional vectors...
const int MSQ_MAX_NUM_VERT_PER_ENT
Definition: Mesquite.hpp:120
void note_have_info(ComputedInfo info)
PatchDataMem< size_t > elemConnectivityArray
int num_free_vertices(MsqError &err) const
Returns the number of elements in the current patch who are free to move.
bool next()
Increments the iterator. returns false if there is no more free vertex.
double computedInfos[MAX_COMPUTED_INFO_ENUM]
static double compute_Lambda(const Matrix3D &A, MsqError &err)
Note that this function is static, i.e. it can be used independently of an object.
T norm(const NVec< DIM, T > &v)
void initialize_data(size_t *elem_offset_array, MsqError &err)
Call after filling vertex handle and connectivity arrays to finish initializing the PatchData...
void update_mesh(const PatchData &pd, MsqError &err)
Updates the coordinates in the underlying mesh with the coordinates stored in PatchData.
void get_minmax_element_unsigned_area(double &min, double &max, MsqError &err)
Returns the maximum volume or area out of all the elements in the patch This information is stored in...
void generate_vertex_to_element_data()
average corner determinant out of all elements in the patch
void get_adjacent_entities_via_n_dim(int n, size_t ent_ind, msq_std::vector< size_t > &adj_ents, MsqError &err)
Get the indices of entities attached to entity (given by ent_ind). adj_ents is filled with the indice...
void get_domain_normal_at_element(size_t elem_index, Vector3D &surf_norm, MsqError &err) const
invalid function argument passed
rational * A
Definition: vinci_lass.c:67
size_t num_elements() const
number of elements in the Patch.
NVec< 3, double > Vector3D
msq_stdc::size_t vertex_count() const
Returns the number of vertices in this element, based on its element type.
void get_subpatch(size_t center_vertex_index, PatchData &pd_to_fill, MsqError &err)
Fills a PatchData with the elements attached to a center vertex.
double get_barrier_delta(MsqError &err)
Returns delta based on the minimum and maximum corner determinant over all elements in the patch This...
#define MSQ_CHKERR(err)
Mesquite&#39;s Error Checking macro.
3*3 Matric class, row-oriented, 0-based [i][j] indexing.
bool have_computed_info(ComputedInfo info) const
#define MSQ_SETERR(err)
Macro to set error - use err.clear() to clear.
virtual void snap_to(Mesh::EntityHandle entity_handle, Vector3D &coordinate) const =0
Modifies &quot;coordinate&quot; so that it lies on the domain to which &quot;entity_handle&quot; is constrained.
minimum and maximum corner area out of all elements in the patch
blockLoc i
Definition: read.cpp:79
void snap_vertex_to_domain(size_t vertex_index, MsqError &err)
Adjust the position of the specified vertex so that it lies on its constraining domain.
void get_element_vertex_indices(size_t elem_index, msq_std::vector< size_t > &vertex_indices, MsqError &err)
void get_adjacent_vertex_indices(size_t vertex_index, msq_std::vector< size_t > &vert_indices, MsqError &err)
const NT & n
A Mesquite::Mesh is a collection of mesh elements which are composed of mesh vertices. Intermediate objects are not accessible through this interface (where intermediate objects include things like the faces of a hex, or an element&#39;s edges).
void update_cached_normals(MsqError &)
size_t num_nodes() const
Get number of nodes (vertex + higher-order nodes)
PatchDataMem< Vector3D > vertexNormals
double get_average_Lambda_3d(MsqError &err)
Returns average corner determinant over all corners in the patch This information is stored in the pa...
maximum edge length in the patch
size_t num_vertices() const
number of vertices in the patch.
PatchDataMem< size_t > vertAdjacencyOffsets
double det(const Matrix3D &A)
size_t num_corners()
number of elements corners in the Patch.
double length_squared() const
PatchDataMem< MsqMeshEntity > elementArray
void get_connected_vertices(msq_stdc::size_t vertex_index, msq_std::vector< msq_stdc::size_t > &vert_indices, MsqError &err)
Fills a vector&lt;size_t&gt; with vertices connected to the given vertex through the edges of this MsqMeshE...
void move_free_vertices_constrained(Vector3D dk[], size_t nb_vtx, double step_size, MsqError &err)
Moves free vertices and then snaps the free vertices to the domain.
Vector_n min(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:346
void set_free_vertices_constrained(PatchDataVerticesMemento *memento, Vector3D dk[], size_t nb_vtx, double step_size, MsqError &err)
j indices j
Definition: Indexing.h:6
void get_domain_normal_at_vertex(size_t vertex_index, bool normalize, Vector3D &surf_norm, MsqError &err)
NT q
vertex is always fixed. This can only be set on and never off.
EntityTopology get_element_type() const
Returns element type.
object is in an invalid state
const msq_stdc::size_t * get_vertex_index_array() const
Very efficient retrieval of vertices indexes (corresponding to the PatchData vertex array)...
void reorder()
Reorders the mesh data.
PatchDataMem< Mesh::ElementHandle > elementHandlesArray
Contains a copy of the coordinates of a PatchData.
msq_stdio::ostream & operator<<(msq_stdio::ostream &s, const Matrix3D &A)
PatchDataMem< Mesh::VertexHandle > vertexHandlesArray
#define MSQ_DBGOUT(flag)
Check debug flag and return ostream associated with flag.
const MsqMeshEntity * get_element_array(MsqError &err) const
Returns a pointer to the start of the element array.
virtual void normal_at(Mesh::EntityHandle entity_handle, Vector3D &coordinate) const =0
Returns the normal of the domain to which &quot;entity_handle&quot; is constrained.
iterates over indexes of free vetices in a PatchData.
minimum and maximum corner volume out of all elements in the patch
minimum volume or area out of all elements in the patch
size_t * get_vertex_element_adjacencies(size_t vertex_index, size_t &array_len_out, MsqError &err)
#define MSQ_ERRRTN(err)
If passed error is true, return from a void function.
maximum volume or area out of all elements in the patch
void set_all_vertices_soft_fixed(MsqError &err)
Add a soft_fixed flag to all vertices in the patch.
PatchDataMem< size_t > vertAdjacencyArray
void set_mesh_set(MeshSet *ms)
Sets the originating meshSet.
MsqVertex * vertices
array of vertices
minimum edge length in the patch
The MeshSet class stores one or more Mesquite::Mesh pointers and manages access to the mesh informati...
void get_element_vertex_coordinates(size_t elem_index, msq_std::vector< Vector3D > &coords, MsqError &err)
Get the coordinates of vertices attached to the specified element.
msq_stdc::size_t node_count() const
Return number of nodes in element (number of corner vertices + number of higher-order nodes)...
const double MSQ_MIN
Definition: Mesquite.hpp:160
unsigned num_free_nodes(MsqError &err) const