v0.14.0
CutMeshInterface.cpp
Go to the documentation of this file.
1 /** \file CutMeshInterface.cpp
2  * \brief Cut mesh by surface
3  */
4 
5 
6 
7 #define CutMeshFunctionBegin \
8  MoFEMFunctionBegin; \
9  MOFEM_LOG_CHANNEL("WORLD"); \
10  MOFEM_LOG_FUNCTION(); \
11  MOFEM_LOG_TAG("WORLD", "CutMesh");
12 
13 namespace MoFEM {
14 
16 CutMeshInterface::query_interface(boost::typeindex::type_index type_index,
17  UnknownInterface **iface) const {
19  *iface = const_cast<CutMeshInterface *>(this);
21 }
22 
24  : cOre(const_cast<Core &>(core)) {
25  lineSearchSteps = 10;
26  nbMaxMergingCycles = 200;
28 }
29 
32  treeSurfPtr.reset();
34 }
35 
38  fRont = front;
40 }
41 
44  sUrface = surface;
46 }
47 
49  double *shift, double *origin,
50  double *transform,
51  const std::string save_mesh) {
52  CoreInterface &m_field = cOre;
53  moab::Interface &moab = m_field.get_moab();
55  sUrface.clear();
56  std::map<EntityHandle, EntityHandle> verts_map;
57  for (Range::const_iterator tit = surface.begin(); tit != surface.end();
58  tit++) {
59  int num_nodes;
60  const EntityHandle *conn;
61  CHKERR moab.get_connectivity(*tit, conn, num_nodes, true);
62  MatrixDouble coords(num_nodes, 3);
63  if (th) {
64  CHKERR moab.tag_get_data(th, conn, num_nodes, &coords(0, 0));
65  } else {
66  CHKERR moab.get_coords(conn, num_nodes, &coords(0, 0));
67  }
68  EntityHandle new_verts[num_nodes];
69  for (int nn = 0; nn != num_nodes; nn++) {
70  if (verts_map.find(conn[nn]) != verts_map.end()) {
71  new_verts[nn] = verts_map[conn[nn]];
72  } else {
73  if (transform) {
74  ublas::matrix_row<MatrixDouble> mr(coords, nn);
75  if (origin) {
76  VectorAdaptor vec_origin(
77  3, ublas::shallow_array_adaptor<double>(3, origin));
78  mr = mr - vec_origin;
79  }
80  MatrixAdaptor mat_transform = MatrixAdaptor(
81  3, 3, ublas::shallow_array_adaptor<double>(9, transform));
82  mr = prod(mat_transform, mr);
83  if (origin) {
84  VectorAdaptor vec_origin(
85  3, ublas::shallow_array_adaptor<double>(3, origin));
86  mr = mr + vec_origin;
87  }
88  }
89  if (shift) {
90  ublas::matrix_row<MatrixDouble> mr(coords, nn);
91  VectorAdaptor vec_shift(
92  3, ublas::shallow_array_adaptor<double>(3, shift));
93  mr = mr + vec_shift;
94  }
95  CHKERR moab.create_vertex(&coords(nn, 0), new_verts[nn]);
96  verts_map[conn[nn]] = new_verts[nn];
97  }
98  }
99  EntityHandle ele;
100  CHKERR moab.create_element(MBTRI, new_verts, num_nodes, ele);
101  sUrface.insert(ele);
102  }
103  if (!save_mesh.empty())
104  CHKERR SaveData(m_field.get_moab())(save_mesh, sUrface);
106 }
107 
110  vOlume = volume;
112 }
113 
116  constrainSurface = surf;
118 }
119 
122  sUrface.merge(surface);
124 }
125 
128  vOlume.merge(volume);
130 }
131 
133  const double rel_tol,
134  const double abs_tol,
135  Tag th,
136  const bool debug) {
137  CoreInterface &m_field = cOre;
138  moab::Interface &moab = m_field.get_moab();
140 
141  // Get cutting surface skin
142  Skinner skin(&moab);
143  Range surface_skin;
144  CHKERR skin.find_skin(0, sUrface, false, surface_skin);
145 
146  CHKERR snapSurfaceToEdges(surface_skin, fixed_edges, rel_tol, abs_tol, th,
147  debug);
148 
150 }
151 
153  const Range fixed_edges,
154  const double rel_tol,
155  const double abs_tol,
156  Tag th, const bool debug) {
157  CoreInterface &m_field = cOre;
158  moab::Interface &moab = m_field.get_moab();
161 
162  map<EntityHandle, double> map_verts_length;
163 
164  for (auto f : surface_edges) {
165  int num_nodes;
166  const EntityHandle *conn_skin;
167  CHKERR moab.get_connectivity(f, conn_skin, num_nodes, true);
168  VectorDouble6 coords_skin(6);
169  if (th)
170  CHKERR moab.tag_get_data(th, conn_skin, num_nodes, &coords_skin[0]);
171  else
172  CHKERR moab.get_coords(conn_skin, num_nodes, &coords_skin[0]);
174  &coords_skin[0], &coords_skin[1], &coords_skin[2]);
176  &coords_skin[3], &coords_skin[4], &coords_skin[5]);
177  FTensor::Tensor1<double, 3> t_skin_delta;
178  t_skin_delta(i) = t_n1(i) - t_n0(i);
179  const double skin_edge_length = sqrt(t_skin_delta(i) * t_skin_delta(i));
180  for (int nn = 0; nn != 2; ++nn) {
181  auto it = map_verts_length.find(conn_skin[nn]);
182  if (it != map_verts_length.end())
183  it->second = std::min(it->second, skin_edge_length);
184  else
185  map_verts_length[conn_skin[nn]] = skin_edge_length;
186  }
187  }
188 
189  for (auto m : map_verts_length) {
190 
192  if (th)
193  CHKERR moab.tag_get_data(th, &m.first, 1, &t_n(0));
194  else
195  CHKERR moab.get_coords(&m.first, 1, &t_n(0));
196 
197  double min_dist = rel_tol * m.second;
198  FTensor::Tensor1<double, 3> t_min_coords;
199  CHKERR cOre.getInterface<Tools>()->findMinDistanceFromTheEdges(
200  &t_n(0), 1, fixed_edges, &min_dist, &t_min_coords(0));
201 
202  if (min_dist < rel_tol * m.second || min_dist < abs_tol) {
203  if (debug)
204  MOFEM_LOG("WORLD", Sev::noisy) << "Snap " << min_dist;
205  if (th)
206  CHKERR moab.tag_set_data(th, &m.first, 1, &t_min_coords(0));
207  else
208  CHKERR moab.set_coords(&m.first, 1, &t_min_coords(0));
209  }
210  }
211 
213 }
214 
216  CoreInterface &m_field = cOre;
217  moab::Interface &moab = m_field.get_moab();
219  treeSurfPtr = boost::shared_ptr<OrientedBoxTreeTool>(
220  new OrientedBoxTreeTool(&moab, "ROOTSETSURF", true));
223 }
224 
227  const double tol_geometry, const double tol_cut_close,
228  Range *fixed_edges, Range *corner_nodes,
229  const bool update_meshsets, const bool debug) {
230  CoreInterface &m_field = cOre;
231  moab::Interface &moab = m_field.get_moab();
233 
234  // cut mesh
236  CHKERR projectZeroDistanceEnts(fixed_edges, corner_nodes, tol_geometry,
237  tol_cut_close, QUIET, debug);
240 
241  CHKERR cOre.getInterface<BitRefManager>()->updateRangeByChildren(constrainSurface,
243  if (fixed_edges)
244  CHKERR cOre.getInterface<BitRefManager>()->updateRangeByChildren(*fixed_edges,
245  *fixed_edges);
246  if (corner_nodes)
247  CHKERR cOre.getInterface<BitRefManager>()->updateRangeByChildren(*corner_nodes,
248  *corner_nodes);
249  if (update_meshsets)
251  ->updateAllMeshsetsByEntitiesChildren(cut_bit);
253 
254  if (debug) {
256  if (fixed_edges)
257  CHKERR SaveData(moab)("out_cut_new_fixed_edges.vtk", *fixed_edges);
258  }
259 
261 }
262 
264  const double tol_trim_close,
265  Range *fixed_edges,
266  Range *corner_nodes,
267  const bool update_meshsets,
268  const bool debug) {
269  CoreInterface &m_field = cOre;
270  moab::Interface &moab = m_field.get_moab();
272 
273  // trim mesh
274  CHKERR findEdgesToTrim(fixed_edges, corner_nodes, th, tol_trim_close, debug);
275  CHKERR trimEdgesInTheMiddle(trim_bit, debug);
276 
277  CHKERR cOre.getInterface<BitRefManager>()->updateRangeByChildren(constrainSurface,
279  if (fixed_edges)
280  CHKERR cOre.getInterface<BitRefManager>()->updateRangeByChildren(*fixed_edges,
281  *fixed_edges);
282 
283  if (corner_nodes)
284  CHKERR cOre.getInterface<BitRefManager>()->updateRangeByChildren(*corner_nodes,
285  *corner_nodes);
286 
287  if (update_meshsets)
289  ->updateAllMeshsetsByEntitiesChildren(trim_bit);
290 
291  // move nodes
293 
294  // remove faces
295  CHKERR trimSurface(fixed_edges, corner_nodes, tol_trim_close, th, debug);
296 
297  if (debug) {
299  Range bit2_edges;
300  CHKERR cOre.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
301  trim_bit, BitRefLevel().set(), MBEDGE, bit2_edges);
302  CHKERR SaveData(moab)("trim_fixed_edges.vtk",
303  intersect(*fixed_edges, bit2_edges));
304  }
305 
307 }
308 
310  int &first_bit, Tag th, const double tol_geometry,
311  const double tol_cut_close, const double tol_trim_close, Range *fixed_edges,
312  Range *corner_nodes, const bool update_meshsets, const bool debug) {
313  CoreInterface &m_field = cOre;
315 
316  std::vector<BitRefLevel> bit_levels;
317 
318  auto get_back_bit_levels = [&]() {
319  bit_levels.push_back(BitRefLevel());
320  bit_levels.back().set(first_bit + bit_levels.size() - 1);
321  return bit_levels.back();
322  };
323 
324  BitRefLevel cut_bit = get_back_bit_levels();
325 
327  tol_geometry, tol_cut_close, fixed_edges, corner_nodes,
328  update_meshsets, debug);
329 
330  auto get_min_quality = [&m_field](const BitRefLevel bit, Tag th) {
331  Range tets_level; // test at level
332  CHKERR m_field.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
333  bit, BitRefLevel().set(), MBTET, tets_level);
334  double min_q = 1;
335  CHKERR m_field.getInterface<Tools>()->minTetsQuality(tets_level, min_q, th);
336  return min_q;
337  };
338 
339  MOFEM_LOG_C("WORLD", Sev::inform, "Min quality cut %6.4g",
340  get_min_quality(cut_bit, th));
341 
342  Range starting_volume = cutNewVolumes;
343  Range starting_volume_nodes;
344  CHKERR m_field.get_moab().get_connectivity(starting_volume,
345  starting_volume_nodes, true);
346  std::vector<double> staring_volume_coords(3 * starting_volume_nodes.size());
347  CHKERR m_field.get_moab().get_coords(starting_volume_nodes,
348  &*staring_volume_coords.begin());
349 
350  if (th) {
351  std::vector<double> staring_volume_th_coords(3 *
352  starting_volume_nodes.size());
353  CHKERR m_field.get_moab().tag_get_data(th, starting_volume_nodes,
354  &*staring_volume_th_coords.begin());
355  CHKERR m_field.get_moab().set_coords(starting_volume_nodes,
356  &*staring_volume_th_coords.begin());
357  }
358 
359  if (th)
361 
362  BitRefLevel trim_bit = get_back_bit_levels();
363 
364  CHKERR trimOnly(trim_bit, th, tol_trim_close, fixed_edges, corner_nodes,
365  update_meshsets, debug);
366 
367  MOFEM_LOG_C("WORLD", Sev::inform, "Min quality trim %3.2g",
368  get_min_quality(trim_bit, th));
369 
370  first_bit += bit_levels.size() - 1;
371 
372  if (th)
373  CHKERR m_field.get_moab().set_coords(starting_volume_nodes,
374  &*staring_volume_coords.begin());
375 
377 }
378 
380  int &first_bit, const int fraction_level, Tag th, const double tol_geometry,
381  const double tol_cut_close, const double tol_trim_close, Range &fixed_edges,
382  Range &corner_nodes, const bool update_meshsets, const bool debug) {
383  CoreInterface &m_field = cOre;
385 
386  std::vector<BitRefLevel> bit_levels;
387 
388  auto get_back_bit_levels = [&]() {
389  bit_levels.push_back(BitRefLevel());
390  bit_levels.back().set(first_bit + bit_levels.size() - 1);
391  return bit_levels.back();
392  };
393 
394  if (debug) {
395  CHKERR cOre.getInterface<BitRefManager>()->writeEntitiesNotInDatabase(
396  "ents_not_in_database.vtk", "VTK", "");
397  }
398 
399  CHKERR cutAndTrim(first_bit, th, tol_geometry, tol_cut_close, tol_trim_close,
400  &fixed_edges, &corner_nodes, update_meshsets, debug);
401  if (debug)
402  CHKERR cOre.getInterface<BitRefManager>()->writeEntitiesNotInDatabase(
403  "cut_trim_ents_not_in_database.vtk", "VTK", "");
404 
405  BitRefLevel bit_level1 = BitRefLevel().set(first_bit - 1);
406  BitRefLevel bit_level2 = get_back_bit_levels();
407  BitRefLevel bit_level3 = get_back_bit_levels();
408 
409  CHKERR mergeBadEdges(fraction_level, bit_level1, bit_level2, bit_level3,
410  getNewTrimSurfaces(), fixed_edges, corner_nodes, th,
411  update_meshsets, debug);
412 
413  auto get_min_quality = [&m_field, debug](const BitRefLevel bit, Tag th) {
414  Range tets_level; // test at level
415  CHKERR m_field.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
416  bit, BitRefLevel().set(), MBTET, tets_level);
417  double min_q = 1;
418  CHKERR m_field.getInterface<Tools>()->minTetsQuality(tets_level, min_q, th);
419  if (min_q < 0 && debug) {
420  CHKERR m_field.getInterface<Tools>()->writeTetsWithQuality(
421  "negative_tets.vtk", "VTK", "", tets_level, th);
422  }
423  return min_q;
424  };
425 
426  MOFEM_LOG_C("WORLD", Sev::inform, "Min quality node merge %6.4g",
427  get_min_quality(bit_level3, th));
428 
429  CHKERR cOre.getInterface<BitRefManager>()->updateRangeByChildren(constrainSurface,
431  CHKERR cOre.getInterface<BitRefManager>()->updateRangeByChildren(fixed_edges,
432  fixed_edges);
433  CHKERR cOre.getInterface<BitRefManager>()->updateRangeByChildren(corner_nodes,
434  corner_nodes);
435 
436  first_bit += bit_levels.size() - 1;
437 
438  if (debug) {
439  CHKERR cOre.getInterface<BitRefManager>()->writeBitLevelByType(
440  bit_level3, BitRefLevel().set(), MBTET, "out_tets_merged.vtk", "VTK",
441  "");
442  CHKERR cOre.getInterface<BitRefManager>()->writeEntitiesNotInDatabase(
443  "cut_trim_merge_ents_not_in_database.vtk", "VTK", "");
444  CHKERR SaveData(m_field.get_moab())("merged_surface.vtk", mergedSurfaces);
445  }
446 
448 }
449 
451  CoreInterface &m_field = cOre;
452  moab::Interface &moab = m_field.get_moab();
454  Skinner skin(&moab);
455  Range tets_skin;
456  CHKERR skin.find_skin(0, vOlume, false, tets_skin);
457  Range tets_skin_edges;
458  ErrorCode tmp_result;
459  tmp_result = moab.get_adjacencies(tets_skin, 1, false, tets_skin_edges,
460  moab::Interface::UNION);
461 
462  if (MB_SUCCESS != tmp_result)
463  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
464  "Duplicated edges: most likely the source of error is comming from "
465  "adding the vertices of the cracking "
466  "volume to a BLOCKSET rather than NODESET (corresponding to the "
467  "input parameter-vertex_block_set)");
468 
469  Range surface_skin;
470  CHKERR skin.find_skin(0, sUrface, false, surface_skin);
471  fRont = subtract(surface_skin, tets_skin_edges);
472  if (debug)
473  CHKERR SaveData(moab)("front.vtk", fRont);
475 }
476 
478  const bool debug) {
479  CoreInterface &m_field = cOre;
480  moab::Interface &moab = m_field.get_moab();
482  auto tools_interface = m_field.getInterface<Tools>();
483 
484  auto create_tag = [&](const std::string name, const int dim) {
485  Tag th;
486  rval = moab.tag_get_handle(name.c_str(), th);
487  if (rval == MB_SUCCESS)
488  return th;
489  std::vector<double> def_val(dim, 0);
490  CHKERR moab.tag_get_handle(name.c_str(), dim, MB_TYPE_DOUBLE, th,
491  MB_TAG_CREAT | MB_TAG_SPARSE, &*def_val.begin());
492 
493  return th;
494  };
495 
496  auto set_vol = [&](const Range &vol_verts, std::vector<double> &coords,
497  std::vector<double> &dist_surface_vec,
498  std::vector<double> &dist_surface_normal_vec,
499  std::vector<double> &dist_surface_signed_dist_vec) {
501 
502  coords.resize(3 * vol_verts.size());
503  dist_surface_vec.resize(3 * vol_verts.size());
504  dist_surface_normal_vec.resize(3 * vol_verts.size());
505  dist_surface_signed_dist_vec.resize(vol_verts.size());
506 
507  CHKERR moab.get_coords(vol_verts, &*coords.begin());
508  std::srand(0);
509 
510  for (auto v : vol_verts) {
511 
512  const int index = vol_verts.index(v);
513  auto point_in = getVectorAdaptor(&coords[3 * index], 3);
514  VectorDouble3 point_out(3);
515  EntityHandle facets_out;
516  CHKERR treeSurfPtr->closest_to_location(&point_in[0], rootSetSurf,
517  &point_out[0], facets_out);
518 
519  VectorDouble3 delta = point_out - point_in;
520  VectorDouble3 n_first(3);
521  CHKERR tools_interface->getTriNormal(facets_out, &*n_first.begin());
522 
523  // Check of only triangle in proximity of point out is one triangle, if is
524  // more than one, use normal of lager triangle to set orientation.
525  auto check_triangle_orientation = [&](auto n) {
526  int num_nodes;
527  const EntityHandle *conn;
528  CHKERR moab.get_connectivity(facets_out, conn, num_nodes, true);
529  MatrixDouble3by3 coords(3, 3);
530  CHKERR moab.get_coords(conn, 3, &coords(0, 0));
531  VectorDouble3 center(3);
532  center.clear();
533  for (auto ii : {0, 1, 2})
534  for (auto jj : {0, 1, 2})
535  center(jj) += coords(ii, jj) / 3;
536 
537  std::vector<EntityHandle> triangles_out;
538  std::vector<double> distance_out;
539  auto a_max = norm_2(n);
540  VectorDouble3 ray = -n / a_max;
541  VectorDouble3 pt = center - ray * sqrt(a_max);
542  const double ray_length = 2 * sqrt(a_max);
543 
544  CHKERR treeSurfPtr->ray_intersect_triangles(
545  distance_out, triangles_out, rootSetSurf,
546  std::numeric_limits<float>::epsilon(), &pt[0], &ray[0],
547  &ray_length);
548 
549  if (triangles_out.size() > 1) {
550  VectorDouble3 nt(3);
551  for (auto t : triangles_out) {
552  CHKERR tools_interface->getTriNormal(t, &*nt.begin());
553  double at = norm_2(nt);
554  if (at > a_max) {
555  n = nt;
556  a_max = at;
557  }
558  }
559  }
560 
561  return n;
562  };
563 
564  auto n = check_triangle_orientation(n_first);
565  n /= norm_2(n);
566  const double dot = inner_prod(delta, n);
567 
568 
569  if (std::abs(dot) < std::numeric_limits<double>::epsilon()) {
570  if (std::rand() % 2 == 0)
571  delta += n * std::numeric_limits<double>::epsilon();
572  else
573  delta -= n * std::numeric_limits<double>::epsilon();
574  }
575 
576  auto dist_vec = getVectorAdaptor(&dist_surface_vec[3 * index], 3);
577  noalias(dist_vec) = delta;
578 
579  auto dist_normal_vec =
580  getVectorAdaptor(&dist_surface_normal_vec[3 * index], 3);
581 
582  dist_surface_signed_dist_vec[index] = dot;
583  noalias(dist_normal_vec) = dot * n;
584  }
585 
587  };
588 
589  std::vector<double> coords;
590  std::vector<double> dist_surface_vec;
591  std::vector<double> dist_surface_normal_vec;
592  std::vector<double> dist_surface_signed_dist_vec;
593  Range vol_verts;
594  CHKERR moab.get_connectivity(vOlume, vol_verts, true);
595 
596  CHKERR set_vol(vol_verts, coords, dist_surface_vec, dist_surface_normal_vec,
597  dist_surface_signed_dist_vec);
598 
599  CHKERR moab.tag_set_data(create_tag("DIST_SURFACE_VECTOR", 3), vol_verts,
600  &*dist_surface_vec.begin());
601  CHKERR moab.tag_set_data(create_tag("DIST_SURFACE_NORMAL_VECTOR", 3),
602  vol_verts, &*dist_surface_normal_vec.begin());
603  CHKERR moab.tag_set_data(create_tag("DIST_SURFACE_NORMAL_SIGNED", 1),
604  vol_verts, &*dist_surface_signed_dist_vec.begin());
605 
607 }
608 
610  int verb,
611  const bool debug) {
612  CoreInterface &m_field = cOre;
613  moab::Interface &moab = m_field.get_moab();
615 
616  auto create_tag = [&](const std::string name, const int dim) {
617  Tag th;
618  rval = moab.tag_get_handle(name.c_str(), th);
619  if (rval == MB_SUCCESS)
620  return th;
621  std::vector<double> def_val(dim, 0);
622  CHKERR moab.tag_get_handle(name.c_str(), dim, MB_TYPE_DOUBLE, th,
623  MB_TAG_CREAT | MB_TAG_SPARSE, &*def_val.begin());
624  return th;
625  };
626 
627  Range vol_vertices;
628  CHKERR moab.get_connectivity(vol, vol_vertices, true);
629 
630  std::vector<double> min_distances_from_front(vol_vertices.size(), -1);
631  std::vector<double> points_on_edges(3 * vol_vertices.size(), 0);
632  std::vector<EntityHandle> closest_edges(vol_vertices.size(), 0);
633 
634  std::vector<double> coords(3 * vol_vertices.size());
635  if (th)
636  CHKERR moab.tag_get_data(th, vol_vertices, &*coords.begin());
637  else
638  CHKERR moab.get_coords(vol_vertices, &*coords.begin());
639 
640  CHKERR cOre.getInterface<Tools>()->findMinDistanceFromTheEdges(
641  &*coords.begin(), vol_vertices.size(), fRont,
642  &*min_distances_from_front.begin(), &*points_on_edges.begin(),
643  &*closest_edges.begin());
644 
645  if (!points_on_edges.empty()) {
646  for (int i = 0; i != min_distances_from_front.size(); ++i) {
647  Range faces;
648  CHKERR moab.get_adjacencies(&closest_edges[0], 1, 2, false, faces);
649  auto point_in = getVectorAdaptor(&coords[3 * i], 3);
650  auto point_out = getVectorAdaptor(&points_on_edges[3 * i], 3);
651  point_out -= point_in;
652  }
653  }
654 
655  auto th_dist_front_vec = create_tag("DIST_FRONT_VECTOR", 3);
656  CHKERR moab.tag_set_data(th_dist_front_vec, vol_vertices,
657  &*points_on_edges.begin());
658 
660 }
661 
663  Tag th, Range &vol_edges, const bool remove_adj_prims_edges, int verb,
664  const bool debug, const std::string edges_file_name) {
665  CoreInterface &m_field = cOre;
666  moab::Interface &moab = m_field.get_moab();
668 
669  auto get_tag_dim = [&](auto th) {
670  int dim;
671  CHKERR moab.tag_get_length(th, dim);
672  return dim;
673  };
674  auto dim = get_tag_dim(th);
675 
676  auto get_tag_data = [&](auto th, auto conn) {
677  const void *ptr;
678  CHKERR moab.tag_get_by_ptr(th, &conn, 1, &ptr);
679  return getVectorAdaptor(
680  const_cast<double *>(static_cast<const double *>(ptr)), 3);
681  };
682 
683  auto get_edge_ray = [&](auto conn) {
684  VectorDouble6 coords(6);
685  CHKERR moab.get_coords(conn, 2, &coords[0]);
686  VectorAdaptor n0 = getVectorAdaptor(&coords[0], 3);
687  VectorAdaptor n1 = getVectorAdaptor(&coords[3], 3);
688  VectorDouble3 ray = n1 - n0;
689  return ray;
690  };
691 
692  Range edges;
693  CHKERR moab.get_adjacencies(vOlume, 1, true, edges, moab::Interface::UNION);
694 
695  auto remove_prisms_edges = [&](Range &edges) {
697  Range prisms;
698  CHKERR moab.get_adjacencies(edges, 3, false, prisms,
699  moab::Interface::UNION);
700  prisms = prisms.subset_by_type(MBPRISM);
701  Range prisms_verts;
702  CHKERR moab.get_connectivity(prisms, prisms_verts, true);
703  Range prism_edges;
704  CHKERR moab.get_adjacencies(prisms_verts, 1, false, prism_edges,
705  moab::Interface::UNION);
706  edges = subtract(edges, prism_edges);
708  };
709  if (remove_adj_prims_edges)
710  CHKERR remove_prisms_edges(edges);
711 
712  std::vector<EntityHandle> cut_edges;
713  cut_edges.reserve(edges.size());
714 
715  auto get_cut_edges_vec = [&](auto th, auto &cut_edges, auto e, auto &&conn) {
717 
718  auto ray = get_edge_ray(conn);
719  const double length = norm_2(ray);
720  ray /= length;
721  const auto dist0 = get_tag_data(th, conn[0]);
722  const auto dist1 = get_tag_data(th, conn[1]);
723  const double max_dist = std::max(norm_2(dist0), norm_2(dist1));
724  if (max_dist < length) {
725  cut_edges.push_back(e);
726  }
727 
729  };
730 
731  auto get_cut_edges_signed_dist = [&](auto th, auto &cut_edges, auto e,
732  auto &&conn) {
734  auto get_tag_signed_dist = [&](auto conn) {
735  double dist;
736  CHKERR moab.tag_get_data(th, &conn, 1, &dist);
737  return dist;
738  };
739  const auto dist0 = get_tag_signed_dist(conn[0]);
740  const auto dist1 = get_tag_signed_dist(conn[1]);
741  const double opposite = dist0 * dist1;
742  if (opposite <= 0)
743  cut_edges.push_back(e);
745  };
746 
747  auto get_conn = [&](auto e) {
748  int num_nodes;
749  const EntityHandle *conn;
750  CHKERR moab.get_connectivity(e, conn, num_nodes, true);
751  return conn;
752  };
753 
754  if (dim == 3)
755  for (auto e : edges)
756  CHKERR get_cut_edges_vec(th, cut_edges, e, get_conn(e));
757  else
758  for (auto e : edges)
759  CHKERR get_cut_edges_signed_dist(th, cut_edges, e, get_conn(e));
760 
761  CHKERR moab.get_adjacencies(&*cut_edges.begin(), cut_edges.size(), 3, false,
762  vol_edges, moab::Interface::UNION);
763  vol_edges = intersect(vol_edges, vOlume);
764 
765  auto convert_to_ranger = [](auto &v) {
766  Range r;
767  r.insert_list(v.begin(), v.end());
768  return r;
769  };
770 
771  if (debug && !edges_file_name.empty())
772  CHKERR SaveData(m_field.get_moab())(edges_file_name,
773  convert_to_ranger(cut_edges));
774 
776 }
777 
779  const bool debug) {
780  CoreInterface &m_field = cOre;
781  moab::Interface &moab = m_field.get_moab();
783 
784  CHKERR createFrontLevelSets(vOlume, nullptr, verb, debug);
785  Tag th_dist_front_vec;
786  CHKERR moab.tag_get_handle("DIST_FRONT_VECTOR", th_dist_front_vec);
787  CHKERR findLevelSetVolumes(th_dist_front_vec, cutFrontVolumes, true, verb,
788  debug, "cutFrontEdges.vtk");
789 
791 
792  Tag th_dist_surface_vec;
793  CHKERR moab.tag_get_handle("DIST_SURFACE_VECTOR", th_dist_surface_vec);
794  cutSurfaceVolumes.clear();
795  CHKERR findLevelSetVolumes(th_dist_surface_vec, cutSurfaceVolumes, true, verb,
796  debug, "cutSurfaceEdges.vtk");
797 
798  if (debug)
799  CHKERR SaveData(m_field.get_moab())("level_sets.vtk", vOlume);
800  if (debug)
801  CHKERR SaveData(m_field.get_moab())("cutSurfaceVolumes.vtk",
803  if (debug)
804  CHKERR SaveData(m_field.get_moab())("cutFrontVolumes.vtk", cutFrontVolumes);
805 
807 }
808 
810  const int surf_levels,
811  const int front_levels,
812  Range *fixed_edges, int verb,
813  const bool debug) {
814  CoreInterface &m_field = cOre;
815  moab::Interface &moab = m_field.get_moab();
816  MeshRefinement *refiner;
817  BitRefManager *bit_ref_manager;
819  CHKERR m_field.getInterface(refiner);
820  CHKERR m_field.getInterface(bit_ref_manager);
821 
822  auto add_bit = [&](const int bit) {
824  CHKERR bit_ref_manager->addBitRefLevel(vOlume, BitRefLevel().set(bit),
825  verb);
826  Range adj_ents;
827  for (auto d : {2, 1, 0}) {
828  CHKERR moab.get_adjacencies(vOlume, d, true, adj_ents,
829  moab::Interface::UNION);
830  CHKERR bit_ref_manager->addBitRefLevel(adj_ents, BitRefLevel().set(bit),
831  verb);
832  }
834  };
835  CHKERR add_bit(init_bit_level);
836 
837  auto update_range = [&](Range *r_ptr) {
839  if (r_ptr) {
840  Range childs;
841  CHKERR bit_ref_manager->updateRangeByChildren(*r_ptr, childs);
842  r_ptr->merge(childs);
843  }
845  };
846 
847  auto refine = [&](const BitRefLevel bit, const Range tets) {
849  Range verts;
850  CHKERR moab.get_connectivity(tets, verts, true);
851  Range ref_edges;
852  CHKERR moab.get_adjacencies(verts, 1, true, ref_edges,
853  moab::Interface::UNION);
854 
855  CHKERR refiner->addVerticesInTheMiddleOfEdges(ref_edges, bit);
856  CHKERR refiner->refineTets(vOlume, bit, verb);
857 
858  CHKERR update_range(fixed_edges);
859  CHKERR update_range(&vOlume);
861  ->updateAllMeshsetsByEntitiesChildren(bit);
862 
863  Range bit_tets;
864  CHKERR m_field.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
865  bit, BitRefLevel().set(), MBTET, bit_tets);
866  vOlume = intersect(vOlume, bit_tets);
867 
868  Range bit_edges;
869  CHKERR m_field.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
870  bit, BitRefLevel().set(), MBEDGE, bit_edges);
871  if (fixed_edges)
872  *fixed_edges = intersect(*fixed_edges, bit_edges);
873 
875  };
876 
877  for (int ll = init_bit_level; ll != init_bit_level + surf_levels; ++ll) {
879  CHKERR refine(BitRefLevel().set(ll + 1),
881  }
882 
883  for (int ll = init_bit_level + surf_levels;
884  ll != init_bit_level + surf_levels + front_levels; ++ll) {
886  CHKERR refine(BitRefLevel().set(ll + 1), cutFrontVolumes);
887  }
888 
890 
891  if (debug)
892  CHKERR SaveData(m_field.get_moab())("refinedVolume.vtk", vOlume);
893 
895 }
896 
898  const bool debug) {
899  CoreInterface &m_field = cOre;
900  moab::Interface &moab = m_field.get_moab();
902 
903  edgesToCut.clear();
904  cutEdges.clear();
905 
906  Tag th_signed_dist;
907  CHKERR moab.tag_get_handle("DIST_SURFACE_NORMAL_SIGNED", th_signed_dist);
908 
909  auto get_tag_edge_dist = [&](auto th, auto conn) {
910  std::array<double, 2> r;
911  CHKERR moab.tag_get_data(th, conn, 2, r.data());
912  return r;
913  };
914 
915  auto get_conn = [&](const auto e) {
916  int num_nodes;
917  const EntityHandle *conn;
918  CHKERR moab.get_connectivity(e, conn, num_nodes, true);
919  return conn;
920  };
921 
922  auto get_adj = [&moab](const Range r, const int dim) {
923  Range a;
924  if (dim)
925  CHKERR moab.get_adjacencies(r, dim, false, a, moab::Interface::UNION);
926  else
927  CHKERR moab.get_connectivity(r, a, true);
928  return a;
929  };
930 
931  auto vol_edges = get_adj(vol, 1);
932 
933  aveLength = 0;
934  maxLength = 0;
935  int nb_ave_length = 0;
936  for (auto e : vol_edges) {
937 
938  auto conn = get_conn(e);
939  auto dist = get_tag_edge_dist(th_signed_dist, conn);
940  const auto dist_max = std::max(dist[0], dist[1]);
941  const auto dist_min = std::min(dist[0], dist[1]);
942  const auto dot = dist[0] * dist[1];
943 
944  VectorDouble6 coords(6);
945  CHKERR moab.get_coords(conn, 2, &coords[0]);
946  VectorAdaptor n0 = getVectorAdaptor(&coords[0], 3);
947  VectorAdaptor n1 = getVectorAdaptor(&coords[3], 3);
948  VectorDouble3 ray = n1 - n0;
949  const double ray_length = norm_2(ray);
950  ray /= ray_length;
951 
952  if (
953 
954  (dot < 0 && dist_max > std::numeric_limits<double>::epsilon()) ||
955  (std::abs(dist_min) < std::numeric_limits<double>::epsilon() &&
956  dist_max > std::numeric_limits<double>::epsilon())
957 
958  ) {
959 
960  // Edges is on two sides of the surface
961  const double s = dist[0] / (dist[0] - dist[1]);
962  const double dist = s * ray_length;
963 
964  auto add_edge = [&](auto dist) {
965  edgesToCut[e].dIst = dist;
966  edgesToCut[e].lEngth = ray_length;
967  edgesToCut[e].unitRayDir = ray;
968  edgesToCut[e].rayPoint = n0;
969  cutEdges.insert(e);
970 
971  aveLength += norm_2(ray);
972  maxLength = fmax(maxLength, norm_2(ray));
973  ++nb_ave_length;
974  };
975 
976  add_edge(dist);
977  }
978  }
979  aveLength /= nb_ave_length;
980 
981  if (debug)
982  CHKERR SaveData(m_field.get_moab())("cut_edges.vtk", cutEdges);
983 
984  if (debug)
985  CHKERR SaveData(m_field.get_moab())("cut_edges_vol.vtk",
986  get_adj(cutEdges, 3));
987 
989 }
990 
992  Range *fixed_edges, Range *corner_nodes, const double geometry_tol,
993  const double close_tol, const int verb, const bool debug) {
994  CoreInterface &m_field = cOre;
995  moab::Interface &moab = m_field.get_moab();
996  Skinner skin(&moab);
998 
999  auto get_ent_adj = [&moab](const EntityHandle v, const int dim) {
1000  Range a;
1001  if (dim)
1002  CHKERR moab.get_adjacencies(&v, 1, dim, true, a);
1003  return a;
1004  };
1005 
1006  auto get_adj = [&moab](const Range r, const int dim) {
1007  Range a;
1008  if (dim)
1009  CHKERR moab.get_adjacencies(r, dim, false, a, moab::Interface::UNION);
1010  else
1011  CHKERR moab.get_connectivity(r, a, true);
1012  return a;
1013  };
1014 
1015  auto get_skin = [&skin](const auto r) {
1016  Range s;
1017  CHKERR skin.find_skin(0, r, false, s);
1018  return s;
1019  };
1020 
1021 
1022  auto get_range = [](std::vector<EntityHandle> v) {
1023  Range r;
1024  r.insert_list(v.begin(), v.end());
1025  return r;
1026  };
1027 
1028  auto get_coords = [&](const auto v) {
1029  VectorDouble3 coords(3);
1030  CHKERR moab.get_coords(&v, 1, &coords[0]);
1031  return coords;
1032  };
1033 
1034  Tag th_normal_dist;
1035  CHKERR moab.tag_get_handle("DIST_SURFACE_NORMAL_VECTOR", th_normal_dist);
1036 
1037  auto get_normal_dits = [&](const EntityHandle v) {
1038  VectorDouble3 dist_vec(3);
1039  CHKERR moab.tag_get_data(th_normal_dist, &v, 1, &*dist_vec.begin());
1040  return dist_vec;
1041  };
1042 
1043  auto get_prj_point = [&](const EntityHandle v, const Range edges,
1044  const double geometry_tol) {
1045  auto get_tuple = [](const EntityHandle e, const double dist,
1046  const double l) { return std::make_tuple(e, dist, l); };
1047 
1048  std::tuple<EntityHandle, double, double> min_tuple{0, 0, 0};
1049 
1050  for (auto e : edges) {
1051  auto eit = edgesToCut.find(e);
1052  if (eit != edgesToCut.end()) {
1053 
1054  auto get_dist = [&](auto eit) {
1055  int num_nodes;
1056  const EntityHandle *conn;
1057  CHKERR moab.get_connectivity(eit->first, conn, num_nodes, true);
1058  if (conn[0] == v)
1059  return eit->second.dIst;
1060  else if (conn[1] == v)
1061  return (eit->second.lEngth - eit->second.dIst);
1062  else
1063  THROW_MESSAGE("Data inconsistency");
1064  };
1065 
1066  const auto d = get_dist(eit);
1067  if (std::get<0>(min_tuple) == 0) {
1068  min_tuple = get_tuple(e, d, eit->second.lEngth);
1069  } else if (std::get<1>(min_tuple) > d) {
1070  min_tuple = get_tuple(e, d, eit->second.lEngth);
1071  }
1072  }
1073  }
1074 
1075  const auto geom_dist_vec = get_normal_dits(v);
1076  const auto geom_tol = norm_2(geom_dist_vec);
1077  const auto l = std::get<2>(min_tuple);
1078 
1079  if (geom_tol < l * geometry_tol) {
1080  return std::make_pair(get_coords(v), l);
1081 
1082  } else {
1083  const auto &d = edgesToCut.at(std::get<0>(min_tuple));
1084  return std::make_pair(VectorDouble3(d.rayPoint + d.dIst * d.unitRayDir),
1085  l);
1086  }
1087  };
1088 
1089  auto get_in_range = [](auto v, auto &r) { return (r.find(v) != r.end()); };
1090 
1091  auto project_nodes = [&](auto nodes_to_check) {
1092  if (debug)
1093  CHKERR SaveData(moab)("nodes_to_check.vtk", nodes_to_check);
1094 
1095  auto get_fix_e = [](auto fixed_edges) {
1096  if (fixed_edges)
1097  return *fixed_edges;
1098  else
1099  return Range();
1100  };
1101 
1102  const auto fix_e = get_fix_e(fixed_edges);
1103  const auto skin_e = get_adj(unite(get_skin(vOlume), constrainSurface), 1);
1104  const auto cut_fix = intersect(cutEdges, fix_e);
1105  const auto cut_skin = intersect(cutEdges, skin_e);
1106 
1107  Range corner_n;
1108  if (corner_nodes)
1109  corner_n = intersect(*corner_nodes, nodes_to_check);
1110  auto fixe_n = intersect(get_adj(fix_e, 0), nodes_to_check);
1111  auto skin_n = intersect(get_adj(skin_e, 0), nodes_to_check);
1112 
1113  std::vector<std::pair<EntityHandle, TreeData>> vertices_on_cut_edges;
1114  vertices_on_cut_edges.reserve(nodes_to_check.size());
1115 
1116  auto add_zero_vertex = [&](const EntityHandle v, auto &&new_pos) {
1117  auto coords = get_coords(v);
1118  auto ray = new_pos - coords;
1119  auto l = norm_2(ray);
1120  TreeData data;
1121  data.dIst = l;
1122  if (l > std::numeric_limits<double>::epsilon()) {
1123  data.unitRayDir = ray / l;
1124  } else {
1125  data.dIst = 0;
1126  data.unitRayDir = ray;
1127  }
1128  data.rayPoint = coords;
1129  return std::make_pair(v, data);
1130  };
1131 
1132  auto intersect_v = [&](const auto v, const auto r) {
1133  return intersect(r, get_ent_adj(v, 1));
1134  };
1135 
1136  for (auto v : nodes_to_check) {
1137 
1138  const auto e = intersect_v(v, cutEdges);
1139  if (!e.empty()) {
1140 
1141  if (get_in_range(v, corner_n)) {
1142  auto p = get_prj_point(v, e, 0);
1143  if (norm_2(get_coords(v) - p.first) < close_tol * p.second) {
1144  vertices_on_cut_edges.push_back(add_zero_vertex(v, get_coords(v)));
1145  continue;
1146  }
1147 
1148  } else if (get_in_range(v, fixe_n)) {
1149  const auto b = intersect_v(v, cut_fix);
1150  if (!b.empty()) {
1151  auto p = get_prj_point(v, b, geometry_tol);
1152  if (norm_2(get_coords(v) - p.first) < close_tol * p.second) {
1153  vertices_on_cut_edges.push_back(add_zero_vertex(v, p.first));
1154  continue;
1155  }
1156 
1157  } else if (get_in_range(v, skin_n)) {
1158  const auto b = intersect_v(v, cut_skin);
1159  if (!b.empty()) {
1160  auto p = get_prj_point(v, b, geometry_tol);
1161  if (norm_2(get_coords(v) - p.first) < close_tol * p.second) {
1162  vertices_on_cut_edges.push_back(add_zero_vertex(v, p.first));
1163  continue;
1164  }
1165  }
1166 
1167  }
1168  }
1169 
1170  auto p = get_prj_point(v, e, geometry_tol);
1171  if (norm_2(get_coords(v) - p.first) < close_tol * p.second) {
1172  if (get_in_range(v, fixe_n) || get_in_range(v, skin_n))
1173  vertices_on_cut_edges.push_back(add_zero_vertex(v, get_coords(v)));
1174  else
1175  vertices_on_cut_edges.push_back(add_zero_vertex(v, p.first));
1176  }
1177  }
1178 
1179  }
1180 
1181  auto get_distances = [&](auto &data) {
1182  std::map<EntityHandle, double> dist_map;
1183  if (!data.empty()) {
1184  Tag th;
1185  CHKERR moab.tag_get_handle("DIST_SURFACE_NORMAL_SIGNED", th);
1186 
1187  std::vector<EntityHandle> verts;
1188  verts.reserve(data.size());
1189  for (auto d : data)
1190  verts.emplace_back(d.first);
1191  std::vector<double> distances(verts.size());
1192  CHKERR moab.tag_get_data(th, &*verts.begin(), verts.size(),
1193  &*distances.begin());
1194  for (size_t i = 0; i != verts.size(); ++i)
1195  dist_map[verts[i]] = distances[i];
1196  }
1197  return dist_map;
1198  };
1199 
1200  auto dist_map = get_distances(vertices_on_cut_edges);
1201  if (!dist_map.empty()) {
1202  auto cmp = [&dist_map](const auto &a, const auto &b) {
1203  return dist_map[a.first] < dist_map[b.first];
1204  };
1205  std::sort(vertices_on_cut_edges.begin(), vertices_on_cut_edges.end(),
1206  cmp);
1207  }
1208 
1209  return vertices_on_cut_edges;
1210  };
1211 
1212  auto get_min_quality =
1213  [&](const Range &adj_tets,
1214  const map<EntityHandle, TreeData> &vertices_on_cut_edges,
1215  const std::pair<EntityHandle, TreeData> *test_data_ptr) {
1216  double min_q = 1;
1217  for (auto t : adj_tets) {
1218  int num_nodes;
1219  const EntityHandle *conn;
1220  CHKERR m_field.get_moab().get_connectivity(t, conn, num_nodes, true);
1221  VectorDouble12 coords(12);
1222  CHKERR moab.get_coords(conn, num_nodes, &coords[0]);
1223 
1224  auto set_new_coord = [](auto d) {
1225  return d.rayPoint + d.dIst * d.unitRayDir;
1226  };
1227 
1228  for (auto n : {0, 1, 2, 3}) {
1229  auto n_coords = getVectorAdaptor(&coords[3 * n], 3);
1230  if (test_data_ptr) {
1231  if (test_data_ptr->first == conn[n]) {
1232  noalias(n_coords) = set_new_coord(test_data_ptr->second);
1233  }
1234  }
1235  auto mit = vertices_on_cut_edges.find(conn[n]);
1236  if (mit != vertices_on_cut_edges.end()) {
1237  noalias(n_coords) = set_new_coord(mit->second);
1238  }
1239  }
1240  min_q = std::min(min_q, Tools::volumeLengthQuality(&coords[0]));
1241  }
1242  return min_q;
1243  };
1244 
1245  auto get_zero_distance_verts = [&](const auto &&vertices_on_cut_edges) {
1246  std::vector<EntityHandle> zero_dist_vec;
1247  zero_dist_vec.reserve(vertices_on_cut_edges.size());
1248  for (auto t : vertices_on_cut_edges) {
1249 
1250  auto adj_tet = intersect(vOlume, get_ent_adj(t.first, 3));
1251  const double q0 = get_min_quality(adj_tet, verticesOnCutEdges, nullptr);
1252  const double q = get_min_quality(adj_tet, verticesOnCutEdges, &t);
1253  if (std::isnormal(q) && (q / q0) > projectEntitiesQualityTrashold) {
1254  verticesOnCutEdges[t.first] = t.second;
1255  zero_dist_vec.push_back(t.first);
1256  }
1257  }
1258  return zero_dist_vec;
1259  };
1260 
1261  auto vol_cut_ents = intersect(vOlume, get_adj(cutEdges, 3));
1262 
1263  auto get_zero_distant_ents = [&](auto bridge_ents, const int dim,
1264  const int bridge_dim) {
1265  auto ents =
1266  intersect(get_adj(bridge_ents, dim), get_adj(vol_cut_ents, dim));
1267  auto ents_to_remove =
1268  get_adj(subtract(get_adj(ents, bridge_dim), bridge_ents), dim);
1269  return subtract(ents, ents_to_remove);
1270  };
1271 
1272  verticesOnCutEdges.clear();
1273  zeroDistanceVerts.clear();
1274  zeroDistanceVerts.merge(
1275  get_range(get_zero_distance_verts(project_nodes(get_adj(cutEdges, 0)))));
1276  zeroDistanceEnts = subtract(get_zero_distant_ents(zeroDistanceVerts, 2, 0),
1277  get_skin(vOlume));
1278 
1279  if (debug)
1280  CHKERR SaveData(moab)("zero_distance_verts.vtk", zeroDistanceVerts);
1281  if (debug)
1282  CHKERR SaveData(moab)("zero_distance_ents.vtk", zeroDistanceEnts);
1283 
1284  for (auto f : zeroDistanceVerts) {
1285  auto adj_edges = get_ent_adj(f, 1);
1286  for (auto e : adj_edges) {
1287  cutEdges.erase(e);
1288  edgesToCut.erase(e);
1289  }
1290  }
1291 
1292  if (debug)
1293  CHKERR SaveData(moab)("cut_edges_to_cut.vtk", cutEdges);
1294 
1296 }
1297 
1299  Range &cut_vols,
1300  Range &cut_surf,
1301  Range &cut_verts,
1302  const bool debug) {
1303  CoreInterface &m_field = cOre;
1304  moab::Interface &moab = m_field.get_moab();
1305  MeshRefinement *refiner;
1306  auto ref_ents_ptr = m_field.get_ref_ents();
1308 
1309  if (cutEdges.size() != edgesToCut.size())
1310  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "Data inconsistency");
1311 
1312  auto refine_mesh = [&]() {
1314  CHKERR m_field.getInterface(refiner);
1316  CHKERR refiner->refineTets(vOlume, bit, QUIET, debug);
1318  };
1319 
1320  CHKERR refine_mesh();
1321 
1322  if (debug)
1323  if (cutEdges.size() != edgesToCut.size())
1324  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "Data inconsistency");
1325 
1326  cut_vols.clear();
1327  CHKERR m_field.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
1328  bit, BitRefLevel().set(), MBTET, cut_vols);
1329  cut_surf.clear();
1330  CHKERR m_field.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
1331  bit, bit, MBTRI, cut_surf);
1332 
1333  if (debug)
1334  CHKERR SaveData(moab)("cut_surf_from_bit.vtk", cut_surf);
1335 
1336  // Find new vertices on cut edges
1337  cut_verts.clear();
1338  cut_verts.merge(zeroDistanceVerts);
1339 
1340  for (auto &m : edgesToCut) {
1341  auto vit = ref_ents_ptr->get<Composite_ParentEnt_And_EntType_mi_tag>().find(
1342  boost::make_tuple(MBVERTEX, m.first));
1343  if (vit ==
1344  ref_ents_ptr->get<Composite_ParentEnt_And_EntType_mi_tag>().end()) {
1345  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1346  "No vertex on cut edges, that make no sense");
1347  }
1348  const boost::shared_ptr<RefEntity> &ref_ent = *vit;
1349  if ((ref_ent->getBitRefLevel() & bit).any()) {
1350  EntityHandle vert = ref_ent->getEnt();
1351  cut_verts.insert(vert);
1352  verticesOnCutEdges[vert] = m.second;
1353  } else {
1354  SETERRQ1(
1355  PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1356  "Vertex has wrong bit ref level %s",
1357  boost::lexical_cast<std::string>(ref_ent->getBitRefLevel()).c_str());
1358  }
1359  }
1360 
1361  // Add zero distance entities faces
1362  Range tets_skin;
1363  Skinner skin(&moab);
1364  CHKERR skin.find_skin(0, cut_vols, false, tets_skin);
1365  tets_skin.merge(constrainSurface);
1366 
1367  // At that point cut_surf has all newly created faces, now take all
1368  // nodes on those faces and subtract nodes on cut edges. Faces adjacent to
1369  // nodes which left are not part of surface.
1370  cut_surf.merge(zeroDistanceEnts.subset_by_type(MBTRI));
1371  Range diff_verts;
1372  CHKERR moab.get_connectivity(cut_surf, diff_verts, true);
1373  diff_verts = subtract(diff_verts, cut_verts);
1374 
1375  Range subtract_faces;
1376  CHKERR moab.get_adjacencies(diff_verts, 2, false, subtract_faces,
1377  moab::Interface::UNION);
1378  cut_surf = subtract(cut_surf, unite(subtract_faces, tets_skin));
1379 
1380  cut_verts.clear();
1381  CHKERR moab.get_connectivity(cut_surf, cut_verts, true);
1382 
1383  // Check non-mainfolds
1384  auto check_for_non_minfold = [&]() {
1386  Range surf_edges;
1387  CHKERR moab.get_adjacencies(cut_surf, 1, false, surf_edges,
1388  moab::Interface::UNION);
1389  for (auto e : surf_edges) {
1390 
1391  Range faces;
1392  CHKERR moab.get_adjacencies(&e, 1, 2, false, faces);
1393  faces = intersect(faces, cut_surf);
1394  if (faces.size() > 2) {
1395 
1396  bool resolved = false;
1397 
1398  // Check for haning node
1399  Range nodes;
1400  CHKERR moab.get_connectivity(faces, nodes, true);
1401  for (auto n : nodes) {
1402  Range adj_faces;
1403  CHKERR moab.get_adjacencies(&n, 1, 2, false, adj_faces);
1404  adj_faces = intersect(adj_faces, cut_surf);
1405  if (adj_faces.size() == 1) {
1406  cut_surf.erase(adj_faces[0]);
1407  resolved = true;
1408  }
1409  }
1410 
1411  // Check for two edges minfold
1412  Range adj_edges;
1413  CHKERR moab.get_adjacencies(faces, 1, false, adj_edges,
1414  moab::Interface::UNION);
1415  adj_edges = intersect(adj_edges, surf_edges);
1416  adj_edges.erase(e);
1417  for (auto other_e : adj_edges) {
1418  Range other_faces;
1419  CHKERR moab.get_adjacencies(&other_e, 1, 2, false, other_faces);
1420  other_faces = intersect(other_faces, cut_surf);
1421  if (other_faces.size() > 2) {
1422  other_faces = intersect(other_faces, faces);
1423  cut_surf = subtract(cut_surf, other_faces);
1424  resolved = true;
1425  }
1426  }
1427 
1428  if (!resolved && !debug)
1429  SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
1430  "Non-mainfold surface");
1431 
1432  cut_verts.clear();
1433  CHKERR moab.get_connectivity(cut_surf, cut_verts, true);
1434  }
1435  }
1437  };
1438 
1439  CHKERR check_for_non_minfold();
1440 
1441  if (debug)
1442  CHKERR SaveData(moab)("cut_surf.vtk", cut_surf);
1443 
1445 }
1446 
1448  CoreInterface &m_field = cOre;
1449  moab::Interface &moab = m_field.get_moab();
1451 
1452  // Range out_side_vertices;
1453  for (auto m : verticesOnCutEdges) {
1454  double dist = m.second.dIst;
1455  VectorDouble3 new_coors = m.second.rayPoint + dist * m.second.unitRayDir;
1456  if (th)
1457  CHKERR moab.tag_set_data(th, &m.first, 1, &new_coors[0]);
1458  else
1459  CHKERR moab.set_coords(&m.first, 1, &new_coors[0]);
1460  }
1461 
1463 }
1464 
1466  CoreInterface &m_field = cOre;
1467  moab::Interface &moab = m_field.get_moab();
1469  for (auto &v : verticesOnTrimEdges) {
1470  double dist = v.second.dIst;
1471  VectorDouble3 new_coors = v.second.rayPoint + dist * v.second.unitRayDir;
1472  if (th)
1473  CHKERR moab.tag_set_data(th, &v.first, 1, &new_coors[0]);
1474  else
1475  CHKERR moab.set_coords(&v.first, 1, &new_coors[0]);
1476  }
1478 }
1479 
1481  Range *corner_nodes, Tag th,
1482  const double tol_trim_close,
1483  const bool debug) {
1484  CoreInterface &m_field = cOre;
1485  moab::Interface &moab = m_field.get_moab();
1487 
1488  // takes body skin
1489  Skinner skin(&moab);
1490  Range tets_skin;
1491  CHKERR skin.find_skin(0, cutNewVolumes, false, tets_skin);
1492  tets_skin.merge(constrainSurface);
1493 
1494  // vertices on the skin
1495  Range tets_skin_verts;
1496  CHKERR moab.get_connectivity(tets_skin, tets_skin_verts, true);
1497  // edges on the skin
1498  Range tets_skin_edges;
1499  CHKERR moab.get_adjacencies(tets_skin, 1, false, tets_skin_edges,
1500  moab::Interface::UNION);
1501 
1502  // get edges on new surface
1503  Range cut_surface_edges;
1504  CHKERR moab.get_adjacencies(cutNewSurfaces, 1, false, cut_surface_edges,
1505  moab::Interface::UNION);
1506  Range cut_surface_verts;
1507  CHKERR moab.get_connectivity(cutNewSurfaces, cut_surface_verts, true);
1508 
1509  Range corners;
1510  if (corner_nodes)
1511  corners = *corner_nodes;
1512 
1513  Range fix_edges;
1514  if (fixed_edges)
1515  fix_edges = *fixed_edges;
1516 
1517  Range fixed_edges_verts;
1518  if (fixed_edges)
1519  CHKERR moab.get_connectivity(*fixed_edges, fixed_edges_verts, true);
1520 
1521  Range surface_skin;
1522  if (fRont.empty())
1523  CHKERR skin.find_skin(0, sUrface, false, surface_skin);
1524  else
1525  surface_skin = fRont;
1526 
1527  auto get_point_coords = [&](EntityHandle v) {
1528  VectorDouble3 point(3);
1529  if (th)
1530  CHKERR moab.tag_get_data(th, &v, 1, &point[0]);
1531  else
1532  CHKERR moab.get_coords(&v, 1, &point[0]);
1533  return point;
1534  };
1535 
1536  struct VertMap {
1537  const double d;
1538  const EntityHandle v;
1539  const EntityHandle e;
1540  VertMap(const double d, const EntityHandle v, const EntityHandle e)
1541  : d(d), v(v), e(e) {}
1542  };
1543 
1544  typedef multi_index_container<
1545  VertMap,
1546  indexed_by<
1547  ordered_non_unique<member<VertMap, const double, &VertMap::d>>,
1548  ordered_non_unique<member<VertMap, const EntityHandle, &VertMap::v>>,
1549  ordered_non_unique<member<VertMap, const EntityHandle, &VertMap::e>>
1550 
1551  >>
1552  VertMapMultiIndex;
1553 
1554  VertMapMultiIndex verts_map;
1555 
1556  auto add_vert = [&](const EntityHandle v, const EntityHandle e,
1557  const double dist) {
1558  verts_map.insert(VertMap(dist, v, e));
1559  };
1560 
1561  // clear data ranges
1562  trimEdges.clear();
1563  edgesToTrim.clear();
1564  verticesOnTrimEdges.clear();
1565  trimNewVertices.clear();
1566 
1567  auto cut_this_edge = [&](const EntityHandle e, const double length, auto &ray,
1568  auto &ray_point) {
1569  trimEdges.insert(e);
1570  edgesToTrim[e].dIst = 1;
1571  edgesToTrim[e].lEngth = length;
1572  edgesToTrim[e].unitRayDir.resize(3, false);
1573  edgesToTrim[e].rayPoint.resize(3, false);
1574  for (int ii = 0; ii != 3; ++ii)
1575  edgesToTrim[e].unitRayDir[ii] = ray(ii);
1576  for (int ii = 0; ii != 3; ++ii)
1577  edgesToTrim[e].rayPoint[ii] = ray_point(ii);
1578  };
1579 
1583 
1584  int num_nodes;
1585 
1586  auto get_tag_data = [&](auto th, auto conn) {
1588  CHKERR moab.tag_get_data(th, &conn, 1, &t(0));
1589  return t;
1590  };
1591 
1592  double max_edge_length = 0;
1593 
1594  /// Project front entities on on the cut surface plane
1595  if (!fRont.empty()) {
1596  // Calculate distances
1597  treeSurfPtr = boost::shared_ptr<OrientedBoxTreeTool>(
1598  new OrientedBoxTreeTool(&moab, "ROOTSETSURF", true));
1600 
1601  for (auto s : surface_skin) {
1602 
1603  auto project_on_surface = [&](auto &t) {
1605 
1606  EntityHandle facets_out;
1607  CHKERR treeSurfPtr->closest_to_location(&t(0), rootSetSurf, &t_p(0),
1608  facets_out);
1609 
1610  FTensor::Tensor1<double, 3> t_normal;
1611  CHKERR m_field.getInterface<Tools>()->getTriNormal(facets_out,
1612  &t_normal(0));
1613  t_normal(i) /= sqrt(t_normal(i) * t_normal(i));
1614  const double dot = t_normal(i) * (t_p(i) - t(i));
1615  t_p(i) = t(i) + dot * t_normal(i);
1616 
1617  return t_p;
1618  };
1619 
1620  const EntityHandle *conn;
1621  CHKERR moab.get_connectivity(s, conn, num_nodes, true);
1622 
1623  VectorDouble6 coords_front(6);
1624  CHKERR moab.get_coords(conn, num_nodes, &coords_front[0]);
1625 
1626  FTensor::Tensor1<double *, 3> t_f0(&coords_front[0], &coords_front[1],
1627  &coords_front[2]);
1628  FTensor::Tensor1<double *, 3> t_f1(&coords_front[3], &coords_front[4],
1629  &coords_front[5]);
1630 
1631  auto t_p_f0 = project_on_surface(t_f0);
1632  auto t_p_f1 = project_on_surface(t_f1);
1633 
1634  CHKERR moab.set_coords(&conn[0], 1, &t_p_f0(0));
1635  CHKERR moab.set_coords(&conn[1], 1, &t_p_f1(0));
1636  }
1637  }
1638 
1639  if (debug)
1640  CHKERR SaveData(moab)("surface_skin_to_trim.vtk", surface_skin);
1641 
1643  Tag th_dist_front_vec;
1644  CHKERR moab.tag_get_handle("DIST_FRONT_VECTOR", th_dist_front_vec);
1645 
1646  // iterate over edges on cut surface
1647  for (auto e : cut_surface_edges) {
1648 
1649  auto get_conn_edge = [&moab](auto e) {
1650  // Get edge connectivity and coords
1651  const EntityHandle *conn_edge;
1652  int num_nodes;
1653  CHKERR moab.get_connectivity(e, conn_edge, num_nodes, true);
1654  return conn_edge;
1655  };
1656 
1657  auto get_coords_edge = [&moab](auto conn_edge) {
1658  std::array<double, 6> coords_edge;
1659  CHKERR moab.get_coords(conn_edge, 2, coords_edge.data());
1660  return coords_edge;
1661  };
1662 
1663  auto get_ftensor_coords = [](const double *ptr) {
1664  return FTensor::Tensor1<double, 3>{ptr[0], ptr[1], ptr[2]};
1665  };
1666 
1667  auto conn_edge = get_conn_edge(e);
1668  auto coords_edge = get_coords_edge(conn_edge);
1669 
1670  auto t_dist0 = get_tag_data(th_dist_front_vec, conn_edge[0]);
1671  auto t_dist1 = get_tag_data(th_dist_front_vec, conn_edge[1]);
1672  auto t_e0 = get_ftensor_coords(&coords_edge[0]);
1673  auto t_e1 = get_ftensor_coords(&coords_edge[3]);
1674 
1675  FTensor::Tensor1<double, 3> t_edge_delta;
1676  t_edge_delta(i) = t_e1(i) - t_e0(i);
1677  const double edge_length2 = t_edge_delta(i) * t_edge_delta(i);
1678  const double edge_length = sqrt(edge_length2);
1679  if (edge_length == 0)
1680  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "Zero edge length");
1681 
1682  auto add_edge = [&](auto t_cut) {
1684  if (t_cut < 0.5) {
1685  t_ray(i) = t_cut * t_edge_delta(i);
1686  add_vert(conn_edge[0], e, fabs(t_cut));
1687  add_vert(conn_edge[1], e, fabs(t_cut - 1));
1688  cut_this_edge(e, edge_length, t_ray, t_e0);
1689  } else {
1690  FTensor::Tensor1<double, 3> t_edge_point;
1691  t_edge_point(i) = t_e0(i) + t_cut * t_edge_delta(i);
1692  t_ray(i) = t_edge_point(i) - t_e1(i);
1693  add_vert(conn_edge[0], e, fabs(t_cut));
1694  add_vert(conn_edge[1], e, fabs(t_cut - 1));
1695  cut_this_edge(e, edge_length, t_ray, t_e1);
1696  }
1697  max_edge_length = std::max(max_edge_length, edge_length);
1698  };
1699 
1700  auto trim_cross_edges = [&]() {
1701  if (std::min(t_dist0(i) * t_dist0(i), t_dist1(i) * t_dist1(i)) <
1702  edge_length2) {
1703 
1704  auto make_pair = [&](const double d, const double te) {
1705  return std::make_pair(d, te);
1706  };
1707 
1708  auto min_pair = make_pair(-1, -1);
1709 
1710  for (auto f : surface_skin) {
1711 
1712  auto conn_front = get_conn_edge(f);
1713  auto coords_front = get_coords_edge(conn_front);
1714  auto t_f0 = get_ftensor_coords(&coords_front[0]);
1715  auto t_f1 = get_ftensor_coords(&coords_front[3]);
1716 
1717  double te;
1718  double tf;
1719 
1720  auto res = Tools::minDistanceFromSegments(
1721  &t_e0(0), &t_e1(0), &t_f0(0), &t_f1(0), &te, &tf);
1722 
1723  if (res != Tools::NO_SOLUTION) {
1724 
1725  auto check = [](auto v) {
1726  return (v > -std::numeric_limits<double>::epsilon() &&
1727  (v - 1) < std::numeric_limits<double>::epsilon());
1728  };
1729 
1730  if (check(te) && check(tf)) {
1731 
1732  FTensor::Tensor1<double, 3> t_delta, t_cross;
1733  t_delta(i) = (t_e0(i) + te * t_edge_delta(i)) -
1734  (t_f0(0) + tf * (t_f1(i) - t_f0(i)));
1735 
1736  t_delta(i) /= edge_length;
1737 
1738  const double dot = t_delta(i) * t_delta(i);
1739 
1740  if (min_pair.first < 0 || min_pair.first > dot) {
1741 
1742  if (dot < tol_trim_close * tol_trim_close)
1743  min_pair = make_pair(dot, te);
1744  }
1745  }
1746  }
1747  }
1748 
1749  if (min_pair.first > -std::numeric_limits<double>::epsilon()) {
1750  add_edge(min_pair.second);
1751  return true;
1752  }
1753  }
1754 
1755  return false;
1756  };
1757 
1758  if (!trim_cross_edges()) {
1759 
1760  const double dot = t_dist0(i) * t_dist1(i);
1761  const double dot_direction0 = t_dist0(i) * t_edge_delta(i);
1762  const double dot_direction1 = t_dist1(i) * t_edge_delta(i);
1763 
1764  if (dot < std::numeric_limits<double>::epsilon() &&
1765  dot_direction0 > -std::numeric_limits<double>::epsilon() &&
1766  dot_direction1 < std::numeric_limits<double>::epsilon()) {
1767 
1768  const double s0 = t_dist0(i) * t_edge_delta(i) / edge_length;
1769  const double s1 = t_dist1(i) * t_edge_delta(i) / edge_length;
1770  const double t_cut = s0 / (s0 - s1);
1771 
1772  add_edge(t_cut);
1773  }
1774  }
1775  }
1776 
1777  if (debug)
1778  CHKERR SaveData(moab)("edges_potentially_to_trim.vtk", cut_surface_edges);
1779 
1780  if (debug)
1781  CHKERR SaveData(moab)("edges_selected_to_trim.vtk", trimEdges);
1782 
1783  auto get_quality_change = [&](const Range &adj_tets, const EntityHandle &v,
1784  const VectorDouble3 &new_pos) {
1785  double q0 = 1;
1786  CHKERR m_field.getInterface<Tools>()->minTetsQuality(adj_tets, q0, th);
1787 
1788  double min_q = 1;
1789  for (auto t : adj_tets) {
1790  int num_nodes;
1791  const EntityHandle *conn;
1792  CHKERR m_field.get_moab().get_connectivity(t, conn, num_nodes, true);
1793  VectorDouble12 coords(12);
1794  if (th)
1795  CHKERR moab.tag_get_data(th, conn, num_nodes, &coords[0]);
1796  else
1797  CHKERR moab.get_coords(conn, num_nodes, &coords[0]);
1798 
1799  for (int n = 0; n != 4; ++n) {
1800  auto n_coords = getVectorAdaptor(&coords[3 * n], 3);
1801  if (conn[n] == v) {
1802  noalias(n_coords) = new_pos;
1803  } else {
1804  auto m = verticesOnTrimEdges.find(conn[n]);
1805  if (m != verticesOnTrimEdges.end())
1806  noalias(n_coords) =
1807  m->second.rayPoint + m->second.dIst * m->second.unitRayDir;
1808  }
1809  }
1810 
1811  const double q = Tools::volumeLengthQuality(&coords[0]);
1812  if (!std::isnormal(q)) {
1813  min_q = -2;
1814  break;
1815  }
1816  min_q = std::min(min_q, q);
1817  }
1818  return min_q / q0;
1819  };
1820 
1821  Range checked_verts;
1822  auto add_trim_vert = [&](const EntityHandle v, const EntityHandle e) {
1823  if (!(trimNewVertices.find(v) != trimNewVertices.end())) {
1824  auto &r = edgesToTrim.at(e);
1825  VectorDouble3 ray_point = get_point_coords(v);
1826  VectorDouble3 new_pos = r.rayPoint + r.dIst * r.unitRayDir;
1827  VectorDouble3 unit_ray_dir = ray_point - new_pos;
1828  Range adj_tets;
1829  CHKERR moab.get_adjacencies(&v, 1, 3, false, adj_tets);
1830  adj_tets = intersect(adj_tets, cutNewVolumes);
1831  double q = get_quality_change(adj_tets, v, new_pos);
1833  VectorDouble3 ray_dir = new_pos - ray_point;
1834  double dist = norm_2(ray_dir);
1835  verticesOnTrimEdges[v].dIst = 1;
1836  verticesOnTrimEdges[v].lEngth = dist;
1837  verticesOnTrimEdges[v].unitRayDir = ray_dir;
1838  verticesOnTrimEdges[v].rayPoint = ray_point;
1839  trimNewVertices.insert(v);
1840  }
1841  checked_verts.insert(v);
1842  }
1843  };
1844 
1845  auto add_no_move_trim = [&](const EntityHandle v, const EntityHandle e) {
1846  if (!(trimNewVertices.find(v) != trimNewVertices.end())) {
1847  auto &m = edgesToTrim.at(e);
1848  verticesOnTrimEdges[v] = m;
1849  verticesOnTrimEdges[v].rayPoint = get_point_coords(v);
1850  verticesOnTrimEdges[v].lEngth = 0;
1851  verticesOnTrimEdges[v].dIst = 0;
1852  trimNewVertices.insert(v);
1853  checked_verts.insert(v);
1854  }
1855  };
1856 
1857  // Iterate over all vertives close to surface front and check if those can
1858  // be moved
1859 
1860  // filer nodes which distance is in given tolerance
1861  auto hi = verts_map.get<0>().upper_bound(tol_trim_close);
1862  verts_map.get<0>().erase(hi, verts_map.end());
1863 
1864  auto remove_verts = [&](Range nodes) {
1865  for (auto n : nodes) {
1866  auto r = verts_map.get<1>().equal_range(n);
1867  verts_map.get<1>().erase(r.first, r.second);
1868  }
1869  };
1870 
1871  auto trim_verts = [&](const Range verts, const bool move) {
1872  VertMapMultiIndex verts_map_tmp;
1873  for (auto p = corners.pair_begin(); p != corners.pair_end(); ++p) {
1874  auto lo = verts_map.get<1>().lower_bound(p->first);
1875  auto hi = verts_map.get<1>().upper_bound(p->second);
1876  verts_map_tmp.insert(lo, hi);
1877  }
1878  if (move) {
1879  for (auto &m : verts_map_tmp.get<0>())
1880  add_trim_vert(m.v, m.e);
1881  } else {
1882  for (auto &m : verts_map_tmp.get<0>())
1883  add_no_move_trim(m.v, m.e);
1884  }
1885  };
1886 
1887  auto trim_edges = [&](const Range ents, const bool move) {
1888  VertMapMultiIndex verts_map_tmp;
1889  for (auto p = ents.pair_begin(); p != ents.pair_end(); ++p) {
1890  auto lo = verts_map.get<2>().lower_bound(p->first);
1891  auto hi = verts_map.get<2>().upper_bound(p->second);
1892  verts_map_tmp.insert(lo, hi);
1893  verts_map.get<2>().erase(lo, hi);
1894  }
1895  if (move) {
1896  for (auto &m : verts_map_tmp.get<0>())
1897  add_trim_vert(m.v, m.e);
1898  } else {
1899  for (auto &m : verts_map_tmp.get<0>())
1900  add_no_move_trim(m.v, m.e);
1901  }
1902  };
1903 
1904  auto intersect_self = [&](Range &a, const Range b) { a = intersect(a, b); };
1905 
1906  map<std::string, Range> range_maps;
1907 
1908  // Edges on surface skin
1909  CHKERR skin.find_skin(0, cutNewSurfaces, false, range_maps["surface_skin"]);
1910  // Edges as trimmed
1911  intersect_self(range_maps["surface_skin"], trimEdges);
1912  // Edges are on fixed edges
1913  range_maps["fixed_edges_on_surface_skin"] =
1914  intersect(range_maps["surface_skin"], fix_edges);
1915 
1916  // Edges adjacent to fixed edges
1917  CHKERR moab.get_adjacencies(fixed_edges_verts, 1, false,
1918  range_maps["fixed_edges_verts_edges"],
1919  moab::Interface::UNION);
1920  intersect_self(range_maps["fixed_edges_verts_edges"], trimEdges);
1921 
1922  CHKERR moab.get_connectivity(
1923  range_maps["fixed_edges_verts_edges"],
1924  range_maps["fixed_edges_verts_edges_verts_on_the_skin"], false);
1925  intersect_self(range_maps["fixed_edges_verts_edges_verts_on_the_skin"],
1926  tets_skin_verts);
1927 
1928  // Do not move nodes at the corners
1929  trim_verts(corners, false);
1930  remove_verts(corners);
1931 
1932  // Trim edges on the body skin move
1933  trim_edges(range_maps["fixed_edges_on_surface_skin"], true);
1934  remove_verts(range_maps["fixed_edges_on_surface_skin_verts"]);
1935 
1936  // Trim edges nodes on the skin but edge not on the skin do not
1937  trim_verts(range_maps["fixed_edges_verts_edges_verts_on_the_skin"], false);
1938  remove_verts(range_maps["fixed_edges_verts_edges_verts_on_the_skin"]);
1939 
1940  // Trim edges on the cut skin move
1941  trim_edges(range_maps["surface_skin"], true);
1942  trim_verts(tets_skin_verts, false);
1943  remove_verts(tets_skin_verts);
1944 
1945  for (auto &m : verts_map.get<0>())
1946  add_trim_vert(m.v, m.e);
1947 
1948  for (auto m : verticesOnTrimEdges) {
1949  EntityHandle v = m.first;
1950  Range adj;
1951  CHKERR moab.get_adjacencies(&v, 1, 1, false, adj);
1952  for (auto e : adj) {
1953  edgesToTrim.erase(e);
1954  trimEdges.erase(e);
1955  }
1956  }
1957 
1958  if (debug)
1959  if (!trimNewVertices.empty())
1960  CHKERR SaveData(moab)("trim_close_vertices.vtk", trimNewVertices);
1961 
1962  if (debug)
1963  if (!trimEdges.empty())
1964  CHKERR SaveData(moab)("trim_edges.vtk", trimEdges);
1965 
1967 }
1968 
1970  const bool debug) {
1971  CoreInterface &m_field = cOre;
1972  moab::Interface &moab = m_field.get_moab();
1973  MeshRefinement *refiner;
1974  auto ref_ents_ptr = m_field.get_ref_ents();
1976 
1977  CHKERR m_field.getInterface(refiner);
1980 
1981  trimNewVolumes.clear();
1982  CHKERR m_field.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
1983  bit, BitRefLevel().set(), MBTET, trimNewVolumes);
1984 
1985  for (map<EntityHandle, TreeData>::iterator mit = edgesToTrim.begin();
1986  mit != edgesToTrim.end(); mit++) {
1987  auto vit = ref_ents_ptr->get<Composite_ParentEnt_And_EntType_mi_tag>().find(
1988  boost::make_tuple(MBVERTEX, mit->first));
1989  if (vit ==
1990  ref_ents_ptr->get<Composite_ParentEnt_And_EntType_mi_tag>().end())
1991  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1992  "No vertex on trim edges, that make no sense");
1993 
1994  const boost::shared_ptr<RefEntity> &ref_ent = *vit;
1995  if ((ref_ent->getBitRefLevel() & bit).any()) {
1996  EntityHandle vert = ref_ent->getEnt();
1997  trimNewVertices.insert(vert);
1998  verticesOnTrimEdges[vert] = mit->second;
1999  }
2000  }
2001 
2002  // Get faces which are trimmed
2003  trimNewSurfaces.clear();
2004  CHKERR m_field.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
2005  bit, bit, MBTRI, trimNewSurfaces);
2006 
2007  Range trim_new_surfaces_nodes;
2008  CHKERR moab.get_connectivity(trimNewSurfaces, trim_new_surfaces_nodes, true);
2009  trim_new_surfaces_nodes = subtract(trim_new_surfaces_nodes, trimNewVertices);
2010  trim_new_surfaces_nodes = subtract(trim_new_surfaces_nodes, cutNewVertices);
2011  Range faces_not_on_surface;
2012  CHKERR moab.get_adjacencies(trim_new_surfaces_nodes, 2, false,
2013  faces_not_on_surface, moab::Interface::UNION);
2014  trimNewSurfaces = subtract(trimNewSurfaces, faces_not_on_surface);
2015 
2016  // Get surfaces which are not trimmed and add them to surface
2017  Range all_surfaces_on_bit_level;
2018  CHKERR m_field.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
2019  bit, BitRefLevel().set(), MBTRI, all_surfaces_on_bit_level);
2020  all_surfaces_on_bit_level =
2021  intersect(all_surfaces_on_bit_level, cutNewSurfaces);
2022 
2023  trimNewSurfaces = unite(trimNewSurfaces, all_surfaces_on_bit_level);
2024 
2026 }
2027 
2029  Range *corner_nodes,
2030  const double tol, Tag th,
2031  const bool debug) {
2032  CoreInterface &m_field = cOre;
2033  moab::Interface &moab = m_field.get_moab();
2034  Skinner skin(&moab);
2035 
2036  auto get_adj = [&moab](const Range r, const int dim) {
2037  Range a;
2038  if (dim)
2039  CHKERR moab.get_adjacencies(r, dim, false, a, moab::Interface::UNION);
2040  else
2041  CHKERR moab.get_connectivity(r, a, true);
2042  return a;
2043  };
2044 
2045  auto get_skin = [&skin](const auto r) {
2046  Range s;
2047  CHKERR skin.find_skin(0, r, false, s);
2048  return s;
2049  };
2050 
2052 
2053  auto trim_tets_skin = get_skin(trimNewVolumes);
2054  auto trim_tets_skin_edges = get_adj(trim_tets_skin, 1);
2055  auto trim_surface_edges = get_adj(trimNewSurfaces, 1);
2056 
2057  auto contarain_edges =
2058  intersect(trim_surface_edges, get_adj(constrainSurface, 1));
2059  if (fixed_edges)
2060  contarain_edges.merge(
2061  intersect(fixed_edges->subset_by_type(MBEDGE), trim_surface_edges));
2062 
2063  Range barrier_vertices(trimNewVertices);
2064  if (corner_nodes) {
2065  // Add nodes which re adjacent to corner nodes
2066  barrier_vertices.merge(get_adj(
2067  intersect(get_adj(intersect(*corner_nodes, barrier_vertices), 2),
2068  trimNewSurfaces),
2069  0));
2070  }
2071 
2072  auto get_nodes_with_one_node_on_fixed_edge_other_not = [&]() {
2073  const auto fixed_edges_on_surface =
2074  intersect(*fixed_edges, trim_surface_edges);
2075  const auto skin_fixed_edges_on_surface = get_skin(fixed_edges_on_surface);
2076  const auto barrier_nodes = subtract(skin_fixed_edges_on_surface,
2077  get_adj(get_skin(trimNewSurfaces), 0));
2078  return barrier_nodes;
2079  };
2080 
2081  if (fixed_edges)
2082  barrier_vertices.merge(get_nodes_with_one_node_on_fixed_edge_other_not());
2083 
2084  auto add_close_surface_barrier = [&]() {
2086 
2087  // Ten algorytm dedykuje destylarni Bowmore. Jeżeli coÅ› pójdzie nie tak, coÅ›
2088  // pÄ™knie inaczej niż trzeba, to peÅ‚nÄ… odpowiedzialność ponosi Beam Suntory
2089  // UK Ltd.
2090 
2091  CHKERR buildTree();
2092 
2093  auto test_edges =
2094  subtract(trim_surface_edges, get_adj(constrainSurface, 1));
2095  if (fixed_edges)
2096  test_edges = subtract(test_edges, *fixed_edges);
2097  auto trim_surface_nodes = get_adj(test_edges, 0);
2098  trim_surface_nodes = subtract(trim_surface_nodes, barrier_vertices);
2099  if (fixed_edges)
2100  trim_surface_nodes =
2101  subtract(trim_surface_nodes, get_adj(*fixed_edges, 0));
2102 
2103  Range trim_skin;
2104  trim_skin.merge(contarain_edges);
2105  if (fRont.empty())
2106  trim_skin.merge(get_skin(sUrface));
2107  else
2108  trim_skin.merge(fRont);
2109  if (fixed_edges)
2110  trim_skin.merge(intersect(*fixed_edges, trim_surface_edges));
2111 
2112  if (debug && !trim_skin.empty())
2113  CHKERR SaveData(m_field.get_moab())("trim_skin.vtk", trim_skin);
2114 
2115  VectorDouble coords(3 * trim_surface_nodes.size());
2116  if (th)
2117  CHKERR moab.tag_get_data(th, trim_surface_nodes, &*coords.begin());
2118  else
2119  CHKERR moab.get_coords(trim_surface_nodes, &*coords.begin());
2120 
2121  if (!trim_skin.empty()) {
2122 
2123  std::vector<double> min_distances(trim_surface_nodes.size(), -1);
2124  CHKERR cOre.getInterface<Tools>()->findMinDistanceFromTheEdges(
2125  &*coords.begin(), trim_surface_nodes.size(), trim_skin,
2126  &*min_distances.begin());
2127 
2128  auto coords_ptr = &*coords.begin();
2129  auto min_dist = &*min_distances.begin();
2130 
2131  std::vector<EntityHandle> add_nodes;
2132  add_nodes.reserve(trim_surface_nodes.size());
2133 
2134  for (auto n : trim_surface_nodes) {
2135 
2136  if ((*min_dist) > std::numeric_limits<double>::epsilon()) {
2137  VectorDouble3 point_out(3);
2138 
2139  EntityHandle facets_out;
2140  CHKERR treeSurfPtr->closest_to_location(coords_ptr, rootSetSurf,
2141  &point_out[0], facets_out);
2142 
2143  VectorDouble3 delta = point_out - getVectorAdaptor(coords_ptr, 3);
2144  VectorDouble3 normal(3);
2145  CHKERR m_field.getInterface<Tools>()->getTriNormal(facets_out,
2146  &normal[0]);
2147 
2148  normal /= norm_2(normal);
2149  delta -= inner_prod(normal, delta) * normal;
2150 
2151  double dist = norm_2(delta);
2152  if (dist < tol * (*min_dist))
2153  add_nodes.emplace_back(n);
2154  }
2155 
2156  coords_ptr += 3;
2157  min_dist += 1;
2158  }
2159 
2160  barrier_vertices.insert_list(add_nodes.begin(), add_nodes.end());
2161  }
2162 
2164  };
2165 
2166  auto remove_faces_on_skin = [&]() {
2168  Range skin_faces = intersect(trimNewSurfaces, trim_tets_skin);
2169  if (!skin_faces.empty()) {
2170  barrier_vertices.merge(get_adj(skin_faces, 0));
2171  for (auto f : skin_faces)
2172  trimNewSurfaces.erase(f);
2173  }
2175  };
2176 
2177  auto get_trim_free_edges = [&]() {
2178  // get current surface skin
2179  Range trim_surf_skin;
2180  CHKERR skin.find_skin(0, trimNewSurfaces, false, trim_surf_skin);
2181  trim_surf_skin = subtract(trim_surf_skin, trim_tets_skin_edges);
2182 
2183  Range trim_surf_skin_verts;
2184  CHKERR moab.get_connectivity(trim_surf_skin, trim_surf_skin_verts, true);
2185  for (auto e : barrier_vertices)
2186  trim_surf_skin_verts.erase(e);
2187 
2188  Range free_edges;
2189  CHKERR moab.get_adjacencies(trim_surf_skin_verts, 1, false, free_edges,
2190  moab::Interface::UNION);
2191  free_edges =
2192  subtract(intersect(free_edges, trim_surf_skin), contarain_edges);
2193 
2194  return free_edges;
2195  };
2196 
2197  CHKERR remove_faces_on_skin();
2198  CHKERR add_close_surface_barrier();
2199 
2200  if (debug && !barrier_vertices.empty())
2201  CHKERR SaveData(m_field.get_moab())("barrier_vertices.vtk",
2202  barrier_vertices);
2203 
2204  int nn = 0;
2205  Range out_edges;
2206  while (!(out_edges = get_trim_free_edges()).empty()) {
2207 
2208  if (debug && !trimNewSurfaces.empty())
2209  CHKERR SaveData(m_field.get_moab())(
2210  "trimNewSurfaces_" + boost::lexical_cast<std::string>(nn) + ".vtk",
2211  trimNewSurfaces);
2212 
2213  if (debug && !out_edges.empty())
2214  CHKERR SaveData(m_field.get_moab())(
2215  "trimNewSurfacesOutsideVerts_" +
2216  boost::lexical_cast<std::string>(nn) + ".vtk",
2217  out_edges);
2218 
2219  Range outside_faces;
2220  CHKERR moab.get_adjacencies(out_edges, 2, false, outside_faces,
2221  moab::Interface::UNION);
2222  trimNewSurfaces = subtract(trimNewSurfaces, outside_faces);
2223  ++nn;
2224  }
2225 
2226  if (debug && !trimNewSurfaces.empty())
2227  CHKERR SaveData(m_field.get_moab())(
2228  "trimNewSurfaces_" + boost::lexical_cast<std::string>(nn) + ".vtk",
2229  trimNewSurfaces);
2230 
2232 }
2233 
2236  Range &ents) {
2237  CoreInterface &m_field = cOre;
2238  moab::Interface &moab = m_field.get_moab();
2239  PrismInterface *interface;
2241  CHKERR m_field.getInterface(interface);
2242  // Remove tris on surface front
2243  {
2244  Range front_tris;
2245  EntityHandle meshset;
2246  CHKERR moab.create_meshset(MESHSET_SET, meshset);
2247  CHKERR moab.add_entities(meshset, ents);
2249  meshset, split_bit, true, front_tris);
2250  CHKERR moab.delete_entities(&meshset, 1);
2251  ents = subtract(ents, front_tris);
2252  }
2253  // Remove entities on skin
2254  Range tets;
2255  CHKERR m_field.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
2256  split_bit, BitRefLevel().set(), MBTET, tets);
2257  // Remove entities on skin
2258  Skinner skin(&moab);
2259  Range tets_skin;
2260  CHKERR skin.find_skin(0, tets, false, tets_skin);
2261  ents = subtract(ents, tets_skin);
2262 
2264 }
2265 
2267  const BitRefLevel bit,
2268  const Range &ents, Tag th) {
2269  CoreInterface &m_field = cOre;
2270  moab::Interface &moab = m_field.get_moab();
2271  PrismInterface *interface;
2273  CHKERR m_field.getInterface(interface);
2274  EntityHandle meshset_volume;
2275  CHKERR moab.create_meshset(MESHSET_SET, meshset_volume);
2276  CHKERR m_field.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
2277  split_bit, BitRefLevel().set(), MBTET, meshset_volume);
2278  EntityHandle meshset_surface;
2279  CHKERR moab.create_meshset(MESHSET_SET, meshset_surface);
2280  CHKERR moab.add_entities(meshset_surface, ents);
2281  CHKERR interface->getSides(meshset_surface, split_bit, true);
2282  CHKERR interface->splitSides(meshset_volume, bit, meshset_surface, true,
2283  true);
2284  CHKERR moab.delete_entities(&meshset_volume, 1);
2285  CHKERR moab.delete_entities(&meshset_surface, 1);
2286  if (th) {
2287  Range prisms;
2288  ierr = m_field.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
2289  bit, BitRefLevel().set(), MBPRISM, prisms);
2290  for (Range::iterator pit = prisms.begin(); pit != prisms.end(); pit++) {
2291  int num_nodes;
2292  const EntityHandle *conn;
2293  CHKERR moab.get_connectivity(*pit, conn, num_nodes, true);
2294  MatrixDouble data(3, 3);
2295  CHKERR moab.tag_get_data(th, conn, 3, &data(0, 0));
2296  CHKERR moab.tag_set_data(th, &conn[3], 3, &data(0, 0));
2297  }
2298  }
2300 }
2301 
2303  const int fraction_level, const Range &tets, const Range &surface,
2304  const Range &fixed_edges, const Range &corner_nodes, Range &edges_to_merge,
2305  Range &out_tets, Range &new_surf, Tag th, const bool update_meshsets,
2306  const BitRefLevel *bit_ptr, const bool debug) {
2307  CoreInterface &m_field = cOre;
2308  moab::Interface &moab = m_field.get_moab();
2310 
2311  /**
2312  * \brief Merge nodes
2313  */
2314  struct MergeNodes {
2315  CoreInterface &mField;
2316  const bool onlyIfImproveQuality;
2317  Tag tH;
2318  bool updateMehsets;
2319 
2320  MergeNodes(CoreInterface &m_field, const bool only_if_improve_quality,
2321  Tag th, bool update_mehsets)
2322  : mField(m_field), onlyIfImproveQuality(only_if_improve_quality),
2323  tH(th), updateMehsets(update_mehsets) {
2324  mField.getInterface(nodeMergerPtr);
2325  }
2326  NodeMergerInterface *nodeMergerPtr;
2327  MoFEMErrorCode mergeNodes(int line_search, EntityHandle father,
2328  EntityHandle mother, Range &proc_tets,
2329  bool add_child = true) {
2330  moab::Interface &moab = mField.get_moab();
2332  const EntityHandle conn[] = {father, mother};
2333  Range vert_tets;
2334  CHKERR moab.get_adjacencies(conn, 2, 3, false, vert_tets,
2335  moab::Interface::UNION);
2336  vert_tets = intersect(vert_tets, proc_tets);
2337  Range out_tets;
2338  CHKERR nodeMergerPtr->mergeNodes(father, mother, out_tets, &vert_tets,
2339  onlyIfImproveQuality, 0, line_search,
2340  tH);
2341 
2342  if (add_child && nodeMergerPtr->getSuccessMerge()) {
2343 
2344  Range::iterator lo, hi = proc_tets.begin();
2345  for (auto pt = vert_tets.pair_begin(); pt != vert_tets.pair_end();
2346  ++pt) {
2347  lo = proc_tets.lower_bound(hi, proc_tets.end(), pt->first);
2348  if (lo != proc_tets.end()) {
2349  hi = proc_tets.upper_bound(lo, proc_tets.end(), pt->second);
2350  proc_tets.erase(lo, hi);
2351  } else
2352  break;
2353  }
2354  proc_tets.merge(out_tets);
2355 
2356  auto &parent_child_map = nodeMergerPtr->getParentChildMap();
2357 
2358  struct ChangeChild {
2359  EntityHandle child;
2360  ChangeChild(const EntityHandle child) : child(child) {}
2361  void operator()(NodeMergerInterface::ParentChild &p) {
2362  p.cHild = child;
2363  }
2364  };
2365 
2366  std::vector<decltype(parentsChildMap.get<0>().begin())> it_vec;
2367  it_vec.reserve(parentsChildMap.size());
2368 
2369  for (auto &p : parent_child_map) {
2370 
2371  it_vec.clear();
2372  for (auto it = parentsChildMap.get<0>().equal_range(p.pArent);
2373  it.first != it.second; ++it.first)
2374  it_vec.emplace_back(it.first);
2375 
2376  for (auto it = parentsChildMap.get<1>().equal_range(p.pArent);
2377  it.first != it.second; ++it.first)
2378  it_vec.emplace_back(parentsChildMap.project<0>(it.first));
2379 
2380  for (auto &it : it_vec)
2381  parentsChildMap.modify(it, ChangeChild(p.cHild));
2382  }
2383 
2384  parentsChildMap.insert(parent_child_map.begin(),
2385  parent_child_map.end());
2386  }
2388  }
2389 
2390  MoFEMErrorCode updateRangeByChilds(Range &new_surf, Range &edges_to_merge,
2391  Range &not_merged_edges,
2392  bool add_child) {
2393  moab::Interface &moab = mField.get_moab();
2395  if (add_child) {
2396 
2397  std::vector<EntityHandle> parents_ents_vec(parentsChildMap.size());
2398  for (auto &it : parentsChildMap)
2399  parents_ents_vec.emplace_back(it.pArent);
2400  Range parent_ents;
2401  parent_ents.insert_list(parents_ents_vec.begin(),
2402  parents_ents_vec.end());
2403 
2404  Range surf_parent_ents = intersect(new_surf, parent_ents);
2405  new_surf = subtract(new_surf, surf_parent_ents);
2406  Range child_surf_ents;
2407  CHKERR updateRangeByChilds(parentsChildMap, surf_parent_ents,
2408  child_surf_ents);
2409  new_surf.merge(child_surf_ents);
2410 
2411  Range edges_to_merge_parent_ents =
2412  intersect(edges_to_merge, parent_ents);
2413  edges_to_merge = subtract(edges_to_merge, edges_to_merge_parent_ents);
2414  Range merged_child_edge_ents;
2415  CHKERR updateRangeByChilds(parentsChildMap, edges_to_merge_parent_ents,
2416  merged_child_edge_ents);
2417 
2418  Range not_merged_edges_child_ents =
2419  intersect(not_merged_edges, parent_ents);
2420  not_merged_edges =
2421  subtract(not_merged_edges, not_merged_edges_child_ents);
2422  Range not_merged_child_edge_ents;
2423  CHKERR updateRangeByChilds(parentsChildMap, not_merged_edges_child_ents,
2424  not_merged_child_edge_ents);
2425 
2426  merged_child_edge_ents =
2427  subtract(merged_child_edge_ents, not_merged_child_edge_ents);
2428  edges_to_merge.merge(merged_child_edge_ents);
2429  not_merged_edges.merge(not_merged_child_edge_ents);
2430 
2431  if (updateMehsets) {
2433  (*mField.getInterface<MeshsetsManager>()), cubit_it)) {
2434  EntityHandle cubit_meshset = cubit_it->meshset;
2435  Range meshset_ents;
2436  CHKERR moab.get_entities_by_handle(cubit_meshset, meshset_ents,
2437  true);
2438  Range child_ents;
2439  CHKERR updateRangeByChilds(parentsChildMap, meshset_ents,
2440  child_ents);
2441  CHKERR moab.add_entities(cubit_meshset, child_ents);
2442  }
2443  }
2444  }
2445 
2447  };
2448 
2449  private:
2450  NodeMergerInterface::ParentChildMap parentsChildMap;
2451  std::vector<EntityHandle> childsVec;
2452 
2453  inline MoFEMErrorCode updateRangeByChilds(
2454  const NodeMergerInterface::ParentChildMap &parent_child_map,
2455  const Range &parents, Range &childs) {
2457  childsVec.clear();
2458  childsVec.reserve(parents.size());
2459  for (auto pit = parents.pair_begin(); pit != parents.pair_end(); pit++) {
2460  auto it = parent_child_map.lower_bound(pit->first);
2461  if (it != parent_child_map.end()) {
2462  for (auto hi_it = parent_child_map.upper_bound(pit->second);
2463  it != hi_it; ++it)
2464  childsVec.emplace_back(it->cHild);
2465  }
2466  }
2467  childs.insert_list(childsVec.begin(), childsVec.end());
2469  }
2470  };
2471 
2472  /**
2473  * \brief Calculate edge length
2474  */
2475  struct LengthMap {
2476  Tag tH;
2477  CoreInterface &mField;
2478  moab::Interface &moab;
2479  const double maxLength;
2480  LengthMap(CoreInterface &m_field, Tag th, double max_length)
2481  : tH(th), mField(m_field), moab(m_field.get_moab()),
2482  maxLength(max_length) {
2483  gammaL = 1.;
2484  gammaQ = 3.;
2485  acceptedThrasholdMergeQuality = 0.5;
2486  }
2487 
2488  double
2489  gammaL; ///< Controls importance of length when ranking edges for merge
2490  double
2491  gammaQ; ///< Controls importance of quality when ranking edges for merge
2492  double acceptedThrasholdMergeQuality; ///< Do not merge quality if quality
2493  ///< above accepted thrashold
2494 
2495  MoFEMErrorCode operator()(const Range &tets, const Range &edges,
2496  LengthMapData_multi_index &length_map,
2497  double &ave) const {
2498  int num_nodes;
2499  const EntityHandle *conn;
2500  std::array<double, 12> coords;
2502  VectorAdaptor s0(3, ublas::shallow_array_adaptor<double>(3, &coords[0]));
2503  VectorAdaptor s1(3, ublas::shallow_array_adaptor<double>(3, &coords[3]));
2504  VectorDouble3 delta(3);
2505 
2506  struct NodeQuality {
2507  EntityHandle node;
2508  double quality;
2509  NodeQuality(const EntityHandle node) : node(node), quality(1) {}
2510  };
2511 
2512  typedef multi_index_container<
2513  NodeQuality, indexed_by<
2514 
2515  sequenced<>,
2516 
2517  hashed_non_unique<tag<Ent_mi_tag>,
2518  member<NodeQuality, EntityHandle,
2519  &NodeQuality::node>>
2520 
2521  >>
2522  NodeQuality_sequence;
2523 
2524  NodeQuality_sequence node_quality_sequence;
2525 
2526  Range edges_nodes;
2527  CHKERR moab.get_connectivity(tets, edges_nodes, false);
2528  Range edges_tets;
2529  CHKERR moab.get_adjacencies(edges, 3, false, edges_tets,
2530  moab::Interface::UNION);
2531  edges_tets = intersect(edges_tets, tets);
2532 
2533  for (auto node : edges_nodes)
2534  node_quality_sequence.emplace_back(node);
2535 
2536  for (auto tet : edges_tets) {
2537 
2538  CHKERR moab.get_connectivity(tet, conn, num_nodes, true);
2539  if (tH)
2540  CHKERR moab.tag_get_data(tH, conn, num_nodes, coords.data());
2541  else
2542  CHKERR moab.get_coords(conn, num_nodes, coords.data());
2543 
2544  const double q = Tools::volumeLengthQuality(coords.data());
2545 
2546  for (auto n : {0, 1, 2, 3}) {
2547  auto it = node_quality_sequence.get<1>().find(conn[n]);
2548  if (it != node_quality_sequence.get<1>().end())
2549  const_cast<double &>(it->quality) = std::min(q, it->quality);
2550  }
2551  }
2552 
2553  for (auto edge : edges) {
2554 
2555  CHKERR moab.get_connectivity(edge, conn, num_nodes, true);
2556 
2557  if (tH)
2558  CHKERR moab.tag_get_data(tH, conn, num_nodes, coords.data());
2559  else
2560  CHKERR moab.get_coords(conn, num_nodes, coords.data());
2561 
2562  double q = 1;
2563  for (auto n : {0, 1}) {
2564  auto it = node_quality_sequence.get<1>().find(conn[n]);
2565  if (it != node_quality_sequence.get<1>().end())
2566  q = std::min(q, it->quality);
2567  }
2568 
2569  if (q < acceptedThrasholdMergeQuality) {
2570  noalias(delta) = (s0 - s1) / maxLength;
2571  double dot = inner_prod(delta, delta);
2572  double val = pow(q, gammaQ) * pow(dot, 0.5 * gammaL);
2573  length_map.insert(LengthMapData(val, q, edge));
2574  }
2575  }
2576 
2577  ave = 0;
2578  for (LengthMapData_multi_index::nth_index<0>::type::iterator mit =
2579  length_map.get<0>().begin();
2580  mit != length_map.get<0>().end(); mit++) {
2581  ave += mit->qUality;
2582  }
2583  ave /= length_map.size();
2585  }
2586  };
2587 
2588  /**
2589  * \brief Topological relations
2590  */
2591  struct Toplogy {
2592 
2593  CoreInterface &mField;
2594  Tag tH;
2595  Toplogy(CoreInterface &m_field, Tag th) : mField(m_field), tH(th) {}
2596 
2597  enum TYPE {
2598  FREE = 0,
2599  SKIN = 1 << 0,
2600  SURFACE = 1 << 1,
2601  SURFACE_SKIN = 1 << 2,
2602  FRONT_ENDS = 1 << 3,
2603  FIX_EDGES = 1 << 4,
2604  FIX_CORNERS = 1 << 5
2605  };
2606 
2607  typedef map<int, Range> SetsMap;
2608 
2609  MoFEMErrorCode classifyVerts(const Range &surface, const Range &tets,
2610  const Range &fixed_edges,
2611  const Range &corner_nodes,
2612  const Range &constrain_surface,
2613  SetsMap &sets_map) const {
2614  moab::Interface &moab(mField.get_moab());
2615  Skinner skin(&moab);
2617 
2618  sets_map[FIX_CORNERS].merge(corner_nodes);
2619  Range fixed_verts;
2620  CHKERR moab.get_connectivity(fixed_edges, fixed_verts, true);
2621  sets_map[FIX_EDGES].swap(fixed_verts);
2622 
2623  Range tets_skin;
2624  CHKERR skin.find_skin(0, tets, false, tets_skin);
2625  Range tets_skin_edges;
2626  CHKERR moab.get_adjacencies(tets_skin, 1, false, tets_skin_edges,
2627  moab::Interface::UNION);
2628 
2629  // constrain surface
2630  Range constrain_surface_verts;
2631  CHKERR moab.get_connectivity(constrain_surface, constrain_surface_verts,
2632  true);
2633  Range constrain_surface_edges;
2634  CHKERR moab.get_adjacencies(constrain_surface, 1, false,
2635  constrain_surface_edges,
2636  moab::Interface::UNION);
2637 
2638  // surface skin
2639  Range surface_skin;
2640  CHKERR skin.find_skin(0, surface, false, surface_skin);
2641  Range front_in_the_body;
2642  front_in_the_body = subtract(surface_skin, tets_skin_edges);
2643  Range front_in_the_body_verts;
2644  CHKERR moab.get_connectivity(front_in_the_body, front_in_the_body_verts,
2645  true);
2646  Range front_ends;
2647  CHKERR skin.find_skin(0, front_in_the_body, false, front_ends);
2648  front_ends.merge(
2649  intersect(front_in_the_body_verts, constrain_surface_verts));
2650  sets_map[FRONT_ENDS].swap(front_ends);
2651 
2652  Range surface_skin_verts;
2653  CHKERR moab.get_connectivity(surface_skin, surface_skin_verts, true);
2654  sets_map[SURFACE_SKIN].swap(surface_skin_verts);
2655 
2656  // surface
2657  Range surface_verts;
2658  CHKERR moab.get_connectivity(surface, surface_verts, true);
2659  sets_map[SURFACE_SKIN].merge(
2660  intersect(constrain_surface_verts, surface_verts));
2661  sets_map[SURFACE].swap(surface_verts);
2662 
2663  // skin
2664  Range tets_skin_verts;
2665  CHKERR moab.get_connectivity(tets_skin, tets_skin_verts, true);
2666  sets_map[SKIN].swap(tets_skin_verts);
2667  sets_map[SKIN].merge(constrain_surface_verts);
2668 
2669  Range tets_verts;
2670  CHKERR moab.get_connectivity(tets, tets_verts, true);
2671  sets_map[FREE].swap(tets_verts);
2672 
2674  }
2675 
2676  MoFEMErrorCode getProcTets(const Range &tets, const Range &edges_to_merge,
2677  Range &proc_tets) const {
2678  moab::Interface &moab(mField.get_moab());
2680  Range edges_to_merge_verts;
2681  CHKERR moab.get_connectivity(edges_to_merge, edges_to_merge_verts, true);
2682  Range edges_to_merge_verts_tets;
2683  CHKERR moab.get_adjacencies(edges_to_merge_verts, 3, false,
2684  edges_to_merge_verts_tets,
2685  moab::Interface::UNION);
2686  edges_to_merge_verts_tets = intersect(edges_to_merge_verts_tets, tets);
2687  proc_tets.swap(edges_to_merge_verts_tets);
2689  }
2690 
2691  MoFEMErrorCode removeBadEdges(const Range &surface, const Range &tets,
2692  const Range &fixed_edges,
2693  const Range &corner_nodes,
2694  const Range &constrain_surface,
2695  Range &edges_to_merge,
2696  Range &not_merged_edges) {
2697  moab::Interface &moab(mField.get_moab());
2699 
2700  // find skin
2701  Skinner skin(&moab);
2702  Range tets_skin;
2703  CHKERR skin.find_skin(0, tets, false, tets_skin);
2704  Range surface_skin;
2705  CHKERR skin.find_skin(0, surface, false, surface_skin);
2706 
2707  // constrain surface
2708  Range constrain_surface_verts;
2709  CHKERR moab.get_connectivity(constrain_surface, constrain_surface_verts,
2710  true);
2711  Range constrain_surface_edges;
2712  CHKERR moab.get_adjacencies(constrain_surface, 1, false,
2713  constrain_surface_edges,
2714  moab::Interface::UNION);
2715 
2716  // end nodes
2717  Range tets_skin_edges;
2718  CHKERR moab.get_adjacencies(tets_skin, 1, false, tets_skin_edges,
2719  moab::Interface::UNION);
2720 
2721  Range surface_front;
2722  surface_front = subtract(surface_skin, tets_skin_edges);
2723  Range surface_front_nodes;
2724  CHKERR moab.get_connectivity(surface_front, surface_front_nodes, true);
2725 
2726  Range ends_nodes;
2727  CHKERR skin.find_skin(0, surface_front, false, ends_nodes);
2728  ends_nodes.merge(intersect(surface_front_nodes, constrain_surface_verts));
2729 
2730  // remove bad merges
2731  surface_skin.merge(constrain_surface);
2732  tets_skin_edges.merge(constrain_surface_edges);
2733 
2734  // get surface and body skin verts
2735  Range surface_edges;
2736  CHKERR moab.get_adjacencies(surface, 1, false, surface_edges,
2737  moab::Interface::UNION);
2738  // get nodes on the surface
2739  Range surface_edges_verts;
2740  CHKERR moab.get_connectivity(surface_edges, surface_edges_verts, true);
2741  // get vertices on the body skin
2742  Range tets_skin_edges_verts;
2743  CHKERR moab.get_connectivity(tets_skin_edges, tets_skin_edges_verts,
2744  true);
2745 
2746  Range edges_to_remove;
2747 
2748  // remove edges self connected to body skin
2749  {
2750  Range ents_nodes_and_edges;
2751  ents_nodes_and_edges.merge(tets_skin_edges_verts);
2752  ents_nodes_and_edges.merge(tets_skin_edges);
2753  CHKERR removeSelfConectingEdges(ents_nodes_and_edges, edges_to_remove,
2754  false);
2755  }
2756  edges_to_merge = subtract(edges_to_merge, edges_to_remove);
2757  not_merged_edges.merge(edges_to_remove);
2758 
2759  // remove edges self connected to surface
2760  {
2761  Range ents_nodes_and_edges;
2762  ents_nodes_and_edges.merge(surface_edges_verts);
2763  ents_nodes_and_edges.merge(surface_edges);
2764  ents_nodes_and_edges.merge(tets_skin_edges_verts);
2765  ents_nodes_and_edges.merge(tets_skin_edges);
2766  CHKERR removeSelfConectingEdges(ents_nodes_and_edges, edges_to_remove,
2767  false);
2768  }
2769  edges_to_merge = subtract(edges_to_merge, edges_to_remove);
2770  not_merged_edges.merge(edges_to_remove);
2771 
2772  // remove edges adjacent corner_nodes execpt those on fixed edges
2773  Range fixed_edges_nodes;
2774  CHKERR moab.get_connectivity(fixed_edges, fixed_edges_nodes, true);
2775  {
2776  Range ents_nodes_and_edges;
2777  ents_nodes_and_edges.merge(fixed_edges_nodes);
2778  ents_nodes_and_edges.merge(ends_nodes);
2779  ents_nodes_and_edges.merge(corner_nodes);
2780  ents_nodes_and_edges.merge(fixed_edges);
2781  CHKERR removeSelfConectingEdges(ents_nodes_and_edges, edges_to_remove,
2782  false);
2783  }
2784  edges_to_merge = subtract(edges_to_merge, edges_to_remove);
2785  not_merged_edges.merge(edges_to_remove);
2786 
2787  // remove edges self connected to surface
2788  CHKERR removeSelfConectingEdges(surface_edges, edges_to_remove, false);
2789  edges_to_merge = subtract(edges_to_merge, edges_to_remove);
2790  not_merged_edges.merge(edges_to_remove);
2791 
2792  // remove edges self contented on surface skin
2793  {
2794  Range ents_nodes_and_edges;
2795  ents_nodes_and_edges.merge(surface_skin);
2796  ents_nodes_and_edges.merge(fixed_edges_nodes);
2797  CHKERR removeSelfConectingEdges(ents_nodes_and_edges, edges_to_remove,
2798  false);
2799  }
2800  edges_to_merge = subtract(edges_to_merge, edges_to_remove);
2801  not_merged_edges.merge(edges_to_remove);
2802 
2803  // remove edges connecting crack front and fixed edges, except those short
2804  {
2805  Range ents_nodes_and_edges;
2806  ents_nodes_and_edges.merge(surface_skin.subset_by_type(MBEDGE));
2807  ents_nodes_and_edges.merge(fixed_edges.subset_by_type(MBEDGE));
2808  CHKERR removeSelfConectingEdges(ents_nodes_and_edges, edges_to_remove,
2809  false);
2810  }
2811  edges_to_merge = subtract(edges_to_merge, edges_to_remove);
2812  not_merged_edges.merge(edges_to_remove);
2813 
2814  // remove crack front nodes connected to the surface, except those short
2815  {
2816  Range ents_nodes_and_edges;
2817  ents_nodes_and_edges.merge(surface_front_nodes);
2818  ents_nodes_and_edges.merge(surface_front);
2819  ents_nodes_and_edges.merge(tets_skin_edges_verts);
2820  ents_nodes_and_edges.merge(tets_skin_edges);
2821  CHKERR removeSelfConectingEdges(ents_nodes_and_edges, edges_to_remove,
2822  false);
2823  }
2824  edges_to_merge = subtract(edges_to_merge, edges_to_remove);
2825  not_merged_edges.merge(edges_to_remove);
2826 
2828  }
2829 
2830  private:
2831  MoFEMErrorCode removeSelfConectingEdges(const Range &ents,
2832  Range &edges_to_remove,
2833  bool debug) const {
2834  moab::Interface &moab(mField.get_moab());
2836  // get nodes
2837  Range ents_nodes = ents.subset_by_type(MBVERTEX);
2838  if (ents_nodes.empty()) {
2839  CHKERR moab.get_connectivity(ents, ents_nodes, true);
2840  }
2841  // edges adj. to nodes
2842  Range ents_nodes_edges;
2843  CHKERR moab.get_adjacencies(ents_nodes, 1, false, ents_nodes_edges,
2844  moab::Interface::UNION);
2845  // nodes of adj. edges
2846  Range ents_nodes_edges_nodes;
2847  CHKERR moab.get_connectivity(ents_nodes_edges, ents_nodes_edges_nodes,
2848  true);
2849  // hanging nodes
2850  ents_nodes_edges_nodes = subtract(ents_nodes_edges_nodes, ents_nodes);
2851  Range ents_nodes_edges_nodes_edges;
2852  CHKERR moab.get_adjacencies(ents_nodes_edges_nodes, 1, false,
2853  ents_nodes_edges_nodes_edges,
2854  moab::Interface::UNION);
2855  // remove edges adj. to hanging edges
2856  ents_nodes_edges =
2857  subtract(ents_nodes_edges, ents_nodes_edges_nodes_edges);
2858  ents_nodes_edges =
2859  subtract(ents_nodes_edges, ents.subset_by_type(MBEDGE));
2860 
2861  edges_to_remove.swap(ents_nodes_edges);
2862  if (debug) {
2863  CHKERR SaveData(moab)("edges_to_remove.vtk", edges_to_remove);
2864  }
2866  }
2867  };
2868 
2869  Range not_merged_edges;
2870  CHKERR Toplogy(m_field, th)
2871  .removeBadEdges(surface, tets, fixed_edges, corner_nodes,
2872  constrainSurface, edges_to_merge, not_merged_edges);
2873  Toplogy::SetsMap sets_map;
2874  CHKERR Toplogy(m_field, th)
2875  .classifyVerts(surface, tets, fixed_edges, corner_nodes, constrainSurface,
2876  sets_map);
2877  if (debug) {
2878  for (Toplogy::SetsMap::reverse_iterator sit = sets_map.rbegin();
2879  sit != sets_map.rend(); sit++) {
2880  std::string name = "classification_verts_" +
2881  boost::lexical_cast<std::string>(sit->first) + ".vtk";
2882  if (!sit->second.empty())
2883  CHKERR SaveData(moab)(name, sit->second);
2884  }
2885  }
2886  Range proc_tets;
2887  CHKERR Toplogy(m_field, th).getProcTets(tets, edges_to_merge, proc_tets);
2888  out_tets = subtract(tets, proc_tets);
2889 
2890  if (bit_ptr) {
2891  Range all_out_ents = out_tets;
2892  for (int dd = 2; dd >= 0; dd--) {
2893  CHKERR moab.get_adjacencies(out_tets, dd, false, all_out_ents,
2894  moab::Interface::UNION);
2895  }
2896  CHKERR m_field.getInterface<BitRefManager>()->addBitRefLevel(all_out_ents,
2897  *bit_ptr);
2898  }
2899 
2900  int nb_nodes_merged = 0;
2901  LengthMapData_multi_index length_map;
2902  new_surf = surface;
2903 
2904  auto save_merge_step = [&](const int pp, const Range collapsed_edges) {
2906  Range adj_faces;
2907  CHKERR moab.get_adjacencies(proc_tets, 2, false, adj_faces,
2908  moab::Interface::UNION);
2909  std::string name;
2910  name = "node_merge_step_" + boost::lexical_cast<std::string>(pp) + ".vtk";
2911  CHKERR SaveData(moab)(
2912  name, unite(intersect(new_surf, adj_faces), collapsed_edges));
2913  name =
2914  "edges_to_merge_step_" + boost::lexical_cast<std::string>(pp) + ".vtk";
2915  CHKERR SaveData(moab)(
2916  name, unite(intersect(new_surf, adj_faces), edges_to_merge));
2918  };
2919 
2920  if (debug)
2921  CHKERR save_merge_step(0, Range());
2922 
2923  double ave0 = 0, ave = 0, min = 0, min_p = 0, min_pp;
2924  for (int pp = 0; pp != nbMaxMergingCycles; ++pp) {
2925 
2926  int nb_nodes_merged_p = nb_nodes_merged;
2927  length_map.clear();
2928  min_pp = min_p;
2929  min_p = min;
2930  CHKERR LengthMap(m_field, th, aveLength)(proc_tets, edges_to_merge,
2931  length_map, ave);
2932 
2933  if(!length_map.empty())
2934  min = length_map.get<2>().begin()->qUality;
2935  if (pp == 0) {
2936  ave0 = ave;
2937  }
2938 
2939  int nn = 0;
2940  Range collapsed_edges;
2941  MergeNodes merge_nodes(m_field, true, th, update_meshsets);
2942 
2943  for (auto mit = length_map.get<0>().begin();
2944  mit != length_map.get<0>().end(); mit++, nn++) {
2945 
2946  if (!mit->skip) {
2947 
2948  auto get_father_and_mother =
2949  [&](EntityHandle &father, EntityHandle &mother, int &line_search) {
2951  int num_nodes;
2952  const EntityHandle *conn;
2953  CHKERR moab.get_connectivity(mit->eDge, conn, num_nodes, true);
2954  std::array<int, 2> conn_type = {0, 0};
2955  for (int nn = 0; nn != 2; nn++) {
2956  for (Toplogy::SetsMap::reverse_iterator sit = sets_map.rbegin();
2957  sit != sets_map.rend(); sit++) {
2958  if (sit->second.find(conn[nn]) != sit->second.end()) {
2959  conn_type[nn] |= sit->first;
2960  }
2961  }
2962  }
2963  int type_father, type_mother;
2964  if (conn_type[0] > conn_type[1]) {
2965  father = conn[0];
2966  mother = conn[1];
2967  type_father = conn_type[0];
2968  type_mother = conn_type[1];
2969  } else {
2970  father = conn[1];
2971  mother = conn[0];
2972  type_father = conn_type[1];
2973  type_mother = conn_type[0];
2974  }
2975  if (type_father == type_mother) {
2976  line_search = lineSearchSteps;
2977  }
2979  };
2980 
2981  int line_search = 0;
2982  EntityHandle father, mother;
2983  CHKERR get_father_and_mother(father, mother, line_search);
2984  CHKERR merge_nodes.mergeNodes(line_search, father, mother, proc_tets);
2985  if (m_field.getInterface<NodeMergerInterface>()->getSuccessMerge()) {
2986  const EntityHandle father_and_mother[] = {father, mother};
2987  Range adj_tets;
2988  CHKERR moab.get_adjacencies(father_and_mother, 1, 3, false, adj_tets);
2989  Range adj_tets_nodes;
2990  CHKERR moab.get_connectivity(adj_tets, adj_tets_nodes, true);
2991  Range adj_edges;
2992  CHKERR moab.get_adjacencies(adj_tets_nodes, 1, false, adj_edges,
2993  moab::Interface::UNION);
2994  for (auto ait : adj_edges) {
2995  auto miit = length_map.get<1>().find(ait);
2996  if (miit != length_map.get<1>().end())
2997  (const_cast<LengthMapData &>(*miit)).skip = true;
2998  }
2999  nb_nodes_merged++;
3000  collapsed_edges.insert(mit->eDge);
3001  }
3002 
3003  if (nn > static_cast<int>(length_map.size() / fraction_level))
3004  break;
3005  if (mit->qUality > ave)
3006  break;
3007  }
3008  }
3009 
3010  CHKERR merge_nodes.updateRangeByChilds(new_surf, edges_to_merge,
3011  not_merged_edges, true);
3012 
3013  MOFEM_LOG_C("WORLD", Sev::verbose,
3014  "(%d) Number of nodes merged %d ave q %3.4e min q %3.4e", pp,
3015  nb_nodes_merged, ave, min);
3016 
3017  if (debug)
3018  CHKERR save_merge_step(pp + 1, collapsed_edges);
3019 
3020  if (nb_nodes_merged == nb_nodes_merged_p)
3021  break;
3022  if (min > 1e-2 && min == min_pp)
3023  break;
3024  if (min > ave0)
3025  break;
3026 
3027  Range adj_edges;
3028  CHKERR moab.get_adjacencies(proc_tets, 1, false, adj_edges,
3029  moab::Interface::UNION);
3030  edges_to_merge = intersect(edges_to_merge, adj_edges);
3031  CHKERR Toplogy(m_field, th)
3032  .removeBadEdges(new_surf, proc_tets, fixed_edges, corner_nodes,
3033  constrainSurface, edges_to_merge, not_merged_edges);
3034  }
3035 
3036  auto reconstruct_refined_ents = [&]() {
3040  };
3041 
3042  // Add function which reconstruct core multi-index. Node merging is messy
3043  // process and entity parent could be changed without notification to
3044  // multi-index. TODO Issue has to be tracked down better, however in principle
3045  // is better not to modify multi-index each time parent is changed, that makes
3046  // code slow. Is better to do it in the bulk as below.
3047  CHKERR reconstruct_refined_ents();
3048 
3049  if (bit_ptr)
3050  CHKERR m_field.getInterface<BitRefManager>()->setBitRefLevel(proc_tets,
3051  *bit_ptr);
3052 
3053  out_tets.merge(proc_tets);
3054  Range adj_faces;
3055  CHKERR moab.get_adjacencies(out_tets, 2, false, adj_faces,
3056  moab::Interface::UNION);
3057  new_surf = intersect(new_surf, adj_faces);
3058 
3060 }
3061 
3063  const int fraction_level, const BitRefLevel cut_bit,
3064  const BitRefLevel trim_bit, const BitRefLevel bit, const Range &surface,
3065  const Range &fixed_edges, const Range &corner_nodes, Tag th,
3066  const bool update_meshsets, const bool debug) {
3067  CoreInterface &m_field = cOre;
3069  Range tets_level;
3070  CHKERR m_field.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
3071  trim_bit, BitRefLevel().set(), MBTET, tets_level);
3072 
3073  Range edges_to_merge;
3074  CHKERR m_field.getInterface<BitRefManager>()->getEntitiesByRefLevel(
3075  trim_bit, cut_bit | trim_bit, edges_to_merge);
3076 
3077  // get all entities not in database
3078  Range all_ents_not_in_database_before;
3079  CHKERR cOre.getInterface<BitRefManager>()->getAllEntitiesNotInDatabase(
3080  all_ents_not_in_database_before);
3081 
3082  edges_to_merge = edges_to_merge.subset_by_type(MBEDGE);
3083  if (debug)
3084  CHKERR SaveData(m_field.get_moab())("edges_to_merge.vtk", edges_to_merge);
3085 
3086  Range out_new_tets, out_new_surf;
3087  CHKERR mergeBadEdges(fraction_level, tets_level, surface, fixed_edges,
3088  corner_nodes, edges_to_merge, out_new_tets, out_new_surf,
3089  th, update_meshsets, &bit, debug);
3090 
3091  // get all entities not in database after merge
3092  Range all_ents_not_in_database_after;
3093  CHKERR cOre.getInterface<BitRefManager>()->getAllEntitiesNotInDatabase(
3094  all_ents_not_in_database_after);
3095 
3096  // delete hanging entities
3097  all_ents_not_in_database_after =
3098  subtract(all_ents_not_in_database_after, all_ents_not_in_database_before);
3099  Range meshsets;
3100  CHKERR m_field.get_moab().get_entities_by_type(0, MBENTITYSET, meshsets,
3101  false);
3102  for (auto m : meshsets)
3103  CHKERR m_field.get_moab().remove_entities(m,
3104  all_ents_not_in_database_after);
3105 
3106  m_field.get_moab().delete_entities(all_ents_not_in_database_after);
3107 
3108  mergedVolumes.swap(out_new_tets);
3109  mergedSurfaces.swap(out_new_surf);
3110 
3112 }
3113 
3115  CoreInterface &m_field = cOre;
3116  moab::Interface &moab = m_field.get_moab();
3118  Range nodes;
3119  if (bit.none())
3120  CHKERR moab.get_entities_by_type(0, MBVERTEX, nodes);
3121  else
3122  CHKERR m_field.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
3123  bit, BitRefLevel().set(), MBVERTEX, nodes);
3124  std::vector<double> coords(3 * nodes.size());
3125  CHKERR moab.get_coords(nodes, &coords[0]);
3126  CHKERR moab.tag_set_data(th, nodes, &coords[0]);
3128 }
3129 
3131  const BitRefLevel mask) {
3132  CoreInterface &m_field = cOre;
3133  moab::Interface &moab = m_field.get_moab();
3135  Range nodes;
3136  if (bit.none())
3137  CHKERR moab.get_entities_by_type(0, MBVERTEX, nodes);
3138  else
3139  CHKERR m_field.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
3140  bit, mask, MBVERTEX, nodes);
3141  std::vector<double> coords(3 * nodes.size());
3142  CHKERR moab.tag_get_data(th, nodes, &coords[0]);
3143  CHKERR moab.set_coords(nodes, &coords[0]);
3145 }
3146 
3148  CoreInterface &m_field = cOre;
3149  moab::Interface &moab = m_field.get_moab();
3151  CHKERR SaveData(moab)(prefix + "out_vol.vtk", vOlume);
3152  CHKERR SaveData(moab)(prefix + "out_surface.vtk", sUrface);
3153  CHKERR SaveData(moab)(prefix + "out_cut_edges.vtk", cutEdges);
3154  CHKERR SaveData(moab)(prefix + "out_cut_new_volumes.vtk", cutNewVolumes);
3155  CHKERR SaveData(moab)(prefix + "out_cut_new_surfaces.vtk", cutNewSurfaces);
3156  CHKERR SaveData(moab)(prefix + "out_cut_zero_distance_ents.vtk",
3159 }
3160 
3162  moab::Interface &moab = cOre.getInterface<CoreInterface>()->get_moab();
3164  CHKERR SaveData(moab)("out_trim_surface.vtk", sUrface);
3165  CHKERR SaveData(moab)("out_trim_new_volumes.vtk", trimNewVolumes);
3166  CHKERR SaveData(moab)("out_trim_new_surfaces.vtk", trimNewSurfaces);
3167  CHKERR SaveData(moab)("out_trim_edges.vtk", trimEdges);
3169 }
3170 
3171 } // namespace MoFEM
MoFEMFunctionReturnHot
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
Definition: definitions.h:447
MoFEM::Types::VectorDouble6
VectorBoundedArray< double, 6 > VectorDouble6
Definition: Types.hpp:95
MoFEM::UnknownInterface::getInterface
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface refernce to pointer of interface.
Definition: UnknownInterface.hpp:93
MoFEM::CutMeshInterface::projectZeroDistanceEnts
const Range & projectZeroDistanceEnts() const
Definition: CutMeshInterface.hpp:473
MoFEM::CutMeshInterface::constrainSurface
Range constrainSurface
Definition: CutMeshInterface.hpp:577
MoFEM::CoreTmp< 0 >
Core (interface) class.
Definition: Core.hpp:82
MoFEM::CutMeshInterface::trimOnly
MoFEMErrorCode trimOnly(const BitRefLevel trim_bit, Tag th, const double tol_trim_close, Range *fixed_edges=NULL, Range *corner_nodes=NULL, const bool update_meshsets=false, const bool debug=false)
Trim mesh only.
Definition: CutMeshInterface.cpp:263
surface
Definition: surface.py:1
MoFEM::Types::VectorDouble3
VectorBoundedArray< double, 3 > VectorDouble3
Definition: Types.hpp:92
sdf_hertz.d
float d
Definition: sdf_hertz.py:5
MoFEM::NodeMergerInterface::getParentChildMap
ParentChildMap & getParentChildMap()
Get map of parent cand child.
Definition: NodeMerger.hpp:121
FTensor::Tensor1
Definition: Tensor1_value.hpp:8
EntityHandle
MoFEM::Tools::NO_SOLUTION
@ NO_SOLUTION
Definition: Tools.hpp:530
MoFEM::CutMeshInterface::setFront
MoFEMErrorCode setFront(const Range surface)
Definition: CutMeshInterface.cpp:36
MoFEM::MeshRefinement::addVerticesInTheMiddleOfEdges
MoFEMErrorCode addVerticesInTheMiddleOfEdges(const EntityHandle meshset, const BitRefLevel &bit, const bool recursive=false, int verb=QUIET, EntityHandle start_v=0)
make vertices in the middle of edges in meshset and add them to refinement levels defined by bit
Definition: MeshRefinement.cpp:42
MoFEM::NodeMergerInterface::mergeNodes
MoFEMErrorCode mergeNodes(EntityHandle father, EntityHandle mother, Range &out_tets, Range *tets_ptr=NULL, const bool only_if_improve_quality=false, const double move=0, const int line_search=0, Tag th=NULL, const int verb=0)
merge nodes which sharing edge
Definition: NodeMerger.cpp:37
MoFEM::CutMeshInterface::mergeSurface
MoFEMErrorCode mergeSurface(const Range surface)
merge surface entities
Definition: CutMeshInterface.cpp:120
MoFEM::CutMeshInterface::findLevelSetVolumes
MoFEMErrorCode findLevelSetVolumes(Tag th, Range &vol_edges, const bool remove_adj_prims_edges, int verb=QUIET, const bool debug=false, const std::string edges_file_name=string())
Find level set volumes.
Definition: CutMeshInterface.cpp:662
MoFEM::CutMeshInterface::setVolume
MoFEMErrorCode setVolume(const Range volume)
set volume entities
Definition: CutMeshInterface.cpp:108
MoFEM::Tools
Auxiliary tools.
Definition: Tools.hpp:19
MoFEM::PrismInterface
Create interface from given surface and insert flat prisms in-between.
Definition: PrismInterface.hpp:23
MoFEM::CutMeshInterface::TreeData::unitRayDir
VectorDouble3 unitRayDir
Definition: CutMeshInterface.hpp:563
MoFEM::CutMeshInterface::setCoords
MoFEMErrorCode setCoords(Tag th, const BitRefLevel bit=BitRefLevel(), const BitRefLevel mask=BitRefLevel().set())
set coords from tag
Definition: CutMeshInterface.cpp:3130
MoFEM::CutMeshInterface::CutMeshInterface
CutMeshInterface(const MoFEM::Core &core)
Definition: CutMeshInterface.cpp:23
MoFEM::CutMeshInterface::makeFront
MoFEMErrorCode makeFront(const bool debug=false)
Create front from the surface.
Definition: CutMeshInterface.cpp:450
MoFEM::CutMeshInterface::setTagData
MoFEMErrorCode setTagData(Tag th, const BitRefLevel bit=BitRefLevel())
set coords to tag
Definition: CutMeshInterface.cpp:3114
MoFEM::CutMeshInterface::sUrface
Range sUrface
Definition: CutMeshInterface.hpp:539
MoFEM::Exceptions::MoFEMErrorCode
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
Definition: Exceptions.hpp:56
MoFEM::CutMeshInterface::trimEdges
Range trimEdges
Definition: CutMeshInterface.hpp:555
MoFEM::Types::MatrixDouble
UBlasMatrix< double > MatrixDouble
Definition: Types.hpp:77
MoFEM::CutMeshInterface::mergedVolumes
Range mergedVolumes
Definition: CutMeshInterface.hpp:557
MoFEM::th
Tag th
Definition: Projection10NodeCoordsOnField.cpp:122
MoFEM::CutMeshInterface::copySurface
MoFEMErrorCode copySurface(const Range surface, Tag th=NULL, double *shift=NULL, double *origin=NULL, double *transform=NULL, const std::string save_mesh="")
copy surface entities
Definition: CutMeshInterface.cpp:48
MoFEM::CutMeshInterface::mergedSurfaces
Range mergedSurfaces
Definition: CutMeshInterface.hpp:558
MoFEM::CutMeshInterface::maxLength
double maxLength
Maximal edge length.
Definition: CutMeshInterface.hpp:573
MoFEM::CutMeshInterface::cutNewVertices
Range cutNewVertices
Definition: CutMeshInterface.hpp:550
MoFEM::CutMeshInterface::verticesOnTrimEdges
map< EntityHandle, TreeData > verticesOnTrimEdges
Definition: CutMeshInterface.hpp:570
MoFEM::CutMeshInterface::cutNewSurfaces
Range cutNewSurfaces
Definition: CutMeshInterface.hpp:547
MoFEM::CutMeshInterface::trimSurface
MoFEMErrorCode trimSurface(Range *fixed_edge, Range *corner_nodes, const double tol=1e-4, Tag th=NULL, const bool debug=false)
Trim surface from faces beyond front.
Definition: CutMeshInterface.cpp:2028
MoFEM::NodeMergerInterface
Merge node by collapsing edge between them.
Definition: NodeMerger.hpp:18
THROW_MESSAGE
#define THROW_MESSAGE(msg)
Throw MoFEM exception.
Definition: definitions.h:561
MoFEM::CutMeshInterface::cOre
MoFEM::Core & cOre
Definition: CutMeshInterface.hpp:23
sdf.r
int r
Definition: sdf.py:8
MoFEM::CutMeshInterface::cutEdgesInMiddle
MoFEMErrorCode cutEdgesInMiddle(const BitRefLevel bit, Range &cut_vols, Range &cut_surf, Range &cut_verts, const bool debug=false)
cut edges
Definition: CutMeshInterface.cpp:1298
MoFEM::reconstructMultiIndex
MoFEMErrorCode reconstructMultiIndex(const MI &mi, MO &&mo=Modify_change_nothing())
Template used to reconstruct multi-index.
Definition: Templates.hpp:1824
MoFEM::CutMeshInterface::cutFrontVolumes
Range cutFrontVolumes
Definition: CutMeshInterface.hpp:576
MoFEM::Tools::minDistanceFromSegments
static SEGMENT_MIN_DISTANCE minDistanceFromSegments(const double *w_ptr, const double *v_ptr, const double *k_ptr, const double *l_ptr, double *const tvw_ptr=nullptr, double *const tlk_ptr=nullptr)
Find points on two segments in closest distance.
Definition: Tools.cpp:469
MoFEM::Interface
DeprecatedCoreInterface Interface
Definition: Interface.hpp:1975
MoFEM::NodeMergerInterface::ParentChild
Definition: NodeMerger.hpp:102
MoFEM::MeshRefinement::refineTets
MoFEMErrorCode refineTets(const EntityHandle meshset, const BitRefLevel &bit, int verb=QUIET, const bool debug=false)
refine TET in the meshset
Definition: MeshRefinement.cpp:197
MoFEM::CutMeshInterface::moveMidNodesOnCutEdges
MoFEMErrorCode moveMidNodesOnCutEdges(Tag th=NULL)
projecting of mid edge nodes on new mesh on surface
Definition: CutMeshInterface.cpp:1447
MoFEM::CutMeshInterface::clearMap
MoFEMErrorCode clearMap()
Definition: CutMeshInterface.cpp:30
MoFEM::Exceptions::rval
static MoFEMErrorCodeGeneric< moab::ErrorCode > rval
Definition: Exceptions.hpp:74
MoFEM::CutMeshInterface::mergeVolumes
MoFEMErrorCode mergeVolumes(const Range volume)
merge volume entities
Definition: CutMeshInterface.cpp:126
MoFEM::CutMeshInterface::TreeData
Definition: CutMeshInterface.hpp:560
CHKERR
#define CHKERR
Inline error check.
Definition: definitions.h:535
MoFEM::CutMeshInterface::cutTrimAndMerge
MoFEMErrorCode cutTrimAndMerge(int &first_bit, const int fraction_level, Tag th, const double tol_geometry, const double tol_cut_close, const double tol_trim_close, Range &fixed_edges, Range &corner_nodes, const bool update_meshsets=false, const bool debug=false)
Cut, trim and merge.
Definition: CutMeshInterface.cpp:379
MoFEM::CutMeshInterface
Interface to cut meshes.
Definition: CutMeshInterface.hpp:19
MoFEM::CoreInterface::get_moab
virtual moab::Interface & get_moab()=0
MoFEM::CutMeshInterface::findEdgesToTrim
MoFEMErrorCode findEdgesToTrim(Range *fixed_edges, Range *corner_nodes, Tag th=NULL, const double tol=1e-4, const bool debug=false)
Find edges to trimEdges.
Definition: CutMeshInterface.cpp:1480
MoFEM::CutMeshInterface::mergeBadEdges
MoFEMErrorCode mergeBadEdges(const int fraction_level, const Range &tets, const Range &surface, const Range &fixed_edges, const Range &corner_nodes, Range &merged_nodes, Range &out_tets, Range &new_surf, Tag th, const bool update_meshsets=false, const BitRefLevel *bit_ptr=NULL, const bool debug=false)
Merge edges.
Definition: CutMeshInterface.cpp:2302
MoFEM::CutMeshInterface::saveTrimEdges
MoFEMErrorCode saveTrimEdges()
Definition: CutMeshInterface.cpp:3161
MoFEM
implementation of Data Operators for Forces and Sources
Definition: Common.hpp:10
a
constexpr double a
Definition: approx_sphere.cpp:30
delta
static constexpr double delta
Definition: prism_elements_from_surface.cpp:18
MoFEM::getVectorAdaptor
auto getVectorAdaptor(T1 ptr, const size_t n)
Get Vector adaptor.
Definition: Templates.hpp:31
MoFEM::MeshRefinement
Mesh refinement interface.
Definition: MeshRefinement.hpp:26
MOFEM_LOG_C
#define MOFEM_LOG_C(channel, severity, format,...)
Definition: LogManager.hpp:311
MoFEM::CutMeshInterface::cutNewVolumes
Range cutNewVolumes
Definition: CutMeshInterface.hpp:546
MoFEM::CutMeshInterface::fRont
Range fRont
Definition: CutMeshInterface.hpp:538
bit
auto bit
set bit
Definition: hanging_node_approx.cpp:75
MoFEM::NodeMergerInterface::ParentChildMap
multi_index_container< ParentChild, indexed_by< ordered_unique< member< ParentChild, EntityHandle, &ParentChild::pArent > >, ordered_non_unique< member< ParentChild, EntityHandle, &ParentChild::cHild > > > > ParentChildMap
Definition: NodeMerger.hpp:115
MoFEM::CutMeshInterface::treeSurfPtr
boost::shared_ptr< OrientedBoxTreeTool > treeSurfPtr
Definition: CutMeshInterface.hpp:542
MoFEM::PrismInterface::splitSides
MoFEMErrorCode splitSides(const EntityHandle meshset, const BitRefLevel &bit, const int msId, const CubitBCType cubit_bc_type, const bool add_interface_entities, const bool recursive=false, int verb=QUIET)
Split nodes and other entities of tetrahedra on both sides of the interface and insert flat prisms in...
Definition: PrismInterface.cpp:519
MoFEM::CutMeshInterface::TreeData::dIst
double dIst
Definition: CutMeshInterface.hpp:561
MoFEM::CutMeshInterface::zeroDistanceVerts
Range zeroDistanceVerts
Definition: CutMeshInterface.hpp:549
surface.surface
def surface(x, y, z, eta)
Definition: surface.py:3
MoFEM::CutMeshInterface::removePathologicalFrontTris
MoFEMErrorCode removePathologicalFrontTris(const BitRefLevel split_bit, Range &ents)
Remove pathological elements on surface internal front.
Definition: CutMeshInterface.cpp:2235
MoFEM::BitRefManager::addBitRefLevel
MoFEMErrorCode addBitRefLevel(const Range &ents, const BitRefLevel &bit, int verb=QUIET) const
add bit ref level to ref entity
Definition: BitRefManager.cpp:554
MoFEM::CutMeshInterface::verticesOnCutEdges
map< EntityHandle, TreeData > verticesOnCutEdges
Definition: CutMeshInterface.hpp:568
MoFEM::CutMeshInterface::setConstrainSurface
MoFEMErrorCode setConstrainSurface(const Range surf)
Set the constrain surface object.
Definition: CutMeshInterface.cpp:114
MoFEM::CutMeshInterface::rootSetSurf
EntityHandle rootSetSurf
Definition: CutMeshInterface.hpp:543
MoFEM::CutMeshInterface::cutSurfaceVolumes
Range cutSurfaceVolumes
Definition: CutMeshInterface.hpp:575
MoFEM::CutMeshInterface::trimNewVolumes
Range trimNewVolumes
Definition: CutMeshInterface.hpp:552
CutMeshFunctionBegin
#define CutMeshFunctionBegin
Definition: CutMeshInterface.cpp:7
MoFEM::CutMeshInterface::lineSearchSteps
int lineSearchSteps
Definition: CutMeshInterface.hpp:27
MoFEM::CutMeshInterface::snapSurfaceToEdges
MoFEMErrorCode snapSurfaceToEdges(const Range surface_edges, const Range fixed_edges, const double rel_tol, const double abs_tol, Tag th=nullptr, const bool debug=false)
Definition: CutMeshInterface.cpp:152
MoFEM::CutMeshInterface::zeroDistanceEnts
Range zeroDistanceEnts
Definition: CutMeshInterface.hpp:548
MoFEM::NodeMergerInterface::getSuccessMerge
bool getSuccessMerge()
Return true if successful merge.
Definition: NodeMerger.hpp:31
MoFEM::CutMeshInterface::setSurface
MoFEMErrorCode setSurface(const Range surface)
set surface entities
Definition: CutMeshInterface.cpp:42
t
constexpr double t
plate stiffness
Definition: plate.cpp:59
MoFEM::Types::VectorAdaptor
VectorShallowArrayAdaptor< double > VectorAdaptor
Definition: Types.hpp:115
debug
static const bool debug
Definition: dm_create_subdm.cpp:12
i
FTensor::Index< 'i', SPACE_DIM > i
Definition: hcurl_divergence_operator_2d.cpp:27
MoFEM::CutMeshInterface::query_interface
MoFEMErrorCode query_interface(boost::typeindex::type_index type_index, UnknownInterface **iface) const
Definition: CutMeshInterface.cpp:16
MoFEM::CutMeshInterface::findEdgesToCut
MoFEMErrorCode findEdgesToCut(Range vol, int verb=QUIET, const bool debug=false)
find edges to cut
Definition: CutMeshInterface.cpp:897
MoFEM::CutMeshInterface::createFrontLevelSets
MoFEMErrorCode createFrontLevelSets(Range vol, Tag th=nullptr, int verb=QUIET, const bool debug=false)
Calculate distance from mesh nodes to surface front.
Definition: CutMeshInterface.cpp:609
MoFEM::CutMeshInterface::buildTree
MoFEMErrorCode buildTree()
build tree
Definition: CutMeshInterface.cpp:215
FTensor::Index< 'i', 3 >
convert.n
n
Definition: convert.py:82
MoFEM::BitRefManager::updateRangeByChildren
MoFEMErrorCode updateRangeByChildren(const Range &parent, Range &child, MoFEMTypes bh=MF_ZERO)
Update range by childrens.
Definition: BitRefManager.cpp:1144
MoFEM::UnknownInterface
base class for all interface classes
Definition: UnknownInterface.hpp:34
MoFEM::CutMeshInterface::saveCutEdges
MoFEMErrorCode saveCutEdges(const std::string prefix="")
Definition: CutMeshInterface.cpp:3147
v
const double v
phase velocity of light in medium (cm/ns)
Definition: initial_diffusion.cpp:40
Range
MoFEM::CutMeshInterface::projectEntitiesQualityTrashold
double projectEntitiesQualityTrashold
Definition: CutMeshInterface.hpp:29
FTensor::dd
const Tensor2_symmetric_Expr< const ddTensor0< T, Dim, i, j >, typename promote< T, double >::V, Dim, i, j > dd(const Tensor0< T * > &a, const Index< i, Dim > index1, const Index< j, Dim > index2, const Tensor1< int, Dim > &d_ijk, const Tensor1< double, Dim > &d_xyz)
Definition: ddTensor0.hpp:33
MOFEM_LOG
#define MOFEM_LOG(channel, severity)
Log.
Definition: LogManager.hpp:308
MoFEM::CutMeshInterface::SaveData
Definition: CutMeshInterface.hpp:498
MoFEM::CutMeshInterface::LengthMapData
Definition: CutMeshInterface.hpp:512
MoFEM::CutMeshInterface::trimEdgesInTheMiddle
MoFEMErrorCode trimEdgesInTheMiddle(const BitRefLevel bit, const bool debug=false)
trim edges
Definition: CutMeshInterface.cpp:1969
MoFEM::CutMeshInterface::snapSurfaceSkinToEdges
MoFEMErrorCode snapSurfaceSkinToEdges(const Range fixed_edges, const double rel_tol, const double abs_tol, Tag th=nullptr, const bool debug=false)
Definition: CutMeshInterface.cpp:132
MoFEM::PrismInterface::getSides
MoFEMErrorCode getSides(const int msId, const CubitBCType cubit_bc_type, const BitRefLevel mesh_bit_level, const bool recursive, int verb=QUIET)
Store tetrahedra from each side of the interface separately in two child meshsets of the parent meshs...
Definition: PrismInterface.cpp:56
MoFEM::CutMeshInterface::refineMesh
MoFEMErrorCode refineMesh(const int init_bit_level, const int surf_levels, const int front_levels, Range *fixed_edges=nullptr, int verb=QUIET, const bool debug=false)
Refine and set level sets.
Definition: CutMeshInterface.cpp:809
HenckyOps::f
auto f
Definition: HenckyOps.hpp:15
MoFEM::CutMeshInterface::trimNewVertices
Range trimNewVertices
Definition: CutMeshInterface.hpp:553
j
FTensor::Index< 'j', 3 > j
Definition: matrix_function.cpp:19
MoFEM::CutMeshInterface::cutEdges
Range cutEdges
Definition: CutMeshInterface.hpp:545
MatrixBoundedArray< double, 9 >
MoFEM::CoreInterface::get_ref_ents
virtual const RefEntity_multiIndex * get_ref_ents() const =0
Get the ref ents object.
UBlasVector< double >
MoFEM::Exceptions::ierr
static MoFEMErrorCodeGeneric< PetscErrorCode > ierr
Definition: Exceptions.hpp:76
MOFEM_DATA_INCONSISTENCY
@ MOFEM_DATA_INCONSISTENCY
Definition: definitions.h:31
MoFEM::CutMeshInterface::trimNewSurfaces
Range trimNewSurfaces
Definition: CutMeshInterface.hpp:554
MoFEM::Composite_ParentEnt_And_EntType_mi_tag
Definition: TagMultiIndices.hpp:78
MoFEM::MeshsetsManager
Interface for managing meshsets containing materials and boundary conditions.
Definition: MeshsetsManager.hpp:104
MoFEM::CutMeshInterface::splitSides
MoFEMErrorCode splitSides(const BitRefLevel split_bit, const BitRefLevel bit, const Range &ents, Tag th=NULL)
split sides
Definition: CutMeshInterface.cpp:2266
MoFEM::CutMeshInterface::TreeData::rayPoint
VectorDouble3 rayPoint
Definition: CutMeshInterface.hpp:564
MoFEM::CutMeshInterface::LengthMapData_multi_index
multi_index_container< LengthMapData, indexed_by< ordered_non_unique< member< LengthMapData, double, &LengthMapData::lEngth > >, hashed_unique< member< LengthMapData, EntityHandle, &LengthMapData::eDge > >, ordered_non_unique< member< LengthMapData, double, &LengthMapData::qUality > > > > LengthMapData_multi_index
Definition: CutMeshInterface.hpp:535
FTensor::transform
Tensor2_Expr< transform_Tensor2< A, B, T, Dim0, Dim1, i, j >, T, Dim0, Dim1, i, j > transform(const Tensor2_Expr< A, T, Dim0, Dim1, i, j > &a, B function)
Definition: Tensor2_transform.hpp:27
MoFEM::CutMeshInterface::edgesToTrim
map< EntityHandle, TreeData > edgesToTrim
Definition: CutMeshInterface.hpp:569
MoFEM::CutMeshInterface::aveLength
double aveLength
Average edge length.
Definition: CutMeshInterface.hpp:572
MoFEM::Tools::volumeLengthQuality
static double volumeLengthQuality(const double *coords)
Calculate tetrahedron volume length quality.
Definition: Tools.cpp:15
MoFEM::CutMeshInterface::getNewTrimSurfaces
const Range & getNewTrimSurfaces() const
Definition: CutMeshInterface.hpp:479
_IT_CUBITMESHSETS_FOR_LOOP_
#define _IT_CUBITMESHSETS_FOR_LOOP_(MESHSET_MANAGER, IT)
Iterator that loops over all the Cubit MeshSets in a moFEM field.
Definition: MeshsetsManager.hpp:34
MoFEM::CutMeshInterface::createSurfaceLevelSets
MoFEMErrorCode createSurfaceLevelSets(int verb=QUIET, const bool debug=false)
Calculate distance from mesh nodes to cut surface.
Definition: CutMeshInterface.cpp:477
m
FTensor::Index< 'm', 3 > m
Definition: shallow_wave.cpp:80
MoFEM::BitRefManager
Managing BitRefLevels.
Definition: BitRefManager.hpp:21
MoFEM::Types::MatrixAdaptor
MatrixShallowArrayAdaptor< double > MatrixAdaptor
Matrix adaptor.
Definition: Types.hpp:132
MoFEM::CutMeshInterface::edgesToCut
map< EntityHandle, TreeData > edgesToCut
Definition: CutMeshInterface.hpp:567
MoFEM::Types::BitRefLevel
std::bitset< BITREFLEVEL_SIZE > BitRefLevel
Bit structure attached to each entity identifying to what mesh entity is attached.
Definition: Types.hpp:40
MoFEM::CutMeshInterface::vOlume
Range vOlume
Definition: CutMeshInterface.hpp:540
MoFEM::PrismInterface::findFacesWithThreeNodesOnInternalSurfaceSkin
MoFEMErrorCode findFacesWithThreeNodesOnInternalSurfaceSkin(const EntityHandle sideset, const BitRefLevel mesh_bit_level, const bool recursive, Range &faces_with_three_nodes_on_front, int verb=QUIET)
Find triangles which have three nodes on internal surface skin.
Definition: PrismInterface.cpp:393
MoFEMFunctionBeginHot
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:440
QUIET
@ QUIET
Definition: definitions.h:208
MoFEM::CoreInterface
Interface.
Definition: Interface.hpp:27
MoFEM::CutMeshInterface::nbMaxMergingCycles
int nbMaxMergingCycles
Definition: CutMeshInterface.hpp:28
k
FTensor::Index< 'k', 3 > k
Definition: matrix_function.cpp:20
MoFEM::CutMeshInterface::cutAndTrim
MoFEMErrorCode cutAndTrim(int &first_bit, Tag th, const double tol_geometry, const double tol_cut_close, const double tol_trim_close, Range *fixed_edges=NULL, Range *corner_nodes=NULL, const bool update_meshsets=false, const bool debug=false)
Cut and trim.
Definition: CutMeshInterface.cpp:309
MoFEM::NodeMergerInterface::ParentChild::cHild
EntityHandle cHild
Definition: NodeMerger.hpp:104
MoFEMFunctionReturn
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
Definition: definitions.h:416
MoFEMFunctionBegin
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:346
l
FTensor::Index< 'l', 3 > l
Definition: matrix_function.cpp:21
tol
double tol
Definition: mesh_smoothing.cpp:27
MoFEM::Types::VectorDouble12
VectorBoundedArray< double, 12 > VectorDouble12
Definition: Types.hpp:97
MoFEM::CutMeshInterface::moveMidNodesOnTrimmedEdges
MoFEMErrorCode moveMidNodesOnTrimmedEdges(Tag th=NULL)
move trimmed edges mid nodes
Definition: CutMeshInterface.cpp:1465
MoFEM::CutMeshInterface::cutOnly
MoFEMErrorCode cutOnly(Range vol, const BitRefLevel cut_bit, Tag th, const double tol_geometry, const double tol_cut_close, Range *fixed_edges=NULL, Range *corner_nodes=NULL, const bool update_meshsets=false, const bool debug=false)
Cut mesh only.
Definition: CutMeshInterface.cpp:226