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