AbstractTetrahedralMesh.hpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2011
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 "ChasteSerializationVersion.hpp"
00035 #include <boost/serialization/vector.hpp>
00036 #include <boost/serialization/base_object.hpp>
00037 #include <boost/serialization/split_member.hpp>
00038 
00039 #include <vector>
00040 #include <string>
00041 #include <cassert>
00042 
00043 #include "AbstractMesh.hpp"
00044 #include "BoundaryElement.hpp"
00045 #include "Element.hpp"
00046 #include "AbstractMeshReader.hpp"
00047 #include "TrianglesMeshReader.hpp"
00048 #include "TrianglesMeshWriter.hpp"
00049 #include "ArchiveLocationInfo.hpp"
00050 #include "GenericMeshReader.hpp"
00051 
00052 
00054 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00055 class AbstractConductivityTensors;
00056 
00061 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00062 class AbstractTetrahedralMesh : public AbstractMesh<ELEMENT_DIM, SPACE_DIM>
00063 {
00064     friend class AbstractConductivityTensors<ELEMENT_DIM, SPACE_DIM>; //A class which needs a global to local element mapping
00065 
00066 protected:
00070     bool mMeshIsLinear;
00071 
00072 private:
00080     virtual unsigned SolveElementMapping(unsigned index) const = 0;
00081 
00089     virtual unsigned SolveBoundaryElementMapping(unsigned index) const = 0;
00090 
00092     friend class boost::serialization::access;
00093 
00105     template<class Archive>
00106     void save(Archive & archive, const unsigned int version) const
00107     {
00108         archive & boost::serialization::base_object<AbstractMesh<ELEMENT_DIM,SPACE_DIM> >(*this);
00109         archive & mMeshIsLinear;
00110         // Create a mesh writer pointing to the correct file and directory
00111         TrianglesMeshWriter<ELEMENT_DIM,SPACE_DIM> mesh_writer(ArchiveLocationInfo::GetArchiveRelativePath(),
00112                                                                ArchiveLocationInfo::GetMeshFilename(),
00113                                                                false);
00114         // Binary meshes have similar content to the original Triangle/Tetgen format, but take up less space on disk
00115         mesh_writer.SetWriteFilesAsBinary();
00116 
00117         // Archive the mesh permutation, so we can just copy the original mesh files whenever possible
00118         bool permutation_available = (this->rGetNodePermutation().size() != 0);
00119         archive & permutation_available;
00120 
00121         if (permutation_available)
00122         {
00123             const std::vector<unsigned>& rPermutation = this->rGetNodePermutation();
00124             archive & rPermutation;
00125         }
00126 
00127         if (!this->IsMeshOnDisk())
00128         {
00129             mesh_writer.WriteFilesUsingMesh(*(const_cast<AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>*>(this)));
00130         }
00131         else
00132         {
00133             unsigned order_of_element = (mMeshIsLinear?1:2);
00134             unsigned& order_of_boundary_element = order_of_element;
00135 
00136             // Mesh in disc, copy it to the archiving folder
00137             std::string original_file=this->GetMeshFileBaseName();
00138             std::auto_ptr<AbstractMeshReader<ELEMENT_DIM, SPACE_DIM> > p_original_mesh_reader
00139                 = GenericMeshReader<ELEMENT_DIM, SPACE_DIM>(original_file, order_of_element, order_of_boundary_element);
00140 
00141             if (p_original_mesh_reader->IsFileFormatBinary())
00142             {
00143                 // Mesh is in binary format, we can just copy the files across ignoring the mesh reader
00144                 std::stringstream cp_command;
00145                 cp_command << "for filename in `ls " << this->GetMeshFileBaseName() << ".*`; do " <<
00146                                  "extension=${filename##*.};" << // ##*. deletes basename and . from the filename (i.e. leaves only the extension (http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_10_03.html)
00147                                  "cp $filename " << ArchiveLocationInfo::GetArchiveDirectory() << ArchiveLocationInfo::GetMeshFilename() <<".$extension;" <<
00148                               "done";
00149 
00150                 if (PetscTools::AmMaster())
00151                 {
00152                     ABORT_IF_NON0(system, cp_command.str());
00153                 }
00154             }
00155             else
00156             {
00157                 // Mesh in text format, use the mesh writer to "binarise" it
00158                 mesh_writer.WriteFilesUsingMeshReaderAndMesh(*p_original_mesh_reader,
00159                                                              *(const_cast<AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>*>(this)));
00160             }
00161         }
00162 
00163         // Make sure that the files are written before slave processes proceed
00164         PetscTools::Barrier("AbstractTetrahedralMesh::save");
00165     }
00166 
00173     template<class Archive>
00174     void load(Archive & archive, const unsigned int version)
00175     {
00176         archive & boost::serialization::base_object<AbstractMesh<ELEMENT_DIM,SPACE_DIM> >(*this);
00177         archive & mMeshIsLinear;
00178 
00179         bool permutation_available=false;
00180         std::vector<unsigned> permutation;
00181 
00182         if (version > 0)
00183         {
00184             archive & permutation_available;
00185 
00186             if (permutation_available)
00187             {
00188                 archive & permutation;
00189             }
00190         }
00191 
00192         // Store the DistributedVectorFactory loaded from the archive
00193         DistributedVectorFactory* p_factory = this->mpDistributedVectorFactory;
00194         this->mpDistributedVectorFactory = NULL;
00195 
00196         // Check whether we're migrating, or if we can use the original partition for the mesh
00197         DistributedVectorFactory* p_our_factory = NULL;
00198         if (p_factory)
00199         {
00200             p_our_factory = p_factory->GetOriginalFactory();
00201         }
00202         if (p_our_factory && p_our_factory->GetNumProcs() == p_factory->GetNumProcs())
00203         {
00204             // Specify the node distribution
00205             this->SetDistributedVectorFactory(p_our_factory);
00206         }
00207         else
00208         {
00209             // Migrating; let the mesh re-partition if it likes
00211             p_our_factory = NULL;
00212         }
00213 
00214         if (mMeshIsLinear)
00215         {
00216             // I am a linear mesh
00217             TrianglesMeshReader<ELEMENT_DIM,SPACE_DIM> mesh_reader(ArchiveLocationInfo::GetArchiveDirectory() + ArchiveLocationInfo::GetMeshFilename());
00218 
00219             if (permutation_available)
00220             {
00221                 mesh_reader.SetNodePermutation(permutation);
00222             }
00223 
00224             this->ConstructFromMeshReader(mesh_reader);
00225         }
00226         else
00227         {
00228             // I am a quadratic mesh and need quadratic information from the reader
00229             TrianglesMeshReader<ELEMENT_DIM,SPACE_DIM> mesh_reader(ArchiveLocationInfo::GetArchiveDirectory() + ArchiveLocationInfo::GetMeshFilename(), 2, 2);
00230             this->ConstructFromMeshReader(mesh_reader);
00231         }
00232 
00233         // Make sure we're using the correct vector factory
00234         if (p_factory)
00235         {
00236             if (!this->mpDistributedVectorFactory)
00237             {
00238                 // If we're not using a DistributedTetrahedralMesh, ConstructFromMeshReader won't set
00239                 // this->mpDistributedVectorFactory.
00240                 this->mpDistributedVectorFactory = p_factory;
00241             }
00242             else
00243             {
00244                 // We need to update p_factory to match this->mpDistributedVectorFactory, and then use
00245                 // p_factory, since the rest of the code (e.g. AbstractCardiacPde) will be using p_factory.
00246                 p_factory->SetFromFactory(this->mpDistributedVectorFactory);
00247                 if (p_our_factory != this->mpDistributedVectorFactory)
00248                 {
00249                     // Avoid memory leak
00250                     delete this->mpDistributedVectorFactory;
00251                 }
00252                 this->mpDistributedVectorFactory = p_factory;
00253             }
00254         }
00255     }
00256     BOOST_SERIALIZATION_SPLIT_MEMBER()
00257 
00258 protected:  // Give access of these variables to subclasses
00259 
00261     std::vector<Element<ELEMENT_DIM, SPACE_DIM> *> mElements;
00262 
00264     std::vector<BoundaryElement<ELEMENT_DIM-1, SPACE_DIM> *> mBoundaryElements;
00265 
00273     void SetElementOwnerships();
00274 
00275 public:
00276 
00278     //                            Iterators                             //
00280 
00282     typedef typename std::vector<BoundaryElement<ELEMENT_DIM-1, SPACE_DIM> *>::const_iterator BoundaryElementIterator;
00283 
00285     class ElementIterator;
00286 
00292     inline ElementIterator GetElementIteratorBegin(bool skipDeletedElements=true);
00293 
00297     inline ElementIterator GetElementIteratorEnd();
00298 
00300     //                             Methods                              //
00302 
00306     AbstractTetrahedralMesh();
00307 
00311     virtual ~AbstractTetrahedralMesh();
00312 
00313 
00317     virtual unsigned GetNumElements() const;
00318 
00322     virtual unsigned GetNumLocalElements() const;
00323 
00327     virtual unsigned GetNumBoundaryElements() const;
00328 
00332     unsigned GetNumAllElements() const;
00333 
00337     unsigned GetNumAllBoundaryElements() const;
00338 
00344     virtual unsigned GetNumCableElements() const;
00345 
00352     Element<ELEMENT_DIM, SPACE_DIM>* GetElement(unsigned index) const;
00353 
00360     BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>* GetBoundaryElement(unsigned index) const;
00361 
00362 
00369     virtual void ConstructFromMeshReader(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader)=0;
00370 
00379     void ConstructFromMesh(AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>& rOtherMesh);
00380 
00381 
00385     BoundaryElementIterator GetBoundaryElementIteratorBegin() const;
00386 
00391     BoundaryElementIterator GetBoundaryElementIteratorEnd() const;
00392 
00401     virtual void GetInverseJacobianForElement(unsigned elementIndex, c_matrix<double, SPACE_DIM, ELEMENT_DIM>& rJacobian,
00402                                               double& rJacobianDeterminant,
00403                                               c_matrix<double, ELEMENT_DIM, SPACE_DIM>& rInverseJacobian) const;
00404 
00413     virtual void GetWeightedDirectionForBoundaryElement(unsigned elementIndex,
00414                                                         c_vector<double, SPACE_DIM>& rWeightedDirection,
00415                                                         double& rJacobianDeterminant) const;
00416 
00424     void CheckOutwardNormals();
00425 
00438     virtual void ConstructLinearMesh(unsigned width);
00439 
00440 
00441 
00457     virtual void ConstructRectangularMesh(unsigned width, unsigned height, bool stagger=true);
00458 
00459 
00460 
00472     virtual void ConstructCuboid(unsigned width, unsigned height, unsigned depth);
00473 
00474 
00475 
00486     void ConstructRegularSlabMesh(double spaceStep, double width, double height=0, double depth=0);
00487 
00488 
00489 
00496     virtual bool CalculateDesignatedOwnershipOfBoundaryElement( unsigned faceIndex );
00497 
00504     virtual bool CalculateDesignatedOwnershipOfElement( unsigned elementIndex );
00505 
00513     unsigned CalculateMaximumNodeConnectivityPerProcess() const;
00514 
00521     virtual void GetHaloNodeIndices(std::vector<unsigned>& rHaloIndices) const;
00522 
00536      void CalculateNodeExchange( std::vector<std::vector<unsigned> >& rNodesToSendPerProcess,
00537                                  std::vector<std::vector<unsigned> >& rNodesToReceivePerProcess);
00538 
00539 
00541     //                         Nested classes                           //
00543 
00544 
00548     class ElementIterator
00549     {
00550     public:
00556         inline Element<ELEMENT_DIM, SPACE_DIM>& operator*();
00557 
00561         inline Element<ELEMENT_DIM, SPACE_DIM>* operator->();
00562 
00568         inline bool operator!=(const AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator& rOther);
00569 
00573         inline ElementIterator& operator++();
00574 
00585         ElementIterator(AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>& rMesh,
00586                         typename std::vector<Element<ELEMENT_DIM, SPACE_DIM> *>::iterator elementIter,
00587                         bool skipDeletedElements=true);
00588 
00589     private:
00591         AbstractTetrahedralMesh& mrMesh;
00592 
00594         typename std::vector<Element<ELEMENT_DIM, SPACE_DIM> *>::iterator mElementIter;
00595 
00597         bool mSkipDeletedElements;
00598 
00602         inline bool IsAtEnd();
00603 
00607         inline bool IsAllowedElement();
00608     };
00609 
00610 };
00611 
00612 TEMPLATED_CLASS_IS_ABSTRACT_2_UNSIGNED(AbstractTetrahedralMesh)
00613 
00614 namespace boost {
00615 namespace serialization {
00622 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00623 struct version<AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM> >
00624 {
00626     CHASTE_VERSION_CONTENT(1);
00627 };
00628 } // namespace serialization
00629 } // namespace boost
00630 
00631 
00633 //      ElementIterator class implementation - most methods are inlined     //
00635 
00636 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00637 typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetElementIteratorBegin(
00638         bool skipDeletedElements)
00639 {
00640     return ElementIterator(*this, mElements.begin(), skipDeletedElements);
00641 }
00642 
00643 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00644 typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetElementIteratorEnd()
00645 {
00646     return ElementIterator(*this, mElements.end());
00647 }
00648 
00649 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00650 Element<ELEMENT_DIM, SPACE_DIM>& AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::operator*()
00651 {
00652     assert(!IsAtEnd());
00653     return **mElementIter;
00654 }
00655 
00656 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00657 Element<ELEMENT_DIM, SPACE_DIM>* AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::operator->()
00658 {
00659     assert(!IsAtEnd());
00660     return *mElementIter;
00661 }
00662 
00663 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00664 bool AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::operator!=(const AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator& rOther)
00665 {
00666     return mElementIter != rOther.mElementIter;
00667 }
00668 
00669 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00670 typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator& AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::operator++()
00671 {
00672     do
00673     {
00674         ++mElementIter;
00675     }
00676     while (!IsAtEnd() && !IsAllowedElement());
00677 
00678     return (*this);
00679 }
00680 
00681 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00682 AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::ElementIterator(
00683         AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>& rMesh,
00684         typename std::vector<Element<ELEMENT_DIM, SPACE_DIM> *>::iterator elementIter,
00685         bool skipDeletedElements)
00686     : mrMesh(rMesh),
00687       mElementIter(elementIter),
00688       mSkipDeletedElements(skipDeletedElements)
00689 {
00690     if (mrMesh.mElements.size() == 0)
00691     {
00692         // Cope with empty meshes
00693         mElementIter = mrMesh.mElements.end();
00694     }
00695     else
00696     {
00697         // Make sure we start at an allowed element
00698         if (mElementIter == mrMesh.mElements.begin() && !IsAllowedElement())
00699         {
00700             ++(*this);
00701         }
00702     }
00703 }
00704 
00705 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00706 bool AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::IsAtEnd()
00707 {
00708     return mElementIter == mrMesh.mElements.end();
00709 }
00710 
00711 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00712 bool AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::IsAllowedElement()
00713 {
00714     return !(mSkipDeletedElements && (*this)->IsDeleted());
00715 }
00716 
00717 
00718 #endif /*ABSTRACTTETRAHEDRALMESH_HPP_*/
Generated on Thu Dec 22 13:00:16 2011 for Chaste by  doxygen 1.6.3