MutableVertexMesh.cpp

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

Generated by  doxygen 1.6.2