https://mooseframework.inl.gov
Loading...
Searching...
No Matches
EFAFragment2D.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
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 "EFAElement2D.h"
11
12#include "EFANode.h"
13#include "EFAEdge.h"
14#include "EFAFace.h"
15#include "EFAFragment2D.h"
16
17#include "EFAFaceNode.h"
18#include "EFAFuncs.h"
19#include "EFAError.h"
20
22 bool create_boundary_edges,
23 const EFAElement2D * from_host,
24 unsigned int frag_id)
25 : EFAFragment(), _host_elem(host)
26{
27 if (create_boundary_edges)
28 {
29 if (!from_host)
30 EFAError("EFAfragment2D constructor must have a from_host to copy from");
31 if (frag_id == std::numeric_limits<unsigned int>::max()) // copy the from_host itself
32 {
33 for (unsigned int i = 0; i < from_host->numEdges(); ++i)
34 _boundary_edges.push_back(new EFAEdge(*from_host->getEdge(i)));
35 }
36 else
37 {
38 if (frag_id > from_host->numFragments() - 1)
39 EFAError("In EFAfragment2D constructor fragment_copy_index out of bounds");
40 for (unsigned int i = 0; i < from_host->getFragment(frag_id)->numEdges(); ++i)
41 _boundary_edges.push_back(new EFAEdge(*from_host->getFragmentEdge(frag_id, i)));
42 }
43 }
44}
45
47 : EFAFragment(), _host_elem(host)
48{
49 for (unsigned int i = 0; i < from_face->numEdges(); ++i)
50 _boundary_edges.push_back(new EFAEdge(*from_face->getEdge(i)));
51}
52
54{
55 for (unsigned int i = 0; i < _boundary_edges.size(); ++i)
56 {
57 if (_boundary_edges[i])
58 {
59 delete _boundary_edges[i];
60 _boundary_edges[i] = nullptr;
61 }
62 }
63}
64
65void
67{
68 for (unsigned int i = 0; i < _boundary_edges.size(); ++i)
69 _boundary_edges[i]->switchNode(new_node, old_node);
70}
71
72bool
74{
75 bool contains = false;
76 for (unsigned int i = 0; i < _boundary_edges.size(); ++i)
77 {
78 if (_boundary_edges[i]->containsNode(node))
79 {
80 contains = true;
81 break;
82 }
83 }
84 return contains;
85}
86
87unsigned int
89{
90 unsigned int num_cut_edges = 0;
91 for (unsigned int i = 0; i < _boundary_edges.size(); ++i)
92 {
93 if (_boundary_edges[i]->hasIntersection())
94 num_cut_edges += _boundary_edges[i]->numEmbeddedNodes();
95 }
96 return num_cut_edges;
97}
98
99unsigned int
101{
102 unsigned int num_cut_nodes = 0;
103 for (unsigned int i = 0; i < _boundary_edges.size(); ++i)
104 if (_boundary_edges[i]->getNode(0)->category() == EFANode::N_CATEGORY_EMBEDDED_PERMANENT)
105 num_cut_nodes++;
106 return num_cut_nodes;
107}
108
109std::set<EFANode *>
111{
112 std::set<EFANode *> nodes;
113 for (unsigned int i = 0; i < _boundary_edges.size(); ++i)
114 {
115 nodes.insert(_boundary_edges[i]->getNode(0));
116 nodes.insert(_boundary_edges[i]->getNode(1));
117 }
118 return nodes;
119}
120
121bool
123{
124 bool is_connected = false;
125 EFAFragment2D * other_frag2d = dynamic_cast<EFAFragment2D *>(other_fragment);
126 if (!other_frag2d)
127 EFAError("in isConnected other_fragment is not of type EFAfragement2D");
128
129 for (unsigned int i = 0; i < _boundary_edges.size(); ++i)
130 {
131 for (unsigned int j = 0; j < other_frag2d->numEdges(); ++j)
132 {
133 if (_boundary_edges[i]->equivalent(*other_frag2d->getEdge(j)))
134 {
135 is_connected = true;
136 break;
137 }
138 }
139 if (is_connected)
140 break;
141 } // i
142 return is_connected;
143}
144
145void
146EFAFragment2D::removeInvalidEmbeddedNodes(std::map<unsigned int, EFANode *> & EmbeddedNodes)
147{
148 // if a fragment only has 1 intersection which is in an interior edge
149 // remove this embedded node (MUST DO THIS AFTER combine_tip_edges())
150 if (getNumCuts() == 1)
151 {
152 for (unsigned int i = 0; i < _boundary_edges.size(); ++i)
153 {
154 if (isEdgeInterior(i) && _boundary_edges[i]->hasIntersection())
155 {
156 if (_host_elem->numInteriorNodes() != 1)
157 EFAError("host element must have 1 interior node at this point");
158 Efa::deleteFromMap(EmbeddedNodes, _boundary_edges[i]->getEmbeddedNode(0));
159 _boundary_edges[i]->removeEmbeddedNodes();
161 break;
162 }
163 } // i
164 }
165}
166
167void
169{
170 // combine the tip edges in a crack tip fragment
171 // N.B. the host elem can only have one elem_tip_edge, otherwise it should have already been
172 // completely split
173 if (!_host_elem)
174 EFAError("In combine_tip_edges() the frag must have host_elem");
175
176 bool has_tip_edges = false;
177 unsigned int elem_tip_edge_id = std::numeric_limits<unsigned int>::max();
178 std::vector<unsigned int> frag_tip_edge_id;
179 for (unsigned int i = 0; i < _host_elem->numEdges(); ++i)
180 {
181 frag_tip_edge_id.clear();
183 {
184 for (unsigned int j = 0; j < _boundary_edges.size(); ++j)
185 {
187 frag_tip_edge_id.push_back(j);
188 } // j
189 if (frag_tip_edge_id.size() == 2) // combine the two frag edges on this elem edge
190 {
191 has_tip_edges = true;
192 elem_tip_edge_id = i;
193 break;
194 }
195 }
196 } // i
197 if (has_tip_edges)
198 {
199 // frag_tip_edge_id[0] must precede frag_tip_edge_id[1]
200 unsigned int edge0_next(frag_tip_edge_id[0] < (numEdges() - 1) ? frag_tip_edge_id[0] + 1 : 0);
201 if (edge0_next != frag_tip_edge_id[1])
202 EFAError("frag_tip_edge_id[1] must be the next edge of frag_tip_edge_id[0]");
203
204 // get the two end nodes of the new edge
205 EFANode * node1 = _boundary_edges[frag_tip_edge_id[0]]->getNode(0);
206 EFANode * emb_node = _boundary_edges[frag_tip_edge_id[0]]->getNode(1);
207 EFANode * node2 = _boundary_edges[frag_tip_edge_id[1]]->getNode(1);
208 if (emb_node != _boundary_edges[frag_tip_edge_id[1]]->getNode(0))
209 EFAError("fragment edges are not correctly set up");
210
211 // get the new edge with one intersection
212 EFAEdge * elem_edge = _host_elem->getEdge(elem_tip_edge_id);
213 double xi_node1 = elem_edge->distanceFromNode1(node1);
214 double xi_node2 = elem_edge->distanceFromNode1(node2);
215 double xi_emb = elem_edge->distanceFromNode1(emb_node);
216 double position = (xi_emb - xi_node1) / (xi_node2 - xi_node1);
217 EFAEdge * full_edge = new EFAEdge(node1, node2);
218 full_edge->addIntersection(position, emb_node, node1);
219
220 // combine the two original fragment edges
221 delete _boundary_edges[frag_tip_edge_id[0]];
222 delete _boundary_edges[frag_tip_edge_id[1]];
223 _boundary_edges[frag_tip_edge_id[0]] = full_edge;
224 _boundary_edges.erase(_boundary_edges.begin() + frag_tip_edge_id[1]);
225 }
226}
227
228/*
229std::vector<EFAnode*>
230EFAfragment::commonNodesWithEdge(EFAEdge & other_edge)
231{
232 std::vector<EFAnode*> common_nodes;
233 for (unsigned int i = 0; i < 2; ++i)
234 {
235 EFAnode* edge_node = other_edge.node_ptr(i);
236 if (containsNode(edge_node))
237 common_nodes.push_back(edge_node);
238 }
239 return common_nodes;
240}
241*/
242
243bool
244EFAFragment2D::isEdgeInterior(unsigned int edge_id) const
245{
246 if (!_host_elem)
247 EFAError("in isEdgeInterior fragment must have host elem");
248
249 bool edge_in_elem_edge = false;
250
251 for (unsigned int i = 0; i < _host_elem->numEdges(); ++i)
252 {
254 {
255 edge_in_elem_edge = true;
256 break;
257 }
258 }
259 if (!edge_in_elem_edge)
260 return true; // yes, is interior
261 else
262 return false;
263}
264
265std::vector<unsigned int>
267{
268 std::vector<unsigned int> interior_edge_id;
269 for (unsigned int i = 0; i < _boundary_edges.size(); ++i)
270 {
271 if (isEdgeInterior(i))
272 interior_edge_id.push_back(i);
273 }
274 return interior_edge_id;
275}
276
277bool
278EFAFragment2D::isSecondaryInteriorEdge(unsigned int edge_id) const
279{
280 bool is_second_cut = false;
281 if (!_host_elem)
282 EFAError("in isSecondaryInteriorEdge fragment must have host elem");
283
284 for (unsigned int i = 0; i < _host_elem->numInteriorNodes(); ++i)
285 {
287 {
288 is_second_cut = true;
289 break;
290 }
291 }
292 return is_second_cut;
293}
294
295unsigned int
297{
298 return _boundary_edges.size();
299}
300
301EFAEdge *
302EFAFragment2D::getEdge(unsigned int edge_id) const
303{
304 if (edge_id > _boundary_edges.size() - 1)
305 EFAError("in EFAfragment2D::get_edge, index out of bounds");
306 return _boundary_edges[edge_id];
307}
308
309void
311{
312 _boundary_edges.push_back(new_edge);
313}
314
315std::set<EFANode *>
316EFAFragment2D::getEdgeNodes(unsigned int edge_id) const
317{
318 std::set<EFANode *> edge_nodes;
319 edge_nodes.insert(_boundary_edges[edge_id]->getNode(0));
320 edge_nodes.insert(_boundary_edges[edge_id]->getNode(1));
321 return edge_nodes;
322}
323
326{
327 return _host_elem;
328}
329
330std::vector<EFAFragment2D *>
332{
333 // This method will split one existing fragment into one or two
334 // new fragments and return them.
335 // N.B. each boundary each can only have 1 cut at most
336 std::vector<EFAFragment2D *> new_fragments;
337 std::vector<std::vector<EFANode *>> fragment_nodes(
338 2); // vectors of EFA nodes in the two fragments
339 unsigned int frag_number = 0; // Index of the current fragment that we are assmbling nodes into
340 unsigned int edge_cut_count = 0;
341 unsigned int node_cut_count = 0;
342 for (unsigned int iedge = 0; iedge < _boundary_edges.size(); ++iedge)
343 {
344 fragment_nodes[frag_number].push_back(_boundary_edges[iedge]->getNode(0));
345
346 if (_boundary_edges[iedge]->getNode(0)->category() ==
347 EFANode::N_CATEGORY_EMBEDDED_PERMANENT) // if current node has been cut change fragment
348 {
349 ++node_cut_count;
350 frag_number = 1 - frag_number; // Toggle between 0 and 1
351 fragment_nodes[frag_number].push_back(_boundary_edges[iedge]->getNode(0));
352 }
353
354 if (_boundary_edges[iedge]->numEmbeddedNodes() > 1)
355 EFAError("A fragment boundary edge can't have more than 1 cuts");
356 if (_boundary_edges[iedge]->hasIntersection()) // if current edge is cut add cut intersection //
357 // node to both fragments and and change fragment
358 {
359 fragment_nodes[frag_number].push_back(_boundary_edges[iedge]->getEmbeddedNode(0));
360 ++edge_cut_count;
361 frag_number = 1 - frag_number; // Toggle between 0 and 1
362 fragment_nodes[frag_number].push_back(_boundary_edges[iedge]->getEmbeddedNode(0));
363 }
364 }
365
366 if ((edge_cut_count + node_cut_count) > 1) // any two cuts case
367 {
368 for (unsigned int frag_idx = 0; frag_idx < 2; ++frag_idx) // Create 2 fragments
369 {
370 auto & this_frag_nodes = fragment_nodes[frag_idx];
371 // check to make sure an edge wasn't cut
372 if (this_frag_nodes.size() >= 3)
373 {
374 EFAFragment2D * new_frag = new EFAFragment2D(_host_elem, false, nullptr);
375 for (unsigned int inode = 0; inode < this_frag_nodes.size() - 1; inode++)
376 new_frag->addEdge(new EFAEdge(this_frag_nodes[inode], this_frag_nodes[inode + 1]));
377
378 new_frag->addEdge(
379 new EFAEdge(this_frag_nodes[this_frag_nodes.size() - 1], this_frag_nodes[0]));
380
381 new_fragments.push_back(new_frag);
382 }
383 }
384 }
385 else if (edge_cut_count == 1) // single edge cut case
386 {
387 EFAFragment2D * new_frag = new EFAFragment2D(_host_elem, false, nullptr);
388 for (unsigned int inode = 0; inode < fragment_nodes[0].size() - 1;
389 inode++) // assemble fragment part 1
390 new_frag->addEdge(new EFAEdge(fragment_nodes[0][inode], fragment_nodes[0][inode + 1]));
391
392 for (unsigned int inode = 0; inode < fragment_nodes[1].size() - 1;
393 inode++) // assemble fragment part 2
394 new_frag->addEdge(new EFAEdge(fragment_nodes[1][inode], fragment_nodes[1][inode + 1]));
395
396 new_frag->addEdge(
397 new EFAEdge(fragment_nodes[1][fragment_nodes[1].size() - 1], fragment_nodes[0][0]));
398
399 new_fragments.push_back(new_frag);
400 }
401 else if (node_cut_count == 1) // single node cut case
402 {
403 EFAFragment2D * new_frag = new EFAFragment2D(_host_elem, false, nullptr);
404 for (unsigned int iedge = 0; iedge < _boundary_edges.size(); ++iedge)
405 {
406 EFANode * first_node_on_edge = _boundary_edges[iedge]->getNode(0);
407 EFANode * second_node_on_edge = _boundary_edges[iedge]->getNode(1);
408 new_frag->addEdge(new EFAEdge(first_node_on_edge, second_node_on_edge));
409 }
410
411 new_fragments.push_back(new_frag);
412 }
413
414 return new_fragments;
415}
double distanceFromNode1(EFANode *node) const
Definition EFAEdge.C:250
void addIntersection(double position, EFANode *embedded_node_tmp, EFANode *from_node)
Definition EFAEdge.C:132
bool containsEdge(const EFAEdge &other) const
Definition EFAEdge.C:65
bool hasIntersection() const
Definition EFAEdge.C:200
virtual unsigned int numFragments() const
EFAFragment2D * getFragment(unsigned int frag_id) const
virtual unsigned int numInteriorNodes() const
EFAFaceNode * getInteriorNode(unsigned int interior_node_id) const
EFAEdge * getEdge(unsigned int edge_id) const
unsigned int numEdges() const
EFAEdge * getFragmentEdge(unsigned int frag_id, unsigned int edge_id) const
void deleteInteriorNodes()
EFANode * getNode()
Definition EFAFaceNode.C:25
unsigned int numEdges() const
Definition EFAFace.h:49
EFAEdge * getEdge(unsigned int edge_id) const
Definition EFAFace.h:50
bool isEdgeInterior(unsigned int edge_id) const
EFAEdge * getEdge(unsigned int edge_id) const
EFAElement2D * _host_elem
virtual void switchNode(EFANode *new_node, EFANode *old_node)
void addEdge(EFAEdge *new_edge)
virtual unsigned int getNumCutNodes() const
virtual std::set< EFANode * > getAllNodes() const
EFAFragment2D(EFAElement2D *host, bool create_boundary_edges, const EFAElement2D *from_host, unsigned int frag_id=std::numeric_limits< unsigned int >::max())
std::vector< unsigned int > getInteriorEdgeID() const
virtual unsigned int getNumCuts() const
unsigned int numEdges() const
std::set< EFANode * > getEdgeNodes(unsigned int edge_id) const
void combineTipEdges()
std::vector< EFAFragment2D * > split()
std::vector< EFAEdge * > _boundary_edges
bool isSecondaryInteriorEdge(unsigned int edge_id) const
virtual bool isConnected(EFAFragment *other_fragment) const
EFAElement2D * getHostElement() const
virtual void removeInvalidEmbeddedNodes(std::map< unsigned int, EFANode * > &EmbeddedNodes)
virtual bool containsNode(EFANode *node) const
@ N_CATEGORY_EMBEDDED_PERMANENT
Definition EFANode.h:22
bool deleteFromMap(std::map< unsigned int, T * > &theMap, T *elemToDelete, bool delete_elem=true)
Definition EFAFuncs.h:22