MutableVertexMesh.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2011
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
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     // Reset member variables and clear mNodes and mElements
00049     Clear();
00050 
00051     // Populate mNodes and mElements
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     // In 3D, populate mFaces
00063     if (SPACE_DIM == 3)
00064     {
00065         // Use a std::set to keep track of which faces have been added to mFaces
00066         std::set<unsigned> faces_counted;
00067 
00068         // Loop over mElements
00069         for (unsigned elem_index=0; elem_index<this->mElements.size(); elem_index++)
00070         {
00071             // Loop over faces of this element
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                 // If this face is not already contained in mFaces, add it, and update faces_counted
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     // Register elements with nodes
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), // Overwritten as soon as archiving is complete
00104       mCellRearrangementRatio(1.5), // Overwritten as soon as archiving is complete
00105       mT2Threshold(0.001) // Overwritten as soon as archiving is complete
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 //\todo deal with boundary elements in vertex meshes #1392.
00184 //template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00185 //unsigned AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetNumBoundaryElements() const
00186 //{
00187 //    return mBoundaryElements.size();
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     // Make sure that we are in the correct dimension - this code will be eliminated at compile time
00267     assert(SPACE_DIM == 2); // only works in 2D at present
00268     assert(ELEMENT_DIM == SPACE_DIM);
00269 
00270     // Get the centroid of the element
00271     c_vector<double, SPACE_DIM> centroid = GetCentroidOfElement(pElement->GetIndex());
00272 
00273     // Create a vector perpendicular to the axis of division
00274     c_vector<double, SPACE_DIM> perp_axis;
00275     perp_axis(0) = -axisOfDivision(1);
00276     perp_axis(1) = axisOfDivision(0);
00277 
00278     /*
00279      * Find which edges the axis of division crosses by finding any node
00280      * that lies on the opposite side of the axis of division to its next
00281      * neighbour.
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     // If the axis of division does not cross two edges then we cannot proceed
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     // Find the intersections between the axis of division and the element edges
00306     for (unsigned i=0; i<intersecting_nodes.size(); i++)
00307     {
00308         /*
00309          * Get pointers to the nodes forming the edge into which one new node will be inserted.
00310          *
00311          * Note that when we use the first entry of intersecting_nodes to add a node,
00312          * we change the local index of the second entry of intersecting_nodes in
00313          * pElement, so must account for this by moving one entry further on.
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         // Find the indices of the elements owned by each node on the edge into which one new node will be inserted
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             // Find the location of the intersection
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); // allow for periodicity and other metrics
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              * If then new node is too close to one of the edge nodes, then reposition it
00350              * a distance mCellRearrangementRatio*mCellRearrangementThreshold further along the edge.
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); // to prevent moving intersection back to original position
00362 
00363                 intersection = position_b - mCellRearrangementRatio*mCellRearrangementThreshold*a_to_b/norm_2(a_to_b);
00364             }
00365         }
00366 
00367         /*
00368          * The new node is boundary node if the 2 nodes are boundary nodes and the elements don't look like
00369          *   ___A___
00370          *  |   |   |
00371          *  |___|___|
00372          *      B
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         // Add a new node to the mesh at the location of the intersection
00387         unsigned new_node_global_index = this->AddNode(new Node<SPACE_DIM>(0, is_boundary, intersection[0], intersection[1]));
00388         nodes_added++;
00389 
00390         // Now make sure node is added to neighbouring elements
00391 
00392         // Find common elements
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         // Iterate over common elements
00401         for (std::set<unsigned>::iterator iter = shared_elements.begin();
00402              iter != shared_elements.end();
00403              ++iter)
00404         {
00405             // Find which node has the lower local index in this element
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             // Add new node to this element
00423             this->GetElement(*iter)->AddNode(index, this->GetNode(new_node_global_index));
00424         }
00425         // Store index of new node
00426         division_node_global_indices.push_back(new_node_global_index);
00427     }
00428 
00429     // Now call DivideElement() to divide the element using the new nodes
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     // Make sure that we are in the correct dimension - this code will be eliminated at compile time
00442     assert(SPACE_DIM == 2); // only works in 2D at present
00443     assert(ELEMENT_DIM == SPACE_DIM);
00444 
00445     // Find the short axis of the element
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     // Make sure that we are in the correct dimension - this code will be eliminated at compile time
00460     assert(SPACE_DIM == 2); // only works in 2D at present
00461     assert(ELEMENT_DIM == SPACE_DIM);
00462 
00463     // Sort nodeA and nodeB such that nodeBIndex > nodeAindex
00464     assert(nodeBIndex != nodeAIndex);
00465 
00466     unsigned node1_index = (nodeAIndex < nodeBIndex) ? nodeAIndex : nodeBIndex; // low index
00467     unsigned node2_index = (nodeAIndex < nodeBIndex) ? nodeBIndex : nodeAIndex; // high index
00468 
00469     // Store the number of nodes in the element (this changes when nodes are deleted from the element)
00470     unsigned num_nodes = pElement->GetNumNodes();
00471 
00472     // Copy the nodes in this element
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     // Get the index of the new element
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     // Add the new element to the mesh
00493     AddElement(new VertexElement<ELEMENT_DIM,SPACE_DIM>(new_element_index, nodes_elem));
00494 
00501     // Find lowest element
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     // Mark any nodes that are contained only in this element as deleted
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         // Mark all the nodes contained in the removed element as boundary nodes
00598         p_node->SetAsBoundaryNode(true);
00599     }
00600 
00601     // Mark this element as deleted
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     // Find the indices of the elements owned by each node
00618     std::set<unsigned> elements_containing_nodeA = pNodeA->rGetContainingElementIndices();
00619     std::set<unsigned> elements_containing_nodeB = pNodeB->rGetContainingElementIndices();
00620 
00621     // Find common elements
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     // Check that the nodes have a common edge and not more than 2
00630     assert(!shared_elements.empty());
00631     assert(!shared_elements.size()<=2);
00632 
00633     // Specifiy if its a boundary node
00634     bool is_boundary_node = false;
00635     if (shared_elements.size()==1)
00636     {
00637         // If only one shared element then must be on the boundary.
00638         assert((pNodeA->IsBoundaryNode())&&(pNodeB->IsBoundaryNode()));
00639         is_boundary_node = true;
00640     }
00641 
00642     // Create a new node (position is not important as it will be changed)
00643     Node<SPACE_DIM>* p_new_node = new Node<SPACE_DIM>(GetNumNodes(), is_boundary_node, 0.0, 0.0);
00644 
00645     // Update the node location
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     // Add node to mesh
00651     this->mNodes.push_back(p_new_node);
00652 
00653     // Iterate over common elements
00654     for (std::set<unsigned>::iterator iter = shared_elements.begin();
00655          iter != shared_elements.end();
00656          ++iter)
00657     {
00658         // Find which node has the lower local index in this element
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         // Add new node to this element
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     // Make sure that we are in the correct dimension - this code will be eliminated at compile time
00684     assert(SPACE_DIM==2 || SPACE_DIM==3);
00685     assert(ELEMENT_DIM == SPACE_DIM);
00686 
00687     // Make sure the map is big enough
00688     rElementMap.Resize(this->GetNumAllElements());
00689 
00690     // Remove deleted elements
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     // Remove deleted nodes
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     // Make sure that we are in the correct dimension - this code will be eliminated at compile time
00750     assert(SPACE_DIM==2 || SPACE_DIM==3);
00751     assert(ELEMENT_DIM == SPACE_DIM);
00752 
00753     if (SPACE_DIM==2)
00754     {
00755         /*
00756          * We do not need to call Clear() and remove all current data, since
00757          * cell birth, rearrangement and death result only in local remeshing
00758          * of a vertex-based mesh.
00759          */
00760 
00761         // Remove deleted nodes and elements
00762         RemoveDeletedNodesAndElements(rElementMap);
00763 
00764         // Check for element rearrangements
00765         bool recheck_mesh = true;
00766         while (recheck_mesh == true)
00767         {
00768             // Separate loops as need to check for T2Swaps first
00769             recheck_mesh = CheckForT2Swaps(rElementMap);
00770 
00771             if (recheck_mesh == false)
00772             {
00773                 recheck_mesh = CheckForT1Swaps(rElementMap);
00774             }
00775         }
00776 
00777         //Check for element intersections.
00778         recheck_mesh = true;
00779         while (recheck_mesh == true)
00780         {
00781             //Check mesh for intersections, and perform T3Swaps where required
00782             recheck_mesh = CheckForIntersections();
00783         }
00784 
00785         RemoveDeletedNodes(); // to remove any nodes if they are deleted
00786     }
00787     else // 3D
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     // Loop over elements to check for T1Swaps
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); // if not element should be deleted
00816 
00817         unsigned new_num_nodes = num_nodes;
00818 
00819         /*
00820          * Perform T1 swaps and merges where necessary
00821          * Check there are > 3 nodes in both elements that contain the pair of nodes
00822          * and the edges are small enough
00823          */
00824 
00825         // Loop over element vertices
00826         for (unsigned local_index=0; local_index<num_nodes; local_index++)
00827         {
00828             // Find locations of current node and anticlockwise node
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             // Find distance between nodes
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             // Track if either node is in a triangular element.
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             // If the nodes are too close together and we don't have any triangular elements connected to the nodes, perform a swap
00858             if ((!triangular_element) && (distance_between_nodes < mCellRearrangementThreshold))
00859             {
00860                 // Identify the type of node swap/merge needed then call method to perform swap/merge
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     // Loop over elements to check for T2Swaps
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              * Perform T2 swaps where necessary
00882              * Check there are only 3 nodes and the element is small enough
00883              */
00884             if (GetVolumeOfElement(elem_iter->GetIndex()) < GetT2Threshold())
00885             {
00886                 PerformT2Swap(*elem_iter);
00887 
00888                 // Now remove the deleted nodes (if we don't do this then the search for T1Swap causes errors)
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     // Check that no boundary nodes have overlapped elements on the boundary
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                     // Check that the node is not part of this element.
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     // Make sure that we are in the correct dimension - this code will be eliminated at compile time
00942     assert(SPACE_DIM == 2); // this method only works in 2D at present
00943     assert(ELEMENT_DIM == SPACE_DIM);
00944 
00945     // Find the sets of elements containing nodes A and B
00946     std::set<unsigned> nodeA_elem_indices = pNodeA->rGetContainingElementIndices();
00947 
00948     std::set<unsigned> nodeB_elem_indices = pNodeB->rGetContainingElementIndices();
00949 
00950     // Form the set union
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); // temp_set will be deleted
00956 
00957     if ((nodeA_elem_indices.size()>3) || (nodeB_elem_indices.size()>3))
00958     {
00959         /*
00960          * Looks like
00961          *
00962          *  \
00963          *   \ A   B
00964          * ---o---o---
00965          *   /
00966          *  /
00967          *
00968          */
00969         EXCEPTION("A node is contained in more than three elements"); // the code can't handle this case
00970     }
00971     else // each node is contained in at most three elements
00972     {
00973         switch (all_indices.size())
00974         {
00975             case 1:
00976             {
00977                 /*
00978                  * In this case, each node is contained in a single element, so the nodes
00979                  * lie on the boundary of the mesh:
00980                  *
00981                  *    A   B
00982                  * ---o---o---
00983                  *
00984                  * We merge the nodes.
00985                  */
00986 
00987                 // Check nodes A and B are on the boundary
00988                 assert(pNodeA->IsBoundaryNode());
00989                 assert(pNodeB->IsBoundaryNode());
00990 
00991                 PerformNodeMerge(pNodeA, pNodeB);
00992 
00993                 // Remove the deleted node and re-index
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                          * In this case, the node configuration looks like:
01005                          *
01006                          *   \   /
01007                          *    \ / Node A
01008                          * (1) |   (2)      (element number in brackets)
01009                          *    / \ Node B
01010                          *   /   \
01011                          *
01012                          * With voids on top and bottom
01013                          *
01014                          * We perform a Type 1 swap and separate the elements in this case.
01015                          */
01016                          PerformT1Swap(pNodeA, pNodeB,all_indices);
01017                     }
01018                     else if (pNodeA->IsBoundaryNode() || pNodeB->IsBoundaryNode())
01019                     {
01020                         /*
01021                          * In this case, the node configuration looks like:
01022                          *
01023                          *   \   /
01024                          *    \ / Node A
01025                          * (1) |   (2)      (element number in brackets)
01026                          *     x Node B
01027                          *     |
01028                          *
01029                          * With a void on top.
01030                          *
01031                          * We should not be able to get here when running normal vertex code
01032                          * as there should only be nodes on 3 way junctions or boundaries.
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                          * In this case, each node is contained in two elements, so the nodes
01042                          * lie on an internal edge:
01043                          *
01044                          *    A   B
01045                          * ---o---o---
01046                          *
01047                          * We should not be able to get here when running normal vertex code
01048                          * as there should only be nodes on 3 way junctions or boundaries.
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                      * In this case, the node configuration looks like:
01058                      *
01059                      * Outside
01060                      *         /
01061                      *   --o--o (2)
01062                      *     (1) \
01063                      *
01064                      * We merge the nodes in this case. ///\todo this should be a T1 Swap see #1263
01065                      */
01066 
01067                     PerformNodeMerge(pNodeA, pNodeB);
01068 
01069                     // Remove the deleted node and re-index
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                      * In this case, one node is contained in one element and
01080                      * the other node is contained in three elements:
01081                      *
01082                      *    A   B
01083                      *
01084                      *  empty   /
01085                      *         / (3)
01086                      * ---o---o-----   (element number in brackets)
01087                      *  (1)    \ (2)
01088                      *          \
01089                      *
01090                      * We should not be able to get here when running normal vertex code
01091                      * as a boundary node is contained in at most 2 elements.
01092                      */
01093 
01094                     // Check nodes A and B are on the boundary
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                     // element in nodeA_elem_indices which is not in nodeB_elem_indices contains a shared node with the element in nodeA_elem_indices which is not in nodeB_elem_indices.
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                     // Should only be one such element
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                     // Should only be one such element
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                          * In this case, the node configuration looks like:
01136                          *
01137                          *    A  C  B                A      B
01138                          *      /\                 \        /
01139                          *     /v \                 \  (1) /
01140                          * (3)o----o (1)  or     (2) o----o (3)    (element number in brackets, v is a void)
01141                          *   /  (2) \                 \v /
01142                          *  /        \                 \/
01143                          *                             C
01144                          *
01145                          * We perform a T3 way merge, removing the void.
01146                          */
01147 
01148                         // Check nodes A and B are on the boundary
01149                         assert(pNodeA->IsBoundaryNode());
01150                         assert(pNodeB->IsBoundaryNode());
01151 
01152                         // Get the other node in the triangular void
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                          * In this case, the node configuration looks like:
01174                          *
01175                          *     A  B                  A  B
01176                          *   \ empty/              \      /
01177                          *    \    /                \(1) /
01178                          * (3) o--o (1)  or      (2) o--o (3)    (element number in brackets)
01179                          *    / (2)\                /    \
01180                          *   /      \              /empty \
01181                          *
01182                          * We perform a T1 Swap in this case.
01183                          */
01184 
01185                         // Check nodes A and B are on the boundary
01186                         assert(pNodeA->IsBoundaryNode());
01187                         assert(pNodeB->IsBoundaryNode());
01188 
01189                         PerformT1Swap(pNodeA, pNodeB, all_indices);
01190                     }
01191                 }
01192                 else
01193                 {
01194                     /*
01195                      * In this case, one of the nodes is contained in two elements
01196                      * and the other node is contained in three elements.
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                     // They can't both be boundary nodes
01202                     assert(!(pNodeA->IsBoundaryNode() && pNodeB->IsBoundaryNode()));
01203 
01204                     if (pNodeA->IsBoundaryNode() || pNodeB->IsBoundaryNode())
01205                     {
01206                         /*
01207                          * In this case, the node configuration looks like:
01208                          *
01209                          *     A  B                      A  B
01210                          *   \      /                  \      /
01211                          *    \ (1)/                    \(1) /
01212                          * (3) o--o (empty)  or  (empty) o--o (3)    (element number in brackets)
01213                          *    / (2)\                    /(2) \
01214                          *   /      \                  /      \
01215                          *
01216                          * We perform a Type 1 swap in this case.
01217                          */
01218                         PerformT1Swap(pNodeA, pNodeB, all_indices);
01219                     }
01220                     else
01221                     {
01222                         /*
01223                          * In this case, the node configuration looks like:
01224                          *
01225                          *     A  B             A  B
01226                          *   \                       /
01227                          *    \  (1)           (1)  /
01228                          * (3) o--o---   or  ---o--o (3)    (element number in brackets)
01229                          *    /  (2)           (2)  \
01230                          *   /                       \
01231                          *
01232                          * We should not be able to get here when running normal vertex code
01233                          * as there should only be nodes on 3 way junctions or boundaries.
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                  * In this case, the node configuration looks like:
01245                  *
01246                  *   \(1)/
01247                  *    \ / Node A
01248                  * (2) |   (4)      (element number in brackets)
01249                  *    / \ Node B
01250                  *   /(3)\
01251                  *
01252                  * We perform a Type 1 swap in this case.
01253                  */
01254                 PerformT1Swap(pNodeA, pNodeB, all_indices);
01255                 break;
01256             }
01257             default:
01258                 // This can't happen
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     // Sort the nodes by index
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; // low index
01272     unsigned hi_node_index = (nodeA_index < nodeB_index) ? nodeB_index : nodeA_index; // high index
01273 
01274     // Get pointers to the nodes, sorted by index
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     // Find the sets of elements containing each of the nodes, sorted by index
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     // Move the low-index node to the mid-point
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     // Update the elements previously containing the high-index node to contain the low-index node
01288     for (std::set<unsigned>::const_iterator it = hi_node_elem_indices.begin();
01289          it != hi_node_elem_indices.end();
01290          ++it)
01291     {
01292         // Find the local index of the high-index node in this element
01293         unsigned hi_node_local_index = this->mElements[*it]->GetNodeLocalIndex(hi_node_index);
01294         assert(hi_node_local_index < UINT_MAX); // this element should contain the high-index node
01295 
01296         /*
01297          * If this element already contains the low-index node, then just remove the high-index node.
01298          * Otherwise replace it with the low-index node in the element and remove it from mNodes.
01299          */
01300         if (lo_node_elem_indices.count(*it) > 0)
01301         {
01302             this->mElements[*it]->DeleteNode(hi_node_local_index); // think this method removes the high-index node from mNodes
01303         }
01304         else
01305         {
01306             // Replace the high-index node with the low-index node in this element
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     // Make sure that we are in the correct dimension - this code will be eliminated at compile time
01321     assert(SPACE_DIM == 2); // only works in 2D at present
01322     assert(ELEMENT_DIM == SPACE_DIM);
01323 
01324     /*
01325      * Restructure elements - remember to update nodes and elements.
01326      *
01327      * We need to implement the following changes:
01328      *
01329      * The element whose index was in nodeA_elem_indices but not nodeB_elem_indices,
01330      * and the element whose index was in nodeB_elem_indices but not nodeA_elem_indices,
01331      * should now both contain nodes A and B.
01332      *
01333      * The element whose index was in nodeA_elem_indices and nodeB_elem_indices, and which
01334      * node C lies inside, should now only contain node A.
01335      *
01336      * The element whose index was in nodeA_elem_indices and nodeB_elem_indices, and which
01337      * node D lies inside, should now only contain node B.
01338      *
01339      * Iterate over all elements involved and identify which element they are
01340      * in the diagram then update the nodes as necessary.
01341      *
01342      *   \(1)/
01343      *    \ / Node A
01344      * (2) |   (4)     elements in brackets
01345      *    / \ Node B
01346      *   /(3)\
01347      *
01348      */
01349 
01350     /*
01351      * Compute the locations of two new nodes C, D, placed on either side of the
01352      * edge E_old formed by nodes current_node and anticlockwise_node, such
01353      * that the edge E_new formed by the new nodes is the perpendicular bisector
01354      * of E_old, with |E_new| 'just larger' (mCellRearrangementRatio) than mThresholdDistance.
01355      */
01356 
01357     // Find the sets of elements containing nodes A and B
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     // Store the location of the T1Swap, the mid point of the moving nodes,
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      * Move node A to C and node B to D
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()) // not in nodeA_elem_indices so element 3
01399         {
01400             /*
01401              * In this case the element index was not in
01402              * nodeA_elem_indices, so this element
01403              * does not contain node A. Therefore we must add node A
01404              * (which has been moved to node C) to this element.
01405              *
01406              * Locate local index of node B in element then add node A after
01407              * in anticlockwise direction.
01408              */
01409 
01410             unsigned nodeB_local_index = this->mElements[*it]->GetNodeLocalIndex(pNodeB->GetIndex());
01411             assert(nodeB_local_index < UINT_MAX); // this element should contain node B
01412 
01413             this->mElements[*it]->AddNode(nodeB_local_index, pNodeA);
01414         }
01415         else if (nodeB_elem_indices.find(*it) == nodeB_elem_indices.end()) // not in nodeB_elem_indices so element 1
01416         {
01417             /*
01418              * In this case the element index was not in
01419              * nodeB_elem_indices, so this element
01420              * does not contain node B. Therefore we must add node B
01421              * (which has been moved to node D) to this element.
01422              *
01423              * Locate local index of node A in element then add node B after
01424              * in anticlockwise direction.
01425              */
01426             unsigned nodeA_local_index = this->mElements[*it]->GetNodeLocalIndex(pNodeA->GetIndex());
01427             assert(nodeA_local_index < UINT_MAX); // this element should contain node A
01428             this->mElements[*it]->AddNode(nodeA_local_index, pNodeB);
01429         }
01430         else
01431         {
01432             /*
01433              * In this case the element index was in both nodeB_elem_indices and nodeB_elem_indices
01434              * so is element 2 or 4
01435              */
01436 
01437             /*
01438              * Locate local index of nodeA and nodeB and use the ordering to
01439              * identify the element, if nodeB_index > nodeA_index then element 4
01440              * and if nodeA_index > nodeB_index then element 2
01441              */
01442             unsigned nodeA_local_index = this->mElements[*it]->GetNodeLocalIndex(pNodeA->GetIndex());
01443             assert(nodeA_local_index < UINT_MAX); // this element should contain node A
01444 
01445             unsigned nodeB_local_index = this->mElements[*it]->GetNodeLocalIndex(pNodeB->GetIndex());
01446             assert(nodeB_local_index < UINT_MAX); // this element should contain node B
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                  * In this case the local index of nodeA is the local index of
01454                  * nodeB plus one so we are in element 2 so we remove nodeB
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())); // as A and B are next to each other
01461                 /*
01462                  * In this case the local index of nodeA is the local index of
01463                  * nodeB minus one so we are in element 4 so we remove nodeA
01464                  */
01465                 this->mElements[*it]->DeleteNode(nodeA_local_index);
01466             }
01467         }
01468     }
01469 
01470     // Sort out boundary nodes
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     // Make sure that we are in the correct dimension - this code will be eliminated at compile time
01496     assert(SPACE_DIM == 2); // only works in 2D at present
01497     assert(ELEMENT_DIM == SPACE_DIM);
01498 
01499     /*
01500      * For removing a small triangle
01501      *
01502      *  \
01503      *   \
01504      *   |\
01505      *   | \
01506      *   |  \_ _ _ _ _
01507      *   |  /
01508      *   | /
01509      *   |/
01510      *   /
01511      *  /
01512      *
01513      * To
01514      *
01515      *  \
01516      *   \
01517      *    \
01518      *     \
01519      *      \_ _ _ _ _
01520      *      /
01521      *     /
01522      *    /
01523      *   /
01524      *  /
01525      *
01526      */
01527 
01528     // Assert that the triangle element has only three nodes (!)
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     // Create new node at centroid of element which will be a boundary node if any of the existing nodes was on the boundary.
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) // there is a neighbouring element
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     // Also have to mark pElement, pElement->GetNode(0), pElement->GetNode(1), and pElement->GetNode(2) as deleted.
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     // Make sure that we are in the correct dimension - this code will be eliminated at compile time
01598     assert(SPACE_DIM == 2); // only works in 2D at present
01599     assert(ELEMENT_DIM == SPACE_DIM);
01600 
01601     // Check pNode is a boundary node
01602     assert(pNode->IsBoundaryNode());
01603 
01604     // Store the index of the elements containing the intersecting node
01605     std::set<unsigned> elements_containing_intersecting_node = pNode->rGetContainingElementIndices();
01606 
01607     // Get the local index of the node in the intersected element after which the new node is to be added
01608     unsigned node_A_local_index = GetLocalIndexForElementEdgeClosestToPoint(pNode->rGetLocation(), elementIndex);
01609 
01610     // Get current node location
01611     c_vector<double, SPACE_DIM> node_location = pNode->rGetModifiableLocation();
01612 
01613     // Get element
01614     VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = this->GetElement(elementIndex);
01615     unsigned num_nodes = p_element->GetNumNodes();
01616 
01617 
01619 //   TRACE("intersecting node");
01620 //    PRINT_2_VARIABLES(pNode->GetIndex(),node_location);
01621 //
01622 //
01623 //    for (std::set<unsigned>::const_iterator elem_iter = elements_containing_intersecting_node.begin();
01624 //         elem_iter != elements_containing_intersecting_node.end();
01625 //         elem_iter++)
01626 //
01627 //    {
01628 //        TRACE("intersecting element");
01629 //
01630 //        VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_intersection = this->GetElement(*elem_iter);
01631 //        PRINT_VARIABLE(p_element_intersection->GetIndex());
01632 //
01633 //        for (unsigned node_index = 0;
01634 //             node_index < p_element_intersection->GetNumNodes();
01635 //             node_index++)
01636 //        {
01637 //            PRINT_3_VARIABLES(p_element_intersection->GetNodeGlobalIndex(node_index),
01638 //                              p_element_intersection->GetNode(node_index)->IsBoundaryNode(),
01639 //                              p_element_intersection->GetNodeLocation(node_index));
01640 //        }
01641 //    }
01642 //    TRACE("intersected element");
01643 //    PRINT_VARIABLE(p_element->GetIndex());
01644 //    for (unsigned node_index = 0;
01645 //         node_index < p_element->GetNumNodes();
01646 //         node_index++)
01647 //    {
01648 //        PRINT_3_VARIABLES(p_element->GetNodeGlobalIndex(node_index),
01649 //                          p_element->GetNode(node_index)->IsBoundaryNode(),
01650 //                          p_element->GetNodeLocation(node_index));
01651 //    }
01653 
01654 
01655     // Get the nodes at either end of the edge to be divided
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     // Check these nodes are also boundary nodes if this fails then the elements have become concave and you need a smaller timestep
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     // Get the nodes at either end of the edge to be divided and calculate intersection
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     // Store the location of the T3Swap, the location of the intersection with the edge.
01676     mLocationsOfT3Swaps.push_back(intersection);
01677 
01678     /*
01679      * If the edge is shorter than 4.0*mCellRearrangementRatio*mCellRearrangementThreshold move vertexA and vertexB
01680      * 4.0*mCellRearrangementRatio*mCellRearrangementThreshold apart. \todo investigate if moving A and B causes other issues with nearby nodes.
01681      *
01682      * Note: this distance so that there is always enough room for new nodes (if necessary)
01683      * \todo currently this assumes a worst case scenario of 3 nodes between A and B could be less movement for other cases. #1399
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         // Reset distances
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         // Reset the intersection to the middle to allow enough room for new nodes
01704         intersection = centre_a_and_b;
01705     }
01706 
01707     /*
01708      * If the intersection is within mCellRearrangementRatio^2*mCellRearrangementThreshold of vertexA or vertexB move it
01709      * mCellRearrangementRatio^2*mCellRearrangementThreshold away.
01710      *
01711      * Note: this distance so that there is always enough room for new nodes (if necessary).
01712      * \todo currently this assumes a worst case scenario of 3 nodes between A and B could be less movement for other cases.
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         // Get the index of the element containing the intersecting node
01726         unsigned intersecting_element_index = *elements_containing_intersecting_node.begin();
01727 
01728         // Get element
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         // Check to see if the nodes adjacent to the intersecting node are contained in the intersected element VertexA and VertexB
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             // Calculate the number of common vertices between element_1 and element_2
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                  * This is the situation here.
01774                  *
01775                  *  From          To
01776                  *   _             _
01777                  *    |  <---       |
01778                  *    |  /\         |\
01779                  *    | /  \        | \
01780                  *   _|/____\      _|__\
01781                  *
01782                  * The edge goes from vertexA--vertexB to vertexA--pNode--vertexB
01783                  */
01784 
01785                 // Move original node
01786                 pNode->rGetModifiableLocation() = intersection;
01787 
01788                 // Add the moved nodes to the element (this also updates the node)
01789                 this->GetElement(elementIndex)->AddNode(node_A_local_index, pNode);
01790 
01791                 // Check the nodes are updated correctly
01792                 assert(pNode->GetNumContainingElements() == 2);
01793             }
01794             else if (num_common_vertices == 2)
01795             {
01796                 /*
01797                  * This is the situation here.
01798                  *
01799                  * C is common_vertex D is the other one.
01800                  *
01801                  *  From          To
01802                  *   _ D          _
01803                  *    | <---       |
01804                  *    | /\         |\
01805                  *   C|/  \        | \
01806                  *   _|____\      _|__\
01807                  *
01808                  *  The edge goes from vertexC--vertexB to vertexC--pNode--vertexD
01809                  *  then VertexB is removed as it is no longer needed.
01810                  */
01811 
01812                 // Move original node
01813                 pNode->rGetModifiableLocation() = intersection;
01814 
01815                 // Replace common_vertex with the the moved node (this also updates the nodes)
01816                 this->GetElement(elementIndex)->ReplaceNode(this->mNodes[common_vertex_index], pNode);
01817 
01818                 // Remove common_vertex
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                 // Check the nodes are updated correctly
01826                 assert(pNode->GetNumContainingElements() == 2);
01827             }
01828             else
01829             {
01830                 // This can't happen as nodes can't be on the internal edge of 2 elements.
01831                 NEVER_REACHED;
01832             }
01833         }
01834         else
01835         {
01836             /*
01837              *  From          To
01838              *   ____        _______
01839              *                 / \
01840              *    /\   ^      /   \
01841              *   /  \  |
01842              *
01843              *  The edge goes from vertexA--vertexB to vertexA--new_node--pNode--vertexB
01844              */
01845 
01846             // Move original node
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             // Add new node which will always be a boundary node
01852             unsigned new_node_global_index = this->AddNode(new Node<SPACE_DIM>(0, true, new_node_location[0], new_node_location[1]));
01853 
01854             // Add the moved and new nodes to the element (this also updates the node)
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             // Add the new node to the original element containing pNode (this also updates the node)
01859             this->GetElement(intersecting_element_index)->AddNode(this->GetElement(intersecting_element_index)->GetNodeLocalIndex(pNode->GetIndex()), this->mNodes[new_node_global_index]);
01860 
01861             // Check the nodes are updated correctly
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         // Find the nodes contained in elements containing the intersecting node
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         // Check to see if the nodes adjacent to the intersecting node are contained in the intersected element VertexA and VertexB
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              * Here we have
01887              *        __
01888              *      /|             /
01889              *  __ / |     --> ___/
01890              *     \ |            \
01891              *      \|__           \
01892              *
01893              * Where the node on the left has overlapped the edge A B
01894              *
01895              * Move p_node to the intersection on A B and merge AB and p_node
01896              */
01897 
01898             //Check they are all boundary nodes
01899             assert(pNode->IsBoundaryNode());
01900             assert(this->mNodes[vertexA_index]->IsBoundaryNode());
01901             assert(this->mNodes[vertexB_index]->IsBoundaryNode());
01902 
01903             // Move p_node to the intersection with the edge A B
01904             pNode->rGetModifiableLocation() = intersection;
01905             pNode->SetAsBoundaryNode(false);
01906 
01907             // Add pNode to the intersected element
01908             this->GetElement(elementIndex)->AddNode(node_A_local_index, pNode);
01909 
01910             // Remove VertexA from elements
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             // Remove VertexA from the mesh
01920             assert(this->mNodes[vertexA_index]->GetNumContainingElements()==0);
01921 
01922             this->mNodes[vertexA_index]->MarkAsDeleted();
01923             mDeletedNodeIndices.push_back(vertexA_index);
01924 
01925             // Remove VertexB from elements
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             // Remove VertexB from the mesh
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                 // Get elements containing vertexA_index (the Common vertex)
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                 // Calculate the number of common vertices between element_1 and element_2
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                      *  From          To
01971                      *   _ B              _ B
01972                      *    |  <---          |
01973                      *    |   /|\          |\
01974                      *    |  / | \         | \
01975                      *    | /  |  \        |\ \
01976                      *   _|/___|___\      _|_\_\
01977                      *     A                A
01978                      *
01979                      * The edge goes from vertexA--vertexB to vertexA--pNode--new_node--vertexB
01980                      */
01981 
01982                     // Move original node and change to non-boundary node
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                     // Add new node which will always be a boundary node
01989                     unsigned new_node_global_index = this->AddNode(new Node<SPACE_DIM>(0, true, new_node_location[0], new_node_location[1]));
01990 
01991                     // Add the moved nodes to the element (this also updates the node)
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                     // Add the new nodes to the original elements containing pNode (this also updates the node)
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                     // Check the nodes are updated correctly
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                      *  From          To
02015                      *   _ B              _ B
02016                      *    |<---          |
02017                      *    | /|\          |\
02018                      *    |/ | \         | \
02019                      *    |  |  \        |\ \
02020                      *   _|__|___\      _|_\_\
02021                      *     A              A
02022                      *
02023                      * The edge goes from vertexA--vertexB to vertexA--pNode--new_node--vertexB
02024                      * then vertexA is removed
02025                      */
02026 
02027                     // Move original node and change to non-boundary node
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                     // Add new node which will always be a boundary node
02034                     unsigned new_node_global_index = this->AddNode(new Node<SPACE_DIM>(0, true, new_node_location[0], new_node_location[1]));
02035 
02036                     // Add the moved nodes to the element (this also updates the node)
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                     // Add the new nodes to the original elements containing pNode (this also updates the node)
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                     // Remove VertexA from the mesh
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                     // Check the nodes are updated correctly
02062                     assert(pNode->GetNumContainingElements() == 3);
02063                     assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
02064                 }
02065                 else
02066                 {
02067                     // This can't happen as nodes can't be on the internal edge of 2 elements.
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                 // Get elements containing vertexB_index (the Common vertex)
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                 // Calculate the number of common vertices between element_1 and element_2
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                      *  From          To
02101                      *   _B_________      _B____
02102                      *    |\   |   /       | / /
02103                      *    | \  |  /        |/ /
02104                      *    |  \ | /         | /
02105                      *    |   \|/          |/
02106                      *   _|   <---        _|
02107                      *    A
02108                      *
02109                      * The edge goes from vertexA--vertexB to vertexA--new_node--pNode--vertexB
02110                      */
02111 
02112                     // Move original node and change to non-boundary node
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                     // Add new node which will always be a boundary node
02119                     unsigned new_node_global_index = this->AddNode(new Node<SPACE_DIM>(0, true, new_node_location[0], new_node_location[1]));
02120 
02121                     // Add the moved nodes to the element (this also updates the node)
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                     // Add the new nodes to the original elements containing pNode (this also updates the node)
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                     // Check the nodes are updated correctly
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                      *  From          To
02145                      *   _B_______      _B____
02146                      *    |  |   /       | / /
02147                      *    |  |  /        |/ /
02148                      *    |\ | /         | /
02149                      *    | \|/          |/
02150                      *   _| <---        _|
02151                      *    A
02152                      *
02153                      * The edge goes from vertexA--vertexB to vertexA--new_node--pNode--vertexB
02154                      * then vertexB is removed
02155                      */
02156 
02157                     // Move original node and change to non-boundary node
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                     // Add new node which will always be a boundary node
02164                     unsigned new_node_global_index = this->AddNode(new Node<SPACE_DIM>(0, true, new_node_location[0], new_node_location[1]));
02165 
02166                     // Add the moved nodes to the element (this also updates the node)
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                     // Add the new nodes to the original elements containing pNode (this also updates the node)
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                     // Remove VertexB from the mesh
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                     // Check the nodes are updated correctly
02192                     assert(pNode->GetNumContainingElements() == 3);
02193                     assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
02194                 }
02195                 else
02196                 {
02197                     // This can't happen as nodes can't be on the internal edge of 2 elements.
02198                     NEVER_REACHED;
02199                 }
02200             }
02201             else
02202             {
02203                 /*
02204                  *  From          To
02205                  *   _____         _______
02206                  *                  / | \
02207                  *    /|\   ^      /  |  \
02208                  *   / | \  |
02209                  *
02210                  * The edge goes from vertexA--vertexB to vertexA--new_node_1--pNode--new_node_2--vertexB
02211                  */
02212 
02213                 // Move original node and change to non-boundary node
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                 // Add new nodes which will always be boundary nodes
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                 // Add the moved and new nodes to the element (this also updates the node)
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                 // Add the new nodes to the original elements containing pNode (this also updates the node)
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                 // Check the nodes are updated correctly
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; // Node with the lowest index out of A and B
02267     Node<SPACE_DIM>* p_low_node = (p_low_node_A_B->GetIndex() < nodeC_index) ? p_low_node_A_B : pNodeC; // Node with the lowest index out of A, B and C.
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     // Sort out boundary nodes
02276     p_low_node->SetAsBoundaryNode(false);
02277 
02278     // Remove the deleted nodes and re-index
02279     RemoveDeletedNodes();
02280 }
02281 
02282 
02284 // Explicit instantiation
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 // Serialization for Boost >= 1.36
02296 #include "SerializationExportWrapperForCpp.hpp"
02297 EXPORT_TEMPLATE_CLASS_ALL_DIMS(MutableVertexMesh);

Generated on Mon Apr 18 11:35:35 2011 for Chaste by  doxygen 1.5.5