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