1295 if constexpr (ELEMENT_DIM == 2 && SPACE_DIM == 2)
1298 std::set<unsigned> nodeA_elem_indices = pNodeA->rGetContainingElementIndices();
1299 std::set<unsigned> nodeB_elem_indices = pNodeB->rGetContainingElementIndices();
1302 std::set<unsigned> all_indices, temp_union_set;
1303 std::set_union(nodeA_elem_indices.begin(), nodeA_elem_indices.end(),
1304 nodeB_elem_indices.begin(), nodeB_elem_indices.end(),
1305 std::inserter(temp_union_set, temp_union_set.begin()));
1306 all_indices.swap(temp_union_set);
1309 if ((nodeA_elem_indices.size() > 3) || (nodeB_elem_indices.size() > 3))
1326 this->HandleHighOrderJunctions(pNodeA, pNodeB);
1330 switch (all_indices.size())
1342 assert(pNodeA->IsBoundaryNode());
1343 assert(pNodeB->IsBoundaryNode());
1344 PerformNodeMerge(pNodeA, pNodeB);
1345 RemoveDeletedNodes();
1350 if (nodeA_elem_indices.size() == 2 && nodeB_elem_indices.size() == 2)
1352 if (pNodeA->IsBoundaryNode() && pNodeB->IsBoundaryNode())
1364 PerformT1Swap(pNodeA, pNodeB, all_indices);
1366 else if (pNodeA->IsBoundaryNode() || pNodeB->IsBoundaryNode())
1379 EXCEPTION(
"There is a non-boundary node contained only in two elements; something has gone wrong.");
1391 EXCEPTION(
"There are non-boundary nodes contained only in two elements; something has gone wrong.");
1419 assert((nodeA_elem_indices.size() == 1 && nodeB_elem_indices.size() == 2)
1420 || (nodeA_elem_indices.size() == 2 && nodeB_elem_indices.size() == 1));
1425 std::set<unsigned> node1_elem_indices = nodeA_elem_indices;
1426 std::set<unsigned> node2_elem_indices = nodeB_elem_indices;
1428 if (nodeB_elem_indices.size() == 1)
1431 node1_elem_indices = nodeB_elem_indices;
1433 node2_elem_indices = nodeA_elem_indices;
1435 assert(node1_elem_indices.size() == 1);
1436 unsigned unique_element_index = *node1_elem_indices.begin();
1438 node2_elem_indices.erase(unique_element_index);
1439 assert(node2_elem_indices.size() == 1);
1440 unsigned common_element_index = *node2_elem_indices.begin();
1453 (local_index_2 + 1) % (p_common_element->
GetNumNodes()));
1457 if (next_node_1 == previous_node_2 || next_node_2 == previous_node_1)
1476 if (next_node_1 == previous_node_2)
1478 p_node_C = this->mNodes[next_node_1];
1486 PerformNodeMerge(pNodeA, pNodeB);
1490 if (pNodeB->IsDeleted())
1492 p_merged_node = pNodeA;
1495 PerformNodeMerge(p_node_C, p_merged_node);
1499 p_merged_node = p_node_C;
1510 std::set<unsigned> shared_elements;
1511 std::set_intersection(all_indices.begin(),
1513 previous_previous_elem_indices.begin(),
1514 previous_previous_elem_indices.end(),
1515 std::inserter(shared_elements, shared_elements.begin()));
1517 assert(shared_elements.size() < 3);
1519 if (shared_elements.size() == 2)
1522 p_end_node = this->mNodes[previous_previous_node_1];
1535 PerformNodeMerge(p_end_node, p_merged_node);
1538 RemoveDeletedNodes();
1551 PerformNodeMerge(pNodeA, pNodeB);
1552 RemoveDeletedNodes();
1559 if (nodeA_elem_indices.size() == 1 || nodeB_elem_indices.size() == 1)
1574 assert(pNodeA->IsBoundaryNode());
1575 assert(pNodeB->IsBoundaryNode());
1577 EXCEPTION(
"There is a boundary node contained in three elements something has gone wrong.");
1579 else if (nodeA_elem_indices.size() == 2 && nodeB_elem_indices.size() == 2)
1587 std::set<unsigned> element_A_not_B, temp_set;
1588 std::set_difference(all_indices.begin(), all_indices.end(), nodeB_elem_indices.begin(),
1589 nodeB_elem_indices.end(), std::inserter(temp_set, temp_set.begin()));
1590 element_A_not_B.swap(temp_set);
1593 assert(element_A_not_B.size() == 1);
1595 std::set<unsigned> element_B_not_A;
1596 std::set_difference(all_indices.begin(), all_indices.end(), nodeA_elem_indices.begin(),
1597 nodeA_elem_indices.end(), std::inserter(temp_set, temp_set.begin()));
1598 element_B_not_A.swap(temp_set);
1601 assert(element_B_not_A.size() == 1);
1606 unsigned local_index_1 = p_element_A_not_B->
GetNodeLocalIndex(pNodeA->GetIndex());
1610 unsigned local_index_2 = p_element_B_not_A->
GetNodeLocalIndex(pNodeB->GetIndex());
1612 (local_index_2 + 1) % (p_element_B_not_A->
GetNumNodes()));
1616 if (next_node_1 == previous_node_2 || next_node_2 == previous_node_1)
1630 assert(pNodeA->IsBoundaryNode());
1631 assert(pNodeB->IsBoundaryNode());
1635 unsigned nodeC_index;
1636 if (next_node_1 == previous_node_2 && next_node_2 != previous_node_1)
1638 nodeC_index = next_node_1;
1640 else if (next_node_2 == previous_node_1 && next_node_1 != previous_node_2)
1642 nodeC_index = next_node_2;
1646 assert(next_node_1 == previous_node_2 && next_node_2 == previous_node_1);
1654 EXCEPTION(
"Triangular element next to triangular void, not implemented yet.");
1666 EXCEPTION(
"Triangular element next to triangular void, not implemented yet.");
1668 PerformVoidRemoval(pNodeA, pNodeB, this->mNodes[nodeC_index]);
1683 assert(pNodeA->IsBoundaryNode());
1684 assert(pNodeB->IsBoundaryNode());
1685 PerformT1Swap(pNodeA, pNodeB, all_indices);
1691 assert((nodeA_elem_indices.size() == 2 && nodeB_elem_indices.size() == 3)
1692 || (nodeA_elem_indices.size() == 3 && nodeB_elem_indices.size() == 2));
1695 assert(!(pNodeA->IsBoundaryNode() && pNodeB->IsBoundaryNode()));
1697 if (pNodeA->IsBoundaryNode() || pNodeB->IsBoundaryNode())
1709 PerformT1Swap(pNodeA, pNodeB, all_indices);
1724 EXCEPTION(
"There are non-boundary nodes contained only in two elements; something has gone wrong.");
1747 this->PerformNodeMerge(pNodeA, pNodeB);
1748 this->RemoveDeletedNodes();
1752 this->PerformT1Swap(pNodeA, pNodeB, all_indices);
2026 [[maybe_unused]]
Node<SPACE_DIM>* pNode, [[maybe_unused]]
unsigned elementIndex)
2028 if constexpr (ELEMENT_DIM == 2 && SPACE_DIM == 2)
2033 std::set<unsigned> elements_containing_intersecting_node;
2035 for (
unsigned node_local_index = 0; node_local_index < num_nodes; node_local_index++)
2039 std::set<unsigned> node_elem_indices = this->GetNode(node_global_index)->rGetContainingElementIndices();
2041 for (std::set<unsigned>::const_iterator elem_iter = node_elem_indices.begin();
2042 elem_iter != node_elem_indices.end();
2046 unsigned num_nodes_in_neighbouring_element = p_neighbouring_element->
GetNumNodes();
2049 for (
unsigned node_index_2 = 0; node_index_2 < num_nodes_in_neighbouring_element; node_index_2++)
2053 elements_containing_intersecting_node.insert(p_neighbouring_element->
GetIndex());
2059 std::set<unsigned> all_elements_containing_intersecting_node = pNode->rGetContainingElementIndices();
2061 assert(elements_containing_intersecting_node.size() >= 1);
2062 assert(all_elements_containing_intersecting_node.size() >= 1);
2076 unsigned node_A_index = pNode->GetIndex();
2077 unsigned node_B_index = UINT_MAX;
2079 unsigned element_1_index = UINT_MAX;
2080 unsigned element_2_index = UINT_MAX;
2081 unsigned element_3_index = elementIndex;
2082 unsigned element_4_index = UINT_MAX;
2085 std::set<unsigned> intersecting_element;
2087 std::set_difference(all_elements_containing_intersecting_node.begin(), all_elements_containing_intersecting_node.end(),
2088 elements_containing_intersecting_node.begin(), elements_containing_intersecting_node.end(),
2089 std::inserter(intersecting_element, intersecting_element.begin()));
2091 if (intersecting_element.size() == 1)
2093 element_1_index = *(intersecting_element.begin());
2097 std::set<unsigned>::iterator iter = elements_containing_intersecting_node.begin();
2098 unsigned element_a_index = *(iter);
2102 unsigned element_b_index = UINT_MAX;
2104 if (elements_containing_intersecting_node.size() == 2)
2107 element_b_index = *(iter);
2108 p_element_b = this->GetElement(element_b_index);
2114 EXCEPTION(
"A triangular element has become concave. "
2115 "You need to rerun the simulation with a smaller time step to prevent this.");
2119 unsigned node_A_local_index_in_a = p_element_a->
GetNodeLocalIndex(node_A_index);
2121 unsigned node_before_A_in_a = (node_A_local_index_in_a + p_element_a->
GetNumNodes() - 1) % p_element_a->
GetNumNodes();
2122 unsigned node_after_A_in_a = (node_A_local_index_in_a + 1) % p_element_a->
GetNumNodes();
2124 unsigned global_node_before_A_in_a = p_element_a->
GetNodeGlobalIndex(node_before_A_in_a);
2125 unsigned global_node_after_A_in_a = p_element_a->
GetNodeGlobalIndex(node_after_A_in_a);
2127 for (
unsigned node_index = 0; node_index < num_nodes; ++node_index)
2131 node_B_index = global_node_before_A_in_a;
2136 node_B_index = global_node_after_A_in_a;
2145 if (node_B_index == UINT_MAX)
2147 EXCEPTION(
"Intersection cannot be resolved without splitting the element into two new elements.");
2151 c_vector<double, SPACE_DIM> nodeA_location = pNode->rGetLocation();
2152 c_vector<double, SPACE_DIM> nodeB_location = this->GetNode(node_B_index)->rGetLocation();
2153 c_vector<double, SPACE_DIM> vector_AB = this->GetVectorFromAtoB(nodeA_location, nodeB_location);
2154 mLocationsOfIntersectionSwaps.push_back(nodeA_location + 0.5 * vector_AB);
2157 unsigned node_B_local_index_in_a = p_element_a->
GetNodeLocalIndex(node_B_index);
2159 if ((node_B_local_index_in_a + 1) % p_element_a->
GetNumNodes() == node_A_local_index_in_a)
2162 if (element_b_index != UINT_MAX)
2164 assert(p_element_b !=
nullptr);
2171 element_2_index = element_a_index;
2172 element_4_index = element_b_index;
2177 if (element_b_index != UINT_MAX)
2179 assert(p_element_b !=
nullptr);
2186 element_2_index = element_b_index;
2187 element_4_index = element_a_index;
2191 unsigned intersected_edge = this->GetLocalIndexForElementEdgeClosestToPoint(pNode->rGetLocation(), elementIndex);
2193 unsigned node_A_local_index_in_1 = UINT_MAX;
2194 if (element_1_index != UINT_MAX)
2196 node_A_local_index_in_1 = this->GetElement(element_1_index)->GetNodeLocalIndex(node_A_index);
2199 unsigned node_A_local_index_in_2 = UINT_MAX;
2200 unsigned node_B_local_index_in_2 = UINT_MAX;
2202 if (element_2_index != UINT_MAX)
2204 node_A_local_index_in_2 = this->GetElement(element_2_index)->GetNodeLocalIndex(node_A_index);
2205 node_B_local_index_in_2 = this->GetElement(element_2_index)->GetNodeLocalIndex(node_B_index);
2208 unsigned node_B_local_index_in_3 = this->GetElement(elementIndex)->GetNodeLocalIndex(node_B_index);
2210 unsigned node_A_local_index_in_4 = UINT_MAX;
2211 unsigned node_B_local_index_in_4 = UINT_MAX;
2213 if (element_4_index != UINT_MAX)
2215 node_A_local_index_in_4 = this->GetElement(element_4_index)->GetNodeLocalIndex(node_A_index);
2216 node_B_local_index_in_4 = this->GetElement(element_4_index)->GetNodeLocalIndex(node_B_index);
2220 if (intersected_edge == node_B_local_index_in_3)
2229 if (element_1_index != UINT_MAX)
2231 assert(node_A_local_index_in_1 != UINT_MAX);
2232 this->mElements[element_1_index]->AddNode(this->mNodes[node_B_index], node_A_local_index_in_1);
2233 if (mTrackMeshOperations)
2234 mOperationRecorder.RecordNewEdgeOperation(this->mElements[element_1_index], node_A_local_index_in_1);
2236 this->mElements[element_3_index]->AddNode(this->mNodes[node_A_index], node_B_local_index_in_3);
2237 c_vector<double, SPACE_DIM> vector_B_to_node = this->GetVectorFromAtoB(this->GetElement(elementIndex)->GetNode(intersected_edge)->rGetLocation(), this->mNodes[node_B_index]->rGetLocation());
2238 c_vector<double, SPACE_DIM> vector_A_to_B = this->GetVectorFromAtoB(this->mNodes[node_B_index]->rGetLocation(), this->mNodes[node_A_index]->rGetLocation());
2240 if (mTrackMeshOperations)
2241 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), intersected_edge,
2242 norm_2(vector_A_to_B) / norm_2(vector_B_to_node));
2244 if (element_2_index != UINT_MAX)
2246 assert(node_B_local_index_in_2 != UINT_MAX);
2247 this->mElements[element_2_index]->DeleteNode(node_B_local_index_in_2);
2249 if (mTrackMeshOperations)
2250 mOperationRecorder.RecordEdgeMergeOperation(this->mElements[element_2_index], node_B_local_index_in_2);
2252 if (element_4_index != UINT_MAX)
2254 assert(node_A_local_index_in_4 != UINT_MAX);
2255 this->mElements[element_4_index]->DeleteNode(node_A_local_index_in_4);
2256 if (mTrackMeshOperations)
2257 mOperationRecorder.RecordEdgeMergeOperation(this->mElements[element_4_index], node_A_local_index_in_4);
2262 assert((intersected_edge + 1) % num_nodes == node_B_local_index_in_3);
2265 if (element_1_index != UINT_MAX)
2267 assert(node_A_local_index_in_1 != UINT_MAX);
2268 unsigned node_before_A_in_1 = (node_A_local_index_in_1 + this->GetElement(element_1_index)->GetNumNodes() - 1) % this->GetElement(element_1_index)->GetNumNodes();
2269 this->mElements[element_1_index]->AddNode(this->mNodes[node_B_index], node_before_A_in_1);
2271 if (mTrackMeshOperations)
2272 mOperationRecorder.RecordNewEdgeOperation(this->mElements[element_1_index], node_before_A_in_1 + 1);
2275 unsigned node_before_B_in_3 = (node_B_local_index_in_3 + this->GetElement(element_3_index)->GetNumNodes() - 1) % this->GetElement(element_3_index)->GetNumNodes();
2276 this->mElements[element_3_index]->AddNode(this->mNodes[node_A_index], node_before_B_in_3);
2277 c_vector<double, SPACE_DIM> vector_B_to_node = this->GetVectorFromAtoB(this->GetElement(elementIndex)->GetNode(intersected_edge)->rGetLocation(), this->mNodes[node_B_index]->rGetLocation());
2278 c_vector<double, SPACE_DIM> vector_A_to_B = this->GetVectorFromAtoB(this->mNodes[node_B_index]->rGetLocation(), this->mNodes[node_A_index]->rGetLocation());
2280 if (mTrackMeshOperations)
2281 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), intersected_edge,
2282 norm_2(vector_A_to_B) / norm_2(vector_B_to_node));
2285 if (element_2_index != UINT_MAX)
2287 assert(node_A_local_index_in_2 != UINT_MAX);
2288 this->mElements[element_2_index]->DeleteNode(node_A_local_index_in_2);
2289 if (mTrackMeshOperations)
2290 mOperationRecorder.RecordEdgeMergeOperation(this->mElements[element_2_index], node_A_local_index_in_2);
2292 if (element_4_index != UINT_MAX)
2294 assert(node_B_local_index_in_4 != UINT_MAX);
2295 this->mElements[element_4_index]->DeleteNode(node_B_local_index_in_4);
2296 if (mTrackMeshOperations)
2297 mOperationRecorder.RecordEdgeMergeOperation(this->mElements[element_4_index], node_B_local_index_in_4);
2300 if (element_1_index != UINT_MAX)
2302 this->mElements[element_1_index]->RebuildEdges();
2304 if (element_2_index != UINT_MAX)
2306 this->mElements[element_2_index]->RebuildEdges();
2308 if (element_3_index != UINT_MAX)
2310 this->mElements[element_3_index]->RebuildEdges();
2312 if (element_4_index != UINT_MAX)
2314 this->mElements[element_4_index]->RebuildEdges();
2317 if (all_elements_containing_intersecting_node.size() == 2)
2320 if (elements_containing_intersecting_node.size() == 2)
2322 assert(this->mNodes[node_A_index]->IsBoundaryNode() ==
true);
2323 assert(this->mNodes[node_B_index]->IsBoundaryNode() ==
false);
2324 this->mNodes[node_B_index]->SetAsBoundaryNode(
true);
2326 else if (elements_containing_intersecting_node.size() == 1)
2328 assert(this->mNodes[node_A_index]->IsBoundaryNode() ==
true);
2329 assert(this->mNodes[node_B_index]->IsBoundaryNode() ==
true);
2331 if (element_2_index == UINT_MAX)
2333 if (intersected_edge == node_B_local_index_in_3)
2335 this->mNodes[node_B_index]->SetAsBoundaryNode(
false);
2339 this->mNodes[node_A_index]->SetAsBoundaryNode(
false);
2343 if (element_4_index == UINT_MAX)
2345 if (intersected_edge == node_B_local_index_in_3)
2347 this->mNodes[node_A_index]->SetAsBoundaryNode(
false);
2351 this->mNodes[node_B_index]->SetAsBoundaryNode(
false);
2363 else if (all_elements_containing_intersecting_node.size() == 1)
2365 if (elements_containing_intersecting_node.size() == 1)
2367 assert(this->mNodes[node_A_index]->IsBoundaryNode() ==
true);
2368 assert(this->mNodes[node_B_index]->IsBoundaryNode() ==
true);
2378 assert(this->mNodes[node_A_index]->IsBoundaryNode() ==
false);
2379 assert(this->mNodes[node_B_index]->IsBoundaryNode() ==
false);
2511 [[maybe_unused]]
Node<SPACE_DIM>* pNode, [[maybe_unused]]
unsigned elementIndex)
2513 if constexpr (ELEMENT_DIM == 2 && SPACE_DIM == 2)
2516 assert(pNode->IsBoundaryNode());
2523 std::set<unsigned> elements_containing_intersecting_node = pNode->rGetContainingElementIndices();
2526 unsigned node_A_local_index = this->GetLocalIndexForElementEdgeClosestToPoint(pNode->rGetLocation(), elementIndex);
2529 c_vector<double, SPACE_DIM> node_location;
2530 node_location = pNode->rGetModifiableLocation();
2534 unsigned vertexB_index = p_element->
GetNodeGlobalIndex((node_A_local_index + 1) % num_nodes);
2537 if (!this->mNodes[vertexA_index]->IsBoundaryNode() || !this->mNodes[vertexB_index]->IsBoundaryNode())
2539 EXCEPTION(
"A boundary node has intersected a non-boundary edge; this is because the boundary element has become concave. You need to rerun the simulation with a smaller time step to prevent this.");
2543 c_vector<double, SPACE_DIM> vertexA = p_element->
GetNodeLocation(node_A_local_index);
2544 c_vector<double, SPACE_DIM> vertexB = p_element->
GetNodeLocation((node_A_local_index + 1) % num_nodes);
2545 c_vector<double, SPACE_DIM> vector_a_to_point = this->GetVectorFromAtoB(vertexA, node_location);
2547 c_vector<double, SPACE_DIM> vector_a_to_b = this->GetVectorFromAtoB(vertexA, vertexB);
2549 c_vector<double, SPACE_DIM> edge_ab_unit_vector = vector_a_to_b / norm_2(vector_a_to_b);
2550 c_vector<double, SPACE_DIM> intersection = vertexA + edge_ab_unit_vector * inner_prod(vector_a_to_point, edge_ab_unit_vector);
2557 mOperationRecorder.RecordT3Swap(swap_info);
2560 std::set<unsigned> rebuilt_elements;
2561 if (pNode->GetNumContainingElements() == 1)
2564 unsigned intersecting_element_index = *elements_containing_intersecting_node.begin();
2570 const unsigned num_edges = p_intersecting_element->
GetNumEdges();
2571 std::vector<unsigned> old_ids(num_edges);
2572 for (
unsigned i=0; i<num_edges; ++i)
2574 old_ids[i] = p_intersecting_element->
GetEdge(i)->GetIndex();
2577 unsigned local_index = p_intersecting_element->
GetNodeLocalIndex(pNode->GetIndex());
2582 if (next_node == vertexA_index || previous_node == vertexA_index || next_node == vertexB_index || previous_node == vertexB_index)
2584 unsigned common_vertex_index;
2586 if (next_node == vertexA_index || previous_node == vertexA_index)
2588 common_vertex_index = vertexA_index;
2592 common_vertex_index = vertexB_index;
2595 assert(this->mNodes[common_vertex_index]->GetNumContainingElements() > 1);
2597 std::set<unsigned> elements_containing_common_vertex = this->mNodes[common_vertex_index]->rGetContainingElementIndices();
2598 std::set<unsigned>::const_iterator it = elements_containing_common_vertex.begin();
2604 unsigned num_common_vertices = 0;
2605 std::vector<unsigned> common_vertex_indices;
2606 for (
unsigned i = 0; i < p_element_common_1->
GetNumNodes(); i++)
2608 for (
unsigned j = 0; j < p_element_common_2->
GetNumNodes(); j++)
2612 num_common_vertices++;
2618 if (num_common_vertices == 1 || this->mNodes[common_vertex_index]->GetNumContainingElements() > 2)
2634 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
2637 pNode->rGetModifiableLocation() = intersection;
2640 const double a_to_b_length = norm_2(vector_a_to_b);
2641 c_vector<double, SPACE_DIM> vector_a_to_node = this->GetVectorFromAtoB(vertexA, intersection);
2642 const double a_to_node_length = norm_2(vector_a_to_node);
2645 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2647 if (mTrackMeshOperations)
2648 mOperationRecorder.RecordEdgeSplitOperation(p_element, node_A_local_index, a_to_node_length / a_to_b_length);
2649 rebuilt_elements.insert(p_element->
GetIndex());
2651 assert(pNode->GetNumContainingElements() == 2);
2653 else if (num_common_vertices == 2)
2658 if ((common_vertex_indices[0] == vertexA_index && common_vertex_indices[1] == vertexB_index) || (common_vertex_indices[1] == vertexA_index && common_vertex_indices[0] == vertexB_index))
2676 const unsigned downstream_index = (local_index + p_intersecting_element->
GetNumNodes() - 1) % (p_intersecting_element->
GetNumNodes());
2679 p_intersecting_element->
DeleteNode(local_index);
2682 if (mTrackMeshOperations)
2684 mOperationRecorder.RecordNodeMergeOperation(old_ids, p_intersecting_element, std::pair<unsigned, unsigned>(downstream_index, local_index));
2686 rebuilt_elements.insert(p_intersecting_element->
GetIndex());
2689 pNode->MarkAsDeleted();
2690 mDeletedNodeIndices.push_back(pNode->GetIndex());
2711 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
2714 pNode->rGetModifiableLocation() = intersection;
2717 this->GetElement(elementIndex)->ReplaceNode(this->mNodes[common_vertex_index], pNode);
2720 unsigned common_vertex_local_index = this->GetElement(intersecting_element_index)->GetNodeLocalIndex(common_vertex_index);
2721 this->GetElement(intersecting_element_index)->DeleteNode(common_vertex_local_index);
2722 assert(this->mNodes[common_vertex_index]->GetNumContainingElements() == 0);
2725 if (mTrackMeshOperations)
2726 mOperationRecorder.RecordEdgeMergeOperation(p_intersecting_element, common_vertex_local_index);
2727 rebuilt_elements.insert(p_intersecting_element->
GetIndex());
2729 this->mNodes[common_vertex_index]->MarkAsDeleted();
2730 mDeletedNodeIndices.push_back(common_vertex_index);
2733 assert(pNode->GetNumContainingElements() == 2);
2736 else if (num_common_vertices == 4)
2754 this->GetElement(elementIndex)->DeleteNode(node_A_local_index);
2755 if (mTrackMeshOperations)
2756 mOperationRecorder.RecordEdgeMergeOperation(this->GetElement(elementIndex), node_A_local_index);
2757 unsigned node_B_local_index = this->GetElement(elementIndex)->GetNodeLocalIndex(vertexB_index);
2758 this->GetElement(elementIndex)->DeleteNode(node_B_local_index);
2759 if (mTrackMeshOperations)
2760 mOperationRecorder.RecordEdgeMergeOperation(this->GetElement(elementIndex), node_B_local_index);
2763 unsigned node_A_local_index_intersecting_element = this->GetElement(intersecting_element_index)->GetNodeLocalIndex(vertexA_index);
2764 this->GetElement(intersecting_element_index)->DeleteNode(node_A_local_index_intersecting_element);
2765 if (mTrackMeshOperations)
2766 mOperationRecorder.RecordEdgeMergeOperation(this->GetElement(intersecting_element_index), node_A_local_index_intersecting_element);
2767 unsigned node_B_local_index_intersecting_element = this->GetElement(intersecting_element_index)->GetNodeLocalIndex(vertexB_index);
2768 this->GetElement(intersecting_element_index)->DeleteNode(node_B_local_index_intersecting_element);
2769 if (mTrackMeshOperations)
2770 mOperationRecorder.RecordEdgeMergeOperation(this->GetElement(intersecting_element_index), node_B_local_index_intersecting_element);
2773 unsigned p_node_local_index = this->GetElement(intersecting_element_index)->GetNodeLocalIndex(pNode->GetIndex());
2774 this->GetElement(intersecting_element_index)->DeleteNode(p_node_local_index);
2775 if (mTrackMeshOperations)
2776 mOperationRecorder.RecordEdgeMergeOperation(this->GetElement(intersecting_element_index), p_node_local_index);
2778 rebuilt_elements.insert(elementIndex);
2779 rebuilt_elements.insert(intersecting_element_index);
2781 pNode->MarkAsDeleted();
2782 mDeletedNodeIndices.push_back(pNode->GetIndex());
2783 this->mNodes[vertexA_index]->MarkAsDeleted();
2784 mDeletedNodeIndices.push_back(vertexA_index);
2785 this->mNodes[vertexB_index]->MarkAsDeleted();
2786 mDeletedNodeIndices.push_back(vertexB_index);
2807 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
2808 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index + 1) % num_nodes);
2811 pNode->rGetModifiableLocation() = intersection + 0.5 * mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
2814 c_vector<double, SPACE_DIM> new_node_location;
2815 new_node_location = intersection - 0.5 * mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
2818 unsigned new_node_global_index = this->AddNode(
new Node<SPACE_DIM>(0,
true, new_node_location[0], new_node_location[1]));
2822 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2824 c_vector<double, SPACE_DIM> vector_a_to_node = this->GetVectorFromAtoB(pNode->rGetLocation(), vertexA);
2825 if (mTrackMeshOperations)
2826 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index,
2827 norm_2(vector_a_to_node) / norm_2(vector_a_to_b));
2831 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
2834 c_vector<double, SPACE_DIM> vector_a_to_new_node = this->GetVectorFromAtoB(new_node_location, vertexA);
2835 if (mTrackMeshOperations)
2836 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index,
2837 norm_2(vector_a_to_new_node) / norm_2(vector_a_to_node));
2839 assert(norm_2(vector_a_to_new_node) / norm_2(vector_a_to_node) < 1);
2842 const unsigned new_node_local_index = this->GetElement(intersecting_element_index)->GetNodeLocalIndex(pNode->GetIndex());
2843 this->GetElement(intersecting_element_index)->AddNode(this->mNodes[new_node_global_index], new_node_local_index);
2844 if (mTrackMeshOperations)
2846 mOperationRecorder.RecordNewEdgeOperation(this->GetElement(intersecting_element_index), new_node_local_index);
2850 assert(pNode->GetNumContainingElements() == 2);
2851 assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
2853 rebuilt_elements.insert(elementIndex);
2854 rebuilt_elements.insert(intersecting_element_index);
2857 else if (pNode->GetNumContainingElements() == 2)
2860 std::set<unsigned>::const_iterator it = elements_containing_intersecting_node.begin();
2863 unsigned num_nodes_elem_1 = p_element_1->
GetNumNodes();
2867 unsigned num_nodes_elem_2 = p_element_2->
GetNumNodes();
2869 unsigned node_global_index = pNode->GetIndex();
2872 unsigned next_node_1 = p_element_1->
GetNodeGlobalIndex((local_index_1 + 1) % num_nodes_elem_1);
2873 unsigned previous_node_1 = p_element_1->
GetNodeGlobalIndex((local_index_1 + num_nodes_elem_1 - 1) % num_nodes_elem_1);
2876 unsigned next_node_2 = p_element_2->
GetNodeGlobalIndex((local_index_2 + 1) % num_nodes_elem_2);
2877 unsigned previous_node_2 = p_element_2->
GetNodeGlobalIndex((local_index_2 + num_nodes_elem_2 - 1) % num_nodes_elem_2);
2880 if ((next_node_1 == vertexA_index || previous_node_1 == vertexA_index || next_node_2 == vertexA_index || previous_node_2 == vertexA_index) && (next_node_1 == vertexB_index || previous_node_1 == vertexB_index || next_node_2 == vertexB_index || previous_node_2 == vertexB_index))
2896 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
2897 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index + 1) % num_nodes);
2900 assert(pNode->IsBoundaryNode());
2901 assert(this->mNodes[vertexA_index]->IsBoundaryNode());
2902 assert(this->mNodes[vertexB_index]->IsBoundaryNode());
2905 pNode->rGetModifiableLocation() = intersection;
2906 pNode->SetAsBoundaryNode(
false);
2909 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2912 const double a_to_b_length = norm_2(vector_a_to_b);
2913 c_vector<double, SPACE_DIM> vector_a_to_p = this->GetVectorFromAtoB(intersection, vertexA);
2914 const double split_ratio = norm_2(vector_a_to_p) / a_to_b_length;
2915 if (mTrackMeshOperations)
2916 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, split_ratio);
2917 rebuilt_elements.insert(elementIndex);
2920 std::set<unsigned> elements_containing_vertex_A = this->mNodes[vertexA_index]->rGetContainingElementIndices();
2921 for (std::set<unsigned>::const_iterator iter = elements_containing_vertex_A.begin();
2922 iter != elements_containing_vertex_A.end();
2925 const unsigned this_vertexA_local_index = this->GetElement(*iter)->GetNodeLocalIndex(vertexA_index);
2926 this->GetElement(*iter)->DeleteNode(this_vertexA_local_index);
2927 if (mTrackMeshOperations)
2929 mOperationRecorder.RecordEdgeMergeOperation(this->GetElement(*iter), this_vertexA_local_index);
2931 rebuilt_elements.insert(this->GetElement(*iter)->GetIndex());
2935 assert(this->mNodes[vertexA_index]->GetNumContainingElements() == 0);
2936 this->mNodes[vertexA_index]->MarkAsDeleted();
2937 mDeletedNodeIndices.push_back(vertexA_index);
2940 std::set<unsigned> elements_containing_vertex_B = this->mNodes[vertexB_index]->rGetContainingElementIndices();
2941 for (std::set<unsigned>::const_iterator iter = elements_containing_vertex_B.begin();
2942 iter != elements_containing_vertex_B.end();
2945 const unsigned this_vertexB_local_index = this->GetElement(*iter)->GetNodeLocalIndex(vertexB_index);
2946 this->GetElement(*iter)->DeleteNode(this_vertexB_local_index);
2947 if (mTrackMeshOperations)
2949 mOperationRecorder.RecordEdgeMergeOperation(this->GetElement(*iter), this_vertexB_local_index);
2951 rebuilt_elements.insert(this->GetElement(*iter)->GetIndex());
2955 assert(this->mNodes[vertexB_index]->GetNumContainingElements() == 0);
2956 this->mNodes[vertexB_index]->MarkAsDeleted();
2957 mDeletedNodeIndices.push_back(vertexB_index);
2961 if (next_node_1 == vertexA_index || previous_node_1 == vertexA_index || next_node_2 == vertexA_index || previous_node_2 == vertexA_index)
2965 assert(this->mNodes[vertexA_index]->GetNumContainingElements() > 1);
2967 std::set<unsigned> elements_containing_vertex_A = this->mNodes[vertexA_index]->rGetContainingElementIndices();
2968 std::set<unsigned>::const_iterator iter = elements_containing_vertex_A.begin();
2974 unsigned num_common_vertices = 0;
2975 for (
unsigned i = 0; i < p_element_common_1->
GetNumNodes(); i++)
2977 for (
unsigned j = 0; j < p_element_common_2->
GetNumNodes(); j++)
2981 num_common_vertices++;
2986 if (num_common_vertices == 1 || this->mNodes[vertexA_index]->GetNumContainingElements() > 2)
3002 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
3003 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index + 1) % num_nodes);
3006 pNode->rGetModifiableLocation() = intersection - 0.5 * mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
3007 pNode->SetAsBoundaryNode(
false);
3010 c_vector<double, SPACE_DIM> new_node_location;
3011 new_node_location = intersection + 0.5 * mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
3014 unsigned new_node_global_index = this->AddNode(
new Node<SPACE_DIM>(0,
true, new_node_location[0], new_node_location[1]));
3017 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
3019 const double a_to_b_length = norm_2(vector_a_to_b);
3020 c_vector<double, SPACE_DIM> a_to_new_node_vector = this->GetVectorFromAtoB(vertexA, new_node_location);
3021 const double a_to_new_length = norm_2(a_to_new_node_vector);
3022 const double ratio_new_node = a_to_new_length / a_to_b_length;
3023 if (mTrackMeshOperations)
3024 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, ratio_new_node);
3025 rebuilt_elements.insert(elementIndex);
3027 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
3029 c_vector<double, SPACE_DIM> a_to_p_vector = this->GetVectorFromAtoB(vertexA, pNode->rGetLocation());
3030 const double ratio_p_node = norm_2(a_to_p_vector) / a_to_new_length;
3031 assert(ratio_p_node <= 1);
3032 if (mTrackMeshOperations)
3033 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, ratio_p_node);
3036 if (next_node_1 == previous_node_2)
3038 const unsigned insertion_local_index = (local_index_1 + p_element_1->
GetNumNodes() - 1) % (p_element_1->
GetNumNodes());
3039 p_element_1->
AddNode(this->mNodes[new_node_global_index], insertion_local_index);
3040 if (mTrackMeshOperations)
3042 mOperationRecorder.RecordNewEdgeOperation(p_element_1, insertion_local_index);
3044 rebuilt_elements.insert(p_element_1->
GetIndex());
3048 assert(next_node_2 == previous_node_1);
3049 const unsigned insertion_local_index = (local_index_2 + p_element_2->
GetNumNodes() - 1) % (p_element_2->
GetNumNodes());
3050 p_element_2->
AddNode(this->mNodes[new_node_global_index], insertion_local_index);
3051 if (mTrackMeshOperations)
3053 mOperationRecorder.RecordNewEdgeOperation(p_element_2, insertion_local_index);
3055 rebuilt_elements.insert(p_element_2->
GetIndex());
3059 assert(pNode->GetNumContainingElements() == 3);
3060 assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
3062 else if (num_common_vertices == 2)
3079 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
3080 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index + 1) % num_nodes);
3083 pNode->rGetModifiableLocation() = intersection - 0.5 * mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
3084 pNode->SetAsBoundaryNode(
false);
3087 c_vector<double, SPACE_DIM> new_node_location;
3088 new_node_location = intersection + 0.5 * mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
3091 unsigned new_node_global_index = this->AddNode(
new Node<SPACE_DIM>(0,
true, new_node_location[0], new_node_location[1]));
3094 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
3096 const double a_to_b_length = norm_2(vector_a_to_b);
3097 c_vector<double, SPACE_DIM> a_to_new_node_vector = this->GetVectorFromAtoB(vertexA, new_node_location);
3098 const double a_to_new_length = norm_2(a_to_new_node_vector);
3099 const double ratio_new_node = a_to_new_length / a_to_b_length;
3100 if (mTrackMeshOperations)
3101 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, ratio_new_node);
3103 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
3105 c_vector<double, SPACE_DIM> a_to_p_vector = this->GetVectorFromAtoB(vertexA, pNode->rGetLocation());
3106 const double ratio_p_node = norm_2(a_to_p_vector) / a_to_new_length;
3107 assert(ratio_p_node <= 1);
3108 if (mTrackMeshOperations)
3109 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, ratio_p_node);
3111 rebuilt_elements.insert(elementIndex);
3113 if (next_node_1 == previous_node_2)
3115 const unsigned insertion_local_index = (local_index_1 + p_element_1->
GetNumNodes() - 1) % (p_element_1->
GetNumNodes());
3116 p_element_1->
AddNode(this->mNodes[new_node_global_index], insertion_local_index);
3117 if (mTrackMeshOperations)
3119 mOperationRecorder.RecordNewEdgeOperation(p_element_1, insertion_local_index);
3121 rebuilt_elements.insert(p_element_1->
GetIndex());
3125 assert(next_node_2 == previous_node_1);
3126 const unsigned insertion_local_index = (local_index_2 + p_element_2->
GetNumNodes() - 1) % (p_element_2->
GetNumNodes());
3127 p_element_2->
AddNode(this->mNodes[new_node_global_index], insertion_local_index);
3128 if (mTrackMeshOperations)
3130 mOperationRecorder.RecordNewEdgeOperation(p_element_2, insertion_local_index);
3132 rebuilt_elements.insert(p_element_2->
GetIndex());
3136 const unsigned local_index_1 = p_element_common_1->
GetNodeLocalIndex(vertexA_index);
3137 const unsigned local_index_2 = p_element_common_2->
GetNodeLocalIndex(vertexA_index);
3138 p_element_common_1->
DeleteNode(local_index_1);
3139 if (mTrackMeshOperations)
3141 mOperationRecorder.RecordEdgeMergeOperation(p_element_common_1, local_index_1);
3143 p_element_common_2->
DeleteNode(local_index_2);
3144 if (mTrackMeshOperations)
3146 mOperationRecorder.RecordEdgeMergeOperation(p_element_common_2, local_index_2);
3148 assert(this->mNodes[vertexA_index]->GetNumContainingElements() == 0);
3149 rebuilt_elements.insert(p_element_common_1->
GetIndex());
3150 rebuilt_elements.insert(p_element_common_2->
GetIndex());
3152 this->mNodes[vertexA_index]->MarkAsDeleted();
3153 mDeletedNodeIndices.push_back(vertexA_index);
3156 assert(pNode->GetNumContainingElements() == 3);
3157 assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
3165 else if (next_node_1 == vertexB_index || previous_node_1 == vertexB_index || next_node_2 == vertexB_index || previous_node_2 == vertexB_index)
3169 assert(this->mNodes[vertexB_index]->GetNumContainingElements() > 1);
3171 std::set<unsigned> elements_containing_vertex_B = this->mNodes[vertexB_index]->rGetContainingElementIndices();
3172 std::set<unsigned>::const_iterator iter = elements_containing_vertex_B.begin();
3178 unsigned num_common_vertices = 0;
3179 for (
unsigned i = 0; i < p_element_common_1->
GetNumNodes(); i++)
3181 for (
unsigned j = 0; j < p_element_common_2->
GetNumNodes(); j++)
3185 num_common_vertices++;
3190 if (num_common_vertices == 1 || this->mNodes[vertexB_index]->GetNumContainingElements() > 2)
3206 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
3207 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index + 1) % num_nodes);
3210 pNode->rGetModifiableLocation() = intersection + 0.5 * mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
3211 pNode->SetAsBoundaryNode(
false);
3214 c_vector<double, SPACE_DIM> new_node_location;
3215 new_node_location = intersection - 0.5 * mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
3218 unsigned new_node_global_index = this->AddNode(
new Node<SPACE_DIM>(0,
true, new_node_location[0], new_node_location[1]));
3221 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
3222 const double a_to_b_length = norm_2(vector_a_to_b);
3223 c_vector<double, SPACE_DIM> a_to_p_vector = this->GetVectorFromAtoB(vertexA, pNode->rGetLocation());
3224 const double ratio_p_node = norm_2(a_to_p_vector) / a_to_b_length;
3225 assert(ratio_p_node <= 1);
3226 if (mTrackMeshOperations)
3227 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, ratio_p_node);
3229 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
3230 c_vector<double, SPACE_DIM> a_to_new_node_vector = this->GetVectorFromAtoB(vertexA, new_node_location);
3231 const double a_to_new_length = norm_2(a_to_new_node_vector);
3232 const double ratio_new_node = a_to_new_length / norm_2(a_to_p_vector);
3233 assert(ratio_new_node <= 1);
3234 if (mTrackMeshOperations)
3235 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, ratio_new_node);
3236 rebuilt_elements.insert(elementIndex);
3238 if (next_node_1 == previous_node_2)
3240 p_element_2->
AddNode(this->mNodes[new_node_global_index], local_index_2);
3241 if (mTrackMeshOperations)
3242 mOperationRecorder.RecordNewEdgeOperation(p_element_2, local_index_2);
3243 rebuilt_elements.insert(p_element_2->
GetIndex());
3247 assert(next_node_2 == previous_node_1);
3248 p_element_1->
AddNode(this->mNodes[new_node_global_index], local_index_1);
3249 if (mTrackMeshOperations)
3250 mOperationRecorder.RecordNewEdgeOperation(p_element_1, local_index_1);
3251 rebuilt_elements.insert(p_element_1->
GetIndex());
3255 assert(pNode->GetNumContainingElements() == 3);
3256 assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
3258 else if (num_common_vertices == 2)
3275 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
3276 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index + 1) % num_nodes);
3279 pNode->rGetModifiableLocation() = intersection + 0.5 * mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
3280 pNode->SetAsBoundaryNode(
false);
3283 c_vector<double, SPACE_DIM> new_node_location;
3284 new_node_location = intersection - 0.5 * mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
3287 unsigned new_node_global_index = this->AddNode(
new Node<SPACE_DIM>(0,
true, new_node_location[0], new_node_location[1]));
3290 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
3291 const double a_to_b_length = norm_2(vector_a_to_b);
3292 c_vector<double, SPACE_DIM> a_to_p_vector = this->GetVectorFromAtoB(vertexA, pNode->rGetLocation());
3293 const double ratio_p_node = norm_2(a_to_p_vector) / a_to_b_length;
3294 assert(ratio_p_node <= 1);
3295 if (mTrackMeshOperations)
3296 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, ratio_p_node);
3298 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
3299 c_vector<double, SPACE_DIM> a_to_new_node_vector = this->GetVectorFromAtoB(vertexA, new_node_location);
3300 const double a_to_new_length = norm_2(a_to_new_node_vector);
3301 const double ratio_new_node = a_to_new_length / norm_2(a_to_p_vector);
3302 assert(ratio_new_node <= 1);
3303 if (mTrackMeshOperations)
3304 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, ratio_new_node);
3305 rebuilt_elements.insert(elementIndex);
3307 if (next_node_1 == previous_node_2)
3309 p_element_2->
AddNode(this->mNodes[new_node_global_index], local_index_2);
3310 if (mTrackMeshOperations)
3311 mOperationRecorder.RecordNewEdgeOperation(p_element_2, local_index_2);
3312 rebuilt_elements.insert(p_element_2->
GetIndex());
3316 assert(next_node_2 == previous_node_1);
3317 p_element_1->
AddNode(this->mNodes[new_node_global_index], local_index_1);
3318 if (mTrackMeshOperations)
3319 mOperationRecorder.RecordNewEdgeOperation(p_element_1, local_index_1);
3320 rebuilt_elements.insert(p_element_1->
GetIndex());
3324 const unsigned local_index_1 = p_element_common_1->
GetNodeLocalIndex(vertexB_index);
3325 const unsigned local_index_2 = p_element_common_2->
GetNodeLocalIndex(vertexB_index);
3326 p_element_common_1->
DeleteNode(local_index_1);
3327 if (mTrackMeshOperations)
3329 mOperationRecorder.RecordEdgeMergeOperation(p_element_common_1, local_index_1);
3331 p_element_common_2->
DeleteNode(local_index_2);
3332 if (mTrackMeshOperations)
3334 mOperationRecorder.RecordEdgeMergeOperation(p_element_common_2, local_index_2);
3336 rebuilt_elements.insert(p_element_common_1->
GetIndex());
3337 rebuilt_elements.insert(p_element_common_2->
GetIndex());
3339 assert(this->mNodes[vertexB_index]->GetNumContainingElements() == 0);
3341 this->mNodes[vertexB_index]->MarkAsDeleted();
3342 mDeletedNodeIndices.push_back(vertexB_index);
3345 assert(pNode->GetNumContainingElements() == 3);
3346 assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
3367 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
3368 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index + 1) % num_nodes);
3371 pNode->rGetModifiableLocation() = intersection;
3372 pNode->SetAsBoundaryNode(
false);
3374 c_vector<double, SPACE_DIM> new_node_1_location;
3375 new_node_1_location = intersection - mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
3376 c_vector<double, SPACE_DIM> new_node_2_location;
3377 new_node_2_location = intersection + mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
3380 unsigned new_node_1_global_index = this->AddNode(
new Node<SPACE_DIM>(0,
true, new_node_1_location[0], new_node_1_location[1]));
3381 unsigned new_node_2_global_index = this->AddNode(
new Node<SPACE_DIM>(0,
true, new_node_2_location[0], new_node_2_location[1]));
3384 const double a_to_b_length = norm_2(vector_a_to_b);
3385 const c_vector<double, SPACE_DIM> a_to_node2_vector = this->GetVectorFromAtoB(new_node_2_location, vertexA);
3386 const double a_to_node2_length = norm_2(a_to_node2_vector);
3387 const c_vector<double, SPACE_DIM> a_to_nodeP_vector = this->GetVectorFromAtoB(intersection, vertexA);
3388 const double a_to_nodeP_length = norm_2(a_to_nodeP_vector);
3389 const c_vector<double, SPACE_DIM> a_to_node1_vector = this->GetVectorFromAtoB(new_node_1_location, vertexA);
3390 const double a_to_node1_length = norm_2(a_to_node1_vector);
3392 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_2_global_index], node_A_local_index);
3393 if (mTrackMeshOperations)
3394 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, a_to_node2_length / a_to_b_length);
3395 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
3396 if (mTrackMeshOperations)
3397 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, a_to_nodeP_length / a_to_node2_length);
3398 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_1_global_index], node_A_local_index);
3399 if (mTrackMeshOperations)
3400 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, a_to_node1_length / a_to_nodeP_length);
3401 rebuilt_elements.insert(elementIndex);
3403 if (next_node_1 == previous_node_2)
3405 const unsigned inserted_local_index_1 = (local_index_1 + p_element_1->
GetNumNodes() - 1) % (p_element_1->
GetNumNodes());
3406 p_element_1->
AddNode(this->mNodes[new_node_2_global_index], inserted_local_index_1);
3407 if (mTrackMeshOperations)
3409 mOperationRecorder.RecordNewEdgeOperation(p_element_1, inserted_local_index_1);
3411 p_element_2->
AddNode(this->mNodes[new_node_1_global_index], local_index_2);
3412 if (mTrackMeshOperations)
3414 mOperationRecorder.RecordNewEdgeOperation(p_element_2, local_index_2);
3419 assert(next_node_2 == previous_node_1);
3420 p_element_1->
AddNode(this->mNodes[new_node_1_global_index], local_index_1);
3421 if (mTrackMeshOperations)
3423 mOperationRecorder.RecordNewEdgeOperation(p_element_1, local_index_1);
3425 const unsigned inserted_local_index_2 = (local_index_2 + p_element_2->
GetNumNodes() - 1) % (p_element_2->
GetNumNodes());
3426 p_element_2->
AddNode(this->mNodes[new_node_2_global_index], inserted_local_index_2);
3427 if (mTrackMeshOperations)
3429 mOperationRecorder.RecordNewEdgeOperation(p_element_2, local_index_2);
3432 rebuilt_elements.insert(p_element_1->
GetIndex());
3433 rebuilt_elements.insert(p_element_2->
GetIndex());
3436 assert(pNode->GetNumContainingElements() == 3);
3437 assert(this->mNodes[new_node_1_global_index]->GetNumContainingElements() == 2);
3438 assert(this->mNodes[new_node_2_global_index]->GetNumContainingElements() == 2);
3444 EXCEPTION(
"Trying to merge a node, contained in more than 2 elements, into another element, this is not possible with the vertex mesh.");
3446 for (
unsigned i : rebuilt_elements)
3448 this->GetElement(i)->RebuildEdges();