PottsMesh.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2011
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 */
00028 
00029 #include "PottsMesh.hpp"
00030 #include "RandomNumberGenerator.hpp"
00031 #include "UblasCustomFunctions.hpp"
00032 #include <list>
00033 
00034 
00035 template<unsigned DIM>
00036 PottsMesh<DIM>::PottsMesh(std::vector<Node<DIM>*> nodes,
00037                           std::vector<PottsElement<DIM>*> pottsElements,
00038                           std::vector< std::set<unsigned> > vonNeumannNeighbouringNodeIndices,
00039                           std::vector< std::set<unsigned> > mooreNeighbouringNodeIndices)
00040 {
00041     // Reset member variables and clear mNodes, mElements.
00042     Clear();
00043 
00044     // Verify the same size of nodes and neighbour information.
00045     if ( (vonNeumannNeighbouringNodeIndices.size() != nodes.size()) || (mooreNeighbouringNodeIndices.size() != nodes.size()) )
00046     {
00047         EXCEPTION("Nodes and neighbour information for a potts mesh need to be the same length.");
00048     }
00049     mVonNeumannNeighbouringNodeIndices = vonNeumannNeighbouringNodeIndices;
00050     mMooreNeighbouringNodeIndices = mooreNeighbouringNodeIndices;
00051 
00052     // Populate mNodes and mElements
00053     for (unsigned node_index=0; node_index<nodes.size(); node_index++)
00054     {
00055         Node<DIM>* p_temp_node = nodes[node_index];
00056         this->mNodes.push_back(p_temp_node);
00057 
00058     }
00059     for (unsigned elem_index=0; elem_index<pottsElements.size(); elem_index++)
00060     {
00061         PottsElement<DIM>* p_temp_element = pottsElements[elem_index];
00062         mElements.push_back(p_temp_element);
00063     }
00064 
00065     // Register elements with nodes
00066     for (unsigned index=0; index<mElements.size(); index++)
00067     {
00068         PottsElement<DIM>* p_element = mElements[index];
00069 
00070         unsigned element_index = p_element->GetIndex();
00071         unsigned num_nodes_in_element = p_element->GetNumNodes();
00072 
00073         for (unsigned node_index=0; node_index<num_nodes_in_element; node_index++)
00074         {
00075             p_element->GetNode(node_index)->AddElement(element_index);
00076         }
00077     }
00078 
00079     this->mMeshChangesDuringSimulation = true;
00080 }
00081 
00082 template<unsigned DIM>
00083 PottsMesh<DIM>::PottsMesh()
00084 {
00085     this->mMeshChangesDuringSimulation = true;
00086     Clear();
00087 }
00088 
00089 template<unsigned DIM>
00090 PottsMesh<DIM>::~PottsMesh()
00091 {
00092     Clear();
00093 }
00094 
00095 template<unsigned DIM>
00096 unsigned PottsMesh<DIM>::SolveNodeMapping(unsigned index) const
00097 {
00098     assert(index < this->mNodes.size());
00099     return index;
00100 }
00101 
00102 template<unsigned DIM>
00103 unsigned PottsMesh<DIM>::SolveElementMapping(unsigned index) const
00104 {
00105     assert(index < this->mElements.size());
00106     return index;
00107 }
00108 
00109 template<unsigned DIM>
00110 unsigned PottsMesh<DIM>::SolveBoundaryElementMapping(unsigned index) const
00111 {
00112     return index;
00113 }
00114 
00115 template<unsigned DIM>
00116 void PottsMesh<DIM>::Clear()
00117 {
00118     // Delete elements
00119     for (unsigned i=0; i<mElements.size(); i++)
00120     {
00121         delete mElements[i];
00122     }
00123     mElements.clear();
00124 
00125     // Delete nodes
00126     for (unsigned i=0; i<this->mNodes.size(); i++)
00127     {
00128         delete this->mNodes[i];
00129     }
00130     this->mNodes.clear();
00131 
00132     mDeletedElementIndices.clear();
00133 
00134     // Delete neighbour info
00135     //mVonNeumannNeighbouringNodeIndices.clear();
00136     //mMooreNeighbouringNodeIndices.clear();
00137 }
00138 
00139 template<unsigned DIM>
00140 unsigned PottsMesh<DIM>::GetNumNodes() const
00141 {
00142     return this->mNodes.size();
00143 }
00144 
00145 template<unsigned DIM>
00146 unsigned PottsMesh<DIM>::GetNumElements() const
00147 {
00148     return mElements.size() - mDeletedElementIndices.size();
00149 }
00150 
00151 template<unsigned DIM>
00152 unsigned PottsMesh<DIM>::GetNumAllElements() const
00153 {
00154     return mElements.size();
00155 }
00156 
00157 template<unsigned DIM>
00158 PottsElement<DIM>* PottsMesh<DIM>::GetElement(unsigned index) const
00159 {
00160     assert(index < mElements.size());
00161     return mElements[index];
00162 }
00163 
00164 template<unsigned DIM>
00165 c_vector<double, DIM> PottsMesh<DIM>::GetCentroidOfElement(unsigned index)
00166 {
00167     PottsElement<DIM>* p_element = GetElement(index);
00168     unsigned num_nodes_in_element = p_element->GetNumNodes();
00169 
00171     c_vector<double, DIM> centroid = zero_vector<double>(DIM);
00172 
00173     for (unsigned local_index=0; local_index<num_nodes_in_element; local_index++)
00174     {
00175         // Find location of current node and add it to the centroid
00176         centroid += p_element->GetNodeLocation(local_index);
00177     }
00178 
00179     centroid /= num_nodes_in_element;
00180 
00181     return centroid;
00182 }
00183 
00184 template<unsigned DIM>
00185 c_vector<double, DIM> PottsMesh<DIM>::GetVectorFromAtoB(const c_vector<double, DIM>& rLocationA, const c_vector<double, DIM>& rLocationB)
00186 {
00187     c_vector<double, DIM> vector = AbstractMesh<DIM, DIM>::GetVectorFromAtoB(rLocationA, rLocationB);
00188 
00189     return vector;
00190 }
00191 
00192 template<unsigned DIM>
00193 double PottsMesh<DIM>::GetVolumeOfElement(unsigned index)
00194 {
00195     PottsElement<DIM>* p_element = GetElement(index);
00196     double element_volume = (double) p_element->GetNumNodes();
00197 
00198     return element_volume;
00199 }
00200 
00201 template<unsigned DIM>
00202 double PottsMesh<DIM>::GetSurfaceAreaOfElement(unsigned index)
00203 {
00205     assert(DIM==2 || DIM==3);
00206 
00207     // Get pointer to this element
00208     PottsElement<DIM>* p_element = GetElement(index);
00209 
00210     double surface_area = 0.0;
00211     for (unsigned node_index=0; node_index< p_element->GetNumNodes(); node_index++)
00212     {
00213         std::set<unsigned> neighbouring_node_indices = GetVonNeumannNeighbouringNodeIndices(p_element->GetNode(node_index)->GetIndex());
00214         unsigned local_edges = 2*DIM;
00215         for (std::set<unsigned>::iterator iter = neighbouring_node_indices.begin();
00216              iter != neighbouring_node_indices.end();
00217              iter++)
00218         {
00219             std::set<unsigned> neighbouring_node_element_indices = this->mNodes[*iter]->rGetContainingElementIndices();
00220 
00221             if (neighbouring_node_element_indices.size()>0 && local_edges>0)
00222             {
00223                 unsigned neighbouring_node_element_index = *(neighbouring_node_element_indices.begin());
00224                 if (neighbouring_node_element_index == index)
00225                 {
00226                     local_edges--;
00227                 }
00228             }
00229         }
00230         surface_area += local_edges;
00231     }
00232     return surface_area;
00233 }
00234 
00235 template<unsigned DIM>
00236 std::set<unsigned> PottsMesh<DIM>::GetMooreNeighbouringNodeIndices(unsigned nodeIndex)
00237 {
00238     return mMooreNeighbouringNodeIndices[nodeIndex];
00239 }
00240 
00241 template<unsigned DIM>
00242 std::set<unsigned> PottsMesh<DIM>::GetVonNeumannNeighbouringNodeIndices(unsigned nodeIndex)
00243 {
00244     return mVonNeumannNeighbouringNodeIndices[nodeIndex];
00245 }
00246 
00247 template<unsigned DIM>
00248 void PottsMesh<DIM>::DeleteElement(unsigned index)
00249 {
00250     // Mark this element as deleted; this also updates the nodes containing element indices
00251     this->mElements[index]->MarkAsDeleted();
00252     mDeletedElementIndices.push_back(index);
00253 }
00254 
00255 template<unsigned DIM>
00256 unsigned PottsMesh<DIM>::DivideElement(PottsElement<DIM>* pElement,
00257                                   bool placeOriginalElementBelow)
00258 {
00260     assert(DIM==2);
00261 
00262     // Store the number of nodes in the element (this changes when nodes are deleted from the element)
00263     unsigned num_nodes = pElement->GetNumNodes();
00264 
00265     if (num_nodes < 2)
00266     {
00267         EXCEPTION("Tried to divide a Potts element with only one node. Cell dividing too often given dynamic parameters.");
00268     }
00269 
00270     // Copy the nodes in this element
00271     std::vector<Node<DIM>*> nodes_elem;
00272     for (unsigned i=0; i<num_nodes; i++)
00273     {
00274         nodes_elem.push_back(pElement->GetNode(i));
00275     }
00276 
00277     // Get the index of the new element
00278     unsigned new_element_index;
00279     if (mDeletedElementIndices.empty())
00280     {
00281         new_element_index = this->mElements.size();
00282     }
00283     else
00284     {
00285         new_element_index = mDeletedElementIndices.back();
00286         mDeletedElementIndices.pop_back();
00287         delete this->mElements[new_element_index];
00288     }
00289 
00290     // Add the new element to the mesh
00291     AddElement(new PottsElement<DIM>(new_element_index, nodes_elem));
00292 
00298     unsigned half_num_nodes = num_nodes/2; // This will round down
00299     assert(half_num_nodes > 0);
00300     assert(half_num_nodes < num_nodes);
00301 
00302     // Find lowest element
00304     double height_midpoint_1 = 0.0;
00305     double height_midpoint_2 = 0.0;
00306     unsigned counter_1 = 0;
00307     unsigned counter_2 = 0;
00308 
00309     for (unsigned i=0; i<num_nodes; i++)
00310     {
00311         if (i<half_num_nodes)
00312         {
00313             height_midpoint_1 += pElement->GetNode(i)->rGetLocation()[1];
00314             counter_1++;
00315         }
00316         else
00317         {
00318             height_midpoint_2 += pElement->GetNode(i)->rGetLocation()[1];
00319             counter_2++;
00320         }
00321     }
00322     height_midpoint_1 /= (double)counter_1;
00323     height_midpoint_2 /= (double)counter_2;
00324 
00325     for (unsigned i=num_nodes; i>0; i--)
00326     {
00327         if (i-1 >= half_num_nodes)
00328         {
00329             if (height_midpoint_1 < height_midpoint_2)
00330             {
00331                 if (placeOriginalElementBelow)
00332                 {
00333                     pElement->DeleteNode(i-1);
00334                 }
00335                 else
00336                 {
00337                     this->mElements[new_element_index]->DeleteNode(i-1);
00338                 }
00339             }
00340             else
00341             {
00342                 if (placeOriginalElementBelow)
00343                 {
00344                     this->mElements[new_element_index]->DeleteNode(i-1);
00345                 }
00346                 else
00347                 {
00348                     pElement->DeleteNode(i-1);
00349                 }
00350             }
00351         }
00352         else // i-1 < half_num_nodes
00353         {
00354             if (height_midpoint_1 < height_midpoint_2)
00355             {
00356                 if (placeOriginalElementBelow)
00357                 {
00358                     this->mElements[new_element_index]->DeleteNode(i-1);
00359                 }
00360                 else
00361                 {
00362                     pElement->DeleteNode(i-1);
00363                 }
00364             }
00365             else
00366             {
00367                 if (placeOriginalElementBelow)
00368                 {
00369                     pElement->DeleteNode(i-1);
00370                 }
00371                 else
00372                 {
00373                     this->mElements[new_element_index]->DeleteNode(i-1);
00374                 }
00375             }
00376         }
00377     }
00378 
00379     return new_element_index;
00380 }
00381 
00382 template<unsigned DIM>
00383 unsigned PottsMesh<DIM>::AddElement(PottsElement<DIM>* pNewElement)
00384 {
00385     unsigned new_element_index = pNewElement->GetIndex();
00386 
00387     if (new_element_index == this->mElements.size())
00388     {
00389         this->mElements.push_back(pNewElement);
00390     }
00391     else
00392     {
00393         this->mElements[new_element_index] = pNewElement;
00394     }
00395     pNewElement->RegisterWithNodes();
00396     return pNewElement->GetIndex();
00397 }
00398 
00399 template<unsigned DIM>
00400 void PottsMesh<DIM>::ConstructFromMeshReader(AbstractMeshReader<DIM, DIM>& rMeshReader)
00401 {
00402     // Store numbers of nodes and elements
00403     unsigned num_nodes = rMeshReader.GetNumNodes();
00404     unsigned num_elements = rMeshReader.GetNumElements();
00405 
00406     // Reserve memory for nodes
00407     this->mNodes.reserve(num_nodes);
00408 
00409     rMeshReader.Reset();
00410 
00411     // Add nodes
00412     std::vector<double> node_data;
00413     for (unsigned i=0; i<num_nodes; i++)
00414     {
00415         node_data = rMeshReader.GetNextNode();
00416         unsigned is_boundary_node = (unsigned) node_data[DIM];
00417         node_data.pop_back();
00418         this->mNodes.push_back(new Node<DIM>(i, node_data, is_boundary_node));
00419     }
00420 
00421     rMeshReader.Reset();
00422 
00423     // Reserve memory for nodes
00424     mElements.reserve(rMeshReader.GetNumElements());
00425 
00426     // Add elements
00427     for (unsigned elem_index=0; elem_index<num_elements; elem_index++)
00428     {
00429         // Get the data for this element
00430         ElementData element_data = rMeshReader.GetNextElementData();
00431 
00432         // Get the nodes owned by this element
00433         std::vector<Node<DIM>*> nodes;
00434         unsigned num_nodes_in_element = element_data.NodeIndices.size();
00435         for (unsigned j=0; j<num_nodes_in_element; j++)
00436         {
00437             assert(element_data.NodeIndices[j] < this->mNodes.size());
00438             nodes.push_back(this->mNodes[element_data.NodeIndices[j]]);
00439         }
00440 
00441         // Use nodes and index to construct this element
00442         PottsElement<DIM>* p_element = new PottsElement<DIM>(elem_index, nodes);
00443         mElements.push_back(p_element);
00444 
00445         if (rMeshReader.GetNumElementAttributes() > 0)
00446         {
00447             assert(rMeshReader.GetNumElementAttributes() == 1);
00448             unsigned attribute_value = element_data.AttributeValue;
00449             p_element->SetRegion(attribute_value);
00450         }
00451     }
00452 
00453     // If just using mesh reader then there is no neighbour information see #1932
00454     if (mVonNeumannNeighbouringNodeIndices.size()==0)
00455     {
00456         mVonNeumannNeighbouringNodeIndices.resize(num_nodes);
00457     }
00458     if (mMooreNeighbouringNodeIndices.size()==0)
00459     {
00460         mMooreNeighbouringNodeIndices.resize(num_nodes);
00461     }
00462 }
00463 
00465 // Explicit instantiation
00467 
00468 template class PottsMesh<1>;
00469 template class PottsMesh<2>;
00470 template class PottsMesh<3>;
00471 
00472 // Serialization for Boost >= 1.36
00473 #include "SerializationExportWrapperForCpp.hpp"
00474 EXPORT_TEMPLATE_CLASS_SAME_DIMS(PottsMesh)
Generated on Thu Dec 22 13:00:04 2011 for Chaste by  doxygen 1.6.3