Chaste Release::3.1
VertexMesh.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 #ifndef VERTEXMESH_HPP_
00036 #define VERTEXMESH_HPP_
00037 
00038 // Forward declaration prevents circular include chain
00039 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00040 class VertexMeshWriter;
00041 
00042 #include <iostream>
00043 #include <map>
00044 #include <algorithm>
00045 
00046 #include "ChasteSerialization.hpp"
00047 #include <boost/serialization/vector.hpp>
00048 #include <boost/serialization/base_object.hpp>
00049 #include <boost/serialization/split_member.hpp>
00050 
00051 #include "AbstractMesh.hpp"
00052 #include "ArchiveLocationInfo.hpp"
00053 #include "VertexMeshReader.hpp"
00054 #include "VertexMeshWriter.hpp"
00055 #include "VertexElement.hpp"
00056 #include "VertexElementMap.hpp"
00057 #include "TetrahedralMesh.hpp"
00058 
00062 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00063 class VertexMesh : public AbstractMesh<ELEMENT_DIM, SPACE_DIM>
00064 {
00065     friend class TestVertexMesh;
00066 
00067 protected:
00068 
00070     std::vector<VertexElement<ELEMENT_DIM, SPACE_DIM>*> mElements;
00071 
00073     std::vector<VertexElement<ELEMENT_DIM-1, SPACE_DIM>*> mFaces;
00074 
00082     std::map<unsigned, unsigned> mVoronoiElementIndexMap;
00083 
00091     TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>* mpDelaunayMesh;
00092 
00099     unsigned SolveNodeMapping(unsigned index) const;
00100 
00107     unsigned SolveElementMapping(unsigned index) const;
00108 
00115     unsigned SolveBoundaryElementMapping(unsigned index) const;
00116 
00124     void GenerateVerticesFromElementCircumcentres(TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>& rMesh);
00125 
00127     //                        2D-specific methods                       //
00129 
00146     bool ElementIncludesPoint(const c_vector<double, SPACE_DIM>& rTestPoint, unsigned elementIndex);
00147 
00157     unsigned GetLocalIndexForElementEdgeClosestToPoint(const c_vector<double, SPACE_DIM>& rTestPoint, unsigned elementIndex);
00158 
00160     friend class boost::serialization::access;
00161 
00169     template<class Archive>
00170     void save(Archive & archive, const unsigned int version) const
00171     {
00172         archive & boost::serialization::base_object<AbstractMesh<ELEMENT_DIM,SPACE_DIM> >(*this);
00173 
00174         // Create a mesh writer pointing to the correct file and directory
00175         VertexMeshWriter<ELEMENT_DIM, SPACE_DIM> mesh_writer(ArchiveLocationInfo::GetArchiveRelativePath(),
00176                                                              ArchiveLocationInfo::GetMeshFilename(),
00177                                                              false);
00178         mesh_writer.WriteFilesUsingMesh(*(const_cast<VertexMesh<ELEMENT_DIM, SPACE_DIM>*>(this)));
00179     }
00180 
00187     template<class Archive>
00188     void load(Archive & archive, const unsigned int version)
00189     {
00190         archive & boost::serialization::base_object<AbstractMesh<ELEMENT_DIM,SPACE_DIM> >(*this);
00191 
00192         VertexMeshReader<ELEMENT_DIM,SPACE_DIM> mesh_reader(ArchiveLocationInfo::GetArchiveDirectory() + ArchiveLocationInfo::GetMeshFilename());
00193         this->ConstructFromMeshReader(mesh_reader);
00194     }
00195     BOOST_SERIALIZATION_SPLIT_MEMBER()
00196 
00197 public:
00198 
00200     //                            Iterators                             //
00202 
00204     class VertexElementIterator;
00205 
00211     inline VertexElementIterator GetElementIteratorBegin(bool skipDeletedElements=true);
00212 
00216     inline VertexElementIterator GetElementIteratorEnd();
00217 
00219     //                             Methods                              //
00221 
00228     VertexMesh(std::vector<Node<SPACE_DIM>*> nodes,
00229                std::vector<VertexElement<ELEMENT_DIM, SPACE_DIM>*> vertexElements);
00230 
00238     VertexMesh(std::vector<Node<SPACE_DIM>*> nodes,
00239                std::vector<VertexElement<ELEMENT_DIM-1,SPACE_DIM>*> faces,
00240                std::vector<VertexElement<ELEMENT_DIM,SPACE_DIM>*> vertexElements);
00241 
00251     VertexMesh(TetrahedralMesh<2,2>& rMesh, bool isPeriodic=false);
00252 
00261     VertexMesh(TetrahedralMesh<3,3>& rMesh);
00262 
00266     VertexMesh();
00267 
00271     virtual ~VertexMesh();
00272 
00276     virtual unsigned GetNumNodes() const;
00277 
00281     virtual unsigned GetNumElements() const;
00282 
00286     unsigned GetNumAllElements() const;
00287 
00291     virtual unsigned GetNumFaces() const;
00292 
00298     VertexElement<ELEMENT_DIM, SPACE_DIM>* GetElement(unsigned index) const;
00299 
00305     VertexElement<ELEMENT_DIM-1, SPACE_DIM>* GetFace(unsigned index) const;
00306 
00316     virtual c_vector<double, SPACE_DIM> GetCentroidOfElement(unsigned index);
00317 
00323     void ConstructFromMeshReader(AbstractMeshReader<ELEMENT_DIM,SPACE_DIM>& rMeshReader);
00324 
00328     virtual void Clear();
00329 
00336     unsigned GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(unsigned elementIndex);
00337 
00345     unsigned GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(unsigned nodeIndex);
00346 
00358     virtual c_vector<double, SPACE_DIM> GetVectorFromAtoB(const c_vector<double, SPACE_DIM>& rLocationA,
00359                                                           const c_vector<double, SPACE_DIM>& rLocationB);
00360 
00370     virtual double GetVolumeOfElement(unsigned index);
00371 
00381     virtual double GetSurfaceAreaOfElement(unsigned index);
00382 
00384     //                        2D-specific methods                       //
00386 
00398     c_vector<double, SPACE_DIM> GetAreaGradientOfElementAtNode(VertexElement<ELEMENT_DIM,SPACE_DIM>* pElement, unsigned localIndex);
00399 
00411     c_vector<double, SPACE_DIM> GetPreviousEdgeGradientOfElementAtNode(VertexElement<ELEMENT_DIM,SPACE_DIM>* pElement, unsigned localIndex);
00412 
00424     c_vector<double, SPACE_DIM> GetNextEdgeGradientOfElementAtNode(VertexElement<ELEMENT_DIM,SPACE_DIM>* pElement, unsigned localIndex);
00425 
00435     c_vector<double, SPACE_DIM> GetPerimeterGradientOfElementAtNode(VertexElement<ELEMENT_DIM,SPACE_DIM>* pElement, unsigned localIndex);
00436 
00444     virtual c_vector<double, 3> CalculateMomentsOfElement(unsigned index);
00445 
00452     double GetEdgeLength(unsigned elementIndex1, unsigned elementIndex2);
00453 
00455     //                        3D-specific methods                       //
00457 
00467     c_vector<double, SPACE_DIM> GetUnitNormalToFace(VertexElement<ELEMENT_DIM-1, SPACE_DIM>* pFace);
00468 
00480     virtual double GetAreaOfFace(VertexElement<ELEMENT_DIM-1, SPACE_DIM>* pFace);
00481 
00492     c_vector<double, SPACE_DIM> GetShortAxisOfElement(unsigned index);
00493 
00500     std::set<unsigned> GetNeighbouringNodeIndices(unsigned nodeIndex);
00501 
00514     std::set<unsigned> GetNeighbouringNodeNotAlsoInElement(unsigned nodeIndex, unsigned elemIndex);
00515 
00522     std::set<unsigned> GetNeighbouringElementIndices(unsigned elementIndex);
00523 
00525     //                         Nested classes                           //
00527 
00533     class VertexElementIterator
00534     {
00535     public:
00541         inline VertexElement<ELEMENT_DIM, SPACE_DIM>& operator*();
00542 
00546         inline VertexElement<ELEMENT_DIM, SPACE_DIM>* operator->();
00547 
00553         inline bool operator!=(const VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator& rOther);
00554 
00558         inline VertexElementIterator& operator++();
00559 
00570         VertexElementIterator(VertexMesh<ELEMENT_DIM, SPACE_DIM>& rMesh,
00571                         typename std::vector<VertexElement<ELEMENT_DIM, SPACE_DIM> *>::iterator elementIter,
00572                         bool skipDeletedElements=true);
00573 
00574     private:
00576         VertexMesh& mrMesh;
00577 
00579         typename std::vector<VertexElement<ELEMENT_DIM, SPACE_DIM> *>::iterator mElementIter;
00580 
00582         bool mSkipDeletedElements;
00583 
00587         inline bool IsAtEnd();
00588 
00592         inline bool IsAllowedElement();
00593     };
00594 };
00595 
00596 #include "SerializationExportWrapper.hpp"
00597 EXPORT_TEMPLATE_CLASS_ALL_DIMS(VertexMesh)
00598 
00599 
00600 
00601 // VertexElementIterator class implementation - most methods are inlined    //
00603 
00604 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00605 typename VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetElementIteratorBegin(
00606         bool skipDeletedElements)
00607 {
00608     return VertexElementIterator(*this, mElements.begin(), skipDeletedElements);
00609 }
00610 
00611 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00612 typename VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetElementIteratorEnd()
00613 {
00614     return VertexElementIterator(*this, mElements.end());
00615 }
00616 
00617 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00618 VertexElement<ELEMENT_DIM, SPACE_DIM>& VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator::operator*()
00619 {
00620     assert(!IsAtEnd());
00621     return **mElementIter;
00622 }
00623 
00624 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00625 VertexElement<ELEMENT_DIM, SPACE_DIM>* VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator::operator->()
00626 {
00627     assert(!IsAtEnd());
00628     return *mElementIter;
00629 }
00630 
00631 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00632 bool VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator::operator!=(const VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator& rOther)
00633 {
00634     return mElementIter != rOther.mElementIter;
00635 }
00636 
00637 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00638 typename VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator& VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator::operator++()
00639 {
00640     do
00641     {
00642         ++mElementIter;
00643     }
00644     while (!IsAtEnd() && !IsAllowedElement());
00645 
00646     return (*this);
00647 }
00648 
00649 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00650 VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator::VertexElementIterator(
00651         VertexMesh<ELEMENT_DIM, SPACE_DIM>& rMesh,
00652         typename std::vector<VertexElement<ELEMENT_DIM, SPACE_DIM> *>::iterator elementIter,
00653         bool skipDeletedElements)
00654     : mrMesh(rMesh),
00655       mElementIter(elementIter),
00656       mSkipDeletedElements(skipDeletedElements)
00657 {
00658     if (mrMesh.mElements.empty())
00659     {
00660         // Cope with empty meshes
00661         mElementIter = mrMesh.mElements.end();
00662     }
00663     else
00664     {
00665         // Make sure we start at an allowed element
00666         if (mElementIter == mrMesh.mElements.begin() && !IsAllowedElement())
00667         {
00668             ++(*this);
00669         }
00670     }
00671 }
00672 
00673 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00674 bool VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator::IsAtEnd()
00675 {
00676     return mElementIter == mrMesh.mElements.end();
00677 }
00678 
00679 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00680 bool VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator::IsAllowedElement()
00681 {
00682     return !(mSkipDeletedElements && (*this)->IsDeleted());
00683 }
00684 
00685 
00686 #endif /*VERTEXMESH_HPP_*/