Line data Source code
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 : 21 281525 : EFAFragment2D::EFAFragment2D(EFAElement2D * host, 22 : bool create_boundary_edges, 23 : const EFAElement2D * from_host, 24 281525 : unsigned int frag_id) 25 281525 : : EFAFragment(), _host_elem(host) 26 : { 27 281525 : if (create_boundary_edges) 28 : { 29 261359 : if (!from_host) 30 0 : EFAError("EFAfragment2D constructor must have a from_host to copy from"); 31 261359 : if (frag_id == std::numeric_limits<unsigned int>::max()) // copy the from_host itself 32 : { 33 1020837 : for (unsigned int i = 0; i < from_host->numEdges(); ++i) 34 814444 : _boundary_edges.push_back(new EFAEdge(*from_host->getEdge(i))); 35 : } 36 : else 37 : { 38 54966 : if (frag_id > from_host->numFragments() - 1) 39 0 : EFAError("In EFAfragment2D constructor fragment_copy_index out of bounds"); 40 274266 : for (unsigned int i = 0; i < from_host->getFragment(frag_id)->numEdges(); ++i) 41 219300 : _boundary_edges.push_back(new EFAEdge(*from_host->getFragmentEdge(frag_id, i))); 42 : } 43 : } 44 281525 : } 45 : 46 5733 : EFAFragment2D::EFAFragment2D(EFAElement2D * host, const EFAFace * from_face) 47 5733 : : EFAFragment(), _host_elem(host) 48 : { 49 5733 : for (unsigned int i = 0; i < from_face->numEdges(); ++i) 50 20532 : _boundary_edges.push_back(new EFAEdge(*from_face->getEdge(i))); 51 5733 : } 52 : 53 574516 : EFAFragment2D::~EFAFragment2D() 54 : { 55 1420297 : for (unsigned int i = 0; i < _boundary_edges.size(); ++i) 56 : { 57 1133039 : if (_boundary_edges[i]) 58 : { 59 1133039 : delete _boundary_edges[i]; 60 1133039 : _boundary_edges[i] = nullptr; 61 : } 62 : } 63 574516 : } 64 : 65 : void 66 325973 : EFAFragment2D::switchNode(EFANode * new_node, EFANode * old_node) 67 : { 68 1608874 : for (unsigned int i = 0; i < _boundary_edges.size(); ++i) 69 1282901 : _boundary_edges[i]->switchNode(new_node, old_node); 70 325973 : } 71 : 72 : bool 73 3512754 : EFAFragment2D::containsNode(EFANode * node) const 74 : { 75 : bool contains = false; 76 9573286 : for (unsigned int i = 0; i < _boundary_edges.size(); ++i) 77 : { 78 8237249 : if (_boundary_edges[i]->containsNode(node)) 79 : { 80 : contains = true; 81 : break; 82 : } 83 : } 84 3512754 : return contains; 85 : } 86 : 87 : unsigned int 88 247299 : EFAFragment2D::getNumCuts() const 89 : { 90 : unsigned int num_cut_edges = 0; 91 1221987 : for (unsigned int i = 0; i < _boundary_edges.size(); ++i) 92 : { 93 974688 : if (_boundary_edges[i]->hasIntersection()) 94 10891 : num_cut_edges += _boundary_edges[i]->numEmbeddedNodes(); 95 : } 96 247299 : return num_cut_edges; 97 : } 98 : 99 : unsigned int 100 226846 : EFAFragment2D::getNumCutNodes() const 101 : { 102 : unsigned int num_cut_nodes = 0; 103 1121412 : for (unsigned int i = 0; i < _boundary_edges.size(); ++i) 104 894566 : if (_boundary_edges[i]->getNode(0)->category() == EFANode::N_CATEGORY_EMBEDDED_PERMANENT) 105 200 : num_cut_nodes++; 106 226846 : return num_cut_nodes; 107 : } 108 : 109 : std::set<EFANode *> 110 14164 : EFAFragment2D::getAllNodes() const 111 : { 112 : std::set<EFANode *> nodes; 113 70596 : for (unsigned int i = 0; i < _boundary_edges.size(); ++i) 114 : { 115 56432 : nodes.insert(_boundary_edges[i]->getNode(0)); 116 56432 : nodes.insert(_boundary_edges[i]->getNode(1)); 117 : } 118 14164 : return nodes; 119 : } 120 : 121 : bool 122 89141 : EFAFragment2D::isConnected(EFAFragment * other_fragment) const 123 : { 124 : bool is_connected = false; 125 89141 : EFAFragment2D * other_frag2d = dynamic_cast<EFAFragment2D *>(other_fragment); 126 89141 : if (!other_frag2d) 127 0 : EFAError("in isConnected other_fragment is not of type EFAfragement2D"); 128 : 129 245408 : for (unsigned int i = 0; i < _boundary_edges.size(); ++i) 130 : { 131 956449 : for (unsigned int j = 0; j < other_frag2d->numEdges(); ++j) 132 : { 133 800182 : if (_boundary_edges[i]->equivalent(*other_frag2d->getEdge(j))) 134 : { 135 : is_connected = true; 136 : break; 137 : } 138 : } 139 232490 : if (is_connected) 140 : break; 141 : } // i 142 89141 : return is_connected; 143 : } 144 : 145 : void 146 20453 : EFAFragment2D::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 20453 : if (getNumCuts() == 1) 151 : { 152 4133 : for (unsigned int i = 0; i < _boundary_edges.size(); ++i) 153 : { 154 3332 : if (isEdgeInterior(i) && _boundary_edges[i]->hasIntersection()) 155 : { 156 72 : if (_host_elem->numInteriorNodes() != 1) 157 0 : EFAError("host element must have 1 interior node at this point"); 158 72 : Efa::deleteFromMap(EmbeddedNodes, _boundary_edges[i]->getEmbeddedNode(0)); 159 72 : _boundary_edges[i]->removeEmbeddedNodes(); 160 72 : _host_elem->deleteInteriorNodes(); 161 72 : break; 162 : } 163 : } // i 164 : } 165 20453 : } 166 : 167 : void 168 1181 : EFAFragment2D::combineTipEdges() 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 1181 : if (!_host_elem) 174 0 : 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 3605 : for (unsigned int i = 0; i < _host_elem->numEdges(); ++i) 180 : { 181 3605 : frag_tip_edge_id.clear(); 182 3605 : if (_host_elem->getEdge(i)->hasIntersection()) 183 : { 184 8458 : for (unsigned int j = 0; j < _boundary_edges.size(); ++j) 185 : { 186 7043 : if (_host_elem->getEdge(i)->containsEdge(*_boundary_edges[j])) 187 2596 : frag_tip_edge_id.push_back(j); 188 : } // j 189 1415 : 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 1181 : if (has_tip_edges) 198 : { 199 : // frag_tip_edge_id[0] must precede frag_tip_edge_id[1] 200 1181 : unsigned int edge0_next(frag_tip_edge_id[0] < (numEdges() - 1) ? frag_tip_edge_id[0] + 1 : 0); 201 1181 : if (edge0_next != frag_tip_edge_id[1]) 202 0 : 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 1181 : EFANode * node1 = _boundary_edges[frag_tip_edge_id[0]]->getNode(0); 206 1181 : EFANode * emb_node = _boundary_edges[frag_tip_edge_id[0]]->getNode(1); 207 1181 : EFANode * node2 = _boundary_edges[frag_tip_edge_id[1]]->getNode(1); 208 1181 : if (emb_node != _boundary_edges[frag_tip_edge_id[1]]->getNode(0)) 209 0 : EFAError("fragment edges are not correctly set up"); 210 : 211 : // get the new edge with one intersection 212 1181 : EFAEdge * elem_edge = _host_elem->getEdge(elem_tip_edge_id); 213 1181 : double xi_node1 = elem_edge->distanceFromNode1(node1); 214 1181 : double xi_node2 = elem_edge->distanceFromNode1(node2); 215 1181 : double xi_emb = elem_edge->distanceFromNode1(emb_node); 216 1181 : double position = (xi_emb - xi_node1) / (xi_node2 - xi_node1); 217 1181 : EFAEdge * full_edge = new EFAEdge(node1, node2); 218 1181 : full_edge->addIntersection(position, emb_node, node1); 219 : 220 : // combine the two original fragment edges 221 1181 : delete _boundary_edges[frag_tip_edge_id[0]]; 222 1181 : delete _boundary_edges[frag_tip_edge_id[1]]; 223 1181 : _boundary_edges[frag_tip_edge_id[0]] = full_edge; 224 1181 : _boundary_edges.erase(_boundary_edges.begin() + frag_tip_edge_id[1]); 225 : } 226 1181 : } 227 : 228 : /* 229 : std::vector<EFAnode*> 230 : EFAfragment::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 : 243 : bool 244 9577984 : EFAFragment2D::isEdgeInterior(unsigned int edge_id) const 245 : { 246 9577984 : if (!_host_elem) 247 0 : EFAError("in isEdgeInterior fragment must have host elem"); 248 : 249 : bool edge_in_elem_edge = false; 250 : 251 30148316 : for (unsigned int i = 0; i < _host_elem->numEdges(); ++i) 252 : { 253 27715072 : if (_host_elem->getEdge(i)->containsEdge(*_boundary_edges[edge_id])) 254 : { 255 : edge_in_elem_edge = true; 256 : break; 257 : } 258 : } 259 9577984 : if (!edge_in_elem_edge) 260 : return true; // yes, is interior 261 : else 262 7144740 : return false; 263 : } 264 : 265 : std::vector<unsigned int> 266 0 : EFAFragment2D::getInteriorEdgeID() const 267 : { 268 : std::vector<unsigned int> interior_edge_id; 269 0 : for (unsigned int i = 0; i < _boundary_edges.size(); ++i) 270 : { 271 0 : if (isEdgeInterior(i)) 272 0 : interior_edge_id.push_back(i); 273 : } 274 0 : return interior_edge_id; 275 0 : } 276 : 277 : bool 278 35386 : EFAFragment2D::isSecondaryInteriorEdge(unsigned int edge_id) const 279 : { 280 : bool is_second_cut = false; 281 35386 : if (!_host_elem) 282 0 : EFAError("in isSecondaryInteriorEdge fragment must have host elem"); 283 : 284 35386 : for (unsigned int i = 0; i < _host_elem->numInteriorNodes(); ++i) 285 : { 286 0 : if (_boundary_edges[edge_id]->containsNode(_host_elem->getInteriorNode(i)->getNode())) 287 : { 288 : is_second_cut = true; 289 : break; 290 : } 291 : } 292 35386 : return is_second_cut; 293 : } 294 : 295 : unsigned int 296 14982198 : EFAFragment2D::numEdges() const 297 : { 298 14982198 : return _boundary_edges.size(); 299 : } 300 : 301 : EFAEdge * 302 7312519 : EFAFragment2D::getEdge(unsigned int edge_id) const 303 : { 304 7312519 : if (edge_id > _boundary_edges.size() - 1) 305 0 : EFAError("in EFAfragment2D::get_edge, index out of bounds"); 306 7312519 : return _boundary_edges[edge_id]; 307 : } 308 : 309 : void 310 79944 : EFAFragment2D::addEdge(EFAEdge * new_edge) 311 : { 312 79944 : _boundary_edges.push_back(new_edge); 313 79944 : } 314 : 315 : std::set<EFANode *> 316 0 : EFAFragment2D::getEdgeNodes(unsigned int edge_id) const 317 : { 318 : std::set<EFANode *> edge_nodes; 319 0 : edge_nodes.insert(_boundary_edges[edge_id]->getNode(0)); 320 0 : edge_nodes.insert(_boundary_edges[edge_id]->getNode(1)); 321 0 : return edge_nodes; 322 : } 323 : 324 : EFAElement2D * 325 0 : EFAFragment2D::getHostElement() const 326 : { 327 0 : return _host_elem; 328 : } 329 : 330 : std::vector<EFAFragment2D *> 331 11163 : EFAFragment2D::split() 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 11163 : 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 52891 : for (unsigned int iedge = 0; iedge < _boundary_edges.size(); ++iedge) 343 : { 344 41728 : fragment_nodes[frag_number].push_back(_boundary_edges[iedge]->getNode(0)); 345 : 346 41728 : if (_boundary_edges[iedge]->getNode(0)->category() == 347 : EFANode::N_CATEGORY_EMBEDDED_PERMANENT) // if current node has been cut change fragment 348 : { 349 200 : ++node_cut_count; 350 200 : frag_number = 1 - frag_number; // Toggle between 0 and 1 351 200 : fragment_nodes[frag_number].push_back(_boundary_edges[iedge]->getNode(0)); 352 : } 353 : 354 41728 : if (_boundary_edges[iedge]->numEmbeddedNodes() > 1) 355 0 : EFAError("A fragment boundary edge can't have more than 1 cuts"); 356 41728 : if (_boundary_edges[iedge]->hasIntersection()) // if current edge is cut add cut intersection // 357 : // node to both fragments and and change fragment 358 : { 359 19755 : fragment_nodes[frag_number].push_back(_boundary_edges[iedge]->getEmbeddedNode(0)); 360 19755 : ++edge_cut_count; 361 19755 : frag_number = 1 - frag_number; // Toggle between 0 and 1 362 19755 : fragment_nodes[frag_number].push_back(_boundary_edges[iedge]->getEmbeddedNode(0)); 363 : } 364 : } 365 : 366 11163 : if ((edge_cut_count + node_cut_count) > 1) // any two cuts case 367 : { 368 26376 : for (unsigned int frag_idx = 0; frag_idx < 2; ++frag_idx) // Create 2 fragments 369 : { 370 17584 : auto & this_frag_nodes = fragment_nodes[frag_idx]; 371 : // check to make sure an edge wasn't cut 372 17584 : if (this_frag_nodes.size() >= 3) 373 : { 374 17528 : EFAFragment2D * new_frag = new EFAFragment2D(_host_elem, false, nullptr); 375 67468 : for (unsigned int inode = 0; inode < this_frag_nodes.size() - 1; inode++) 376 49940 : new_frag->addEdge(new EFAEdge(this_frag_nodes[inode], this_frag_nodes[inode + 1])); 377 : 378 17528 : new_frag->addEdge( 379 17528 : new EFAEdge(this_frag_nodes[this_frag_nodes.size() - 1], this_frag_nodes[0])); 380 : 381 17528 : new_fragments.push_back(new_frag); 382 : } 383 : } 384 : } 385 2371 : else if (edge_cut_count == 1) // single edge cut case 386 : { 387 2323 : EFAFragment2D * new_frag = new EFAFragment2D(_host_elem, false, nullptr); 388 8677 : for (unsigned int inode = 0; inode < fragment_nodes[0].size() - 1; 389 : inode++) // assemble fragment part 1 390 6354 : new_frag->addEdge(new EFAEdge(fragment_nodes[0][inode], fragment_nodes[0][inode + 1])); 391 : 392 4941 : for (unsigned int inode = 0; inode < fragment_nodes[1].size() - 1; 393 : inode++) // assemble fragment part 2 394 2618 : new_frag->addEdge(new EFAEdge(fragment_nodes[1][inode], fragment_nodes[1][inode + 1])); 395 : 396 2323 : new_frag->addEdge( 397 2323 : new EFAEdge(fragment_nodes[1][fragment_nodes[1].size() - 1], fragment_nodes[0][0])); 398 : 399 2323 : new_fragments.push_back(new_frag); 400 : } 401 48 : else if (node_cut_count == 1) // single node cut case 402 : { 403 48 : EFAFragment2D * new_frag = new EFAFragment2D(_host_elem, false, nullptr); 404 240 : for (unsigned int iedge = 0; iedge < _boundary_edges.size(); ++iedge) 405 : { 406 192 : EFANode * first_node_on_edge = _boundary_edges[iedge]->getNode(0); 407 192 : EFANode * second_node_on_edge = _boundary_edges[iedge]->getNode(1); 408 192 : new_frag->addEdge(new EFAEdge(first_node_on_edge, second_node_on_edge)); 409 : } 410 : 411 48 : new_fragments.push_back(new_frag); 412 : } 413 : 414 11163 : return new_fragments; 415 11163 : }