MFEM  v3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
mesquite.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
2 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
3 // reserved. See file COPYRIGHT for details.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability see http://mfem.googlecode.com.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the GNU Lesser General Public License (as published by the Free
10 // Software Foundation) version 2.1 dated February 1999.
11 
12 #ifdef MFEM_USE_MESQUITE
13 
14 #include <iostream>
15 
16 #include "../fem/fem.hpp"
17 #include "mesquite.hpp"
18 
19 namespace mfem
20 {
21 
22 using namespace std;
23 
25 {
26  if (elementData)
27  free(elementData);
28  if (vertexData)
29  free(vertexData);
30  if (defaultValue)
31  free(defaultValue);
32 }
33 
34 
35 void MesquiteMesh::MeshTags::clear()
36 {
37  for (std::vector<TagData*>::iterator iter = tagList.begin();
38  iter != tagList.end(); ++iter)
39  if (*iter)
40  delete *iter;
41 
42  tagList.clear();
43 }
44 
45 size_t MesquiteMesh::MeshTags::size_from_tag_type( Mesh::TagType type )
46 {
47  switch( type ) {
48  case Mesh::BYTE: return 1;
49  case Mesh::BOOL: return sizeof(bool);
50  case Mesh::DOUBLE: return sizeof(double);
51  case Mesh::INT: return sizeof(int);
52  case Mesh::HANDLE: return sizeof(void*);
53  case Mesh::LONG_LONG: return sizeof(long long);
54  default: assert(0); return 0;
55  }
56 }
57 
58 size_t MesquiteMesh::MeshTags::create( const std::string& name,
59  Mesh::TagType type,
60  unsigned length,
61  const void* defval,
62  MsqError& err )
63 {
64  size_t h = handle( name, err );
65  if (h)
66  {
67  MSQ_SETERR(err)(name, MsqError::TAG_ALREADY_EXISTS);
68  return 0;
69  }
70 
71  if (length == 0 || size_from_tag_type(type) == 0)
72  {
73  MSQ_SETERR(err)(MsqError::INVALID_ARG);
74  return 0;
75  }
76 
77  TagData* tag = new TagData( name, type, length );
78  h = tagList.size();
79  tagList.push_back(tag);
80 
81  if (defval)
82  {
83  tag->defaultValue = malloc( tag->desc.size );
84  memcpy( tag->defaultValue, defval, tag->desc.size );
85  }
86 
87  return h+1;
88 }
89 
90 size_t MesquiteMesh::MeshTags::create( const MfemTagDescription& desc,
91  const void* defval,
92  MsqError& err )
93 {
94  size_t h = handle( desc.name.c_str(), err );
95  if (h)
96  {
97  MSQ_SETERR(err)(desc.name.c_str(), MsqError::TAG_ALREADY_EXISTS);
98  return 0;
99  }
100 
101  err.clear();
102  if (desc.size == 0 || (desc.size % size_from_tag_type(desc.type)) != 0)
103  {
104  MSQ_SETERR(err)(MsqError::INVALID_ARG);
105  return 0;
106  }
107 
108  TagData* tag = new TagData( desc );
109  h = tagList.size();
110  tagList.push_back(tag);
111 
112  if (defval)
113  {
114  tag->defaultValue = malloc( tag->desc.size );
115  memcpy( tag->defaultValue, defval, tag->desc.size );
116  }
117 
118  return h+1;
119 }
120 
121 void MesquiteMesh::MeshTags::destroy( size_t tag_index, MsqError& err )
122 {
123  --tag_index;
124  if (tag_index >= tagList.size() || 0 == tagList[tag_index])
125  {
126  MSQ_SETERR(err)(MsqError::TAG_NOT_FOUND);
127  return ;
128  }
129 
130  delete tagList[tag_index];
131  tagList[tag_index] = 0;
132 }
133 
134 size_t MesquiteMesh::MeshTags::handle( const std::string& name, MsqError& err ) const
135 {
136  for (size_t i = 0; i < tagList.size(); ++i)
137  if (tagList[i] && tagList[i]->desc.name == name)
138  return i+1;
139 
140  return 0;
141 }
142 
143 const MesquiteMesh::MfemTagDescription& MesquiteMesh::MeshTags::properties( size_t tag_index, MsqError& err ) const
144 {
145  static MfemTagDescription dummy_desc;
146  --tag_index;
147 
148  if (tag_index >= tagList.size() || !tagList[tag_index])
149  {
150  MSQ_SETERR(err)("Invalid tag handle", MsqError::INVALID_ARG);
151  return dummy_desc;
152  }
153 
154  return tagList[tag_index]->desc;
155 }
156 
157 
158 void MesquiteMesh::MeshTags::set_element_data( size_t tag_index,
159  size_t num_indices,
160  const size_t* index_array,
161  const void* values,
162  MsqError& err )
163 {
164  size_t i;
165  char* data;
166  --tag_index;
167  if (tag_index >= tagList.size() || !tagList[tag_index])
168  {
169  MSQ_SETERR(err)("Invalid tag handle", MsqError::INVALID_ARG);
170  return;
171  }
172 
173  TagData* tag = tagList[tag_index];
174 
175  // Get highest element index
176  size_t total = tag->elementCount;
177  for (i = 0; i < num_indices; ++i)
178  if (index_array[i] >= total)
179  total = index_array[i] + 1;
180 
181  // If need more space
182  if (total > tag->elementCount)
183  {
184  // allocate more space
185  tag->elementData = realloc( tag->elementData, tag->desc.size * total );
186  // if a default value, initialize new space with it
187  if (tag->defaultValue)
188  {
189  data = ((char*)tag->elementData) + tag->elementCount * tag->desc.size;
190  for (i = tag->elementCount; i < total; ++i)
191  {
192  memcpy( data, tag->defaultValue, tag->desc.size );
193  data += tag->desc.size;
194  }
195  }
196  else
197  {
198  memset( (char*)tag->elementData + tag->elementCount * tag->desc.size, 0,
199  (total - tag->elementCount) * tag->desc.size );
200  }
201  tag->elementCount = total;
202  }
203 
204  // Store passed tag values
205  data = (char*)tag->elementData;
206  const char* iter = (const char*)values;
207  for (i = 0; i < num_indices; ++i)
208  {
209  memcpy( data + index_array[i]*tag->desc.size, iter, tag->desc.size );
210  iter += tag->desc.size;
211  }
212 }
213 
214 void MesquiteMesh::MeshTags::get_element_data( size_t tag_index,
215  size_t num_indices,
216  const size_t* index_array,
217  void* values,
218  MsqError& err ) const
219 {
220  --tag_index;
221  if (tag_index >= tagList.size() || !tagList[tag_index])
222  {
223  MSQ_SETERR(err)("Invalid tag handle", MsqError::INVALID_ARG);
224  return;
225  }
226 
227  TagData* tag = tagList[tag_index];
228 
229  char* iter = (char*)values;
230  const char* data = (const char*)tag->elementData;
231 
232  for (size_t i = 0; i < num_indices; ++i)
233  {
234  const void* ptr;
235  size_t index = index_array[i];
236  if (index >= tag->elementCount)
237  {
238  ptr = tag->defaultValue;
239  if (!ptr)
240  {
241  MSQ_SETERR(err)(MsqError::TAG_NOT_FOUND);
242  return;
243  }
244  }
245  else
246  {
247  ptr = data + index * tag->desc.size;
248  }
249 
250  memcpy( iter, ptr, tag->desc.size );
251  iter += tag->desc.size;
252  }
253 }
254 
255 void MesquiteMesh::MeshTags::set_vertex_data( size_t tag_index,
256  size_t num_indices,
257  const size_t* index_array,
258  const void* values,
259  MsqError& err )
260 {
261  size_t i;
262  char* data;
263  --tag_index;
264  if (tag_index >= tagList.size() || !tagList[tag_index])
265  {
266  MSQ_SETERR(err)("Invalid tag handle", MsqError::INVALID_ARG);
267  return;
268  }
269 
270  TagData* tag = tagList[tag_index];
271 
272  // Get highest element index
273  size_t total = tag->vertexCount;
274  for (i = 0; i < num_indices; ++i)
275  if (index_array[i] >= total)
276  total = index_array[i] + 1;
277 
278  // If need more space
279  if (total > tag->vertexCount)
280  {
281  // allocate more space
282  tag->vertexData = realloc( tag->vertexData, tag->desc.size * total );
283  // if a default value, initialize new space with it
284  if (tag->defaultValue)
285  {
286  data = ((char*)tag->vertexData) + tag->vertexCount * tag->desc.size;
287  for (i = tag->vertexCount; i < total; ++i)
288  {
289  memcpy( data, tag->defaultValue, tag->desc.size );
290  data += tag->desc.size;
291  }
292  }
293  else
294  {
295  memset( (char*)tag->vertexData + tag->vertexCount * tag->desc.size, 0,
296  (total - tag->vertexCount) * tag->desc.size );
297  }
298  tag->vertexCount = total;
299  }
300 
301  // Store passed tag values
302  data = (char*)tag->vertexData;
303  const char* iter = (const char*)values;
304  for (i = 0; i < num_indices; ++i)
305  {
306  memcpy( data + index_array[i]*tag->desc.size, iter, tag->desc.size );
307  iter += tag->desc.size;
308  }
309 }
310 
311 void MesquiteMesh::MeshTags::get_vertex_data( size_t tag_index,
312  size_t num_indices,
313  const size_t* index_array,
314  void* values,
315  MsqError& err ) const
316 {
317  --tag_index;
318  if (tag_index >= tagList.size() || !tagList[tag_index])
319  {
320  MSQ_SETERR(err)("Invalid tag handle", MsqError::INVALID_ARG);
321  return;
322  }
323 
324  TagData* tag = tagList[tag_index];
325 
326  char* iter = (char*)values;
327  const char* data = (const char*)tag->vertexData;
328 
329  for (size_t i = 0; i < num_indices; ++i)
330  {
331  const void* ptr;
332  size_t index = index_array[i];
333  if (index >= tag->vertexCount)
334  {
335  ptr = tag->defaultValue;
336  if (!ptr)
337  {
338  MSQ_SETERR(err)(MsqError::TAG_NOT_FOUND);
339  return;
340  }
341  }
342  else
343  {
344  ptr = data + index * tag->desc.size;
345  }
346 
347  memcpy( iter, ptr, tag->desc.size );
348  iter += tag->desc.size;
349  }
350 }
351 
352 bool MesquiteMesh::MeshTags::tag_has_vertex_data( size_t tag_index, MsqError& err )
353 {
354  --tag_index;
355  if (tag_index >= tagList.size() || !tagList[tag_index])
356  {
357  MSQ_SETERR(err)("Invalid tag handle", MsqError::INVALID_ARG);
358  return false;
359  }
360 
361  TagData* tag = tagList[tag_index];
362  return 0 != tag->vertexData || tag->defaultValue;
363 }
364 
365 bool MesquiteMesh::MeshTags::tag_has_element_data( size_t tag_index, MsqError& err )
366 {
367  --tag_index;
368  if (tag_index >= tagList.size() || !tagList[tag_index])
369  {
370  MSQ_SETERR(err)("Invalid tag handle", MsqError::INVALID_ARG);
371  return false;
372  }
373 
374  TagData* tag = tagList[tag_index];
375  return 0 != tag->elementData || tag->defaultValue;
376 }
377 
378 MesquiteMesh::MeshTags::TagIterator MesquiteMesh::MeshTags::tag_begin()
379 {
380  size_t index = 0;
381  while (index < tagList.size() && tagList[index] == NULL)
382  ++index;
383  return TagIterator( this, index );
384 }
385 
387 {
388  ++index;
389  while (index < tags->tagList.size() && NULL == tags->tagList[index])
390  ++index;
391  return TagIterator( tags, index );
392 }
393 
395 {
396  --index;
397  while (index < tags->tagList.size() && NULL == tags->tagList[index])
398  --index;
399  return TagIterator( tags, index );
400 }
401 
403 {
404  size_t old = index;
405  ++index;
406  while (index < tags->tagList.size() && NULL == tags->tagList[index])
407  ++index;
408  return TagIterator( tags, old );
409 }
410 
412 {
413  size_t old = index;
414  --index;
415  while (index < tags->tagList.size() && NULL == tags->tagList[index])
416  --index;
417  return TagIterator( tags, old );
418 }
419 
420 //
421 // MesquiteMesh implementation follows
422 //
424  : myTags( new MeshTags )
425 {
426  mesh = mfem_mesh;
427  nelems = mesh->GetNE();
428  nodes = mesh->GetNodes();
429 
430  if (nodes)
431  {
432  fes = nodes->FESpace();
433  ndofs = fes->GetNDofs();
434  fes->BuildElementToDofTable();
435  const Table *elem_dof = &fes->GetElementToDofTable();
436  dof_elem = new Table;
437  Transpose(*elem_dof, *dof_elem, ndofs);
438  }
439  else
440  {
441  ndofs = mesh->GetNV();
442  dof_elem = mesh->GetVertexToElementTable();
443  }
444 
445  mByte = vector<char>(ndofs);
446  mFixed = vector<bool>(ndofs, false);
447 
448  // By default, flag all boundary nodes as fixed
449  Array<int> bdofs;
450  for (int i = 0; i < mesh->GetNBE(); i++)
451  {
452  if (nodes)
453  fes->GetBdrElementDofs(i, bdofs);
454  else
455  mesh->GetBdrElementVertices(i, bdofs);
456  for (int j = 0; j < bdofs.Size(); j++)
457  mFixed[bdofs[j]] = true;
458  }
459 
460 }
461 
462 int MesquiteMesh::get_geometric_dimension(Mesquite::MsqError &err)
463 {
464  return mesh->Dimension();
465 }
466 
467 void MesquiteMesh::get_all_elements(std::vector<ElementHandle>& elements,
468  Mesquite::MsqError& err)
469 {
470  elements.resize(nelems);
471  for (int i = 0; i < nelems; i++)
472  elements[i] = (ElementHandle) i;
473 }
474 
475 void MesquiteMesh::get_all_vertices(std::vector<VertexHandle>& vertices,
476  Mesquite::MsqError& err)
477 {
478  vertices.resize(ndofs);
479  for (int i = 0; i < ndofs; i++)
480  vertices[i] = (VertexHandle) i;
481 }
482 
483 void MesquiteMesh::vertices_get_coordinates(const VertexHandle vert_array[],
484  MsqVertex* coordinates,
485  size_t num_vtx,
486  MsqError &err)
487 {
488 
489  const size_t *indices = (const size_t*) vert_array;
490  double coords[3];
491  for (int i = 0; i < num_vtx; i++)
492  {
493  mesh->GetNode(indices[i], coords);
494  coordinates[i].x(coords[0]);
495  coordinates[i].y(coords[1]);
496  if (mesh->Dimension() == 3 )
497  coordinates[i].z(coords[2]);
498  else
499  coordinates[i].z(0.0);
500  }
501 }
502 
503 void MesquiteMesh::vertex_set_coordinates(VertexHandle vertex,
504  const Vector3D &coordinates,
505  MsqError &err)
506 {
507  double coords[3];
508  coords[0] = coordinates.x();
509  coords[1] = coordinates.y();
510  coords[2] = coordinates.z();
511  mesh->SetNode((size_t) vertex, coords);
512 }
513 
514 void MesquiteMesh::vertex_set_byte(VertexHandle vertex,
515  unsigned char byte,
516  MsqError &err)
517 {
518  size_t index = (size_t) vertex;
519  mByte[index] = byte;
520 }
521 
522 void MesquiteMesh::vertices_set_byte(const VertexHandle *vert_array,
523  const unsigned char *byte_array,
524  size_t array_size,
525  MsqError &err)
526 {
527  const size_t* indices = (const size_t*) vert_array;
528  for (int i = 0; i < array_size; i++)
529  mByte[indices[i]] = byte_array[i];
530 }
531 
532 void MesquiteMesh::vertex_get_byte(const VertexHandle vertex,
533  unsigned char *byte,
534  MsqError &err )
535 {
536  *byte = mByte[(const size_t) vertex];
537 }
538 
539 void MesquiteMesh::vertices_get_byte(const VertexHandle *vertex,
540  unsigned char *byte_array,
541  size_t array_size,
542  MsqError &err )
543 {
544  const size_t* indices = (const size_t*) vertex;
545  for (int i = 0; i < array_size; i++)
546  byte_array[i] = mByte[indices[i]];
547 }
548 
549 void MesquiteMesh::vertices_get_fixed_flag(const VertexHandle vert_array[],
550  std::vector<bool>& fixed_flag_array,
551  size_t num_vtx,
552  MsqError &err )
553 {
554  fixed_flag_array.resize(num_vtx + 1);
555  const size_t* indices = (const size_t*) vert_array;
556  for (int i = 0; i < num_vtx; i++)
557  fixed_flag_array[i] = mFixed[indices[i]];
558 }
559 
560 void MesquiteMesh::vertices_set_fixed_flag(const VertexHandle vert_array[],
561  const std::vector< bool > &fixed_flag_array,
562  size_t num_vtx,
563  MsqError &err )
564 {
565  const size_t* indices = (const size_t*) vert_array;
566  for (int i = 0; i < num_vtx; i++)
567  mFixed[indices[i]] = fixed_flag_array[i];
568 }
569 
570 void MesquiteMesh::elements_get_attached_vertices(const ElementHandle *elem_handles,
571  size_t num_elems,
572  std::vector<VertexHandle>& vert_handles,
573  std::vector<size_t>& offsets,
574  MsqError &err)
575 {
576  const size_t* indices = (const size_t*) elem_handles;
577  vert_handles.clear();
578  offsets.resize(num_elems + 1);
579 
580  Array<int> elem_dofs;
581 
582  for (int i = 0; i < num_elems; i++)
583  {
584  offsets[i] = vert_handles.size();
585  elem = mesh->GetElement(indices[i]);
586  if (nodes)
587  fes->GetElementDofs(indices[i],elem_dofs);
588  else
589  elem->GetVertices(elem_dofs);
590 
591  for (int j = 0; j < elem_dofs.Size(); j++)
592  {
593  // Ordering of this matters!!!
594  // We are good for triangles, quads and hexes. What about tets?
595  vert_handles.push_back( (VertexHandle) elem_dofs[j] );
596  }
597  }
598  offsets[num_elems] = vert_handles.size();
599 }
600 
601 void MesquiteMesh::vertices_get_attached_elements(const VertexHandle* vertex_array,
602  size_t num_vertex,
603  std::vector<ElementHandle>& elements,
604  std::vector<size_t>& offsets,
605  MsqError& err)
606 {
607  const size_t* indices = (const size_t*) vertex_array;
608  elements.clear();
609  offsets.resize(num_vertex + 1);
610 
611  for (int i = 0; i < num_vertex; i++)
612  {
613  offsets[i] = elements.size();
614  int* vertex_elems = dof_elem->GetRow(indices[i]);
615  for (int j = 0; j < dof_elem->RowSize(indices[i]); j++)
616  elements.push_back( (ElementHandle) vertex_elems[j] );
617  }
618  offsets[num_vertex] = elements.size();
619 }
620 
621 void MesquiteMesh::elements_get_topologies(const ElementHandle *element_handle_array,
622  EntityTopology *element_topologies,
623  size_t num_elements,
624  MsqError &err)
625 {
626  // In MESQUITE:
627  // TRIANGLE = 8
628  // QUADRILATERAL = 9
629  // TETRAHEDRON = 11
630  // HEXAHEDRON = 12
631 
632  // In MFEM:
633  // POINT = 0
634  // SEGMENT = 1
635  // TRIANGLE = 2
636  // QUADRILATERAL = 3
637  // TETRAHEDRON = 4
638  // HEXAHEDRON = 5
639  // BISECTED = 6
640  // QUADRISECTED = 7
641  // OCTASECTED = 8
642 
643  int mfem_to_mesquite[9] = {0,0,8,9,11,12,0,0,0};
644  const size_t* indices = (const size_t*) element_handle_array;
645  for (int i = 0; i < num_elements; i++)
646  element_topologies[i] = (EntityTopology) mfem_to_mesquite[mesh->GetElementType(indices[i])];
647 }
648 
650 {
651  MsqPrintError err(cerr);
652  delete myTags;
653 
654  delete dof_elem;
655 }
656 
657 void
659 {
660  MsqError err;
661 
662  // create a tag for a single integer value
663  TagHandle attributeTagHandle = tag_create( "material", Mesh::INT, 1, 0, err );
664 
665  int *materialValues = new int[nelems];
666  for(int i=0;i<nelems;i++)
667  {
668  materialValues[i] = mesh->GetAttribute(i);
669  }
670 
671  //
672  // now put these values into an element tag
673  //
674  std::vector<ElementHandle> elements;
675  get_all_elements(elements, err );
676 
677  tag_set_element_data( attributeTagHandle, nelems, arrptr(elements),
678  (const void*)(materialValues), err );
679 
680  delete materialValues;
681 }
682 
683 TagHandle MesquiteMesh::tag_create( const std::string& name,
684  TagType type,
685  unsigned length,
686  const void* defval,
687  MsqError& err )
688 {
689 
690  size_t size = MeshTags::size_from_tag_type( type );
691  MfemTagDescription desc( name, type, length*size );
692  size_t index = myTags->create( desc, defval, err ); MSQ_ERRZERO(err);
693  return (TagHandle)index;
694 }
695 
696 void MesquiteMesh::tag_delete( TagHandle handle, MsqError& err )
697 {
698  myTags->destroy( (size_t)handle, err ); MSQ_CHKERR(err);
699 }
700 
701 TagHandle MesquiteMesh::tag_get( const std::string& name, MsqError& err )
702 {
703  size_t index = myTags->handle( name, err ); MSQ_ERRZERO(err);
704  if (!index)
705  MSQ_SETERR(err)( MsqError::TAG_NOT_FOUND, "could not find tag \"%s\"", name.c_str() );
706  return (TagHandle)index;
707 }
708 
709 void MesquiteMesh::tag_properties( TagHandle handle,
710  std::string& name,
711  TagType& type,
712  unsigned& length,
713  MsqError& err )
714 {
715  const MfemTagDescription& desc
716  = myTags->properties( (size_t)handle, err ); MSQ_ERRRTN(err);
717 
718  name = desc.name;
719  type = desc.type;
720  length = (unsigned)(desc.size / MeshTags::size_from_tag_type( desc.type ));
721 }
722 
723 
724 void MesquiteMesh::tag_set_element_data( TagHandle handle,
725  size_t num_elems,
726  const ElementHandle* elem_array,
727  const void* values,
728  MsqError& err )
729 {
730  myTags->set_element_data( (size_t)handle,
731  num_elems,
732  (const size_t*)elem_array,
733  values,
734  err ); MSQ_CHKERR(err);
735 }
736 
737 void MesquiteMesh::tag_get_element_data( TagHandle handle,
738  size_t num_elems,
739  const ElementHandle* elem_array,
740  void* values,
741  MsqError& err )
742 {
743  myTags->get_element_data( (size_t)handle,
744  num_elems,
745  (const size_t*)elem_array,
746  values,
747  err ); MSQ_CHKERR(err);
748 }
749 
750 void MesquiteMesh::tag_set_vertex_data( TagHandle handle,
751  size_t num_elems,
752  const VertexHandle* elem_array,
753  const void* values,
754  MsqError& err )
755 {
756  myTags->set_vertex_data( (size_t)handle,
757  num_elems,
758  (const size_t*)elem_array,
759  values,
760  err ); MSQ_CHKERR(err);
761 }
762 
763 void MesquiteMesh::tag_get_vertex_data( TagHandle handle,
764  size_t num_elems,
765  const VertexHandle* elem_array,
766  void* values,
767  MsqError& err )
768 {
769  myTags->get_vertex_data( (size_t)handle,
770  num_elems,
771  (const size_t*)elem_array,
772  values,
773  err ); MSQ_CHKERR(err);
774 }
775 
776 static void BoundaryPreservingOptimization(mfem::MesquiteMesh &mesh)
777 {
778 
779  MsqDebug::enable(1);
780  MsqPrintError err(cerr);
781 
782  int pOrder = 2;
783  int mNumInterfaceSmoothIters = 5;
784  bool mFixBndryInInterfaceSmooth = true; //this fixes exterior surface nodes
785  bool project_gradient= false;
786  double cos_crease_angle=0.2;
787 
788  // get all vertices
789  std::vector<Mesquite::Mesh::VertexHandle> vertices;
790  mesh.get_all_vertices(vertices, err);
791  if (MSQ_CHKERR(err)) {std::cout << err << std::endl; exit(EXIT_FAILURE);}
792  int num_vertices = vertices.size();
793 
794  // get application fixed vertices
795  std::vector<bool> app_fixed(num_vertices);
796 
797  mesh.vertices_get_fixed_flag(&(vertices[0]), app_fixed, num_vertices, err);
798  if (MSQ_CHKERR(err)) {std::cout << err << std::endl; exit(EXIT_FAILURE);}
799  int num_app_fixed = 0;
800 
801  for (int i = 0; i < num_vertices; i++)
802  {
803  if (app_fixed[i]) num_app_fixed++;
804  }
805 
806  std::cout << "mesh has " << num_vertices << " vertices and " << num_app_fixed << " are app fixed. ";
807 
808  // create planar domain for interior and assessor queues
809  Mesquite::PlanarDomain geom( PlanarDomain::XY );
810 
811  // tag the underlying mesh material attributes.
812  mesh.tag_attributes();
813 
814  // create boundary domain and find mesh boundary
815  Mesquite::MeshBoundaryDomain2D* mesh_domain = new Mesquite::MeshBoundaryDomain2D( MeshBoundaryDomain2D::XY, 0.0, project_gradient,
816  Mesquite::MeshBoundaryDomain2D::QUADRATIC);
817  mesh_domain->skin_area_mesh(&mesh,cos_crease_angle,"material");
818 
819  std::vector<Mesquite::Mesh::VertexHandle> theBoundaryVertices;
820  mesh_domain->get_boundary_vertices( theBoundaryVertices );
821 
822  int num_boundary_vertices = theBoundaryVertices.size();
823 
824  std::vector<Mesquite::Mesh::VertexHandle> theBoundaryEdges;
825  mesh_domain->get_boundary_edges( theBoundaryEdges );
826 
827  // int num_boundary_edges = theBoundaryEdges.size();
828  std::vector<bool> fixed_flags_boundary(num_boundary_vertices);
829 
830  // get application fixed boundary vertices
831  std::vector<bool> app_fixed_boundary(num_boundary_vertices);
832  mesh.vertices_get_fixed_flag(&(theBoundaryVertices[0]),app_fixed_boundary,num_boundary_vertices, err);
833 
834  int num_app_fixed_boundary = 0;
835  for (int i = 0; i < num_boundary_vertices; i++)
836  {
837  if (app_fixed_boundary[i]) num_app_fixed_boundary++;
838  }
839 
840  std::cout << "mesh has " << num_boundary_vertices << " boundary vertices and " << num_app_fixed_boundary << " are app fixed" << std::endl;
841 
842 
843  // only fix boundary vertices along corners
844  int num_fixed_boundary_flags = 0;
845 
846  std::vector<Mesquite::Mesh::VertexHandle> theCornerVertices;
847  mesh_domain->get_corner_vertices( theCornerVertices );
848 
849 
850  // fix only vertices that are classified as corners
851  for (int i = 0; i < num_boundary_vertices; i++)
852  {
853  if (!mFixBndryInInterfaceSmooth)
854  fixed_flags_boundary[i] = false;
855  else
856  fixed_flags_boundary[i] = app_fixed_boundary[i];
857 
858  for (int j = 0; j < theCornerVertices.size(); j++)
859  {
860  // printf("theCornerVertices[%d]=%lu\n",j, (size_t)(theCornerVertices[j]));
861  if (theCornerVertices[j] == theBoundaryVertices[i])
862  {
863  fixed_flags_boundary[i] = true;
864  num_fixed_boundary_flags++;
865  break;
866  }
867  }
868  }
869  printf("fixed %d of %d boundary vertices (those classified corner)\n", num_fixed_boundary_flags, num_boundary_vertices);
870 
871 
872  // creates three intruction queues
873  Mesquite::InstructionQueue boundary_queue;
874  Mesquite::InstructionQueue interior_queue;
875 
876 
877  boundary_queue.set_slaved_ho_node_mode(Settings::SLAVE_ALL);
878  interior_queue.set_slaved_ho_node_mode(Settings::SLAVE_ALL);
879 
880  TShapeB1 targetMetric;
881 
882  IdealShapeTarget tc;
883 
884  TQualityMetric metric( &tc, &targetMetric );
885 
886  Mesquite::LPtoPTemplate* obj_func = new Mesquite::LPtoPTemplate(&metric, pOrder, err);
887  if (MSQ_CHKERR(err)) {std::cout << err << std::endl; exit(EXIT_FAILURE);}
888 
889  Mesquite::QuasiNewton* boundary_alg = new Mesquite::QuasiNewton( obj_func);
890  boundary_alg->use_element_on_vertex_patch();
891 
892  Mesquite::QuasiNewton* interior_alg = new Mesquite::QuasiNewton( obj_func );
893  interior_alg->use_global_patch();
894 
895  // **************Set stopping criterion**************
896  double grad_norm = 1e-5;
897  double successiveEps = 1e-5;
898  int boundary_outer = 5;
899  int boundary_inner = 3;
900 
901  // for boundary
902  Mesquite::TerminationCriterion* boundaryTermInner = new Mesquite::TerminationCriterion();
903  Mesquite::TerminationCriterion* boundaryTermOuter = new Mesquite::TerminationCriterion();
904  // boundaryTermInner->add_absolute_gradient_L2_norm(grad_norm);
905  // boundaryTermInner->add_relative_successive_improvement(successiveEps);
906  boundaryTermOuter->add_relative_successive_improvement(successiveEps);
907  boundaryTermOuter->add_iteration_limit(boundary_outer);
908  boundaryTermInner->add_iteration_limit(boundary_inner);
909 
910  ostringstream bndryStream;
911  bndryStream<<"boundary_"<<targetMetric.get_name()<<"_p"<<pOrder;
912  boundaryTermOuter->write_mesh_steps(bndryStream.str().c_str());
913  boundary_alg->set_outer_termination_criterion(boundaryTermOuter);
914  boundary_alg->set_inner_termination_criterion(boundaryTermInner);
915 
916  // for interior
917  Mesquite::TerminationCriterion* interiorTermInner = new Mesquite::TerminationCriterion();
918  Mesquite::TerminationCriterion* interiorTermOuter = new Mesquite::TerminationCriterion();
919  interiorTermInner->add_absolute_gradient_L2_norm(grad_norm);
920  interiorTermInner->add_relative_successive_improvement(successiveEps);
921  // interiorTermInner->add_iteration_limit(3); // for element_on_vertex_patch mode
922  interiorTermInner->add_iteration_limit(100); // for global_patch mode
923 
924  ostringstream interiorStream;
925  interiorStream<<"interior_"<<targetMetric.get_name()<<"_p"<<pOrder;
926  interiorTermOuter->write_mesh_steps(interiorStream.str().c_str());
927  interiorTermOuter->add_iteration_limit(1);
928  interior_alg->set_outer_termination_criterion(interiorTermOuter);
929  interior_alg->set_inner_termination_criterion(interiorTermInner);
930 
931  // ConditionNumberQualityMetric qm_metric;
932  // QualityAssessor boundary_assessor,interior_assessor;
933 
934  // boundary_assessor.add_quality_assessment( &metric, 10 );
935  // boundary_assessor.add_quality_assessment( &qm_metric );
936 
937  // interior_assessor.add_quality_assessment( &metric, 10 );
938  // interior_assessor.add_quality_assessment( &qm_metric );
939 
940 
941  // set the boundary instruction queue
942  // boundary_queue.add_quality_assessor( &boundary_assessor, err );
943  boundary_queue.set_master_quality_improver(boundary_alg, err);
944  // boundary_queue.add_quality_assessor( &boundary_assessor, err );
945  if (MSQ_CHKERR(err)) {std::cout << err << std::endl; exit(EXIT_FAILURE);}
946 
947  // set the interior instruction queue
948  // interior_queue.add_quality_assessor( &interior_assessor, err );
949  interior_queue.set_master_quality_improver(interior_alg, err);
950  // interior_queue.add_quality_assessor( &interior_assessor, err );
951  if (MSQ_CHKERR(err)) {std::cout << err << std::endl; exit(EXIT_FAILURE);}
952 
953  err.clear();
954 
955  std::vector<bool> fixed_flags(num_vertices);
956 
957  for (int j=0; j<mNumInterfaceSmoothIters; j++) {
958 
959  cout<<" Boundary + Interior smoothing pass "<< j<<"....."<<endl;
960 
961  // smooth boundary only
962  for (int i = 0; i < num_vertices; i++) fixed_flags[i] = true;
963  mesh.vertices_set_fixed_flag(&(vertices[0]),fixed_flags,num_vertices, err);
964  if (MSQ_CHKERR(err)) {std::cout << err << std::endl; exit(EXIT_FAILURE);}
965 
966  mesh.vertices_set_fixed_flag(&(theBoundaryVertices[0]),fixed_flags_boundary,num_boundary_vertices, err);
967  if (MSQ_CHKERR(err)) {std::cout << err << std::endl; exit(EXIT_FAILURE);}
968 
969  // -----------------------------------------------------
970  // debug
971  //
972  mesh.vertices_get_fixed_flag(&(vertices[0]),fixed_flags,num_vertices, err);
973  if (MSQ_CHKERR(err)) {std::cout << err << std::endl; exit(EXIT_FAILURE);}
974  int num_fixed = 0;
975  for (int i = 0; i < num_vertices; i++)
976  {
977  if (fixed_flags[i]) num_fixed++;
978  }
979 
980  std::cout << " For Boundary smooth, mesh has " << num_vertices << " vertices and " << num_fixed << " are fixed. "<<endl;
981  //
982  // debug
983  // -----------------------------------------------------
984 
985 
986  boundary_queue.run_instructions(&mesh, mesh_domain, err);
987  if (MSQ_CHKERR(err)) {std::cout << err << std::endl; exit(EXIT_FAILURE);}
988  cout<<" boundary smooth completed in "<<boundaryTermOuter->get_iteration_count()<<" outer and "<<boundaryTermInner->get_iteration_count()<<" inner iterations."<<endl;
989 
990 
991  // smooth interior only
992 
993  if (!mFixBndryInInterfaceSmooth)
994  {
995  //
996  // let all interior vertices float during the interior smooth.
997  //
998  for (int i = 0; i < num_vertices; i++) fixed_flags[i] = false;
999  mesh.vertices_set_fixed_flag(&(vertices[0]),fixed_flags,num_vertices, err);
1000  }
1001  else
1002  {
1003  //
1004  // use the app_fixed settings for the fixed state of boundary vertices.
1005  //
1006  mesh.vertices_set_fixed_flag(&(vertices[0]),app_fixed,num_vertices, err);
1007  }
1008  if (MSQ_CHKERR(err)) {std::cout << err << std::endl; exit(EXIT_FAILURE);}
1009  for (int i = 0; i < num_boundary_vertices; i++) fixed_flags[i] = true;
1010 
1011  mesh.vertices_set_fixed_flag(&(theBoundaryVertices[0]),fixed_flags,num_boundary_vertices, err);
1012  if (MSQ_CHKERR(err)) {std::cout << err << std::endl; exit(EXIT_FAILURE);}
1013 
1014  // -----------------------------------------------------
1015  // debug
1016  //
1017  mesh.vertices_get_fixed_flag(&(vertices[0]),fixed_flags,num_vertices, err);
1018  if (MSQ_CHKERR(err)) {std::cout << err << std::endl; exit(EXIT_FAILURE);}
1019  num_fixed = 0;
1020  for (int i = 0; i < num_vertices; i++)
1021  {
1022  if (fixed_flags[i]) num_fixed++;
1023  }
1024 
1025  std::cout << " For Interior smooth, mesh has " << num_vertices << " vertices and " << num_fixed << " are fixed. "<<endl;
1026  //
1027  // debug
1028  // -----------------------------------------------------
1029 
1030  interior_queue.run_instructions(&mesh, &geom, err);
1031  if (MSQ_CHKERR(err)) {std::cout << err << std::endl; exit(EXIT_FAILURE);}
1032  cout<<" interior smooth completed in "<<interiorTermOuter->get_iteration_count()<<" outer and "<<interiorTermInner->get_iteration_count()<<" inner iterations."<<endl;
1033 
1034  }
1035 
1036 
1037  delete mesh_domain;
1038  delete interiorTermOuter;
1039  delete interiorTermInner;
1040  delete boundaryTermOuter;
1041  delete boundaryTermInner;
1042  delete interior_alg;
1043  delete boundary_alg;
1044  delete obj_func;
1045 
1046 }
1047 
1048 
1049 // Implementation of Mesh::MesquiteSmooth method
1050 
1051 void mfem::Mesh::MesquiteSmooth(const int mesquite_option)
1052 {
1053  mfem::MesquiteMesh msq_mesh(this);
1054  MsqDebug::enable(1);
1055  MsqPrintError err(cerr);
1056 
1057  Wrapper *method;
1058 
1059  const double vert_move_tol = 1e-3;
1060 
1061  switch (mesquite_option)
1062  {
1063  case 0: method = new LaplaceWrapper(); break;
1064  case 1: method = new UntangleWrapper(); break;
1065  case 2: method = new ShapeImprover(); break;
1066  case 3: method = new PaverMinEdgeLengthWrapper(vert_move_tol); break;
1067  }
1068 
1069  if( mesquite_option < 4 )
1070  {
1071  // Specify SLAVE_NONE for high order node positions
1072  method->set_slaved_ho_node_mode(Settings::SLAVE_NONE);
1073 
1074  if( this->Dimension() == 3 )
1075  method->run_instructions(&msq_mesh, err);
1076  else
1077  {
1078  Vector3D normal(0,0,1);
1079  Vector3D point(0,0,0);
1080  PlanarDomain mesh_plane(normal, point);
1081 
1082  method->run_instructions(&msq_mesh, &mesh_plane, err);
1083  }
1084  }
1085  else
1086  {
1087  // boundary perserving smoothing doesn't have a wrapper yet.
1088  BoundaryPreservingOptimization( msq_mesh );
1089  }
1090 }
1091 
1092 }
1093 
1094 #endif
void vertices_set_byte(const VertexHandle *vert_array, const unsigned char *byte_array, size_t array_size, MsqError &err)
Definition: mesquite.cpp:522
void get_all_vertices(std::vector< VertexHandle > &vertices, MsqError &err)
Definition: mesquite.cpp:475
void vertices_set_fixed_flag(const VertexHandle vert_array[], const std::vector< bool > &fixed_flag_array, size_t num_vtx, MsqError &err)
Definition: mesquite.cpp:560
TagHandle tag_create(const std::string &tag_name, TagType type, unsigned length, const void *default_value, MsqError &err)
Definition: mesquite.cpp:683
void vertex_set_coordinates(VertexHandle vertex, const Vector3D &coordinates, MsqError &err)
Definition: mesquite.cpp:503
int Size() const
Logical size of the array.
Definition: array.hpp:108
int GetNDofs() const
Returns number of degrees of freedom.
Definition: fespace.hpp:149
virtual void GetVertices(Array< int > &v) const =0
Returns element&#39;s vertices.
int GetNBE() const
Returns number of boundary elements.
Definition: mesh.hpp:399
MesquiteMesh(mfem::Mesh *mfem_mesh)
Definition: mesquite.cpp:423
void GetRow(int i, Array< int > &row) const
Return row i in array row (the Table must be finalized)
Definition: table.cpp:148
void tag_get_element_data(TagHandle handle, size_t num_elems, const ElementHandle *elem_array, void *tag_data, MsqError &err)
Definition: mesquite.cpp:737
int GetNE() const
Returns number of elements.
Definition: mesh.hpp:396
void get_all_elements(std::vector< ElementHandle > &elements, MsqError &err)
Definition: mesquite.cpp:467
void vertices_get_coordinates(const VertexHandle vert_array[], MsqVertex *coordinates, size_t num_vtx, MsqError &err)
Definition: mesquite.cpp:483
void tag_properties(TagHandle handle, std::string &name_out, TagType &type_out, unsigned &length_out, MsqError &err)
Definition: mesquite.cpp:709
void vertex_set_byte(VertexHandle vertex, unsigned char byte, MsqError &err)
Definition: mesquite.cpp:514
void MesquiteSmooth(const int mesquite_option=0)
Definition: mesquite.cpp:1051
void vertices_get_attached_elements(const VertexHandle *vertex_array, size_t num_vertex, std::vector< ElementHandle > &elements, std::vector< size_t > &offsets, MsqError &err)
Definition: mesquite.cpp:601
void tag_get_vertex_data(TagHandle handle, size_t num_elems, const VertexHandle *node_array, void *tag_data, MsqError &err)
Definition: mesquite.cpp:763
void vertices_get_fixed_flag(const VertexHandle vert_array[], std::vector< bool > &fixed_flag_array, size_t num_vtx, MsqError &err)
Definition: mesquite.cpp:549
virtual void GetElementDofs(int i, Array< int > &dofs) const
Returns indexes of degrees of freedom in array dofs for i&#39;th element.
Definition: fespace.cpp:739
void tag_set_vertex_data(TagHandle handle, size_t num_elems, const VertexHandle *node_array, const void *tag_data, MsqError &err)
Definition: mesquite.cpp:750
void tag_delete(TagHandle handle, MsqError &err)
Definition: mesquite.cpp:696
void Transpose(const Table &A, Table &At, int _ncols_A)
Transpose a Table.
Definition: table.cpp:305
int GetElementType(int i) const
Returns the type of element i.
Definition: mesh.cpp:3632
const Element * GetElement(int i) const
Definition: mesh.hpp:424
FiniteElementSpace * FESpace()
Definition: gridfunc.hpp:246
int Dimension() const
Definition: mesh.hpp:417
void vertices_get_byte(const VertexHandle *vertex, unsigned char *byte_array, size_t array_size, MsqError &err)
Definition: mesquite.cpp:539
virtual void GetBdrElementDofs(int i, Array< int > &dofs) const
Returns indexes of degrees of freedom for i&#39;th boundary element.
Definition: fespace.cpp:825
int GetNV() const
Definition: mesh.hpp:393
void GetBdrElementVertices(int i, Array< int > &dofs) const
Returns the indices of the dofs of boundary element i.
Definition: mesh.hpp:447
void vertex_get_byte(const VertexHandle vertex, unsigned char *byte, MsqError &err)
Definition: mesquite.cpp:532
void elements_get_topologies(const ElementHandle *element_handle_array, EntityTopology *element_topologies, size_t num_elements, MsqError &err)
Definition: mesquite.cpp:621
void GetNodes(Vector &node_coord) const
Definition: mesh.cpp:4948
void SetNode(int i, const double *coord)
Definition: mesh.cpp:4924
void GetNode(int i, double *coord)
Definition: mesh.cpp:4909
const Table & GetElementToDofTable() const
Definition: fespace.hpp:257
int RowSize(int i) const
Definition: table.hpp:82
TagHandle tag_get(const std::string &name, MsqError &err)
Definition: mesquite.cpp:701
void tag_set_element_data(TagHandle handle, size_t num_elems, const ElementHandle *elem_array, const void *tag_data, MsqError &err)
Definition: mesquite.cpp:724
int GetAttribute(int i) const
Return the attribute of element i.
Definition: mesh.hpp:583
void elements_get_attached_vertices(const ElementHandle *elem_handles, size_t num_elems, std::vector< VertexHandle > &vert_handles, std::vector< size_t > &offsets, MsqError &err)
Definition: mesquite.cpp:570
int get_geometric_dimension(MsqError &err)
Definition: mesquite.cpp:462
Table * GetVertexToElementTable()
The returned Table must be destroyed by the caller.
Definition: mesh.cpp:3475