PottsMesh.cpp

00001 /*
00002 
00003 Copyright (c) 2005-2015, University of Oxford.
00004 All rights reserved.
00005 
00006 University of Oxford means the Chancellor, Masters and Scholars of the
00007 University of Oxford, having an administrative office at Wellington
00008 Square, Oxford OX1 2JD, UK.
00009 
00010 This file is part of Chaste.
00011 
00012 Redistribution and use in source and binary forms, with or without
00013 modification, are permitted provided that the following conditions are met:
00014  * Redistributions of source code must retain the above copyright notice,
00015    this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright notice,
00017    this list of conditions and the following disclaimer in the documentation
00018    and/or other materials provided with the distribution.
00019  * Neither the name of the University of Oxford nor the names of its
00020    contributors may be used to endorse or promote products derived from this
00021    software without specific prior written permission.
00022 
00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 
00034 */
00035 
00036 #include "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 double PottsMesh<DIM>::GetVolumeOfElement(unsigned index)
00192 {
00193     PottsElement<DIM>* p_element = GetElement(index);
00194     double element_volume = (double) p_element->GetNumNodes();
00195 
00196     return element_volume;
00197 }
00198 
00199 template<unsigned DIM>
00200 double PottsMesh<DIM>::GetSurfaceAreaOfElement(unsigned index)
00201 {
00203     assert(DIM==2 || DIM==3);
00204 
00205     // Get pointer to this element
00206     PottsElement<DIM>* p_element = GetElement(index);
00207 
00208     double surface_area = 0.0;
00209     for (unsigned node_index=0; node_index< p_element->GetNumNodes(); node_index++)
00210     {
00211         std::set<unsigned> neighbouring_node_indices = GetVonNeumannNeighbouringNodeIndices(p_element->GetNode(node_index)->GetIndex());
00212         unsigned local_edges = 2*DIM;
00213         for (std::set<unsigned>::iterator iter = neighbouring_node_indices.begin();
00214              iter != neighbouring_node_indices.end();
00215              iter++)
00216         {
00217             std::set<unsigned> neighbouring_node_element_indices = this->mNodes[*iter]->rGetContainingElementIndices();
00218 
00219             if (neighbouring_node_element_indices.size()>0 && local_edges>0)
00220             {
00221                 unsigned neighbouring_node_element_index = *(neighbouring_node_element_indices.begin());
00222                 if (neighbouring_node_element_index == index)
00223                 {
00224                     local_edges--;
00225                 }
00226             }
00227         }
00228         surface_area += local_edges;
00229     }
00230     return surface_area;
00231 }
00232 
00233 template<unsigned DIM>
00234 std::set<unsigned> PottsMesh<DIM>::GetMooreNeighbouringNodeIndices(unsigned nodeIndex)
00235 {
00236     return mMooreNeighbouringNodeIndices[nodeIndex];
00237 }
00238 
00239 template<unsigned DIM>
00240 std::set<unsigned> PottsMesh<DIM>::GetVonNeumannNeighbouringNodeIndices(unsigned nodeIndex)
00241 {
00242     return mVonNeumannNeighbouringNodeIndices[nodeIndex];
00243 }
00244 
00245 template<unsigned DIM>
00246 void PottsMesh<DIM>::DeleteElement(unsigned index)
00247 {
00248     // Mark this element as deleted; this also updates the nodes containing element indices
00249     this->mElements[index]->MarkAsDeleted();
00250     mDeletedElementIndices.push_back(index);
00251 }
00252 
00253 template<unsigned DIM>
00254 void PottsMesh<DIM>::DeleteNode(unsigned index)
00255 {
00256     //Mark node as deleted so we don't consider it when iterating over nodes
00257     this->mNodes[index]->MarkAsDeleted();
00258 
00259     //Remove from Elements
00260     std::set<unsigned> containing_element_indices = this->mNodes[index]->rGetContainingElementIndices();
00261 
00262     for (std::set<unsigned>::iterator iter = containing_element_indices.begin();
00263          iter != containing_element_indices.end();
00264          iter++)
00265     {
00266         assert(mElements[*iter]->GetNumNodes() > 0);
00267         if (mElements[*iter]->GetNumNodes() == 1)
00268         {
00269             DeleteElement(*iter);
00270         }
00271         else
00272         {
00273             this->mElements[*iter]->DeleteNode(this->mElements[*iter]->GetNodeLocalIndex(index));
00274         }
00275     }
00276 
00277     // Remove from connectivity
00278     mVonNeumannNeighbouringNodeIndices[index].clear();
00279     mMooreNeighbouringNodeIndices[index].clear();
00280 
00281     assert(mVonNeumannNeighbouringNodeIndices.size()==mMooreNeighbouringNodeIndices.size());
00282     for (unsigned node_index = 0;
00283          node_index < mVonNeumannNeighbouringNodeIndices.size();
00284          node_index++)
00285     {
00286         // Remove node "index" from the Von Neuman neighbourhood of node "node_index".
00287         mVonNeumannNeighbouringNodeIndices[node_index].erase(index);
00288         mMooreNeighbouringNodeIndices[node_index].erase(index);
00289 
00290         // Check there's still connectivity for the other non-deleted nodes
00291         if (!this->mNodes[node_index]->IsDeleted())
00292         {
00293             assert(!mVonNeumannNeighbouringNodeIndices[node_index].empty());
00294             assert(!mMooreNeighbouringNodeIndices[node_index].empty());
00295         }
00296     }
00297 
00298 
00299     // Remove node from mNodes and renumber all the elements and nodes
00300     delete this->mNodes[index];
00301     this->mNodes.erase(this->mNodes.begin()+index);
00302     unsigned num_nodes = GetNumNodes();
00303     mVonNeumannNeighbouringNodeIndices.erase(mVonNeumannNeighbouringNodeIndices.begin()+index);
00304     mMooreNeighbouringNodeIndices.erase(mMooreNeighbouringNodeIndices.begin()+index);
00305 
00306     assert(mVonNeumannNeighbouringNodeIndices.size()==num_nodes);
00307     assert(mMooreNeighbouringNodeIndices.size()==num_nodes);
00308 
00309     for (unsigned node_index = 0; node_index < num_nodes; node_index++)
00310     {
00311         // Reduce the index of all nodes greater than  node "index"
00312         if (node_index >= index)
00313         {
00314             assert(this->mNodes[node_index]->GetIndex() == node_index+1);
00315             this->mNodes[node_index]->SetIndex(node_index);
00316         }
00317         assert(this->mNodes[node_index]->GetIndex() == node_index);
00318 
00319         // Reduce the index of all nodes greater than  node "index"
00320         // in the Moore and Von Neuman neighbourhoods.
00321         std::set<unsigned> von_neuman = mVonNeumannNeighbouringNodeIndices[node_index];
00322         mVonNeumannNeighbouringNodeIndices[node_index].clear();
00323         for (std::set<unsigned>::iterator iter = von_neuman.begin();
00324              iter != von_neuman.end();
00325              iter++)
00326         {
00327             if (*iter >= index)
00328             {
00329                 mVonNeumannNeighbouringNodeIndices[node_index].insert(*iter-1);
00330             }
00331             else
00332             {
00333                 mVonNeumannNeighbouringNodeIndices[node_index].insert(*iter);
00334             }
00335         }
00336         std::set<unsigned> moore = mMooreNeighbouringNodeIndices[node_index];
00337         mMooreNeighbouringNodeIndices[node_index].clear();
00338         for (std::set<unsigned>::iterator iter = moore.begin();
00339              iter != moore.end();
00340              iter++)
00341         {
00342             if (*iter >= index)
00343             {
00344                 mMooreNeighbouringNodeIndices[node_index].insert(*iter-1);
00345             }
00346             else
00347             {
00348                 mMooreNeighbouringNodeIndices[node_index].insert(*iter);
00349             }
00350         }
00351     }
00352     // Finally remove any elememts that have been removed
00353     assert(mDeletedElementIndices.size() <= 1); // Should have at most one element to remove
00354     if (mDeletedElementIndices.size() == 1)
00355     {
00356         unsigned deleted_elem_index = mDeletedElementIndices[0];
00357         delete mElements[deleted_elem_index];
00358         mElements.erase(mElements.begin()+deleted_elem_index);
00359         mDeletedElementIndices.clear();
00360 
00361         for (unsigned elem_index=deleted_elem_index; elem_index<GetNumElements(); elem_index++)
00362         {
00363             mElements[elem_index]->ResetIndex(elem_index);
00364         }
00365     }
00366 }
00367 
00368 template<unsigned DIM>
00369 unsigned PottsMesh<DIM>::DivideElement(PottsElement<DIM>* pElement,
00370                                        bool placeOriginalElementBelow)
00371 {
00373     assert(DIM==2 || DIM==3);
00374 
00375     // Store the number of nodes in the element (this changes when nodes are deleted from the element)
00376     unsigned num_nodes = pElement->GetNumNodes();
00377 
00378     if (num_nodes < 2)
00379     {
00380         EXCEPTION("Tried to divide a Potts element with only one node. Cell dividing too often given dynamic parameters.");
00381     }
00382 
00383     // Copy the nodes in this element
00384     std::vector<Node<DIM>*> nodes_elem;
00385     for (unsigned i=0; i<num_nodes; i++)
00386     {
00387         nodes_elem.push_back(pElement->GetNode(i));
00388     }
00389 
00390     // Get the index of the new element
00391     unsigned new_element_index;
00392     if (mDeletedElementIndices.empty())
00393     {
00394         new_element_index = this->mElements.size();
00395     }
00396     else
00397     {
00398         new_element_index = mDeletedElementIndices.back();
00399         mDeletedElementIndices.pop_back();
00400         delete this->mElements[new_element_index];
00401     }
00402 
00403     // Add the new element to the mesh
00404     AddElement(new PottsElement<DIM>(new_element_index, nodes_elem));
00405 
00411     unsigned half_num_nodes = num_nodes/2; // This will round down
00412     assert(half_num_nodes > 0);
00413     assert(half_num_nodes < num_nodes);
00414 
00415     // Find lowest element
00417     double height_midpoint_1 = 0.0;
00418     double height_midpoint_2 = 0.0;
00419     unsigned counter_1 = 0;
00420     unsigned counter_2 = 0;
00421 
00422     for (unsigned i=0; i<num_nodes; i++)
00423     {
00424         if (i<half_num_nodes)
00425         {
00426             height_midpoint_1 += pElement->GetNode(i)->rGetLocation()[DIM - 1];
00427             counter_1++;
00428         }
00429         else
00430         {
00431             height_midpoint_2 += pElement->GetNode(i)->rGetLocation()[DIM -1];
00432             counter_2++;
00433         }
00434     }
00435     height_midpoint_1 /= (double)counter_1;
00436     height_midpoint_2 /= (double)counter_2;
00437 
00438     for (unsigned i=num_nodes; i>0; i--)
00439     {
00440         if (i-1 >= half_num_nodes)
00441         {
00442             if (height_midpoint_1 < height_midpoint_2)
00443             {
00444                 if (placeOriginalElementBelow)
00445                 {
00446                     pElement->DeleteNode(i-1);
00447                 }
00448                 else
00449                 {
00450                     this->mElements[new_element_index]->DeleteNode(i-1);
00451                 }
00452             }
00453             else
00454             {
00455                 if (placeOriginalElementBelow)
00456                 {
00457                     this->mElements[new_element_index]->DeleteNode(i-1);
00458                 }
00459                 else
00460                 {
00461                     pElement->DeleteNode(i-1);
00462                 }
00463             }
00464         }
00465         else // i-1 < half_num_nodes
00466         {
00467             if (height_midpoint_1 < height_midpoint_2)
00468             {
00469                 if (placeOriginalElementBelow)
00470                 {
00471                     this->mElements[new_element_index]->DeleteNode(i-1);
00472                 }
00473                 else
00474                 {
00475                     pElement->DeleteNode(i-1);
00476                 }
00477             }
00478             else
00479             {
00480                 if (placeOriginalElementBelow)
00481                 {
00482                     pElement->DeleteNode(i-1);
00483                 }
00484                 else
00485                 {
00486                     this->mElements[new_element_index]->DeleteNode(i-1);
00487                 }
00488             }
00489         }
00490     }
00491 
00492     return new_element_index;
00493 }
00494 
00495 template<unsigned DIM>
00496 unsigned PottsMesh<DIM>::AddElement(PottsElement<DIM>* pNewElement)
00497 {
00498     unsigned new_element_index = pNewElement->GetIndex();
00499 
00500     if (new_element_index == this->mElements.size())
00501     {
00502         this->mElements.push_back(pNewElement);
00503     }
00504     else
00505     {
00506         this->mElements[new_element_index] = pNewElement;
00507     }
00508     pNewElement->RegisterWithNodes();
00509     return pNewElement->GetIndex();
00510 }
00511 
00512 template<unsigned DIM>
00513 std::set<unsigned> PottsMesh<DIM>::GetNeighbouringElementIndices(unsigned elementIndex)
00514 {
00515     // Get a pointer to this element
00516     PottsElement<DIM>* p_element = this->GetElement(elementIndex);
00517 
00518     // Create a set of neighbouring element indices
00519     std::set<unsigned> neighbouring_element_indices;
00520 
00521     // Loop over nodes owned by this element
00522     for (unsigned local_index=0; local_index<p_element->GetNumNodes(); local_index++)
00523     {
00524         // Get a pointer to this node
00525         Node<DIM>* p_node = p_element->GetNode(local_index);
00526 
00527         // Find the indices of the elements owned by neighbours of this node
00528 
00529         // Loop over neighbouring nodes. Only want Von Neuman neighbours  (i.e N,S,E,W) as need to share an edge
00530         std::set<unsigned> neighbouring_node_indices = GetVonNeumannNeighbouringNodeIndices(p_node->GetIndex());
00531 
00532          // Iterate over these neighbouring nodes
00533          for (std::set<unsigned>::iterator neighbour_iter = neighbouring_node_indices.begin();
00534                neighbour_iter != neighbouring_node_indices.end();
00535                ++neighbour_iter)
00536          {
00537              std::set<unsigned> neighbouring_node_containing_elem_indices = this->GetNode(*neighbour_iter)->rGetContainingElementIndices();
00538 
00539              assert(neighbouring_node_containing_elem_indices.size()<2); // Either in element or in medium
00540 
00541              if (neighbouring_node_containing_elem_indices.size()==1) // Node is in an element
00542              {
00543                  // Add this element to the neighbouring elements set
00544                  neighbouring_element_indices.insert(*(neighbouring_node_containing_elem_indices.begin()));
00545              }
00546          }
00547     }
00548 
00549     // Lastly remove this element's index from the set of neighbouring element indices
00550     neighbouring_element_indices.erase(elementIndex);
00551 
00552     return neighbouring_element_indices;
00553 }
00554 
00555 template<unsigned DIM>
00556 void PottsMesh<DIM>::ConstructFromMeshReader(AbstractMeshReader<DIM, DIM>& rMeshReader)
00557 {
00558     assert(rMeshReader.HasNodePermutation() == false);
00559 
00560     // Store numbers of nodes and elements
00561     unsigned num_nodes = rMeshReader.GetNumNodes();
00562     unsigned num_elements = rMeshReader.GetNumElements();
00563 
00564     // Reserve memory for nodes
00565     this->mNodes.reserve(num_nodes);
00566 
00567     rMeshReader.Reset();
00568 
00569     // Add nodes
00570     std::vector<double> node_data;
00571     for (unsigned i=0; i<num_nodes; i++)
00572     {
00573         node_data = rMeshReader.GetNextNode();
00574         unsigned is_boundary_node = (bool) node_data[DIM];
00575         node_data.pop_back();
00576         this->mNodes.push_back(new Node<DIM>(i, node_data, is_boundary_node));
00577     }
00578 
00579     rMeshReader.Reset();
00580 
00581     // Reserve memory for nodes
00582     mElements.reserve(rMeshReader.GetNumElements());
00583 
00584     // Add elements
00585     for (unsigned elem_index=0; elem_index<num_elements; elem_index++)
00586     {
00587         // Get the data for this element
00588         ElementData element_data = rMeshReader.GetNextElementData();
00589 
00590         // Get the nodes owned by this element
00591         std::vector<Node<DIM>*> nodes;
00592         unsigned num_nodes_in_element = element_data.NodeIndices.size();
00593         for (unsigned j=0; j<num_nodes_in_element; j++)
00594         {
00595             assert(element_data.NodeIndices[j] < this->mNodes.size());
00596             nodes.push_back(this->mNodes[element_data.NodeIndices[j]]);
00597         }
00598 
00599         // Use nodes and index to construct this element
00600         PottsElement<DIM>* p_element = new PottsElement<DIM>(elem_index, nodes);
00601         mElements.push_back(p_element);
00602 
00603         if (rMeshReader.GetNumElementAttributes() > 0)
00604         {
00605             assert(rMeshReader.GetNumElementAttributes() == 1);
00606             double attribute_value = element_data.AttributeValue;
00607             p_element->SetAttribute(attribute_value);
00608         }
00609     }
00610 
00611     // If we are just using a mesh reader, then there is no neighbour information (see #1932)
00612     if (mVonNeumannNeighbouringNodeIndices.empty())
00613     {
00614         mVonNeumannNeighbouringNodeIndices.resize(num_nodes);
00615     }
00616     if (mMooreNeighbouringNodeIndices.empty())
00617     {
00618         mMooreNeighbouringNodeIndices.resize(num_nodes);
00619     }
00620 }
00621 
00622 // Explicit instantiation
00623 template class PottsMesh<1>;
00624 template class PottsMesh<2>;
00625 template class PottsMesh<3>;
00626 
00627 // Serialization for Boost >= 1.36
00628 #include "SerializationExportWrapperForCpp.hpp"
00629 EXPORT_TEMPLATE_CLASS_SAME_DIMS(PottsMesh)

Generated by  doxygen 1.6.2