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