MutableVertexMesh.cpp

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

Generated by  doxygen 1.6.2