www.mooseframework.org
EFAFragment3D.C
Go to the documentation of this file.
1 /****************************************************************/
2 /* MOOSE - Multiphysics Object Oriented Simulation Environment */
3 /* */
4 /* All contents are licensed under LGPL V2.1 */
5 /* See LICENSE for full restrictions */
6 /****************************************************************/
7 
8 #include "EFAFragment3D.h"
9 
10 #include "EFAVolumeNode.h"
11 #include "EFANode.h"
12 #include "EFAEdge.h"
13 #include "EFAFace.h"
14 #include "EFAFuncs.h"
15 #include "EFAElement3D.h"
16 #include "EFAError.h"
17 
19  bool create_faces,
20  const EFAElement3D * from_host,
21  unsigned int frag_id)
22  : EFAFragment(), _host_elem(host)
23 {
24  if (create_faces)
25  {
26  if (!from_host)
27  EFAError("EFAfragment3D constructor must have a from_host to copy from");
28  if (frag_id == std::numeric_limits<unsigned int>::max()) // copy the from_host itself
29  {
30  for (unsigned int i = 0; i < from_host->numFaces(); ++i)
31  _faces.push_back(new EFAFace(*from_host->getFace(i)));
32  }
33  else
34  {
35  if (frag_id > from_host->numFragments() - 1)
36  EFAError("In EFAfragment3D constructor fragment_copy_index out of bounds");
37  for (unsigned int i = 0; i < from_host->getFragment(frag_id)->numFaces(); ++i)
38  _faces.push_back(new EFAFace(*from_host->getFragmentFace(frag_id, i)));
39  }
40  findFacesAdjacentToFaces(); // IMPORTANT
41  }
42 }
43 
45 {
46  for (unsigned int i = 0; i < _faces.size(); ++i)
47  {
48  if (_faces[i])
49  {
50  delete _faces[i];
51  _faces[i] = NULL;
52  }
53  }
54 }
55 
56 void
57 EFAFragment3D::switchNode(EFANode * new_node, EFANode * old_node)
58 {
59  for (unsigned int i = 0; i < _faces.size(); ++i)
60  _faces[i]->switchNode(new_node, old_node);
61 }
62 
63 bool
65 {
66  bool contains = false;
67  for (unsigned int i = 0; i < _faces.size(); ++i)
68  {
69  if (_faces[i]->containsNode(node))
70  {
71  contains = true;
72  break;
73  }
74  }
75  return contains;
76 }
77 
78 unsigned int
80 {
81  unsigned int num_cut_faces = 0;
82  for (unsigned int i = 0; i < _faces.size(); ++i)
83  if (_faces[i]->hasIntersection())
84  num_cut_faces += 1;
85  return num_cut_faces;
86 }
87 
88 unsigned int
90 {
91  mooseError("Not implemented yet for 3D.");
92 }
93 
94 std::set<EFANode *>
96 {
97  std::set<EFANode *> all_nodes;
98  for (unsigned int i = 0; i < _faces.size(); ++i)
99  for (unsigned int j = 0; j < _faces[i]->numNodes(); ++j)
100  all_nodes.insert(_faces[i]->getNode(j));
101  return all_nodes;
102 }
103 
104 bool
106 {
107  bool is_connected = false;
108  EFAFragment3D * other_frag3d = dynamic_cast<EFAFragment3D *>(other_fragment);
109  if (!other_frag3d)
110  EFAError("in isConnected other_fragment is not of type EFAfragement3D");
111 
112  for (unsigned int i = 0; i < _faces.size(); ++i)
113  {
114  for (unsigned int j = 0; j < other_frag3d->numFaces(); ++j)
115  {
116  if (_faces[i]->equivalent(other_frag3d->_faces[j]))
117  {
118  is_connected = true;
119  break;
120  }
121  }
122  if (is_connected)
123  break;
124  } // i
125  return is_connected;
126 }
127 
128 void
129 EFAFragment3D::removeInvalidEmbeddedNodes(std::map<unsigned int, EFANode *> & EmbeddedNodes)
130 {
131  // N.B. this method is only called before we update fragments
132  // N.B. an embedded node is valid IF at least one of its host faces is exterior and has more than
133  // 1 cuts
134  // TODO: the invalid cases are generalized from 2D. The method may need improvements in 3D
135  if (hasFaceWithOneCut())
136  {
137  // build a local inverse map for all emb cut nodes in this fragment
138  std::map<EFANode *, std::vector<EFAFace *>> emb_inverse_map;
139  for (unsigned int i = 0; i < _faces.size(); ++i)
140  {
141  for (unsigned int j = 0; j < _faces[i]->numEdges(); ++j)
142  {
143  if (_faces[i]->getEdge(j)->hasIntersection())
144  {
145  EFANode * emb_node = _faces[i]->getEdge(j)->getEmbeddedNode(0);
146  emb_inverse_map[emb_node].push_back(_faces[i]);
147  }
148  } // i
149  } // j
150 
151  // find all invalid embedded nodes
152  std::vector<EFANode *> invalid_emb;
153  std::map<EFANode *, std::vector<EFAFace *>>::iterator it;
154  for (it = emb_inverse_map.begin(); it != emb_inverse_map.end(); ++it)
155  {
156  EFANode * emb_node = it->first;
157  std::vector<EFAFace *> & emb_faces = it->second;
158  if (emb_faces.size() != 2)
159  EFAError("one embedded node must be owned by 2 faces");
160  unsigned int counter = 0;
161  for (unsigned int i = 0; i < emb_faces.size(); ++i)
162  {
163  unsigned int face_id = getFaceID(emb_faces[i]);
164  if (!isFaceInterior(face_id) && emb_faces[i]->hasIntersection())
165  counter += 1; // count the appropriate emb's faces
166  }
167  if (counter == 0)
168  invalid_emb.push_back(emb_node);
169  }
170 
171  // delete all invalid emb nodes
172  for (unsigned int i = 0; i < invalid_emb.size(); ++i)
173  {
174  Efa::deleteFromMap(EmbeddedNodes, invalid_emb[i]);
175  _host_elem->removeEmbeddedNode(invalid_emb[i], true); // also remove from neighbors
176  } // i
177  }
178 }
179 
180 void
182 {
183  if (!_host_elem)
184  EFAError("In combine_tip_faces() the frag must have host_elem");
185 
186  for (unsigned int i = 0; i < _host_elem->numFaces(); ++i)
187  {
188  std::vector<unsigned int> frag_tip_face_id;
189  for (unsigned int j = 0; j < _faces.size(); ++j)
190  {
191  if (_host_elem->getFace(i)->containsFace(_faces[j]))
192  frag_tip_face_id.push_back(j);
193  }
194  if (frag_tip_face_id.size() == 2) // combine the two frag faces on this elem face
195  combine_two_faces(frag_tip_face_id[0], frag_tip_face_id[1], _host_elem->getFace(i));
196  }
197  // TODO: may need to combine other frag faces that have tip edges
198 }
199 
200 bool
201 EFAFragment3D::isFaceInterior(unsigned int face_id) const
202 {
203  if (!_host_elem)
204  EFAError("in isFaceInterior() fragment must have host elem");
205 
206  bool face_in_elem_face = false;
207  for (unsigned int i = 0; i < _host_elem->numFaces(); ++i)
208  {
209  if (_host_elem->getFace(i)->containsFace(_faces[face_id]))
210  {
211  face_in_elem_face = true;
212  break;
213  }
214  }
215  if (!face_in_elem_face)
216  return true; // yes, is interior
217  else
218  return false;
219 }
220 
221 std::vector<unsigned int>
223 {
224  std::vector<unsigned int> interior_face_id;
225  for (unsigned int i = 0; i < _faces.size(); ++i)
226  {
227  if (isFaceInterior(i))
228  interior_face_id.push_back(i);
229  }
230  return interior_face_id;
231 }
232 
233 bool
234 EFAFragment3D::isThirdInteriorFace(unsigned int face_id) const
235 {
236  bool is_third_cut = false;
237  if (!_host_elem)
238  EFAError("in isThirdInteriorFace fragment must have host elem");
239 
240  for (unsigned int i = 0; i < _host_elem->numInteriorNodes(); ++i)
241  {
242  if (_faces[face_id]->containsNode(_host_elem->getInteriorNode(i)->getNode()))
243  {
244  is_third_cut = true;
245  break;
246  }
247  }
248  return is_third_cut;
249 }
250 
251 unsigned int
253 {
254  return _faces.size();
255 }
256 
257 EFAFace *
258 EFAFragment3D::getFace(unsigned int face_id) const
259 {
260  if (face_id > _faces.size() - 1)
261  EFAError("in EFAfragment3D::get_face, index out of bounds");
262  return _faces[face_id];
263 }
264 
265 unsigned int
267 {
268  for (unsigned int i = 0; i < _faces.size(); ++i)
269  if (_faces[i] == face)
270  return i;
271  EFAError("face not found in get_face_id()");
272  return 99999;
273 }
274 
275 void
277 {
278  _faces.push_back(new_face);
279 }
280 
281 std::set<EFANode *>
282 EFAFragment3D::getFaceNodes(unsigned int face_id) const
283 {
284  std::set<EFANode *> face_nodes;
285  for (unsigned int i = 0; i < _faces[face_id]->numNodes(); ++i)
286  face_nodes.insert(_faces[face_id]->getNode(i));
287  return face_nodes;
288 }
289 
290 EFAElement3D *
292 {
293  return _host_elem;
294 }
295 
296 std::vector<EFAFragment3D *>
298 {
299  // This method will split one existing fragment into one or two new fragments
300  std::vector<EFAFragment3D *> new_fragments;
301  std::vector<std::vector<EFAFace *>> all_subfaces;
302  for (unsigned int i = 0; i < _faces.size(); ++i)
303  {
304  std::vector<EFAFace *> subfaces = _faces[i]->split();
305  all_subfaces.push_back(subfaces);
306  }
307 
308  // build new frags
309  if (hasFaceWithOneCut()) // "fakely" cut fragment
310  {
311  EFAFragment3D * new_frag = new EFAFragment3D(_host_elem, false, NULL);
312  for (unsigned int i = 0; i < all_subfaces.size(); ++i)
313  for (unsigned int j = 0; j < all_subfaces[i].size(); ++j)
314  new_frag->addFace(all_subfaces[i][j]);
315  new_frag->findFacesAdjacentToFaces();
316  new_fragments.push_back(new_frag);
317  }
318  else // thoroughly cut fragment
319  {
320  // find the first face with 2 sub-faces
321  EFAFace * start_face1 = NULL;
322  EFAFace * start_face2 = NULL;
323  unsigned int startOldFaceID = 0;
324  for (unsigned int i = 0; i < _faces.size(); ++i)
325  {
326  if (all_subfaces[i].size() == 2)
327  {
328  start_face1 = all_subfaces[i][0];
329  start_face2 = all_subfaces[i][1];
330  startOldFaceID = i;
331  break;
332  }
333  } // i
334  EFAFragment3D * new_frag1 = connectSubfaces(start_face1, startOldFaceID, all_subfaces);
335  EFAFragment3D * new_frag2 = connectSubfaces(start_face2, startOldFaceID, all_subfaces);
336  new_fragments.push_back(new_frag1);
337  new_fragments.push_back(new_frag2);
338  }
339  return new_fragments;
340 }
341 
342 void
344 {
345  _faces_adjacent_to_faces.clear();
346  for (unsigned int i = 0; i < _faces.size(); ++i)
347  {
348  std::vector<EFAFace *> face_adjacents(_faces[i]->numEdges(), NULL);
349  for (unsigned int j = 0; j < _faces.size(); ++j)
350  {
351  if (_faces[j] != _faces[i] && _faces[i]->isAdjacent(_faces[j]))
352  {
353  unsigned int adj_edge = _faces[i]->adjacentCommonEdge(_faces[j]);
354  face_adjacents[adj_edge] = _faces[j];
355  }
356  } // j
357  _faces_adjacent_to_faces.push_back(face_adjacents);
358  } // i
359 }
360 
361 EFAFace *
362 EFAFragment3D::getAdjacentFace(unsigned int face_id, unsigned int edge_id) const
363 {
364  return _faces_adjacent_to_faces[face_id][edge_id]; // possibly NULL
365 }
366 
367 void
369 {
370  for (unsigned int i = 0; i < _faces.size(); ++i)
371  _faces[i]->removeEmbeddedNode(emb_node);
372 }
373 
374 bool
376 {
377  // N.B. this method can only be implemented when the fragment has just been marked
378  for (unsigned int i = 0; i < _faces.size(); ++i)
379  if (_faces[i]->getNumCuts() == 1)
380  return true;
381  return false;
382 }
383 
384 void
385 EFAFragment3D::getNodeInfo(std::vector<std::vector<unsigned int>> & face_node_indices,
386  std::vector<EFANode *> & nodes) const
387 {
388  // get all nodes' pointers - a vector
389  std::set<EFANode *> all_node_set = getAllNodes();
390  nodes.resize(all_node_set.size());
391  std::copy(all_node_set.begin(), all_node_set.end(), nodes.begin());
392 
393  // get face connectivity
394  face_node_indices.clear();
395  for (unsigned int i = 0; i < _faces.size(); ++i)
396  {
397  std::vector<unsigned int> line_face_indices;
398  for (unsigned int j = 0; j < _faces[i]->numNodes(); ++j)
399  {
400  EFANode * node = _faces[i]->getNode(j);
401  unsigned int vec_index = std::find(nodes.begin(), nodes.end(), node) - nodes.begin();
402  line_face_indices.push_back(vec_index);
403  }
404  face_node_indices.push_back(line_face_indices);
405  }
406 }
407 
410  unsigned int startOldFaceID,
411  std::vector<std::vector<EFAFace *>> & subfaces)
412 {
413  // this method is only called in EFAfragment3D::split()
414  std::vector<bool> contributed(subfaces.size(), false);
415  contributed[startOldFaceID] = true;
416  unsigned int num_contrib_faces = 1;
417  unsigned int old_num_contrib = 1;
418  std::vector<EFAFace *> frag_faces(1, start_face);
419 
420  // collect all subfaces connected to start_face
421  do
422  {
423  old_num_contrib = num_contrib_faces;
424  for (unsigned int i = 0; i < subfaces.size(); ++i)
425  {
426  if (!contributed[i]) // old face not contributed to new fragment yet
427  {
428  bool adjacent_found = false;
429  for (unsigned int j = 0; j < subfaces[i].size(); ++j)
430  {
431  for (unsigned int k = 0; k < frag_faces.size(); ++k)
432  {
433  if (subfaces[i][j]->isAdjacent(frag_faces[k]))
434  {
435  adjacent_found = true;
436  contributed[i] = true;
437  frag_faces.push_back(subfaces[i][j]);
438  num_contrib_faces += 1;
439  break;
440  }
441  } // k
442  if (adjacent_found)
443  break;
444  } // j
445  }
446  } // i, loop over all old faces
447  } while (num_contrib_faces != old_num_contrib);
448 
449  // get the cut plane face
450  std::vector<EFAEdge *> cut_plane_edges;
451  EFAFragment3D * new_frag = new EFAFragment3D(_host_elem, false, NULL);
452  for (unsigned int i = 0; i < frag_faces.size(); ++i)
453  new_frag->addFace(frag_faces[i]);
454  new_frag->findFacesAdjacentToFaces();
455 
456  for (unsigned int i = 0; i < new_frag->numFaces(); ++i)
457  {
458  EFAEdge * lone_edge = new_frag->loneEdgeOnFace(i);
459  if (lone_edge != NULL) // valid edge
460  cut_plane_edges.push_back(new EFAEdge(*lone_edge));
461  }
462 
463  EFAFace * cut_face = new EFAFace(cut_plane_edges.size());
464  for (unsigned int i = 0; i < cut_plane_edges.size(); ++i)
465  cut_face->setEdge(i, cut_plane_edges[i]);
466  cut_face->sortEdges();
467  cut_face->reverseEdges();
468  cut_face->createNodes();
469 
470  // finalize the new fragment
471  new_frag->addFace(cut_face);
472  new_frag->findFacesAdjacentToFaces();
473  return new_frag;
474 }
475 
476 EFAEdge *
477 EFAFragment3D::loneEdgeOnFace(unsigned int face_id) const
478 {
479  // if any face edge is not shared by any other face, we call it a lone edge
480  for (unsigned int i = 0; i < _faces[face_id]->numEdges(); ++i)
481  if (_faces_adjacent_to_faces[face_id][i] == NULL)
482  return _faces[face_id]->getEdge(i);
483  return NULL;
484 }
485 
486 void
487 EFAFragment3D::combine_two_faces(unsigned int face_id1,
488  unsigned int face_id2,
489  const EFAFace * elem_face)
490 {
491  // get the new full face
492  EFAFace * full_face = _faces[face_id1]->combineWithFace(_faces[face_id2]);
493  full_face->resetEdgeIntersection(elem_face); // IMPORTANT
494 
495  // take care of the common adjacent faces (combine their tip edges)
496  std::set<EFAFace *> face1_neigh;
497  face1_neigh.insert(_faces_adjacent_to_faces[face_id1].begin(),
498  _faces_adjacent_to_faces[face_id1].end());
499  std::set<EFAFace *> face2_neigh;
500  face2_neigh.insert(_faces_adjacent_to_faces[face_id2].begin(),
501  _faces_adjacent_to_faces[face_id2].end());
502  std::vector<EFAFace *> common_adjacent_faces = Efa::getCommonElems(face1_neigh, face2_neigh);
503 
504  for (unsigned int i = 0; i < common_adjacent_faces.size(); ++i)
505  {
506  EFAFace * comm_face = common_adjacent_faces[i];
507  if (comm_face != NULL)
508  {
509  unsigned int edge_id1 = comm_face->adjacentCommonEdge(_faces[face_id1]);
510  unsigned int edge_id2 = comm_face->adjacentCommonEdge(_faces[face_id2]);
511  comm_face->combineTwoEdges(edge_id1, edge_id2);
512  comm_face->resetEdgeIntersection(elem_face); // IMPORTANT
513  }
514  }
515 
516  // delete old faces and update private members of EFAfragment3D
517  delete _faces[face_id1];
518  delete _faces[face_id2];
519  _faces[face_id1] = full_face;
520  _faces.erase(_faces.begin() + face_id2);
521  findFacesAdjacentToFaces(); // rebuild _adjacent_face_ix: IMPORTANT
522 }
void getNodeInfo(std::vector< std::vector< unsigned int >> &face_node_indices, std::vector< EFANode * > &nodes) const
virtual bool containsNode(EFANode *node) const
Definition: EFAFragment3D.C:64
bool isFaceInterior(unsigned int face_id) const
void removeEmbeddedNode(EFANode *emb_node)
void setEdge(unsigned int edge_id, EFAEdge *new_edge)
Definition: EFAFace.C:264
void findFacesAdjacentToFaces()
std::vector< unsigned int > get_interior_face_id() const
std::vector< EFAFragment3D * > split()
void resetEdgeIntersection(const EFAFace *ref_face)
Definition: EFAFace.C:552
bool deleteFromMap(std::map< unsigned int, T * > &theMap, T *elemToDelete, bool delete_elem=true)
Definition: EFAFuncs.h:21
unsigned int adjacentCommonEdge(const EFAFace *other_face) const
Definition: EFAFace.C:642
unsigned int numFaces() const
unsigned int getFaceID(EFAFace *face) const
void combine_tip_faces()
EFAFragment3D * getFragment(unsigned int frag_id) const
bool isThirdInteriorFace(unsigned int face_id) const
std::vector< std::vector< EFAFace * > > _faces_adjacent_to_faces
Definition: EFAFragment3D.h:31
bool containsFace(const EFAFace *other_face) const
Definition: EFAFace.C:415
void combineTwoEdges(unsigned int edge_id1, unsigned int edge_id2)
Definition: EFAFace.C:286
EFAFragment3D(EFAElement3D *host, bool create_faces, const EFAElement3D *from_host, unsigned int frag_id=std::numeric_limits< unsigned int >::max())
Definition: EFAFragment3D.C:18
virtual unsigned int getNumCutNodes() const
Definition: EFAFragment3D.C:89
EFAVolumeNode * getInteriorNode(unsigned int interior_node_id) const
EFAEdge * loneEdgeOnFace(unsigned int face_id) const
void sortEdges()
Definition: EFAFace.C:327
EFAElement3D * _host_elem
Definition: EFAFragment3D.h:29
virtual unsigned int getNumCuts() const
Definition: EFAFragment3D.C:79
EFAFace * getFace(unsigned int face_id) const
EFAFace * getFragmentFace(unsigned int frag_id, unsigned int face_id) const
EFAFace * getAdjacentFace(unsigned int face_id, unsigned int edge_id) const
EFANode * getNode()
Definition: EFAVolumeNode.C:29
virtual void removeInvalidEmbeddedNodes(std::map< unsigned int, EFANode * > &EmbeddedNodes)
void removeEmbeddedNode(EFANode *emb_node, bool remove_for_neighbor)
EFAFragment3D * connectSubfaces(EFAFace *start_face, unsigned int startOldFaceID, std::vector< std::vector< EFAFace * >> &subfaces)
virtual std::set< EFANode * > getAllNodes() const
Definition: EFAFragment3D.C:95
virtual bool isConnected(EFAFragment *other_fragment) const
EFAFace * getFace(unsigned int face_id) const
virtual unsigned int numFragments() const
Definition: EFAElement3D.C:263
void addFace(EFAFace *new_face)
EFAElement3D * getHostElement() const
std::vector< T > getCommonElems(std::set< T > &v1, std::set< T > &v2)
Definition: EFAFuncs.h:68
void reverseEdges()
Definition: EFAFace.C:347
void createNodes()
Definition: EFAFace.C:240
bool hasFaceWithOneCut() const
void combine_two_faces(unsigned int face_id1, unsigned int face_id2, const EFAFace *elem_face)
unsigned int numFaces() const
std::set< EFANode * > getFaceNodes(unsigned int face_id) const
virtual void switchNode(EFANode *new_node, EFANode *old_node)
Definition: EFAFragment3D.C:57
std::vector< EFAFace * > _faces
Definition: EFAFragment3D.h:30
static unsigned int counter
virtual unsigned int numInteriorNodes() const
Definition: EFAElement3D.C:419