AbstractTetrahedralMesh.hpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2010
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 #ifndef ABSTRACTTETRAHEDRALMESH_HPP_
00030 #define ABSTRACTTETRAHEDRALMESH_HPP_
00031 
00032 #include "ChasteSerialization.hpp"
00033 #include "ClassIsAbstract.hpp"
00034 #include <boost/serialization/base_object.hpp>
00035 
00036 #include <vector>
00037 #include <string>
00038 #include <cassert>
00039 
00040 #include "AbstractMesh.hpp"
00041 #include "BoundaryElement.hpp"
00042 #include "Element.hpp"
00043 #include "AbstractMeshReader.hpp"
00044 #include "TrianglesMeshReader.hpp"
00045 #include "TrianglesMeshWriter.hpp"
00046 #include "ArchiveLocationInfo.hpp"
00047 
00048 #include <boost/serialization/split_member.hpp>
00049 
00053 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00054 class AbstractTetrahedralMesh : public AbstractMesh<ELEMENT_DIM, SPACE_DIM>
00055 {
00056 protected:
00060     bool mMeshIsLinear;
00061 
00062 private:
00070     virtual unsigned SolveElementMapping(unsigned index) const = 0;
00071 
00079     virtual unsigned SolveBoundaryElementMapping(unsigned index) const = 0;
00080 
00082     friend class boost::serialization::access;
00083 
00095     template<class Archive>
00096     void save(Archive & archive, const unsigned int version) const
00097     {
00098         archive & boost::serialization::base_object<AbstractMesh<ELEMENT_DIM,SPACE_DIM> >(*this);
00099         archive & mMeshIsLinear;
00100         // Create a mesh writer pointing to the correct file and directory.
00101         TrianglesMeshWriter<ELEMENT_DIM,SPACE_DIM> mesh_writer(ArchiveLocationInfo::GetArchiveRelativePath(),
00102                                                                ArchiveLocationInfo::GetMeshFilename(),
00103                                                                false);
00104         //Binary meshes have similar content to the original Triangle/Tetgen format, but take up less space on disk
00105         mesh_writer.SetWriteFilesAsBinary();
00112         mesh_writer.WriteFilesUsingMesh(*(const_cast<AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>*>(this)));
00113         // Make sure that the files are written before slave processes proceed
00114         PetscTools::Barrier("AbstractTetrahedralMesh::save");
00115     }
00116 
00123     template<class Archive>
00124     void load(Archive & archive, const unsigned int version)
00125     {
00126         archive & boost::serialization::base_object<AbstractMesh<ELEMENT_DIM,SPACE_DIM> >(*this);
00127         archive & mMeshIsLinear;
00128 
00129         // Store the DistributedVectorFactory loaded from the archive
00130         DistributedVectorFactory* p_factory = this->mpDistributedVectorFactory;
00131         this->mpDistributedVectorFactory = NULL;
00132         // Check whether we're migrating, or if we can use the original partition for the mesh
00133         DistributedVectorFactory* p_our_factory = NULL;
00134         if (p_factory)
00135         {
00136             p_our_factory = p_factory->GetOriginalFactory();
00137         }
00138         if (p_our_factory && p_our_factory->GetNumProcs() == p_factory->GetNumProcs())
00139         {
00140             // Specify the node distribution
00141             this->SetDistributedVectorFactory(p_our_factory);
00142         }
00143         else
00144         {
00145             // Migrating; let the mesh re-partition if it likes
00147             p_our_factory = NULL;
00148         }
00149 
00150         if (mMeshIsLinear)
00151         {
00152             //I am a linear mesh
00153             TrianglesMeshReader<ELEMENT_DIM,SPACE_DIM> mesh_reader(ArchiveLocationInfo::GetArchiveDirectory() + ArchiveLocationInfo::GetMeshFilename());
00154             this->ConstructFromMeshReader(mesh_reader);
00155         }
00156         else
00157         {
00158             //I am a quadratic mesh and need quadratic information from the reader
00159             TrianglesMeshReader<ELEMENT_DIM,SPACE_DIM> mesh_reader(ArchiveLocationInfo::GetArchiveDirectory() + ArchiveLocationInfo::GetMeshFilename(), 2, 2);
00160             this->ConstructFromMeshReader(mesh_reader);
00161         }
00162 
00163         // Make sure we're using the correct vector factory
00164         if (p_factory)
00165         {
00166             if (!this->mpDistributedVectorFactory)
00167             {
00168                 // If we're not using a DistributedTetrahedralMesh, ConstructFromMeshReader won't set
00169                 // this->mpDistributedVectorFactory.
00170                 this->mpDistributedVectorFactory = p_factory;
00171             }
00172             else
00173             {
00174                 // We need to update p_factory to match this->mpDistributedVectorFactory, and then use
00175                 // p_factory, since the rest of the code (e.g. AbstractCardiacPde) will be using p_factory.
00176                 p_factory->SetFromFactory(this->mpDistributedVectorFactory);
00177                 if (p_our_factory != this->mpDistributedVectorFactory)
00178                 {
00179                     // Avoid memory leak
00180                     delete this->mpDistributedVectorFactory;
00181                 }
00182                 this->mpDistributedVectorFactory = p_factory;
00183             }
00184         }
00185     }
00186     BOOST_SERIALIZATION_SPLIT_MEMBER()
00187 
00188 
00189 protected:  // Give access of these variables to subclasses
00190 
00192     std::vector<Element<ELEMENT_DIM, SPACE_DIM> *> mElements;
00193 
00195     std::vector<BoundaryElement<ELEMENT_DIM-1, SPACE_DIM> *> mBoundaryElements;
00196 
00197 public:
00198 
00200     //                            Iterators                             //
00202 
00204     typedef typename std::vector<BoundaryElement<ELEMENT_DIM-1, SPACE_DIM> *>::const_iterator BoundaryElementIterator;
00205 
00207     class ElementIterator;
00208 
00214     inline ElementIterator GetElementIteratorBegin(bool skipDeletedElements=true);
00215 
00219     inline ElementIterator GetElementIteratorEnd();
00220 
00222     //                             Methods                              //
00224 
00228     AbstractTetrahedralMesh();
00229 
00233     virtual ~AbstractTetrahedralMesh();
00234 
00235 
00239     virtual unsigned GetNumElements() const;
00240 
00244     virtual unsigned GetNumBoundaryElements() const;
00245 
00249     unsigned GetNumAllElements() const;
00250 
00254     unsigned GetNumAllBoundaryElements() const;
00255 
00262     Element<ELEMENT_DIM, SPACE_DIM>* GetElement(unsigned index) const;
00263 
00270     BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>* GetBoundaryElement(unsigned index) const;
00271 
00281     virtual void SetElementOwnerships(unsigned lo, unsigned hi);
00282 
00289     virtual void ConstructFromMeshReader(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader)=0;
00290 
00294     BoundaryElementIterator GetBoundaryElementIteratorBegin() const;
00295 
00300     BoundaryElementIterator GetBoundaryElementIteratorEnd() const;
00301 
00310     virtual void GetInverseJacobianForElement(unsigned elementIndex, c_matrix<double, SPACE_DIM, ELEMENT_DIM>& rJacobian,
00311                                               double& rJacobianDeterminant,
00312                                               c_matrix<double, ELEMENT_DIM, SPACE_DIM>& rInverseJacobian) const;
00313 
00322     virtual void GetWeightedDirectionForBoundaryElement(unsigned elementIndex,
00323                                                         c_vector<double, SPACE_DIM>& rWeightedDirection,
00324                                                         double& rJacobianDeterminant) const;
00325 
00326 
00327 
00336      virtual void ConstructLinearMesh(unsigned width);
00337 
00349     virtual void ConstructRectangularMesh(unsigned width, unsigned height, bool stagger=true);
00350 
00359     virtual void ConstructCuboid(unsigned width, unsigned height, unsigned depth);
00360 
00367     virtual bool CalculateDesignatedOwnershipOfBoundaryElement( unsigned faceIndex );
00368 
00375     virtual bool CalculateDesignatedOwnershipOfElement( unsigned elementIndex );
00376 
00377 
00379     //                         Nested classes                           //
00381 
00382 
00386     class ElementIterator
00387     {
00388     public:
00394         inline Element<ELEMENT_DIM, SPACE_DIM>& operator*();
00395 
00399         inline Element<ELEMENT_DIM, SPACE_DIM>* operator->();
00400 
00406         inline bool operator!=(const AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator& rOther);
00407 
00411         inline ElementIterator& operator++();
00412 
00423         ElementIterator(AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>& rMesh,
00424                         typename std::vector<Element<ELEMENT_DIM, SPACE_DIM> *>::iterator elementIter,
00425                         bool skipDeletedElements=true);
00426 
00427     private:
00429         AbstractTetrahedralMesh& mrMesh;
00430 
00432         typename std::vector<Element<ELEMENT_DIM, SPACE_DIM> *>::iterator mElementIter;
00433 
00435         bool mSkipDeletedElements;
00436 
00440         inline bool IsAtEnd();
00441 
00445         inline bool IsAllowedElement();
00446     };
00447 
00448 };
00449 
00450 TEMPLATED_CLASS_IS_ABSTRACT_2_UNSIGNED(AbstractTetrahedralMesh);
00451 
00453 //      ElementIterator class implementation - most methods are inlined     //
00455 
00456 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00457 typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetElementIteratorBegin(
00458         bool skipDeletedElements)
00459 {
00460     return ElementIterator(*this, mElements.begin(), skipDeletedElements);
00461 }
00462 
00463 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00464 typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetElementIteratorEnd()
00465 {
00466     return ElementIterator(*this, mElements.end());
00467 }
00468 
00469 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00470 Element<ELEMENT_DIM, SPACE_DIM>& AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::operator*()
00471 {
00472     assert(!IsAtEnd());
00473     return **mElementIter;
00474 }
00475 
00476 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00477 Element<ELEMENT_DIM, SPACE_DIM>* AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::operator->()
00478 {
00479     assert(!IsAtEnd());
00480     return *mElementIter;
00481 }
00482 
00483 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00484 bool AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::operator!=(const AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator& rOther)
00485 {
00486     return mElementIter != rOther.mElementIter;
00487 }
00488 
00489 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00490 typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator& AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::operator++()
00491 {
00492     do
00493     {
00494         ++mElementIter;
00495     }
00496     while (!IsAtEnd() && !IsAllowedElement());
00497 
00498     return (*this);
00499 }
00500 
00501 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00502 AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::ElementIterator(
00503         AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>& rMesh,
00504         typename std::vector<Element<ELEMENT_DIM, SPACE_DIM> *>::iterator elementIter,
00505         bool skipDeletedElements)
00506     : mrMesh(rMesh),
00507       mElementIter(elementIter),
00508       mSkipDeletedElements(skipDeletedElements)
00509 {
00510     if (mrMesh.mElements.size() == 0)
00511     {
00512         // Cope with empty meshes
00513         mElementIter = mrMesh.mElements.end();
00514     }
00515     else
00516     {
00517         // Make sure we start at an allowed element
00518         if (mElementIter == mrMesh.mElements.begin() && !IsAllowedElement())
00519         {
00520             ++(*this);
00521         }
00522     }
00523 }
00524 
00525 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00526 bool AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::IsAtEnd()
00527 {
00528     return mElementIter == mrMesh.mElements.end();
00529 }
00530 
00531 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00532 bool AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::IsAllowedElement()
00533 {
00534     return !(mSkipDeletedElements && (*this)->IsDeleted());
00535 }
00536 
00537 
00538 #endif /*ABSTRACTTETRAHEDRALMESH_HPP_*/

Generated by  doxygen 1.6.2