AbstractTetrahedralMesh.hpp

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 #ifndef ABSTRACTTETRAHEDRALMESH_HPP_
00037 #define ABSTRACTTETRAHEDRALMESH_HPP_
00038 
00039 #include "ChasteSerialization.hpp"
00040 #include "ClassIsAbstract.hpp"
00041 #include "ChasteSerializationVersion.hpp"
00042 #include <boost/serialization/vector.hpp>
00043 #include <boost/serialization/base_object.hpp>
00044 #include <boost/serialization/split_member.hpp>
00045 
00046 #include <vector>
00047 #include <string>
00048 #include <cassert>
00049 #include <boost/foreach.hpp>
00050 
00051 #include "AbstractMesh.hpp"
00052 #include "BoundaryElement.hpp"
00053 #include "Element.hpp"
00054 #include "GenericMeshReader.hpp"
00055 #include "AbstractMeshReader.hpp"
00056 #include "TrianglesMeshReader.hpp"
00057 #include "TrianglesMeshWriter.hpp"
00058 #include "ArchiveLocationInfo.hpp"
00059 #include "FileFinder.hpp"
00060 
00061 
00063 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00064 class AbstractConductivityTensors;
00065 
00070 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00071 class AbstractTetrahedralMesh : public AbstractMesh<ELEMENT_DIM, SPACE_DIM>
00072 {
00073     friend class AbstractConductivityTensors<ELEMENT_DIM, SPACE_DIM>; //A class which needs a global to local element mapping
00074     friend class CentroidWriter; //A test class which needs access to mElements in order to check that local/global indices match
00075 protected:
00079     bool mMeshIsLinear;
00080 
00081 private:
00091     virtual unsigned SolveElementMapping(unsigned index) const = 0;
00092 
00101     virtual unsigned SolveBoundaryElementMapping(unsigned index) const = 0;
00102 
00104     friend class boost::serialization::access;
00105 
00117     template<class Archive>
00118     void save(Archive & archive, const unsigned int version) const
00119     {
00120         archive & boost::serialization::base_object<AbstractMesh<ELEMENT_DIM,SPACE_DIM> >(*this);
00121         archive & mMeshIsLinear;
00122         // Create a mesh writer pointing to the correct file and directory
00123         TrianglesMeshWriter<ELEMENT_DIM,SPACE_DIM> mesh_writer(ArchiveLocationInfo::GetArchiveRelativePath(),
00124                                                                ArchiveLocationInfo::GetMeshFilename(),
00125                                                                false);
00126         // Binary meshes have similar content to the original Triangle/Tetgen format, but take up less space on disk
00127         mesh_writer.SetWriteFilesAsBinary();
00128 
00129         // Archive the mesh permutation, so we can just copy the original mesh files whenever possible
00130         bool permutation_available = (this->rGetNodePermutation().size() != 0);
00131         archive & permutation_available;
00132 
00133         if (permutation_available)
00134         {
00135             const std::vector<unsigned>& rPermutation = this->rGetNodePermutation();
00136             archive & rPermutation;
00137         }
00138 
00139         if (!this->IsMeshOnDisk() || this->mMeshChangesDuringSimulation)
00140         {
00141             mesh_writer.WriteFilesUsingMesh(*(const_cast<AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>*>(this)));
00142         }
00143         else
00144         {
00145             unsigned order_of_element = (mMeshIsLinear?1:2);
00146             unsigned& order_of_boundary_element = order_of_element;
00147 
00148             // Mesh in disc, copy it to the archiving folder
00149             std::string original_file=this->GetMeshFileBaseName();
00150             std::auto_ptr<AbstractMeshReader<ELEMENT_DIM, SPACE_DIM> > p_original_mesh_reader
00151                 = GenericMeshReader<ELEMENT_DIM, SPACE_DIM>(original_file, order_of_element, order_of_boundary_element);
00152 
00153             if (p_original_mesh_reader->IsFileFormatBinary())
00154             {
00155                 // Mesh is in binary format, we can just copy the files across ignoring the mesh reader
00156                 if (PetscTools::AmMaster())
00157                 {
00158                     FileFinder mesh_base(this->GetMeshFileBaseName());
00159                     FileFinder mesh_folder = mesh_base.GetParent();
00160                     std::string mesh_leaf_name = mesh_base.GetLeafNameNoExtension();
00161                     std::vector<FileFinder> mesh_files = mesh_folder.FindMatches(mesh_leaf_name + ".*");
00162                     FileFinder dest_dir(ArchiveLocationInfo::GetArchiveDirectory());
00163                     BOOST_FOREACH(const FileFinder& r_mesh_file, mesh_files)
00164                     {
00165                         FileFinder dest_file(ArchiveLocationInfo::GetMeshFilename() + r_mesh_file.GetExtension(),
00166                                              dest_dir);
00167                         ABORT_IF_THROWS(r_mesh_file.CopyTo(dest_file));
00168                     }
00169                 }
00170             }
00171             else
00172             {
00173                 // Mesh in text format, use the mesh writer to "binarise" it
00174                 mesh_writer.WriteFilesUsingMeshReaderAndMesh(*p_original_mesh_reader,
00175                                                              *(const_cast<AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>*>(this)));
00176             }
00177         }
00178 
00179         // Make sure that the files are written before slave processes proceed
00180         PetscTools::Barrier("AbstractTetrahedralMesh::save");
00181     }
00182 
00189     template<class Archive>
00190     void load(Archive & archive, const unsigned int version)
00191     {
00192         archive & boost::serialization::base_object<AbstractMesh<ELEMENT_DIM,SPACE_DIM> >(*this);
00193         archive & mMeshIsLinear;
00194 
00195         bool permutation_available=false;
00196         std::vector<unsigned> permutation;
00197 
00198         if (version > 0)
00199         {
00200             archive & permutation_available;
00201 
00202             if (permutation_available)
00203             {
00204                 archive & permutation;
00205             }
00206         }
00207 
00208         // Store the DistributedVectorFactory loaded from the archive
00209         DistributedVectorFactory* p_factory = this->mpDistributedVectorFactory;
00210         this->mpDistributedVectorFactory = NULL;
00211 
00212         // Check whether we're migrating, or if we can use the original partition for the mesh
00213         DistributedVectorFactory* p_our_factory = NULL;
00214         if (p_factory)
00215         {
00216             p_our_factory = p_factory->GetOriginalFactory();
00217         }
00218         if (p_our_factory && p_our_factory->GetNumProcs() == p_factory->GetNumProcs())
00219         {
00220             // Specify the node distribution
00221             this->SetDistributedVectorFactory(p_our_factory);
00222         }
00223         else
00224         {
00225             // Migrating; let the mesh re-partition if it likes
00227             p_our_factory = NULL;
00228         }
00229 
00230         if (mMeshIsLinear)
00231         {
00232             // I am a linear mesh
00233             TrianglesMeshReader<ELEMENT_DIM,SPACE_DIM> mesh_reader(ArchiveLocationInfo::GetArchiveDirectory() + ArchiveLocationInfo::GetMeshFilename());
00234 
00235             if (permutation_available)
00236             {
00237                 mesh_reader.SetNodePermutation(permutation);
00238             }
00239 
00240             this->ConstructFromMeshReader(mesh_reader);
00241         }
00242         else
00243         {
00244             // I am a quadratic mesh and need quadratic information from the reader
00245             TrianglesMeshReader<ELEMENT_DIM,SPACE_DIM> mesh_reader(ArchiveLocationInfo::GetArchiveDirectory() + ArchiveLocationInfo::GetMeshFilename(), 2, 2);
00246             this->ConstructFromMeshReader(mesh_reader);
00247         }
00248 
00249         // Make sure we're using the correct vector factory
00250         if (p_factory)
00251         {
00252             if (!this->mpDistributedVectorFactory)
00253             {
00254                 // If we're not using a DistributedTetrahedralMesh, ConstructFromMeshReader won't set
00255                 // this->mpDistributedVectorFactory.
00256                 this->mpDistributedVectorFactory = p_factory;
00257             }
00258             else
00259             {
00260                 // We need to update p_factory to match this->mpDistributedVectorFactory, and then use
00261                 // p_factory, since the rest of the code (e.g. AbstractCardiacPde) will be using p_factory.
00262                 p_factory->SetFromFactory(this->mpDistributedVectorFactory);
00263                 if (p_our_factory != this->mpDistributedVectorFactory)
00264                 {
00265                     // Avoid memory leak
00266                     delete this->mpDistributedVectorFactory;
00267                 }
00268                 this->mpDistributedVectorFactory = p_factory;
00269             }
00270         }
00271     }
00272     BOOST_SERIALIZATION_SPLIT_MEMBER()
00273 
00274 protected:  // Give access of these variables to subclasses
00275 
00277     std::vector<Element<ELEMENT_DIM, SPACE_DIM> *> mElements;
00278 
00280     std::vector<BoundaryElement<ELEMENT_DIM-1, SPACE_DIM> *> mBoundaryElements;
00281 
00289     void SetElementOwnerships();
00290 
00291 public:
00292 
00294     //                            Iterators                             //
00296 
00298     typedef typename std::vector<BoundaryElement<ELEMENT_DIM-1, SPACE_DIM> *>::const_iterator BoundaryElementIterator;
00299 
00301     class ElementIterator;
00302 
00308     inline ElementIterator GetElementIteratorBegin(bool skipDeletedElements=true);
00309 
00313     inline ElementIterator GetElementIteratorEnd();
00314 
00316     //                             Methods                              //
00318 
00322     AbstractTetrahedralMesh();
00323 
00327     virtual ~AbstractTetrahedralMesh();
00328 
00329 
00333     virtual unsigned GetNumElements() const;
00334 
00338     virtual unsigned GetNumLocalElements() const;
00339 
00343     virtual unsigned GetNumBoundaryElements() const;
00344 
00348     virtual unsigned GetNumLocalBoundaryElements() const;
00349 
00353     unsigned GetNumAllElements() const;
00354 
00358     unsigned GetNumAllBoundaryElements() const;
00359 
00365     virtual unsigned GetNumCableElements() const;
00366 
00371     virtual unsigned GetNumVertices() const;
00372 
00379     virtual unsigned GetMaximumNodeIndex();
00380 
00387     Element<ELEMENT_DIM, SPACE_DIM>* GetElement(unsigned index) const;
00388 
00395     BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>* GetBoundaryElement(unsigned index) const;
00396 
00397 
00404     virtual void ConstructFromMeshReader(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader)=0;
00405 
00414     void ConstructFromMesh(AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>& rOtherMesh);
00415 
00416 
00420     BoundaryElementIterator GetBoundaryElementIteratorBegin() const;
00421 
00426     BoundaryElementIterator GetBoundaryElementIteratorEnd() const;
00427 
00436     virtual void GetInverseJacobianForElement(unsigned elementIndex, c_matrix<double, SPACE_DIM, ELEMENT_DIM>& rJacobian,
00437                                               double& rJacobianDeterminant,
00438                                               c_matrix<double, ELEMENT_DIM, SPACE_DIM>& rInverseJacobian) const;
00439 
00448     virtual void GetWeightedDirectionForBoundaryElement(unsigned elementIndex,
00449                                                         c_vector<double, SPACE_DIM>& rWeightedDirection,
00450                                                         double& rJacobianDeterminant) const;
00451 
00459     void CheckOutwardNormals();
00460 
00473     virtual void ConstructLinearMesh(unsigned width);
00474 
00475 
00476 
00492     virtual void ConstructRectangularMesh(unsigned width, unsigned height, bool stagger=true);
00493 
00494 
00495 
00507     virtual void ConstructCuboid(unsigned width, unsigned height, unsigned depth);
00508 
00509 
00510 
00521     void ConstructRegularSlabMesh(double spaceStep, double width, double height=0, double depth=0);
00522 
00523 
00524 
00532     virtual bool CalculateDesignatedOwnershipOfBoundaryElement( unsigned faceIndex );
00533 
00541     virtual bool CalculateDesignatedOwnershipOfElement( unsigned elementIndex );
00542 
00552     unsigned CalculateMaximumNodeConnectivityPerProcess() const;
00553 
00560     virtual void GetHaloNodeIndices(std::vector<unsigned>& rHaloIndices) const;
00561 
00575      void CalculateNodeExchange( std::vector<std::vector<unsigned> >& rNodesToSendPerProcess,
00576                                  std::vector<std::vector<unsigned> >& rNodesToReceivePerProcess);
00577 
00578 
00587      virtual c_vector<double, 2> CalculateMinMaxEdgeLengths();
00588 
00602      unsigned GetContainingElementIndex(const ChastePoint<SPACE_DIM>& rTestPoint,
00603                                         bool strict=false,
00604                                         std::set<unsigned> testElements=std::set<unsigned>(),
00605                                         bool onlyTryWithTestElements = false);
00606 
00612      unsigned GetNearestElementIndexFromTestElements(const ChastePoint<SPACE_DIM>& rTestPoint,
00613                                                      std::set<unsigned> testElements);
00614 
00615 
00616 
00618     //                         Nested classes                           //
00620 
00621 
00625     class ElementIterator
00626     {
00627     public:
00633         inline Element<ELEMENT_DIM, SPACE_DIM>& operator*();
00634 
00639         inline Element<ELEMENT_DIM, SPACE_DIM>* operator->();
00640 
00646         inline bool operator!=(const typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator& rOther);
00647 
00652         inline ElementIterator& operator++();
00653 
00664         ElementIterator(AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>& rMesh,
00665                         typename std::vector<Element<ELEMENT_DIM, SPACE_DIM> *>::iterator elementIter,
00666                         bool skipDeletedElements=true);
00667 
00668     private:
00670         AbstractTetrahedralMesh& mrMesh;
00671 
00673         typename std::vector<Element<ELEMENT_DIM, SPACE_DIM> *>::iterator mElementIter;
00674 
00676         bool mSkipDeletedElements;
00677 
00682         inline bool IsAtEnd();
00683 
00688         inline bool IsAllowedElement();
00689     };
00690 
00691 };
00692 
00693 TEMPLATED_CLASS_IS_ABSTRACT_2_UNSIGNED(AbstractTetrahedralMesh)
00694 
00695 namespace boost {
00696 namespace serialization {
00703 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00704 struct version<AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM> >
00705 {
00707     CHASTE_VERSION_CONTENT(1);
00708 };
00709 } // namespace serialization
00710 } // namespace boost
00711 
00712 
00714 //      ElementIterator class implementation - most methods are inlined     //
00716 
00717 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00718 typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetElementIteratorBegin(
00719         bool skipDeletedElements)
00720 {
00721     return ElementIterator(*this, mElements.begin(), skipDeletedElements);
00722 }
00723 
00724 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00725 typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetElementIteratorEnd()
00726 {
00727     return ElementIterator(*this, mElements.end());
00728 }
00729 
00730 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00731 Element<ELEMENT_DIM, SPACE_DIM>& AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::operator*()
00732 {
00733     assert(!IsAtEnd());
00734     return **mElementIter;
00735 }
00736 
00737 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00738 Element<ELEMENT_DIM, SPACE_DIM>* AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::operator->()
00739 {
00740     assert(!IsAtEnd());
00741     return *mElementIter;
00742 }
00743 
00744 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00745 bool AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::operator!=(const typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator& rOther)
00746 {
00747     return mElementIter != rOther.mElementIter;
00748 }
00749 
00750 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00751 typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator& AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::operator++()
00752 {
00753     do
00754     {
00755         ++mElementIter;
00756     }
00757     while (!IsAtEnd() && !IsAllowedElement());
00758 
00759     return (*this);
00760 }
00761 
00762 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00763 AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::ElementIterator(
00764         AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>& rMesh,
00765         typename std::vector<Element<ELEMENT_DIM, SPACE_DIM> *>::iterator elementIter,
00766         bool skipDeletedElements)
00767     : mrMesh(rMesh),
00768       mElementIter(elementIter),
00769       mSkipDeletedElements(skipDeletedElements)
00770 {
00771     if (mrMesh.mElements.size() == 0)
00772     {
00773         // Cope with empty meshes
00774         mElementIter = mrMesh.mElements.end();
00775     }
00776     else
00777     {
00778         // Make sure we start at an allowed element
00779         if (mElementIter == mrMesh.mElements.begin() && !IsAllowedElement())
00780         {
00781             ++(*this);
00782         }
00783     }
00784 }
00785 
00786 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00787 bool AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::IsAtEnd()
00788 {
00789     return mElementIter == mrMesh.mElements.end();
00790 }
00791 
00792 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00793 bool AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::IsAllowedElement()
00794 {
00795     return !(mSkipDeletedElements && (*this)->IsDeleted());
00796 }
00797 
00798 
00799 
00800 #endif /*ABSTRACTTETRAHEDRALMESH_HPP_*/

Generated by  doxygen 1.6.2