00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "MutableVertexMesh.hpp"
00037 #include "UblasCustomFunctions.hpp"
00038 #include "Warnings.hpp"
00039 #include "LogFile.hpp"
00040
00041 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00042 MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::MutableVertexMesh(std::vector<Node<SPACE_DIM>*> nodes,
00043 std::vector<VertexElement<ELEMENT_DIM,SPACE_DIM>*> vertexElements,
00044 double cellRearrangementThreshold,
00045 double t2Threshold,
00046 double cellRearrangementRatio)
00047 : mCellRearrangementThreshold(cellRearrangementThreshold),
00048 mCellRearrangementRatio(cellRearrangementRatio),
00049 mT2Threshold(t2Threshold),
00050 mCheckForInternalIntersections(false)
00051 {
00052
00053 assert(cellRearrangementThreshold > 0.0);
00054 assert(t2Threshold > 0.0);
00055
00056
00057 Clear();
00058
00059
00060 for (unsigned node_index=0; node_index<nodes.size(); node_index++)
00061 {
00062 Node<SPACE_DIM>* p_temp_node = nodes[node_index];
00063 this->mNodes.push_back(p_temp_node);
00064 }
00065 for (unsigned elem_index=0; elem_index<vertexElements.size(); elem_index++)
00066 {
00067 VertexElement<ELEMENT_DIM,SPACE_DIM>* p_temp_vertex_element = vertexElements[elem_index];
00068 this->mElements.push_back(p_temp_vertex_element);
00069 }
00070
00071
00072 if (SPACE_DIM == 3)
00073 {
00074
00075 std::set<unsigned> faces_counted;
00076
00077
00078 for (unsigned elem_index=0; elem_index<this->mElements.size(); elem_index++)
00079 {
00080
00081 for (unsigned face_index=0; face_index<this->mElements[elem_index]->GetNumFaces(); face_index++)
00082 {
00083 VertexElement<ELEMENT_DIM-1, SPACE_DIM>* p_face = this->mElements[elem_index]->GetFace(face_index);
00084
00085
00086 if (faces_counted.find(p_face->GetIndex()) == faces_counted.end())
00087 {
00088 this->mFaces.push_back(p_face);
00089 faces_counted.insert(p_face->GetIndex());
00090 }
00091 }
00092 }
00093 }
00094
00095
00096 for (unsigned index=0; index<this->mElements.size(); index++)
00097 {
00098 VertexElement<ELEMENT_DIM,SPACE_DIM>* p_temp_vertex_element = this->mElements[index];
00099 for (unsigned node_index=0; node_index<p_temp_vertex_element->GetNumNodes(); node_index++)
00100 {
00101 Node<SPACE_DIM>* p_temp_node = p_temp_vertex_element->GetNode(node_index);
00102 p_temp_node->AddElement(p_temp_vertex_element->GetIndex());
00103 }
00104 }
00105
00106 this->mMeshChangesDuringSimulation = true;
00107 }
00108
00109 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00110 MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::MutableVertexMesh()
00111 : mCellRearrangementThreshold(0.01),
00112 mCellRearrangementRatio(1.5),
00113 mT2Threshold(0.001),
00114 mCheckForInternalIntersections(false)
00115 {
00116
00117 this->mMeshChangesDuringSimulation = true;
00118 Clear();
00119 }
00120
00121 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00122 MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::~MutableVertexMesh()
00123 {
00124 Clear();
00125 }
00126
00127 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00128 double MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::GetCellRearrangementThreshold() const
00129 {
00130 return mCellRearrangementThreshold;
00131 }
00132
00133 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00134 double MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::GetT2Threshold() const
00135 {
00136 return mT2Threshold;
00137 }
00138
00139 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00140 double MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::GetCellRearrangementRatio() const
00141 {
00142 return mCellRearrangementRatio;
00143 }
00144
00145 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00146 bool MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::GetCheckForInternalIntersections() const
00147 {
00148 return mCheckForInternalIntersections;
00149 }
00150
00151 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00152 void MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::SetCellRearrangementThreshold(double cellRearrangementThreshold)
00153 {
00154 mCellRearrangementThreshold = cellRearrangementThreshold;
00155 }
00156
00157 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00158 void MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::SetT2Threshold(double t2Threshold)
00159 {
00160 mT2Threshold = t2Threshold;
00161 }
00162
00163 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00164 void MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::SetCellRearrangementRatio(double cellRearrangementRatio)
00165 {
00166 mCellRearrangementRatio = cellRearrangementRatio;
00167 }
00168
00169 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00170 void MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::SetCheckForInternalIntersections(bool checkForInternalIntersections)
00171 {
00172 mCheckForInternalIntersections = checkForInternalIntersections;
00173 }
00174
00175 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00176 void MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::Clear()
00177 {
00178 mDeletedNodeIndices.clear();
00179 mDeletedElementIndices.clear();
00180
00181 VertexMesh<ELEMENT_DIM, SPACE_DIM>::Clear();
00182 }
00183
00184 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00185 unsigned MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::GetNumNodes() const
00186 {
00187 return this->mNodes.size() - mDeletedNodeIndices.size();
00188 }
00189
00190 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00191 unsigned MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::GetNumElements() const
00192 {
00193 return this->mElements.size() - mDeletedElementIndices.size();
00194 }
00195
00196 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00197 std::vector< c_vector<double, SPACE_DIM> > MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::GetLocationsOfT1Swaps()
00198 {
00199 return mLocationsOfT1Swaps;
00200 }
00201
00202 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00203 c_vector<double, SPACE_DIM> MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::GetLastT2SwapLocation()
00204 {
00205 return mLastT2SwapLocation;
00206 }
00207
00208 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00209 std::vector< c_vector<double, SPACE_DIM> > MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::GetLocationsOfT3Swaps()
00210 {
00211 return mLocationsOfT3Swaps;
00212 }
00213
00214 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00215 void MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::ClearLocationsOfT1Swaps()
00216 {
00217 mLocationsOfT1Swaps.clear();
00218 }
00219
00220 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00221 void MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::ClearLocationsOfT3Swaps()
00222 {
00223 mLocationsOfT3Swaps.clear();
00224 }
00225
00226 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00227 unsigned MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::AddNode(Node<SPACE_DIM>* pNewNode)
00228 {
00229 if (mDeletedNodeIndices.empty())
00230 {
00231 pNewNode->SetIndex(this->mNodes.size());
00232 this->mNodes.push_back(pNewNode);
00233 }
00234 else
00235 {
00236 unsigned index = mDeletedNodeIndices.back();
00237 pNewNode->SetIndex(index);
00238 mDeletedNodeIndices.pop_back();
00239 delete this->mNodes[index];
00240 this->mNodes[index] = pNewNode;
00241 }
00242 return pNewNode->GetIndex();
00243 }
00244
00245 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00246 unsigned MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::AddElement(VertexElement<ELEMENT_DIM,SPACE_DIM>* pNewElement)
00247 {
00248 unsigned new_element_index = pNewElement->GetIndex();
00249
00250 if (new_element_index == this->mElements.size())
00251 {
00252 this->mElements.push_back(pNewElement);
00253 }
00254 else
00255 {
00256 this->mElements[new_element_index] = pNewElement;
00257 }
00258 pNewElement->RegisterWithNodes();
00259 return pNewElement->GetIndex();
00260 }
00261
00262 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00263 void MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::SetNode(unsigned nodeIndex, ChastePoint<SPACE_DIM> point)
00264 {
00265 this->mNodes[nodeIndex]->SetPoint(point);
00266 }
00267
00268 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00269 unsigned MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::DivideElementAlongGivenAxis(VertexElement<ELEMENT_DIM,SPACE_DIM>* pElement,
00270 c_vector<double, SPACE_DIM> axisOfDivision,
00271 bool placeOriginalElementBelow)
00272 {
00273 assert(SPACE_DIM == 2);
00274 assert(ELEMENT_DIM == SPACE_DIM);
00275
00276
00277 c_vector<double, SPACE_DIM> centroid = this->GetCentroidOfElement(pElement->GetIndex());
00278
00279
00280 c_vector<double, SPACE_DIM> perp_axis;
00281 perp_axis(0) = -axisOfDivision(1);
00282 perp_axis(1) = axisOfDivision(0);
00283
00284
00285
00286
00287
00288
00289 unsigned num_nodes = pElement->GetNumNodes();
00290 std::vector<unsigned> intersecting_nodes;
00291 bool is_current_node_on_left = (inner_prod(this->GetVectorFromAtoB(pElement->GetNodeLocation(0), centroid), perp_axis) >= 0);
00292 for (unsigned i=0; i<num_nodes; i++)
00293 {
00294 bool is_next_node_on_left = (inner_prod(this->GetVectorFromAtoB(pElement->GetNodeLocation((i+1)%num_nodes), centroid), perp_axis) >= 0);
00295 if (is_current_node_on_left != is_next_node_on_left)
00296 {
00297 intersecting_nodes.push_back(i);
00298 }
00299 is_current_node_on_left = is_next_node_on_left;
00300 }
00301
00302
00303 if (intersecting_nodes.size() != 2)
00304 {
00305 EXCEPTION("Cannot proceed with element division: the given axis of division does not cross two edges of the element");
00306 }
00307
00308 std::vector<unsigned> division_node_global_indices;
00309 unsigned nodes_added = 0;
00310
00311
00312 for (unsigned i=0; i<intersecting_nodes.size(); i++)
00313 {
00314
00315
00316
00317
00318
00319
00320
00321 Node<SPACE_DIM>* p_node_A = pElement->GetNode((intersecting_nodes[i]+nodes_added)%pElement->GetNumNodes());
00322 Node<SPACE_DIM>* p_node_B = pElement->GetNode((intersecting_nodes[i]+nodes_added+1)%pElement->GetNumNodes());
00323
00324
00325 std::set<unsigned> elems_containing_node_A = p_node_A->rGetContainingElementIndices();
00326 std::set<unsigned> elems_containing_node_B = p_node_B->rGetContainingElementIndices();
00327
00328 c_vector<double, SPACE_DIM> position_a = p_node_A->rGetLocation();
00329 c_vector<double, SPACE_DIM> position_b = p_node_B->rGetLocation();
00330 c_vector<double, SPACE_DIM> a_to_b = this->GetVectorFromAtoB(position_a, position_b);
00331
00332 c_vector<double, SPACE_DIM> intersection;
00333
00334 if (norm_2(a_to_b) < 2.0*mCellRearrangementRatio*mCellRearrangementThreshold)
00335 {
00336 WARNING("Edge is too small for normal division; putting node in the middle of a and b. There may be T1 swaps straight away.");
00338 intersection = position_a + 0.5*a_to_b;
00339 }
00340 else
00341 {
00342
00343 double determinant = a_to_b[0]*axisOfDivision[1] - a_to_b[1]*axisOfDivision[0];
00344
00345
00346 c_vector<double, SPACE_DIM> moved_centroid;
00347 moved_centroid = position_a + this->GetVectorFromAtoB(position_a, centroid);
00348
00349 double alpha = (moved_centroid[0]*a_to_b[1] - position_a[0]*a_to_b[1]
00350 -moved_centroid[1]*a_to_b[0] + position_a[1]*a_to_b[0])/determinant;
00351
00352 intersection = moved_centroid + alpha*axisOfDivision;
00353
00354
00355
00356
00357
00358 c_vector<double, SPACE_DIM> a_to_intersection = this->GetVectorFromAtoB(position_a, intersection);
00359 if (norm_2(a_to_intersection) < mCellRearrangementThreshold)
00360 {
00361 intersection = position_a + mCellRearrangementRatio*mCellRearrangementThreshold*a_to_b/norm_2(a_to_b);
00362 }
00363
00364 c_vector<double, SPACE_DIM> b_to_intersection = this->GetVectorFromAtoB(position_b, intersection);
00365 if (norm_2(b_to_intersection) < mCellRearrangementThreshold)
00366 {
00367 assert(norm_2(a_to_intersection) > mCellRearrangementThreshold);
00368
00369 intersection = position_b - mCellRearrangementRatio*mCellRearrangementThreshold*a_to_b/norm_2(a_to_b);
00370 }
00371 }
00372
00373
00374
00375
00376
00377
00378
00379
00380 bool is_boundary = false;
00381 if (p_node_A->IsBoundaryNode() && p_node_B->IsBoundaryNode())
00382 {
00383 if (elems_containing_node_A.size() != 2 ||
00384 elems_containing_node_B.size() != 2 ||
00385 elems_containing_node_A != elems_containing_node_B)
00386 {
00387 is_boundary = true;
00388 }
00389 }
00390
00391
00392 unsigned new_node_global_index = this->AddNode(new Node<SPACE_DIM>(0, is_boundary, intersection[0], intersection[1]));
00393 nodes_added++;
00394
00395
00396
00397
00398 std::set<unsigned> shared_elements;
00399 std::set_intersection(elems_containing_node_A.begin(),
00400 elems_containing_node_A.end(),
00401 elems_containing_node_B.begin(),
00402 elems_containing_node_B.end(),
00403 std::inserter(shared_elements, shared_elements.begin()));
00404
00405
00406 unsigned node_A_index = p_node_A->GetIndex();
00407 unsigned node_B_index = p_node_B->GetIndex();
00408 for (std::set<unsigned>::iterator iter = shared_elements.begin();
00409 iter != shared_elements.end();
00410 ++iter)
00411 {
00412 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = this->GetElement(*iter);
00413
00414
00415 unsigned local_indexA = p_element->GetNodeLocalIndex(node_A_index);
00416 unsigned local_indexB = p_element->GetNodeLocalIndex(node_B_index);
00417
00418 unsigned index = local_indexB;
00419
00420
00421 if (local_indexB > local_indexA)
00422 {
00423 index = local_indexA;
00424
00425
00426 if ((local_indexA == 0) && (local_indexB == p_element->GetNumNodes()-1))
00427 {
00428 index = local_indexB;
00429 }
00430 }
00431 else if ((local_indexB == 0) && (local_indexA == p_element->GetNumNodes()-1))
00432 {
00433
00434 index = local_indexA;
00435 }
00436
00437
00438 this->GetElement(*iter)->AddNode(this->GetNode(new_node_global_index), index);
00439 }
00440
00441
00442 division_node_global_indices.push_back(new_node_global_index);
00443 }
00444
00445
00446 unsigned new_element_index = DivideElement(pElement,
00447 pElement->GetNodeLocalIndex(division_node_global_indices[0]),
00448 pElement->GetNodeLocalIndex(division_node_global_indices[1]),
00449 placeOriginalElementBelow);
00450
00451 return new_element_index;
00452 }
00453
00454 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00455 unsigned MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::DivideElementAlongShortAxis(VertexElement<ELEMENT_DIM,SPACE_DIM>* pElement,
00456 bool placeOriginalElementBelow)
00457 {
00458 assert(SPACE_DIM == 2);
00459 assert(ELEMENT_DIM == SPACE_DIM);
00460
00461 c_vector<double, SPACE_DIM> short_axis = this->GetShortAxisOfElement(pElement->GetIndex());
00462
00463 unsigned new_element_index = DivideElementAlongGivenAxis(pElement, short_axis, placeOriginalElementBelow);
00464 return new_element_index;
00465 }
00466
00467 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00468 unsigned MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::DivideElement(VertexElement<ELEMENT_DIM,SPACE_DIM>* pElement,
00469 unsigned nodeAIndex,
00470 unsigned nodeBIndex,
00471 bool placeOriginalElementBelow)
00472 {
00473 assert(SPACE_DIM == 2);
00474 assert(ELEMENT_DIM == SPACE_DIM);
00475
00476
00477 assert(nodeBIndex != nodeAIndex);
00478 unsigned node1_index = (nodeAIndex < nodeBIndex) ? nodeAIndex : nodeBIndex;
00479 unsigned node2_index = (nodeAIndex < nodeBIndex) ? nodeBIndex : nodeAIndex;
00480
00481
00482 unsigned num_nodes = pElement->GetNumNodes();
00483
00484
00485 std::vector<Node<SPACE_DIM>*> nodes_elem;
00486 for (unsigned i=0; i<num_nodes; i++)
00487 {
00488 nodes_elem.push_back(pElement->GetNode(i));
00489 }
00490
00491
00492 unsigned new_element_index;
00493 if (mDeletedElementIndices.empty())
00494 {
00495 new_element_index = this->mElements.size();
00496 }
00497 else
00498 {
00499 new_element_index = mDeletedElementIndices.back();
00500 mDeletedElementIndices.pop_back();
00501 delete this->mElements[new_element_index];
00502 }
00503
00504
00505 AddElement(new VertexElement<ELEMENT_DIM,SPACE_DIM>(new_element_index, nodes_elem));
00506
00513
00515 double height_midpoint_1 = 0.0;
00516 double height_midpoint_2 = 0.0;
00517 unsigned counter_1 = 0;
00518 unsigned counter_2 = 0;
00519
00520 for (unsigned i=0; i<num_nodes; i++)
00521 {
00522 if (i>=node1_index && i<=node2_index)
00523 {
00524 height_midpoint_1 += pElement->GetNode(i)->rGetLocation()[1];
00525 counter_1++;
00526 }
00527 if (i<=node1_index || i>=node2_index)
00528 {
00529 height_midpoint_2 += pElement->GetNode(i)->rGetLocation()[1];
00530 counter_2++;
00531 }
00532 }
00533 height_midpoint_1 /= (double)counter_1;
00534 height_midpoint_2 /= (double)counter_2;
00535
00536 for (unsigned i=num_nodes; i>0; i--)
00537 {
00538 if (i-1 < node1_index || i-1 > node2_index)
00539 {
00540 if (height_midpoint_1 < height_midpoint_2)
00541 {
00542 if (placeOriginalElementBelow)
00543 {
00544 pElement->DeleteNode(i-1);
00545 }
00546 else
00547 {
00548 this->mElements[new_element_index]->DeleteNode(i-1);
00549 }
00550 }
00551 else
00552 {
00553 if (placeOriginalElementBelow)
00554 {
00555 this->mElements[new_element_index]->DeleteNode(i-1);
00556 }
00557 else
00558 {
00559 pElement->DeleteNode(i-1);
00560 }
00561 }
00562 }
00563 else if (i-1 > node1_index && i-1 < node2_index)
00564 {
00565 if (height_midpoint_1 < height_midpoint_2)
00566 {
00567 if (placeOriginalElementBelow)
00568 {
00569 this->mElements[new_element_index]->DeleteNode(i-1);
00570 }
00571 else
00572 {
00573 pElement->DeleteNode(i-1);
00574 }
00575 }
00576 else
00577 {
00578 if (placeOriginalElementBelow)
00579 {
00580 pElement->DeleteNode(i-1);
00581 }
00582 else
00583 {
00584 this->mElements[new_element_index]->DeleteNode(i-1);
00585 }
00586 }
00587 }
00588 }
00589
00590 return new_element_index;
00591 }
00592
00593 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00594 void MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::DeleteElementPriorToReMesh(unsigned index)
00595 {
00596 assert(SPACE_DIM == 2);
00597
00598
00599 for (unsigned i=0; i<this->mElements[index]->GetNumNodes(); i++)
00600 {
00601 Node<SPACE_DIM>* p_node = this->mElements[index]->GetNode(i);
00602
00603 if (p_node->rGetContainingElementIndices().size() == 1)
00604 {
00605 DeleteNodePriorToReMesh(p_node->GetIndex());
00606 }
00607
00608
00609 p_node->SetAsBoundaryNode(true);
00610 }
00611
00612
00613 this->mElements[index]->MarkAsDeleted();
00614 mDeletedElementIndices.push_back(index);
00615 }
00616
00617 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00618 void MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::DeleteNodePriorToReMesh(unsigned index)
00619 {
00620 this->mNodes[index]->MarkAsDeleted();
00621 mDeletedNodeIndices.push_back(index);
00622 }
00623
00624 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00625 void MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::DivideEdge(Node<SPACE_DIM>* pNodeA, Node<SPACE_DIM>* pNodeB)
00626 {
00627
00628 std::set<unsigned> elements_containing_nodeA = pNodeA->rGetContainingElementIndices();
00629 std::set<unsigned> elements_containing_nodeB = pNodeB->rGetContainingElementIndices();
00630
00631
00632 std::set<unsigned> shared_elements;
00633 std::set_intersection(elements_containing_nodeA.begin(),
00634 elements_containing_nodeA.end(),
00635 elements_containing_nodeB.begin(),
00636 elements_containing_nodeB.end(),
00637 std::inserter(shared_elements, shared_elements.begin()));
00638
00639
00640 assert(!shared_elements.empty());
00641 assert(shared_elements.size()<=2u);
00642
00643
00644 bool is_boundary_node = false;
00645 if (shared_elements.size()==1u)
00646 {
00647
00648 assert((pNodeA->IsBoundaryNode()) && (pNodeB->IsBoundaryNode()));
00649 is_boundary_node = true;
00650 }
00651
00652
00653 Node<SPACE_DIM>* p_new_node = new Node<SPACE_DIM>(GetNumNodes(), is_boundary_node, 0.0, 0.0);
00654
00655
00656 c_vector<double, SPACE_DIM> new_node_position = pNodeA->rGetLocation() + 0.5*this->GetVectorFromAtoB(pNodeA->rGetLocation(), pNodeB->rGetLocation());
00657 ChastePoint<SPACE_DIM> point(new_node_position);
00658 p_new_node->SetPoint(new_node_position);
00659
00660
00661 this->mNodes.push_back(p_new_node);
00662
00663
00664 unsigned node_A_index = pNodeA->GetIndex();
00665 unsigned node_B_index = pNodeB->GetIndex();
00666 for (std::set<unsigned>::iterator iter = shared_elements.begin();
00667 iter != shared_elements.end();
00668 ++iter)
00669 {
00670 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = this->GetElement(*iter);
00671
00672
00673 unsigned local_indexA = p_element->GetNodeLocalIndex(node_A_index);
00674 unsigned local_indexB = p_element->GetNodeLocalIndex(node_B_index);
00675
00676 unsigned index = local_indexB;
00677
00678
00679 if (local_indexB > local_indexA)
00680 {
00681 index = local_indexA;
00682
00683
00684 if ((local_indexA == 0) && (local_indexB == p_element->GetNumNodes()-1))
00685 {
00686 index = local_indexB;
00687 }
00688 }
00689 else if ((local_indexB == 0) && (local_indexA == p_element->GetNumNodes()-1))
00690 {
00691
00692 index = local_indexA;
00693 }
00694
00695
00696 this->GetElement(*iter)->AddNode(p_new_node, index);
00697 }
00698 }
00699
00700 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00701 void MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::RemoveDeletedNodesAndElements(VertexElementMap& rElementMap)
00702 {
00703
00704 rElementMap.Resize(this->GetNumAllElements());
00705
00706
00707 std::vector<VertexElement<ELEMENT_DIM, SPACE_DIM>*> live_elements;
00708 for (unsigned i=0; i<this->mElements.size(); i++)
00709 {
00710 if (this->mElements[i]->IsDeleted())
00711 {
00712 delete this->mElements[i];
00713 rElementMap.SetDeleted(i);
00714 }
00715 else
00716 {
00717 live_elements.push_back(this->mElements[i]);
00718 rElementMap.SetNewIndex(i, (unsigned)(live_elements.size()-1));
00719 }
00720 }
00721
00722
00723 assert(mDeletedElementIndices.size() == this->mElements.size() - live_elements.size());
00724
00725
00726 mDeletedElementIndices.clear();
00727 this->mElements = live_elements;
00728
00729
00730 for (unsigned i=0; i<this->mElements.size(); i++)
00731 {
00732 this->mElements[i]->ResetIndex(i);
00733 }
00734
00735
00736 RemoveDeletedNodes();
00737 }
00738
00739 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00740 void MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::RemoveDeletedNodes()
00741 {
00742
00743 std::vector<Node<SPACE_DIM>*> live_nodes;
00744 for (unsigned i=0; i<this->mNodes.size(); i++)
00745 {
00746 if (this->mNodes[i]->IsDeleted())
00747 {
00748 delete this->mNodes[i];
00749 }
00750 else
00751 {
00752 live_nodes.push_back(this->mNodes[i]);
00753 }
00754 }
00755
00756
00757 assert(mDeletedNodeIndices.size() == this->mNodes.size() - live_nodes.size());
00758
00759
00760 this->mNodes = live_nodes;
00761 mDeletedNodeIndices.clear();
00762
00763
00764 for (unsigned i=0; i<this->mNodes.size(); i++)
00765 {
00766 this->mNodes[i]->SetIndex(i);
00767 }
00768 }
00769
00770 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00771 void MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::ReMesh(VertexElementMap& rElementMap)
00772 {
00773
00774 assert(SPACE_DIM==2 || SPACE_DIM==3);
00775 assert(ELEMENT_DIM == SPACE_DIM);
00776
00777 if (SPACE_DIM == 2)
00778 {
00779
00780 rElementMap.Resize(this->GetNumAllElements());
00781
00782
00783
00784
00785
00786
00787 RemoveDeletedNodesAndElements(rElementMap);
00788 bool recheck_mesh = true;
00789 while (recheck_mesh == true)
00790 {
00791
00792 recheck_mesh = CheckForSwapsFromShortEdges();
00793 }
00794
00795
00796 recheck_mesh = true;
00797 while (recheck_mesh == true)
00798 {
00799
00800 recheck_mesh = CheckForIntersections();
00801 }
00802
00803 RemoveDeletedNodes();
00804 }
00805 else
00806 {
00807 #define COVERAGE_IGNORE
00808 EXCEPTION("Remeshing has not been implemented in 3D (see #827 and #860)\n");
00809 #undef COVERAGE_IGNORE
00811 }
00812 }
00813
00814 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00815 void MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::ReMesh()
00816 {
00817 VertexElementMap map(GetNumElements());
00818 ReMesh(map);
00819 }
00820
00821 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00822 bool MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::CheckForSwapsFromShortEdges()
00823 {
00824
00825 for (typename VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator elem_iter = this->GetElementIteratorBegin();
00826 elem_iter != this->GetElementIteratorEnd();
00827 ++elem_iter)
00828 {
00830
00831 unsigned num_nodes = elem_iter->GetNumNodes();
00832 assert(num_nodes > 0);
00833
00834
00835 for (unsigned local_index=0; local_index<num_nodes; local_index++)
00836 {
00837
00838 Node<SPACE_DIM>* p_current_node = elem_iter->GetNode(local_index);
00839 unsigned local_index_plus_one = (local_index+1)%num_nodes;
00840 Node<SPACE_DIM>* p_anticlockwise_node = elem_iter->GetNode(local_index_plus_one);
00841
00842
00843 double distance_between_nodes = this->GetDistanceBetweenNodes(p_current_node->GetIndex(), p_anticlockwise_node->GetIndex());
00844
00845
00846 if (distance_between_nodes < mCellRearrangementThreshold)
00847 {
00848
00849 std::set<unsigned> elements_of_node_a = p_current_node->rGetContainingElementIndices();
00850 std::set<unsigned> elements_of_node_b = p_anticlockwise_node->rGetContainingElementIndices();
00851
00852 std::set<unsigned> shared_elements;
00853 std::set_intersection(elements_of_node_a.begin(), elements_of_node_a.end(),
00854 elements_of_node_b.begin(), elements_of_node_b.end(),
00855 std::inserter(shared_elements, shared_elements.begin()));
00856
00857 bool both_nodes_share_triangular_element = false;
00858 for (std::set<unsigned>::const_iterator it = shared_elements.begin();
00859 it != shared_elements.end();
00860 ++it)
00861 {
00862 if (this->GetElement(*it)->GetNumNodes() <= 3)
00863 {
00864 both_nodes_share_triangular_element = true;
00865 break;
00866 }
00867 }
00868
00869
00870 if (!both_nodes_share_triangular_element)
00871 {
00872 IdentifySwapType(p_current_node, p_anticlockwise_node);
00873 return true;
00874 }
00875 }
00876 }
00877 }
00878
00879 return false;
00880 }
00881
00882 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00883 bool MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::CheckForT2Swaps(VertexElementMap& rElementMap)
00884 {
00885
00886 for (typename VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator elem_iter = this->GetElementIteratorBegin();
00887 elem_iter != this->GetElementIteratorEnd();
00888 ++elem_iter)
00889 {
00890
00891 if (elem_iter->GetNumNodes() == 3)
00892 {
00893
00894 if (this->GetVolumeOfElement(elem_iter->GetIndex()) < GetT2Threshold())
00895 {
00896
00897 PerformT2Swap(*elem_iter);
00899 rElementMap.SetDeleted(elem_iter->GetIndex());
00900 return true;
00901 }
00902 }
00903 }
00904 return false;
00905 }
00906
00907 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00908 bool MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::CheckForIntersections()
00909 {
00910
00911 if (mCheckForInternalIntersections)
00912 {
00914 for (typename AbstractMesh<ELEMENT_DIM,SPACE_DIM>::NodeIterator node_iter = this->GetNodeIteratorBegin();
00915 node_iter != this->GetNodeIteratorEnd();
00916 ++node_iter)
00917 {
00918 assert(!(node_iter->IsDeleted()));
00919
00920 for (typename VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator elem_iter = this->GetElementIteratorBegin();
00921 elem_iter != this->GetElementIteratorEnd();
00922 ++elem_iter)
00923 {
00924 unsigned elem_index = elem_iter->GetIndex();
00925
00926
00927 if (node_iter->rGetContainingElementIndices().count(elem_index) == 0)
00928 {
00929 if (this->ElementIncludesPoint(node_iter->rGetLocation(), elem_index))
00930 {
00931 PerformIntersectionSwap(&(*node_iter), elem_index);
00932 return true;
00933 }
00934 }
00935 }
00936 }
00937 }
00938 else
00939 {
00940
00941 std::set<unsigned> boundary_element_indices;
00942 for (typename VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator elem_iter = this->GetElementIteratorBegin();
00943 elem_iter != this->GetElementIteratorEnd();
00944 ++elem_iter)
00945 {
00946 if (elem_iter->IsElementOnBoundary())
00947 {
00948 boundary_element_indices.insert(elem_iter->GetIndex());
00949 }
00950 }
00951
00952 for (typename AbstractMesh<ELEMENT_DIM,SPACE_DIM>::NodeIterator node_iter = this->GetNodeIteratorBegin();
00953 node_iter != this->GetNodeIteratorEnd();
00954 ++node_iter)
00955 {
00956 if (node_iter->IsBoundaryNode())
00957 {
00958 assert(!(node_iter->IsDeleted()));
00959
00960 for (std::set<unsigned>::iterator elem_iter = boundary_element_indices.begin();
00961 elem_iter != boundary_element_indices.end();
00962 ++elem_iter)
00963 {
00964
00965 if (node_iter->rGetContainingElementIndices().count(*elem_iter) == 0)
00966 {
00967 if (this->ElementIncludesPoint(node_iter->rGetLocation(), *elem_iter))
00968 {
00969 PerformT3Swap(&(*node_iter), *elem_iter);
00970 return true;
00971 }
00972 }
00973 }
00974 }
00975 }
00976 }
00977
00978 return false;
00979 }
00980
00981 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00982 void MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::IdentifySwapType(Node<SPACE_DIM>* pNodeA, Node<SPACE_DIM>* pNodeB)
00983 {
00984
00985 std::set<unsigned> nodeA_elem_indices = pNodeA->rGetContainingElementIndices();
00986 std::set<unsigned> nodeB_elem_indices = pNodeB->rGetContainingElementIndices();
00987
00988
00989 std::set<unsigned> all_indices, temp_union_set;
00990 std::set_union(nodeA_elem_indices.begin(), nodeA_elem_indices.end(),
00991 nodeB_elem_indices.begin(), nodeB_elem_indices.end(),
00992 std::inserter(temp_union_set, temp_union_set.begin()));
00993 all_indices.swap(temp_union_set);
00994
00995
00996 if ((nodeA_elem_indices.size()>3) || (nodeB_elem_indices.size()>3))
00997 {
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008 EXCEPTION("A node is contained in more than three elements");
01009 }
01010 else
01011 {
01012 switch (all_indices.size())
01013 {
01014 case 1:
01015 {
01016
01017
01018
01019
01020
01021
01022
01023
01024 assert(pNodeA->IsBoundaryNode());
01025 assert(pNodeB->IsBoundaryNode());
01026
01027 PerformNodeMerge(pNodeA, pNodeB);
01028 RemoveDeletedNodes();
01029 break;
01030 }
01031 case 2:
01032 {
01033 if (nodeA_elem_indices.size()==2 && nodeB_elem_indices.size()==2)
01034 {
01035 if (pNodeA->IsBoundaryNode() && pNodeB->IsBoundaryNode())
01036 {
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047 PerformT1Swap(pNodeA, pNodeB,all_indices);
01048 }
01049 else if (pNodeA->IsBoundaryNode() || pNodeB->IsBoundaryNode())
01050 {
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062 EXCEPTION("There is a non-boundary node contained only in two elements; something has gone wrong.");
01063 }
01064 else
01065 {
01066
01067
01068
01069
01070
01071
01072
01073
01074 EXCEPTION("There are non-boundary nodes contained only in two elements; something has gone wrong.");
01075 }
01076 }
01077 else
01078 {
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093 PerformNodeMerge(pNodeA, pNodeB);
01094 RemoveDeletedNodes();
01095 }
01096 break;
01097 }
01098 case 3:
01099 {
01100 if (nodeA_elem_indices.size()==1 || nodeB_elem_indices.size()==1)
01101 {
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115 assert(pNodeA->IsBoundaryNode());
01116 assert(pNodeB->IsBoundaryNode());
01117
01118 EXCEPTION("There is a boundary node contained in three elements something has gone wrong.");
01119 }
01120 else if (nodeA_elem_indices.size()==2 && nodeB_elem_indices.size()==2)
01121 {
01122
01123
01124
01125
01126
01127
01128 std::set<unsigned> element_A_not_B, temp_set;
01129 std::set_difference(all_indices.begin(), all_indices.end(), nodeB_elem_indices.begin(),
01130 nodeB_elem_indices.end(), std::inserter(temp_set, temp_set.begin()));
01131 element_A_not_B.swap(temp_set);
01132
01133
01134 assert(element_A_not_B.size() == 1);
01135
01136 std::set<unsigned> element_B_not_A;
01137 std::set_difference(all_indices.begin(), all_indices.end(), nodeA_elem_indices.begin(),
01138 nodeA_elem_indices.end(), std::inserter(temp_set, temp_set.begin()));
01139 element_B_not_A.swap(temp_set);
01140
01141
01142 assert(element_B_not_A.size() == 1);
01143
01144 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_A_not_B = this->mElements[*element_A_not_B.begin()];
01145 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_B_not_A = this->mElements[*element_B_not_A.begin()];
01146
01147 unsigned local_index_1 = p_element_A_not_B->GetNodeLocalIndex(pNodeA->GetIndex());
01148 unsigned next_node_1 = p_element_A_not_B->GetNodeGlobalIndex((local_index_1 + 1)%(p_element_A_not_B->GetNumNodes()));
01149 unsigned previous_node_1 = p_element_A_not_B->GetNodeGlobalIndex(
01150 (local_index_1 + p_element_A_not_B->GetNumNodes() - 1)%(p_element_A_not_B->GetNumNodes()));
01151 unsigned local_index_2 = p_element_B_not_A->GetNodeLocalIndex(pNodeB->GetIndex());
01152 unsigned next_node_2 = p_element_B_not_A->GetNodeGlobalIndex(
01153 (local_index_2 + 1)%(p_element_B_not_A->GetNumNodes()));
01154 unsigned previous_node_2 = p_element_B_not_A->GetNodeGlobalIndex(
01155 (local_index_2 + p_element_B_not_A->GetNumNodes() - 1)%(p_element_B_not_A->GetNumNodes()));
01156
01157 if (next_node_1 == previous_node_2 || next_node_2 == previous_node_1)
01158 {
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171 assert(pNodeA->IsBoundaryNode());
01172 assert(pNodeB->IsBoundaryNode());
01173
01174
01175
01176 unsigned nodeC_index;
01177 if (next_node_1 == previous_node_2 && next_node_2 != previous_node_1)
01178 {
01179 nodeC_index = next_node_1;
01180 }
01181 else if (next_node_2 == previous_node_1 && next_node_1 != previous_node_2)
01182 {
01183 nodeC_index = next_node_2;
01184 }
01185 else
01186 {
01187 assert(next_node_1 == previous_node_2 && next_node_2 == previous_node_1);
01195 EXCEPTION("Triangular element next to triangular void, not implemented yet.");
01196 }
01197
01198 if(p_element_A_not_B->GetNumNodes() == 3u || p_element_B_not_A->GetNumNodes() == 3u)
01199 {
01207 EXCEPTION("Triangular element next to triangular void, not implemented yet.");
01208 }
01209
01210 PerformVoidRemoval(pNodeA, pNodeB, this->mNodes[nodeC_index]);
01211 }
01212 else
01213 {
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225 assert(pNodeA->IsBoundaryNode());
01226 assert(pNodeB->IsBoundaryNode());
01227
01228 PerformT1Swap(pNodeA, pNodeB, all_indices);
01229 }
01230 }
01231 else
01232 {
01233
01234 assert ( (nodeA_elem_indices.size()==2 && nodeB_elem_indices.size()==3)
01235 || (nodeA_elem_indices.size()==3 && nodeB_elem_indices.size()==2) );
01236
01237
01238 assert(!(pNodeA->IsBoundaryNode() && pNodeB->IsBoundaryNode()));
01239
01240 if (pNodeA->IsBoundaryNode() || pNodeB->IsBoundaryNode())
01241 {
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252 PerformT1Swap(pNodeA, pNodeB, all_indices);
01253 }
01254 else
01255 {
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267 EXCEPTION("There are non-boundary nodes contained only in two elements; something has gone wrong.");
01268 }
01269 }
01270 break;
01271 }
01272 case 4:
01273 {
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283 PerformT1Swap(pNodeA, pNodeB, all_indices);
01284 break;
01285 }
01286 default:
01287
01288 NEVER_REACHED;
01289 }
01290 }
01291 }
01292
01293 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01294 void MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::PerformNodeMerge(Node<SPACE_DIM>* pNodeA, Node<SPACE_DIM>* pNodeB)
01295 {
01296
01297 unsigned nodeA_index = pNodeA->GetIndex();
01298 unsigned nodeB_index = pNodeB->GetIndex();
01299
01300 unsigned lo_node_index = (nodeA_index < nodeB_index) ? nodeA_index : nodeB_index;
01301 unsigned hi_node_index = (nodeA_index < nodeB_index) ? nodeB_index : nodeA_index;
01302
01303
01304 Node<SPACE_DIM>* p_lo_node = this->GetNode(lo_node_index);
01305 Node<SPACE_DIM>* p_hi_node = this->GetNode(hi_node_index);
01306
01307
01308 std::set<unsigned> lo_node_elem_indices = p_lo_node->rGetContainingElementIndices();
01309 std::set<unsigned> hi_node_elem_indices = p_hi_node->rGetContainingElementIndices();
01310
01311
01312 c_vector<double, SPACE_DIM> node_midpoint = p_lo_node->rGetLocation() + 0.5*this->GetVectorFromAtoB(p_lo_node->rGetLocation(), p_hi_node->rGetLocation());
01313 c_vector<double, SPACE_DIM>& r_lo_node_location = p_lo_node->rGetModifiableLocation();
01314 r_lo_node_location = node_midpoint;
01315
01316
01317 for (std::set<unsigned>::const_iterator it = hi_node_elem_indices.begin();
01318 it != hi_node_elem_indices.end();
01319 ++it)
01320 {
01321
01322 unsigned hi_node_local_index = this->mElements[*it]->GetNodeLocalIndex(hi_node_index);
01323 assert(hi_node_local_index < UINT_MAX);
01324
01325
01326
01327
01328
01329 if (lo_node_elem_indices.count(*it) > 0)
01330 {
01331 this->mElements[*it]->DeleteNode(hi_node_local_index);
01332 }
01333 else
01334 {
01335
01336 this->mElements[*it]->UpdateNode(hi_node_local_index, p_lo_node);
01337 }
01338 }
01339 assert(!(this->mNodes[hi_node_index]->IsDeleted()));
01340 this->mNodes[hi_node_index]->MarkAsDeleted();
01341 mDeletedNodeIndices.push_back(hi_node_index);
01342 }
01343
01344 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01345 void MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::PerformT1Swap(Node<SPACE_DIM>* pNodeA,
01346 Node<SPACE_DIM>* pNodeB,
01347 std::set<unsigned>& rElementsContainingNodes)
01348 {
01349
01350 double distance_between_nodes_CD = mCellRearrangementRatio*mCellRearrangementThreshold;
01351
01352 c_vector<double, SPACE_DIM> nodeA_location = pNodeA->rGetLocation();
01353 c_vector<double, SPACE_DIM> nodeB_location = pNodeB->rGetLocation();
01354 c_vector<double, SPACE_DIM> vector_AB = this->GetVectorFromAtoB(nodeA_location, nodeB_location);
01355 mLocationsOfT1Swaps.push_back(nodeA_location + 0.5*vector_AB);
01356
01357 double distance_AB = norm_2(vector_AB);
01358 if (distance_AB < 1e-10)
01359 {
01360 EXCEPTION("Nodes are too close together, this shouldn't happen");
01361 }
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392 c_vector<double, SPACE_DIM> vector_CD;
01393 vector_CD(0) = -vector_AB(1) * distance_between_nodes_CD / distance_AB;
01394 vector_CD(1) = vector_AB(0) * distance_between_nodes_CD / distance_AB;
01395
01396 c_vector<double, SPACE_DIM> nodeC_location = nodeA_location + 0.5*vector_AB - 0.5*vector_CD;
01397 c_vector<double, SPACE_DIM> nodeD_location = nodeC_location + vector_CD;
01398
01399 pNodeA->rGetModifiableLocation() = nodeC_location;
01400 pNodeB->rGetModifiableLocation() = nodeD_location;
01401
01402
01403 std::set<unsigned> nodeA_elem_indices = pNodeA->rGetContainingElementIndices();
01404 std::set<unsigned> nodeB_elem_indices = pNodeB->rGetContainingElementIndices();
01405
01406 for (std::set<unsigned>::const_iterator it = rElementsContainingNodes.begin();
01407 it != rElementsContainingNodes.end();
01408 ++it)
01409 {
01410
01411 if (nodeA_elem_indices.find(*it) == nodeA_elem_indices.end())
01412 {
01413
01414 unsigned nodeB_local_index = this->mElements[*it]->GetNodeLocalIndex(pNodeB->GetIndex());
01415 assert(nodeB_local_index < UINT_MAX);
01416
01417 this->mElements[*it]->AddNode(pNodeA, nodeB_local_index);
01418 }
01419 else if (nodeB_elem_indices.find(*it) == nodeB_elem_indices.end())
01420 {
01421
01422 unsigned nodeA_local_index = this->mElements[*it]->GetNodeLocalIndex(pNodeA->GetIndex());
01423 assert(nodeA_local_index < UINT_MAX);
01424
01425 this->mElements[*it]->AddNode(pNodeB, nodeA_local_index);
01426 }
01427 else
01428 {
01429
01430 unsigned nodeA_local_index = this->mElements[*it]->GetNodeLocalIndex(pNodeA->GetIndex());
01431 unsigned nodeB_local_index = this->mElements[*it]->GetNodeLocalIndex(pNodeB->GetIndex());
01432
01433 assert(nodeA_local_index < UINT_MAX);
01434 assert(nodeB_local_index < UINT_MAX);
01435
01436
01437
01438
01439
01440
01441 unsigned nodeB_local_index_plus_one = (nodeB_local_index + 1)%(this->mElements[*it]->GetNumNodes());
01442
01443 if (nodeA_local_index == nodeB_local_index_plus_one)
01444 {
01445
01446
01447
01448
01449 this->mElements[*it]->DeleteNode(nodeB_local_index);
01450 }
01451 else
01452 {
01453 assert(nodeB_local_index == (nodeA_local_index + 1)%(this->mElements[*it]->GetNumNodes()));
01454
01455
01456
01457
01458 this->mElements[*it]->DeleteNode(nodeA_local_index);
01459 }
01460 }
01461 }
01462
01463
01464 if (pNodeA->IsBoundaryNode() || pNodeB->IsBoundaryNode())
01465 {
01466 if (pNodeA->GetNumContainingElements() == 3)
01467 {
01468 pNodeA->SetAsBoundaryNode(false);
01469 }
01470 else
01471 {
01472 pNodeA->SetAsBoundaryNode(true);
01473 }
01474 if (pNodeB->GetNumContainingElements() == 3)
01475 {
01476 pNodeB->SetAsBoundaryNode(false);
01477 }
01478 else
01479 {
01480 pNodeB->SetAsBoundaryNode(true);
01481 }
01482 }
01483 }
01484
01485 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01486 void MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::PerformIntersectionSwap(Node<SPACE_DIM>* pNode, unsigned elementIndex)
01487 {
01488 assert(SPACE_DIM == 2);
01489 assert(ELEMENT_DIM == SPACE_DIM);
01490
01491 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = this->GetElement(elementIndex);
01492 unsigned num_nodes = p_element->GetNumNodes();
01493
01494 std::set<unsigned> elements_containing_intersecting_node;
01495
01496 for (unsigned node_local_index=0; node_local_index<num_nodes; node_local_index++)
01497 {
01498 unsigned node_global_index = p_element->GetNodeGlobalIndex(node_local_index);
01499
01500 std::set<unsigned> node_elem_indices = this->GetNode(node_global_index)->rGetContainingElementIndices();
01501
01502 for (std::set<unsigned>::const_iterator elem_iter = node_elem_indices.begin();
01503 elem_iter != node_elem_indices.end();
01504 ++elem_iter)
01505 {
01506 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_neighbouring_element = this->GetElement(*elem_iter);
01507 unsigned num_nodes_in_neighbouring_element = p_neighbouring_element->GetNumNodes();
01508
01509
01510 for (unsigned node_index_2 = 0; node_index_2 < num_nodes_in_neighbouring_element; node_index_2++)
01511 {
01512 if (p_neighbouring_element->GetNodeGlobalIndex(node_index_2) == pNode->GetIndex())
01513 {
01514 elements_containing_intersecting_node.insert(p_neighbouring_element->GetIndex());
01515 }
01516 }
01517 }
01518 }
01519
01520
01521
01522
01523 assert(elements_containing_intersecting_node.size() == 2);
01524
01525 std::set<unsigned> all_elements_containing_intersecting_node = pNode->rGetContainingElementIndices();
01526
01527 std::set<unsigned> intersecting_element;
01528
01529 std::set_difference(all_elements_containing_intersecting_node.begin(), all_elements_containing_intersecting_node.end(),
01530 elements_containing_intersecting_node.begin(), elements_containing_intersecting_node.end(),
01531 std::inserter(intersecting_element, intersecting_element.begin()));
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543 unsigned node_A_index = pNode->GetIndex();
01544 unsigned node_B_index;
01545 unsigned element_1_index = *(intersecting_element.begin());
01546 unsigned element_2_index;
01547 unsigned element_3_index = elementIndex;
01548 unsigned element_4_index;
01549
01550 std::set<unsigned>::iterator iter = elements_containing_intersecting_node.begin();
01551 unsigned element_a_index = *(iter);
01552 iter++;
01553 unsigned element_b_index = *(iter);
01554
01555 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_a = this->GetElement(element_a_index);
01556 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_b = this->GetElement(element_b_index);
01557
01558 std::set<unsigned> element_a_nodes;
01559 for (unsigned node_index = 0; node_index < p_element_a->GetNumNodes(); node_index++)
01560 {
01561 element_a_nodes.insert(p_element_a->GetNodeGlobalIndex(node_index));
01562 }
01563
01564 std::set<unsigned> element_b_nodes;
01565 for (unsigned node_index = 0; node_index < p_element_b->GetNumNodes(); node_index++)
01566 {
01567 element_b_nodes.insert(p_element_b->GetNodeGlobalIndex(node_index));
01568 }
01569
01570 std::set<unsigned> switching_nodes;
01571 std::set_intersection(element_a_nodes.begin(), element_a_nodes.end(),
01572 element_b_nodes.begin(), element_b_nodes.end(),
01573 std::inserter(switching_nodes, switching_nodes.begin()));
01574
01575 assert(switching_nodes.size() == 2);
01576
01577
01578 assert(switching_nodes.find(node_A_index) != switching_nodes.end());
01579 switching_nodes.erase(node_A_index);
01580
01581 assert(switching_nodes.size() == 1);
01582
01583 node_B_index = *(switching_nodes.begin());
01584
01585
01586 unsigned node_A_local_index_in_a = p_element_a->GetNodeLocalIndex(node_A_index);
01587 unsigned node_B_local_index_in_a = p_element_a->GetNodeLocalIndex(node_B_index);
01588
01589 if ((node_B_local_index_in_a+1)%p_element_a->GetNumNodes() == node_A_local_index_in_a)
01590 {
01591 assert((p_element_b->GetNodeLocalIndex(node_A_index)+1)%p_element_b->GetNumNodes()
01592 == p_element_b->GetNodeLocalIndex(node_B_index));
01593
01594
01595 element_2_index = element_a_index;
01596 element_4_index = element_b_index;
01597 }
01598 else
01599 {
01600 assert((p_element_b->GetNodeLocalIndex(node_B_index)+1)%p_element_b->GetNumNodes()
01601 == p_element_b->GetNodeLocalIndex(node_A_index));
01602
01603
01604 element_2_index = element_b_index;
01605 element_4_index = element_a_index;
01606 }
01607
01608 unsigned intersected_edge = this->GetLocalIndexForElementEdgeClosestToPoint(pNode->rGetLocation(), elementIndex);
01609
01610 unsigned node_A_local_index_in_1 = this->GetElement(element_1_index)->GetNodeLocalIndex(node_A_index);
01611
01612 unsigned node_A_local_index_in_2 = this->GetElement(element_2_index)->GetNodeLocalIndex(node_A_index);
01613 unsigned node_B_local_index_in_2 = this->GetElement(element_2_index)->GetNodeLocalIndex(node_B_index);
01614
01615 unsigned node_B_local_index_in_3 = this->GetElement(elementIndex)->GetNodeLocalIndex(node_B_index);
01616
01617 unsigned node_A_local_index_in_4 = this->GetElement(element_4_index)->GetNodeLocalIndex(node_A_index);
01618 unsigned node_B_local_index_in_4 = this->GetElement(element_4_index)->GetNodeLocalIndex(node_B_index);
01619
01620 if (intersected_edge==node_B_local_index_in_3)
01621 {
01622
01623
01624
01625
01626
01627
01628
01629 this->mElements[element_1_index]->AddNode(this->mNodes[node_B_index], node_A_local_index_in_1);
01630 this->mElements[element_3_index]->AddNode(this->mNodes[node_A_index], node_B_local_index_in_3);
01631
01632 this->mElements[element_2_index]->DeleteNode(node_B_local_index_in_2);
01633 this->mElements[element_4_index]->DeleteNode(node_A_local_index_in_4);
01634 }
01635 else
01636 {
01637 assert((intersected_edge+1)%num_nodes==node_B_local_index_in_3);
01638
01639
01640 unsigned node_before_A_in_1 = (node_A_local_index_in_1 - 1)%this->GetElement(element_1_index)->GetNumNodes();
01641 unsigned node_before_B_in_3 = (node_B_local_index_in_3 - 1)%this->GetElement(element_3_index)->GetNumNodes();
01642 this->mElements[element_1_index]->AddNode(this->mNodes[node_B_index], node_before_A_in_1);
01643 this->mElements[element_3_index]->AddNode(this->mNodes[node_A_index], node_before_B_in_3);
01644
01645
01646 this->mElements[element_2_index]->DeleteNode(node_A_local_index_in_2);
01647 this->mElements[element_4_index]->DeleteNode(node_B_local_index_in_4);
01648 }
01649 }
01650
01651 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01652 void MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::PerformT2Swap(VertexElement<ELEMENT_DIM,SPACE_DIM>& rElement)
01653 {
01654
01655 assert(rElement.GetNumNodes() == 3);
01656
01657
01658 c_vector<double, SPACE_DIM> new_node_location;
01659 new_node_location = this->GetCentroidOfElement(rElement.GetIndex());
01660 mLastT2SwapLocation = new_node_location;
01661
01662
01663 bool is_node_on_boundary = false;
01664 for (unsigned i=0; i<3; i++)
01665 {
01666 if (rElement.GetNode(i)->IsBoundaryNode())
01667 {
01668 is_node_on_boundary = true;
01669 break;
01670 }
01671 }
01672 unsigned new_node_global_index = this->AddNode(new Node<SPACE_DIM>(GetNumNodes(), new_node_location, is_node_on_boundary));
01673 Node<SPACE_DIM>* p_new_node = this->GetNode(new_node_global_index);
01674
01675 for (unsigned i=0; i<3; i++)
01676 {
01677 Node<SPACE_DIM>* p_node_a = rElement.GetNode((i+1)%3);
01678 Node<SPACE_DIM>* p_node_b = rElement.GetNode((i+2)%3);
01679
01680 std::set<unsigned> elements_of_node_a = p_node_a->rGetContainingElementIndices();
01681 std::set<unsigned> elements_of_node_b = p_node_b->rGetContainingElementIndices();
01682
01683 std::set<unsigned> common_elements;
01684
01685 std::set_intersection(elements_of_node_a.begin(), elements_of_node_a.end(),
01686 elements_of_node_b.begin(), elements_of_node_b.end(),
01687 std::inserter(common_elements, common_elements.begin()));
01688
01689 assert(common_elements.size() <= 2);
01690 common_elements.erase(rElement.GetIndex());
01691
01692 if (common_elements.size() == 1)
01693 {
01694 VertexElement<ELEMENT_DIM,SPACE_DIM>* p_neighbouring_element = this->GetElement(*(common_elements.begin()));
01695
01696 if (p_neighbouring_element->GetNumNodes() < 4)
01697 {
01698 EXCEPTION("One of the neighbours of a small triangular element is also a triangle - dealing with this has not been implemented yet");
01699 }
01700
01701 p_neighbouring_element->ReplaceNode(p_node_a, p_new_node);
01702 p_neighbouring_element->DeleteNode(p_neighbouring_element->GetNodeLocalIndex(p_node_b->GetIndex()));
01703 }
01704 else
01705 {
01706 assert((p_node_a->IsBoundaryNode()) && (p_node_b->IsBoundaryNode()));
01707 }
01708 }
01709
01710
01711 mDeletedNodeIndices.push_back(rElement.GetNodeGlobalIndex(0));
01712 mDeletedNodeIndices.push_back(rElement.GetNodeGlobalIndex(1));
01713 mDeletedNodeIndices.push_back(rElement.GetNodeGlobalIndex(2));
01714
01715 rElement.GetNode(0)->MarkAsDeleted();
01716 rElement.GetNode(1)->MarkAsDeleted();
01717 rElement.GetNode(2)->MarkAsDeleted();
01718
01719 mDeletedElementIndices.push_back(rElement.GetIndex());
01720 rElement.MarkAsDeleted();
01721 }
01722
01723 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01724 void MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::PerformT3Swap(Node<SPACE_DIM>* pNode, unsigned elementIndex)
01725 {
01726 assert(SPACE_DIM == 2);
01727 assert(ELEMENT_DIM == SPACE_DIM);
01728 assert(pNode->IsBoundaryNode());
01729
01730
01731 std::set<unsigned> elements_containing_intersecting_node = pNode->rGetContainingElementIndices();
01732
01733
01734 unsigned node_A_local_index = this->GetLocalIndexForElementEdgeClosestToPoint(pNode->rGetLocation(), elementIndex);
01735
01736
01737 c_vector<double, SPACE_DIM> node_location;
01738 node_location = pNode->rGetModifiableLocation();
01739
01740
01741 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = this->GetElement(elementIndex);
01742 unsigned num_nodes = p_element->GetNumNodes();
01743
01744
01745 unsigned vertexA_index = p_element->GetNodeGlobalIndex(node_A_local_index);
01746 unsigned vertexB_index = p_element->GetNodeGlobalIndex((node_A_local_index+1)%num_nodes);
01747
01748
01749 if (!this->mNodes[vertexA_index]->IsBoundaryNode() || !this->mNodes[vertexB_index]->IsBoundaryNode())
01750 {
01751 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.");
01752 }
01753
01754
01755 c_vector<double, SPACE_DIM> vertexA = p_element->GetNodeLocation(node_A_local_index);
01756 c_vector<double, SPACE_DIM> vertexB = p_element->GetNodeLocation((node_A_local_index+1)%num_nodes);
01757 c_vector<double, SPACE_DIM> vector_a_to_point = this->GetVectorFromAtoB(vertexA, node_location);
01758
01759 c_vector<double, SPACE_DIM> vector_a_to_b = this->GetVectorFromAtoB(vertexA, vertexB);
01760
01761 c_vector<double, SPACE_DIM> edge_ab_unit_vector = vector_a_to_b/norm_2(vector_a_to_b);
01762 c_vector<double, SPACE_DIM> intersection = vertexA + edge_ab_unit_vector*inner_prod(vector_a_to_point, edge_ab_unit_vector);
01763
01764
01766
01767
01768 mLocationsOfT3Swaps.push_back(intersection);
01769
01770 if (pNode->GetNumContainingElements() == 1)
01771 {
01772
01773 unsigned intersecting_element_index = *elements_containing_intersecting_node.begin();
01774
01775
01776 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_intersecting_element = this->GetElement(intersecting_element_index);
01777
01778 unsigned local_index = p_intersecting_element->GetNodeLocalIndex(pNode->GetIndex());
01779 unsigned next_node = p_intersecting_element->GetNodeGlobalIndex((local_index + 1)%(p_intersecting_element->GetNumNodes()));
01780 unsigned previous_node = p_intersecting_element->GetNodeGlobalIndex((local_index + p_intersecting_element->GetNumNodes() - 1)%(p_intersecting_element->GetNumNodes()));
01781
01782
01783 if (next_node == vertexA_index || previous_node == vertexA_index || next_node == vertexB_index || previous_node == vertexB_index)
01784 {
01785 unsigned common_vertex_index;
01786
01787 if (next_node == vertexA_index || previous_node == vertexA_index)
01788 {
01789 common_vertex_index = vertexA_index;
01790 }
01791 else
01792 {
01793 common_vertex_index = vertexB_index;
01794 }
01795
01796 assert(this->mNodes[common_vertex_index]->GetNumContainingElements()>1);
01797
01798 std::set<unsigned> elements_containing_common_vertex = this->mNodes[common_vertex_index]->rGetContainingElementIndices();
01799 std::set<unsigned>::const_iterator it = elements_containing_common_vertex.begin();
01800 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_common_1 = this->GetElement(*it);
01801 it++;
01802 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_common_2 = this->GetElement(*it);
01803
01804
01805 unsigned num_common_vertices = 0;
01806 std::vector<unsigned> common_vertex_indices;
01807 for (unsigned i=0; i<p_element_common_1->GetNumNodes(); i++)
01808 {
01809 for (unsigned j=0; j<p_element_common_2->GetNumNodes(); j++)
01810 {
01811 if (p_element_common_1->GetNodeGlobalIndex(i)==p_element_common_2->GetNodeGlobalIndex(j))
01812 {
01813 num_common_vertices++;
01814 common_vertex_indices.push_back(p_element_common_1->GetNodeGlobalIndex(i));
01815 }
01816 }
01817 }
01818
01819 if (num_common_vertices == 1 || this->mNodes[common_vertex_index]->GetNumContainingElements() > 2)
01820 {
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
01836
01837
01838 pNode->rGetModifiableLocation() = intersection;
01839
01840
01841 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
01842
01843
01844 assert(pNode->GetNumContainingElements() == 2);
01845 }
01846 else if (num_common_vertices == 2)
01847 {
01848
01849
01850
01851 if ( ( common_vertex_indices[0]==vertexA_index && common_vertex_indices[1]==vertexB_index ) ||
01852 ( common_vertex_indices[1]==vertexA_index && common_vertex_indices[0]==vertexB_index ) )
01853 {
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870 unsigned p_node_local_index = this->
01871 GetElement(intersecting_element_index)->GetNodeLocalIndex(pNode->GetIndex());
01872 this->GetElement(intersecting_element_index)->DeleteNode(p_node_local_index);
01873
01874
01875 pNode->MarkAsDeleted();
01876 mDeletedNodeIndices.push_back(pNode->GetIndex());
01877 }
01878 else
01879 {
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
01898
01899
01900 pNode->rGetModifiableLocation() = intersection;
01901
01902
01903 this->GetElement(elementIndex)->ReplaceNode(this->mNodes[common_vertex_index], pNode);
01904
01905
01906 unsigned common_vertex_local_index = this->GetElement(intersecting_element_index)->GetNodeLocalIndex(common_vertex_index);
01907 this->GetElement(intersecting_element_index)->DeleteNode(common_vertex_local_index);
01908 assert(this->mNodes[common_vertex_index]->GetNumContainingElements() == 0);
01909
01910 this->mNodes[common_vertex_index]->MarkAsDeleted();
01911 mDeletedNodeIndices.push_back(common_vertex_index);
01912
01913
01914 assert(pNode->GetNumContainingElements() == 2);
01915 }
01916 }
01917 else if (num_common_vertices == 4)
01918 {
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935 this->GetElement(elementIndex)->DeleteNode(node_A_local_index);
01936 unsigned node_B_local_index = this->
01937 GetElement(elementIndex)->GetNodeLocalIndex(vertexB_index);
01938 this->GetElement(elementIndex)->DeleteNode(node_B_local_index);
01939
01940
01941 unsigned node_A_local_index_intersecting_element = this->
01942 GetElement(intersecting_element_index)->GetNodeLocalIndex(vertexA_index);
01943 this->GetElement(intersecting_element_index)->DeleteNode(node_A_local_index_intersecting_element);
01944 unsigned node_B_local_index_intersecting_element = this->
01945 GetElement(intersecting_element_index)->GetNodeLocalIndex(vertexB_index);
01946 this->GetElement(intersecting_element_index)->DeleteNode(node_B_local_index_intersecting_element);
01947
01948
01949 unsigned p_node_local_index = this->
01950 GetElement(intersecting_element_index)->GetNodeLocalIndex(pNode->GetIndex());
01951 this->GetElement(intersecting_element_index)->DeleteNode(p_node_local_index);
01952
01953
01954 pNode->MarkAsDeleted();
01955 mDeletedNodeIndices.push_back(pNode->GetIndex());
01956 this->mNodes[vertexA_index]->MarkAsDeleted();
01957 mDeletedNodeIndices.push_back(vertexA_index);
01958 this->mNodes[vertexB_index]->MarkAsDeleted();
01959 mDeletedNodeIndices.push_back(vertexB_index);
01960 }
01961 else
01962 {
01963
01964 NEVER_REACHED;
01965 }
01966 }
01967 else
01968 {
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979
01980 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
01981 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index+1)%num_nodes);
01982
01983
01984 pNode->rGetModifiableLocation() = intersection + 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
01985
01986
01987 c_vector<double, SPACE_DIM> new_node_location;
01988 new_node_location = intersection - 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
01989
01990
01991 unsigned new_node_global_index = this->AddNode(new Node<SPACE_DIM>(0, true, new_node_location[0], new_node_location[1]));
01992
01993
01994 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
01995 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
01996
01997
01998 this->GetElement(intersecting_element_index)->AddNode(this->mNodes[new_node_global_index], this->GetElement(intersecting_element_index)->GetNodeLocalIndex(pNode->GetIndex()));
01999
02000
02001 assert(pNode->GetNumContainingElements() == 2);
02002 assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
02003 }
02004 }
02005 else if (pNode->GetNumContainingElements() == 2)
02006 {
02007
02008 std::set<unsigned>::const_iterator it = elements_containing_intersecting_node.begin();
02009
02010 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_1 = this->GetElement(*it);
02011 unsigned num_nodes_elem_1 = p_element_1->GetNumNodes();
02012 it++;
02013
02014 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_2 = this->GetElement(*it);
02015 unsigned num_nodes_elem_2 = p_element_2->GetNumNodes();
02016
02017 unsigned node_global_index = pNode->GetIndex();
02018
02019 unsigned local_index_1 = p_element_1->GetNodeLocalIndex(node_global_index);
02020 unsigned next_node_1 = p_element_1->GetNodeGlobalIndex((local_index_1 + 1)%num_nodes_elem_1);
02021 unsigned previous_node_1 = p_element_1->GetNodeGlobalIndex((local_index_1 + num_nodes_elem_1 - 1)%num_nodes_elem_1);
02022
02023 unsigned local_index_2 = p_element_2->GetNodeLocalIndex(node_global_index);
02024 unsigned next_node_2 = p_element_2->GetNodeGlobalIndex((local_index_2 + 1)%num_nodes_elem_2);
02025 unsigned previous_node_2 = p_element_2->GetNodeGlobalIndex((local_index_2 + num_nodes_elem_2 - 1)%num_nodes_elem_2);
02026
02027
02028 if ((next_node_1 == vertexA_index || previous_node_1 == vertexA_index || next_node_2 == vertexA_index || previous_node_2 == vertexA_index) &&
02029 (next_node_1 == vertexB_index || previous_node_1 == vertexB_index || next_node_2 == vertexB_index || previous_node_2 == vertexB_index))
02030 {
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
02046 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index+1)%num_nodes);
02047
02048
02049 assert(pNode->IsBoundaryNode());
02050 assert(this->mNodes[vertexA_index]->IsBoundaryNode());
02051 assert(this->mNodes[vertexB_index]->IsBoundaryNode());
02052
02053
02054 pNode->rGetModifiableLocation() = intersection;
02055 pNode->SetAsBoundaryNode(false);
02056
02057
02058 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
02059
02060
02061 std::set<unsigned> elements_containing_vertex_A = this->mNodes[vertexA_index]->rGetContainingElementIndices();
02062 for (std::set<unsigned>::const_iterator iter = elements_containing_vertex_A.begin();
02063 iter != elements_containing_vertex_A.end();
02064 iter++)
02065 {
02066 this->GetElement(*iter)->DeleteNode(this->GetElement(*iter)->GetNodeLocalIndex(vertexA_index));
02067 }
02068
02069
02070 assert(this->mNodes[vertexA_index]->GetNumContainingElements() == 0);
02071 this->mNodes[vertexA_index]->MarkAsDeleted();
02072 mDeletedNodeIndices.push_back(vertexA_index);
02073
02074
02075 std::set<unsigned> elements_containing_vertex_B = this->mNodes[vertexB_index]->rGetContainingElementIndices();
02076 for (std::set<unsigned>::const_iterator iter = elements_containing_vertex_B.begin();
02077 iter != elements_containing_vertex_B.end();
02078 iter++)
02079 {
02080 this->GetElement(*iter)->DeleteNode(this->GetElement(*iter)->GetNodeLocalIndex(vertexB_index));
02081 }
02082
02083
02084 assert(this->mNodes[vertexB_index]->GetNumContainingElements()==0);
02085 this->mNodes[vertexB_index]->MarkAsDeleted();
02086 mDeletedNodeIndices.push_back(vertexB_index);
02087 }
02088 else
02089 {
02090 if (next_node_1 == vertexA_index || previous_node_1 == vertexA_index || next_node_2 == vertexA_index || previous_node_2 == vertexA_index)
02091 {
02092
02093
02094 assert(this->mNodes[vertexA_index]->GetNumContainingElements() > 1);
02095
02096 std::set<unsigned> elements_containing_vertex_A = this->mNodes[vertexA_index]->rGetContainingElementIndices();
02097 std::set<unsigned>::const_iterator iter = elements_containing_vertex_A.begin();
02098 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_common_1 = this->GetElement(*iter);
02099 iter++;
02100 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_common_2 = this->GetElement(*iter);
02101
02102
02103 unsigned num_common_vertices = 0;
02104 for (unsigned i=0; i<p_element_common_1->GetNumNodes(); i++)
02105 {
02106 for (unsigned j=0; j<p_element_common_2->GetNumNodes(); j++)
02107 {
02108 if (p_element_common_1->GetNodeGlobalIndex(i) == p_element_common_2->GetNodeGlobalIndex(j))
02109 {
02110 num_common_vertices++;
02111 }
02112 }
02113 }
02114
02115 if (num_common_vertices == 1 || this->mNodes[vertexA_index]->GetNumContainingElements() > 2)
02116 {
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
02132 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index+1)%num_nodes);
02133
02134
02135 pNode->rGetModifiableLocation() = intersection - 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
02136 pNode->SetAsBoundaryNode(false);
02137
02138
02139 c_vector<double, SPACE_DIM> new_node_location;
02140 new_node_location = intersection + 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
02141
02142
02143 unsigned new_node_global_index = this->AddNode(new Node<SPACE_DIM>(0, true, new_node_location[0], new_node_location[1]));
02144
02145
02146 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
02147 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
02148
02149
02150 if (next_node_1 == previous_node_2)
02151 {
02152 p_element_1->AddNode(this->mNodes[new_node_global_index], (local_index_1 + p_element_1->GetNumNodes() - 1)%(p_element_1->GetNumNodes()));
02153 }
02154 else
02155 {
02156 assert(next_node_2 == previous_node_1);
02157
02158 p_element_2->AddNode(this->mNodes[new_node_global_index], (local_index_2 + p_element_2->GetNumNodes() - 1)%(p_element_2->GetNumNodes()));
02159 }
02160
02161
02162 assert(pNode->GetNumContainingElements() == 3);
02163 assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
02164 }
02165 else if (num_common_vertices == 2)
02166 {
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
02183 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index+1)%num_nodes);
02184
02185
02186 pNode->rGetModifiableLocation() = intersection - 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
02187 pNode->SetAsBoundaryNode(false);
02188
02189
02190 c_vector<double, SPACE_DIM> new_node_location;
02191 new_node_location = intersection + 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
02192
02193
02194 unsigned new_node_global_index = this->AddNode(new Node<SPACE_DIM>(0, true, new_node_location[0], new_node_location[1]));
02195
02196
02197 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
02198 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
02199
02200
02201 if (next_node_1 == previous_node_2)
02202 {
02203 p_element_1->AddNode(this->mNodes[new_node_global_index], (local_index_1 + p_element_1->GetNumNodes() - 1)%(p_element_1->GetNumNodes()));
02204 }
02205 else
02206 {
02207 assert(next_node_2 == previous_node_1);
02208 p_element_2->AddNode(this->mNodes[new_node_global_index], (local_index_2 + p_element_2->GetNumNodes() - 1)%(p_element_2->GetNumNodes()));
02209 }
02210
02211
02212 p_element_common_1->DeleteNode(p_element_common_1->GetNodeLocalIndex(vertexA_index));
02213 p_element_common_2->DeleteNode(p_element_common_2->GetNodeLocalIndex(vertexA_index));
02214
02215 assert(this->mNodes[vertexA_index]->GetNumContainingElements()==0);
02216
02217 this->mNodes[vertexA_index]->MarkAsDeleted();
02218 mDeletedNodeIndices.push_back(vertexA_index);
02219
02220
02221 assert(pNode->GetNumContainingElements() == 3);
02222 assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
02223 }
02224 else
02225 {
02226
02227 NEVER_REACHED;
02228 }
02229 }
02230 else if (next_node_1 == vertexB_index || previous_node_1 == vertexB_index || next_node_2 == vertexB_index || previous_node_2 == vertexB_index)
02231 {
02232
02233
02234 assert(this->mNodes[vertexB_index]->GetNumContainingElements()>1);
02235
02236 std::set<unsigned> elements_containing_vertex_B = this->mNodes[vertexB_index]->rGetContainingElementIndices();
02237 std::set<unsigned>::const_iterator iter = elements_containing_vertex_B.begin();
02238 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_common_1 = this->GetElement(*iter);
02239 iter++;
02240 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_common_2 = this->GetElement(*iter);
02241
02242
02243 unsigned num_common_vertices = 0;
02244 for (unsigned i=0; i<p_element_common_1->GetNumNodes(); i++)
02245 {
02246 for (unsigned j=0; j<p_element_common_2->GetNumNodes(); j++)
02247 {
02248 if (p_element_common_1->GetNodeGlobalIndex(i) == p_element_common_2->GetNodeGlobalIndex(j))
02249 {
02250 num_common_vertices++;
02251 }
02252 }
02253 }
02254
02255 if (num_common_vertices == 1 || this->mNodes[vertexB_index]->GetNumContainingElements() > 2)
02256 {
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269
02270
02271 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
02272 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index+1)%num_nodes);
02273
02274
02275 pNode->rGetModifiableLocation() = intersection + 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
02276 pNode->SetAsBoundaryNode(false);
02277
02278
02279 c_vector<double, SPACE_DIM> new_node_location;
02280 new_node_location = intersection - 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
02281
02282
02283 unsigned new_node_global_index = this->AddNode(new Node<SPACE_DIM>(0, true, new_node_location[0], new_node_location[1]));
02284
02285
02286 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
02287 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
02288
02289
02290 if (next_node_1 == previous_node_2)
02291 {
02292 p_element_2->AddNode(this->mNodes[new_node_global_index], local_index_2);
02293 }
02294 else
02295 {
02296 assert(next_node_2 == previous_node_1);
02297 p_element_1->AddNode(this->mNodes[new_node_global_index], local_index_1);
02298 }
02299
02300
02301 assert(pNode->GetNumContainingElements() == 3);
02302 assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
02303 }
02304 else if (num_common_vertices == 2)
02305 {
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
02322 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index+1)%num_nodes);
02323
02324
02325 pNode->rGetModifiableLocation() = intersection + 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
02326 pNode->SetAsBoundaryNode(false);
02327
02328
02329 c_vector<double, SPACE_DIM> new_node_location;
02330 new_node_location = intersection - 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
02331
02332
02333 unsigned new_node_global_index = this->AddNode(new Node<SPACE_DIM>(0, true, new_node_location[0], new_node_location[1]));
02334
02335
02336 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
02337 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
02338
02339
02340 if (next_node_1 == previous_node_2)
02341 {
02342 p_element_2->AddNode(this->mNodes[new_node_global_index], local_index_2);
02343 }
02344 else
02345 {
02346 assert(next_node_2 == previous_node_1);
02347 p_element_1->AddNode(this->mNodes[new_node_global_index], local_index_1);
02348 }
02349
02350
02351 p_element_common_1->DeleteNode(p_element_common_1->GetNodeLocalIndex(vertexB_index));
02352 p_element_common_2->DeleteNode(p_element_common_2->GetNodeLocalIndex(vertexB_index));
02353
02354 assert(this->mNodes[vertexB_index]->GetNumContainingElements()==0);
02355
02356 this->mNodes[vertexB_index]->MarkAsDeleted();
02357 mDeletedNodeIndices.push_back(vertexB_index);
02358
02359
02360 assert(pNode->GetNumContainingElements() == 3);
02361 assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
02362 }
02363 else
02364 {
02365
02366 NEVER_REACHED;
02367 }
02368 }
02369 else
02370 {
02371
02372
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382 intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
02383 edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index+1)%num_nodes);
02384
02385
02386 pNode->rGetModifiableLocation() = intersection;
02387 pNode->SetAsBoundaryNode(false);
02388
02389 c_vector<double, SPACE_DIM> new_node_1_location;
02390 new_node_1_location = intersection - mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
02391 c_vector<double, SPACE_DIM> new_node_2_location;
02392 new_node_2_location = intersection + mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
02393
02394
02395 unsigned new_node_1_global_index = this->AddNode(new Node<SPACE_DIM>(0, true, new_node_1_location[0], new_node_1_location[1]));
02396 unsigned new_node_2_global_index = this->AddNode(new Node<SPACE_DIM>(0, true, new_node_2_location[0], new_node_2_location[1]));
02397
02398
02399 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_2_global_index], node_A_local_index);
02400 this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
02401 this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_1_global_index], node_A_local_index);
02402
02403
02404 if (next_node_1 == previous_node_2)
02405 {
02406 p_element_1->AddNode(this->mNodes[new_node_2_global_index], (local_index_1 + p_element_1->GetNumNodes() - 1)%(p_element_1->GetNumNodes()));
02407 p_element_2->AddNode(this->mNodes[new_node_1_global_index], local_index_2);
02408 }
02409 else
02410 {
02411 assert(next_node_2 == previous_node_1);
02412
02413 p_element_1->AddNode(this->mNodes[new_node_1_global_index], local_index_1);
02414 p_element_2->AddNode(this->mNodes[new_node_2_global_index], (local_index_2 + p_element_2->GetNumNodes() - 1)%(p_element_2->GetNumNodes()));
02415 }
02416
02417
02418 assert(pNode->GetNumContainingElements() == 3);
02419 assert(this->mNodes[new_node_1_global_index]->GetNumContainingElements() == 2);
02420 assert(this->mNodes[new_node_2_global_index]->GetNumContainingElements() == 2);
02421 }
02422 }
02423 }
02424 else
02425 {
02426 EXCEPTION("Trying to merge a node, contained in more than 2 elements, into another element, this is not possible with the vertex mesh.");
02427 }
02428 }
02429
02430 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
02431 void MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::PerformVoidRemoval(Node<SPACE_DIM>* pNodeA, Node<SPACE_DIM>* pNodeB, Node<SPACE_DIM>* pNodeC)
02432 {
02433 unsigned nodeA_index = pNodeA->GetIndex();
02434 unsigned nodeB_index = pNodeB->GetIndex();
02435 unsigned nodeC_index = pNodeC->GetIndex();
02436
02437 c_vector<double, SPACE_DIM> nodes_midpoint = pNodeA->rGetLocation() + this->GetVectorFromAtoB(pNodeA->rGetLocation(), pNodeB->rGetLocation())/3.0
02438 + this->GetVectorFromAtoB(pNodeA->rGetLocation(), pNodeC->rGetLocation())/3.0;
02439
02440 Node<SPACE_DIM>* p_low_node_A_B = (nodeA_index < nodeB_index) ? pNodeA : pNodeB;
02441 Node<SPACE_DIM>* p_low_node = (p_low_node_A_B->GetIndex() < nodeC_index) ? p_low_node_A_B : pNodeC;
02442
02443 PerformNodeMerge(pNodeA, pNodeB);
02444 PerformNodeMerge(p_low_node_A_B, pNodeC);
02445
02446 c_vector<double, SPACE_DIM>& r_low_node_location = p_low_node->rGetModifiableLocation();
02447 r_low_node_location = nodes_midpoint;
02448
02449
02450 p_low_node->SetAsBoundaryNode(false);
02451
02452
02453 RemoveDeletedNodes();
02454 }
02455
02456 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
02457 c_vector<double, 2> MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::WidenEdgeOrCorrectIntersectionLocationIfNecessary(
02458 unsigned indexA, unsigned indexB, c_vector<double,2> intersection)
02459 {
02469 c_vector<double, SPACE_DIM> vertexA = this->GetNode(indexA)->rGetLocation();
02470 c_vector<double, SPACE_DIM> vertexB = this->GetNode(indexB)->rGetLocation();
02471 c_vector<double, SPACE_DIM> vector_a_to_b = this->GetVectorFromAtoB(vertexA, vertexB);
02472
02473 if (norm_2(vector_a_to_b) < 4.0*mCellRearrangementRatio*mCellRearrangementThreshold)
02474 {
02475 WARNING("Trying to merge a node onto an edge which is too small.");
02476
02477 c_vector<double, SPACE_DIM> centre_a_and_b = vertexA + 0.5*vector_a_to_b;
02478
02479 vertexA = centre_a_and_b - 2.0*mCellRearrangementRatio*mCellRearrangementThreshold*vector_a_to_b/norm_2(vector_a_to_b);
02480 ChastePoint<SPACE_DIM> vertex_A_point(vertexA);
02481 SetNode(indexA, vertex_A_point);
02482
02483 vertexB = centre_a_and_b + 2.0*mCellRearrangementRatio*mCellRearrangementThreshold*vector_a_to_b/norm_2(vector_a_to_b);
02484 ChastePoint<SPACE_DIM> vertex_B_point(vertexB);
02485 SetNode(indexB, vertex_B_point);
02486
02487 intersection = centre_a_and_b;
02488 }
02489
02490
02491 vector_a_to_b = this->GetVectorFromAtoB(vertexA, vertexB);
02492 c_vector<double,2> edge_ab_unit_vector = vector_a_to_b/norm_2(vector_a_to_b);
02493
02494
02503 if (norm_2(intersection - vertexA) < 2.0*mCellRearrangementRatio*mCellRearrangementThreshold)
02504 {
02505 intersection = vertexA + 2.0*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
02506 }
02507 if (norm_2(intersection - vertexB) < 2.0*mCellRearrangementRatio*mCellRearrangementThreshold)
02508 {
02509 intersection = vertexB - 2.0*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
02510 }
02511 return intersection;
02512 }
02513
02514
02515 template class MutableVertexMesh<1,1>;
02516 template class MutableVertexMesh<1,2>;
02517 template class MutableVertexMesh<1,3>;
02518 template class MutableVertexMesh<2,2>;
02519 template class MutableVertexMesh<2,3>;
02520 template class MutableVertexMesh<3,3>;
02521
02522
02523 #include "SerializationExportWrapperForCpp.hpp"
02524 EXPORT_TEMPLATE_CLASS_ALL_DIMS(MutableVertexMesh)