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
2238 = this->GetVectorFromAtoB(this->GetElement(elementIndex)->GetNode(intersected_edge)->rGetLocation(), this->mNodes[node_B_index]->rGetLocation());
2239 c_vector<double, SPACE_DIM> vector_A_to_B
2240 = this->GetVectorFromAtoB(this->mNodes[node_B_index]->rGetLocation(), this->mNodes[node_A_index]->rGetLocation());
2242 if (mTrackMeshOperations)
2243 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), intersected_edge,
2244 norm_2(vector_A_to_B) / norm_2(vector_B_to_node));
2246 if (element_2_index != UINT_MAX)
2248 assert(node_B_local_index_in_2 != UINT_MAX);
2249 this->mElements[element_2_index]->DeleteNode(node_B_local_index_in_2);
2251 if (mTrackMeshOperations)
2252 mOperationRecorder.RecordEdgeMergeOperation(this->mElements[element_2_index], node_B_local_index_in_2);
2254 if (element_4_index != UINT_MAX)
2256 assert(node_A_local_index_in_4 != UINT_MAX);
2257 this->mElements[element_4_index]->DeleteNode(node_A_local_index_in_4);
2258 if (mTrackMeshOperations)
2259 mOperationRecorder.RecordEdgeMergeOperation(this->mElements[element_4_index], node_A_local_index_in_4);
2264 assert((intersected_edge + 1) % num_nodes == node_B_local_index_in_3);
2267 if (element_1_index != UINT_MAX)
2269 assert(node_A_local_index_in_1 != UINT_MAX);
2270 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();
2271 this->mElements[element_1_index]->AddNode(this->mNodes[node_B_index], node_before_A_in_1);
2273 if (mTrackMeshOperations)
2274 mOperationRecorder.RecordNewEdgeOperation(this->mElements[element_1_index], node_before_A_in_1 + 1);
2277 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();
2278 this->mElements[element_3_index]->AddNode(this->mNodes[node_A_index], node_before_B_in_3);
2279 c_vector<double, SPACE_DIM> vector_B_to_node
2280 = this->GetVectorFromAtoB(this->GetElement(elementIndex)->GetNode(intersected_edge)->rGetLocation(), this->mNodes[node_B_index]->rGetLocation());
2281 c_vector<double, SPACE_DIM> vector_A_to_B
2282 = this->GetVectorFromAtoB(this->mNodes[node_B_index]->rGetLocation(), this->mNodes[node_A_index]->rGetLocation());
2284 if (mTrackMeshOperations)
2285 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), intersected_edge,
2286 norm_2(vector_A_to_B) / norm_2(vector_B_to_node));
2289 if (element_2_index != UINT_MAX)
2291 assert(node_A_local_index_in_2 != UINT_MAX);
2292 this->mElements[element_2_index]->DeleteNode(node_A_local_index_in_2);
2293 if (mTrackMeshOperations)
2294 mOperationRecorder.RecordEdgeMergeOperation(this->mElements[element_2_index], node_A_local_index_in_2);
2296 if (element_4_index != UINT_MAX)
2298 assert(node_B_local_index_in_4 != UINT_MAX);
2299 this->mElements[element_4_index]->DeleteNode(node_B_local_index_in_4);
2300 if (mTrackMeshOperations)
2301 mOperationRecorder.RecordEdgeMergeOperation(this->mElements[element_4_index], node_B_local_index_in_4);
2304 if (element_1_index != UINT_MAX)
2306 this->mElements[element_1_index]->RebuildEdges();
2308 if (element_2_index != UINT_MAX)
2310 this->mElements[element_2_index]->RebuildEdges();
2312 if (element_3_index != UINT_MAX)
2314 this->mElements[element_3_index]->RebuildEdges();
2316 if (element_4_index != UINT_MAX)
2318 this->mElements[element_4_index]->RebuildEdges();
2321 if (all_elements_containing_intersecting_node.size() == 2)
2324 if (elements_containing_intersecting_node.size() == 2)
2326 assert(this->mNodes[node_A_index]->IsBoundaryNode() ==
true);
2327 assert(this->mNodes[node_B_index]->IsBoundaryNode() ==
false);
2328 this->mNodes[node_B_index]->SetAsBoundaryNode(
true);
2330 else if (elements_containing_intersecting_node.size() == 1)
2332 assert(this->mNodes[node_A_index]->IsBoundaryNode() ==
true);
2333 assert(this->mNodes[node_B_index]->IsBoundaryNode() ==
true);
2335 if (element_2_index == UINT_MAX)
2337 if (intersected_edge == node_B_local_index_in_3)
2339 this->mNodes[node_B_index]->SetAsBoundaryNode(
false);
2343 this->mNodes[node_A_index]->SetAsBoundaryNode(
false);
2347 if (element_4_index == UINT_MAX)
2349 if (intersected_edge == node_B_local_index_in_3)
2351 this->mNodes[node_A_index]->SetAsBoundaryNode(
false);
2355 this->mNodes[node_B_index]->SetAsBoundaryNode(
false);
2367 else if (all_elements_containing_intersecting_node.size() == 1)
2369 if (elements_containing_intersecting_node.size() == 1)
2371 assert(this->mNodes[node_A_index]->IsBoundaryNode() ==
true);
2372 assert(this->mNodes[node_B_index]->IsBoundaryNode() ==
true);
2382 assert(this->mNodes[node_A_index]->IsBoundaryNode() ==
false);
2383 assert(this->mNodes[node_B_index]->IsBoundaryNode() ==
false);
2515 [[maybe_unused]]
Node<SPACE_DIM>* pNode, [[maybe_unused]]
unsigned elementIndex)
2517 if constexpr (ELEMENT_DIM == 2 && SPACE_DIM == 2)
2520 assert(pNode->IsBoundaryNode());
2527 std::set<unsigned> elements_containing_intersecting_node = pNode->rGetContainingElementIndices();
2530 unsigned node_A_local_index = this->GetLocalIndexForElementEdgeClosestToPoint(pNode->rGetLocation(), elementIndex);
2533 c_vector<double, SPACE_DIM> node_location;
2534 node_location = pNode->rGetModifiableLocation();
2538 unsigned vertexB_index = p_element->
GetNodeGlobalIndex((node_A_local_index + 1) % num_nodes);
2541 if (!this->mNodes[vertexA_index]->IsBoundaryNode() || !this->mNodes[vertexB_index]->IsBoundaryNode())
2543 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.");
2547 c_vector<double, SPACE_DIM> vertexA = p_element->
GetNodeLocation(node_A_local_index);
2548 c_vector<double, SPACE_DIM> vertexB = p_element->
GetNodeLocation((node_A_local_index + 1) % num_nodes);
2549 c_vector<double, SPACE_DIM> vector_a_to_point = this->GetVectorFromAtoB(vertexA, node_location);
2551 c_vector<double, SPACE_DIM> vector_a_to_b = this->GetVectorFromAtoB(vertexA, vertexB);
2553 c_vector<double, SPACE_DIM> edge_ab_unit_vector = vector_a_to_b / norm_2(vector_a_to_b);
2554 c_vector<double, SPACE_DIM> intersection = vertexA + edge_ab_unit_vector * inner_prod(vector_a_to_point, edge_ab_unit_vector);
2561 mOperationRecorder.RecordT3Swap(swap_info);
2564 std::set<unsigned> rebuilt_elements;
2565 if (pNode->GetNumContainingElements() == 1)
2568 unsigned intersecting_element_index = *elements_containing_intersecting_node.begin();
2574 const unsigned num_edges = p_intersecting_element->
GetNumEdges();
2575 std::vector<unsigned> old_ids(num_edges);
2576 for (
unsigned i=0; i<num_edges; ++i)
2578 old_ids[i] = p_intersecting_element->
GetEdge(i)->GetIndex();
2581 unsigned local_index = p_intersecting_element->
GetNodeLocalIndex(pNode->GetIndex());
2586 if (next_node == vertexA_index || previous_node == vertexA_index || next_node == vertexB_index || previous_node == vertexB_index)
2588 unsigned common_vertex_index;
2590 if (next_node == vertexA_index || previous_node == vertexA_index)
2592 common_vertex_index = vertexA_index;
2596 common_vertex_index = vertexB_index;
2599 assert(this->mNodes[common_vertex_index]->GetNumContainingElements() > 1);
2601 std::set<unsigned> elements_containing_common_vertex = this->mNodes[common_vertex_index]->rGetContainingElementIndices();
2602 std::set<unsigned>::const_iterator it = elements_containing_common_vertex.begin();
2608 unsigned num_common_vertices = 0;
2609 std::vector<unsigned> common_vertex_indices;
2610 for (
unsigned i = 0; i < p_element_common_1->
GetNumNodes(); i++)
2612 for (
unsigned j = 0; j < p_element_common_2->
GetNumNodes(); j++)
2616 num_common_vertices++;
2622 if (num_common_vertices == 1 || this->mNodes[common_vertex_index]->GetNumContainingElements() > 2)
2638 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
2641 pNode->rGetModifiableLocation() = intersection;
2644 const double a_to_b_length = norm_2(vector_a_to_b);
2645 c_vector<double, SPACE_DIM> vector_a_to_node = this->GetVectorFromAtoB(vertexA, intersection);
2646 const double a_to_node_length = norm_2(vector_a_to_node);
2649 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2651 if (mTrackMeshOperations)
2652 mOperationRecorder.RecordEdgeSplitOperation(p_element, node_A_local_index, a_to_node_length / a_to_b_length);
2653 rebuilt_elements.insert(p_element->
GetIndex());
2655 assert(pNode->GetNumContainingElements() == 2);
2657 else if (num_common_vertices == 2)
2662 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))
2680 const unsigned downstream_index = (local_index + p_intersecting_element->
GetNumNodes() - 1) % (p_intersecting_element->
GetNumNodes());
2683 p_intersecting_element->
DeleteNode(local_index);
2686 if (mTrackMeshOperations)
2688 mOperationRecorder.RecordNodeMergeOperation(old_ids, p_intersecting_element, std::pair<unsigned, unsigned>(downstream_index, local_index));
2690 rebuilt_elements.insert(p_intersecting_element->
GetIndex());
2693 pNode->MarkAsDeleted();
2694 mDeletedNodeIndices.push_back(pNode->GetIndex());
2715 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
2718 pNode->rGetModifiableLocation() = intersection;
2721 this->GetElement(elementIndex)->ReplaceNode(this->mNodes[common_vertex_index], pNode);
2724 unsigned common_vertex_local_index = this->GetElement(intersecting_element_index)->GetNodeLocalIndex(common_vertex_index);
2725 this->GetElement(intersecting_element_index)->DeleteNode(common_vertex_local_index);
2726 assert(this->mNodes[common_vertex_index]->GetNumContainingElements() == 0);
2729 if (mTrackMeshOperations)
2730 mOperationRecorder.RecordEdgeMergeOperation(p_intersecting_element, common_vertex_local_index);
2731 rebuilt_elements.insert(p_intersecting_element->
GetIndex());
2733 this->mNodes[common_vertex_index]->MarkAsDeleted();
2734 mDeletedNodeIndices.push_back(common_vertex_index);
2737 assert(pNode->GetNumContainingElements() == 2);
2740 else if (num_common_vertices == 4)
2758 this->GetElement(elementIndex)->DeleteNode(node_A_local_index);
2759 if (mTrackMeshOperations)
2760 mOperationRecorder.RecordEdgeMergeOperation(this->GetElement(elementIndex), node_A_local_index);
2761 unsigned node_B_local_index = this->GetElement(elementIndex)->GetNodeLocalIndex(vertexB_index);
2762 this->GetElement(elementIndex)->DeleteNode(node_B_local_index);
2763 if (mTrackMeshOperations)
2764 mOperationRecorder.RecordEdgeMergeOperation(this->GetElement(elementIndex), node_B_local_index);
2767 unsigned node_A_local_index_intersecting_element = this->GetElement(intersecting_element_index)->GetNodeLocalIndex(vertexA_index);
2768 this->GetElement(intersecting_element_index)->DeleteNode(node_A_local_index_intersecting_element);
2769 if (mTrackMeshOperations)
2770 mOperationRecorder.RecordEdgeMergeOperation(this->GetElement(intersecting_element_index), node_A_local_index_intersecting_element);
2771 unsigned node_B_local_index_intersecting_element = this->GetElement(intersecting_element_index)->GetNodeLocalIndex(vertexB_index);
2772 this->GetElement(intersecting_element_index)->DeleteNode(node_B_local_index_intersecting_element);
2773 if (mTrackMeshOperations)
2774 mOperationRecorder.RecordEdgeMergeOperation(this->GetElement(intersecting_element_index), node_B_local_index_intersecting_element);
2777 unsigned p_node_local_index = this->GetElement(intersecting_element_index)->GetNodeLocalIndex(pNode->GetIndex());
2778 this->GetElement(intersecting_element_index)->DeleteNode(p_node_local_index);
2779 if (mTrackMeshOperations)
2780 mOperationRecorder.RecordEdgeMergeOperation(this->GetElement(intersecting_element_index), p_node_local_index);
2782 rebuilt_elements.insert(elementIndex);
2783 rebuilt_elements.insert(intersecting_element_index);
2785 pNode->MarkAsDeleted();
2786 mDeletedNodeIndices.push_back(pNode->GetIndex());
2787 this->mNodes[vertexA_index]->MarkAsDeleted();
2788 mDeletedNodeIndices.push_back(vertexA_index);
2789 this->mNodes[vertexB_index]->MarkAsDeleted();
2790 mDeletedNodeIndices.push_back(vertexB_index);
2811 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
2812 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index + 1) % num_nodes);
2815 pNode->rGetModifiableLocation() = intersection + 0.5 * mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
2818 c_vector<double, SPACE_DIM> new_node_location;
2819 new_node_location = intersection - 0.5 * mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
2822 unsigned new_node_global_index = this->AddNode(
new Node<SPACE_DIM>(0,
true, new_node_location[0], new_node_location[1]));
2826 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2828 c_vector<double, SPACE_DIM> vector_a_to_node = this->GetVectorFromAtoB(pNode->rGetLocation(), vertexA);
2829 if (mTrackMeshOperations)
2830 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index,
2831 norm_2(vector_a_to_node) / norm_2(vector_a_to_b));
2835 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
2838 c_vector<double, SPACE_DIM> vector_a_to_new_node = this->GetVectorFromAtoB(new_node_location, vertexA);
2839 if (mTrackMeshOperations)
2840 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index,
2841 norm_2(vector_a_to_new_node) / norm_2(vector_a_to_node));
2843 assert(norm_2(vector_a_to_new_node) / norm_2(vector_a_to_node) < 1);
2846 const unsigned new_node_local_index = this->GetElement(intersecting_element_index)->GetNodeLocalIndex(pNode->GetIndex());
2847 this->GetElement(intersecting_element_index)->AddNode(this->mNodes[new_node_global_index], new_node_local_index);
2848 if (mTrackMeshOperations)
2850 mOperationRecorder.RecordNewEdgeOperation(this->GetElement(intersecting_element_index), new_node_local_index);
2854 assert(pNode->GetNumContainingElements() == 2);
2855 assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
2857 rebuilt_elements.insert(elementIndex);
2858 rebuilt_elements.insert(intersecting_element_index);
2861 else if (pNode->GetNumContainingElements() == 2)
2864 std::set<unsigned>::const_iterator it = elements_containing_intersecting_node.begin();
2867 unsigned num_nodes_elem_1 = p_element_1->
GetNumNodes();
2871 unsigned num_nodes_elem_2 = p_element_2->
GetNumNodes();
2873 unsigned node_global_index = pNode->GetIndex();
2876 unsigned next_node_1 = p_element_1->
GetNodeGlobalIndex((local_index_1 + 1) % num_nodes_elem_1);
2877 unsigned previous_node_1 = p_element_1->
GetNodeGlobalIndex((local_index_1 + num_nodes_elem_1 - 1) % num_nodes_elem_1);
2880 unsigned next_node_2 = p_element_2->
GetNodeGlobalIndex((local_index_2 + 1) % num_nodes_elem_2);
2881 unsigned previous_node_2 = p_element_2->
GetNodeGlobalIndex((local_index_2 + num_nodes_elem_2 - 1) % num_nodes_elem_2);
2884 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))
2900 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
2901 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index + 1) % num_nodes);
2904 assert(pNode->IsBoundaryNode());
2905 assert(this->mNodes[vertexA_index]->IsBoundaryNode());
2906 assert(this->mNodes[vertexB_index]->IsBoundaryNode());
2909 pNode->rGetModifiableLocation() = intersection;
2910 pNode->SetAsBoundaryNode(
false);
2913 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2916 const double a_to_b_length = norm_2(vector_a_to_b);
2917 c_vector<double, SPACE_DIM> vector_a_to_p = this->GetVectorFromAtoB(intersection, vertexA);
2918 const double split_ratio = norm_2(vector_a_to_p) / a_to_b_length;
2919 if (mTrackMeshOperations)
2920 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, split_ratio);
2921 rebuilt_elements.insert(elementIndex);
2924 std::set<unsigned> elements_containing_vertex_A = this->mNodes[vertexA_index]->rGetContainingElementIndices();
2925 for (std::set<unsigned>::const_iterator iter = elements_containing_vertex_A.begin();
2926 iter != elements_containing_vertex_A.end();
2929 const unsigned this_vertexA_local_index = this->GetElement(*iter)->GetNodeLocalIndex(vertexA_index);
2930 this->GetElement(*iter)->DeleteNode(this_vertexA_local_index);
2931 if (mTrackMeshOperations)
2933 mOperationRecorder.RecordEdgeMergeOperation(this->GetElement(*iter), this_vertexA_local_index);
2935 rebuilt_elements.insert(this->GetElement(*iter)->GetIndex());
2939 assert(this->mNodes[vertexA_index]->GetNumContainingElements() == 0);
2940 this->mNodes[vertexA_index]->MarkAsDeleted();
2941 mDeletedNodeIndices.push_back(vertexA_index);
2944 std::set<unsigned> elements_containing_vertex_B = this->mNodes[vertexB_index]->rGetContainingElementIndices();
2945 for (std::set<unsigned>::const_iterator iter = elements_containing_vertex_B.begin();
2946 iter != elements_containing_vertex_B.end();
2949 const unsigned this_vertexB_local_index = this->GetElement(*iter)->GetNodeLocalIndex(vertexB_index);
2950 this->GetElement(*iter)->DeleteNode(this_vertexB_local_index);
2951 if (mTrackMeshOperations)
2953 mOperationRecorder.RecordEdgeMergeOperation(this->GetElement(*iter), this_vertexB_local_index);
2955 rebuilt_elements.insert(this->GetElement(*iter)->GetIndex());
2959 assert(this->mNodes[vertexB_index]->GetNumContainingElements() == 0);
2960 this->mNodes[vertexB_index]->MarkAsDeleted();
2961 mDeletedNodeIndices.push_back(vertexB_index);
2965 if (next_node_1 == vertexA_index || previous_node_1 == vertexA_index || next_node_2 == vertexA_index || previous_node_2 == vertexA_index)
2969 assert(this->mNodes[vertexA_index]->GetNumContainingElements() > 1);
2971 std::set<unsigned> elements_containing_vertex_A = this->mNodes[vertexA_index]->rGetContainingElementIndices();
2972 std::set<unsigned>::const_iterator iter = elements_containing_vertex_A.begin();
2978 unsigned num_common_vertices = 0;
2979 for (
unsigned i = 0; i < p_element_common_1->
GetNumNodes(); i++)
2981 for (
unsigned j = 0; j < p_element_common_2->
GetNumNodes(); j++)
2985 num_common_vertices++;
2990 if (num_common_vertices == 1 || this->mNodes[vertexA_index]->GetNumContainingElements() > 2)
3006 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
3007 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index + 1) % num_nodes);
3010 pNode->rGetModifiableLocation() = intersection - 0.5 * mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
3011 pNode->SetAsBoundaryNode(
false);
3014 c_vector<double, SPACE_DIM> new_node_location;
3015 new_node_location = intersection + 0.5 * mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
3018 unsigned new_node_global_index = this->AddNode(
new Node<SPACE_DIM>(0,
true, new_node_location[0], new_node_location[1]));
3021 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
3023 const double a_to_b_length = norm_2(vector_a_to_b);
3024 c_vector<double, SPACE_DIM> a_to_new_node_vector = this->GetVectorFromAtoB(vertexA, new_node_location);
3025 const double a_to_new_length = norm_2(a_to_new_node_vector);
3026 const double ratio_new_node = a_to_new_length / a_to_b_length;
3027 if (mTrackMeshOperations)
3028 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, ratio_new_node);
3029 rebuilt_elements.insert(elementIndex);
3031 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
3033 c_vector<double, SPACE_DIM> a_to_p_vector = this->GetVectorFromAtoB(vertexA, pNode->rGetLocation());
3034 const double ratio_p_node = norm_2(a_to_p_vector) / a_to_new_length;
3035 assert(ratio_p_node <= 1);
3036 if (mTrackMeshOperations)
3037 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, ratio_p_node);
3040 if (next_node_1 == previous_node_2)
3042 const unsigned insertion_local_index = (local_index_1 + p_element_1->
GetNumNodes() - 1) % (p_element_1->
GetNumNodes());
3043 p_element_1->
AddNode(this->mNodes[new_node_global_index], insertion_local_index);
3044 if (mTrackMeshOperations)
3046 mOperationRecorder.RecordNewEdgeOperation(p_element_1, insertion_local_index);
3048 rebuilt_elements.insert(p_element_1->
GetIndex());
3052 assert(next_node_2 == previous_node_1);
3053 const unsigned insertion_local_index = (local_index_2 + p_element_2->
GetNumNodes() - 1) % (p_element_2->
GetNumNodes());
3054 p_element_2->
AddNode(this->mNodes[new_node_global_index], insertion_local_index);
3055 if (mTrackMeshOperations)
3057 mOperationRecorder.RecordNewEdgeOperation(p_element_2, insertion_local_index);
3059 rebuilt_elements.insert(p_element_2->
GetIndex());
3063 assert(pNode->GetNumContainingElements() == 3);
3064 assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
3066 else if (num_common_vertices == 2)
3083 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
3084 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index + 1) % num_nodes);
3087 pNode->rGetModifiableLocation() = intersection - 0.5 * mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
3088 pNode->SetAsBoundaryNode(
false);
3091 c_vector<double, SPACE_DIM> new_node_location;
3092 new_node_location = intersection + 0.5 * mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
3095 unsigned new_node_global_index = this->AddNode(
new Node<SPACE_DIM>(0,
true, new_node_location[0], new_node_location[1]));
3098 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
3100 const double a_to_b_length = norm_2(vector_a_to_b);
3101 c_vector<double, SPACE_DIM> a_to_new_node_vector = this->GetVectorFromAtoB(vertexA, new_node_location);
3102 const double a_to_new_length = norm_2(a_to_new_node_vector);
3103 const double ratio_new_node = a_to_new_length / a_to_b_length;
3104 if (mTrackMeshOperations)
3105 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, ratio_new_node);
3107 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
3109 c_vector<double, SPACE_DIM> a_to_p_vector = this->GetVectorFromAtoB(vertexA, pNode->rGetLocation());
3110 const double ratio_p_node = norm_2(a_to_p_vector) / a_to_new_length;
3111 assert(ratio_p_node <= 1);
3112 if (mTrackMeshOperations)
3113 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, ratio_p_node);
3115 rebuilt_elements.insert(elementIndex);
3117 if (next_node_1 == previous_node_2)
3119 const unsigned insertion_local_index = (local_index_1 + p_element_1->
GetNumNodes() - 1) % (p_element_1->
GetNumNodes());
3120 p_element_1->
AddNode(this->mNodes[new_node_global_index], insertion_local_index);
3121 if (mTrackMeshOperations)
3123 mOperationRecorder.RecordNewEdgeOperation(p_element_1, insertion_local_index);
3125 rebuilt_elements.insert(p_element_1->
GetIndex());
3129 assert(next_node_2 == previous_node_1);
3130 const unsigned insertion_local_index = (local_index_2 + p_element_2->
GetNumNodes() - 1) % (p_element_2->
GetNumNodes());
3131 p_element_2->
AddNode(this->mNodes[new_node_global_index], insertion_local_index);
3132 if (mTrackMeshOperations)
3134 mOperationRecorder.RecordNewEdgeOperation(p_element_2, insertion_local_index);
3136 rebuilt_elements.insert(p_element_2->
GetIndex());
3140 const unsigned local_index_1 = p_element_common_1->
GetNodeLocalIndex(vertexA_index);
3141 const unsigned local_index_2 = p_element_common_2->
GetNodeLocalIndex(vertexA_index);
3142 p_element_common_1->
DeleteNode(local_index_1);
3143 if (mTrackMeshOperations)
3145 mOperationRecorder.RecordEdgeMergeOperation(p_element_common_1, local_index_1);
3147 p_element_common_2->
DeleteNode(local_index_2);
3148 if (mTrackMeshOperations)
3150 mOperationRecorder.RecordEdgeMergeOperation(p_element_common_2, local_index_2);
3152 assert(this->mNodes[vertexA_index]->GetNumContainingElements() == 0);
3153 rebuilt_elements.insert(p_element_common_1->
GetIndex());
3154 rebuilt_elements.insert(p_element_common_2->
GetIndex());
3156 this->mNodes[vertexA_index]->MarkAsDeleted();
3157 mDeletedNodeIndices.push_back(vertexA_index);
3160 assert(pNode->GetNumContainingElements() == 3);
3161 assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
3169 else if (next_node_1 == vertexB_index || previous_node_1 == vertexB_index || next_node_2 == vertexB_index || previous_node_2 == vertexB_index)
3173 assert(this->mNodes[vertexB_index]->GetNumContainingElements() > 1);
3175 std::set<unsigned> elements_containing_vertex_B = this->mNodes[vertexB_index]->rGetContainingElementIndices();
3176 std::set<unsigned>::const_iterator iter = elements_containing_vertex_B.begin();
3182 unsigned num_common_vertices = 0;
3183 for (
unsigned i = 0; i < p_element_common_1->
GetNumNodes(); i++)
3185 for (
unsigned j = 0; j < p_element_common_2->
GetNumNodes(); j++)
3189 num_common_vertices++;
3194 if (num_common_vertices == 1 || this->mNodes[vertexB_index]->GetNumContainingElements() > 2)
3210 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
3211 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index + 1) % num_nodes);
3214 pNode->rGetModifiableLocation() = intersection + 0.5 * mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
3215 pNode->SetAsBoundaryNode(
false);
3218 c_vector<double, SPACE_DIM> new_node_location;
3219 new_node_location = intersection - 0.5 * mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
3222 unsigned new_node_global_index = this->AddNode(
new Node<SPACE_DIM>(0,
true, new_node_location[0], new_node_location[1]));
3225 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
3226 const double a_to_b_length = norm_2(vector_a_to_b);
3227 c_vector<double, SPACE_DIM> a_to_p_vector = this->GetVectorFromAtoB(vertexA, pNode->rGetLocation());
3228 const double ratio_p_node = norm_2(a_to_p_vector) / a_to_b_length;
3229 assert(ratio_p_node <= 1);
3230 if (mTrackMeshOperations)
3231 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, ratio_p_node);
3233 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
3234 c_vector<double, SPACE_DIM> a_to_new_node_vector = this->GetVectorFromAtoB(vertexA, new_node_location);
3235 const double a_to_new_length = norm_2(a_to_new_node_vector);
3236 const double ratio_new_node = a_to_new_length / norm_2(a_to_p_vector);
3237 assert(ratio_new_node <= 1);
3238 if (mTrackMeshOperations)
3239 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, ratio_new_node);
3240 rebuilt_elements.insert(elementIndex);
3242 if (next_node_1 == previous_node_2)
3244 p_element_2->
AddNode(this->mNodes[new_node_global_index], local_index_2);
3245 if (mTrackMeshOperations)
3246 mOperationRecorder.RecordNewEdgeOperation(p_element_2, local_index_2);
3247 rebuilt_elements.insert(p_element_2->
GetIndex());
3251 assert(next_node_2 == previous_node_1);
3252 p_element_1->
AddNode(this->mNodes[new_node_global_index], local_index_1);
3253 if (mTrackMeshOperations)
3254 mOperationRecorder.RecordNewEdgeOperation(p_element_1, local_index_1);
3255 rebuilt_elements.insert(p_element_1->
GetIndex());
3259 assert(pNode->GetNumContainingElements() == 3);
3260 assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
3262 else if (num_common_vertices == 2)
3279 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
3280 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index + 1) % num_nodes);
3283 pNode->rGetModifiableLocation() = intersection + 0.5 * mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
3284 pNode->SetAsBoundaryNode(
false);
3287 c_vector<double, SPACE_DIM> new_node_location;
3288 new_node_location = intersection - 0.5 * mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
3291 unsigned new_node_global_index = this->AddNode(
new Node<SPACE_DIM>(0,
true, new_node_location[0], new_node_location[1]));
3294 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
3295 const double a_to_b_length = norm_2(vector_a_to_b);
3296 c_vector<double, SPACE_DIM> a_to_p_vector = this->GetVectorFromAtoB(vertexA, pNode->rGetLocation());
3297 const double ratio_p_node = norm_2(a_to_p_vector) / a_to_b_length;
3298 assert(ratio_p_node <= 1);
3299 if (mTrackMeshOperations)
3300 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, ratio_p_node);
3302 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
3303 c_vector<double, SPACE_DIM> a_to_new_node_vector = this->GetVectorFromAtoB(vertexA, new_node_location);
3304 const double a_to_new_length = norm_2(a_to_new_node_vector);
3305 const double ratio_new_node = a_to_new_length / norm_2(a_to_p_vector);
3306 assert(ratio_new_node <= 1);
3307 if (mTrackMeshOperations)
3308 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, ratio_new_node);
3309 rebuilt_elements.insert(elementIndex);
3311 if (next_node_1 == previous_node_2)
3313 p_element_2->
AddNode(this->mNodes[new_node_global_index], local_index_2);
3314 if (mTrackMeshOperations)
3315 mOperationRecorder.RecordNewEdgeOperation(p_element_2, local_index_2);
3316 rebuilt_elements.insert(p_element_2->
GetIndex());
3320 assert(next_node_2 == previous_node_1);
3321 p_element_1->
AddNode(this->mNodes[new_node_global_index], local_index_1);
3322 if (mTrackMeshOperations)
3323 mOperationRecorder.RecordNewEdgeOperation(p_element_1, local_index_1);
3324 rebuilt_elements.insert(p_element_1->
GetIndex());
3328 const unsigned local_index_1 = p_element_common_1->
GetNodeLocalIndex(vertexB_index);
3329 const unsigned local_index_2 = p_element_common_2->
GetNodeLocalIndex(vertexB_index);
3330 p_element_common_1->
DeleteNode(local_index_1);
3331 if (mTrackMeshOperations)
3333 mOperationRecorder.RecordEdgeMergeOperation(p_element_common_1, local_index_1);
3335 p_element_common_2->
DeleteNode(local_index_2);
3336 if (mTrackMeshOperations)
3338 mOperationRecorder.RecordEdgeMergeOperation(p_element_common_2, local_index_2);
3340 rebuilt_elements.insert(p_element_common_1->
GetIndex());
3341 rebuilt_elements.insert(p_element_common_2->
GetIndex());
3343 assert(this->mNodes[vertexB_index]->GetNumContainingElements() == 0);
3345 this->mNodes[vertexB_index]->MarkAsDeleted();
3346 mDeletedNodeIndices.push_back(vertexB_index);
3349 assert(pNode->GetNumContainingElements() == 3);
3350 assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
3371 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
3372 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index + 1) % num_nodes);
3375 pNode->rGetModifiableLocation() = intersection;
3376 pNode->SetAsBoundaryNode(
false);
3378 c_vector<double, SPACE_DIM> new_node_1_location;
3379 new_node_1_location = intersection - mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
3380 c_vector<double, SPACE_DIM> new_node_2_location;
3381 new_node_2_location = intersection + mCellRearrangementRatio * mCellRearrangementThreshold * edge_ab_unit_vector;
3384 unsigned new_node_1_global_index = this->AddNode(
new Node<SPACE_DIM>(0,
true, new_node_1_location[0], new_node_1_location[1]));
3385 unsigned new_node_2_global_index = this->AddNode(
new Node<SPACE_DIM>(0,
true, new_node_2_location[0], new_node_2_location[1]));
3388 const double a_to_b_length = norm_2(vector_a_to_b);
3389 const c_vector<double, SPACE_DIM> a_to_node2_vector
3390 = this->GetVectorFromAtoB(new_node_2_location, vertexA);
3391 const double a_to_node2_length = norm_2(a_to_node2_vector);
3392 const c_vector<double, SPACE_DIM> a_to_nodeP_vector
3393 = this->GetVectorFromAtoB(intersection, vertexA);
3394 const double a_to_nodeP_length = norm_2(a_to_nodeP_vector);
3395 const c_vector<double, SPACE_DIM> a_to_node1_vector
3396 = this->GetVectorFromAtoB(new_node_1_location, vertexA);
3397 const double a_to_node1_length = norm_2(a_to_node1_vector);
3399 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_2_global_index], node_A_local_index);
3400 if (mTrackMeshOperations)
3401 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, a_to_node2_length / a_to_b_length);
3402 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
3403 if (mTrackMeshOperations)
3404 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, a_to_nodeP_length / a_to_node2_length);
3405 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_1_global_index], node_A_local_index);
3406 if (mTrackMeshOperations)
3407 mOperationRecorder.RecordEdgeSplitOperation(this->GetElement(elementIndex), node_A_local_index, a_to_node1_length / a_to_nodeP_length);
3408 rebuilt_elements.insert(elementIndex);
3410 if (next_node_1 == previous_node_2)
3412 const unsigned inserted_local_index_1 = (local_index_1 + p_element_1->
GetNumNodes() - 1) % (p_element_1->
GetNumNodes());
3413 p_element_1->
AddNode(this->mNodes[new_node_2_global_index], inserted_local_index_1);
3414 if (mTrackMeshOperations)
3416 mOperationRecorder.RecordNewEdgeOperation(p_element_1, inserted_local_index_1);
3418 p_element_2->
AddNode(this->mNodes[new_node_1_global_index], local_index_2);
3419 if (mTrackMeshOperations)
3421 mOperationRecorder.RecordNewEdgeOperation(p_element_2, local_index_2);
3426 assert(next_node_2 == previous_node_1);
3427 p_element_1->
AddNode(this->mNodes[new_node_1_global_index], local_index_1);
3428 if (mTrackMeshOperations)
3430 mOperationRecorder.RecordNewEdgeOperation(p_element_1, local_index_1);
3432 const unsigned inserted_local_index_2 = (local_index_2 + p_element_2->
GetNumNodes() - 1) % (p_element_2->
GetNumNodes());
3433 p_element_2->
AddNode(this->mNodes[new_node_2_global_index], inserted_local_index_2);
3434 if (mTrackMeshOperations)
3436 mOperationRecorder.RecordNewEdgeOperation(p_element_2, local_index_2);
3439 rebuilt_elements.insert(p_element_1->
GetIndex());
3440 rebuilt_elements.insert(p_element_2->
GetIndex());
3443 assert(pNode->GetNumContainingElements() == 3);
3444 assert(this->mNodes[new_node_1_global_index]->GetNumContainingElements() == 2);
3445 assert(this->mNodes[new_node_2_global_index]->GetNumContainingElements() == 2);
3451 EXCEPTION(
"Trying to merge a node, contained in more than 2 elements, into another element, this is not possible with the vertex mesh.");
3453 for (
unsigned i : rebuilt_elements)
3455 this->GetElement(i)->RebuildEdges();