36 #include "MutableVertexMesh.hpp"
38 #include "Warnings.hpp"
39 #include "LogFile.hpp"
41 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
44 double cellRearrangementThreshold,
46 double cellRearrangementRatio,
47 double protorosetteFormationProbability,
48 double protorosetteResolutionProbabilityPerTimestep,
49 double rosetteResolutionProbabilityPerTimestep)
50 : mCellRearrangementThreshold(cellRearrangementThreshold),
51 mCellRearrangementRatio(cellRearrangementRatio),
52 mT2Threshold(t2Threshold),
53 mProtorosetteFormationProbability(protorosetteFormationProbability),
54 mProtorosetteResolutionProbabilityPerTimestep(protorosetteResolutionProbabilityPerTimestep),
55 mRosetteResolutionProbabilityPerTimestep(rosetteResolutionProbabilityPerTimestep),
56 mCheckForInternalIntersections(false)
59 assert(cellRearrangementThreshold > 0.0);
60 assert(t2Threshold > 0.0);
61 assert(protorosetteFormationProbability >= 0.0);
62 assert(protorosetteFormationProbability <= 1.0);
63 assert(protorosetteResolutionProbabilityPerTimestep >= 0.0);
64 assert(protorosetteResolutionProbabilityPerTimestep <= 1.0);
65 assert(rosetteResolutionProbabilityPerTimestep >= 0.0);
66 assert(rosetteResolutionProbabilityPerTimestep <= 1.0);
72 for (
unsigned node_index=0; node_index<nodes.size(); node_index++)
75 this->
mNodes.push_back(p_temp_node);
77 for (
unsigned elem_index=0; elem_index<vertexElements.size(); elem_index++)
80 this->
mElements.push_back(p_temp_vertex_element);
87 std::set<unsigned> faces_counted;
90 for (
unsigned elem_index=0; elem_index<this->
mElements.size(); elem_index++)
93 for (
unsigned face_index=0; face_index<this->
mElements[elem_index]->GetNumFaces(); face_index++)
98 if (faces_counted.find(p_face->GetIndex()) == faces_counted.end())
100 this->
mFaces.push_back(p_face);
101 faces_counted.insert(p_face->GetIndex());
108 for (
unsigned index=0; index<this->
mElements.size(); index++)
111 for (
unsigned node_index=0; node_index<p_temp_vertex_element->
GetNumNodes(); node_index++)
121 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
123 : mCellRearrangementThreshold(0.01),
124 mCellRearrangementRatio(1.5),
126 mProtorosetteFormationProbability(0.0),
127 mProtorosetteResolutionProbabilityPerTimestep(0.0),
128 mRosetteResolutionProbabilityPerTimestep(0.0),
129 mCheckForInternalIntersections(false)
136 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
142 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
145 return mCellRearrangementThreshold;
148 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
154 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
157 return mCellRearrangementRatio;
160 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
163 return this->mProtorosetteFormationProbability;
166 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
169 return this->mProtorosetteResolutionProbabilityPerTimestep;
172 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
175 return this->mRosetteResolutionProbabilityPerTimestep;
178 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
181 return mCheckForInternalIntersections;
184 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
187 mCellRearrangementThreshold = cellRearrangementThreshold;
190 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
193 mT2Threshold = t2Threshold;
196 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
199 mCellRearrangementRatio = cellRearrangementRatio;
202 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
206 if (protorosetteFormationProbability < 0.0)
208 EXCEPTION(
"Attempting to assign a negative probability.");
210 if (protorosetteFormationProbability > 1.0)
212 EXCEPTION(
"Attempting to assign a probability greater than one.");
216 mProtorosetteFormationProbability = protorosetteFormationProbability;
219 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
223 if (protorosetteResolutionProbabilityPerTimestep < 0.0)
225 EXCEPTION(
"Attempting to assign a negative probability.");
227 if (protorosetteResolutionProbabilityPerTimestep > 1.0)
229 EXCEPTION(
"Attempting to assign a probability greater than one.");
233 mProtorosetteResolutionProbabilityPerTimestep = protorosetteResolutionProbabilityPerTimestep;
236 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
240 if (rosetteResolutionProbabilityPerTimestep < 0.0)
242 EXCEPTION(
"Attempting to assign a negative probability.");
244 if (rosetteResolutionProbabilityPerTimestep > 1.0)
246 EXCEPTION(
"Attempting to assign a probability greater than one.");
250 mRosetteResolutionProbabilityPerTimestep = rosetteResolutionProbabilityPerTimestep;
253 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
256 mCheckForInternalIntersections = checkForInternalIntersections;
259 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
262 mDeletedNodeIndices.clear();
263 mDeletedElementIndices.clear();
268 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
271 return this->mNodes.size() - mDeletedNodeIndices.size();
274 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
277 return this->mElements.size() - mDeletedElementIndices.size();
280 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
283 return mLocationsOfT1Swaps;
286 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
289 return mLastT2SwapLocation;
292 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
295 return mLocationsOfT3Swaps;
298 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
301 mLocationsOfT1Swaps.clear();
304 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
307 mLocationsOfT3Swaps.clear();
310 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
313 if (mDeletedNodeIndices.empty())
315 pNewNode->
SetIndex(this->mNodes.size());
316 this->mNodes.push_back(pNewNode);
320 unsigned index = mDeletedNodeIndices.back();
322 mDeletedNodeIndices.pop_back();
323 delete this->mNodes[index];
324 this->mNodes[index] = pNewNode;
329 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
332 unsigned new_element_index = pNewElement->
GetIndex();
334 if (new_element_index == this->mElements.size())
336 this->mElements.push_back(pNewElement);
340 this->mElements[new_element_index] = pNewElement;
346 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
349 this->mNodes[nodeIndex]->SetPoint(point);
352 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
354 c_vector<double, SPACE_DIM> axisOfDivision,
355 bool placeOriginalElementBelow)
357 assert(SPACE_DIM == 2);
358 assert(ELEMENT_DIM == SPACE_DIM);
361 c_vector<double, SPACE_DIM> centroid = this->GetCentroidOfElement(pElement->
GetIndex());
364 c_vector<double, SPACE_DIM> perp_axis;
365 perp_axis(0) = -axisOfDivision(1);
366 perp_axis(1) = axisOfDivision(0);
374 std::vector<unsigned> intersecting_nodes;
375 bool is_current_node_on_left = (inner_prod(this->GetVectorFromAtoB(pElement->
GetNodeLocation(0), centroid), perp_axis) >= 0);
376 for (
unsigned i=0; i<num_nodes; i++)
378 bool is_next_node_on_left = (inner_prod(this->GetVectorFromAtoB(pElement->
GetNodeLocation((i+1)%num_nodes), centroid), perp_axis) >= 0);
379 if (is_current_node_on_left != is_next_node_on_left)
381 intersecting_nodes.push_back(i);
383 is_current_node_on_left = is_next_node_on_left;
387 if (intersecting_nodes.size() != 2)
389 EXCEPTION(
"Cannot proceed with element division: the given axis of division does not cross two edges of the element");
392 std::vector<unsigned> division_node_global_indices;
393 unsigned nodes_added = 0;
396 for (
unsigned i=0; i<intersecting_nodes.size(); i++)
412 c_vector<double, SPACE_DIM> position_a = p_node_A->
rGetLocation();
413 c_vector<double, SPACE_DIM> position_b = p_node_B->
rGetLocation();
414 c_vector<double, SPACE_DIM> a_to_b = this->GetVectorFromAtoB(position_a, position_b);
416 c_vector<double, SPACE_DIM> intersection;
418 if (norm_2(a_to_b) < 2.0*mCellRearrangementRatio*mCellRearrangementThreshold)
420 WARNING(
"Edge is too small for normal division; putting node in the middle of a and b. There may be T1 swaps straight away.");
422 intersection = position_a + 0.5*a_to_b;
427 double determinant = a_to_b[0]*axisOfDivision[1] - a_to_b[1]*axisOfDivision[0];
430 c_vector<double, SPACE_DIM> moved_centroid;
431 moved_centroid = position_a + this->GetVectorFromAtoB(position_a, centroid);
433 double alpha = (moved_centroid[0]*a_to_b[1] - position_a[0]*a_to_b[1]
434 -moved_centroid[1]*a_to_b[0] + position_a[1]*a_to_b[0])/determinant;
436 intersection = moved_centroid + alpha*axisOfDivision;
442 c_vector<double, SPACE_DIM> a_to_intersection = this->GetVectorFromAtoB(position_a, intersection);
443 if (norm_2(a_to_intersection) < mCellRearrangementThreshold)
445 intersection = position_a + mCellRearrangementRatio*mCellRearrangementThreshold*a_to_b/norm_2(a_to_b);
448 c_vector<double, SPACE_DIM> b_to_intersection = this->GetVectorFromAtoB(position_b, intersection);
449 if (norm_2(b_to_intersection) < mCellRearrangementThreshold)
451 assert(norm_2(a_to_intersection) > mCellRearrangementThreshold);
453 intersection = position_b - mCellRearrangementRatio*mCellRearrangementThreshold*a_to_b/norm_2(a_to_b);
464 bool is_boundary =
false;
467 if (elems_containing_node_A.size() != 2 ||
468 elems_containing_node_B.size() != 2 ||
469 elems_containing_node_A != elems_containing_node_B)
476 unsigned new_node_global_index = this->AddNode(
new Node<SPACE_DIM>(0, is_boundary, intersection[0], intersection[1]));
482 std::set<unsigned> shared_elements;
483 std::set_intersection(elems_containing_node_A.begin(),
484 elems_containing_node_A.end(),
485 elems_containing_node_B.begin(),
486 elems_containing_node_B.end(),
487 std::inserter(shared_elements, shared_elements.begin()));
490 unsigned node_A_index = p_node_A->
GetIndex();
491 unsigned node_B_index = p_node_B->
GetIndex();
492 for (std::set<unsigned>::iterator iter = shared_elements.begin();
493 iter != shared_elements.end();
502 unsigned index = local_indexB;
505 if (local_indexB > local_indexA)
507 index = local_indexA;
510 if ((local_indexA == 0) && (local_indexB == p_element->
GetNumNodes()-1))
512 index = local_indexB;
515 else if ((local_indexB == 0) && (local_indexA == p_element->
GetNumNodes()-1))
518 index = local_indexA;
522 this->GetElement(*iter)->AddNode(this->GetNode(new_node_global_index), index);
526 division_node_global_indices.push_back(new_node_global_index);
530 unsigned new_element_index = DivideElement(pElement,
533 placeOriginalElementBelow);
535 return new_element_index;
538 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
540 bool placeOriginalElementBelow)
542 assert(SPACE_DIM == 2);
543 assert(ELEMENT_DIM == SPACE_DIM);
545 c_vector<double, SPACE_DIM> short_axis = this->GetShortAxisOfElement(pElement->
GetIndex());
547 unsigned new_element_index = DivideElementAlongGivenAxis(pElement, short_axis, placeOriginalElementBelow);
548 return new_element_index;
551 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
555 bool placeOriginalElementBelow)
557 assert(SPACE_DIM == 2);
558 assert(ELEMENT_DIM == SPACE_DIM);
561 assert(nodeBIndex != nodeAIndex);
562 unsigned node1_index = (nodeAIndex < nodeBIndex) ? nodeAIndex : nodeBIndex;
563 unsigned node2_index = (nodeAIndex < nodeBIndex) ? nodeBIndex : nodeAIndex;
569 std::vector<Node<SPACE_DIM>*> nodes_elem;
570 for (
unsigned i=0; i<num_nodes; i++)
572 nodes_elem.push_back(pElement->
GetNode(i));
576 unsigned new_element_index;
577 if (mDeletedElementIndices.empty())
579 new_element_index = this->mElements.size();
583 new_element_index = mDeletedElementIndices.back();
584 mDeletedElementIndices.pop_back();
585 delete this->mElements[new_element_index];
599 double height_midpoint_1 = 0.0;
600 double height_midpoint_2 = 0.0;
601 unsigned counter_1 = 0;
602 unsigned counter_2 = 0;
604 for (
unsigned i=0; i<num_nodes; i++)
606 if (i>=node1_index && i<=node2_index)
608 height_midpoint_1 += pElement->
GetNode(i)->rGetLocation()[1];
611 if (i<=node1_index || i>=node2_index)
613 height_midpoint_2 += pElement->
GetNode(i)->rGetLocation()[1];
617 height_midpoint_1 /= (
double)counter_1;
618 height_midpoint_2 /= (
double)counter_2;
620 for (
unsigned i=num_nodes; i>0; i--)
622 if (i-1 < node1_index || i-1 > node2_index)
624 if (height_midpoint_1 < height_midpoint_2)
626 if (placeOriginalElementBelow)
632 this->mElements[new_element_index]->DeleteNode(i-1);
637 if (placeOriginalElementBelow)
639 this->mElements[new_element_index]->DeleteNode(i-1);
647 else if (i-1 > node1_index && i-1 < node2_index)
649 if (height_midpoint_1 < height_midpoint_2)
651 if (placeOriginalElementBelow)
653 this->mElements[new_element_index]->DeleteNode(i-1);
662 if (placeOriginalElementBelow)
668 this->mElements[new_element_index]->DeleteNode(i-1);
674 return new_element_index;
677 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
680 assert(SPACE_DIM == 2);
683 for (
unsigned i=0; i<this->mElements[index]->GetNumNodes(); i++)
689 DeleteNodePriorToReMesh(p_node->
GetIndex());
697 this->mElements[index]->MarkAsDeleted();
698 mDeletedElementIndices.push_back(index);
701 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
704 this->mNodes[index]->MarkAsDeleted();
705 mDeletedNodeIndices.push_back(index);
708 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
716 std::set<unsigned> shared_elements;
717 std::set_intersection(elements_containing_nodeA.begin(),
718 elements_containing_nodeA.end(),
719 elements_containing_nodeB.begin(),
720 elements_containing_nodeB.end(),
721 std::inserter(shared_elements, shared_elements.begin()));
724 assert(!shared_elements.empty());
725 assert(shared_elements.size()<=2u);
728 bool is_boundary_node =
false;
729 if (shared_elements.size()==1u)
733 is_boundary_node =
true;
742 p_new_node->
SetPoint(new_node_position);
745 this->mNodes.push_back(p_new_node);
748 unsigned node_A_index = pNodeA->
GetIndex();
749 unsigned node_B_index = pNodeB->
GetIndex();
750 for (std::set<unsigned>::iterator iter = shared_elements.begin();
751 iter != shared_elements.end();
760 unsigned index = local_indexB;
763 if (local_indexB > local_indexA)
765 index = local_indexA;
768 if ((local_indexA == 0) && (local_indexB == p_element->
GetNumNodes()-1))
770 index = local_indexB;
773 else if ((local_indexB == 0) && (local_indexA == p_element->
GetNumNodes()-1))
776 index = local_indexA;
780 this->GetElement(*iter)->AddNode(p_new_node, index);
784 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
788 rElementMap.
Resize(this->GetNumAllElements());
791 std::vector<VertexElement<ELEMENT_DIM, SPACE_DIM>*> live_elements;
792 for (
unsigned i=0; i<this->mElements.size(); i++)
794 if (this->mElements[i]->IsDeleted())
796 delete this->mElements[i];
801 live_elements.push_back(this->mElements[i]);
802 rElementMap.
SetNewIndex(i, (
unsigned)(live_elements.size()-1));
807 assert(mDeletedElementIndices.size() == this->mElements.size() - live_elements.size());
810 mDeletedElementIndices.clear();
811 this->mElements = live_elements;
814 for (
unsigned i=0; i<this->mElements.size(); i++)
816 this->mElements[i]->ResetIndex(i);
820 RemoveDeletedNodes();
823 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
827 std::vector<Node<SPACE_DIM>*> live_nodes;
828 for (
unsigned i=0; i<this->mNodes.size(); i++)
830 if (this->mNodes[i]->IsDeleted())
832 delete this->mNodes[i];
836 live_nodes.push_back(this->mNodes[i]);
841 assert(mDeletedNodeIndices.size() == this->mNodes.size() - live_nodes.size());
844 this->mNodes = live_nodes;
845 mDeletedNodeIndices.clear();
848 for (
unsigned i=0; i<this->mNodes.size(); i++)
850 this->mNodes[i]->SetIndex(i);
854 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
858 assert(SPACE_DIM==2 || SPACE_DIM==3);
859 assert(ELEMENT_DIM == SPACE_DIM);
864 rElementMap.
Resize(this->GetNumAllElements());
871 RemoveDeletedNodesAndElements(rElementMap);
872 bool recheck_mesh =
true;
873 while (recheck_mesh ==
true)
876 recheck_mesh = CheckForSwapsFromShortEdges();
881 while (recheck_mesh ==
true)
884 recheck_mesh = CheckForIntersections();
887 RemoveDeletedNodes();
893 this->CheckForRosettes();
897 #define COVERAGE_IGNORE
898 EXCEPTION(
"Remeshing has not been implemented in 3D (see #827 and #860)\n");
899 #undef COVERAGE_IGNORE
904 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
911 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
916 elem_iter != this->GetElementIteratorEnd();
921 unsigned num_nodes = elem_iter->GetNumNodes();
922 assert(num_nodes > 0);
925 for (
unsigned local_index=0; local_index<num_nodes; local_index++)
929 unsigned local_index_plus_one = (local_index+1)%num_nodes;
930 Node<SPACE_DIM>* p_anticlockwise_node = elem_iter->GetNode(local_index_plus_one);
933 double distance_between_nodes = this->GetDistanceBetweenNodes(p_current_node->
GetIndex(), p_anticlockwise_node->
GetIndex());
936 if (distance_between_nodes < mCellRearrangementThreshold)
942 std::set<unsigned> shared_elements;
943 std::set_intersection(elements_of_node_a.begin(), elements_of_node_a.end(),
944 elements_of_node_b.begin(), elements_of_node_b.end(),
945 std::inserter(shared_elements, shared_elements.begin()));
947 bool both_nodes_share_triangular_element =
false;
948 for (std::set<unsigned>::const_iterator it = shared_elements.begin();
949 it != shared_elements.end();
952 if (this->GetElement(*it)->GetNumNodes() <= 3)
954 both_nodes_share_triangular_element =
true;
960 if (!both_nodes_share_triangular_element)
962 IdentifySwapType(p_current_node, p_anticlockwise_node);
972 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
977 elem_iter != this->GetElementIteratorEnd();
981 if (elem_iter->GetNumNodes() == 3)
984 if (this->GetVolumeOfElement(elem_iter->GetIndex()) < GetT2Threshold())
987 PerformT2Swap(*elem_iter);
989 rElementMap.
SetDeleted(elem_iter->GetIndex());
997 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1001 if (mCheckForInternalIntersections)
1005 node_iter != this->GetNodeIteratorEnd();
1008 assert(!(node_iter->IsDeleted()));
1011 elem_iter != this->GetElementIteratorEnd();
1014 unsigned elem_index = elem_iter->GetIndex();
1017 if (node_iter->rGetContainingElementIndices().count(elem_index) == 0)
1019 if (this->ElementIncludesPoint(node_iter->rGetLocation(), elem_index))
1021 PerformIntersectionSwap(&(*node_iter), elem_index);
1031 std::set<unsigned> boundary_element_indices;
1033 elem_iter != this->GetElementIteratorEnd();
1036 if (elem_iter->IsElementOnBoundary())
1038 boundary_element_indices.insert(elem_iter->GetIndex());
1043 node_iter != this->GetNodeIteratorEnd();
1046 if (node_iter->IsBoundaryNode())
1048 assert(!(node_iter->IsDeleted()));
1050 for (std::set<unsigned>::iterator elem_iter = boundary_element_indices.begin();
1051 elem_iter != boundary_element_indices.end();
1055 if (node_iter->rGetContainingElementIndices().count(*elem_iter) == 0)
1057 if (this->ElementIncludesPoint(node_iter->rGetLocation(), *elem_iter))
1059 PerformT3Swap(&(*node_iter), *elem_iter);
1071 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1079 std::set<unsigned> all_indices, temp_union_set;
1080 std::set_union(nodeA_elem_indices.begin(), nodeA_elem_indices.end(),
1081 nodeB_elem_indices.begin(), nodeB_elem_indices.end(),
1082 std::inserter(temp_union_set, temp_union_set.begin()));
1083 all_indices.swap(temp_union_set);
1086 if ((nodeA_elem_indices.size()>3) || (nodeB_elem_indices.size()>3))
1103 this->HandleHighOrderJunctions(pNodeA, pNodeB);
1107 switch (all_indices.size())
1122 PerformNodeMerge(pNodeA, pNodeB);
1123 RemoveDeletedNodes();
1128 if (nodeA_elem_indices.size()==2 && nodeB_elem_indices.size()==2)
1142 PerformT1Swap(pNodeA, pNodeB,all_indices);
1157 EXCEPTION(
"There is a non-boundary node contained only in two elements; something has gone wrong.");
1169 EXCEPTION(
"There are non-boundary nodes contained only in two elements; something has gone wrong.");
1188 PerformNodeMerge(pNodeA, pNodeB);
1189 RemoveDeletedNodes();
1195 if (nodeA_elem_indices.size()==1 || nodeB_elem_indices.size()==1)
1213 EXCEPTION(
"There is a boundary node contained in three elements something has gone wrong.");
1215 else if (nodeA_elem_indices.size()==2 && nodeB_elem_indices.size()==2)
1223 std::set<unsigned> element_A_not_B, temp_set;
1224 std::set_difference(all_indices.begin(), all_indices.end(), nodeB_elem_indices.begin(),
1225 nodeB_elem_indices.end(), std::inserter(temp_set, temp_set.begin()));
1226 element_A_not_B.swap(temp_set);
1229 assert(element_A_not_B.size() == 1);
1231 std::set<unsigned> element_B_not_A;
1232 std::set_difference(all_indices.begin(), all_indices.end(), nodeA_elem_indices.begin(),
1233 nodeA_elem_indices.end(), std::inserter(temp_set, temp_set.begin()));
1234 element_B_not_A.swap(temp_set);
1237 assert(element_B_not_A.size() == 1);
1243 unsigned next_node_1 = p_element_A_not_B->GetNodeGlobalIndex((local_index_1 + 1)%(p_element_A_not_B->GetNumNodes()));
1244 unsigned previous_node_1 = p_element_A_not_B->GetNodeGlobalIndex(
1245 (local_index_1 + p_element_A_not_B->GetNumNodes() - 1)%(p_element_A_not_B->GetNumNodes()));
1248 (local_index_2 + 1)%(p_element_B_not_A->
GetNumNodes()));
1252 if (next_node_1 == previous_node_2 || next_node_2 == previous_node_1)
1271 unsigned nodeC_index;
1272 if (next_node_1 == previous_node_2 && next_node_2 != previous_node_1)
1274 nodeC_index = next_node_1;
1276 else if (next_node_2 == previous_node_1 && next_node_1 != previous_node_2)
1278 nodeC_index = next_node_2;
1282 assert(next_node_1 == previous_node_2 && next_node_2 == previous_node_1);
1290 EXCEPTION(
"Triangular element next to triangular void, not implemented yet.");
1293 if(p_element_A_not_B->GetNumNodes() == 3u || p_element_B_not_A->
GetNumNodes() == 3u)
1302 EXCEPTION(
"Triangular element next to triangular void, not implemented yet.");
1305 PerformVoidRemoval(pNodeA, pNodeB, this->mNodes[nodeC_index]);
1323 PerformT1Swap(pNodeA, pNodeB, all_indices);
1329 assert ( (nodeA_elem_indices.size()==2 && nodeB_elem_indices.size()==3)
1330 || (nodeA_elem_indices.size()==3 && nodeB_elem_indices.size()==2) );
1347 PerformT1Swap(pNodeA, pNodeB, all_indices);
1362 EXCEPTION(
"There are non-boundary nodes contained only in two elements; something has gone wrong.");
1385 this->PerformNodeMerge(pNodeA, pNodeB);
1386 this->RemoveDeletedNodes();
1390 this->PerformT1Swap(pNodeA, pNodeB, all_indices);
1401 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1412 unsigned node_B_index = pNodeB->
GetIndex();
1413 for (std::set<unsigned>::const_iterator it = nodeB_elem_indices.begin(); it != nodeB_elem_indices.end(); ++it)
1416 unsigned node_B_local_index = this->mElements[*it]->GetNodeLocalIndex(node_B_index);
1417 assert(node_B_local_index < UINT_MAX);
1423 if (nodeA_elem_indices.count(*it) != 0)
1425 this->mElements[*it]->DeleteNode(node_B_local_index);
1430 this->mElements[*it]->UpdateNode(node_B_local_index, pNodeA);
1434 assert(!(this->mNodes[node_B_index]->IsDeleted()));
1435 this->mNodes[node_B_index]->MarkAsDeleted();
1436 mDeletedNodeIndices.push_back(node_B_index);
1439 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1442 std::set<unsigned>& rElementsContainingNodes)
1445 double distance_between_nodes_CD = mCellRearrangementRatio*mCellRearrangementThreshold;
1447 c_vector<double, SPACE_DIM> nodeA_location = pNodeA->
rGetLocation();
1448 c_vector<double, SPACE_DIM> nodeB_location = pNodeB->
rGetLocation();
1449 c_vector<double, SPACE_DIM> vector_AB = this->GetVectorFromAtoB(nodeA_location, nodeB_location);
1450 mLocationsOfT1Swaps.push_back(nodeA_location + 0.5*vector_AB);
1452 double distance_AB = norm_2(vector_AB);
1453 if (distance_AB < 1e-10)
1455 EXCEPTION(
"Nodes are too close together, this shouldn't happen");
1487 c_vector<double, SPACE_DIM> vector_CD;
1488 vector_CD(0) = -vector_AB(1) * distance_between_nodes_CD / distance_AB;
1489 vector_CD(1) = vector_AB(0) * distance_between_nodes_CD / distance_AB;
1491 c_vector<double, SPACE_DIM> nodeC_location = nodeA_location + 0.5*vector_AB - 0.5*vector_CD;
1492 c_vector<double, SPACE_DIM> nodeD_location = nodeC_location + vector_CD;
1501 for (std::set<unsigned>::const_iterator it = rElementsContainingNodes.begin();
1502 it != rElementsContainingNodes.end();
1506 if (nodeA_elem_indices.find(*it) == nodeA_elem_indices.end())
1509 unsigned nodeB_local_index = this->mElements[*it]->GetNodeLocalIndex(pNodeB->
GetIndex());
1510 assert(nodeB_local_index < UINT_MAX);
1512 this->mElements[*it]->AddNode(pNodeA, nodeB_local_index);
1514 else if (nodeB_elem_indices.find(*it) == nodeB_elem_indices.end())
1517 unsigned nodeA_local_index = this->mElements[*it]->GetNodeLocalIndex(pNodeA->
GetIndex());
1518 assert(nodeA_local_index < UINT_MAX);
1520 this->mElements[*it]->AddNode(pNodeB, nodeA_local_index);
1525 unsigned nodeA_local_index = this->mElements[*it]->GetNodeLocalIndex(pNodeA->
GetIndex());
1526 unsigned nodeB_local_index = this->mElements[*it]->GetNodeLocalIndex(pNodeB->
GetIndex());
1528 assert(nodeA_local_index < UINT_MAX);
1529 assert(nodeB_local_index < UINT_MAX);
1536 unsigned nodeB_local_index_plus_one = (nodeB_local_index + 1)%(this->mElements[*it]->GetNumNodes());
1538 if (nodeA_local_index == nodeB_local_index_plus_one)
1544 this->mElements[*it]->DeleteNode(nodeB_local_index);
1548 assert(nodeB_local_index == (nodeA_local_index + 1)%(this->mElements[*it]->GetNumNodes()));
1553 this->mElements[*it]->DeleteNode(nodeA_local_index);
1580 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1583 assert(SPACE_DIM == 2);
1584 assert(ELEMENT_DIM == SPACE_DIM);
1589 std::set<unsigned> elements_containing_intersecting_node;
1591 for (
unsigned node_local_index=0; node_local_index<num_nodes; node_local_index++)
1595 std::set<unsigned> node_elem_indices = this->GetNode(node_global_index)->rGetContainingElementIndices();
1597 for (std::set<unsigned>::const_iterator elem_iter = node_elem_indices.begin();
1598 elem_iter != node_elem_indices.end();
1602 unsigned num_nodes_in_neighbouring_element = p_neighbouring_element->
GetNumNodes();
1605 for (
unsigned node_index_2 = 0; node_index_2 < num_nodes_in_neighbouring_element; node_index_2++)
1609 elements_containing_intersecting_node.insert(p_neighbouring_element->
GetIndex());
1618 assert(elements_containing_intersecting_node.size() == 2);
1622 std::set<unsigned> intersecting_element;
1624 std::set_difference(all_elements_containing_intersecting_node.begin(), all_elements_containing_intersecting_node.end(),
1625 elements_containing_intersecting_node.begin(), elements_containing_intersecting_node.end(),
1626 std::inserter(intersecting_element, intersecting_element.begin()));
1638 unsigned node_A_index = pNode->
GetIndex();
1639 unsigned node_B_index;
1640 unsigned element_1_index = *(intersecting_element.begin());
1641 unsigned element_2_index;
1642 unsigned element_3_index = elementIndex;
1643 unsigned element_4_index;
1645 std::set<unsigned>::iterator iter = elements_containing_intersecting_node.begin();
1646 unsigned element_a_index = *(iter);
1648 unsigned element_b_index = *(iter);
1653 std::set<unsigned> element_a_nodes;
1654 for (
unsigned node_index = 0; node_index < p_element_a->
GetNumNodes(); node_index++)
1659 std::set<unsigned> element_b_nodes;
1660 for (
unsigned node_index = 0; node_index < p_element_b->
GetNumNodes(); node_index++)
1665 std::set<unsigned> switching_nodes;
1666 std::set_intersection(element_a_nodes.begin(), element_a_nodes.end(),
1667 element_b_nodes.begin(), element_b_nodes.end(),
1668 std::inserter(switching_nodes, switching_nodes.begin()));
1670 assert(switching_nodes.size() == 2);
1673 assert(switching_nodes.find(node_A_index) != switching_nodes.end());
1674 switching_nodes.erase(node_A_index);
1676 assert(switching_nodes.size() == 1);
1678 node_B_index = *(switching_nodes.begin());
1681 unsigned node_A_local_index_in_a = p_element_a->
GetNodeLocalIndex(node_A_index);
1682 unsigned node_B_local_index_in_a = p_element_a->
GetNodeLocalIndex(node_B_index);
1684 if ((node_B_local_index_in_a+1)%p_element_a->
GetNumNodes() == node_A_local_index_in_a)
1690 element_2_index = element_a_index;
1691 element_4_index = element_b_index;
1699 element_2_index = element_b_index;
1700 element_4_index = element_a_index;
1703 unsigned intersected_edge = this->GetLocalIndexForElementEdgeClosestToPoint(pNode->
rGetLocation(), elementIndex);
1705 unsigned node_A_local_index_in_1 = this->GetElement(element_1_index)->GetNodeLocalIndex(node_A_index);
1707 unsigned node_A_local_index_in_2 = this->GetElement(element_2_index)->GetNodeLocalIndex(node_A_index);
1708 unsigned node_B_local_index_in_2 = this->GetElement(element_2_index)->GetNodeLocalIndex(node_B_index);
1710 unsigned node_B_local_index_in_3 = this->GetElement(elementIndex)->GetNodeLocalIndex(node_B_index);
1712 unsigned node_A_local_index_in_4 = this->GetElement(element_4_index)->GetNodeLocalIndex(node_A_index);
1713 unsigned node_B_local_index_in_4 = this->GetElement(element_4_index)->GetNodeLocalIndex(node_B_index);
1715 if (intersected_edge==node_B_local_index_in_3)
1724 this->mElements[element_1_index]->AddNode(this->mNodes[node_B_index], node_A_local_index_in_1);
1725 this->mElements[element_3_index]->AddNode(this->mNodes[node_A_index], node_B_local_index_in_3);
1727 this->mElements[element_2_index]->DeleteNode(node_B_local_index_in_2);
1728 this->mElements[element_4_index]->DeleteNode(node_A_local_index_in_4);
1732 assert((intersected_edge+1)%num_nodes==node_B_local_index_in_3);
1735 unsigned node_before_A_in_1 = (node_A_local_index_in_1 - 1)%this->GetElement(element_1_index)->GetNumNodes();
1736 unsigned node_before_B_in_3 = (node_B_local_index_in_3 - 1)%this->GetElement(element_3_index)->GetNumNodes();
1737 this->mElements[element_1_index]->AddNode(this->mNodes[node_B_index], node_before_A_in_1);
1738 this->mElements[element_3_index]->AddNode(this->mNodes[node_A_index], node_before_B_in_3);
1741 this->mElements[element_2_index]->DeleteNode(node_A_local_index_in_2);
1742 this->mElements[element_4_index]->DeleteNode(node_B_local_index_in_4);
1746 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1753 c_vector<double, SPACE_DIM> new_node_location;
1754 new_node_location = this->GetCentroidOfElement(rElement.
GetIndex());
1755 mLastT2SwapLocation = new_node_location;
1758 bool is_node_on_boundary =
false;
1759 for (
unsigned i=0; i<3; i++)
1761 if (rElement.
GetNode(i)->IsBoundaryNode())
1763 is_node_on_boundary =
true;
1767 unsigned new_node_global_index = this->AddNode(
new Node<SPACE_DIM>(GetNumNodes(), new_node_location, is_node_on_boundary));
1771 for (
unsigned i=0; i<3; i++)
1776 containing_elements.erase(rElement.
GetIndex());
1779 for (std::set<unsigned>::iterator elem_iter = containing_elements.begin(); elem_iter != containing_elements.end(); ++elem_iter)
1786 EXCEPTION(
"One of the neighbours of a small triangular element is also a triangle - dealing with this has not been implemented yet");
1806 rElement.
GetNode(0)->MarkAsDeleted();
1807 rElement.
GetNode(1)->MarkAsDeleted();
1808 rElement.
GetNode(2)->MarkAsDeleted();
1810 mDeletedElementIndices.push_back(rElement.
GetIndex());
1814 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1817 assert(SPACE_DIM == 2);
1818 assert(ELEMENT_DIM == SPACE_DIM);
1825 unsigned node_A_local_index = this->GetLocalIndexForElementEdgeClosestToPoint(pNode->
rGetLocation(), elementIndex);
1828 c_vector<double, SPACE_DIM> node_location;
1837 unsigned vertexB_index = p_element->
GetNodeGlobalIndex((node_A_local_index+1)%num_nodes);
1840 if (!this->mNodes[vertexA_index]->IsBoundaryNode() || !this->mNodes[vertexB_index]->IsBoundaryNode())
1842 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.");
1846 c_vector<double, SPACE_DIM> vertexA = p_element->
GetNodeLocation(node_A_local_index);
1847 c_vector<double, SPACE_DIM> vertexB = p_element->
GetNodeLocation((node_A_local_index+1)%num_nodes);
1848 c_vector<double, SPACE_DIM> vector_a_to_point = this->GetVectorFromAtoB(vertexA, node_location);
1850 c_vector<double, SPACE_DIM> vector_a_to_b = this->GetVectorFromAtoB(vertexA, vertexB);
1852 c_vector<double, SPACE_DIM> edge_ab_unit_vector = vector_a_to_b/norm_2(vector_a_to_b);
1853 c_vector<double, SPACE_DIM> intersection = vertexA + edge_ab_unit_vector*inner_prod(vector_a_to_point, edge_ab_unit_vector);
1859 mLocationsOfT3Swaps.push_back(intersection);
1864 unsigned intersecting_element_index = *elements_containing_intersecting_node.begin();
1874 if (next_node == vertexA_index || previous_node == vertexA_index || next_node == vertexB_index || previous_node == vertexB_index)
1876 unsigned common_vertex_index;
1878 if (next_node == vertexA_index || previous_node == vertexA_index)
1880 common_vertex_index = vertexA_index;
1884 common_vertex_index = vertexB_index;
1887 assert(this->mNodes[common_vertex_index]->GetNumContainingElements()>1);
1889 std::set<unsigned> elements_containing_common_vertex = this->mNodes[common_vertex_index]->rGetContainingElementIndices();
1890 std::set<unsigned>::const_iterator it = elements_containing_common_vertex.begin();
1896 unsigned num_common_vertices = 0;
1897 std::vector<unsigned> common_vertex_indices;
1898 for (
unsigned i=0; i<p_element_common_1->
GetNumNodes(); i++)
1900 for (
unsigned j=0; j<p_element_common_2->
GetNumNodes(); j++)
1904 num_common_vertices++;
1910 if (num_common_vertices == 1 || this->mNodes[common_vertex_index]->GetNumContainingElements() > 2)
1926 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
1932 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
1937 else if (num_common_vertices == 2)
1942 if ( ( common_vertex_indices[0]==vertexA_index && common_vertex_indices[1]==vertexB_index ) ||
1943 ( common_vertex_indices[1]==vertexA_index && common_vertex_indices[0]==vertexB_index ) )
1961 unsigned p_node_local_index = this->
1962 GetElement(intersecting_element_index)->GetNodeLocalIndex(pNode->
GetIndex());
1963 this->GetElement(intersecting_element_index)->DeleteNode(p_node_local_index);
1967 mDeletedNodeIndices.push_back(pNode->
GetIndex());
1988 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
1994 this->GetElement(elementIndex)->ReplaceNode(this->mNodes[common_vertex_index], pNode);
1997 unsigned common_vertex_local_index = this->GetElement(intersecting_element_index)->GetNodeLocalIndex(common_vertex_index);
1998 this->GetElement(intersecting_element_index)->DeleteNode(common_vertex_local_index);
1999 assert(this->mNodes[common_vertex_index]->GetNumContainingElements() == 0);
2001 this->mNodes[common_vertex_index]->MarkAsDeleted();
2002 mDeletedNodeIndices.push_back(common_vertex_index);
2008 else if (num_common_vertices == 4)
2026 this->GetElement(elementIndex)->DeleteNode(node_A_local_index);
2027 unsigned node_B_local_index = this->
2028 GetElement(elementIndex)->GetNodeLocalIndex(vertexB_index);
2029 this->GetElement(elementIndex)->DeleteNode(node_B_local_index);
2032 unsigned node_A_local_index_intersecting_element = this->
2033 GetElement(intersecting_element_index)->GetNodeLocalIndex(vertexA_index);
2034 this->GetElement(intersecting_element_index)->DeleteNode(node_A_local_index_intersecting_element);
2035 unsigned node_B_local_index_intersecting_element = this->
2036 GetElement(intersecting_element_index)->GetNodeLocalIndex(vertexB_index);
2037 this->GetElement(intersecting_element_index)->DeleteNode(node_B_local_index_intersecting_element);
2040 unsigned p_node_local_index = this->
2041 GetElement(intersecting_element_index)->GetNodeLocalIndex(pNode->
GetIndex());
2042 this->GetElement(intersecting_element_index)->DeleteNode(p_node_local_index);
2046 mDeletedNodeIndices.push_back(pNode->
GetIndex());
2047 this->mNodes[vertexA_index]->MarkAsDeleted();
2048 mDeletedNodeIndices.push_back(vertexA_index);
2049 this->mNodes[vertexB_index]->MarkAsDeleted();
2050 mDeletedNodeIndices.push_back(vertexB_index);
2071 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
2072 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index+1)%num_nodes);
2075 pNode->
rGetModifiableLocation() = intersection + 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2078 c_vector<double, SPACE_DIM> new_node_location;
2079 new_node_location = intersection - 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2082 unsigned new_node_global_index = this->AddNode(
new Node<SPACE_DIM>(0,
true, new_node_location[0], new_node_location[1]));
2085 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2086 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
2089 this->GetElement(intersecting_element_index)->AddNode(this->mNodes[new_node_global_index], this->GetElement(intersecting_element_index)->GetNodeLocalIndex(pNode->
GetIndex()));
2093 assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
2099 std::set<unsigned>::const_iterator it = elements_containing_intersecting_node.begin();
2102 unsigned num_nodes_elem_1 = p_element_1->
GetNumNodes();
2106 unsigned num_nodes_elem_2 = p_element_2->
GetNumNodes();
2108 unsigned node_global_index = pNode->
GetIndex();
2111 unsigned next_node_1 = p_element_1->
GetNodeGlobalIndex((local_index_1 + 1)%num_nodes_elem_1);
2112 unsigned previous_node_1 = p_element_1->
GetNodeGlobalIndex((local_index_1 + num_nodes_elem_1 - 1)%num_nodes_elem_1);
2115 unsigned next_node_2 = p_element_2->
GetNodeGlobalIndex((local_index_2 + 1)%num_nodes_elem_2);
2116 unsigned previous_node_2 = p_element_2->
GetNodeGlobalIndex((local_index_2 + num_nodes_elem_2 - 1)%num_nodes_elem_2);
2119 if ((next_node_1 == vertexA_index || previous_node_1 == vertexA_index || next_node_2 == vertexA_index || previous_node_2 == vertexA_index) &&
2120 (next_node_1 == vertexB_index || previous_node_1 == vertexB_index || next_node_2 == vertexB_index || previous_node_2 == vertexB_index))
2136 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
2137 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index+1)%num_nodes);
2141 assert(this->mNodes[vertexA_index]->IsBoundaryNode());
2142 assert(this->mNodes[vertexB_index]->IsBoundaryNode());
2149 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2152 std::set<unsigned> elements_containing_vertex_A = this->mNodes[vertexA_index]->rGetContainingElementIndices();
2153 for (std::set<unsigned>::const_iterator iter = elements_containing_vertex_A.begin();
2154 iter != elements_containing_vertex_A.end();
2157 this->GetElement(*iter)->DeleteNode(this->GetElement(*iter)->GetNodeLocalIndex(vertexA_index));
2161 assert(this->mNodes[vertexA_index]->GetNumContainingElements() == 0);
2162 this->mNodes[vertexA_index]->MarkAsDeleted();
2163 mDeletedNodeIndices.push_back(vertexA_index);
2166 std::set<unsigned> elements_containing_vertex_B = this->mNodes[vertexB_index]->rGetContainingElementIndices();
2167 for (std::set<unsigned>::const_iterator iter = elements_containing_vertex_B.begin();
2168 iter != elements_containing_vertex_B.end();
2171 this->GetElement(*iter)->DeleteNode(this->GetElement(*iter)->GetNodeLocalIndex(vertexB_index));
2175 assert(this->mNodes[vertexB_index]->GetNumContainingElements()==0);
2176 this->mNodes[vertexB_index]->MarkAsDeleted();
2177 mDeletedNodeIndices.push_back(vertexB_index);
2181 if (next_node_1 == vertexA_index || previous_node_1 == vertexA_index || next_node_2 == vertexA_index || previous_node_2 == vertexA_index)
2185 assert(this->mNodes[vertexA_index]->GetNumContainingElements() > 1);
2187 std::set<unsigned> elements_containing_vertex_A = this->mNodes[vertexA_index]->rGetContainingElementIndices();
2188 std::set<unsigned>::const_iterator iter = elements_containing_vertex_A.begin();
2194 unsigned num_common_vertices = 0;
2195 for (
unsigned i=0; i<p_element_common_1->
GetNumNodes(); i++)
2197 for (
unsigned j=0; j<p_element_common_2->
GetNumNodes(); j++)
2201 num_common_vertices++;
2206 if (num_common_vertices == 1 || this->mNodes[vertexA_index]->GetNumContainingElements() > 2)
2222 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
2223 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index+1)%num_nodes);
2226 pNode->
rGetModifiableLocation() = intersection - 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2230 c_vector<double, SPACE_DIM> new_node_location;
2231 new_node_location = intersection + 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2234 unsigned new_node_global_index = this->AddNode(
new Node<SPACE_DIM>(0,
true, new_node_location[0], new_node_location[1]));
2237 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
2238 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2241 if (next_node_1 == previous_node_2)
2247 assert(next_node_2 == previous_node_1);
2254 assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
2256 else if (num_common_vertices == 2)
2273 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
2274 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index+1)%num_nodes);
2277 pNode->
rGetModifiableLocation() = intersection - 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2281 c_vector<double, SPACE_DIM> new_node_location;
2282 new_node_location = intersection + 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2285 unsigned new_node_global_index = this->AddNode(
new Node<SPACE_DIM>(0,
true, new_node_location[0], new_node_location[1]));
2288 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
2289 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2292 if (next_node_1 == previous_node_2)
2298 assert(next_node_2 == previous_node_1);
2306 assert(this->mNodes[vertexA_index]->GetNumContainingElements()==0);
2308 this->mNodes[vertexA_index]->MarkAsDeleted();
2309 mDeletedNodeIndices.push_back(vertexA_index);
2313 assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
2321 else if (next_node_1 == vertexB_index || previous_node_1 == vertexB_index || next_node_2 == vertexB_index || previous_node_2 == vertexB_index)
2325 assert(this->mNodes[vertexB_index]->GetNumContainingElements()>1);
2327 std::set<unsigned> elements_containing_vertex_B = this->mNodes[vertexB_index]->rGetContainingElementIndices();
2328 std::set<unsigned>::const_iterator iter = elements_containing_vertex_B.begin();
2334 unsigned num_common_vertices = 0;
2335 for (
unsigned i=0; i<p_element_common_1->
GetNumNodes(); i++)
2337 for (
unsigned j=0; j<p_element_common_2->
GetNumNodes(); j++)
2341 num_common_vertices++;
2346 if (num_common_vertices == 1 || this->mNodes[vertexB_index]->GetNumContainingElements() > 2)
2362 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
2363 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index+1)%num_nodes);
2366 pNode->
rGetModifiableLocation() = intersection + 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2370 c_vector<double, SPACE_DIM> new_node_location;
2371 new_node_location = intersection - 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2374 unsigned new_node_global_index = this->AddNode(
new Node<SPACE_DIM>(0,
true, new_node_location[0], new_node_location[1]));
2377 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2378 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
2381 if (next_node_1 == previous_node_2)
2383 p_element_2->
AddNode(this->mNodes[new_node_global_index], local_index_2);
2387 assert(next_node_2 == previous_node_1);
2388 p_element_1->
AddNode(this->mNodes[new_node_global_index], local_index_1);
2393 assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
2395 else if (num_common_vertices == 2)
2412 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
2413 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index+1)%num_nodes);
2416 pNode->
rGetModifiableLocation() = intersection + 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2420 c_vector<double, SPACE_DIM> new_node_location;
2421 new_node_location = intersection - 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2424 unsigned new_node_global_index = this->AddNode(
new Node<SPACE_DIM>(0,
true, new_node_location[0], new_node_location[1]));
2427 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2428 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
2431 if (next_node_1 == previous_node_2)
2433 p_element_2->
AddNode(this->mNodes[new_node_global_index], local_index_2);
2437 assert(next_node_2 == previous_node_1);
2438 p_element_1->
AddNode(this->mNodes[new_node_global_index], local_index_1);
2445 assert(this->mNodes[vertexB_index]->GetNumContainingElements()==0);
2447 this->mNodes[vertexB_index]->MarkAsDeleted();
2448 mDeletedNodeIndices.push_back(vertexB_index);
2452 assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
2473 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
2474 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index+1)%num_nodes);
2480 c_vector<double, SPACE_DIM> new_node_1_location;
2481 new_node_1_location = intersection - mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2482 c_vector<double, SPACE_DIM> new_node_2_location;
2483 new_node_2_location = intersection + mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2486 unsigned new_node_1_global_index = this->AddNode(
new Node<SPACE_DIM>(0,
true, new_node_1_location[0], new_node_1_location[1]));
2487 unsigned new_node_2_global_index = this->AddNode(
new Node<SPACE_DIM>(0,
true, new_node_2_location[0], new_node_2_location[1]));
2490 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_2_global_index], node_A_local_index);
2491 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2492 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_1_global_index], node_A_local_index);
2495 if (next_node_1 == previous_node_2)
2498 p_element_2->
AddNode(this->mNodes[new_node_1_global_index], local_index_2);
2502 assert(next_node_2 == previous_node_1);
2504 p_element_1->
AddNode(this->mNodes[new_node_1_global_index], local_index_1);
2510 assert(this->mNodes[new_node_1_global_index]->GetNumContainingElements() == 2);
2511 assert(this->mNodes[new_node_2_global_index]->GetNumContainingElements() == 2);
2517 EXCEPTION(
"Trying to merge a node, contained in more than 2 elements, into another element, this is not possible with the vertex mesh.");
2521 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
2525 c_vector<double, SPACE_DIM> nodes_midpoint = pNodeA->
rGetLocation()
2534 PerformNodeMerge(pNodeA, pNodeB);
2540 p_merged_node = pNodeA;
2543 PerformNodeMerge(pNodeC, p_merged_node);
2547 p_merged_node = pNodeC;
2556 RemoveDeletedNodes();
2559 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
2565 if ((node_a_rank > 3) && (node_b_rank > 3))
2568 EXCEPTION(
"Both nodes involved in a swap event are contained in more than three elements");
2572 assert(node_a_rank > 3 || node_b_rank > 3);
2573 this->PerformRosetteRankIncrease(pNodeA, pNodeB);
2574 this->RemoveDeletedNodes();
2578 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
2586 unsigned node_a_index = pNodeA->
GetIndex();
2587 unsigned node_b_index = pNodeB->
GetIndex();
2592 unsigned lo_rank_index = (node_a_rank < node_b_rank) ? node_a_index : node_b_index;
2593 unsigned hi_rank_index = (node_a_rank < node_b_rank) ? node_b_index : node_a_index;
2629 for (std::set<unsigned>::const_iterator it = lo_rank_elem_indices.begin();
2630 it != lo_rank_elem_indices.end();
2634 unsigned lo_rank_local_index = this->mElements[*it]->GetNodeLocalIndex(lo_rank_index);
2635 assert(lo_rank_local_index < UINT_MAX);
2647 if (hi_rank_elem_indices.count(*it) > 0)
2650 this->mElements[*it]->DeleteNode(lo_rank_local_index);
2655 this->mElements[*it]->UpdateNode(lo_rank_local_index, p_hi_rank_node);
2660 assert(!(this->mNodes[lo_rank_index]->IsDeleted()));
2661 this->mNodes[lo_rank_index]->MarkAsDeleted();
2662 this->mDeletedNodeIndices.push_back(lo_rank_index);
2665 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
2678 std::set<unsigned>::const_iterator elem_index_iter(protorosette_node_containing_elem_indices.begin());
2679 advance(elem_index_iter, random_elem_increment);
2712 unsigned elem_a_idx = *elem_index_iter;
2713 unsigned elem_b_idx = UINT_MAX;
2714 unsigned elem_c_idx = UINT_MAX;
2715 unsigned elem_d_idx = UINT_MAX;
2721 unsigned num_nodes_elem_a = p_elem_a->
GetNumNodes();
2722 unsigned protorosette_node_global_idx = pProtorosetteNode->
GetIndex();
2723 unsigned protorosette_node_local_idx = p_elem_a->
GetNodeLocalIndex(protorosette_node_global_idx);
2726 unsigned prev_node_global_idx = p_elem_a->
GetNodeGlobalIndex((protorosette_node_local_idx + num_nodes_elem_a - 1) % num_nodes_elem_a);
2727 unsigned next_node_global_idx = p_elem_a->
GetNodeGlobalIndex((protorosette_node_local_idx + 1) % num_nodes_elem_a);
2736 std::set<unsigned> intersection_with_prev;
2737 std::set<unsigned> intersection_with_next;
2740 std::set_intersection(protorosette_node_containing_elem_indices.begin(),
2741 protorosette_node_containing_elem_indices.end(),
2742 prev_node_elem_indices.begin(),
2743 prev_node_elem_indices.end(),
2744 std::inserter(intersection_with_prev, intersection_with_prev.begin()));
2747 std::set_intersection(protorosette_node_containing_elem_indices.begin(),
2748 protorosette_node_containing_elem_indices.end(),
2749 next_node_elem_indices.begin(),
2750 next_node_elem_indices.end(),
2751 std::inserter(intersection_with_next, intersection_with_next.begin()));
2753 assert(intersection_with_prev.size() == 2);
2754 assert(intersection_with_next.size() == 2);
2757 if (*intersection_with_prev.begin() != elem_a_idx)
2759 elem_b_idx = *(intersection_with_prev.begin());
2763 elem_b_idx = *(++(intersection_with_prev.begin()));
2765 assert(elem_b_idx < UINT_MAX);
2768 if (*intersection_with_next.begin() != elem_a_idx)
2770 elem_d_idx = *(intersection_with_next.begin());
2774 elem_d_idx = *(++(intersection_with_next.begin()));
2776 assert(elem_d_idx < UINT_MAX);
2779 for (elem_index_iter = protorosette_node_containing_elem_indices.begin();
2780 elem_index_iter != protorosette_node_containing_elem_indices.end();
2783 if ( (*elem_index_iter != elem_a_idx) && (*elem_index_iter != elem_b_idx) && (*elem_index_iter != elem_d_idx) )
2785 elem_c_idx = *elem_index_iter;
2788 assert(elem_c_idx < UINT_MAX);
2808 double swap_distance = (this->mCellRearrangementRatio) * (this->mCellRearrangementThreshold);
2811 c_vector<double, SPACE_DIM> node_to_elem_a_centre = this->GetCentroidOfElement(elem_a_idx) - pProtorosetteNode->
rGetLocation();
2812 node_to_elem_a_centre /= norm_2(node_to_elem_a_centre);
2814 c_vector<double, SPACE_DIM> node_to_elem_c_centre = this->GetCentroidOfElement(elem_c_idx) - pProtorosetteNode->
rGetLocation();
2815 node_to_elem_c_centre /= norm_2(node_to_elem_c_centre);
2818 c_vector<double, SPACE_DIM> new_location_of_protorosette_node = pProtorosetteNode->
rGetLocation() + (0.5 * swap_distance) * node_to_elem_a_centre;
2819 c_vector<double, SPACE_DIM> location_of_new_node = pProtorosetteNode->
rGetLocation() + (0.5 * swap_distance) * node_to_elem_c_centre;
2825 unsigned new_node_global_index = this->AddNode(
new Node<SPACE_DIM>(this->GetNumNodes(), location_of_new_node,
false));
2838 unsigned local_idx_elem_b = p_elem_b->
GetNodeLocalIndex(protorosette_node_global_idx);
2840 unsigned local_idx_elem_c = p_elem_c->
GetNodeLocalIndex(protorosette_node_global_idx);
2841 unsigned local_idx_elem_d = p_elem_d->
GetNodeLocalIndex(protorosette_node_global_idx);
2843 p_elem_b->
AddNode(p_new_node, local_idx_elem_b);
2844 p_elem_c->
AddNode(p_new_node, local_idx_elem_c);
2845 p_elem_d->
AddNode(p_new_node, local_idx_elem_d);
2851 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
2857 assert(rosette_rank > 4);
2866 std::set<unsigned>::const_iterator elem_index_iter(rosette_node_containing_elem_indices.begin());
2867 advance(elem_index_iter, random_elem_increment);
2912 unsigned elem_s_idx = *elem_index_iter;
2915 unsigned elem_n_idx = UINT_MAX;
2916 unsigned elem_p_idx = UINT_MAX;
2919 unsigned num_nodes_elem_s = p_elem_s->
GetNumNodes();
2920 unsigned rosette_node_global_idx = pRosetteNode->
GetIndex();
2921 unsigned rosette_node_local_idx = p_elem_s->
GetNodeLocalIndex(rosette_node_global_idx);
2924 unsigned prev_node_global_idx = p_elem_s->
GetNodeGlobalIndex((rosette_node_local_idx + num_nodes_elem_s - 1) % num_nodes_elem_s);
2925 unsigned next_node_global_idx = p_elem_s->
GetNodeGlobalIndex((rosette_node_local_idx + 1) % num_nodes_elem_s);
2934 std::set<unsigned> intersection_with_prev;
2935 std::set<unsigned> intersection_with_next;
2938 std::set_intersection(rosette_node_containing_elem_indices.begin(),
2939 rosette_node_containing_elem_indices.end(),
2940 prev_node_elem_indices.begin(),
2941 prev_node_elem_indices.end(),
2942 std::inserter(intersection_with_prev, intersection_with_prev.begin()));
2945 std::set_intersection(rosette_node_containing_elem_indices.begin(),
2946 rosette_node_containing_elem_indices.end(),
2947 next_node_elem_indices.begin(),
2948 next_node_elem_indices.end(),
2949 std::inserter(intersection_with_next, intersection_with_next.begin()));
2951 assert(intersection_with_prev.size() == 2);
2952 assert(intersection_with_next.size() == 2);
2955 if (*intersection_with_prev.begin() != elem_s_idx)
2957 elem_n_idx = *intersection_with_prev.begin();
2961 elem_n_idx = *(++(intersection_with_prev.begin()));
2963 assert(elem_n_idx < UINT_MAX);
2966 if (*intersection_with_next.begin() != elem_s_idx)
2968 elem_p_idx = *intersection_with_next.begin();
2972 elem_p_idx = *(++(intersection_with_next.begin()));
2974 assert(elem_p_idx < UINT_MAX);
2989 double swap_distance = (this->mCellRearrangementRatio) * (this->mCellRearrangementThreshold);
2992 c_vector<double, 2> node_to_selected_elem = this->GetCentroidOfElement(elem_s_idx) - pRosetteNode->
rGetLocation();
2993 node_to_selected_elem /= norm_2(node_to_selected_elem);
2994 c_vector<double, 2> new_node_location = pRosetteNode->
rGetLocation() + (swap_distance * node_to_selected_elem);
2997 unsigned new_node_global_index = this->AddNode(
new Node<SPACE_DIM>(this->GetNumNodes(), new_node_location,
false));
3012 unsigned node_local_idx_in_elem_s = p_elem_s->
GetNodeLocalIndex(rosette_node_global_idx);
3013 p_elem_s->
AddNode(p_new_node, node_local_idx_in_elem_s);
3014 p_elem_s->
DeleteNode(node_local_idx_in_elem_s);
3017 unsigned node_local_idx_in_elem_n = p_elem_n->
GetNodeLocalIndex(rosette_node_global_idx);
3018 node_local_idx_in_elem_n = (node_local_idx_in_elem_n + p_elem_n->
GetNumNodes() - 1) % p_elem_n->
GetNumNodes();
3019 p_elem_n->
AddNode(p_new_node, node_local_idx_in_elem_n);
3022 unsigned node_local_idx_in_elem_p = p_elem_p->
GetNodeLocalIndex(rosette_node_global_idx);
3023 p_elem_p->
AddNode(p_new_node, node_local_idx_in_elem_p);
3026 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
3038 std::vector<Node<SPACE_DIM>* > protorosette_nodes;
3039 std::vector<Node<SPACE_DIM>* > rosette_nodes;
3042 unsigned num_nodes = this->GetNumAllNodes();
3043 for (
unsigned node_idx = 0 ; node_idx < num_nodes ; node_idx++)
3053 else if (node_rank == 4)
3058 protorosette_nodes.push_back(current_node);
3066 rosette_nodes.push_back(current_node);
3079 for (
unsigned node_idx = 0 ; node_idx < protorosette_nodes.size() ; node_idx++)
3088 this->PerformProtorosetteResolution(current_node);
3092 for (
unsigned node_idx = 0 ; node_idx < rosette_nodes.size() ; node_idx++)
3101 this->PerformRosetteRankDecrease(current_node);
3105 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
3107 unsigned indexA,
unsigned indexB, c_vector<double,2> intersection)
3118 c_vector<double, SPACE_DIM> vertexA = this->GetNode(indexA)->rGetLocation();
3119 c_vector<double, SPACE_DIM> vertexB = this->GetNode(indexB)->rGetLocation();
3120 c_vector<double, SPACE_DIM> vector_a_to_b = this->GetVectorFromAtoB(vertexA, vertexB);
3122 if (norm_2(vector_a_to_b) < 4.0*mCellRearrangementRatio*mCellRearrangementThreshold)
3124 WARNING(
"Trying to merge a node onto an edge which is too small.");
3126 c_vector<double, SPACE_DIM> centre_a_and_b = vertexA + 0.5*vector_a_to_b;
3128 vertexA = centre_a_and_b - 2.0*mCellRearrangementRatio*mCellRearrangementThreshold*vector_a_to_b/norm_2(vector_a_to_b);
3130 SetNode(indexA, vertex_A_point);
3132 vertexB = centre_a_and_b + 2.0*mCellRearrangementRatio*mCellRearrangementThreshold*vector_a_to_b/norm_2(vector_a_to_b);
3134 SetNode(indexB, vertex_B_point);
3136 intersection = centre_a_and_b;
3140 vector_a_to_b = this->GetVectorFromAtoB(vertexA, vertexB);
3141 c_vector<double,2> edge_ab_unit_vector = vector_a_to_b/norm_2(vector_a_to_b);
3152 if (norm_2(intersection - vertexA) < 2.0*mCellRearrangementRatio*mCellRearrangementThreshold)
3154 intersection = vertexA + 2.0*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
3156 if (norm_2(intersection - vertexB) < 2.0*mCellRearrangementRatio*mCellRearrangementThreshold)
3158 intersection = vertexB - 2.0*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
3160 return intersection;
unsigned DivideElement(VertexElement< ELEMENT_DIM, SPACE_DIM > *pElement, unsigned nodeAIndex, unsigned nodeBIndex, bool placeOriginalElementBelow=false)
void SetRosetteResolutionProbabilityPerTimestep(double rosetteResolutionProbabilityPerTimestep)
double GetRosetteResolutionProbabilityPerTimestep() const
void PerformIntersectionSwap(Node< SPACE_DIM > *pNode, unsigned elementIndex)
double GetCellRearrangementRatio() const
c_vector< double, 2 > WidenEdgeOrCorrectIntersectionLocationIfNecessary(unsigned indexA, unsigned indexB, c_vector< double, 2 > intersection)
std::vector< c_vector< double, SPACE_DIM > > GetLocationsOfT3Swaps()
void RemoveDeletedNodesAndElements(VertexElementMap &rElementMap)
void SetPoint(ChastePoint< SPACE_DIM > point)
void PerformRosetteRankDecrease(Node< SPACE_DIM > *pRosetteNode)
unsigned DivideElementAlongGivenAxis(VertexElement< ELEMENT_DIM, SPACE_DIM > *pElement, c_vector< double, SPACE_DIM > axisOfDivision, bool placeOriginalElementBelow=false)
unsigned randMod(unsigned base)
void SetAsBoundaryNode(bool value=true)
bool CheckForT2Swaps(VertexElementMap &rElementMap)
unsigned GetNodeGlobalIndex(unsigned localIndex) const
std::vector< c_vector< double, SPACE_DIM > > GetLocationsOfT1Swaps()
unsigned DivideElementAlongShortAxis(VertexElement< ELEMENT_DIM, SPACE_DIM > *pElement, bool placeOriginalElementBelow=false)
void PerformNodeMerge(Node< SPACE_DIM > *pNodeA, Node< SPACE_DIM > *pNodeB)
bool CheckForSwapsFromShortEdges()
void SetProtorosetteResolutionProbabilityPerTimestep(double protorosetteResolutionProbabilityPerTimestep)
bool IsBoundaryNode() const
#define EXCEPTION(message)
double GetT2Threshold() const
unsigned AddNode(Node< SPACE_DIM > *pNewNode)
void ReplaceNode(Node< SPACE_DIM > *pOldNode, Node< SPACE_DIM > *pNewNode)
double GetCellRearrangementThreshold() const
void PerformVoidRemoval(Node< SPACE_DIM > *pNodeA, Node< SPACE_DIM > *pNodeB, Node< SPACE_DIM > *pNodeC)
std::set< unsigned > & rGetContainingElementIndices()
void SetIndex(unsigned index)
void ClearLocationsOfT1Swaps()
bool GetCheckForInternalIntersections() const
Node< SPACE_DIM > * GetNode(unsigned localIndex) const
void SetCellRearrangementThreshold(double cellRearrangementThreshold)
bool mMeshChangesDuringSimulation
double GetProtorosetteResolutionProbabilityPerTimestep() const
void PerformT3Swap(Node< SPACE_DIM > *pNode, unsigned elementIndex)
void AddNode(Node< SPACE_DIM > *pNode, const unsigned &rIndex)
std::vector< Node< SPACE_DIM > * > mNodes
virtual void SetNode(unsigned nodeIndex, ChastePoint< SPACE_DIM > point)
unsigned AddElement(VertexElement< ELEMENT_DIM, SPACE_DIM > *pNewElement)
void PerformProtorosetteResolution(Node< SPACE_DIM > *pProtorosetteNode)
bool CheckForIntersections()
void SetDeleted(unsigned index)
unsigned GetNumNodes() const
void PerformRosetteRankIncrease(Node< SPACE_DIM > *pNodeA, Node< SPACE_DIM > *pNodeB)
unsigned GetNumNodes() const
void DeleteNodePriorToReMesh(unsigned index)
double GetProtorosetteFormationProbability() const
void SetNewIndex(unsigned oldIndex, unsigned newIndex)
static RandomNumberGenerator * Instance()
void ClearLocationsOfT3Swaps()
#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)
const c_vector< double, SPACE_DIM > & rGetLocation() const
void AddElement(unsigned index)
void DeleteElementPriorToReMesh(unsigned index)
unsigned GetIndex() const
unsigned GetNumElements() const
void SetCellRearrangementRatio(double cellRearrangementRatio)
void RemoveDeletedNodes()
virtual ~MutableVertexMesh()
void DeleteNode(const unsigned &rIndex)
unsigned GetNumContainingElements() const
double GetNodeLocation(unsigned localIndex, unsigned dimension) const
void PerformT1Swap(Node< SPACE_DIM > *pNodeA, Node< SPACE_DIM > *pNodeB, std::set< unsigned > &rElementsContainingNodes)
unsigned GetIndex() const
unsigned GetNodeLocalIndex(unsigned globalIndex) const
void SetT2Threshold(double t2Threshold)
virtual void IdentifySwapType(Node< SPACE_DIM > *pNodeA, Node< SPACE_DIM > *pNodeB)
std::vector< VertexElement< ELEMENT_DIM-1, SPACE_DIM > * > mFaces
c_vector< double, SPACE_DIM > & rGetModifiableLocation()
c_vector< double, SPACE_DIM > GetLastT2SwapLocation()
void PerformT2Swap(VertexElement< ELEMENT_DIM, SPACE_DIM > &rElement)
void Resize(unsigned size)