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