36 #include "MutableVertexMesh.hpp" 38 #include "LogFile.hpp" 40 #include "Warnings.hpp" 42 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
45 double cellRearrangementThreshold,
47 double cellRearrangementRatio,
48 double protorosetteFormationProbability,
49 double protorosetteResolutionProbabilityPerTimestep,
50 double rosetteResolutionProbabilityPerTimestep)
51 : mCellRearrangementThreshold(cellRearrangementThreshold),
52 mCellRearrangementRatio(cellRearrangementRatio),
53 mT2Threshold(t2Threshold),
54 mProtorosetteFormationProbability(protorosetteFormationProbability),
55 mProtorosetteResolutionProbabilityPerTimestep(protorosetteResolutionProbabilityPerTimestep),
56 mRosetteResolutionProbabilityPerTimestep(rosetteResolutionProbabilityPerTimestep),
57 mCheckForInternalIntersections(false),
58 mDistanceForT3SwapChecking(5.0)
61 assert(cellRearrangementThreshold > 0.0);
62 assert(t2Threshold > 0.0);
63 assert(protorosetteFormationProbability >= 0.0);
64 assert(protorosetteFormationProbability <= 1.0);
65 assert(protorosetteResolutionProbabilityPerTimestep >= 0.0);
66 assert(protorosetteResolutionProbabilityPerTimestep <= 1.0);
67 assert(rosetteResolutionProbabilityPerTimestep >= 0.0);
68 assert(rosetteResolutionProbabilityPerTimestep <= 1.0);
74 for (
unsigned node_index=0; node_index<nodes.size(); node_index++)
77 this->
mNodes.push_back(p_temp_node);
79 for (
unsigned elem_index=0; elem_index<vertexElements.size(); elem_index++)
82 this->
mElements.push_back(p_temp_vertex_element);
89 std::set<unsigned> faces_counted;
92 for (
unsigned elem_index=0; elem_index<this->
mElements.size(); elem_index++)
95 for (
unsigned face_index=0; face_index<this->
mElements[elem_index]->GetNumFaces(); face_index++)
100 if (faces_counted.find(p_face->GetIndex()) == faces_counted.end())
102 this->
mFaces.push_back(p_face);
103 faces_counted.insert(p_face->GetIndex());
110 for (
unsigned index=0; index<this->
mElements.size(); index++)
113 for (
unsigned node_index=0; node_index<p_temp_vertex_element->
GetNumNodes(); node_index++)
123 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
139 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
145 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
151 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
157 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
163 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
169 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
175 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
181 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
187 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
195 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
201 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
207 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
213 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
219 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
223 if (protorosetteFormationProbability < 0.0)
225 EXCEPTION(
"Attempting to assign a negative probability.");
227 if (protorosetteFormationProbability > 1.0)
229 EXCEPTION(
"Attempting to assign a probability greater than one.");
236 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
240 if (protorosetteResolutionProbabilityPerTimestep < 0.0)
242 EXCEPTION(
"Attempting to assign a negative probability.");
244 if (protorosetteResolutionProbabilityPerTimestep > 1.0)
246 EXCEPTION(
"Attempting to assign a probability greater than one.");
253 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
257 if (rosetteResolutionProbabilityPerTimestep < 0.0)
259 EXCEPTION(
"Attempting to assign a negative probability.");
261 if (rosetteResolutionProbabilityPerTimestep > 1.0)
263 EXCEPTION(
"Attempting to assign a probability greater than one.");
270 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
276 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
285 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
291 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
297 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
303 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
309 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
315 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
321 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
327 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
333 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
339 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
345 this->
mNodes.push_back(pNewNode);
352 delete this->
mNodes[index];
353 this->
mNodes[index] = pNewNode;
358 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
361 unsigned new_element_index = pNewElement->
GetIndex();
363 if (new_element_index == this->
mElements.size())
369 this->
mElements[new_element_index] = pNewElement;
375 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
378 this->
mNodes[nodeIndex]->SetPoint(point);
381 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
383 c_vector<double, SPACE_DIM> axisOfDivision,
384 bool placeOriginalElementBelow)
386 assert(SPACE_DIM == 2);
387 assert(ELEMENT_DIM == SPACE_DIM);
393 c_vector<double, SPACE_DIM> perp_axis;
394 perp_axis(0) = -axisOfDivision(1);
395 perp_axis(1) = axisOfDivision(0);
403 std::vector<unsigned> intersecting_nodes;
405 for (
unsigned i=0; i<num_nodes; i++)
408 if (is_current_node_on_left != is_next_node_on_left)
410 intersecting_nodes.push_back(i);
412 is_current_node_on_left = is_next_node_on_left;
416 if (intersecting_nodes.size() != 2)
418 EXCEPTION(
"Cannot proceed with element division: the given axis of division does not cross two edges of the element");
421 std::vector<unsigned> division_node_global_indices;
422 unsigned nodes_added = 0;
425 for (
unsigned i=0; i<intersecting_nodes.size(); i++)
441 c_vector<double, SPACE_DIM> position_a = p_node_A->
rGetLocation();
442 c_vector<double, SPACE_DIM> position_b = p_node_B->
rGetLocation();
443 c_vector<double, SPACE_DIM> a_to_b = this->
GetVectorFromAtoB(position_a, position_b);
445 c_vector<double, SPACE_DIM> intersection;
449 WARNING(
"Edge is too small for normal division; putting node in the middle of a and b. There may be T1 swaps straight away.");
451 intersection = position_a + 0.5*a_to_b;
456 double determinant = a_to_b[0]*axisOfDivision[1] - a_to_b[1]*axisOfDivision[0];
459 c_vector<double, SPACE_DIM> moved_centroid;
462 double alpha = (moved_centroid[0]*a_to_b[1] - position_a[0]*a_to_b[1]
463 -moved_centroid[1]*a_to_b[0] + position_a[1]*a_to_b[0])/determinant;
465 intersection = moved_centroid + alpha*axisOfDivision;
471 c_vector<double, SPACE_DIM> a_to_intersection = this->
GetVectorFromAtoB(position_a, intersection);
472 if (norm_2(a_to_intersection) < mCellRearrangementThreshold)
477 c_vector<double, SPACE_DIM> b_to_intersection = this->
GetVectorFromAtoB(position_b, intersection);
478 if (norm_2(b_to_intersection) < mCellRearrangementThreshold)
480 assert(norm_2(a_to_intersection) > mCellRearrangementThreshold);
493 bool is_boundary =
false;
496 if (elems_containing_node_A.size() != 2 ||
497 elems_containing_node_B.size() != 2 ||
498 elems_containing_node_A != elems_containing_node_B)
505 unsigned new_node_global_index = this->
AddNode(
new Node<SPACE_DIM>(0, is_boundary, intersection[0], intersection[1]));
511 std::set<unsigned> shared_elements;
512 std::set_intersection(elems_containing_node_A.begin(),
513 elems_containing_node_A.end(),
514 elems_containing_node_B.begin(),
515 elems_containing_node_B.end(),
516 std::inserter(shared_elements, shared_elements.begin()));
519 unsigned node_A_index = p_node_A->
GetIndex();
520 unsigned node_B_index = p_node_B->
GetIndex();
521 for (std::set<unsigned>::iterator iter = shared_elements.begin();
522 iter != shared_elements.end();
531 unsigned index = local_indexB;
534 if (local_indexB > local_indexA)
536 index = local_indexA;
539 if ((local_indexA == 0) && (local_indexB == p_element->
GetNumNodes()-1))
541 index = local_indexB;
544 else if ((local_indexB == 0) && (local_indexA == p_element->
GetNumNodes()-1))
547 index = local_indexA;
551 this->
GetElement(*iter)->AddNode(this->GetNode(new_node_global_index), index);
555 division_node_global_indices.push_back(new_node_global_index);
562 placeOriginalElementBelow);
564 return new_element_index;
567 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
569 bool placeOriginalElementBelow)
571 assert(SPACE_DIM == 2);
572 assert(ELEMENT_DIM == SPACE_DIM);
577 return new_element_index;
580 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
584 bool placeOriginalElementBelow)
586 assert(SPACE_DIM == 2);
587 assert(ELEMENT_DIM == SPACE_DIM);
590 assert(nodeBIndex != nodeAIndex);
591 unsigned node1_index = (nodeAIndex < nodeBIndex) ? nodeAIndex : nodeBIndex;
592 unsigned node2_index = (nodeAIndex < nodeBIndex) ? nodeBIndex : nodeAIndex;
598 std::vector<Node<SPACE_DIM>*> nodes_elem;
599 for (
unsigned i=0; i<num_nodes; i++)
601 nodes_elem.push_back(pElement->
GetNode(i));
605 unsigned new_element_index;
608 new_element_index = this->
mElements.size();
614 delete this->
mElements[new_element_index];
628 double height_midpoint_1 = 0.0;
629 double height_midpoint_2 = 0.0;
630 unsigned counter_1 = 0;
631 unsigned counter_2 = 0;
633 for (
unsigned i=0; i<num_nodes; i++)
635 if (i>=node1_index && i<=node2_index)
637 height_midpoint_1 += pElement->
GetNode(i)->rGetLocation()[1];
640 if (i<=node1_index || i>=node2_index)
642 height_midpoint_2 += pElement->
GetNode(i)->rGetLocation()[1];
646 height_midpoint_1 /= (
double)counter_1;
647 height_midpoint_2 /= (
double)counter_2;
649 for (
unsigned i=num_nodes; i>0; i--)
651 if (i-1 < node1_index || i-1 > node2_index)
653 if (height_midpoint_1 < height_midpoint_2)
655 if (placeOriginalElementBelow)
661 this->
mElements[new_element_index]->DeleteNode(i-1);
666 if (placeOriginalElementBelow)
668 this->
mElements[new_element_index]->DeleteNode(i-1);
676 else if (i-1 > node1_index && i-1 < node2_index)
678 if (height_midpoint_1 < height_midpoint_2)
680 if (placeOriginalElementBelow)
682 this->
mElements[new_element_index]->DeleteNode(i-1);
691 if (placeOriginalElementBelow)
697 this->
mElements[new_element_index]->DeleteNode(i-1);
703 return new_element_index;
706 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
709 assert(SPACE_DIM == 2);
712 for (
unsigned i=0; i<this->
mElements[index]->GetNumNodes(); i++)
730 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
733 this->
mNodes[index]->MarkAsDeleted();
737 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
745 std::set<unsigned> shared_elements;
746 std::set_intersection(elements_containing_nodeA.begin(),
747 elements_containing_nodeA.end(),
748 elements_containing_nodeB.begin(),
749 elements_containing_nodeB.end(),
750 std::inserter(shared_elements, shared_elements.begin()));
753 assert(!shared_elements.empty());
754 assert(shared_elements.size()<=2u);
757 bool is_boundary_node =
false;
758 if (shared_elements.size()==1u)
762 is_boundary_node =
true;
771 p_new_node->
SetPoint(new_node_position);
774 this->
mNodes.push_back(p_new_node);
777 unsigned node_A_index = pNodeA->
GetIndex();
778 unsigned node_B_index = pNodeB->
GetIndex();
779 for (std::set<unsigned>::iterator iter = shared_elements.begin();
780 iter != shared_elements.end();
789 unsigned index = local_indexB;
792 if (local_indexB > local_indexA)
794 index = local_indexA;
797 if ((local_indexA == 0) && (local_indexB == p_element->
GetNumNodes()-1))
799 index = local_indexB;
802 else if ((local_indexB == 0) && (local_indexA == p_element->
GetNumNodes()-1))
805 index = local_indexA;
809 this->
GetElement(*iter)->AddNode(p_new_node, index);
813 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
820 std::vector<VertexElement<ELEMENT_DIM, SPACE_DIM>*> live_elements;
821 for (
unsigned i=0; i<this->
mElements.size(); i++)
830 live_elements.push_back(this->
mElements[i]);
831 rElementMap.
SetNewIndex(i, (
unsigned)(live_elements.size()-1));
843 for (
unsigned i=0; i<this->
mElements.size(); i++)
852 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
856 std::vector<Node<SPACE_DIM>*> live_nodes;
857 for (
unsigned i=0; i<this->
mNodes.size(); i++)
859 if (this->
mNodes[i]->IsDeleted())
865 live_nodes.push_back(this->
mNodes[i]);
873 this->
mNodes = live_nodes;
877 for (
unsigned i=0; i<this->mNodes.size(); i++)
879 this->mNodes[i]->SetIndex(i);
883 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
887 assert(SPACE_DIM==2 || SPACE_DIM==3);
888 assert(ELEMENT_DIM == SPACE_DIM);
902 bool recheck_mesh =
true;
903 while (recheck_mesh ==
true)
911 while (recheck_mesh ==
true)
928 EXCEPTION(
"Remeshing has not been implemented in 3D (see #827 and #860)\n");
934 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
941 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
951 unsigned num_nodes = elem_iter->GetNumNodes();
952 assert(num_nodes > 0);
955 for (
unsigned local_index=0; local_index<num_nodes; local_index++)
959 unsigned local_index_plus_one = (local_index+1)%num_nodes;
960 Node<SPACE_DIM>* p_anticlockwise_node = elem_iter->GetNode(local_index_plus_one);
972 std::set<unsigned> shared_elements;
973 std::set_intersection(elements_of_node_a.begin(), elements_of_node_a.end(),
974 elements_of_node_b.begin(), elements_of_node_b.end(),
975 std::inserter(shared_elements, shared_elements.begin()));
977 bool both_nodes_share_triangular_element =
false;
978 for (std::set<unsigned>::const_iterator it = shared_elements.begin();
979 it != shared_elements.end();
982 if (this->
GetElement(*it)->GetNumNodes() <= 3)
984 both_nodes_share_triangular_element =
true;
990 if (!both_nodes_share_triangular_element)
1002 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1011 if (elem_iter->GetNumNodes() == 3)
1019 rElementMap.
SetDeleted(elem_iter->GetIndex());
1027 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1041 assert(!(node_iter->IsDeleted()));
1044 std::set<unsigned> first_neighbour_node_indices;
1046 auto first_neighbour_indices = node_iter->rGetContainingElementIndices();
1048 for (
auto elem_iter = first_neighbour_indices.begin();
1049 elem_iter != first_neighbour_indices.end();
1052 auto p_element = this->
GetElement(*elem_iter);
1054 for (
auto local_node_index = 0u;
1055 local_node_index < p_element->GetNumNodes();
1058 first_neighbour_node_indices.insert(p_element->GetNodeGlobalIndex(local_node_index));
1063 std::set<unsigned> all_neighbours;
1065 for (
auto second_node_iter = first_neighbour_node_indices.begin();
1066 second_node_iter != first_neighbour_node_indices.end();
1069 auto containing_element_indices =
1070 this->
GetNode(*second_node_iter)->rGetContainingElementIndices();
1071 all_neighbours.insert(containing_element_indices.begin(),
1072 containing_element_indices.end());
1077 std::set<unsigned> second_neighbour_indices;
1078 std::set_difference(
1079 all_neighbours.begin(), all_neighbours.end(),
1080 first_neighbour_indices.begin(), first_neighbour_indices.end(),
1081 std::inserter(second_neighbour_indices, second_neighbour_indices.begin()));
1084 for (
auto elem_iter = second_neighbour_indices.begin();
1085 elem_iter != second_neighbour_indices.end();
1088 unsigned elem_index = *elem_iter;
1091 assert(node_iter->rGetContainingElementIndices().count(elem_index) == 0);
1105 std::vector<unsigned> boundary_element_indices;
1106 std::vector< c_vector<double, SPACE_DIM> > boundary_element_centroids;
1111 if (elem_iter->IsElementOnBoundary())
1113 unsigned element_index = elem_iter->GetIndex();
1114 boundary_element_indices.push_back(element_index);
1126 if (node_iter->IsBoundaryNode())
1128 assert(!(node_iter->IsDeleted()));
1131 unsigned boundary_element_index = 0;
1132 for (std::vector<unsigned>::iterator elem_iter = boundary_element_indices.begin();
1133 elem_iter != boundary_element_indices.end();
1137 if (node_iter->rGetContainingElementIndices().count(*elem_iter) == 0)
1139 c_vector<double, SPACE_DIM> node_location = node_iter->rGetLocation();
1140 c_vector<double, SPACE_DIM> element_centroid = boundary_element_centroids[boundary_element_index];
1141 double node_element_distance = norm_2(this->
GetVectorFromAtoB(node_location, element_centroid));
1153 boundary_element_index +=1u;
1162 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1170 std::set<unsigned> all_indices, temp_union_set;
1171 std::set_union(nodeA_elem_indices.begin(), nodeA_elem_indices.end(),
1172 nodeB_elem_indices.begin(), nodeB_elem_indices.end(),
1173 std::inserter(temp_union_set, temp_union_set.begin()));
1174 all_indices.swap(temp_union_set);
1177 if ((nodeA_elem_indices.size()>3) || (nodeB_elem_indices.size()>3))
1198 switch (all_indices.size())
1219 if (nodeA_elem_indices.size()==2 && nodeB_elem_indices.size()==2)
1248 EXCEPTION(
"There is a non-boundary node contained only in two elements; something has gone wrong.");
1260 EXCEPTION(
"There are non-boundary nodes contained only in two elements; something has gone wrong.");
1286 if (nodeA_elem_indices.size()==1 || nodeB_elem_indices.size()==1)
1304 EXCEPTION(
"There is a boundary node contained in three elements something has gone wrong.");
1306 else if (nodeA_elem_indices.size()==2 && nodeB_elem_indices.size()==2)
1314 std::set<unsigned> element_A_not_B, temp_set;
1315 std::set_difference(all_indices.begin(), all_indices.end(), nodeB_elem_indices.begin(),
1316 nodeB_elem_indices.end(), std::inserter(temp_set, temp_set.begin()));
1317 element_A_not_B.swap(temp_set);
1320 assert(element_A_not_B.size() == 1);
1322 std::set<unsigned> element_B_not_A;
1323 std::set_difference(all_indices.begin(), all_indices.end(), nodeA_elem_indices.begin(),
1324 nodeA_elem_indices.end(), std::inserter(temp_set, temp_set.begin()));
1325 element_B_not_A.swap(temp_set);
1328 assert(element_B_not_A.size() == 1);
1333 unsigned local_index_1 = p_element_A_not_B->GetNodeLocalIndex(pNodeA->
GetIndex());
1334 unsigned next_node_1 = p_element_A_not_B->GetNodeGlobalIndex((local_index_1 + 1)%(p_element_A_not_B->GetNumNodes()));
1335 unsigned previous_node_1 = p_element_A_not_B->GetNodeGlobalIndex(
1336 (local_index_1 + p_element_A_not_B->GetNumNodes() - 1)%(p_element_A_not_B->GetNumNodes()));
1339 (local_index_2 + 1)%(p_element_B_not_A->
GetNumNodes()));
1343 if (next_node_1 == previous_node_2 || next_node_2 == previous_node_1)
1362 unsigned nodeC_index;
1363 if (next_node_1 == previous_node_2 && next_node_2 != previous_node_1)
1365 nodeC_index = next_node_1;
1367 else if (next_node_2 == previous_node_1 && next_node_1 != previous_node_2)
1369 nodeC_index = next_node_2;
1373 assert(next_node_1 == previous_node_2 && next_node_2 == previous_node_1);
1381 EXCEPTION(
"Triangular element next to triangular void, not implemented yet.");
1384 if (p_element_A_not_B->GetNumNodes() == 3u || p_element_B_not_A->
GetNumNodes() == 3u)
1393 EXCEPTION(
"Triangular element next to triangular void, not implemented yet.");
1420 assert ( (nodeA_elem_indices.size()==2 && nodeB_elem_indices.size()==3)
1421 || (nodeA_elem_indices.size()==3 && nodeB_elem_indices.size()==2) );
1453 EXCEPTION(
"There are non-boundary nodes contained only in two elements; something has gone wrong.");
1492 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1503 unsigned node_B_index = pNodeB->
GetIndex();
1504 for (std::set<unsigned>::const_iterator it = nodeB_elem_indices.begin(); it != nodeB_elem_indices.end(); ++it)
1507 unsigned node_B_local_index = this->
mElements[*it]->GetNodeLocalIndex(node_B_index);
1508 assert(node_B_local_index < UINT_MAX);
1514 if (nodeA_elem_indices.count(*it) != 0)
1516 this->
mElements[*it]->DeleteNode(node_B_local_index);
1521 this->
mElements[*it]->UpdateNode(node_B_local_index, pNodeA);
1525 assert(!(this->
mNodes[node_B_index]->IsDeleted()));
1526 this->
mNodes[node_B_index]->MarkAsDeleted();
1530 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1533 std::set<unsigned>& rElementsContainingNodes)
1538 c_vector<double, SPACE_DIM> nodeA_location = pNodeA->
rGetLocation();
1539 c_vector<double, SPACE_DIM> nodeB_location = pNodeB->
rGetLocation();
1540 c_vector<double, SPACE_DIM> vector_AB = this->
GetVectorFromAtoB(nodeA_location, nodeB_location);
1543 double distance_AB = norm_2(vector_AB);
1544 if (distance_AB < 1e-10)
1546 EXCEPTION(
"Nodes are too close together, this shouldn't happen");
1578 c_vector<double, SPACE_DIM> vector_CD;
1579 vector_CD(0) = -vector_AB(1) * distance_between_nodes_CD / distance_AB;
1580 vector_CD(1) = vector_AB(0) * distance_between_nodes_CD / distance_AB;
1582 c_vector<double, SPACE_DIM> nodeC_location = nodeA_location + 0.5*vector_AB - 0.5*vector_CD;
1583 c_vector<double, SPACE_DIM> nodeD_location = nodeC_location + vector_CD;
1592 for (std::set<unsigned>::const_iterator it = rElementsContainingNodes.begin();
1593 it != rElementsContainingNodes.end();
1597 if (nodeA_elem_indices.find(*it) == nodeA_elem_indices.end())
1600 unsigned nodeB_local_index = this->
mElements[*it]->GetNodeLocalIndex(pNodeB->
GetIndex());
1601 assert(nodeB_local_index < UINT_MAX);
1603 this->
mElements[*it]->AddNode(pNodeA, nodeB_local_index);
1605 else if (nodeB_elem_indices.find(*it) == nodeB_elem_indices.end())
1608 unsigned nodeA_local_index = this->
mElements[*it]->GetNodeLocalIndex(pNodeA->
GetIndex());
1609 assert(nodeA_local_index < UINT_MAX);
1611 this->
mElements[*it]->AddNode(pNodeB, nodeA_local_index);
1616 unsigned nodeA_local_index = this->
mElements[*it]->GetNodeLocalIndex(pNodeA->
GetIndex());
1617 unsigned nodeB_local_index = this->
mElements[*it]->GetNodeLocalIndex(pNodeB->
GetIndex());
1619 assert(nodeA_local_index < UINT_MAX);
1620 assert(nodeB_local_index < UINT_MAX);
1627 unsigned nodeB_local_index_plus_one = (nodeB_local_index + 1)%(this->
mElements[*it]->
GetNumNodes());
1629 if (nodeA_local_index == nodeB_local_index_plus_one)
1635 this->
mElements[*it]->DeleteNode(nodeB_local_index);
1644 this->
mElements[*it]->DeleteNode(nodeA_local_index);
1671 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1674 assert(SPACE_DIM == 2);
1675 assert(ELEMENT_DIM == SPACE_DIM);
1681 std::set<unsigned> elements_containing_intersecting_node;
1683 for (
unsigned node_local_index=0; node_local_index<num_nodes; node_local_index++)
1687 std::set<unsigned> node_elem_indices = this->
GetNode(node_global_index)->rGetContainingElementIndices();
1689 for (std::set<unsigned>::const_iterator elem_iter = node_elem_indices.begin();
1690 elem_iter != node_elem_indices.end();
1694 unsigned num_nodes_in_neighbouring_element = p_neighbouring_element->
GetNumNodes();
1697 for (
unsigned node_index_2 = 0; node_index_2 < num_nodes_in_neighbouring_element; node_index_2++)
1701 elements_containing_intersecting_node.insert(p_neighbouring_element->
GetIndex());
1709 assert(elements_containing_intersecting_node.size() >= 1);
1710 assert(all_elements_containing_intersecting_node.size() >= 1);
1724 unsigned node_A_index = pNode->
GetIndex();
1725 unsigned node_B_index = UINT_MAX;
1727 unsigned element_1_index = UINT_MAX;
1728 unsigned element_2_index = UINT_MAX;
1729 unsigned element_3_index = elementIndex;
1730 unsigned element_4_index = UINT_MAX;
1733 std::set<unsigned> intersecting_element;
1735 std::set_difference(all_elements_containing_intersecting_node.begin(), all_elements_containing_intersecting_node.end(),
1736 elements_containing_intersecting_node.begin(), elements_containing_intersecting_node.end(),
1737 std::inserter(intersecting_element, intersecting_element.begin()));
1739 if (intersecting_element.size() == 1)
1741 element_1_index = *(intersecting_element.begin());
1745 std::set<unsigned>::iterator iter = elements_containing_intersecting_node.begin();
1746 unsigned element_a_index = *(iter);
1750 unsigned element_b_index = UINT_MAX;
1752 if (elements_containing_intersecting_node.size() == 2)
1755 element_b_index = *(iter);
1756 p_element_b = this->
GetElement(element_b_index);
1762 EXCEPTION(
"A triangular element has become concave. " 1763 "You need to rerun the simulation with a smaller time step to prevent this.");
1767 unsigned node_A_local_index_in_a = p_element_a->
GetNodeLocalIndex(node_A_index);
1769 unsigned node_before_A_in_a = (node_A_local_index_in_a + p_element_a->
GetNumNodes() - 1) % p_element_a->
GetNumNodes();
1770 unsigned node_after_A_in_a = (node_A_local_index_in_a + 1) % p_element_a->
GetNumNodes();
1772 unsigned global_node_before_A_in_a = p_element_a->
GetNodeGlobalIndex(node_before_A_in_a);
1773 unsigned global_node_after_A_in_a = p_element_a->
GetNodeGlobalIndex(node_after_A_in_a);
1775 for (
unsigned node_index = 0; node_index < num_nodes; ++node_index)
1779 node_B_index = global_node_before_A_in_a;
1784 node_B_index = global_node_after_A_in_a;
1793 if (node_B_index == UINT_MAX)
1795 EXCEPTION(
"Intersection cannot be resolved without splitting the element into two new elements.");
1799 c_vector<double, SPACE_DIM> nodeA_location = pNode->
rGetLocation();
1800 c_vector<double, SPACE_DIM> nodeB_location = this->
GetNode(node_B_index)->rGetLocation();
1801 c_vector<double, SPACE_DIM> vector_AB = this->
GetVectorFromAtoB(nodeA_location, nodeB_location);
1805 unsigned node_B_local_index_in_a = p_element_a->
GetNodeLocalIndex(node_B_index);
1807 if ((node_B_local_index_in_a+1)%p_element_a->
GetNumNodes() == node_A_local_index_in_a)
1810 if (element_b_index != UINT_MAX)
1812 assert(p_element_b !=
nullptr);
1819 element_2_index = element_a_index;
1820 element_4_index = element_b_index;
1825 if (element_b_index != UINT_MAX)
1827 assert(p_element_b !=
nullptr);
1834 element_2_index = element_b_index;
1835 element_4_index = element_a_index;
1841 unsigned node_A_local_index_in_1 = UINT_MAX;
1842 if (element_1_index != UINT_MAX)
1844 node_A_local_index_in_1 = this->
GetElement(element_1_index)->GetNodeLocalIndex(node_A_index);
1847 unsigned node_A_local_index_in_2 = UINT_MAX;
1848 unsigned node_B_local_index_in_2 = UINT_MAX;
1850 if (element_2_index != UINT_MAX)
1852 node_A_local_index_in_2 = this->
GetElement(element_2_index)->GetNodeLocalIndex(node_A_index);
1853 node_B_local_index_in_2 = this->
GetElement(element_2_index)->GetNodeLocalIndex(node_B_index);
1856 unsigned node_B_local_index_in_3 = this->
GetElement(elementIndex)->GetNodeLocalIndex(node_B_index);
1858 unsigned node_A_local_index_in_4 = UINT_MAX;
1859 unsigned node_B_local_index_in_4 = UINT_MAX;
1861 if (element_4_index != UINT_MAX)
1863 node_A_local_index_in_4 = this->
GetElement(element_4_index)->GetNodeLocalIndex(node_A_index);
1864 node_B_local_index_in_4 = this->
GetElement(element_4_index)->GetNodeLocalIndex(node_B_index);
1868 if (intersected_edge==node_B_local_index_in_3)
1877 if (element_1_index != UINT_MAX)
1879 assert(node_A_local_index_in_1 != UINT_MAX);
1880 this->
mElements[element_1_index]->AddNode(this->
mNodes[node_B_index], node_A_local_index_in_1);
1882 this->
mElements[element_3_index]->AddNode(this->
mNodes[node_A_index], node_B_local_index_in_3);
1884 if (element_2_index != UINT_MAX)
1886 assert(node_B_local_index_in_2 != UINT_MAX);
1887 this->
mElements[element_2_index]->DeleteNode(node_B_local_index_in_2);
1889 if (element_4_index != UINT_MAX)
1891 assert(node_A_local_index_in_4 != UINT_MAX);
1892 this->
mElements[element_4_index]->DeleteNode(node_A_local_index_in_4);
1897 assert((intersected_edge+1)%num_nodes==node_B_local_index_in_3);
1900 if (element_1_index != UINT_MAX)
1902 assert(node_A_local_index_in_1 != UINT_MAX);
1903 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();
1904 this->
mElements[element_1_index]->AddNode(this->
mNodes[node_B_index], node_before_A_in_1);
1907 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();
1908 this->
mElements[element_3_index]->AddNode(this->
mNodes[node_A_index], node_before_B_in_3);
1911 if (element_2_index != UINT_MAX)
1913 assert(node_A_local_index_in_2 != UINT_MAX);
1914 this->
mElements[element_2_index]->DeleteNode(node_A_local_index_in_2);
1916 if (element_4_index != UINT_MAX)
1918 assert(node_B_local_index_in_4 != UINT_MAX);
1919 this->
mElements[element_4_index]->DeleteNode(node_B_local_index_in_4);
1924 if (all_elements_containing_intersecting_node.size() == 2)
1927 if (elements_containing_intersecting_node.size() == 2)
1929 assert(this->
mNodes[node_A_index]->IsBoundaryNode() ==
true);
1930 assert(this->
mNodes[node_B_index]->IsBoundaryNode() ==
false);
1931 this->
mNodes[node_B_index]->SetAsBoundaryNode(
true);
1933 else if (elements_containing_intersecting_node.size() == 1)
1935 assert(this->
mNodes[node_A_index]->IsBoundaryNode() ==
true);
1936 assert(this->
mNodes[node_B_index]->IsBoundaryNode() ==
true);
1938 if (element_2_index == UINT_MAX)
1940 if (intersected_edge==node_B_local_index_in_3)
1942 this->
mNodes[node_B_index]->SetAsBoundaryNode(
false);
1946 this->
mNodes[node_A_index]->SetAsBoundaryNode(
false);
1950 if (element_4_index == UINT_MAX)
1952 if (intersected_edge==node_B_local_index_in_3)
1954 this->
mNodes[node_A_index]->SetAsBoundaryNode(
false);
1958 this->
mNodes[node_B_index]->SetAsBoundaryNode(
false);
1970 else if (all_elements_containing_intersecting_node.size() == 1)
1972 if (elements_containing_intersecting_node.size() == 1)
1974 assert(this->
mNodes[node_A_index]->IsBoundaryNode() ==
true);
1975 assert(this->
mNodes[node_B_index]->IsBoundaryNode() ==
true);
1985 assert(this->
mNodes[node_A_index]->IsBoundaryNode() ==
false);
1986 assert(this->
mNodes[node_B_index]->IsBoundaryNode() ==
false);
1991 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1998 c_vector<double, SPACE_DIM> new_node_location;
2009 rElement.
GetNode(0)->MarkAsDeleted();
2010 rElement.
GetNode(1)->MarkAsDeleted();
2011 rElement.
GetNode(2)->MarkAsDeleted();
2020 bool is_node_on_boundary =
false;
2021 for (
unsigned i=0; i<3; i++)
2023 if (rElement.
GetNode(i)->IsBoundaryNode())
2025 is_node_on_boundary =
true;
2033 for (
unsigned i=0; i<3; i++)
2038 containing_elements.erase(rElement.
GetIndex());
2041 for (std::set<unsigned>::iterator elem_iter = containing_elements.begin(); elem_iter != containing_elements.end(); ++elem_iter)
2048 EXCEPTION(
"One of the neighbours of a small triangular element is also a triangle - dealing with this has not been implemented yet");
2068 rElement.
GetNode(0)->MarkAsDeleted();
2069 rElement.
GetNode(1)->MarkAsDeleted();
2070 rElement.
GetNode(2)->MarkAsDeleted();
2076 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
2079 assert(SPACE_DIM == 2);
2080 assert(ELEMENT_DIM == SPACE_DIM);
2091 c_vector<double, SPACE_DIM> node_location;
2100 unsigned vertexB_index = p_element->
GetNodeGlobalIndex((node_A_local_index+1)%num_nodes);
2103 if (!this->
mNodes[vertexA_index]->IsBoundaryNode() || !this->
mNodes[vertexB_index]->IsBoundaryNode())
2105 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.");
2109 c_vector<double, SPACE_DIM> vertexA = p_element->
GetNodeLocation(node_A_local_index);
2110 c_vector<double, SPACE_DIM> vertexB = p_element->
GetNodeLocation((node_A_local_index+1)%num_nodes);
2111 c_vector<double, SPACE_DIM> vector_a_to_point = this->
GetVectorFromAtoB(vertexA, node_location);
2113 c_vector<double, SPACE_DIM> vector_a_to_b = this->
GetVectorFromAtoB(vertexA, vertexB);
2115 c_vector<double, SPACE_DIM> edge_ab_unit_vector = vector_a_to_b/norm_2(vector_a_to_b);
2116 c_vector<double, SPACE_DIM> intersection = vertexA + edge_ab_unit_vector*inner_prod(vector_a_to_point, edge_ab_unit_vector);
2127 unsigned intersecting_element_index = *elements_containing_intersecting_node.begin();
2137 if (next_node == vertexA_index || previous_node == vertexA_index || next_node == vertexB_index || previous_node == vertexB_index)
2139 unsigned common_vertex_index;
2141 if (next_node == vertexA_index || previous_node == vertexA_index)
2143 common_vertex_index = vertexA_index;
2147 common_vertex_index = vertexB_index;
2150 assert(this->
mNodes[common_vertex_index]->GetNumContainingElements()>1);
2152 std::set<unsigned> elements_containing_common_vertex = this->
mNodes[common_vertex_index]->rGetContainingElementIndices();
2153 std::set<unsigned>::const_iterator it = elements_containing_common_vertex.begin();
2159 unsigned num_common_vertices = 0;
2160 std::vector<unsigned> common_vertex_indices;
2161 for (
unsigned i=0; i<p_element_common_1->
GetNumNodes(); i++)
2163 for (
unsigned j=0; j<p_element_common_2->
GetNumNodes(); j++)
2167 num_common_vertices++;
2173 if (num_common_vertices == 1 || this->
mNodes[common_vertex_index]->GetNumContainingElements() > 2)
2195 this->
GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2200 else if (num_common_vertices == 2)
2205 if ((common_vertex_indices[0]==vertexA_index && common_vertex_indices[1]==vertexB_index) ||
2206 (common_vertex_indices[1]==vertexA_index && common_vertex_indices[0]==vertexB_index))
2224 unsigned p_node_local_index = this->
2226 this->
GetElement(intersecting_element_index)->DeleteNode(p_node_local_index);
2257 this->
GetElement(elementIndex)->ReplaceNode(this->
mNodes[common_vertex_index], pNode);
2260 unsigned common_vertex_local_index = this->
GetElement(intersecting_element_index)->GetNodeLocalIndex(common_vertex_index);
2261 this->
GetElement(intersecting_element_index)->DeleteNode(common_vertex_local_index);
2262 assert(this->
mNodes[common_vertex_index]->GetNumContainingElements() == 0);
2264 this->
mNodes[common_vertex_index]->MarkAsDeleted();
2271 else if (num_common_vertices == 4)
2289 this->
GetElement(elementIndex)->DeleteNode(node_A_local_index);
2290 unsigned node_B_local_index = this->
2291 GetElement(elementIndex)->GetNodeLocalIndex(vertexB_index);
2292 this->
GetElement(elementIndex)->DeleteNode(node_B_local_index);
2295 unsigned node_A_local_index_intersecting_element = this->
2296 GetElement(intersecting_element_index)->GetNodeLocalIndex(vertexA_index);
2297 this->
GetElement(intersecting_element_index)->DeleteNode(node_A_local_index_intersecting_element);
2298 unsigned node_B_local_index_intersecting_element = this->
2299 GetElement(intersecting_element_index)->GetNodeLocalIndex(vertexB_index);
2300 this->
GetElement(intersecting_element_index)->DeleteNode(node_B_local_index_intersecting_element);
2303 unsigned p_node_local_index = this->
2305 this->
GetElement(intersecting_element_index)->DeleteNode(p_node_local_index);
2310 this->
mNodes[vertexA_index]->MarkAsDeleted();
2312 this->
mNodes[vertexB_index]->MarkAsDeleted();
2341 c_vector<double, SPACE_DIM> new_node_location;
2345 unsigned new_node_global_index = this->
AddNode(
new Node<SPACE_DIM>(0,
true, new_node_location[0], new_node_location[1]));
2348 this->
GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2349 this->
GetElement(elementIndex)->AddNode(this->
mNodes[new_node_global_index], node_A_local_index);
2352 this->
GetElement(intersecting_element_index)->AddNode(this->
mNodes[new_node_global_index], this->
GetElement(intersecting_element_index)->GetNodeLocalIndex(pNode->
GetIndex()));
2356 assert(this->
mNodes[new_node_global_index]->GetNumContainingElements() == 2);
2362 std::set<unsigned>::const_iterator it = elements_containing_intersecting_node.begin();
2365 unsigned num_nodes_elem_1 = p_element_1->
GetNumNodes();
2369 unsigned num_nodes_elem_2 = p_element_2->
GetNumNodes();
2371 unsigned node_global_index = pNode->
GetIndex();
2374 unsigned next_node_1 = p_element_1->
GetNodeGlobalIndex((local_index_1 + 1)%num_nodes_elem_1);
2375 unsigned previous_node_1 = p_element_1->
GetNodeGlobalIndex((local_index_1 + num_nodes_elem_1 - 1)%num_nodes_elem_1);
2378 unsigned next_node_2 = p_element_2->
GetNodeGlobalIndex((local_index_2 + 1)%num_nodes_elem_2);
2379 unsigned previous_node_2 = p_element_2->
GetNodeGlobalIndex((local_index_2 + num_nodes_elem_2 - 1)%num_nodes_elem_2);
2382 if ((next_node_1 == vertexA_index || previous_node_1 == vertexA_index || next_node_2 == vertexA_index || previous_node_2 == vertexA_index) &&
2383 (next_node_1 == vertexB_index || previous_node_1 == vertexB_index || next_node_2 == vertexB_index || previous_node_2 == vertexB_index))
2404 assert(this->
mNodes[vertexA_index]->IsBoundaryNode());
2405 assert(this->
mNodes[vertexB_index]->IsBoundaryNode());
2412 this->
GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2415 std::set<unsigned> elements_containing_vertex_A = this->
mNodes[vertexA_index]->rGetContainingElementIndices();
2416 for (std::set<unsigned>::const_iterator iter = elements_containing_vertex_A.begin();
2417 iter != elements_containing_vertex_A.end();
2420 this->
GetElement(*iter)->DeleteNode(this->GetElement(*iter)->GetNodeLocalIndex(vertexA_index));
2424 assert(this->
mNodes[vertexA_index]->GetNumContainingElements() == 0);
2425 this->
mNodes[vertexA_index]->MarkAsDeleted();
2429 std::set<unsigned> elements_containing_vertex_B = this->
mNodes[vertexB_index]->rGetContainingElementIndices();
2430 for (std::set<unsigned>::const_iterator iter = elements_containing_vertex_B.begin();
2431 iter != elements_containing_vertex_B.end();
2434 this->
GetElement(*iter)->DeleteNode(this->GetElement(*iter)->GetNodeLocalIndex(vertexB_index));
2438 assert(this->
mNodes[vertexB_index]->GetNumContainingElements()==0);
2439 this->
mNodes[vertexB_index]->MarkAsDeleted();
2444 if (next_node_1 == vertexA_index || previous_node_1 == vertexA_index || next_node_2 == vertexA_index || previous_node_2 == vertexA_index)
2448 assert(this->
mNodes[vertexA_index]->GetNumContainingElements() > 1);
2450 std::set<unsigned> elements_containing_vertex_A = this->
mNodes[vertexA_index]->rGetContainingElementIndices();
2451 std::set<unsigned>::const_iterator iter = elements_containing_vertex_A.begin();
2457 unsigned num_common_vertices = 0;
2458 for (
unsigned i=0; i<p_element_common_1->
GetNumNodes(); i++)
2460 for (
unsigned j=0; j<p_element_common_2->
GetNumNodes(); j++)
2464 num_common_vertices++;
2469 if (num_common_vertices == 1 || this->
mNodes[vertexA_index]->GetNumContainingElements() > 2)
2493 c_vector<double, SPACE_DIM> new_node_location;
2497 unsigned new_node_global_index = this->
AddNode(
new Node<SPACE_DIM>(0,
true, new_node_location[0], new_node_location[1]));
2500 this->
GetElement(elementIndex)->AddNode(this->
mNodes[new_node_global_index], node_A_local_index);
2501 this->
GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2504 if (next_node_1 == previous_node_2)
2510 assert(next_node_2 == previous_node_1);
2517 assert(this->
mNodes[new_node_global_index]->GetNumContainingElements() == 2);
2519 else if (num_common_vertices == 2)
2544 c_vector<double, SPACE_DIM> new_node_location;
2548 unsigned new_node_global_index = this->
AddNode(
new Node<SPACE_DIM>(0,
true, new_node_location[0], new_node_location[1]));
2551 this->
GetElement(elementIndex)->AddNode(this->
mNodes[new_node_global_index], node_A_local_index);
2552 this->
GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2555 if (next_node_1 == previous_node_2)
2561 assert(next_node_2 == previous_node_1);
2569 assert(this->
mNodes[vertexA_index]->GetNumContainingElements()==0);
2571 this->
mNodes[vertexA_index]->MarkAsDeleted();
2576 assert(this->
mNodes[new_node_global_index]->GetNumContainingElements() == 2);
2584 else if (next_node_1 == vertexB_index || previous_node_1 == vertexB_index || next_node_2 == vertexB_index || previous_node_2 == vertexB_index)
2588 assert(this->
mNodes[vertexB_index]->GetNumContainingElements()>1);
2590 std::set<unsigned> elements_containing_vertex_B = this->
mNodes[vertexB_index]->rGetContainingElementIndices();
2591 std::set<unsigned>::const_iterator iter = elements_containing_vertex_B.begin();
2597 unsigned num_common_vertices = 0;
2598 for (
unsigned i=0; i<p_element_common_1->
GetNumNodes(); i++)
2600 for (
unsigned j=0; j<p_element_common_2->
GetNumNodes(); j++)
2604 num_common_vertices++;
2609 if (num_common_vertices == 1 || this->
mNodes[vertexB_index]->GetNumContainingElements() > 2)
2633 c_vector<double, SPACE_DIM> new_node_location;
2637 unsigned new_node_global_index = this->
AddNode(
new Node<SPACE_DIM>(0,
true, new_node_location[0], new_node_location[1]));
2640 this->
GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2641 this->
GetElement(elementIndex)->AddNode(this->
mNodes[new_node_global_index], node_A_local_index);
2644 if (next_node_1 == previous_node_2)
2646 p_element_2->
AddNode(this->
mNodes[new_node_global_index], local_index_2);
2650 assert(next_node_2 == previous_node_1);
2651 p_element_1->
AddNode(this->
mNodes[new_node_global_index], local_index_1);
2656 assert(this->
mNodes[new_node_global_index]->GetNumContainingElements() == 2);
2658 else if (num_common_vertices == 2)
2683 c_vector<double, SPACE_DIM> new_node_location;
2687 unsigned new_node_global_index = this->
AddNode(
new Node<SPACE_DIM>(0,
true, new_node_location[0], new_node_location[1]));
2690 this->
GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2691 this->
GetElement(elementIndex)->AddNode(this->
mNodes[new_node_global_index], node_A_local_index);
2694 if (next_node_1 == previous_node_2)
2696 p_element_2->
AddNode(this->
mNodes[new_node_global_index], local_index_2);
2700 assert(next_node_2 == previous_node_1);
2701 p_element_1->
AddNode(this->
mNodes[new_node_global_index], local_index_1);
2708 assert(this->
mNodes[vertexB_index]->GetNumContainingElements()==0);
2710 this->
mNodes[vertexB_index]->MarkAsDeleted();
2715 assert(this->
mNodes[new_node_global_index]->GetNumContainingElements() == 2);
2743 c_vector<double, SPACE_DIM> new_node_1_location;
2745 c_vector<double, SPACE_DIM> new_node_2_location;
2749 unsigned new_node_1_global_index = this->
AddNode(
new Node<SPACE_DIM>(0,
true, new_node_1_location[0], new_node_1_location[1]));
2750 unsigned new_node_2_global_index = this->
AddNode(
new Node<SPACE_DIM>(0,
true, new_node_2_location[0], new_node_2_location[1]));
2753 this->
GetElement(elementIndex)->AddNode(this->
mNodes[new_node_2_global_index], node_A_local_index);
2754 this->
GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2755 this->
GetElement(elementIndex)->AddNode(this->
mNodes[new_node_1_global_index], node_A_local_index);
2758 if (next_node_1 == previous_node_2)
2761 p_element_2->
AddNode(this->
mNodes[new_node_1_global_index], local_index_2);
2765 assert(next_node_2 == previous_node_1);
2767 p_element_1->
AddNode(this->
mNodes[new_node_1_global_index], local_index_1);
2773 assert(this->
mNodes[new_node_1_global_index]->GetNumContainingElements() == 2);
2774 assert(this->
mNodes[new_node_2_global_index]->GetNumContainingElements() == 2);
2780 EXCEPTION(
"Trying to merge a node, contained in more than 2 elements, into another element, this is not possible with the vertex mesh.");
2784 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
2788 c_vector<double, SPACE_DIM> nodes_midpoint = pNodeA->
rGetLocation()
2803 p_merged_node = pNodeA;
2810 p_merged_node = pNodeC;
2822 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
2828 if ((node_a_rank > 3) && (node_b_rank > 3))
2831 EXCEPTION(
"Both nodes involved in a swap event are contained in more than three elements");
2835 assert(node_a_rank > 3 || node_b_rank > 3);
2841 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
2849 unsigned node_a_index = pNodeA->
GetIndex();
2850 unsigned node_b_index = pNodeB->
GetIndex();
2855 unsigned lo_rank_index = (node_a_rank < node_b_rank) ? node_a_index : node_b_index;
2856 unsigned hi_rank_index = (node_a_rank < node_b_rank) ? node_b_index : node_a_index;
2892 for (std::set<unsigned>::const_iterator it = lo_rank_elem_indices.begin();
2893 it != lo_rank_elem_indices.end();
2897 unsigned lo_rank_local_index = this->
mElements[*it]->GetNodeLocalIndex(lo_rank_index);
2898 assert(lo_rank_local_index < UINT_MAX);
2910 if (hi_rank_elem_indices.count(*it) > 0)
2913 this->
mElements[*it]->DeleteNode(lo_rank_local_index);
2918 this->
mElements[*it]->UpdateNode(lo_rank_local_index, p_hi_rank_node);
2923 assert(!(this->
mNodes[lo_rank_index]->IsDeleted()));
2924 this->
mNodes[lo_rank_index]->MarkAsDeleted();
2928 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
2941 std::set<unsigned>::const_iterator elem_index_iter(protorosette_node_containing_elem_indices.begin());
2942 advance(elem_index_iter, random_elem_increment);
2975 unsigned elem_a_idx = *elem_index_iter;
2976 unsigned elem_b_idx = UINT_MAX;
2977 unsigned elem_c_idx = UINT_MAX;
2978 unsigned elem_d_idx = UINT_MAX;
2984 unsigned num_nodes_elem_a = p_elem_a->
GetNumNodes();
2985 unsigned protorosette_node_global_idx = pProtorosetteNode->
GetIndex();
2986 unsigned protorosette_node_local_idx = p_elem_a->
GetNodeLocalIndex(protorosette_node_global_idx);
2989 unsigned prev_node_global_idx = p_elem_a->
GetNodeGlobalIndex((protorosette_node_local_idx + num_nodes_elem_a - 1) % num_nodes_elem_a);
2990 unsigned next_node_global_idx = p_elem_a->
GetNodeGlobalIndex((protorosette_node_local_idx + 1) % num_nodes_elem_a);
2999 std::set<unsigned> intersection_with_prev;
3000 std::set<unsigned> intersection_with_next;
3003 std::set_intersection(protorosette_node_containing_elem_indices.begin(),
3004 protorosette_node_containing_elem_indices.end(),
3005 prev_node_elem_indices.begin(),
3006 prev_node_elem_indices.end(),
3007 std::inserter(intersection_with_prev, intersection_with_prev.begin()));
3010 std::set_intersection(protorosette_node_containing_elem_indices.begin(),
3011 protorosette_node_containing_elem_indices.end(),
3012 next_node_elem_indices.begin(),
3013 next_node_elem_indices.end(),
3014 std::inserter(intersection_with_next, intersection_with_next.begin()));
3016 assert(intersection_with_prev.size() == 2);
3017 assert(intersection_with_next.size() == 2);
3020 if (*intersection_with_prev.begin() != elem_a_idx)
3022 elem_b_idx = *(intersection_with_prev.begin());
3026 elem_b_idx = *(++(intersection_with_prev.begin()));
3028 assert(elem_b_idx < UINT_MAX);
3031 if (*intersection_with_next.begin() != elem_a_idx)
3033 elem_d_idx = *(intersection_with_next.begin());
3037 elem_d_idx = *(++(intersection_with_next.begin()));
3039 assert(elem_d_idx < UINT_MAX);
3042 for (elem_index_iter = protorosette_node_containing_elem_indices.begin();
3043 elem_index_iter != protorosette_node_containing_elem_indices.end();
3046 if ((*elem_index_iter != elem_a_idx) && (*elem_index_iter != elem_b_idx) && (*elem_index_iter != elem_d_idx))
3048 elem_c_idx = *elem_index_iter;
3051 assert(elem_c_idx < UINT_MAX);
3075 node_to_elem_a_centre /= norm_2(node_to_elem_a_centre);
3078 node_to_elem_c_centre /= norm_2(node_to_elem_c_centre);
3081 c_vector<double, SPACE_DIM> new_location_of_protorosette_node = pProtorosetteNode->
rGetLocation() + (0.5 * swap_distance) * node_to_elem_a_centre;
3082 c_vector<double, SPACE_DIM> location_of_new_node = pProtorosetteNode->
rGetLocation() + (0.5 * swap_distance) * node_to_elem_c_centre;
3101 unsigned local_idx_elem_b = p_elem_b->
GetNodeLocalIndex(protorosette_node_global_idx);
3103 unsigned local_idx_elem_c = p_elem_c->
GetNodeLocalIndex(protorosette_node_global_idx);
3104 unsigned local_idx_elem_d = p_elem_d->
GetNodeLocalIndex(protorosette_node_global_idx);
3106 p_elem_b->
AddNode(p_new_node, local_idx_elem_b);
3107 p_elem_c->
AddNode(p_new_node, local_idx_elem_c);
3108 p_elem_d->
AddNode(p_new_node, local_idx_elem_d);
3114 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
3120 assert(rosette_rank > 4);
3129 std::set<unsigned>::const_iterator elem_index_iter(rosette_node_containing_elem_indices.begin());
3130 advance(elem_index_iter, random_elem_increment);
3175 unsigned elem_s_idx = *elem_index_iter;
3178 unsigned elem_n_idx = UINT_MAX;
3179 unsigned elem_p_idx = UINT_MAX;
3182 unsigned num_nodes_elem_s = p_elem_s->
GetNumNodes();
3183 unsigned rosette_node_global_idx = pRosetteNode->
GetIndex();
3184 unsigned rosette_node_local_idx = p_elem_s->
GetNodeLocalIndex(rosette_node_global_idx);
3187 unsigned prev_node_global_idx = p_elem_s->
GetNodeGlobalIndex((rosette_node_local_idx + num_nodes_elem_s - 1) % num_nodes_elem_s);
3188 unsigned next_node_global_idx = p_elem_s->
GetNodeGlobalIndex((rosette_node_local_idx + 1) % num_nodes_elem_s);
3197 std::set<unsigned> intersection_with_prev;
3198 std::set<unsigned> intersection_with_next;
3201 std::set_intersection(rosette_node_containing_elem_indices.begin(),
3202 rosette_node_containing_elem_indices.end(),
3203 prev_node_elem_indices.begin(),
3204 prev_node_elem_indices.end(),
3205 std::inserter(intersection_with_prev, intersection_with_prev.begin()));
3208 std::set_intersection(rosette_node_containing_elem_indices.begin(),
3209 rosette_node_containing_elem_indices.end(),
3210 next_node_elem_indices.begin(),
3211 next_node_elem_indices.end(),
3212 std::inserter(intersection_with_next, intersection_with_next.begin()));
3214 assert(intersection_with_prev.size() == 2);
3215 assert(intersection_with_next.size() == 2);
3218 if (*intersection_with_prev.begin() != elem_s_idx)
3220 elem_n_idx = *intersection_with_prev.begin();
3224 elem_n_idx = *(++(intersection_with_prev.begin()));
3226 assert(elem_n_idx < UINT_MAX);
3229 if (*intersection_with_next.begin() != elem_s_idx)
3231 elem_p_idx = *intersection_with_next.begin();
3235 elem_p_idx = *(++(intersection_with_next.begin()));
3237 assert(elem_p_idx < UINT_MAX);
3256 node_to_selected_elem /= norm_2(node_to_selected_elem);
3257 c_vector<double, 2> new_node_location = pRosetteNode->
rGetLocation() + (swap_distance * node_to_selected_elem);
3275 unsigned node_local_idx_in_elem_s = p_elem_s->
GetNodeLocalIndex(rosette_node_global_idx);
3276 p_elem_s->
AddNode(p_new_node, node_local_idx_in_elem_s);
3277 p_elem_s->
DeleteNode(node_local_idx_in_elem_s);
3280 unsigned node_local_idx_in_elem_n = p_elem_n->
GetNodeLocalIndex(rosette_node_global_idx);
3281 node_local_idx_in_elem_n = (node_local_idx_in_elem_n + p_elem_n->
GetNumNodes() - 1) % p_elem_n->
GetNumNodes();
3282 p_elem_n->
AddNode(p_new_node, node_local_idx_in_elem_n);
3285 unsigned node_local_idx_in_elem_p = p_elem_p->
GetNodeLocalIndex(rosette_node_global_idx);
3286 p_elem_p->
AddNode(p_new_node, node_local_idx_in_elem_p);
3289 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
3301 std::vector<Node<SPACE_DIM>* > protorosette_nodes;
3302 std::vector<Node<SPACE_DIM>* > rosette_nodes;
3306 for (
unsigned node_idx = 0 ; node_idx < num_nodes ; node_idx++)
3316 else if (node_rank == 4)
3321 protorosette_nodes.push_back(current_node);
3329 rosette_nodes.push_back(current_node);
3342 for (
unsigned node_idx = 0 ; node_idx < protorosette_nodes.size() ; node_idx++)
3355 for (
unsigned node_idx = 0 ; node_idx < rosette_nodes.size() ; node_idx++)
3368 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
3370 unsigned indexA,
unsigned indexB, c_vector<double,2> intersection)
3381 c_vector<double, SPACE_DIM> vertexA = this->
GetNode(indexA)->rGetLocation();
3382 c_vector<double, SPACE_DIM> vertexB = this->
GetNode(indexB)->rGetLocation();
3383 c_vector<double, SPACE_DIM> vector_a_to_b = this->
GetVectorFromAtoB(vertexA, vertexB);
3387 WARNING(
"Trying to merge a node onto an edge which is too small.");
3389 c_vector<double, SPACE_DIM> centre_a_and_b = vertexA + 0.5*vector_a_to_b;
3391 vertexA = centre_a_and_b - 2.0*
mCellRearrangementRatio*mCellRearrangementThreshold*vector_a_to_b/norm_2(vector_a_to_b);
3393 SetNode(indexA, vertex_A_point);
3395 vertexB = centre_a_and_b + 2.0*
mCellRearrangementRatio*mCellRearrangementThreshold*vector_a_to_b/norm_2(vector_a_to_b);
3397 SetNode(indexB, vertex_B_point);
3399 intersection = centre_a_and_b;
3404 c_vector<double,2> edge_ab_unit_vector = vector_a_to_b/norm_2(vector_a_to_b);
3423 return intersection;
unsigned DivideElement(VertexElement< ELEMENT_DIM, SPACE_DIM > *pElement, unsigned nodeAIndex, unsigned nodeBIndex, bool placeOriginalElementBelow=false)
void SetRosetteResolutionProbabilityPerTimestep(double rosetteResolutionProbabilityPerTimestep)
void PerformIntersectionSwap(Node< SPACE_DIM > *pNode, unsigned elementIndex)
void SetDistanceForT3SwapChecking(double distanceForT3SwapChecking)
unsigned GetNumAllElements() const
c_vector< double, 2 > WidenEdgeOrCorrectIntersectionLocationIfNecessary(unsigned indexA, unsigned indexB, c_vector< double, 2 > intersection)
std::vector< c_vector< double, SPACE_DIM > > GetLocationsOfIntersectionSwaps()
std::vector< c_vector< double, SPACE_DIM > > GetLocationsOfT3Swaps()
void RemoveDeletedNodesAndElements(VertexElementMap &rElementMap)
void SetPoint(ChastePoint< SPACE_DIM > point)
void PerformRosetteRankDecrease(Node< SPACE_DIM > *pRosetteNode)
std::vector< c_vector< double, SPACE_DIM > > mLocationsOfT3Swaps
double GetCellRearrangementRatio() const
unsigned DivideElementAlongGivenAxis(VertexElement< ELEMENT_DIM, SPACE_DIM > *pElement, c_vector< double, SPACE_DIM > axisOfDivision, bool placeOriginalElementBelow=false)
unsigned randMod(unsigned base)
virtual c_vector< double, SPACE_DIM > GetVectorFromAtoB(const c_vector< double, SPACE_DIM > &rLocationA, const c_vector< double, SPACE_DIM > &rLocationB)
void SetAsBoundaryNode(bool value=true)
bool CheckForT2Swaps(VertexElementMap &rElementMap)
std::vector< c_vector< double, SPACE_DIM > > GetLocationsOfT1Swaps()
unsigned GetNumContainingElements() const
unsigned DivideElementAlongShortAxis(VertexElement< ELEMENT_DIM, SPACE_DIM > *pElement, bool placeOriginalElementBelow=false)
void PerformNodeMerge(Node< SPACE_DIM > *pNodeA, Node< SPACE_DIM > *pNodeB)
virtual bool CheckForSwapsFromShortEdges()
void SetProtorosetteResolutionProbabilityPerTimestep(double protorosetteResolutionProbabilityPerTimestep)
double mDistanceForT3SwapChecking
void ClearLocationsOfIntersectionSwaps()
std::vector< VertexElement< ELEMENT_DIM - 1, SPACE_DIM > * > mFaces
#define EXCEPTION(message)
VertexElement< ELEMENT_DIM, SPACE_DIM > * GetElement(unsigned index) const
bool mCheckForInternalIntersections
unsigned AddNode(Node< SPACE_DIM > *pNewNode)
void ReplaceNode(Node< SPACE_DIM > *pOldNode, Node< SPACE_DIM > *pNewNode)
std::vector< unsigned > mDeletedNodeIndices
NodeIterator GetNodeIteratorEnd()
void PerformVoidRemoval(Node< SPACE_DIM > *pNodeA, Node< SPACE_DIM > *pNodeB, Node< SPACE_DIM > *pNodeC)
std::set< unsigned > & rGetContainingElementIndices()
double mRosetteResolutionProbabilityPerTimestep
void SetIndex(unsigned index)
unsigned GetIndex() const
std::vector< c_vector< double, SPACE_DIM > > mLocationsOfT1Swaps
c_vector< double, SPACE_DIM > mLastT2SwapLocation
unsigned GetNumNodes() const
unsigned GetNumElements() const
unsigned GetIndex() const
Node< SPACE_DIM > * GetNode(unsigned index) const
double mCellRearrangementRatio
c_vector< double, SPACE_DIM > GetPreviousEdgeGradientOfElementAtNode(VertexElement< ELEMENT_DIM, SPACE_DIM > *pElement, unsigned localIndex)
double mCellRearrangementThreshold
void ClearLocationsOfT1Swaps()
unsigned GetNodeLocalIndex(unsigned globalIndex) const
bool GetCheckForInternalIntersections() const
void SetCellRearrangementThreshold(double cellRearrangementThreshold)
double GetDistanceBetweenNodes(unsigned indexA, unsigned indexB)
unsigned GetNodeGlobalIndex(unsigned localIndex) const
const c_vector< double, SPACE_DIM > & rGetLocation() const
bool mMeshChangesDuringSimulation
void PerformT3Swap(Node< SPACE_DIM > *pNode, unsigned elementIndex)
void AddNode(Node< SPACE_DIM > *pNode, const unsigned &rIndex)
std::vector< Node< SPACE_DIM > * > mNodes
VertexElementIterator GetElementIteratorBegin(bool skipDeletedElements=true)
virtual void SetNode(unsigned nodeIndex, ChastePoint< SPACE_DIM > point)
double GetNodeLocation(unsigned localIndex, unsigned dimension) const
unsigned AddElement(VertexElement< ELEMENT_DIM, SPACE_DIM > *pNewElement)
void PerformProtorosetteResolution(Node< SPACE_DIM > *pProtorosetteNode)
bool CheckForIntersections()
void SetDeleted(unsigned index)
double mProtorosetteResolutionProbabilityPerTimestep
double GetDistanceForT3SwapChecking() const
virtual unsigned GetNumAllNodes() const
std::vector< c_vector< double, SPACE_DIM > > mLocationsOfIntersectionSwaps
void PerformRosetteRankIncrease(Node< SPACE_DIM > *pNodeA, Node< SPACE_DIM > *pNodeB)
double GetT2Threshold() const
double mProtorosetteFormationProbability
void DeleteNodePriorToReMesh(unsigned index)
void SetNewIndex(unsigned oldIndex, unsigned newIndex)
static RandomNumberGenerator * Instance()
double GetCellRearrangementThreshold() const
virtual double GetVolumeOfElement(unsigned index)
void ClearLocationsOfT3Swaps()
NodeIterator GetNodeIteratorBegin(bool skipDeletedNodes=true)
#define EXPORT_TEMPLATE_CLASS_ALL_DIMS(CLASS)
void SetProtorosetteFormationProbability(double protorosetteFormationProbability)
std::vector< VertexElement< ELEMENT_DIM, SPACE_DIM > * > mElements
virtual void HandleHighOrderJunctions(Node< SPACE_DIM > *pNodeA, Node< SPACE_DIM > *pNodeB)
void DivideEdge(Node< SPACE_DIM > *pNodeA, Node< SPACE_DIM > *pNodeB)
void SetCheckForInternalIntersections(bool checkForInternalIntersections)
void AddElement(unsigned index)
void DeleteElementPriorToReMesh(unsigned index)
Node< SPACE_DIM > * GetNode(unsigned localIndex) const
double GetProtorosetteResolutionProbabilityPerTimestep() const
virtual c_vector< double, SPACE_DIM > GetCentroidOfElement(unsigned index)
std::set< unsigned > GetNeighbouringElementIndices(unsigned elementIndex)
void SetCellRearrangementRatio(double cellRearrangementRatio)
void RemoveDeletedNodes()
virtual ~MutableVertexMesh()
double GetRosetteResolutionProbabilityPerTimestep() const
void DeleteNode(const unsigned &rIndex)
unsigned GetNumNodes() const
void PerformT1Swap(Node< SPACE_DIM > *pNodeA, Node< SPACE_DIM > *pNodeB, std::set< unsigned > &rElementsContainingNodes)
double GetProtorosetteFormationProbability() const
void SetT2Threshold(double t2Threshold)
virtual void IdentifySwapType(Node< SPACE_DIM > *pNodeA, Node< SPACE_DIM > *pNodeB)
VertexElementIterator GetElementIteratorEnd()
c_vector< double, SPACE_DIM > & rGetModifiableLocation()
bool IsBoundaryNode() const
bool ElementIncludesPoint(const c_vector< double, SPACE_DIM > &rTestPoint, unsigned elementIndex)
c_vector< double, SPACE_DIM > GetLastT2SwapLocation()
void PerformT2Swap(VertexElement< ELEMENT_DIM, SPACE_DIM > &rElement)
unsigned GetLocalIndexForElementEdgeClosestToPoint(const c_vector< double, SPACE_DIM > &rTestPoint, unsigned elementIndex)
std::vector< unsigned > mDeletedElementIndices
void Resize(unsigned size)
c_vector< double, SPACE_DIM > GetShortAxisOfElement(unsigned index)