Chaste Release::3.1
PottsMesh.cpp
00001 /*
00002 
00003 Copyright (c) 2005-2012, 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 "PottsMesh.hpp"
00037 #include "RandomNumberGenerator.hpp"
00038 #include "UblasCustomFunctions.hpp"
00039 #include <list>
00040 
00041 
00042 template<unsigned DIM>
00043 PottsMesh<DIM>::PottsMesh(std::vector<Node<DIM>*> nodes,
00044                           std::vector<PottsElement<DIM>*> pottsElements,
00045                           std::vector< std::set<unsigned> > vonNeumannNeighbouringNodeIndices,
00046                           std::vector< std::set<unsigned> > mooreNeighbouringNodeIndices)
00047 {
00048     // Reset member variables and clear mNodes, mElements.
00049     Clear();
00050 
00051     // Verify the same size of nodes and neighbour information.
00052     if ( (vonNeumannNeighbouringNodeIndices.size() != nodes.size()) || (mooreNeighbouringNodeIndices.size() != nodes.size()) )
00053     {
00054         EXCEPTION("Nodes and neighbour information for a potts mesh need to be the same length.");
00055     }
00056     mVonNeumannNeighbouringNodeIndices = vonNeumannNeighbouringNodeIndices;
00057     mMooreNeighbouringNodeIndices = mooreNeighbouringNodeIndices;
00058 
00059     // Populate mNodes and mElements
00060     for (unsigned node_index=0; node_index<nodes.size(); node_index++)
00061     {
00062         Node<DIM>* p_temp_node = nodes[node_index];
00063         this->mNodes.push_back(p_temp_node);
00064     }
00065     for (unsigned elem_index=0; elem_index<pottsElements.size(); elem_index++)
00066     {
00067         PottsElement<DIM>* p_temp_element = pottsElements[elem_index];
00068         mElements.push_back(p_temp_element);
00069     }
00070 
00071     // Register elements with nodes
00072     for (unsigned index=0; index<mElements.size(); index++)
00073     {
00074         PottsElement<DIM>* p_element = mElements[index];
00075 
00076         unsigned element_index = p_element->GetIndex();
00077         unsigned num_nodes_in_element = p_element->GetNumNodes();
00078 
00079         for (unsigned node_index=0; node_index<num_nodes_in_element; node_index++)
00080         {
00081             p_element->GetNode(node_index)->AddElement(element_index);
00082         }
00083     }
00084 
00085     this->mMeshChangesDuringSimulation = true;
00086 }
00087 
00088 template<unsigned DIM>
00089 PottsMesh<DIM>::PottsMesh()
00090 {
00091     this->mMeshChangesDuringSimulation = true;
00092     Clear();
00093 }
00094 
00095 template<unsigned DIM>
00096 PottsMesh<DIM>::~PottsMesh()
00097 {
00098     Clear();
00099 }
00100 
00101 template<unsigned DIM>
00102 unsigned PottsMesh<DIM>::SolveNodeMapping(unsigned index) const
00103 {
00104     assert(index < this->mNodes.size());
00105     return index;
00106 }
00107 
00108 template<unsigned DIM>
00109 unsigned PottsMesh<DIM>::SolveElementMapping(unsigned index) const
00110 {
00111     assert(index < this->mElements.size());
00112     return index;
00113 }
00114 
00115 template<unsigned DIM>
00116 unsigned PottsMesh<DIM>::SolveBoundaryElementMapping(unsigned index) const
00117 {
00118     return index;
00119 }
00120 
00121 template<unsigned DIM>
00122 void PottsMesh<DIM>::Clear()
00123 {
00124     // Delete elements
00125     for (unsigned i=0; i<mElements.size(); i++)
00126     {
00127         delete mElements[i];
00128     }
00129     mElements.clear();
00130 
00131     // Delete nodes
00132     for (unsigned i=0; i<this->mNodes.size(); i++)
00133     {
00134         delete this->mNodes[i];
00135     }
00136     this->mNodes.clear();
00137 
00138     mDeletedElementIndices.clear();
00139 
00140     // Delete neighbour info
00141     //mVonNeumannNeighbouringNodeIndices.clear();
00142     //mMooreNeighbouringNodeIndices.clear();
00143 }
00144 
00145 template<unsigned DIM>
00146 unsigned PottsMesh<DIM>::GetNumNodes() const
00147 {
00148     return this->mNodes.size();
00149 }
00150 
00151 template<unsigned DIM>
00152 unsigned PottsMesh<DIM>::GetNumElements() const
00153 {
00154     return mElements.size() - mDeletedElementIndices.size();
00155 }
00156 
00157 template<unsigned DIM>
00158 unsigned PottsMesh<DIM>::GetNumAllElements() const
00159 {
00160     return mElements.size();
00161 }
00162 
00163 template<unsigned DIM>
00164 PottsElement<DIM>* PottsMesh<DIM>::GetElement(unsigned index) const
00165 {
00166     assert(index < mElements.size());
00167     return mElements[index];
00168 }
00169 
00170 template<unsigned DIM>
00171 c_vector<double, DIM> PottsMesh<DIM>::GetCentroidOfElement(unsigned index)
00172 {
00173     PottsElement<DIM>* p_element = GetElement(index);
00174     unsigned num_nodes_in_element = p_element->GetNumNodes();
00175 
00177     c_vector<double, DIM> centroid = zero_vector<double>(DIM);
00178 
00179     for (unsigned local_index=0; local_index<num_nodes_in_element; local_index++)
00180     {
00181         // Find location of current node and add it to the centroid
00182         centroid += p_element->GetNodeLocation(local_index);
00183     }
00184 
00185     centroid /= num_nodes_in_element;
00186 
00187     return centroid;
00188 }
00189 
00190 template<unsigned DIM>
00191 c_vector<double, DIM> PottsMesh<DIM>::GetVectorFromAtoB(const c_vector<double, DIM>& rLocationA, const c_vector<double, DIM>& rLocationB)
00192 {
00193     c_vector<double, DIM> vector = AbstractMesh<DIM, DIM>::GetVectorFromAtoB(rLocationA, rLocationB);
00194 
00195     return vector;
00196 }
00197 
00198 template<unsigned DIM>
00199 double PottsMesh<DIM>::GetVolumeOfElement(unsigned index)
00200 {
00201     PottsElement<DIM>* p_element = GetElement(index);
00202     double element_volume = (double) p_element->GetNumNodes();
00203 
00204     return element_volume;
00205 }
00206 
00207 template<unsigned DIM>
00208 double PottsMesh<DIM>::GetSurfaceAreaOfElement(unsigned index)
00209 {
00211     assert(DIM==2 || DIM==3);
00212 
00213     // Get pointer to this element
00214     PottsElement<DIM>* p_element = GetElement(index);
00215 
00216     double surface_area = 0.0;
00217     for (unsigned node_index=0; node_index< p_element->GetNumNodes(); node_index++)
00218     {
00219         std::set<unsigned> neighbouring_node_indices = GetVonNeumannNeighbouringNodeIndices(p_element->GetNode(node_index)->GetIndex());
00220         unsigned local_edges = 2*DIM;
00221         for (std::set<unsigned>::iterator iter = neighbouring_node_indices.begin();
00222              iter != neighbouring_node_indices.end();
00223              iter++)
00224         {
00225             std::set<unsigned> neighbouring_node_element_indices = this->mNodes[*iter]->rGetContainingElementIndices();
00226 
00227             if (neighbouring_node_element_indices.size()>0 && local_edges>0)
00228             {
00229                 unsigned neighbouring_node_element_index = *(neighbouring_node_element_indices.begin());
00230                 if (neighbouring_node_element_index == index)
00231                 {
00232                     local_edges--;
00233                 }
00234             }
00235         }
00236         surface_area += local_edges;
00237     }
00238     return surface_area;
00239 }
00240 
00241 template<unsigned DIM>
00242 std::set<unsigned> PottsMesh<DIM>::GetMooreNeighbouringNodeIndices(unsigned nodeIndex)
00243 {
00244     return mMooreNeighbouringNodeIndices[nodeIndex];
00245 }
00246 
00247 template<unsigned DIM>
00248 std::set<unsigned> PottsMesh<DIM>::GetVonNeumannNeighbouringNodeIndices(unsigned nodeIndex)
00249 {
00250     return mVonNeumannNeighbouringNodeIndices[nodeIndex];
00251 }
00252 
00253 template<unsigned DIM>
00254 void PottsMesh<DIM>::DeleteElement(unsigned index)
00255 {
00256     // Mark this element as deleted; this also updates the nodes containing element indices
00257     this->mElements[index]->MarkAsDeleted();
00258     mDeletedElementIndices.push_back(index);
00259 }
00260 
00261 template<unsigned DIM>
00262 unsigned PottsMesh<DIM>::DivideElement(PottsElement<DIM>* pElement,
00263                                   bool placeOriginalElementBelow)
00264 {
00266     assert(DIM==2 || DIM==3);
00267 
00268     // Store the number of nodes in the element (this changes when nodes are deleted from the element)
00269     unsigned num_nodes = pElement->GetNumNodes();
00270 
00271     if (num_nodes < 2)
00272     {
00273         EXCEPTION("Tried to divide a Potts element with only one node. Cell dividing too often given dynamic parameters.");
00274     }
00275 
00276     // Copy the nodes in this element
00277     std::vector<Node<DIM>*> nodes_elem;
00278     for (unsigned i=0; i<num_nodes; i++)
00279     {
00280         nodes_elem.push_back(pElement->GetNode(i));
00281     }
00282 
00283     // Get the index of the new element
00284     unsigned new_element_index;
00285     if (mDeletedElementIndices.empty())
00286     {
00287         new_element_index = this->mElements.size();
00288     }
00289     else
00290     {
00291         new_element_index = mDeletedElementIndices.back();
00292         mDeletedElementIndices.pop_back();
00293         delete this->mElements[new_element_index];
00294     }
00295 
00296     // Add the new element to the mesh
00297     AddElement(new PottsElement<DIM>(new_element_index, nodes_elem));
00298 
00304     unsigned half_num_nodes = num_nodes/2; // This will round down
00305     assert(half_num_nodes > 0);
00306     assert(half_num_nodes < num_nodes);
00307 
00308     // Find lowest element
00310     double height_midpoint_1 = 0.0;
00311     double height_midpoint_2 = 0.0;
00312     unsigned counter_1 = 0;
00313     unsigned counter_2 = 0;
00314 
00315     for (unsigned i=0; i<num_nodes; i++)
00316     {
00317         if (i<half_num_nodes)
00318         {
00319             height_midpoint_1 += pElement->GetNode(i)->rGetLocation()[DIM - 1];
00320             counter_1++;
00321         }
00322         else
00323         {
00324             height_midpoint_2 += pElement->GetNode(i)->rGetLocation()[DIM -1];
00325             counter_2++;
00326         }
00327     }
00328     height_midpoint_1 /= (double)counter_1;
00329     height_midpoint_2 /= (double)counter_2;
00330 
00331     for (unsigned i=num_nodes; i>0; i--)
00332     {
00333         if (i-1 >= half_num_nodes)
00334         {
00335             if (height_midpoint_1 < height_midpoint_2)
00336             {
00337                 if (placeOriginalElementBelow)
00338                 {
00339                     pElement->DeleteNode(i-1);
00340                 }
00341                 else
00342                 {
00343                     this->mElements[new_element_index]->DeleteNode(i-1);
00344                 }
00345             }
00346             else
00347             {
00348                 if (placeOriginalElementBelow)
00349                 {
00350                     this->mElements[new_element_index]->DeleteNode(i-1);
00351                 }
00352                 else
00353                 {
00354                     pElement->DeleteNode(i-1);
00355                 }
00356             }
00357         }
00358         else // i-1 < half_num_nodes
00359         {
00360             if (height_midpoint_1 < height_midpoint_2)
00361             {
00362                 if (placeOriginalElementBelow)
00363                 {
00364                     this->mElements[new_element_index]->DeleteNode(i-1);
00365                 }
00366                 else
00367                 {
00368                     pElement->DeleteNode(i-1);
00369                 }
00370             }
00371             else
00372             {
00373                 if (placeOriginalElementBelow)
00374                 {
00375                     pElement->DeleteNode(i-1);
00376                 }
00377                 else
00378                 {
00379                     this->mElements[new_element_index]->DeleteNode(i-1);
00380                 }
00381             }
00382         }
00383     }
00384 
00385     return new_element_index;
00386 }
00387 
00388 template<unsigned DIM>
00389 unsigned PottsMesh<DIM>::AddElement(PottsElement<DIM>* pNewElement)
00390 {
00391     unsigned new_element_index = pNewElement->GetIndex();
00392 
00393     if (new_element_index == this->mElements.size())
00394     {
00395         this->mElements.push_back(pNewElement);
00396     }
00397     else
00398     {
00399         this->mElements[new_element_index] = pNewElement;
00400     }
00401     pNewElement->RegisterWithNodes();
00402     return pNewElement->GetIndex();
00403 }
00404 
00405 template<unsigned DIM>
00406 void PottsMesh<DIM>::ConstructFromMeshReader(AbstractMeshReader<DIM, DIM>& rMeshReader)
00407 {
00408     // Store numbers of nodes and elements
00409     unsigned num_nodes = rMeshReader.GetNumNodes();
00410     unsigned num_elements = rMeshReader.GetNumElements();
00411 
00412     // Reserve memory for nodes
00413     this->mNodes.reserve(num_nodes);
00414 
00415     rMeshReader.Reset();
00416 
00417     // Add nodes
00418     std::vector<double> node_data;
00419     for (unsigned i=0; i<num_nodes; i++)
00420     {
00421         node_data = rMeshReader.GetNextNode();
00422         unsigned is_boundary_node = (unsigned) node_data[DIM];
00423         node_data.pop_back();
00424         this->mNodes.push_back(new Node<DIM>(i, node_data, is_boundary_node));
00425     }
00426 
00427     rMeshReader.Reset();
00428 
00429     // Reserve memory for nodes
00430     mElements.reserve(rMeshReader.GetNumElements());
00431 
00432     // Add elements
00433     for (unsigned elem_index=0; elem_index<num_elements; elem_index++)
00434     {
00435         // Get the data for this element
00436         ElementData element_data = rMeshReader.GetNextElementData();
00437 
00438         // Get the nodes owned by this element
00439         std::vector<Node<DIM>*> nodes;
00440         unsigned num_nodes_in_element = element_data.NodeIndices.size();
00441         for (unsigned j=0; j<num_nodes_in_element; j++)
00442         {
00443             assert(element_data.NodeIndices[j] < this->mNodes.size());
00444             nodes.push_back(this->mNodes[element_data.NodeIndices[j]]);
00445         }
00446 
00447         // Use nodes and index to construct this element
00448         PottsElement<DIM>* p_element = new PottsElement<DIM>(elem_index, nodes);
00449         mElements.push_back(p_element);
00450 
00451         if (rMeshReader.GetNumElementAttributes() > 0)
00452         {
00453             assert(rMeshReader.GetNumElementAttributes() == 1);
00454             unsigned attribute_value = element_data.AttributeValue;
00455             p_element->SetAttribute(attribute_value);
00456         }
00457     }
00458 
00459     // If just using mesh reader then there is no neighbour information see #1932
00460     if (mVonNeumannNeighbouringNodeIndices.size()==0)
00461     {
00462         mVonNeumannNeighbouringNodeIndices.resize(num_nodes);
00463     }
00464     if (mMooreNeighbouringNodeIndices.size()==0)
00465     {
00466         mMooreNeighbouringNodeIndices.resize(num_nodes);
00467     }
00468 }
00469 
00471 // Explicit instantiation
00473 
00474 template class PottsMesh<1>;
00475 template class PottsMesh<2>;
00476 template class PottsMesh<3>;
00477 
00478 // Serialization for Boost >= 1.36
00479 #include "SerializationExportWrapperForCpp.hpp"
00480 EXPORT_TEMPLATE_CLASS_SAME_DIMS(PottsMesh)