www.mooseframework.org
EFAElement3D.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #include "EFAElement3D.h"
11 
12 #include <iomanip>
13 
14 #include "EFAFaceNode.h"
15 #include "EFAVolumeNode.h"
16 #include "EFANode.h"
17 #include "EFAEdge.h"
18 #include "EFAFace.h"
19 #include "EFAFragment3D.h"
20 #include "EFAFuncs.h"
21 #include "EFAError.h"
22 #include "XFEMFuncs.h"
23 
24 EFAElement3D::EFAElement3D(unsigned int eid, unsigned int n_nodes, unsigned int n_faces)
25  : EFAElement(eid, n_nodes),
26  _num_faces(n_faces),
27  _faces(_num_faces, NULL),
28  _face_neighbors(_num_faces),
29  _face_edge_neighbors(_num_faces)
30 {
31  if (_num_faces == 4)
32  {
33  _num_vertices = 4;
34  if (_num_nodes == 10)
36  else if (_num_nodes == 4)
38  else
39  EFAError("In EFAelement3D the supported TET element types are TET4 and TET10");
40  }
41  else if (_num_faces == 6)
42  {
43  _num_vertices = 8;
44  if (_num_nodes == 27)
46  else if (_num_nodes == 20)
48  else if (_num_nodes == 8)
50  else
51  EFAError("In EFAelement3D the supported HEX element types are HEX8, HEX20 and HEX27");
52  }
53  else
54  EFAError("In EFAelement3D the supported element types are TET4, TET10, HEX8, HEX20 and HEX27");
56 }
57 
58 EFAElement3D::EFAElement3D(const EFAElement3D * from_elem, bool convert_to_local)
59  : EFAElement(from_elem->_id, from_elem->_num_nodes),
60  _num_faces(from_elem->_num_faces),
61  _faces(_num_faces, NULL),
62  _face_neighbors(_num_faces),
63  _face_edge_neighbors(_num_faces)
64 {
65  if (convert_to_local)
66  {
67  // build local nodes from global nodes
68  for (unsigned int i = 0; i < _num_nodes; ++i)
69  {
70  if (from_elem->_nodes[i]->category() == EFANode::N_CATEGORY_PERMANENT ||
71  from_elem->_nodes[i]->category() == EFANode::N_CATEGORY_TEMP)
72  {
73  _nodes[i] = from_elem->createLocalNodeFromGlobalNode(from_elem->_nodes[i]);
74  _local_nodes.push_back(_nodes[i]); // convenient to delete local nodes
75  }
76  else
77  EFAError("In EFAelement3D ",
78  from_elem->id(),
79  " the copy constructor must have from_elem w/ global nodes. node: ",
80  i,
81  " category: ",
82  from_elem->_nodes[i]->category());
83  }
84 
85  // copy faces, fragments and interior nodes from from_elem
86  for (unsigned int i = 0; i < _num_faces; ++i)
87  _faces[i] = new EFAFace(*from_elem->_faces[i]);
88  for (unsigned int i = 0; i < from_elem->_fragments.size(); ++i)
89  _fragments.push_back(new EFAFragment3D(this, true, from_elem, i));
90  for (unsigned int i = 0; i < from_elem->_interior_nodes.size(); ++i)
91  _interior_nodes.push_back(new EFAVolumeNode(*from_elem->_interior_nodes[i]));
92 
93  // replace all global nodes with local nodes
94  for (unsigned int i = 0; i < _num_nodes; ++i)
95  {
96  if (_nodes[i]->category() == EFANode::N_CATEGORY_LOCAL_INDEX)
97  switchNode(
98  _nodes[i],
99  from_elem->_nodes[i],
100  false); // when save to _cut_elem_map, the EFAelement is not a child of any parent
101  else
102  EFAError("In EFAelement3D copy constructor this elem's nodes must be local");
103  }
104 
105  // create element face connectivity array (IMPORTANT)
107 
108  _local_node_coor = from_elem->_local_node_coor;
110  _num_vertices = from_elem->_num_vertices;
111  }
112  else
113  EFAError("this EFAelement3D constructor only converts global nodes to local nodes");
114 }
115 
117 {
118  for (unsigned int i = 0; i < _fragments.size(); ++i)
119  {
120  if (_fragments[i])
121  {
122  delete _fragments[i];
123  _fragments[i] = NULL;
124  }
125  }
126  for (unsigned int i = 0; i < _faces.size(); ++i)
127  {
128  if (_faces[i])
129  {
130  delete _faces[i];
131  _faces[i] = NULL;
132  }
133  }
134  for (unsigned int i = 0; i < _interior_nodes.size(); ++i)
135  {
136  if (_interior_nodes[i])
137  {
138  delete _interior_nodes[i];
139  _interior_nodes[i] = NULL;
140  }
141  }
142  for (unsigned int i = 0; i < _local_nodes.size(); ++i)
143  {
144  if (_local_nodes[i])
145  {
146  delete _local_nodes[i];
147  _local_nodes[i] = NULL;
148  }
149  }
150 }
151 
152 void
154 {
155  if (_num_faces == 6)
156  {
157  /*
158  HEX27(HEX20): 7 18 6
159  o--------------o--------------o
160  /: / /|
161  / : / / |
162  / : / / |
163  19/ : 25/ 17/ |
164  o--------------o--------------o |
165  / : / /| |
166  / 15o / 23o / | 14o
167  / : / / | /|
168  4/ : 16/ 5/ | / |
169  o--------------o--------------o | / |
170  | : | 26 | |/ |
171  | 24o : | o | 22o |
172  | : | 10 | /| |
173  | 3o....|.........o....|../.|....o
174  | . | | / | / 2
175  | . 21| 13|/ | /
176  12 o--------------o--------------o | /
177  | . | | |/
178  | 11o | 20o | o
179  | . | | / 9
180  | . | | /
181  | . | | /
182  |. | |/
183  o--------------o--------------o
184  0 8 1
185 
186  */
188  _local_node_coor[0] = EFAPoint(0.0, 0.0, 0.0);
189  _local_node_coor[1] = EFAPoint(1.0, 0.0, 0.0);
190  _local_node_coor[2] = EFAPoint(1.0, 1.0, 0.0);
191  _local_node_coor[3] = EFAPoint(0.0, 1.0, 0.0);
192  _local_node_coor[4] = EFAPoint(0.0, 0.0, 1.0);
193  _local_node_coor[5] = EFAPoint(1.0, 0.0, 1.0);
194  _local_node_coor[6] = EFAPoint(1.0, 1.0, 1.0);
195  _local_node_coor[7] = EFAPoint(0.0, 1.0, 1.0);
196 
197  if (_num_nodes > 8)
198  {
199  _local_node_coor[8] = EFAPoint(0.5, 0.0, 0.0);
200  _local_node_coor[9] = EFAPoint(1.0, 0.5, 0.0);
201  _local_node_coor[10] = EFAPoint(0.5, 1.0, 0.0);
202  _local_node_coor[11] = EFAPoint(0.0, 0.5, 0.0);
203  _local_node_coor[12] = EFAPoint(0.0, 0.0, 0.5);
204  _local_node_coor[13] = EFAPoint(1.0, 0.0, 0.5);
205  _local_node_coor[14] = EFAPoint(1.0, 1.0, 0.5);
206  _local_node_coor[15] = EFAPoint(0.0, 1.0, 0.5);
207  _local_node_coor[16] = EFAPoint(0.5, 0.0, 1.0);
208  _local_node_coor[17] = EFAPoint(1.0, 0.5, 1.0);
209  _local_node_coor[18] = EFAPoint(0.5, 1.0, 1.0);
210  _local_node_coor[19] = EFAPoint(0.0, 0.5, 1.0);
211  }
212 
213  if (_num_nodes > 20)
214  {
215  _local_node_coor[20] = EFAPoint(0.5, 0.5, 0.0);
216  _local_node_coor[21] = EFAPoint(0.5, 0.0, 0.5);
217  _local_node_coor[22] = EFAPoint(1.0, 0.5, 0.5);
218  _local_node_coor[23] = EFAPoint(0.5, 1.0, 0.5);
219  _local_node_coor[24] = EFAPoint(0.0, 0.5, 0.5);
220  _local_node_coor[25] = EFAPoint(0.5, 0.5, 1.0);
221  _local_node_coor[26] = EFAPoint(0.5, 0.5, 0.5);
222  }
223  }
224  else if (_num_faces == 4)
225  {
226  /*
227  3
228  TET10: o
229  /|\
230  / | \
231  7 / | \9
232  o | o
233  / |8 \
234  / o \
235  / 6 | \
236  0 o.....o.|.......o 2
237  \ | /
238  \ | /
239  \ | /
240  4 o | o 5
241  \ | /
242  \ | /
243  \|/
244  o
245  1
246 
247  */
249  _local_node_coor[0] = EFAPoint(0.0, 0.0, 0.0);
250  _local_node_coor[1] = EFAPoint(1.0, 0.0, 0.0);
251  _local_node_coor[2] = EFAPoint(0.0, 1.0, 0.0);
252  _local_node_coor[3] = EFAPoint(0.0, 0.0, 1.0);
253 
254  if (_num_nodes > 4)
255  {
256  _local_node_coor[4] = EFAPoint(0.5, 0.0, 0.0);
257  _local_node_coor[5] = EFAPoint(0.5, 0.5, 0.0);
258  _local_node_coor[6] = EFAPoint(0.0, 0.5, 0.0);
259  _local_node_coor[7] = EFAPoint(0.0, 0.0, 0.5);
260  _local_node_coor[8] = EFAPoint(0.5, 0.0, 0.5);
261  _local_node_coor[9] = EFAPoint(0.0, 0.5, 0.5);
262  }
263  }
264  else
265  EFAError("EFAElement3D: number of faces should be either 4(TET) or 6(HEX).");
266 }
267 
268 unsigned int
270 {
271  return _fragments.size();
272 }
273 
274 bool
276 {
277  bool partial = false;
278  if (_fragments.size() > 0)
279  {
280  for (unsigned int i = 0; i < _num_vertices; ++i)
281  {
282  bool node_in_frag = false;
283  for (unsigned int j = 0; j < _fragments.size(); ++j)
284  {
285  if (_fragments[j]->containsNode(_nodes[i]))
286  {
287  node_in_frag = true;
288  break;
289  }
290  } // j
291  if (!node_in_frag)
292  {
293  partial = true;
294  break;
295  }
296  } // i
297  }
298  return partial;
299 }
300 
301 void
302 EFAElement3D::getNonPhysicalNodes(std::set<EFANode *> & non_physical_nodes) const
303 {
304  // Any nodes that don't belong to any fragment are non-physical
305  // First add all nodes in the element to the set
306  for (unsigned int i = 0; i < _nodes.size(); ++i)
307  non_physical_nodes.insert(_nodes[i]);
308 
309  // Now delete any nodes that are contained in fragments
310  std::set<EFANode *>::iterator sit;
311  for (sit = non_physical_nodes.begin(); sit != non_physical_nodes.end();)
312  {
313  bool erased = false;
314  for (unsigned int i = 0; i < _fragments.size(); ++i)
315  {
316  if (_fragments[i]->containsNode(*sit))
317  {
318  non_physical_nodes.erase(sit++);
319  erased = true;
320  break;
321  }
322  }
323  if (!erased)
324  ++sit;
325  }
326 }
327 
328 void
329 EFAElement3D::switchNode(EFANode * new_node, EFANode * old_node, bool descend_to_parent)
330 {
331  // We are not switching any embedded nodes here; This is an enhanced version
332  for (unsigned int i = 0; i < _num_nodes; ++i)
333  {
334  if (_nodes[i] == old_node)
335  _nodes[i] = new_node;
336  }
337  for (unsigned int i = 0; i < _fragments.size(); ++i)
338  _fragments[i]->switchNode(new_node, old_node);
339 
340  for (unsigned int i = 0; i < _faces.size(); ++i)
341  _faces[i]->switchNode(new_node, old_node);
342 
343  if (_parent && descend_to_parent)
344  {
345  _parent->switchNode(new_node, old_node, false);
346  for (unsigned int i = 0; i < _parent->numGeneralNeighbors(); ++i)
347  {
348  EFAElement * neigh_elem = _parent->getGeneralNeighbor(i); // generalized neighbor element
349  for (unsigned int k = 0; k < neigh_elem->numChildren(); ++k)
350  neigh_elem->getChild(k)->switchNode(new_node, old_node, false);
351  }
352  }
353 }
354 
355 void
356 EFAElement3D::switchEmbeddedNode(EFANode * new_emb_node, EFANode * old_emb_node)
357 {
358  for (unsigned int i = 0; i < _num_faces; ++i)
359  _faces[i]->switchNode(new_emb_node, old_emb_node);
360  for (unsigned int i = 0; i < _interior_nodes.size(); ++i)
361  _interior_nodes[i]->switchNode(new_emb_node, old_emb_node);
362  for (unsigned int i = 0; i < _fragments.size(); ++i)
363  _fragments[i]->switchNode(new_emb_node, old_emb_node);
364 }
365 
366 void
368 {
369  // In EFAElement3D, updateFragmentNode needs to be implemented
370 }
371 
372 void
374  std::vector<EFANode *> & master_nodes,
375  std::vector<double> & master_weights) const
376 {
377  // Given a EFAnode, return its master nodes and weights
378  master_nodes.clear();
379  master_weights.clear();
380  bool masters_found = false;
381  for (unsigned int i = 0; i < _num_faces; ++i) // check element exterior faces
382  {
383  if (_faces[i]->containsNode(node))
384  {
385  masters_found = _faces[i]->getMasterInfo(node, master_nodes, master_weights);
386  if (masters_found)
387  break;
388  else
389  EFAError("In getMasterInfo: cannot find master nodes in element faces");
390  }
391  }
392 
393  if (!masters_found) // check element interior embedded nodes
394  {
395  for (unsigned int i = 0; i < _interior_nodes.size(); ++i)
396  {
397  if (_interior_nodes[i]->getNode() == node)
398  {
399  std::vector<double> xi_3d(3, -100.0);
400  for (unsigned int j = 0; j < 3; ++j)
401  xi_3d[j] = _interior_nodes[i]->getParametricCoordinates(j);
402  for (unsigned int j = 0; j < _num_nodes; ++j)
403  {
404  master_nodes.push_back(_nodes[j]);
405  double weight = 0.0;
406  if (_num_nodes == 8)
407  weight = Efa::linearHexShape3D(j, xi_3d);
408  else if (_num_nodes == 4)
409  weight = Efa::linearTetShape3D(j, xi_3d);
410  else
411  EFAError("unknown 3D element");
412  master_weights.push_back(weight);
413  }
414  masters_found = true;
415  break;
416  }
417  }
418  }
419 
420  if (!masters_found)
421  EFAError("In EFAelement3D::getMaterInfo, cannot find the given EFAnode");
422 }
423 
424 unsigned int
426 {
427  return _interior_nodes.size();
428 }
429 
430 bool
432 {
433  bool overlays = false;
434  const EFAElement3D * other3d = dynamic_cast<const EFAElement3D *>(other_elem);
435  if (!other3d)
436  EFAError("failed to dynamic cast to other3d");
437 
438  // Find indices of common nodes
439  std::vector<unsigned int> common_face_curr = getCommonFaceID(other3d);
440  if (common_face_curr.size() == 1)
441  {
442  unsigned int curr_face_id = common_face_curr[0];
443  EFAFace * curr_face = _faces[curr_face_id];
444  unsigned int other_face_id = other3d->getFaceID(curr_face);
445  EFAFace * other_face = other3d->_faces[other_face_id];
446  if (curr_face->hasSameOrientation(other_face))
447  overlays = true;
448  }
449  else if (common_face_curr.size() > 1)
450  {
451  // TODO: We probably need more error checking here.
452  overlays = true;
453  }
454  return overlays;
455 }
456 
457 unsigned int
458 EFAElement3D::getNeighborIndex(const EFAElement * neighbor_elem) const
459 {
460  for (unsigned int i = 0; i < _num_faces; ++i)
461  for (unsigned int j = 0; j < _face_neighbors[i].size(); ++j)
462  if (_face_neighbors[i][j] == neighbor_elem)
463  return i;
464  EFAError("in getNeighborIndex() element ", _id, " does not have neighbor ", neighbor_elem->id());
465  return 99999;
466 }
467 
468 void
470  unsigned int face_id,
471  unsigned int edge_id,
472  unsigned int & neigh_face_id,
473  unsigned int & neigh_edge_id) const
474 {
475  EFAEdge * edge = this->getFace(face_id)->getEdge(edge_id);
476  for (unsigned int i = 0; i < neighbor_elem->numFaces(); ++i)
477  {
478  for (unsigned int j = 0; j < neighbor_elem->getFace(i)->numEdges(); ++j)
479  {
480  EFAEdge * neigh_edge = neighbor_elem->getFace(i)->getEdge(j);
481  if (neigh_edge->equivalent(*edge))
482  {
483  neigh_face_id = i;
484  neigh_edge_id = j;
485  return;
486  }
487  }
488  }
489  EFAError("in getNeighborEdgeIndex() element ",
490  _id,
491  " does not share a common edge with element",
492  neighbor_elem->id());
493 }
494 
495 void
497 {
498  _general_neighbors.clear();
499  for (unsigned int face_iter = 0; face_iter < _num_faces; ++face_iter)
500  {
501  _face_neighbors[face_iter].clear();
502  for (unsigned int edge_iter = 0; edge_iter < _faces[face_iter]->numEdges(); ++edge_iter)
503  _face_edge_neighbors[face_iter][edge_iter].clear();
504  }
505 }
506 
507 void
508 EFAElement3D::setupNeighbors(std::map<EFANode *, std::set<EFAElement *>> & InverseConnectivityMap)
509 {
510  findGeneralNeighbors(InverseConnectivityMap);
511  for (unsigned int eit2 = 0; eit2 < _general_neighbors.size(); ++eit2)
512  {
513  EFAElement3D * neigh_elem = dynamic_cast<EFAElement3D *>(_general_neighbors[eit2]);
514  if (!neigh_elem)
515  EFAError("neighbor_elem is not of EFAelement3D type");
516 
517  std::vector<unsigned int> common_face_id = getCommonFaceID(neigh_elem);
518  std::vector<unsigned int> face_ids, edge_ids;
519  if (common_face_id.size() == 0 && getCommonEdgeID(neigh_elem, face_ids, edge_ids) &&
520  !overlaysElement(neigh_elem))
521  {
522  bool is_edge_neighbor = false;
523 
524  // Fragments must match up.
525  if ((_fragments.size() > 1) || (neigh_elem->numFragments() > 1))
526  {
527  EFAError("in updateFaceNeighbors: Cannot have more than 1 fragment");
528  }
529  else if ((_fragments.size() == 1) && (neigh_elem->numFragments() == 1))
530  {
531  if (_fragments[0]->isEdgeConnected(neigh_elem->getFragment(0)))
532  is_edge_neighbor = true;
533  }
534  else // If there are no fragments to match up, consider them edge neighbors
535  is_edge_neighbor = true;
536 
537  if (is_edge_neighbor)
538  {
539  for (unsigned int i = 0; i < face_ids.size(); ++i)
540  {
541  unsigned int face_id = face_ids[i];
542  unsigned int edge_id = edge_ids[i];
543  _face_edge_neighbors[face_id][edge_id].push_back(neigh_elem);
544  }
545  }
546  }
547 
548  if (common_face_id.size() == 1 && !overlaysElement(neigh_elem))
549  {
550  unsigned int face_id = common_face_id[0];
551  bool is_face_neighbor = false;
552 
553  // Fragments must match up.
554  if ((_fragments.size() > 1) || (neigh_elem->numFragments() > 1))
555  {
556  EFAError("in updateFaceNeighbors: Cannot have more than 1 fragment");
557  }
558  else if ((_fragments.size() == 1) && (neigh_elem->numFragments() == 1))
559  {
560  if (_fragments[0]->isConnected(neigh_elem->getFragment(0)))
561  is_face_neighbor = true;
562  }
563  else // If there are no fragments to match up, consider them neighbors
564  is_face_neighbor = true;
565 
566  if (is_face_neighbor)
567  {
568  if (_face_neighbors[face_id].size() > 1)
569  {
570  EFAError("Element ",
571  _id,
572  " already has 2 face neighbors: ",
573  _face_neighbors[face_id][0]->id(),
574  " ",
575  _face_neighbors[face_id][1]->id());
576  }
577  _face_neighbors[face_id].push_back(neigh_elem);
578  }
579  }
580  }
581 }
582 
583 void
585 {
586  for (unsigned int face_iter = 0; face_iter < _num_faces; ++face_iter)
587  {
588  for (unsigned int en_iter = 0; en_iter < _face_neighbors[face_iter].size(); ++en_iter)
589  {
590  EFAElement3D * neigh_elem = _face_neighbors[face_iter][en_iter];
591  if (neigh_elem != NULL)
592  {
593  bool found_neighbor = false;
594  for (unsigned int face_iter2 = 0; face_iter2 < neigh_elem->numFaces(); ++face_iter2)
595  {
596  for (unsigned int en_iter2 = 0; en_iter2 < neigh_elem->numFaceNeighbors(face_iter2);
597  ++en_iter2)
598  {
599  if (neigh_elem->getFaceNeighbor(face_iter2, en_iter2) == this)
600  {
601  if ((en_iter2 > 1) && (en_iter > 1))
602  {
603  EFAError(
604  "Element and neighbor element cannot both have >1 neighbors on a common face");
605  }
606  found_neighbor = true;
607  break;
608  }
609  }
610  }
611  if (!found_neighbor)
612  EFAError("Neighbor element doesn't recognize current element as neighbor");
613  }
614  }
615  }
616 }
617 
618 void
619 EFAElement3D::initCrackTip(std::set<EFAElement *> & CrackTipElements)
620 {
621  if (isCrackTipElement())
622  {
623  CrackTipElements.insert(this);
624  for (unsigned int face_iter = 0; face_iter < _num_faces; ++face_iter)
625  {
626  if ((_face_neighbors[face_iter].size() == 2) && (_faces[face_iter]->hasIntersection()))
627  {
628  // Neither neighbor overlays current element. We are on the uncut element ahead of the tip.
629  // Flag neighbors as crack tip split elements and add this element as their crack tip
630  // neighbor.
631  if (_face_neighbors[face_iter][0]->overlaysElement(this) ||
632  _face_neighbors[face_iter][1]->overlaysElement(this))
633  EFAError("Element has a neighbor that overlays itself");
634 
635  // Make sure the current elment hasn't been flagged as a tip element
637  EFAError("crack_tip_split_element already flagged. In elem: ",
638  _id,
639  " flags: ",
641  " ",
642  _face_neighbors[face_iter][0]->isCrackTipSplit(),
643  " ",
644  _face_neighbors[face_iter][1]->isCrackTipSplit());
645 
646  _face_neighbors[face_iter][0]->setCrackTipSplit();
647  _face_neighbors[face_iter][1]->setCrackTipSplit();
648 
649  _face_neighbors[face_iter][0]->addCrackTipNeighbor(this);
650  _face_neighbors[face_iter][1]->addCrackTipNeighbor(this);
651  }
652  } // face_iter
653  }
654 }
655 
656 bool
657 EFAElement3D::shouldDuplicateForCrackTip(const std::set<EFAElement *> & CrackTipElements)
658 {
659  // This method is called in createChildElements()
660  // Only duplicate when
661  // 1) currElem will be a NEW crack tip element
662  // 2) currElem is a crack tip split element at last time step and the tip will extend
663  // 3) currElem is the neighbor of a to-be-second-split element which has another neighbor
664  // sharing a phantom node with currElem
665  bool should_duplicate = false;
666  if (_fragments.size() == 1)
667  {
668  std::set<EFAElement *>::iterator sit;
669  sit = CrackTipElements.find(this);
670  if (sit == CrackTipElements.end() && isCrackTipElement())
671  should_duplicate = true;
672  else if (shouldDuplicateCrackTipSplitElement(CrackTipElements))
673  should_duplicate = true;
675  should_duplicate = true;
676  }
677  return should_duplicate;
678 }
679 
680 bool
681 EFAElement3D::shouldDuplicateCrackTipSplitElement(const std::set<EFAElement *> & CrackTipElements)
682 {
683  // Determine whether element at crack tip should be duplicated. It should be duplicated
684  // if the crack will extend into the next element, or if it has a non-physical node
685  // connected to a face where a crack terminates, but will extend.
686 
687  bool should_duplicate = false;
688  if (_fragments.size() == 1)
689  {
690  std::vector<unsigned int> split_neighbors;
691  if (willCrackTipExtend(split_neighbors))
692  should_duplicate = true;
693  else
694  {
695  // The element may not be at the crack tip, but could have a non-physical node
696  // connected to a crack tip face (on a neighbor element) that will be split. We need to
697  // duplicate in that case as well.
698  std::set<EFANode *> non_physical_nodes;
699  getNonPhysicalNodes(non_physical_nodes);
700 
701  for (unsigned int eit = 0; eit < _general_neighbors.size(); ++eit)
702  {
703  EFAElement3D * neigh_elem = dynamic_cast<EFAElement3D *>(_general_neighbors[eit]);
704  if (!neigh_elem)
705  EFAError("general elem is not of type EFAelement3D");
706 
707  // check if a general neighbor is an old crack tip element and will be split
708  std::set<EFAElement *>::iterator sit;
709  sit = CrackTipElements.find(neigh_elem);
710  if (sit != CrackTipElements.end() && neigh_elem->numFragments() > 1)
711  {
712  for (unsigned int i = 0; i < neigh_elem->numFaces(); ++i)
713  {
714  std::set<EFANode *> neigh_face_nodes = neigh_elem->getFaceNodes(i);
715  if (neigh_elem->numFaceNeighbors(i) == 2 &&
716  Efa::numCommonElems(neigh_face_nodes, non_physical_nodes) > 0)
717  {
718  should_duplicate = true;
719  break;
720  }
721  } // i
722  }
723  if (should_duplicate)
724  break;
725  } // eit
726  }
727  } // IF only one fragment
728  return should_duplicate;
729 }
730 
731 bool
733 {
734  // if a partial element will be split for a second time and it has two neighbor elements
735  // sharing one phantom node with the aforementioned partial element, then the two neighbor
736  // elements should be duplicated
737  bool should_duplicate = false;
738  if (_fragments.size() == 1 && (!_crack_tip_split_element))
739  {
740  for (unsigned int i = 0; i < _num_faces; ++i)
741  {
742  std::set<EFANode *> phantom_nodes = getPhantomNodeOnFace(i);
743  if (phantom_nodes.size() > 0 && numFaceNeighbors(i) == 1)
744  {
745  EFAElement3D * neighbor_elem = _face_neighbors[i][0];
746  if (neighbor_elem->numFragments() > 1) // neighbor will be split
747  {
748  for (unsigned int j = 0; j < neighbor_elem->numFaces(); ++j)
749  {
750  if (!neighbor_elem->getFace(j)->equivalent(_faces[i]) &&
751  neighbor_elem->numFaceNeighbors(j) > 0)
752  {
753  std::set<EFANode *> neigh_phantom_nodes = neighbor_elem->getPhantomNodeOnFace(j);
754  if (Efa::numCommonElems(phantom_nodes, neigh_phantom_nodes) > 0)
755  {
756  should_duplicate = true;
757  break;
758  }
759  }
760  } // j
761  }
762  }
763  if (should_duplicate)
764  break;
765  } // i
766  }
767  return should_duplicate;
768 }
769 
770 bool
771 EFAElement3D::willCrackTipExtend(std::vector<unsigned int> & split_neighbors) const
772 {
773  // Determine whether the current element is a crack tip element for which the crack will
774  // extend into the next element.
775  // N.B. this is called at the beginning of createChildElements
776  bool will_extend = false;
777  if (_fragments.size() == 1 && _crack_tip_split_element)
778  {
779  for (unsigned int i = 0; i < _crack_tip_neighbors.size(); ++i)
780  {
781  unsigned int neigh_idx = _crack_tip_neighbors[i]; // essentially a face_id
782  if (numFaceNeighbors(neigh_idx) != 1)
783  EFAError("in will_crack_tip_extend() element ",
784  _id,
785  " has ",
786  _face_neighbors[neigh_idx].size(),
787  " neighbors on face ",
788  neigh_idx);
789 
790  EFAElement3D * neighbor_elem = _face_neighbors[neigh_idx][0];
791  if (neighbor_elem->numFragments() > 2)
792  {
793  EFAError("in will_crack_tip_extend() element ",
794  neighbor_elem->id(),
795  " has ",
796  neighbor_elem->numFragments(),
797  " fragments");
798  }
799  else if (neighbor_elem->numFragments() == 2)
800  {
801  EFAFragment3D * neigh_frag1 = neighbor_elem->getFragment(0);
802  EFAFragment3D * neigh_frag2 = neighbor_elem->getFragment(1);
803  std::vector<EFANode *> neigh_cut_nodes = neigh_frag1->getCommonNodes(neigh_frag2);
804  unsigned int counter = 0; // counter how many common nodes are contained by current face
805  for (unsigned int j = 0; j < neigh_cut_nodes.size(); ++j)
806  {
807  if (_faces[neigh_idx]->containsNode(neigh_cut_nodes[j]))
808  counter += 1;
809  }
810  if (counter == 2)
811  {
812  split_neighbors.push_back(neigh_idx);
813  will_extend = true;
814  }
815  }
816  } // i
817  }
818  return will_extend;
819 }
820 
821 bool
823 {
824  return fragmentHasTipFaces();
825 }
826 
827 unsigned int
829 {
830  unsigned int num_cut_faces = 0;
831  for (unsigned int i = 0; i < _num_faces; ++i)
832  if (_faces[i]->hasIntersection())
833  num_cut_faces += 1;
834  return num_cut_faces;
835 }
836 
837 bool
839 {
840  // if an element has been cut third times its fragment must have 3 interior faces
841  // and at this point, we do not want it to be further cut
842  bool cut_third = false;
843  if (_fragments.size() > 0)
844  {
845  unsigned int num_interior_faces = 0;
846  for (unsigned int i = 0; i < _fragments[0]->numFaces(); ++i)
847  {
848  if (_fragments[0]->isFaceInterior(i))
849  num_interior_faces += 1;
850  }
851  if (num_interior_faces == 3)
852  cut_third = true;
853  }
854  return cut_third;
855 }
856 
857 void
858 EFAElement3D::updateFragments(const std::set<EFAElement *> & CrackTipElements,
859  std::map<unsigned int, EFANode *> & EmbeddedNodes)
860 {
861  // combine the crack-tip faces in a fragment to a single intersected face
862  std::set<EFAElement *>::iterator sit;
863  sit = CrackTipElements.find(this);
864  if (sit != CrackTipElements.end()) // curr_elem is a crack tip element
865  {
866  if (_fragments.size() == 1)
867  _fragments[0]->combine_tip_faces();
868  else
869  EFAError("crack tip elem ", _id, " must have 1 fragment");
870  }
871 
872  // remove the inappropriate embedded nodes on interior faces
873  // (MUST DO THIS AFTER combine_tip_faces())
874  if (_fragments.size() == 1)
875  _fragments[0]->removeInvalidEmbeddedNodes(EmbeddedNodes);
876 
877  // for an element with no fragment, create one fragment identical to the element
878  if (_fragments.size() == 0)
879  _fragments.push_back(new EFAFragment3D(this, true, this));
880  if (_fragments.size() != 1)
881  EFAError("Element ", _id, " must have 1 fragment at this point");
882 
883  // count fragment's cut faces
884  unsigned int num_cut_frag_faces = _fragments[0]->getNumCuts();
885  unsigned int num_frag_faces = _fragments[0]->numFaces();
886  if (num_cut_frag_faces > _fragments[0]->numFaces())
887  EFAError("In element ", _id, " there are too many cut fragment faces");
888 
889  // leave the uncut frag as it is
890  if (num_cut_frag_faces == 0)
891  {
892  if (!isPartial()) // delete the temp frag for an uncut elem
893  {
894  delete _fragments[0];
895  _fragments.clear();
896  }
897  return;
898  }
899 
900  // split one fragment into one or two new fragments
901  std::vector<EFAFragment3D *> new_frags = _fragments[0]->split();
902  if (new_frags.size() == 1 || new_frags.size() == 2)
903  {
904  delete _fragments[0]; // delete the old fragment
905  _fragments.clear();
906  for (unsigned int i = 0; i < new_frags.size(); ++i)
907  _fragments.push_back(new_frags[i]);
908  }
909  else
910  EFAError("Number of fragments must be 1 or 2 at this point");
911 
912  fragmentSanityCheck(num_frag_faces, num_cut_frag_faces);
913 }
914 
915 void
916 EFAElement3D::fragmentSanityCheck(unsigned int n_old_frag_faces, unsigned int n_old_frag_cuts) const
917 {
918  unsigned int n_interior_nodes = numInteriorNodes();
919  if (n_interior_nodes > 0 && n_interior_nodes != 1)
920  EFAError("After update_fragments this element has ", n_interior_nodes, " interior nodes");
921 
922  if (n_old_frag_cuts == 0)
923  {
924  if (_fragments.size() != 1 || _fragments[0]->numFaces() != n_old_frag_faces)
925  EFAError("Incorrect link size for element with 0 cuts");
926  }
927  else if (fragmentHasTipFaces()) // crack tip case
928  {
929  if (_fragments.size() != 1 || _fragments[0]->numFaces() != n_old_frag_faces + n_old_frag_cuts)
930  EFAError("Incorrect link size for element with crack-tip faces");
931  }
932  else // frag is thoroughly cut
933  {
934  if (_fragments.size() != 2 || (_fragments[0]->numFaces() + _fragments[1]->numFaces()) !=
935  n_old_frag_faces + n_old_frag_cuts + 2)
936  EFAError("Incorrect link size for element that has been completely cut");
937  }
938 }
939 
940 void
942 {
943  const EFAElement3D * from_elem3d = dynamic_cast<const EFAElement3D *>(from_elem);
944  if (!from_elem3d)
945  EFAError("from_elem is not of EFAelement3D type");
946 
947  // restore fragments
948  if (_fragments.size() != 0)
949  EFAError("in restoreFragmentInfo elements must not have any pre-existing fragments");
950  for (unsigned int i = 0; i < from_elem3d->numFragments(); ++i)
951  _fragments.push_back(new EFAFragment3D(this, true, from_elem3d, i));
952 
953  // restore interior nodes
954  if (_interior_nodes.size() != 0)
955  EFAError("in restoreFragmentInfo elements must not have any pre-exsiting interior nodes");
956  for (unsigned int i = 0; i < from_elem3d->_interior_nodes.size(); ++i)
957  _interior_nodes.push_back(new EFAVolumeNode(*from_elem3d->_interior_nodes[i]));
958 
959  // restore face intersections
960  if (getNumCuts() != 0)
961  EFAError("In restoreEdgeIntersection: edge cuts already exist in element ", _id);
962  for (unsigned int i = 0; i < _num_faces; ++i)
963  _faces[i]->copyIntersection(*from_elem3d->_faces[i]);
964 
965  // replace all local nodes with global nodes
966  for (unsigned int i = 0; i < from_elem3d->numNodes(); ++i)
967  {
968  if (from_elem3d->_nodes[i]->category() == EFANode::N_CATEGORY_LOCAL_INDEX)
969  switchNode(
970  _nodes[i], from_elem3d->_nodes[i], false); // EFAelement is not a child of any parent
971  else
972  EFAError("In restoreFragmentInfo all of from_elem's nodes must be local");
973  }
974 }
975 
976 void
977 EFAElement3D::createChild(const std::set<EFAElement *> & CrackTipElements,
978  std::map<unsigned int, EFAElement *> & Elements,
979  std::map<unsigned int, EFAElement *> & newChildElements,
980  std::vector<EFAElement *> & ChildElements,
981  std::vector<EFAElement *> & ParentElements,
982  std::map<unsigned int, EFANode *> & TempNodes)
983 {
984  if (_children.size() != 0)
985  EFAError("Element cannot have existing children in createChildElements");
986 
987  if (_fragments.size() > 1 || shouldDuplicateForCrackTip(CrackTipElements))
988  {
989  if (_fragments.size() > 2)
990  EFAError("More than 2 fragments not yet supported");
991 
992  // set up the children
993  ParentElements.push_back(this);
994  for (unsigned int ichild = 0; ichild < _fragments.size(); ++ichild)
995  {
996  unsigned int new_elem_id;
997  if (newChildElements.size() == 0)
998  new_elem_id = Efa::getNewID(Elements);
999  else
1000  new_elem_id = Efa::getNewID(newChildElements);
1001 
1002  EFAElement3D * childElem = new EFAElement3D(new_elem_id, this->numNodes(), this->numFaces());
1003  newChildElements.insert(std::make_pair(new_elem_id, childElem));
1004 
1005  ChildElements.push_back(childElem);
1006  childElem->setParent(this);
1007  _children.push_back(childElem);
1008 
1009  std::vector<std::vector<EFANode *>> cut_plane_nodes;
1010  for (unsigned int i = 0; i < this->getFragment(ichild)->numFaces(); ++i)
1011  {
1012  if (this->getFragment(ichild)->isFaceInterior(i))
1013  {
1014  EFAFace * face = this->getFragment(ichild)->getFace(i);
1015  std::vector<EFANode *> node_line;
1016  for (unsigned int j = 0; j < face->numNodes(); ++j)
1017  node_line.push_back(face->getNode(j));
1018  cut_plane_nodes.push_back(node_line);
1019  }
1020  }
1021 
1022  std::vector<EFAPoint> cut_plane_points;
1023 
1024  EFAPoint normal(0.0, 0.0, 0.0);
1025  EFAPoint orig(0.0, 0.0, 0.0);
1026 
1027  if (cut_plane_nodes.size())
1028  {
1029  for (unsigned int i = 0; i < cut_plane_nodes[0].size(); ++i)
1030  {
1031  std::vector<EFANode *> master_nodes;
1032  std::vector<double> master_weights;
1033 
1034  this->getMasterInfo(cut_plane_nodes[0][i], master_nodes, master_weights);
1035  EFAPoint coor(0.0, 0.0, 0.0);
1036  for (unsigned int i = 0; i < master_nodes.size(); ++i)
1037  {
1038  EFANode * local = this->createLocalNodeFromGlobalNode(master_nodes[i]);
1039  coor += _local_node_coor[local->id()] * master_weights[i];
1040  delete local;
1041  }
1042  cut_plane_points.push_back(coor);
1043  }
1044  for (unsigned int i = 0; i < cut_plane_points.size(); ++i)
1045  orig += cut_plane_points[i];
1046  orig /= cut_plane_points.size();
1047 
1048  EFAPoint center(0.0, 0.0, 0.0);
1049  for (unsigned int i = 0; i < cut_plane_points.size(); ++i)
1050  center += cut_plane_points[i];
1051  center /= cut_plane_points.size();
1052 
1053  for (unsigned int i = 0; i < cut_plane_points.size(); ++i)
1054  {
1055  unsigned int iplus1 = i < cut_plane_points.size() - 1 ? i + 1 : 0;
1056  EFAPoint ray1 = cut_plane_points[i] - center;
1057  EFAPoint ray2 = cut_plane_points[iplus1] - center;
1058  normal += ray1.cross(ray2);
1059  }
1060  normal /= cut_plane_points.size();
1061  Xfem::normalizePoint(normal);
1062  }
1063 
1064  // get child element's nodes
1065  for (unsigned int j = 0; j < _num_nodes; ++j)
1066  {
1067  EFAPoint p(0.0, 0.0, 0.0);
1068  p = _local_node_coor[j];
1069  EFAPoint origin_to_point = p - orig;
1070  if (_fragments.size() == 1 && !shouldDuplicateForCrackTip(CrackTipElements))
1071  childElem->setNode(j, _nodes[j]); // inherit parent's node
1072  else if (origin_to_point * normal < Xfem::tol)
1073  childElem->setNode(j, _nodes[j]); // inherit parent's node
1074  else // parent element's node is not in fragment
1075  {
1076  unsigned int new_node_id = Efa::getNewID(TempNodes);
1077  EFANode * newNode = new EFANode(new_node_id, EFANode::N_CATEGORY_TEMP, _nodes[j]);
1078  TempNodes.insert(std::make_pair(new_node_id, newNode));
1079  childElem->setNode(j, newNode); // be a temp node
1080  }
1081  }
1082 
1083  // get child element's fragments
1084  EFAFragment3D * new_frag = new EFAFragment3D(childElem, true, this, ichild);
1085  childElem->_fragments.push_back(new_frag);
1086 
1087  // get child element's faces and set up adjacent faces
1088  childElem->createFaces();
1089  for (unsigned int j = 0; j < _num_faces; ++j)
1090  childElem->_faces[j]->copyIntersection(*_faces[j]);
1091  childElem->removePhantomEmbeddedNode(); // IMPORTANT
1092 
1093  // inherit old interior nodes
1094  for (unsigned int j = 0; j < _interior_nodes.size(); ++j)
1095  childElem->_interior_nodes.push_back(new EFAVolumeNode(*_interior_nodes[j]));
1096  }
1097  }
1098  else // num_links == 1 || num_links == 0
1099  {
1100  // child is itself - but don't insert into the list of ChildElements!!!
1101  _children.push_back(this);
1102  }
1103 }
1104 
1105 void
1107 {
1108  // remove the embedded nodes on faces that are outside the real domain
1109  if (_fragments.size() > 0)
1110  {
1111  for (unsigned int i = 0; i < _num_faces; ++i)
1112  {
1113  // get emb nodes to be removed on edges
1114  std::vector<EFANode *> nodes_to_delete;
1115  for (unsigned int j = 0; j < _faces[i]->numEdges(); ++j)
1116  {
1117  EFAEdge * edge = _faces[i]->getEdge(j);
1118  for (unsigned int k = 0; k < edge->numEmbeddedNodes(); ++k)
1119  {
1120  if (!_fragments[0]->containsNode(edge->getEmbeddedNode(k)))
1121  nodes_to_delete.push_back(edge->getEmbeddedNode(k));
1122  } // k
1123  } // j
1124 
1125  // get emb nodes to be removed in the face interior
1126  for (unsigned int j = 0; j < _faces[i]->numInteriorNodes(); ++j)
1127  {
1128  EFANode * face_node = _faces[i]->getInteriorNode(j)->getNode();
1129  if (!_fragments[0]->containsNode(face_node))
1130  nodes_to_delete.push_back(face_node);
1131  } // j
1132 
1133  // remove all invalid embedded nodes
1134  for (unsigned int j = 0; j < nodes_to_delete.size(); ++j)
1135  _faces[i]->removeEmbeddedNode(nodes_to_delete[j]);
1136  } // i
1137  }
1138 }
1139 
1140 void
1141 EFAElement3D::connectNeighbors(std::map<unsigned int, EFANode *> & PermanentNodes,
1142  std::map<unsigned int, EFANode *> & TempNodes,
1143  std::map<EFANode *, std::set<EFAElement *>> & InverseConnectivityMap,
1144  bool merge_phantom_faces)
1145 {
1146  // N.B. "this" must point to a child element that was just created
1147  if (!_parent)
1148  EFAError("no parent element for child element ", _id, " in connect_neighbors");
1149  EFAElement3D * parent3d = dynamic_cast<EFAElement3D *>(_parent);
1150  if (!parent3d)
1151  EFAError("cannot dynamic cast to parent3d in connect_neighbors");
1152 
1153  // First loop through edges and merge nodes with neighbors as appropriate
1154  for (unsigned int j = 0; j < _num_faces; ++j)
1155  {
1156  for (unsigned int k = 0; k < parent3d->numFaceNeighbors(j); ++k)
1157  {
1158  EFAElement3D * NeighborElem = parent3d->getFaceNeighbor(j, k);
1159  unsigned int neighbor_face_id = NeighborElem->getNeighborIndex(parent3d);
1160 
1161  if (_faces[j]->hasIntersection())
1162  {
1163  for (unsigned int l = 0; l < NeighborElem->numChildren(); ++l)
1164  {
1165  EFAElement3D * childOfNeighborElem =
1166  dynamic_cast<EFAElement3D *>(NeighborElem->getChild(l));
1167  if (!childOfNeighborElem)
1168  EFAError("dynamic cast childOfNeighborElem fails");
1169 
1170  // Check to see if the nodes are already merged. There's nothing else to do in that case.
1171  EFAFace * neighborChildFace = childOfNeighborElem->getFace(neighbor_face_id);
1172  if (_faces[j]->equivalent(neighborChildFace))
1173  continue;
1174 
1175  if (_fragments[0]->isConnected(childOfNeighborElem->getFragment(0)))
1176  {
1177  for (unsigned int i = 0; i < _faces[j]->numNodes(); ++i)
1178  {
1179  unsigned int childNodeIndex = i;
1180  unsigned int neighborChildNodeIndex =
1181  parent3d->getNeighborFaceNodeID(j, childNodeIndex, NeighborElem);
1182 
1183  EFANode * childNode = _faces[j]->getNode(childNodeIndex);
1184  EFANode * childOfNeighborNode = neighborChildFace->getNode(neighborChildNodeIndex);
1185  mergeNodes(
1186  childNode, childOfNeighborNode, childOfNeighborElem, PermanentNodes, TempNodes);
1187  } // i
1188 
1189  for (unsigned int m = 0; m < _num_interior_face_nodes; ++m)
1190  {
1191  unsigned int childNodeIndex = m;
1192  unsigned int neighborChildNodeIndex =
1193  parent3d->getNeighborFaceInteriorNodeID(j, childNodeIndex, NeighborElem);
1194 
1195  EFANode * childNode = _faces[j]->getInteriorFaceNode(childNodeIndex);
1196  EFANode * childOfNeighborNode =
1197  neighborChildFace->getInteriorFaceNode(neighborChildNodeIndex);
1198  mergeNodes(
1199  childNode, childOfNeighborNode, childOfNeighborElem, PermanentNodes, TempNodes);
1200  } // m
1201  }
1202  } // l, loop over NeighborElem's children
1203  }
1204  else // No edge intersection -- optionally merge non-material nodes if they share a common
1205  // parent
1206  {
1207  if (merge_phantom_faces)
1208  {
1209  for (unsigned int l = 0; l < NeighborElem->numChildren(); ++l)
1210  {
1211  EFAElement3D * childOfNeighborElem =
1212  dynamic_cast<EFAElement3D *>(NeighborElem->getChild(l));
1213  if (!childOfNeighborElem)
1214  EFAError("dynamic cast childOfNeighborElem fails");
1215 
1216  EFAFace * neighborChildFace = childOfNeighborElem->getFace(neighbor_face_id);
1217  if (!neighborChildFace
1218  ->hasIntersection()) // neighbor face must NOT have intersection either
1219  {
1220  // Check to see if the nodes are already merged. There's nothing else to do in that
1221  // case.
1222  if (_faces[j]->equivalent(neighborChildFace))
1223  continue;
1224 
1225  for (unsigned int i = 0; i < _faces[j]->numNodes(); ++i)
1226  {
1227  unsigned int childNodeIndex = i;
1228  unsigned int neighborChildNodeIndex =
1229  parent3d->getNeighborFaceNodeID(j, childNodeIndex, NeighborElem);
1230 
1231  EFANode * childNode = _faces[j]->getNode(childNodeIndex);
1232  EFANode * childOfNeighborNode = neighborChildFace->getNode(neighborChildNodeIndex);
1233 
1234  if (childNode->parent() != NULL &&
1235  childNode->parent() ==
1236  childOfNeighborNode
1237  ->parent()) // non-material node and both come from same parent
1238  mergeNodes(childNode,
1239  childOfNeighborNode,
1240  childOfNeighborElem,
1241  PermanentNodes,
1242  TempNodes);
1243  } // i
1244  }
1245  } // loop over NeighborElem's children
1246  } // if (merge_phantom_edges)
1247  } // IF edge-j has_intersection()
1248  } // k, loop over neighbors on edge j
1249  } // j, loop over all faces
1250 
1251  // Now do a second loop through faces and convert remaining nodes to permanent nodes.
1252  // If there is no neighbor on that face, also duplicate the embedded node if it exists
1253  for (unsigned int j = 0; j < _num_nodes; ++j)
1254  {
1255  EFANode * childNode = _nodes[j];
1256  if (childNode->category() == EFANode::N_CATEGORY_TEMP)
1257  {
1258  // if current child element does not have siblings, and if current temp node is a lone one
1259  // this temp node should be merged back to its parent permanent node. Otherwise we would have
1260  // permanent nodes that are not connected to any element
1261  std::set<EFAElement *> patch_elems = InverseConnectivityMap[childNode->parent()];
1262  if (parent3d->numFragments() == 1 && patch_elems.size() == 1)
1263  switchNode(childNode->parent(), childNode, false);
1264  else
1265  {
1266  unsigned int new_node_id = Efa::getNewID(PermanentNodes);
1267  EFANode * newNode =
1268  new EFANode(new_node_id, EFANode::N_CATEGORY_PERMANENT, childNode->parent());
1269  PermanentNodes.insert(std::make_pair(new_node_id, newNode));
1270  switchNode(newNode, childNode, false);
1271  }
1272  if (!Efa::deleteFromMap(TempNodes, childNode))
1273  EFAError(
1274  "Attempted to delete node: ", childNode->id(), " from TempNodes, but couldn't find it");
1275  }
1276  }
1277 }
1278 
1279 void
1280 EFAElement3D::printElement(std::ostream & ostream)
1281 {
1282  // first line: all elem faces
1283  ostream << std::setw(5);
1284  ostream << _id << "| ";
1285  for (unsigned int j = 0; j < _num_faces; ++j)
1286  {
1287  for (unsigned int k = 0; k < _faces[j]->numNodes(); ++k)
1288  ostream << std::setw(5) << _faces[j]->getNode(k)->idCatString();
1289  ostream << " | ";
1290  }
1291  ostream << std::endl;
1292 
1293  // second line: emb nodes in all faces + neighbor of each face
1294  ostream << std::setw(5);
1295  ostream << "embed"
1296  << "| ";
1297  for (unsigned int j = 0; j < _num_faces; ++j)
1298  {
1299  for (unsigned int k = 0; k < _faces[j]->numEdges(); ++k)
1300  {
1301  ostream << std::setw(4);
1302  if (_faces[j]->getEdge(k)->hasIntersection())
1303  {
1304  if (_faces[j]->getEdge(k)->numEmbeddedNodes() > 1)
1305  {
1306  ostream << "[";
1307  for (unsigned int l = 0; l < _faces[j]->getEdge(k)->numEmbeddedNodes(); ++l)
1308  {
1309  ostream << _faces[j]->getEdge(k)->getEmbeddedNode(l)->id() << " ";
1310  if (l == _faces[j]->getEdge(k)->numEmbeddedNodes() - 1)
1311  ostream << "]";
1312  else
1313  ostream << " ";
1314  } // l
1315  }
1316  else
1317  ostream << _faces[j]->getEdge(k)->getEmbeddedNode(0)->id() << " ";
1318  }
1319  else
1320  ostream << " -- ";
1321  } // k
1322  ostream << " | ";
1323  } // j
1324  ostream << std::endl;
1325 
1326  // third line: neighbors
1327  ostream << std::setw(5);
1328  ostream << "neigh"
1329  << "| ";
1330  for (unsigned int j = 0; j < _num_faces; ++j)
1331  {
1332  ostream << std::setw(4);
1333  if (numFaceNeighbors(j) > 1)
1334  {
1335  ostream << "[";
1336  for (unsigned int k = 0; k < numFaceNeighbors(j); ++k)
1337  {
1338  ostream << getFaceNeighbor(j, k)->id();
1339  if (k == numFaceNeighbors(j) - 1)
1340  ostream << "]";
1341  else
1342  ostream << " ";
1343  }
1344  }
1345  else
1346  {
1347  if (numFaceNeighbors(j) == 1)
1348  ostream << getFaceNeighbor(j, 0)->id() << " ";
1349  else
1350  ostream << " -- ";
1351  }
1352  }
1353  ostream << std::endl;
1354 
1355  // fourth line: fragments
1356  for (unsigned int j = 0; j < _fragments.size(); ++j)
1357  {
1358  ostream << std::setw(4);
1359  ostream << "frag" << j << "| ";
1360  for (unsigned int k = 0; k < _fragments[j]->numFaces(); ++k)
1361  {
1362  for (unsigned int l = 0; l < _fragments[j]->getFace(k)->numNodes(); ++l)
1363  ostream << std::setw(5) << _fragments[j]->getFace(k)->getNode(l)->idCatString();
1364  ostream << " | ";
1365  }
1366  ostream << std::endl;
1367  }
1368  ostream << std::endl;
1369 }
1370 
1371 EFAFragment3D *
1372 EFAElement3D::getFragment(unsigned int frag_id) const
1373 {
1374  if (frag_id < _fragments.size())
1375  return _fragments[frag_id];
1376  else
1377  EFAError("frag_id out of bounds");
1378 }
1379 
1380 std::set<EFANode *>
1381 EFAElement3D::getFaceNodes(unsigned int face_id) const
1382 {
1383  std::set<EFANode *> face_nodes;
1384  for (unsigned int i = 0; i < _faces[face_id]->numNodes(); ++i)
1385  face_nodes.insert(_faces[face_id]->getNode(i));
1386  return face_nodes;
1387 }
1388 
1389 bool
1390 EFAElement3D::getFaceNodeParametricCoordinates(EFANode * node, std::vector<double> & xi_3d) const
1391 {
1392  // get the parametric coords of a node in an element face
1393  unsigned int face_id = 99999;
1394  bool face_found = false;
1395  for (unsigned int i = 0; i < _num_faces; ++i)
1396  {
1397  if (_faces[i]->containsNode(node))
1398  {
1399  face_id = i;
1400  face_found = true;
1401  break;
1402  }
1403  }
1404  if (face_found)
1405  {
1406  std::vector<double> xi_2d(2, 0.0);
1407  if (_faces[face_id]->getFaceNodeParametricCoords(node, xi_2d))
1408  mapParametricCoordinateFrom2DTo3D(face_id, xi_2d, xi_3d);
1409  else
1410  EFAError("failed to get the 2D para coords on the face");
1411  }
1412  return face_found;
1413 }
1414 
1415 EFAVolumeNode *
1416 EFAElement3D::getInteriorNode(unsigned int interior_node_id) const
1417 {
1418  if (interior_node_id < _interior_nodes.size())
1419  return _interior_nodes[interior_node_id];
1420  else
1421  EFAError("interior_node_id out of bounds");
1422 }
1423 
1424 void
1425 EFAElement3D::removeEmbeddedNode(EFANode * emb_node, bool remove_for_neighbor)
1426 {
1427  for (unsigned int i = 0; i < _fragments.size(); ++i)
1428  _fragments[i]->removeEmbeddedNode(emb_node);
1429 
1430  for (unsigned int i = 0; i < _faces.size(); ++i)
1431  _faces[i]->removeEmbeddedNode(emb_node);
1432 
1433  if (remove_for_neighbor)
1434  {
1435  for (unsigned int i = 0; i < numFaces(); ++i)
1436  for (unsigned int j = 0; j < numFaceNeighbors(i); ++j)
1437  getFaceNeighbor(i, j)->removeEmbeddedNode(emb_node, false);
1438  }
1439 }
1440 
1441 unsigned int
1443 {
1444  return _faces.size();
1445 }
1446 
1447 void
1448 EFAElement3D::setFace(unsigned int face_id, EFAFace * face)
1449 {
1450  _faces[face_id] = face;
1451 }
1452 
1453 void
1455 {
1456  // create element faces based on existing element nodes
1457  int hex_local_node_indices[6][4] = {
1458  {0, 3, 2, 1}, {0, 1, 5, 4}, {1, 2, 6, 5}, {2, 3, 7, 6}, {3, 0, 4, 7}, {4, 5, 6, 7}};
1459  int tet_local_node_indices[4][3] = {{0, 2, 1}, {0, 1, 3}, {1, 2, 3}, {2, 0, 3}};
1460 
1461  int hex_interior_face_node_indices[6][5] = {{8, 9, 10, 11, 20},
1462  {8, 13, 16, 12, 21},
1463  {9, 14, 17, 13, 22},
1464  {10, 14, 18, 15, 23},
1465  {11, 15, 19, 12, 24},
1466  {16, 17, 18, 19, 25}};
1467  int tet_interior_face_node_indices[4][3] = {{4, 5, 6}, {4, 7, 8}, {5, 8, 9}, {6, 7, 9}};
1468 
1469  _faces = std::vector<EFAFace *>(_num_faces, NULL);
1470  if (_num_nodes == 8 || _num_nodes == 20 || _num_nodes == 27)
1471  {
1472  if (_num_faces != 6)
1473  EFAError("num_faces of hexes must be 6");
1474  for (unsigned int i = 0; i < _num_faces; ++i)
1475  {
1477  for (unsigned int j = 0; j < 4; ++j)
1478  _faces[i]->setNode(j, _nodes[hex_local_node_indices[i][j]]);
1479  _faces[i]->createEdges();
1480  for (unsigned int k = 0; k < _num_interior_face_nodes; ++k)
1481  _faces[i]->setInteriorFaceNode(k, _nodes[hex_interior_face_node_indices[i][k]]);
1482  }
1483  }
1484  else if (_num_nodes == 4 || _num_nodes == 10)
1485  {
1486  if (_num_faces != 4)
1487  EFAError("num_faces of tets must be 4");
1488  for (unsigned int i = 0; i < _num_faces; ++i)
1489  {
1491  for (unsigned int j = 0; j < 3; ++j)
1492  _faces[i]->setNode(j, _nodes[tet_local_node_indices[i][j]]);
1493  _faces[i]->createEdges();
1494  for (unsigned int k = 0; k < _num_interior_face_nodes; ++k)
1495  _faces[i]->setInteriorFaceNode(k, _nodes[tet_interior_face_node_indices[i][k]]);
1496  }
1497  }
1498  else
1499  EFAError("unknown 3D element type in createFaces()");
1500 
1501  for (unsigned int face_iter = 0; face_iter < _num_faces; ++face_iter)
1502  {
1503  _face_edge_neighbors[face_iter].resize(_faces[face_iter]->numEdges());
1504  for (unsigned int edge_iter = 0; edge_iter < _faces[face_iter]->numEdges(); ++edge_iter)
1505  _face_edge_neighbors[face_iter][edge_iter].clear();
1506  }
1507 
1508  // create element face connectivity array
1509  findFacesAdjacentToFaces(); // IMPORTANT
1510 }
1511 
1512 EFAFace *
1513 EFAElement3D::getFace(unsigned int face_id) const
1514 {
1515  return _faces[face_id];
1516 }
1517 
1518 unsigned int
1520 {
1521  bool found_face_id = false;
1522  unsigned int face_id;
1523  for (unsigned int iface = 0; iface < _num_faces; ++iface)
1524  {
1525  if (_faces[iface]->equivalent(face))
1526  {
1527  face_id = iface;
1528  found_face_id = true;
1529  break;
1530  }
1531  }
1532  if (!found_face_id)
1533  EFAError("input face not found in get_face_id()");
1534  return face_id;
1535 }
1536 
1537 std::vector<unsigned int>
1539 {
1540  std::vector<unsigned int> face_id;
1541  for (unsigned int i = 0; i < _num_faces; ++i)
1542  {
1543  for (unsigned int j = 0; j < other_elem->_num_faces; ++j)
1544  {
1545  if (_faces[i]->equivalent(other_elem->_faces[j]))
1546  {
1547  face_id.push_back(i);
1548  break;
1549  }
1550  }
1551  }
1552  return face_id;
1553 }
1554 
1555 bool
1557  std::vector<unsigned int> & face_id,
1558  std::vector<unsigned int> & edge_id) const
1559 {
1560  bool has_common_edge = false;
1561  bool move_to_next_edge = false;
1562  face_id.clear();
1563  edge_id.clear();
1564  for (unsigned int i = 0; i < _num_faces; ++i)
1565  for (unsigned int j = 0; j < _faces[i]->numEdges(); ++j)
1566  {
1567  move_to_next_edge = false;
1568  for (unsigned int k = 0; k < other_elem->_num_faces; ++k)
1569  {
1570  for (unsigned int l = 0; l < other_elem->_faces[k]->numEdges(); ++l)
1571  if ((_faces[i]->getEdge(j)->equivalent(*(other_elem->_faces[k]->getEdge(l)))) &&
1572  !(_faces[i]->equivalent(other_elem->_faces[k])))
1573  {
1574  face_id.push_back(i);
1575  edge_id.push_back(j);
1576  move_to_next_edge = true;
1577  has_common_edge = true;
1578  break;
1579  }
1580 
1581  if (move_to_next_edge)
1582  break;
1583  }
1584  }
1585 
1586  return has_common_edge;
1587 }
1588 
1589 unsigned int
1591  unsigned int node_id,
1592  EFAElement3D * neighbor_elem) const
1593 {
1594  // get the corresponding node_id on the corresponding face of neighbor_elem
1595  bool found_id = false;
1596  unsigned int neigh_face_node_id;
1597  unsigned int common_face_id = getNeighborIndex(neighbor_elem);
1598  if (common_face_id == face_id)
1599  {
1600  unsigned int neigh_face_id = neighbor_elem->getNeighborIndex(this);
1601  EFAFace * neigh_face = neighbor_elem->getFace(neigh_face_id);
1602  for (unsigned int i = 0; i < neigh_face->numNodes(); ++i)
1603  {
1604  if (_faces[face_id]->getNode(node_id) == neigh_face->getNode(i))
1605  {
1606  neigh_face_node_id = i;
1607  found_id = true;
1608  break;
1609  }
1610  }
1611  }
1612  else
1613  EFAError("getNeighborFaceNodeID: neighbor_elem is not a neighbor on face_id");
1614  if (!found_id)
1615  EFAError("getNeighborFaceNodeID: could not find neighbor face node id");
1616  return neigh_face_node_id;
1617 }
1618 
1619 unsigned int
1621  unsigned int node_id,
1622  EFAElement3D * neighbor_elem) const
1623 {
1624  // get the corresponding node_id on the corresponding face of neighbor_elem
1625  bool found_id = false;
1626  unsigned int neigh_face_node_id;
1627  unsigned int common_face_id = getNeighborIndex(neighbor_elem);
1628  if (common_face_id == face_id)
1629  {
1630  unsigned int neigh_face_id = neighbor_elem->getNeighborIndex(this);
1631  EFAFace * neigh_face = neighbor_elem->getFace(neigh_face_id);
1632 
1633  for (unsigned int i = 0; i < _num_interior_face_nodes; ++i)
1634  {
1635  if (_faces[face_id]->getInteriorFaceNode(node_id) == neigh_face->getInteriorFaceNode(i))
1636  {
1637  neigh_face_node_id = i;
1638  found_id = true;
1639  break;
1640  }
1641  }
1642  }
1643  else
1644  EFAError("getNeighborFaceNodeID: neighbor_elem is not a neighbor on face_id");
1645  if (!found_id)
1646  EFAError("getNeighborFaceNodeID: could not find neighbor face node id");
1647  return neigh_face_node_id;
1648 }
1649 
1650 unsigned int
1652  unsigned int edge_id,
1653  EFAElement3D * neighbor_elem) const
1654 {
1655  // get the corresponding edge_id on the corresponding face of neighbor_elem
1656  bool found_id = false;
1657  unsigned int neigh_face_edge_id;
1658  unsigned int common_face_id = getNeighborIndex(neighbor_elem);
1659  if (common_face_id == face_id)
1660  {
1661  unsigned int neigh_face_id = neighbor_elem->getNeighborIndex(this);
1662  EFAFace * neigh_face = neighbor_elem->getFace(neigh_face_id);
1663  for (unsigned int i = 0; i < neigh_face->numEdges(); ++i)
1664  {
1665  if (_faces[face_id]->getEdge(edge_id)->equivalent(*neigh_face->getEdge(i)))
1666  {
1667  neigh_face_edge_id = i;
1668  found_id = true;
1669  break;
1670  }
1671  }
1672  }
1673  else
1674  EFAError("getNeighborFaceEdgeID: neighbor_elem is not a neighbor on face_id");
1675  if (!found_id)
1676  EFAError("getNeighborFaceEdgeID: could not find neighbor face edge id");
1677  return neigh_face_edge_id;
1678 }
1679 
1680 void
1682 {
1683  _faces_adjacent_to_faces.clear();
1684  for (unsigned int i = 0; i < _faces.size(); ++i)
1685  {
1686  std::vector<EFAFace *> face_adjacents(_faces[i]->numEdges(), NULL);
1687  for (unsigned int j = 0; j < _faces.size(); ++j)
1688  {
1689  if (_faces[j] != _faces[i] && _faces[i]->isAdjacent(_faces[j]))
1690  {
1691  unsigned int adj_edge = _faces[i]->adjacentCommonEdge(_faces[j]);
1692  face_adjacents[adj_edge] = _faces[j];
1693  }
1694  }
1695  _faces_adjacent_to_faces.push_back(face_adjacents);
1696  }
1697 }
1698 
1699 EFAFace *
1700 EFAElement3D::getAdjacentFace(unsigned int face_id, unsigned int edge_id) const
1701 {
1702  return _faces_adjacent_to_faces[face_id][edge_id];
1703 }
1704 
1705 EFAFace *
1706 EFAElement3D::getFragmentFace(unsigned int frag_id, unsigned int face_id) const
1707 {
1708  if (frag_id < _fragments.size())
1709  return _fragments[frag_id]->getFace(face_id);
1710  else
1711  EFAError("frag_id out of bounds in getFragmentFace");
1712 }
1713 
1714 std::set<EFANode *>
1715 EFAElement3D::getPhantomNodeOnFace(unsigned int face_id) const
1716 {
1717  std::set<EFANode *> phantom_nodes;
1718  if (_fragments.size() > 0)
1719  {
1720  for (unsigned int j = 0; j < _faces[face_id]->numNodes(); ++j) // loop ove 2 edge nodes
1721  {
1722  bool node_in_frag = false;
1723  for (unsigned int k = 0; k < _fragments.size(); ++k)
1724  {
1725  if (_fragments[k]->containsNode(_faces[face_id]->getNode(j)))
1726  {
1727  node_in_frag = true;
1728  break;
1729  }
1730  }
1731  if (!node_in_frag)
1732  phantom_nodes.insert(_faces[face_id]->getNode(j));
1733  }
1734  }
1735  return phantom_nodes;
1736 }
1737 
1738 bool
1739 EFAElement3D::getFragmentFaceID(unsigned int elem_face_id, unsigned int & frag_face_id) const
1740 {
1741  // find the fragment face that is contained by given element edge
1742  // N.B. if the elem edge contains two frag edges, this method will only return
1743  // the first frag edge ID
1744  bool frag_face_found = false;
1745  frag_face_id = 99999;
1746  if (_fragments.size() == 1)
1747  {
1748  for (unsigned int j = 0; j < _fragments[0]->numFaces(); ++j)
1749  {
1750  if (_faces[elem_face_id]->containsFace(_fragments[0]->getFace(j)))
1751  {
1752  frag_face_id = j;
1753  frag_face_found = true;
1754  break;
1755  }
1756  }
1757  }
1758  return frag_face_found;
1759 }
1760 
1761 bool
1762 EFAElement3D::getFragmentFaceEdgeID(unsigned int ElemFaceID,
1763  unsigned int ElemFaceEdgeID,
1764  unsigned int & FragFaceID,
1765  unsigned int & FragFaceEdgeID) const
1766 {
1767  // Purpose: given an edge of an elem face, find which frag face's edge it contains
1768  bool frag_edge_found = false;
1769  FragFaceID = 99999;
1770  FragFaceEdgeID = 99999;
1771  if (getFragmentFaceID(ElemFaceID, FragFaceID))
1772  {
1773  EFAEdge * elem_edge = _faces[ElemFaceID]->getEdge(ElemFaceEdgeID);
1774  EFAFace * frag_face = getFragmentFace(0, FragFaceID);
1775  for (unsigned int i = 0; i < frag_face->numEdges(); ++i)
1776  {
1777  if (elem_edge->containsEdge(*frag_face->getEdge(i)))
1778  {
1779  FragFaceEdgeID = i;
1780  frag_edge_found = true;
1781  break;
1782  }
1783  }
1784  }
1785  return frag_edge_found;
1786 }
1787 
1788 bool
1789 EFAElement3D::isPhysicalEdgeCut(unsigned int ElemFaceID,
1790  unsigned int ElemFaceEdgeID,
1791  double position) const
1792 {
1793  unsigned int FragFaceID = 99999, FragFaceEdgeID = 99999;
1794  bool is_in_real = false;
1795  if (_fragments.size() == 0)
1796  {
1797  is_in_real = true;
1798  }
1799  else if (getFragmentFaceEdgeID(ElemFaceID, ElemFaceEdgeID, FragFaceID, FragFaceEdgeID))
1800  {
1801  EFAEdge * elem_edge = _faces[ElemFaceID]->getEdge(ElemFaceEdgeID);
1802  EFAEdge * frag_edge = getFragmentFace(0, FragFaceID)->getEdge(FragFaceEdgeID);
1803  double xi[2] = {-1.0, -1.0}; // relative coords of two frag edge nodes
1804  xi[0] = elem_edge->distanceFromNode1(frag_edge->getNode(0));
1805  xi[1] = elem_edge->distanceFromNode1(frag_edge->getNode(1));
1806  if ((position - xi[0]) * (position - xi[1]) <
1807  0.0) // the cut to be added is within the real part of the edge
1808  is_in_real = true;
1809  }
1810  return is_in_real;
1811 }
1812 
1813 bool
1814 EFAElement3D::isFacePhantom(unsigned int face_id) const
1815 {
1816  bool is_phantom = false;
1817  if (_fragments.size() > 0)
1818  {
1819  bool contains_frag_face = false;
1820  for (unsigned int i = 0; i < _fragments.size(); ++i)
1821  {
1822  for (unsigned int j = 0; j < _fragments[i]->numFaces(); ++j)
1823  {
1824  if (_faces[face_id]->containsFace(_fragments[i]->getFace(j)))
1825  {
1826  contains_frag_face = true;
1827  break;
1828  }
1829  }
1830  if (contains_frag_face)
1831  break;
1832  }
1833  if (!contains_frag_face)
1834  is_phantom = true;
1835  }
1836  return is_phantom;
1837 }
1838 
1839 unsigned int
1840 EFAElement3D::numFaceNeighbors(unsigned int face_id) const
1841 {
1842  return _face_neighbors[face_id].size();
1843 }
1844 
1845 unsigned int
1846 EFAElement3D::numEdgeNeighbors(unsigned int face_id, unsigned int edge_id) const
1847 {
1848  return _face_edge_neighbors[face_id][edge_id].size();
1849 }
1850 
1851 EFAElement3D *
1852 EFAElement3D::getFaceNeighbor(unsigned int face_id, unsigned int neighbor_id) const
1853 {
1854  if (_face_neighbors[face_id][0] != NULL && neighbor_id < _face_neighbors[face_id].size())
1855  return _face_neighbors[face_id][neighbor_id];
1856  else
1857  EFAError("edge neighbor does not exist");
1858 }
1859 
1860 EFAElement3D *
1861 EFAElement3D::getEdgeNeighbor(unsigned int face_id,
1862  unsigned int edge_id,
1863  unsigned int neighbor_id) const
1864 {
1865  if (neighbor_id < _face_edge_neighbors[face_id][edge_id].size())
1866  return _face_edge_neighbors[face_id][edge_id][neighbor_id];
1867  else
1868  EFAError("edge neighbor does not exist");
1869 }
1870 
1871 bool
1873 {
1874  bool has_tip_faces = false;
1875  if (_fragments.size() == 1)
1876  {
1877  for (unsigned int i = 0; i < _num_faces; ++i)
1878  {
1879  unsigned int num_frag_faces = 0; // count how many fragment edges this element edge contains
1880  if (_faces[i]->hasIntersection())
1881  {
1882  for (unsigned int j = 0; j < _fragments[0]->numFaces(); ++j)
1883  {
1884  if (_faces[i]->containsFace(_fragments[0]->getFace(j)))
1885  num_frag_faces += 1;
1886  } // j
1887  if (num_frag_faces == 2)
1888  {
1889  has_tip_faces = true;
1890  break;
1891  }
1892  }
1893  } // i
1894  }
1895  return has_tip_faces;
1896 }
1897 
1898 std::vector<unsigned int>
1900 {
1901  // if this element is a crack tip element, returns the crack tip faces' ID
1902  std::vector<unsigned int> tip_face_id;
1903  if (_fragments.size() == 1) // crack tip element with a partial fragment saved
1904  {
1905  for (unsigned int i = 0; i < _num_faces; ++i)
1906  {
1907  unsigned int num_frag_faces = 0; // count how many fragment faces this element edge contains
1908  if (_faces[i]->hasIntersection())
1909  {
1910  for (unsigned int j = 0; j < _fragments[0]->numFaces(); ++j)
1911  {
1912  if (_faces[i]->containsFace(_fragments[0]->getFace(j)))
1913  num_frag_faces += 1;
1914  } // j
1915  if (num_frag_faces == 2) // element face contains two fragment edges
1916  tip_face_id.push_back(i);
1917  }
1918  } // i
1919  }
1920  return tip_face_id;
1921 }
1922 
1923 std::set<EFANode *>
1925 {
1926  // if this element is a crack tip element, returns the crack tip edge's ID
1927  std::set<EFANode *> tip_emb;
1928  if (_fragments.size() == 1) // crack tip element with a partial fragment saved
1929  {
1930  for (unsigned int i = 0; i < _num_faces; ++i)
1931  {
1932  std::vector<EFAFace *> frag_faces; // count how many fragment edges this element edge contains
1933  if (_faces[i]->hasIntersection())
1934  {
1935  for (unsigned int j = 0; j < _fragments[0]->numFaces(); ++j)
1936  {
1937  if (_faces[i]->containsFace(_fragments[0]->getFace(j)))
1938  frag_faces.push_back(_fragments[0]->getFace(j));
1939  } // j
1940  if (frag_faces.size() == 2) // element edge contains two fragment edges
1941  {
1942  unsigned int edge_id = frag_faces[0]->adjacentCommonEdge(frag_faces[1]);
1943  tip_emb.insert(frag_faces[0]->getEdge(edge_id)->getNode(0));
1944  tip_emb.insert(frag_faces[0]->getEdge(edge_id)->getNode(1));
1945  }
1946  }
1947  } // i
1948  }
1949  return tip_emb;
1950 }
1951 
1952 bool
1953 EFAElement3D::faceContainsTip(unsigned int face_id) const
1954 {
1955  bool contain_tip = false;
1956  if (_fragments.size() == 1)
1957  {
1958  unsigned int num_frag_faces = 0; // count how many fragment faces this element face contains
1959  if (_faces[face_id]->hasIntersection())
1960  {
1961  for (unsigned int j = 0; j < _fragments[0]->numFaces(); ++j)
1962  {
1963  if (_faces[face_id]->containsFace(_fragments[0]->getFace(j)))
1964  num_frag_faces += 1;
1965  } // j
1966  if (num_frag_faces == 2)
1967  contain_tip = true;
1968  }
1969  }
1970  return contain_tip;
1971 }
1972 
1973 bool
1974 EFAElement3D::fragmentFaceAlreadyCut(unsigned int ElemFaceID) const
1975 {
1976  // when marking cuts, check if the corresponding frag face already has been cut
1977  bool has_cut = false;
1978  if (faceContainsTip(ElemFaceID))
1979  has_cut = true;
1980  else
1981  {
1982  unsigned int FragFaceID = 99999;
1983  if (getFragmentFaceID(ElemFaceID, FragFaceID))
1984  {
1985  EFAFace * frag_face = getFragmentFace(0, FragFaceID);
1986  if (frag_face->hasIntersection())
1987  has_cut = true;
1988  }
1989  }
1990  return has_cut;
1991 }
1992 
1993 void
1994 EFAElement3D::addFaceEdgeCut(unsigned int face_id,
1995  unsigned int edge_id,
1996  double position,
1997  EFANode * embedded_node,
1998  std::map<unsigned int, EFANode *> & EmbeddedNodes,
1999  bool add_to_neighbor,
2000  bool add_to_adjacent)
2001 {
2002  // Purpose: add intersection on Edge edge_id of Face face_id
2003  EFANode * local_embedded = NULL;
2004  EFAEdge * cut_edge = _faces[face_id]->getEdge(edge_id);
2005  EFANode * edge_node1 = cut_edge->getNode(0);
2006  if (embedded_node) // use the existing embedded node if it was passed in
2007  local_embedded = embedded_node;
2008 
2009  // get adjacent face info
2010  EFAFace * adj_face = getAdjacentFace(face_id, edge_id);
2011  unsigned int adj_face_id = getFaceID(adj_face);
2012  unsigned int adj_edge_id = adj_face->adjacentCommonEdge(_faces[face_id]);
2013 
2014  // check if cut has already been added to this face edge
2015  bool cut_exist = false;
2016 
2017  if (cut_edge->hasIntersectionAtPosition(position, edge_node1))
2018  {
2019  unsigned int emb_id = cut_edge->getEmbeddedNodeIndex(position, edge_node1);
2020  EFANode * old_emb = cut_edge->getEmbeddedNode(emb_id);
2021  if (embedded_node && embedded_node != old_emb)
2022  EFAError("Attempting to add edge intersection when one already exists with different node.",
2023  " elem: ",
2024  _id,
2025  " edge: ",
2026  edge_id,
2027  " position: ",
2028  position);
2029  local_embedded = old_emb;
2030  cut_exist = true;
2031  }
2032 
2033  if (!cut_exist && !fragmentFaceAlreadyCut(face_id) &&
2034  isPhysicalEdgeCut(face_id, edge_id, position))
2035  {
2036  // check if cut has already been added to the neighbor edges
2037  checkNeighborFaceCut(face_id, edge_id, position, edge_node1, embedded_node, local_embedded);
2039  adj_face_id, adj_edge_id, position, edge_node1, embedded_node, local_embedded);
2040 
2041  if (!local_embedded) // need to create new embedded node
2042  {
2043  unsigned int new_node_id = Efa::getNewID(EmbeddedNodes);
2044  local_embedded = new EFANode(new_node_id, EFANode::N_CATEGORY_EMBEDDED);
2045  EmbeddedNodes.insert(std::make_pair(new_node_id, local_embedded));
2046  }
2047 
2048  // add to elem face edge
2049  cut_edge->addIntersection(position, local_embedded, edge_node1);
2050  if (cut_edge->numEmbeddedNodes() > 2)
2051  EFAError("element edge can't have >2 embedded nodes");
2052 
2053  // cut fragment faces, which is an essential addition to other code in this method that cuts
2054  // element faces
2055  unsigned int FragFaceID;
2056  unsigned int FragFaceEdgeID;
2057  if (getFragmentFaceEdgeID(face_id, edge_id, FragFaceID, FragFaceEdgeID))
2058  {
2059  EFAEdge * elem_edge = _faces[face_id]->getEdge(edge_id);
2060  EFAEdge * frag_edge = getFragmentFace(0, FragFaceID)->getEdge(FragFaceEdgeID);
2061  double xi[2] = {-1.0, -1.0}; // relative coords of two frag edge nodes
2062  xi[0] = elem_edge->distanceFromNode1(frag_edge->getNode(0));
2063  xi[1] = elem_edge->distanceFromNode1(frag_edge->getNode(1));
2064  double frag_pos = (position - xi[0]) / (xi[1] - xi[0]);
2065  EFANode * frag_edge_node1 = frag_edge->getNode(0);
2066 
2067  if (!frag_edge->hasIntersection())
2068  frag_edge->addIntersection(frag_pos, local_embedded, frag_edge_node1);
2069  }
2070 
2071  // add to adjacent face edge
2072  if (add_to_adjacent)
2073  {
2074  double adj_pos = 1.0 - position;
2076  adj_face_id, adj_edge_id, adj_pos, local_embedded, EmbeddedNodes, false, false);
2077  }
2078  }
2079 
2080  // add cut to neighbor face edge
2081  if (add_to_neighbor)
2082  {
2083  for (unsigned int en_iter = 0; en_iter < numFaceNeighbors(face_id); ++en_iter)
2084  {
2085  EFAElement3D * face_neighbor = getFaceNeighbor(face_id, en_iter);
2086  unsigned int neigh_face_id = face_neighbor->getNeighborIndex(this);
2087  unsigned neigh_edge_id = getNeighborFaceEdgeID(face_id, edge_id, face_neighbor);
2088  double neigh_pos = 1.0 - position; // get emb node's postion on neighbor edge
2089  face_neighbor->addFaceEdgeCut(
2090  neigh_face_id, neigh_edge_id, neigh_pos, local_embedded, EmbeddedNodes, false, true);
2091  }
2092 
2093  for (unsigned int en_iter = 0; en_iter < numEdgeNeighbors(face_id, edge_id); ++en_iter)
2094  {
2095  EFAElement3D * edge_neighbor = getEdgeNeighbor(face_id, edge_id, en_iter);
2096  unsigned int neigh_face_id, neigh_edge_id;
2097  getNeighborEdgeIndex(edge_neighbor, face_id, edge_id, neigh_face_id, neigh_edge_id);
2098 
2099  // Check the ordering of the node and the assign the position
2100  double neigh_pos;
2101  if (_faces[face_id]->getEdge(edge_id)->getNode(0) ==
2102  edge_neighbor->getFace(neigh_face_id)->getEdge(neigh_edge_id)->getNode(0))
2103  neigh_pos = position;
2104  else if (_faces[face_id]->getEdge(edge_id)->getNode(1) ==
2105  edge_neighbor->getFace(neigh_face_id)->getEdge(neigh_edge_id)->getNode(0))
2106  neigh_pos = 1.0 - position;
2107  else
2108  EFAError("The EFANodes on commaon edge are not matched.");
2109 
2110  edge_neighbor->addFaceEdgeCut(
2111  neigh_face_id, neigh_edge_id, neigh_pos, local_embedded, EmbeddedNodes, false, true);
2112  }
2113  } // If add_to_neighbor required
2114 }
2115 
2116 void
2117 EFAElement3D::addFragFaceEdgeCut(unsigned int /*frag_face_id*/,
2118  unsigned int /*frag_edge_id*/,
2119  double /*position*/,
2120  std::map<unsigned int, EFANode *> & /*EmbeddedNodes*/,
2121  bool /*add_to_neighbor*/,
2122  bool /*add_to_adjacent*/)
2123 {
2124  // TODO: mark frag face edges
2125  // also need to check if cut has been added to this frag face edge or neighbor edge of adjacent
2126  // face
2127 }
2128 
2129 void
2131  unsigned int edge_id,
2132  double position,
2133  EFANode * from_node,
2134  EFANode * embedded_node,
2135  EFANode *& local_embedded)
2136 {
2137  // N.B. this is important. We are checking if the corresponding edge of the neighbor face or of
2138  // the adjacent
2139  // face's neighbor face has a cut at the same position. If so, use the existing embedded node as
2140  // local_embedded
2141  for (unsigned int en_iter = 0; en_iter < numFaceNeighbors(face_id); ++en_iter)
2142  {
2143  EFAElement3D * face_neighbor = getFaceNeighbor(face_id, en_iter);
2144  unsigned int neigh_face_id = face_neighbor->getNeighborIndex(this);
2145  unsigned neigh_edge_id = getNeighborFaceEdgeID(face_id, edge_id, face_neighbor);
2146  EFAEdge * neigh_edge = face_neighbor->getFace(neigh_face_id)->getEdge(neigh_edge_id);
2147 
2148  if (neigh_edge->hasIntersectionAtPosition(position, from_node))
2149  {
2150  unsigned int emb_id = neigh_edge->getEmbeddedNodeIndex(position, from_node);
2151  EFANode * old_emb = neigh_edge->getEmbeddedNode(emb_id);
2152 
2153  if (embedded_node && embedded_node != old_emb)
2154  EFAError(
2155  "attempting to add edge intersection when one already exists with different node.");
2156  if (local_embedded && local_embedded != old_emb)
2157  EFAError("attempting to assign contradictory pointer to local_embedded.");
2158 
2159  local_embedded = old_emb;
2160  }
2161  } // en_iter
2162 }
2163 
2164 void
2166  std::vector<double> & xi_2d,
2167  std::vector<double> & xi_3d) const
2168 {
2169  // given the coords of a point in a 2D face, translate it to 3D parametric coords
2170  xi_3d.resize(3, 0.0);
2171  if (_num_faces == 6)
2172  {
2173  if (face_id == 0)
2174  {
2175  xi_3d[0] = xi_2d[1];
2176  xi_3d[1] = xi_2d[0];
2177  xi_3d[2] = -1.0;
2178  }
2179  else if (face_id == 1)
2180  {
2181  xi_3d[0] = xi_2d[0];
2182  xi_3d[1] = -1.0;
2183  xi_3d[2] = xi_2d[1];
2184  }
2185  else if (face_id == 2)
2186  {
2187  xi_3d[0] = 1.0;
2188  xi_3d[1] = xi_2d[0];
2189  xi_3d[2] = xi_2d[1];
2190  }
2191  else if (face_id == 3)
2192  {
2193  xi_3d[0] = -xi_2d[0];
2194  xi_3d[1] = 1.0;
2195  xi_3d[2] = xi_2d[1];
2196  }
2197  else if (face_id == 4)
2198  {
2199  xi_3d[0] = -1.0;
2200  xi_3d[1] = -xi_2d[0];
2201  xi_3d[2] = xi_2d[1];
2202  }
2203  else if (face_id == 5)
2204  {
2205  xi_3d[0] = xi_2d[0];
2206  xi_3d[1] = xi_2d[1];
2207  xi_3d[2] = 1.0;
2208  }
2209  else
2210  EFAError("face_id out of bounds");
2211  }
2212  else if (_num_faces == 4)
2213  {
2214  if (face_id == 0)
2215  {
2216  xi_3d[0] = xi_2d[0];
2217  xi_3d[1] = xi_2d[1];
2218  xi_3d[2] = 0.0;
2219  }
2220  else if (face_id == 1)
2221  {
2222  xi_3d[0] = 0.0;
2223  xi_3d[1] = xi_2d[0];
2224  xi_3d[2] = xi_2d[1];
2225  }
2226  else if (face_id == 2)
2227  {
2228  xi_3d[0] = xi_2d[1];
2229  xi_3d[1] = 0.0;
2230  xi_3d[2] = xi_2d[0];
2231  }
2232  else if (face_id == 3)
2233  {
2234  xi_3d[0] = xi_2d[0];
2235  xi_3d[1] = xi_2d[2];
2236  xi_3d[2] = xi_2d[1];
2237  }
2238  else
2239  EFAError("face_id out of bounds");
2240  }
2241  else
2242  EFAError("unknown element for 3D");
2243 }
2244 
2245 std::vector<EFANode *>
2247 {
2248  std::set<EFANode *> e1nodes(_nodes.begin(),
2249  _nodes.begin() + _num_vertices); // only account for corner nodes
2250  std::set<EFANode *> e2nodes(other_elem->_nodes.begin(),
2251  other_elem->_nodes.begin() + _num_vertices);
2252  std::vector<EFANode *> common_nodes = Efa::getCommonElems(e1nodes, e2nodes);
2253  return common_nodes;
2254 }
EFAElement::switchNode
virtual void switchNode(EFANode *new_node, EFANode *old_node, bool descend_to_parent)=0
EFAFace::getEdge
EFAEdge * getEdge(unsigned int edge_id) const
Definition: EFAFace.C:260
EFAEdge::hasIntersectionAtPosition
bool hasIntersectionAtPosition(double position, EFANode *from_node) const
Definition: EFAEdge.C:211
EFAElement3D::updateFragmentNode
virtual void updateFragmentNode()
Definition: EFAElement3D.C:367
EFAElement3D::overlaysElement
bool overlaysElement(const EFAElement3D *other_elem) const
Definition: EFAElement3D.C:431
EFAElement::_parent
EFAElement * _parent
Definition: EFAElement.h:31
EFAElement::getNode
EFANode * getNode(unsigned int node_id) const
Definition: EFAElement.C:46
EFANode::category
N_CATEGORY category() const
Definition: EFANode.C:42
EFANode::id
unsigned int id() const
Definition: EFANode.C:36
EFAElement3D::getFaceID
unsigned int getFaceID(EFAFace *face) const
Definition: EFAElement3D.C:1519
EFAElement3D::fragmentFaceAlreadyCut
bool fragmentFaceAlreadyCut(unsigned int ElemFaceID) const
Definition: EFAElement3D.C:1974
EFAElement
Definition: EFAElement.h:19
EFAElement3D::_fragments
std::vector< EFAFragment3D * > _fragments
Definition: EFAElement3D.h:34
EFAElement3D::getFragmentFace
EFAFace * getFragmentFace(unsigned int frag_id, unsigned int face_id) const
Definition: EFAElement3D.C:1706
EFAElement::getGeneralNeighbor
EFAElement * getGeneralNeighbor(unsigned int index) const
Definition: EFAElement.C:236
EFAFragment3D::numFaces
unsigned int numFaces() const
Definition: EFAFragment3D.C:271
EFAFace::hasIntersection
bool hasIntersection() const
Definition: EFAFace.C:609
EFAElement3D::isFinalCut
virtual bool isFinalCut() const
Definition: EFAElement3D.C:838
EFANode.h
EFAFragment3D::getFace
EFAFace * getFace(unsigned int face_id) const
Definition: EFAFragment3D.C:277
EFAElement3D::removeEmbeddedNode
void removeEmbeddedNode(EFANode *emb_node, bool remove_for_neighbor)
Definition: EFAElement3D.C:1425
EFAFuncs.h
EFAFragment3D.h
EFAPoint::cross
EFAPoint cross(const EFAPoint &point)
Definition: EFAPoint.C:96
EFAElement3D::neighborSanityCheck
virtual void neighborSanityCheck() const
Definition: EFAElement3D.C:584
EFANode::N_CATEGORY_EMBEDDED
Definition: EFANode.h:21
EFAElement3D::getFragment
EFAFragment3D * getFragment(unsigned int frag_id) const
Definition: EFAElement3D.C:1372
EFAFace::getNode
EFANode * getNode(unsigned int node_id) const
Definition: EFAFace.C:99
EFAElement3D::getFragmentFaceID
bool getFragmentFaceID(unsigned int elem_face_id, unsigned int &frag_face_id) const
Definition: EFAElement3D.C:1739
EFAElement3D::getInteriorNode
EFAVolumeNode * getInteriorNode(unsigned int interior_node_id) const
Definition: EFAElement3D.C:1416
EFAElement3D::_face_edge_neighbors
std::vector< std::vector< std::vector< EFAElement3D * > > > _face_edge_neighbors
Definition: EFAElement3D.h:33
EFAElement3D::_num_faces
unsigned int _num_faces
Definition: EFAElement3D.h:29
EFAElement3D::numEdgeNeighbors
unsigned int numEdgeNeighbors(unsigned int face_id, unsigned int edge_id) const
Definition: EFAElement3D.C:1846
EFANode::N_CATEGORY_LOCAL_INDEX
Definition: EFANode.h:23
EFAFaceNode.h
EFAElement3D::getCommonFaceID
std::vector< unsigned int > getCommonFaceID(const EFAElement3D *other_elem) const
Definition: EFAElement3D.C:1538
EFAElement3D::mapParametricCoordinateFrom2DTo3D
void mapParametricCoordinateFrom2DTo3D(unsigned int face_id, std::vector< double > &xi_2d, std::vector< double > &xi_3d) const
Definition: EFAElement3D.C:2165
EFANode::N_CATEGORY_TEMP
Definition: EFANode.h:20
EFAElement3D::setFace
void setFace(unsigned int face_id, EFAFace *face)
Definition: EFAElement3D.C:1448
EFAElement3D::getNeighborIndex
virtual unsigned int getNeighborIndex(const EFAElement *neighbor_elem) const
Definition: EFAElement3D.C:458
EFAElement3D::_faces
std::vector< EFAFace * > _faces
Definition: EFAElement3D.h:30
EFAElement3D::~EFAElement3D
~EFAElement3D()
Definition: EFAElement3D.C:116
EFAElement3D::addFragFaceEdgeCut
void addFragFaceEdgeCut(unsigned int frag_face_id, unsigned int frag_edge_id, double position, std::map< unsigned int, EFANode * > &EmbeddedNodes, bool add_to_neighbor, bool add_to_adjacent)
Definition: EFAElement3D.C:2117
counter
static unsigned int counter
Definition: ContactPenetrationAuxAction.C:17
EFAElement3D::getCommonNodes
std::vector< EFANode * > getCommonNodes(const EFAElement3D *other_elem) const
Definition: EFAElement3D.C:2246
EFAElement3D::willCrackTipExtend
virtual bool willCrackTipExtend(std::vector< unsigned int > &split_neighbors) const
Definition: EFAElement3D.C:771
EFAEdge::equivalent
bool equivalent(const EFAEdge &other) const
Definition: EFAEdge.C:38
EFAElement::mergeNodes
void mergeNodes(EFANode *&childNode, EFANode *&childOfNeighborNode, EFAElement *childOfNeighborElem, std::map< unsigned int, EFANode * > &PermanentNodes, std::map< unsigned int, EFANode * > &TempNodes)
Definition: EFAElement.C:248
EFAElement::numNodes
unsigned int numNodes() const
Definition: EFAElement.C:34
EFAFragment3D::isFaceInterior
bool isFaceInterior(unsigned int face_id) const
Definition: EFAFragment3D.C:220
EFAElement::findGeneralNeighbors
void findGeneralNeighbors(std::map< EFANode *, std::set< EFAElement * >> &InverseConnectivity)
Definition: EFAElement.C:216
EFAElement3D::getFragmentFaceEdgeID
bool getFragmentFaceEdgeID(unsigned int ElemFaceID, unsigned int ElemFaceEdgeID, unsigned int &FragFaceID, unsigned int &FragFaceEdgeID) const
Definition: EFAElement3D.C:1762
EFAElement3D::checkNeighborFaceCut
void checkNeighborFaceCut(unsigned int face_id, unsigned int edge_id, double position, EFANode *from_node, EFANode *embedded_node, EFANode *&local_embedded)
Definition: EFAElement3D.C:2130
EFAElement3D::createChild
virtual void createChild(const std::set< EFAElement * > &CrackTipElements, std::map< unsigned int, EFAElement * > &Elements, std::map< unsigned int, EFAElement * > &newChildElements, std::vector< EFAElement * > &ChildElements, std::vector< EFAElement * > &ParentElements, std::map< unsigned int, EFANode * > &TempNodes)
Definition: EFAElement3D.C:977
EFAEdge::numEmbeddedNodes
unsigned int numEmbeddedNodes() const
Definition: EFAEdge.C:339
EFAElement3D::isPartial
virtual bool isPartial() const
Definition: EFAElement3D.C:275
EFAElement3D::connectNeighbors
virtual void connectNeighbors(std::map< unsigned int, EFANode * > &PermanentNodes, std::map< unsigned int, EFANode * > &TempNodes, std::map< EFANode *, std::set< EFAElement * >> &InverseConnectivityMap, bool merge_phantom_faces)
Definition: EFAElement3D.C:1141
EFAEdge::addIntersection
void addIntersection(double position, EFANode *embedded_node_tmp, EFANode *from_node)
Definition: EFAEdge.C:130
EFAElement::createLocalNodeFromGlobalNode
EFANode * createLocalNodeFromGlobalNode(const EFANode *global_node) const
Definition: EFAElement.C:70
EFAElement3D::removePhantomEmbeddedNode
virtual void removePhantomEmbeddedNode()
Definition: EFAElement3D.C:1106
EFAFragment::getCommonNodes
std::vector< EFANode * > getCommonNodes(EFAFragment *other) const
Definition: EFAFragment.C:20
EFAElement3D::getNumCuts
virtual unsigned int getNumCuts() const
Definition: EFAElement3D.C:828
EFAElement3D::setLocalCoordinates
void setLocalCoordinates()
Definition: EFAElement3D.C:153
EFAElement::_crack_tip_neighbors
std::vector< unsigned int > _crack_tip_neighbors
Definition: EFAElement.h:34
EFAElement3D::getTipFaceIDs
std::vector< unsigned int > getTipFaceIDs() const
Definition: EFAElement3D.C:1899
EFAElement3D::getFaceNodeParametricCoordinates
bool getFaceNodeParametricCoordinates(EFANode *node, std::vector< double > &xi_3d) const
Definition: EFAElement3D.C:1390
EFAElement::setNode
void setNode(unsigned int node_id, EFANode *node)
Definition: EFAElement.C:40
XFEMFuncs.h
EFAVolumeNode.h
EFAElement3D::numFaceNeighbors
unsigned int numFaceNeighbors(unsigned int face_id) const
Definition: EFAElement3D.C:1840
EFAElement3D::switchEmbeddedNode
virtual void switchEmbeddedNode(EFANode *new_node, EFANode *old_node)
Definition: EFAElement3D.C:356
EFAFace.h
EFAElement3D
Definition: EFAElement3D.h:20
EFAElement::_general_neighbors
std::vector< EFAElement * > _general_neighbors
Definition: EFAElement.h:36
EFAElement::_local_nodes
std::vector< EFANode * > _local_nodes
Definition: EFAElement.h:30
EFAElement::_children
std::vector< EFAElement * > _children
Definition: EFAElement.h:32
EFAElement3D::clearNeighbors
virtual void clearNeighbors()
Definition: EFAElement3D.C:496
EFAElement3D::getPhantomNodeOnFace
std::set< EFANode * > getPhantomNodeOnFace(unsigned int face_id) const
Definition: EFAElement3D.C:1715
EFAElement3D::_interior_nodes
std::vector< EFAVolumeNode * > _interior_nodes
Definition: EFAElement3D.h:31
EFAElement::_crack_tip_split_element
bool _crack_tip_split_element
Definition: EFAElement.h:33
EFAElement3D::getAdjacentFace
EFAFace * getAdjacentFace(unsigned int face_id, unsigned int edge_id) const
Definition: EFAElement3D.C:1700
Efa::numCommonElems
unsigned int numCommonElems(std::set< T > &v1, std::set< T > &v2)
Definition: EFAFuncs.h:49
EFAElement3D::getFaceNodes
std::set< EFANode * > getFaceNodes(unsigned int face_id) const
Definition: EFAElement3D.C:1381
EFAElement3D::switchNode
virtual void switchNode(EFANode *new_node, EFANode *old_node, bool descend_to_parent)
Definition: EFAElement3D.C:329
EFAElement3D::updateFragments
virtual void updateFragments(const std::set< EFAElement * > &CrackTipElements, std::map< unsigned int, EFANode * > &EmbeddedNodes)
Definition: EFAElement3D.C:858
EFAElement3D::getFace
EFAFace * getFace(unsigned int face_id) const
Definition: EFAElement3D.C:1513
EFAElement3D::isFacePhantom
bool isFacePhantom(unsigned int face_id) const
Definition: EFAElement3D.C:1814
EFAElement3D.h
EFAElement3D::addFaceEdgeCut
void addFaceEdgeCut(unsigned int face_id, unsigned int edge_id, double position, EFANode *embedded_node, std::map< unsigned int, EFANode * > &EmbeddedNodes, bool add_to_neighbor, bool add_to_adjacent)
Definition: EFAElement3D.C:1994
EFAElement3D::isPhysicalEdgeCut
bool isPhysicalEdgeCut(unsigned int ElemFaceID, unsigned int ElemFaceEdgeID, double position) const
Definition: EFAElement3D.C:1789
EFAVolumeNode
Definition: EFAVolumeNode.h:14
EFAElement3D::initCrackTip
virtual void initCrackTip(std::set< EFAElement * > &CrackTipElements)
Definition: EFAElement3D.C:619
EFAElement3D::getNeighborFaceEdgeID
unsigned int getNeighborFaceEdgeID(unsigned int face_id, unsigned int edg_id, EFAElement3D *neighbor_elem) const
Definition: EFAElement3D.C:1651
EFAFace::hasSameOrientation
bool hasSameOrientation(const EFAFace *other_face) const
Definition: EFAFace.C:658
EFAElement::id
unsigned int id() const
Definition: EFAElement.C:28
EFAElement3D::getFaceNeighbor
EFAElement3D * getFaceNeighbor(unsigned int face_id, unsigned int neighbor_id) const
Definition: EFAElement3D.C:1852
EFAElement3D::fragmentHasTipFaces
bool fragmentHasTipFaces() const
Definition: EFAElement3D.C:1872
EFAElement::isCrackTipSplit
bool isCrackTipSplit() const
Definition: EFAElement.C:136
EFAElement3D::numInteriorNodes
virtual unsigned int numInteriorNodes() const
Definition: EFAElement3D.C:425
EFAElement3D::numFaces
unsigned int numFaces() const
Definition: EFAElement3D.C:1442
EFAPoint
Definition: EFAPoint.h:12
Xfem::tol
static const double tol
Definition: XFEMFuncs.h:20
EFAEdge::getNode
EFANode * getNode(unsigned int index) const
Definition: EFAEdge.C:179
EFAElement3D::printElement
virtual void printElement(std::ostream &ostream)
Definition: EFAElement3D.C:1280
EFAError.h
EFAElement3D::_faces_adjacent_to_faces
std::vector< std::vector< EFAFace * > > _faces_adjacent_to_faces
Definition: EFAElement3D.h:35
EFAElement::numChildren
unsigned int numChildren() const
Definition: EFAElement.C:197
EFAElement3D::shouldDuplicateCrackTipSplitElement
virtual bool shouldDuplicateCrackTipSplitElement(const std::set< EFAElement * > &CrackTipElements)
Definition: EFAElement3D.C:681
EFAElement3D::getNeighborEdgeIndex
virtual void getNeighborEdgeIndex(const EFAElement3D *neighbor_elem, unsigned int face_id, unsigned int edge_id, unsigned int &neigh_face_id, unsigned int &neigh_edge_id) const
Definition: EFAElement3D.C:469
EFAElement3D::getMasterInfo
virtual void getMasterInfo(EFANode *node, std::vector< EFANode * > &master_nodes, std::vector< double > &master_weights) const
Definition: EFAElement3D.C:373
Efa::linearTetShape3D
double linearTetShape3D(unsigned int node_id, std::vector< double > &xi_3d)
Definition: EFAFuncs.C:48
EFAElement3D::EFAElement3D
EFAElement3D(unsigned int eid, unsigned int n_nodes, unsigned int n_faces)
Definition: EFAElement3D.C:24
Efa::getCommonElems
std::vector< T > getCommonElems(std::set< T > &v1, std::set< T > &v2)
Definition: EFAFuncs.h:69
EFAElement3D::shouldDuplicateForCrackTip
virtual bool shouldDuplicateForCrackTip(const std::set< EFAElement * > &CrackTipElements)
Definition: EFAElement3D.C:657
EFAElement::_id
unsigned int _id
Definition: EFAElement.h:27
EFAEdge::getEmbeddedNode
EFANode * getEmbeddedNode(unsigned int index) const
Definition: EFAEdge.C:330
Efa::linearHexShape3D
double linearHexShape3D(unsigned int node_id, std::vector< double > &xi_3d)
Definition: EFAFuncs.C:33
EFAEdge.h
EFANode::N_CATEGORY_PERMANENT
Definition: EFANode.h:19
EFAFace
Definition: EFAFace.h:19
EFAEdge::distanceFromNode1
double distanceFromNode1(EFANode *node) const
Definition: EFAEdge.C:248
EFAElement3D::createFaces
void createFaces()
Definition: EFAElement3D.C:1454
EFAElement3D::_num_interior_face_nodes
unsigned int _num_interior_face_nodes
Definition: EFAElement3D.h:37
EFAElement3D::getTipEmbeddedNodes
std::set< EFANode * > getTipEmbeddedNodes() const
Definition: EFAElement3D.C:1924
Xfem::normalizePoint
void normalizePoint(Point &p)
Definition: XFEMFuncs.C:621
EFAElement3D::shouldDuplicateForPhantomCorner
virtual bool shouldDuplicateForPhantomCorner()
Definition: EFAElement3D.C:732
EFAElement3D::fragmentSanityCheck
virtual void fragmentSanityCheck(unsigned int n_old_frag_faces, unsigned int n_old_frag_cuts) const
Definition: EFAElement3D.C:916
EFAElement3D::findFacesAdjacentToFaces
void findFacesAdjacentToFaces()
Definition: EFAElement3D.C:1681
EFAElement3D::numFragments
virtual unsigned int numFragments() const
Definition: EFAElement3D.C:269
EFAEdge
Definition: EFAEdge.h:16
EFAElement3D::_num_vertices
unsigned int _num_vertices
Definition: EFAElement3D.h:36
EFANode
Definition: EFANode.h:14
EFAEdge::hasIntersection
bool hasIntersection() const
Definition: EFAEdge.C:198
EFAElement3D::isCrackTipElement
virtual bool isCrackTipElement() const
Definition: EFAElement3D.C:822
EFANode::parent
EFANode * parent() const
Definition: EFANode.C:48
EFAElement3D::faceContainsTip
bool faceContainsTip(unsigned int face_id) const
Definition: EFAElement3D.C:1953
EFAElement3D::_face_neighbors
std::vector< std::vector< EFAElement3D * > > _face_neighbors
Definition: EFAElement3D.h:32
EFAEdge::containsEdge
bool containsEdge(const EFAEdge &other) const
Definition: EFAEdge.C:63
EFAElement3D::getNonPhysicalNodes
virtual void getNonPhysicalNodes(std::set< EFANode * > &non_physical_nodes) const
Definition: EFAElement3D.C:302
EFAFace::getInteriorFaceNode
EFANode * getInteriorFaceNode(unsigned int i) const
Definition: EFAFace.h:58
EFAElement::getChild
EFAElement * getChild(unsigned int child_id) const
Definition: EFAElement.C:182
EFAElement3D::restoreFragment
virtual void restoreFragment(const EFAElement *const from_elem)
Definition: EFAElement3D.C:941
EFAElement3D::getNeighborFaceNodeID
unsigned int getNeighborFaceNodeID(unsigned int face_id, unsigned int node_id, EFAElement3D *neighbor_elem) const
Definition: EFAElement3D.C:1590
EFAFace::numNodes
unsigned int numNodes() const
Definition: EFAFace.C:87
Efa::deleteFromMap
bool deleteFromMap(std::map< unsigned int, T * > &theMap, T *elemToDelete, bool delete_elem=true)
Definition: EFAFuncs.h:22
EFAElement::_nodes
std::vector< EFANode * > _nodes
Definition: EFAElement.h:29
EFAElement3D::getEdgeNeighbor
EFAElement3D * getEdgeNeighbor(unsigned int face_id, unsigned int edge_id, unsigned int neighbor_id) const
Definition: EFAElement3D.C:1861
EFAElement3D::_local_node_coor
std::vector< EFAPoint > _local_node_coor
Definition: EFAElement3D.h:38
EFAElement::numGeneralNeighbors
unsigned int numGeneralNeighbors() const
Definition: EFAElement.C:242
EFAElement::containsNode
bool containsNode(EFANode *node) const
Definition: EFAElement.C:52
EFAFragment3D
Definition: EFAFragment3D.h:20
EFAEdge::getEmbeddedNodeIndex
unsigned int getEmbeddedNodeIndex(EFANode *node) const
Definition: EFAEdge.C:281
Efa::getNewID
unsigned int getNewID(std::map< unsigned int, T * > &theMap)
Definition: EFAFuncs.h:38
EFAFace::numEdges
unsigned int numEdges() const
Definition: EFAFace.C:254
EFAElement::setParent
void setParent(EFAElement *parent)
Definition: EFAElement.C:191
EFAElement3D::getNeighborFaceInteriorNodeID
unsigned int getNeighborFaceInteriorNodeID(unsigned int face_id, unsigned int node_id, EFAElement3D *neighbor_elem) const
Definition: EFAElement3D.C:1620
EFAFace::equivalent
bool equivalent(const EFAFace *other_face) const
Definition: EFAFace.C:367
EFAElement3D::setupNeighbors
virtual void setupNeighbors(std::map< EFANode *, std::set< EFAElement * >> &InverseConnectivityMap)
Definition: EFAElement3D.C:508
EFAElement3D::getCommonEdgeID
bool getCommonEdgeID(const EFAElement3D *other_elem, std::vector< unsigned int > &face_id, std::vector< unsigned int > &edge_id) const
Definition: EFAElement3D.C:1556
EFAElement::_num_nodes
unsigned int _num_nodes
Definition: EFAElement.h:28
EFAFace::adjacentCommonEdge
unsigned int adjacentCommonEdge(const EFAFace *other_face) const
Definition: EFAFace.C:644