v0.8.4
Classes | Public Types | Public Member Functions | Public Attributes | Private Types | Private Member Functions | Private Attributes | List of all members
MoFEM::NodeMergerInterface Struct Reference

merge node from two bit levels More...

#include <src/interfaces/NodeMerger.hpp>

Inheritance diagram for MoFEM::NodeMergerInterface:
[legend]
Collaboration diagram for MoFEM::NodeMergerInterface:
[legend]

Classes

struct  FaceMap
 
struct  ParentChild
 

Public Types

typedef multi_index_container< ParentChild, indexed_by< hashed_unique< member< ParentChild, EntityHandle,&ParentChild::pArent > >, hashed_non_unique< member< ParentChild, EntityHandle,&ParentChild::cHild > > > > ParentChildMap
 

Public Member Functions

MoFEMErrorCode query_interface (const MOFEMuuid &uuid, UnknownInterface **iface) const
 
 NodeMergerInterface (const MoFEM::Core &core)
 
bool getSucessMerge ()
 Return true if successful merge. More...
 
void setErrorIfNoCommonEdge (const bool b=true)
 Set error if no common edge. More...
 
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 More...
 
MoFEMErrorCode mergeNodes (EntityHandle father, EntityHandle mother, BitRefLevel bit, Range *tets_ptr=NULL, const bool only_if_improve_quality=false, const double move=0, Tag th=NULL)
 merge nodes which sharing edge More...
 
MoFEMErrorCode mergeNodes (EntityHandle father, EntityHandle mother, BitRefLevel bit, BitRefLevel tets_from_bit_ref_level, const bool only_if_improve_quality=false, const double move=0, Tag th=NULL)
 merge nodes which sharing edge More...
 
ParentChildMapgetParentChildMap ()
 Get map of parent cand child. More...
 
- Public Member Functions inherited from MoFEM::UnknownInterface
template<class IFACE >
MoFEMErrorCode registerInterface (const MOFEMuuid &uuid, bool error_if_registration_failed=true)
 Register interface. More...
 
template<class IFACE , bool VERIFY = false>
MoFEMErrorCode getInterface (const MOFEMuuid &uuid, IFACE *&iface) const
 Get interface by uuid and return reference to pointer of interface. More...
 
template<class IFACE >
MoFEMErrorCode getInterface (IFACE *&iface) const
 Get interface refernce to pointer of interface. More...
 
template<class IFACE >
MoFEMErrorCode getInterface (IFACE **const iface) const
 Get interface pointer to pointer of interface. More...
 
template<class IFACE , typename boost::enable_if< boost::is_pointer< IFACE >, int >::type = 0>
IFACE getInterface () const
 Get interface pointer to pointer of interface. More...
 
template<class IFACE , typename boost::enable_if< boost::is_reference< IFACE >, int >::type = 0>
IFACE getInterface () const
 Get reference to interface. More...
 
template<class IFACE >
IFACE * getInterface () const
 Function returning pointer to interface. More...
 
virtual ~UnknownInterface ()
 
virtual MoFEMErrorCode getLibVersion (Version &version) const
 Get library version. More...
 
virtual const MoFEMErrorCode getFileVersion (moab::Interface &moab, Version &version) const
 Get database major version. More...
 
virtual MoFEMErrorCode getInterfaceVersion (Version &version) const
 Get database major version. More...
 
template<>
MoFEMErrorCode getInterface (const MOFEMuuid &uuid, UnknownInterface *&iface) const
 

Public Attributes

MoFEM::CorecOre
 

Private Types

typedef multi_index_container< FaceMap, indexed_by< hashed_unique< composite_key< FaceMap, member< FaceMap, EntityHandle,&FaceMap::n0 >, member< FaceMap, EntityHandle,&FaceMap::n1 > > > > > FaceMapIdx
 

Private Member Functions

MoFEMErrorCode minQuality (Range &check_tests, EntityHandle father, EntityHandle mother, double *coords_move, double &min_quality, Tag th=NULL, boost::function< double(double, double)> f=[](double a, double b) -> double { return std::min(a, b);})
 Calualte quality if nodes merged. More...
 
MoFEMErrorCode lineSearch (Range &check_tests, EntityHandle father, EntityHandle mother, int line_search, FTensor::Tensor1< double, 3 > &t_move, Tag th=NULL)
 Use bisection method to find point of edge collapse. More...
 

Private Attributes

bool successMerge
 True if marge is success. More...
 
bool errorIfNoCommonEdge
 Send error if no common edge. More...
 
ParentChildMap parentChildMap
 

Additional Inherited Members

- Protected Member Functions inherited from MoFEM::UnknownInterface
boost::typeindex::type_index getClassIdx (const MOFEMuuid &uid) const
 Get type name for interface Id. More...
 
MOFEMuuid getUId (const boost::typeindex::type_index &class_idx) const
 Get interface Id for class name. More...
 

Detailed Description

merge node from two bit levels

Definition at line 29 of file NodeMerger.hpp.

Member Typedef Documentation

◆ FaceMapIdx

typedef multi_index_container< FaceMap, indexed_by< hashed_unique< composite_key< FaceMap, member<FaceMap,EntityHandle,&FaceMap::n0>, member<FaceMap,EntityHandle,&FaceMap::n1> > > > > MoFEM::NodeMergerInterface::FaceMapIdx
private

Definition at line 213 of file NodeMerger.hpp.

◆ ParentChildMap

typedef multi_index_container< ParentChild, indexed_by< hashed_unique< member<ParentChild,EntityHandle,&ParentChild::pArent> >, hashed_non_unique< member<ParentChild,EntityHandle,&ParentChild::cHild> > > > MoFEM::NodeMergerInterface::ParentChildMap

Definition at line 150 of file NodeMerger.hpp.

Constructor & Destructor Documentation

◆ NodeMergerInterface()

MoFEM::NodeMergerInterface::NodeMergerInterface ( const MoFEM::Core core)

Definition at line 34 of file NodeMerger.hpp.

34  :
35  cOre(const_cast<MoFEM::Core&>(core)),
36  successMerge(false),
37  errorIfNoCommonEdge(false) {
38  }
bool successMerge
True if marge is success.
Definition: NodeMerger.hpp:162
bool errorIfNoCommonEdge
Send error if no common edge.
Definition: NodeMerger.hpp:163

Member Function Documentation

◆ getParentChildMap()

ParentChildMap& MoFEM::NodeMergerInterface::getParentChildMap ( )

Get map of parent cand child.

Returns

Definition at line 156 of file NodeMerger.hpp.

156  {
157  return parentChildMap;
158  }
ParentChildMap parentChildMap
Definition: NodeMerger.hpp:193

◆ getSucessMerge()

bool MoFEM::NodeMergerInterface::getSucessMerge ( )

Return true if successful merge.

Returns
Error code

Definition at line 44 of file NodeMerger.hpp.

44 { return successMerge; }
bool successMerge
True if marge is success.
Definition: NodeMerger.hpp:162

◆ lineSearch()

MoFEMErrorCode MoFEM::NodeMergerInterface::lineSearch ( Range &  check_tests,
EntityHandle  father,
EntityHandle  mother,
int  line_search,
FTensor::Tensor1< double, 3 > &  t_move,
Tag  th = NULL 
)
private

Use bisection method to find point of edge collapse.

Parameters
check_testsrange of tets to check quality
fatherfirst node of the edge
mothersecond node of the edge
line_searchnumber of iterations
coords_movenode to move
Returns
error code

Definition at line 467 of file NodeMerger.cpp.

469  {
470  Interface &m_field = cOre;
472 
473  EntityHandle conn[] = {father, mother};
474 
475  double coords[6];
476  if(th == NULL) {
477  CHKERR m_field.get_moab().get_coords(conn,2,coords);
478  } else {
479  CHKERR m_field.get_moab().tag_get_data(th,conn,2,coords);
480  }
481 
484  coords[0],coords[1],coords[2]
485  );
487  for(int nn = 0;nn!=3;nn++) {
488  t_delta(nn) = coords[3+nn]-t_coords(nn);
489  }
490 
491  t_move(i) = t_coords(i);
492  double min_quality_i = 1;
493  auto abs_min = [](double a, double b) {
494  return std::min(fabs(a), fabs(b));
495  };
496  CHKERR minQuality(check_tests, father, mother, &t_move(0), min_quality_i, th,
497  abs_min);
498 
499  t_move(i) = t_coords(i) + t_delta(i);
500  double min_quality_k = 1;
501  CHKERR minQuality(check_tests, father, mother, &t_move(0), min_quality_k, th,
502  abs_min);
503 
504  double alpha_i = 0;
505  double alpha_k = 1;
506 
507  for (int ii = 0; ii != line_search; ii++) {
508  double min_quality = 1;
509  double alpha = (alpha_i+alpha_k)*0.5;
510  t_move(i) = t_coords(i) + alpha * t_delta(i);
511  ierr = minQuality(
512  check_tests,father,mother,&t_move(0),min_quality,th
513  ); CHKERRG(ierr);
514  if(min_quality_i >= min_quality_k) {
515  min_quality_k = min_quality;
516  alpha_k = alpha;
517  } else {
518  min_quality_i = min_quality;
519  alpha_i = alpha;
520  }
521  }
522 
523  if(min_quality_i > min_quality_k) {
524  t_move(i) = t_coords(i)+alpha_i*t_delta(i);
525  // cerr << min_quality_i << endl << endl;
526  } else {
527  t_move(i) = t_coords(i)+alpha_k*t_delta(i);
528  // cerr << min_quality_k << endl << endl;
529  }
530 
532 }
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return() ...
Definition: definitions.h:498
#define CHKERRG(n)
Check error code of MoFEM/MOAB/PETSc function.
Definition: definitions.h:565
static MoFEMErrorCodeGeneric< PetscErrorCode > ierr
Definition: Common.hpp:80
#define CHKERR
Inline error check.
Definition: definitions.h:617
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:443
MoFEMErrorCode minQuality(Range &check_tests, EntityHandle father, EntityHandle mother, double *coords_move, double &min_quality, Tag th=NULL, boost::function< double(double, double)> f=[](double a, double b) -> double { return std::min(a, b);})
Calualte quality if nodes merged.
Definition: NodeMerger.cpp:408

◆ mergeNodes() [1/3]

MoFEMErrorCode MoFEM::NodeMergerInterface::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

Father is sties, mother is merged.

Parameters
fathernode to which mother is merged to.
mothermerged node
tetrahedraafter merge
testonly tets_ptr from range are changed
only_if_improve_qualityDo merge if that improve quality
movefather by fraction of edge length move=[0,1]

Move node on the edge, 0 not move, 1 move to mother side, 0.5 will be in the middle.

Definition at line 66 of file NodeMerger.cpp.

69  {
70  Interface &m_field = cOre;
73 
74  // Get edges adjacent to father and mother, i.e. mother is merged to father.
75  Range father_edges;
76  CHKERR m_field.get_moab().get_adjacencies(&father, 1, 1, false, father_edges);
77  Range mother_edges;
78  CHKERR m_field.get_moab().get_adjacencies(&mother, 1, 1, false, mother_edges);
79 
80  // Get tets adjacent to mother and father
81  Range father_tets;
82  CHKERR m_field.get_moab().get_adjacencies(&father, 1, 3, false, father_tets);
83  Range mother_tets;
84  CHKERR m_field.get_moab().get_adjacencies(&mother, 1, 3, false, mother_tets);
85  if (tets_ptr != NULL) {
86  mother_tets = intersect(mother_tets,*tets_ptr);
87  father_tets = intersect(father_tets,*tets_ptr);
88  }
89 
90  // Find common edge
91  Range common_edge;
92  common_edge = intersect(father_edges, mother_edges);
93  if (tets_ptr != NULL) {
94  Range tets = unite(father_tets, mother_tets);
95  Range tets_edges;
96  CHKERR m_field.get_moab().get_adjacencies(tets, 1, false, tets_edges,
97  moab::Interface::UNION);
98  common_edge = intersect(common_edge, tets_edges);
99  father_edges = intersect(father_edges, tets_edges);
100  mother_edges = intersect(mother_edges, tets_edges);
101  }
102 
103  // No common edge, merge no possible
104  if (errorIfNoCommonEdge && common_edge.empty()) {
105  SETERRQ(PETSC_COMM_SELF, 1, "no common edge between nodes");
106  } else if (common_edge.empty()) {
107  Range seed_tets;
108  if (tets_ptr != NULL) {
109  seed_tets.merge(*tets_ptr);
110  }
111  out_tets = seed_tets;
112  successMerge = false;
114  }
115 
116  // Common edge tets, that tests will be squashed
117  Range edge_tets;
118  CHKERR m_field.get_moab().get_adjacencies(common_edge, 3, true, edge_tets);
119  // Intersect with ptr_tets (usually associated with some bit level)
120  if (tets_ptr != NULL) {
121  edge_tets = intersect(edge_tets, *tets_ptr);
122  }
123  // Mother tets, has only one mother vertex and no father vertex.
124  mother_tets = subtract(mother_tets, edge_tets);
125  father_tets = subtract(father_tets, edge_tets);
126 
127  auto get_coords = [&m_field](Tag th, const EntityHandle *conn,
128  const int num_nodes) {
129  VectorDouble coords(3 * num_nodes);
130  if (th == NULL) {
131  CHKERR m_field.get_moab().get_coords(conn, num_nodes, &coords[0]);
132  } else {
133  CHKERR m_field.get_moab().tag_get_data(th, conn, num_nodes, &coords[0]);
134  }
135  return coords;
136  };
137 
138  auto get_tensor = [](VectorDouble &coords,const int shift) {
140  &coords[shift], &coords[shift+1], &coords[shift+2]);
141  };
142 
143 
144 
145  // move father coord is move > 0
147  if (move > 0) {
148  EntityHandle conn[] = {father, mother};
149  VectorDouble coords = get_coords(th, conn, 2);
150  auto t_n0 = get_tensor(coords,0);
151  auto t_n1 = get_tensor(coords,3);
152  t_move(i) = t_n0(i) + move * (t_n1(i) - t_n0(i));
153  }
154 
155  if (line_search > 0) {
156  Range check_tests = unite(father_tets, mother_tets);
157  CHKERR lineSearch(check_tests, father, mother, line_search, t_move, th);
158  }
159 
160  if (only_if_improve_quality) {
161  Range check_tests = mother_tets;
162  // no need to check father tets since no change of quality for them
163  if (move > 0 || line_search) {
164  check_tests.merge(father_tets);
165  }
166 
167  auto abs_min = [](double a, double b) {
168  return std::min(fabs(a), fabs(b));
169 
170  };
171  double min_quality0 = 1;
172  CHKERR minQuality(edge_tets, 0, 0, NULL, min_quality0, th, abs_min);
173  CHKERR minQuality(check_tests, 0, 0, NULL, min_quality0, th, abs_min);
174  double min_quality = 1;
176  check_tests, father, mother,
177  ((move > 0) || line_search) ? &t_move(0) : NULL, min_quality, th);
178  if (min_quality < min_quality0) {
179  if (tets_ptr != NULL) {
180  out_tets = *tets_ptr;
181  }
182  successMerge = false;
184  }
185 
186  }
187 
188  // Move node
189  if (move > 0 || line_search) {
190  if (th == NULL) {
191  CHKERR m_field.get_moab().set_coords(&father, 1, &t_move(0));
192  } else {
193  CHKERR m_field.get_moab().tag_set_data(th, &father, 1, &t_move(0));
194  }
195  }
196 
197  auto get_conn = [&m_field](const EntityHandle ent,
198  int *ret_num_nodes = nullptr) {
199  int num_nodes;
200  const EntityHandle *conn;
201  CHKERR m_field.get_moab().get_connectivity(ent, conn, num_nodes, true);
202  if (ret_num_nodes)
203  *ret_num_nodes = num_nodes;
204  return conn;
205  };
206 
207  auto create_tet = [this, &m_field](const EntityHandle *new_conn,
208  const EntityHandle parent) {
209  EntityHandle tet;
210  Range tets;
211  CHKERR m_field.get_moab().get_adjacencies(new_conn, 4, 3, false, tets);
212  bool tet_found = false;
213  for (auto it_tet : tets) {
214  const EntityHandle *tet_conn;
215  int num_nodes;
216  CHKERR m_field.get_moab().get_connectivity(it_tet, tet_conn, num_nodes,
217  true);
218  const EntityHandle *p = std::find(tet_conn, &tet_conn[4], new_conn[0]);
219  if (p != &tet_conn[4]) {
220  int s = std::distance(tet_conn, p);
221  int n = 0;
222  for (; n != 4; ++n) {
223  const int idx[] = {0, 1, 2, 3, 0, 1, 2, 3};
224  if (tet_conn[idx[s + n]] != new_conn[n])
225  break;
226  }
227  if (n == 4 && !tet_found) {
228  tet = it_tet;
229  tet_found = true;
230  } else if(n == 4) {
231  THROW_MESSAGE("More that one tet with the same connectivity");
232  }
233  }
234  }
235  if (!tet_found) {
236  // Create tet with new connectivity
237  CHKERR m_field.get_moab().create_element(MBTET, new_conn, 4, tet);
238  CHKERR m_field.get_moab().tag_set_data(cOre.get_th_RefParentHandle(),
239  &tet, 1, &parent);
240  parentChildMap.insert(ParentChild(parent, tet));
241  }
242  return tet;
243  };
244 
245  auto swap_conn = [](EntityHandle *new_conn) {
246  EntityHandle n0 = new_conn[0];
247  new_conn[0] = new_conn[1];
248  new_conn[1] = n0;
249  return new_conn;
250  };
251 
252  // clear map
253  parentChildMap.clear();
254 
255  Range created_tets;
256  Range negative_volume_tets;
257 
258  for (auto f_tet : father_tets) {
259  const EntityHandle *conn = get_conn(f_tet);
260  VectorDouble coords = get_coords(th, conn, 4);
261  double new_v = Tools::tetVolume(&coords[0]);
262  if (new_v < 0) {
263  EntityHandle new_conn[4];
264  copy(conn, &conn[4], new_conn);
265  swap_conn(new_conn);
266  negative_volume_tets.insert(f_tet);
267  // add tet to range
268  created_tets.insert(create_tet(new_conn, f_tet));
269  }
270  }
271 
272  for (auto m_tet : mother_tets) {
273  const EntityHandle *conn = get_conn(m_tet);
274  EntityHandle new_conn[4];
275  // Replace mother vertices by father vertices
276  int nb_mother_verts = 0;
277  for (int nn = 0; nn < 4; nn++) {
278  if (conn[nn] == father) {
279  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
280  "Tet has father vertex, impossible but here it is");
281  }
282  if (conn[nn] == mother) {
283  new_conn[nn] = father;
284  nb_mother_verts++;
285  } else {
286  new_conn[nn] = conn[nn];
287  }
288  }
289  if (nb_mother_verts != 1) {
290  SETERRQ1(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
291  "Tet should have only one vertex but have %d", nb_mother_verts);
292  }
293 
294  VectorDouble new_coords = get_coords(th, new_conn, 4);
295  double new_v = Tools::tetVolume(&new_coords[0]);
296  if (new_v < 0) {
297  swap_conn(new_conn);
298  }
299 
300  // add tet to range
301  created_tets.insert(create_tet(new_conn, m_tet));
302  }
303 
304  // Loop over mother adjacent entities to use them as parents
305  Range adj_father_ents;
306  for (int dd = 1; dd <= 2; dd++) {
307  CHKERR m_field.get_moab().get_adjacencies(
308  created_tets, dd, true, adj_father_ents, moab::Interface::UNION);
309  }
310  FaceMapIdx face_map;
311  for (auto ent : adj_father_ents) {
312  int num_nodes;
313  const EntityHandle *conn = get_conn(ent,&num_nodes);
314  EntityHandle small_conn[num_nodes];
315  int ii = 0;
316  int nn = 0;
317  bool father_node = false;
318  for (; nn != num_nodes; nn++) {
319  if (conn[nn] == father) {
320  father_node = true;
321  } else {
322  small_conn[ii++] = conn[nn];
323  }
324  }
325  if (father_node) {
326  if (ii > 1) {
327  std::sort(&small_conn[0], &small_conn[ii]);
328  }
329  if (ii == 2) {
330  face_map.insert(FaceMap(ent, small_conn[0], small_conn[1]));
331  } else {
332  face_map.insert(FaceMap(ent, small_conn[0], 0));
333  }
334  }
335  }
336 
337  Range adj_mother_ents;
338  for (int dd = 1; dd <= 2; ++dd) {
339  CHKERR m_field.get_moab().get_adjacencies(
340  mother_tets, dd, false, adj_mother_ents, moab::Interface::UNION);
341  }
342 
343  adj_mother_ents.erase(common_edge[0]);
344  for (auto ent : adj_mother_ents) {
345  int num_nodes;
346  const EntityHandle *conn = get_conn(ent, &num_nodes);
347  // EntityHandle new_conn[num_nodes];
348  EntityHandle small_conn[num_nodes];
349  int nb_new_node = 0;
350  int nn = 0;
351  int ii = 0;
352  for (; nn != num_nodes; ++nn) {
353  if (conn[nn] == mother) {
354  // new_conn[nn] = father;
355  nb_new_node++;
356  } else {
357  // new_conn[nn] = conn[nn];
358  small_conn[ii++] = conn[nn];
359  }
360  }
361  if (nb_new_node > 0) {
362  if (ii > 1) {
363  std::sort(&small_conn[0], &small_conn[ii]);
364  }
365  EntityHandle n0 = small_conn[0], n1 = 0;
366  if (ii == 2) {
367  n1 = small_conn[1];
368  }
369  FaceMapIdx::iterator fit = face_map.find(boost::make_tuple(n0, n1));
370  if (fit == face_map.end()) {
371  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "Entity not found");
372  }
373  const EntityHandle child = fit->e;
374  const EntityHandle parent = ent;
375  if (m_field.get_moab().dimension_from_handle(parent) !=
376  m_field.get_moab().dimension_from_handle(child)) {
377  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
378  "Huston we have a problem!");
379  }
380  CHKERR m_field.get_moab().tag_set_data(cOre.get_th_RefParentHandle(),
381  &parent, 1, &child);
382  // create map
383  parentChildMap.insert(ParentChild(parent, child));
384  }
385  }
386 
387  // Seed tets to given bit level
388  Range seed_tets;
389  if (tets_ptr != NULL) {
390  seed_tets.merge(*tets_ptr);
391  mother_tets.merge(negative_volume_tets);
392  mother_tets.merge(edge_tets);
393  seed_tets = subtract(seed_tets, mother_tets);
394  }
395  seed_tets.merge(created_tets);
396  out_tets.swap(seed_tets);
397 
398  successMerge = true;
399 
400  if (verb > VERY_VERBOSE) {
401  std::cout << "nodes merged" << endl;
402  }
403 
405 }
Tag get_th_RefParentHandle() const
Definition: Core.hpp:150
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
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return() ...
Definition: definitions.h:498
#define THROW_MESSAGE(a)
Throw MoFEM exception.
Definition: definitions.h:641
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return() ...
Definition: definitions.h:528
bool successMerge
True if marge is success.
Definition: NodeMerger.hpp:162
static double tetVolume(const double *coords)
Calculate volume of tetrahedron.
Definition: Tools.cpp:47
ParentChildMap parentChildMap
Definition: NodeMerger.hpp:193
bool errorIfNoCommonEdge
Send error if no common edge.
Definition: NodeMerger.hpp:163
multi_index_container< FaceMap, indexed_by< hashed_unique< composite_key< FaceMap, member< FaceMap, EntityHandle,&FaceMap::n0 >, member< FaceMap, EntityHandle,&FaceMap::n1 > > > > > FaceMapIdx
Definition: NodeMerger.hpp:213
ublas::vector< double, DoubleAllocator > VectorDouble
Definition: Common.hpp:211
#define CHKERR
Inline error check.
Definition: definitions.h:617
MoFEMErrorCode lineSearch(Range &check_tests, EntityHandle father, EntityHandle mother, int line_search, FTensor::Tensor1< double, 3 > &t_move, Tag th=NULL)
Use bisection method to find point of edge collapse.
Definition: NodeMerger.cpp:467
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:443
MoFEMErrorCode minQuality(Range &check_tests, EntityHandle father, EntityHandle mother, double *coords_move, double &min_quality, Tag th=NULL, boost::function< double(double, double)> f=[](double a, double b) -> double { return std::min(a, b);})
Calualte quality if nodes merged.
Definition: NodeMerger.cpp:408

◆ mergeNodes() [2/3]

MoFEMErrorCode MoFEM::NodeMergerInterface::mergeNodes ( EntityHandle  father,
EntityHandle  mother,
BitRefLevel  bit,
Range *  tets_ptr = NULL,
const bool  only_if_improve_quality = false,
const double  move = 0,
Tag  th = NULL 
)

merge nodes which sharing edge

Father is sties, mother is merged.

Parameters
fathernode to which mother is merged to.
mothermerged node
bitlevel of mesh merged nodes mesh
testonly tets_ptr from range are changed
only_if_improve_qualityDo merge if that improve quality
movefather by fraction of edge length move=[0,1]

Move node on the edge, 0 not move, 1 move to mother side, 0.5 will be in the middle.

Definition at line 535 of file NodeMerger.cpp.

542  {
543  Interface& m_field = cOre;
545  Range out_tets;
546  ierr = mergeNodes(
547  father,mother,out_tets,tets_ptr,only_if_improve_quality,move,0,th
548  ); CHKERRG(ierr);
549  ierr = m_field.getInterface<BitRefManager>()->setBitRefLevel(out_tets,bit); CHKERRG(ierr);
551 }
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:522
#define CHKERRG(n)
Check error code of MoFEM/MOAB/PETSc function.
Definition: definitions.h:565
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return() ...
Definition: definitions.h:528
static MoFEMErrorCodeGeneric< PetscErrorCode > ierr
Definition: Common.hpp:80
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:66

◆ mergeNodes() [3/3]

MoFEMErrorCode MoFEM::NodeMergerInterface::mergeNodes ( EntityHandle  father,
EntityHandle  mother,
BitRefLevel  bit,
BitRefLevel  tets_from_bit_ref_level,
const bool  only_if_improve_quality = false,
const double  move = 0,
Tag  th = NULL 
)

merge nodes which sharing edge

Father is sties, mother is merged.

Parameters
fathernode to which mother is merged to.
mothermerged node
tets_from_bit_ref_levelonly tetrahedrons from bit level are changed
only_if_improve_qualityDo merge if that improve quality
movefather by fraction of edge length move=[0,1]

Move node on the edge, 0 not move, 1 move to mother side, 0.5 will be in the middle.

Definition at line 553 of file NodeMerger.cpp.

560  {
561  Interface& m_field = cOre;
563  Range level_tets;
564  ierr = m_field.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
565  tets_from_bit_ref_level,BitRefLevel().set(),MBTET,level_tets
566  ); CHKERRG(ierr);
567  ierr = mergeNodes(father,mother,bit,&level_tets,only_if_improve_quality,move,th); CHKERRG(ierr);
569 }
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:522
#define CHKERRG(n)
Check error code of MoFEM/MOAB/PETSc function.
Definition: definitions.h:565
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return() ...
Definition: definitions.h:528
std::bitset< BITREFLEVEL_SIZE > BitRefLevel
Bit structure attached to each entity identifying to what mesh entity is attached.
Definition: Common.hpp:147
static MoFEMErrorCodeGeneric< PetscErrorCode > ierr
Definition: Common.hpp:80
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:66

◆ minQuality()

MoFEMErrorCode MoFEM::NodeMergerInterface::minQuality ( Range &  check_tests,
EntityHandle  father,
EntityHandle  mother,
double coords_move,
double min_quality,
Tag  th = NULL,
boost::function< double(double, double)>  f = [](double a, double b) -> double { return std::min(a, b); } 
)
private

Calualte quality if nodes merged.

Parameters
check_teststets to check
fatherfirst node of the edge
mothersecond node of the edge
coords_movemoved father node
min_qualitycalculated quality
Returns
error code

Definition at line 408 of file NodeMerger.cpp.

411  {
412  Interface &m_field = cOre;
413  double coords[12];
415  for (Range::iterator tit = check_tests.begin(); tit != check_tests.end();
416  tit++) {
417  const EntityHandle *conn;
418  int num_nodes;
419  CHKERR m_field.get_moab().get_connectivity(*tit, conn, num_nodes, true);
420  if (mother > 0) {
421  EntityHandle new_conn[4];
422  // Replace mother vertices by father vertices
423  int nb_mother_verts = 0;
424  int father_nn = 0;
425  for (int nn = 0; nn < 4; nn++) {
426  if (conn[nn] == father) {
427  father_nn = nn;
428  }
429  if (conn[nn] == mother) {
430  new_conn[nn] = father;
431  father_nn = nn;
432  nb_mother_verts++;
433  } else {
434  new_conn[nn] = conn[nn];
435  }
436  }
437  if (nb_mother_verts > 1) {
438  SETERRQ1(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
439  "Tet should have no more than one mother vertex but have %d",
440  nb_mother_verts);
441  }
442  if (th == NULL) {
443  CHKERR m_field.get_moab().get_coords(new_conn, num_nodes, coords);
444  } else {
445  CHKERR m_field.get_moab().tag_get_data(th, new_conn, num_nodes, coords);
446  }
447  if (coords_move) {
448  int shift = 3 * father_nn;
449  for (int nn = 0; nn != 3; nn++) {
450  coords[shift + nn] = coords_move[nn];
451  }
452  }
453  } else {
454  if (th == NULL) {
455  CHKERR m_field.get_moab().get_coords(conn, num_nodes, coords);
456  } else {
457  CHKERR m_field.get_moab().tag_get_data(th, conn, num_nodes, coords);
458  }
459  }
460  double quality = Tools::volumeLengthQuality(coords);
461  min_quality = fmin(min_quality, quality);
462  }
464 };
static double volumeLengthQuality(const double *coords)
Calculate tetrahedron volume length quality.
Definition: Tools.cpp:32
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return() ...
Definition: definitions.h:498
#define CHKERR
Inline error check.
Definition: definitions.h:617
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:443

◆ query_interface()

MoFEMErrorCode MoFEM::NodeMergerInterface::query_interface ( const MOFEMuuid uuid,
UnknownInterface **  iface 
) const
virtual

Implements MoFEM::UnknownInterface.

Definition at line 55 of file NodeMerger.cpp.

55  {
57  *iface = NULL;
58  if(uuid == IDD_MOFEMNodeMerger) {
59  *iface = const_cast<NodeMergerInterface*>(this);
61  }
62  SETERRQ(PETSC_COMM_SELF,MOFEM_DATA_INCONSISTENCY,"unknown interface");
64 }
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:522
static const MOFEMuuid IDD_MOFEMNodeMerger
Definition: NodeMerger.hpp:23
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return() ...
Definition: definitions.h:528
NodeMergerInterface(const MoFEM::Core &core)
Definition: NodeMerger.hpp:34

◆ setErrorIfNoCommonEdge()

void MoFEM::NodeMergerInterface::setErrorIfNoCommonEdge ( const bool  b = true)

Set error if no common edge.

Parameters
bIf true send error if false no error

Definition at line 50 of file NodeMerger.hpp.

50  {
52  }
bool errorIfNoCommonEdge
Send error if no common edge.
Definition: NodeMerger.hpp:163

Member Data Documentation

◆ cOre

MoFEM::Core& MoFEM::NodeMergerInterface::cOre

Definition at line 33 of file NodeMerger.hpp.

◆ errorIfNoCommonEdge

bool MoFEM::NodeMergerInterface::errorIfNoCommonEdge
private

Send error if no common edge.

Definition at line 163 of file NodeMerger.hpp.

◆ parentChildMap

ParentChildMap MoFEM::NodeMergerInterface::parentChildMap
private

Definition at line 193 of file NodeMerger.hpp.

◆ successMerge

bool MoFEM::NodeMergerInterface::successMerge
private

True if marge is success.

Definition at line 162 of file NodeMerger.hpp.


The documentation for this struct was generated from the following files: