Chaste Release::3.1
PottsMesh.hpp
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 #ifndef POTTSMESH_HPP_
00037 #define POTTSMESH_HPP_
00038 
00039 // Forward declaration prevents circular include chain
00040 template<unsigned DIM>
00041 class PottsMeshWriter;
00042 
00043 #include <iostream>
00044 #include <map>
00045 #include <algorithm>
00046 
00047 #include "ChasteSerialization.hpp"
00048 #include <boost/serialization/vector.hpp>
00049 #include <boost/serialization/set.hpp>
00050 #include <boost/serialization/base_object.hpp>
00051 #include <boost/serialization/split_member.hpp>
00052 
00053 #include "AbstractMesh.hpp"
00054 #include "ArchiveLocationInfo.hpp"
00055 #include "PottsMeshReader.hpp"
00056 #include "PottsMeshWriter.hpp"
00057 #include "PottsElement.hpp"
00058 
00062 template<unsigned DIM>
00063 class PottsMesh : public AbstractMesh<DIM, DIM>
00064 {
00065     friend class TestPottsMesh;
00066 
00067 protected:
00069     std::vector<PottsElement<DIM>*> mElements;
00070 
00075     std::vector<unsigned> mDeletedElementIndices;
00076 
00078     std::vector< std::set<unsigned> > mVonNeumannNeighbouringNodeIndices;
00079 
00081     std::vector< std::set<unsigned> > mMooreNeighbouringNodeIndices;
00082 
00089     unsigned SolveNodeMapping(unsigned index) const;
00090 
00097     unsigned SolveElementMapping(unsigned index) const;
00098 
00105     unsigned SolveBoundaryElementMapping(unsigned index) const;
00106 
00108     friend class boost::serialization::access;
00109 
00117     template<class Archive>
00118     void save(Archive & archive, const unsigned int version) const
00119     {
00120         // NOTE - Subclasses must archive their member variables BEFORE calling this method.
00121         archive & mDeletedElementIndices;
00122         archive & mVonNeumannNeighbouringNodeIndices;
00123         archive & mMooreNeighbouringNodeIndices;
00124         archive & boost::serialization::base_object<AbstractMesh<DIM, DIM> >(*this);
00125 
00126         // Create a mesh writer pointing to the correct file and directory
00127         PottsMeshWriter<DIM> mesh_writer(ArchiveLocationInfo::GetArchiveRelativePath(),
00128                                          ArchiveLocationInfo::GetMeshFilename(),
00129                                          false);
00130         mesh_writer.WriteFilesUsingMesh(*(const_cast<PottsMesh<DIM>*>(this)));
00131     }
00132 
00139     template<class Archive>
00140     void load(Archive & archive, const unsigned int version)
00141     {
00142         // NOTE - Subclasses must archive their member variables BEFORE calling this method.
00143         archive & mDeletedElementIndices;
00144         archive & mVonNeumannNeighbouringNodeIndices;
00145         archive & mMooreNeighbouringNodeIndices;
00146         archive & boost::serialization::base_object<AbstractMesh<DIM, DIM> >(*this);
00147 
00148         PottsMeshReader<DIM> mesh_reader(ArchiveLocationInfo::GetArchiveDirectory() + ArchiveLocationInfo::GetMeshFilename());
00149         this->ConstructFromMeshReader(mesh_reader);
00150     }
00151     BOOST_SERIALIZATION_SPLIT_MEMBER()
00152 
00153 public:
00154 
00156     //                            Iterators                             //
00158 
00160     class PottsElementIterator;
00161 
00167     inline PottsElementIterator GetElementIteratorBegin(bool skipDeletedElements=true);
00168 
00172     inline PottsElementIterator GetElementIteratorEnd();
00173 
00175     //                             Methods                              //
00177 
00186     PottsMesh(std::vector<Node<DIM>*> nodes,
00187               std::vector<PottsElement<DIM>*> pottsElements,
00188               std::vector< std::set<unsigned> > vonNeumannNeighbouringNodeIndices,
00189               std::vector< std::set<unsigned> > mooreNeighbouringNodeIndices);
00190 
00191 
00195     PottsMesh();
00196 
00200     virtual ~PottsMesh();
00201 
00205     virtual unsigned GetNumNodes() const;
00206 
00210     virtual unsigned GetNumElements() const;
00211 
00215     unsigned GetNumAllElements() const;
00216 
00222     PottsElement<DIM>* GetElement(unsigned index) const;
00223 
00233     virtual c_vector<double, DIM> GetCentroidOfElement(unsigned index);
00234 
00240     void ConstructFromMeshReader(AbstractMeshReader<DIM, DIM>& rMeshReader);
00241 
00245     virtual void Clear();
00246 
00258     virtual c_vector<double, DIM> GetVectorFromAtoB(const c_vector<double, DIM>& rLocationA,
00259                                                     const c_vector<double, DIM>& rLocationB);
00260 
00270     virtual double GetVolumeOfElement(unsigned index);
00271 
00281     virtual double GetSurfaceAreaOfElement(unsigned index);
00282 
00289     std::set<unsigned> GetMooreNeighbouringNodeIndices(unsigned nodeIndex);
00290 
00297     std::set<unsigned> GetVonNeumannNeighbouringNodeIndices(unsigned nodeIndex);
00298 
00305     void DeleteElement(unsigned index);
00306 
00317     unsigned DivideElement(PottsElement<DIM>* pElement,
00318                            bool placeOriginalElementBelow=false);
00319 
00327     unsigned AddElement(PottsElement<DIM>* pNewElement);
00328 
00330     //                         Nested classes                           //
00332 
00338     class PottsElementIterator
00339     {
00340     public:
00346         inline PottsElement<DIM>& operator*();
00347 
00351         inline PottsElement<DIM>* operator->();
00352 
00358         inline bool operator!=(const PottsMesh<DIM>::PottsElementIterator& rOther);
00359 
00363         inline PottsElementIterator& operator++();
00364 
00375         PottsElementIterator(PottsMesh<DIM>& rMesh,
00376                              typename std::vector<PottsElement<DIM> *>::iterator elementIter,
00377                              bool skipDeletedElements=true);
00378 
00379     private:
00381         PottsMesh<DIM>& mrMesh;
00382 
00384         typename std::vector<PottsElement<DIM> *>::iterator mElementIter;
00385 
00387         bool mSkipDeletedElements;
00388 
00392         inline bool IsAtEnd();
00393 
00397         inline bool IsAllowedElement();
00398     };
00399 };
00400 
00401 #include "SerializationExportWrapper.hpp"
00402 EXPORT_TEMPLATE_CLASS_SAME_DIMS(PottsMesh)
00403 
00404 
00405 // PottsElementIterator class implementation - most methods are inlined     //
00407 
00408 template<unsigned DIM>
00409 typename PottsMesh<DIM>::PottsElementIterator PottsMesh<DIM>::GetElementIteratorBegin(
00410         bool skipDeletedElements)
00411 {
00412     return PottsElementIterator(*this, mElements.begin(), skipDeletedElements);
00413 }
00414 
00415 template<unsigned DIM>
00416 typename PottsMesh<DIM>::PottsElementIterator PottsMesh<DIM>::GetElementIteratorEnd()
00417 {
00418     return PottsElementIterator(*this, mElements.end());
00419 }
00420 template<unsigned DIM>
00421 PottsElement<DIM>& PottsMesh<DIM>::PottsElementIterator::operator*()
00422 {
00423     assert(!IsAtEnd());
00424     return **mElementIter;
00425 }
00426 
00427 template<unsigned DIM>
00428 PottsElement<DIM>* PottsMesh<DIM>::PottsElementIterator::operator->()
00429 {
00430     assert(!IsAtEnd());
00431     return *mElementIter;
00432 }
00433 
00434 template<unsigned DIM>
00435 bool PottsMesh<DIM>::PottsElementIterator::operator!=(const PottsMesh<DIM>::PottsElementIterator& rOther)
00436 {
00437     return mElementIter != rOther.mElementIter;
00438 }
00439 
00440 template<unsigned DIM>
00441 typename PottsMesh<DIM>::PottsElementIterator& PottsMesh<DIM>::PottsElementIterator::operator++()
00442 {
00443     do
00444     {
00445         ++mElementIter;
00446     }
00447     while (!IsAtEnd() && !IsAllowedElement());
00448 
00449     return (*this);
00450 }
00451 
00452 template<unsigned DIM>
00453 PottsMesh<DIM>::PottsElementIterator::PottsElementIterator(
00454         PottsMesh<DIM>& rMesh,
00455         typename std::vector<PottsElement<DIM>*>::iterator elementIter,
00456         bool skipDeletedElements)
00457     : mrMesh(rMesh),
00458       mElementIter(elementIter),
00459       mSkipDeletedElements(skipDeletedElements)
00460 {
00461     if (mrMesh.mElements.empty())
00462     {
00463         // Cope with empty meshes
00464         mElementIter = mrMesh.mElements.end();
00465     }
00466     else
00467     {
00468         // Make sure we start at an allowed element
00469         if (mElementIter == mrMesh.mElements.begin() && !IsAllowedElement())
00470         {
00471             ++(*this);
00472         }
00473     }
00474 }
00475 
00476 template<unsigned DIM>
00477 bool PottsMesh<DIM>::PottsElementIterator::IsAtEnd()
00478 {
00479     return mElementIter == mrMesh.mElements.end();
00480 }
00481 
00482 template<unsigned DIM>
00483 bool PottsMesh<DIM>::PottsElementIterator::IsAllowedElement()
00484 {
00485     return !(mSkipDeletedElements && (*this)->IsDeleted());
00486 }
00487 
00488 #endif /*POTTSMESH_HPP_*/