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 
00053 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00054 class AbstractConductivityTensors;
00055 
00060 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00061 class AbstractTetrahedralMesh : public AbstractMesh<ELEMENT_DIM, SPACE_DIM>
00062 {
00063     friend class AbstractConductivityTensors<ELEMENT_DIM, SPACE_DIM>; //A class which needs a global to local element mapping
00064 
00065 protected:
00069     bool mMeshIsLinear;
00070 
00071 private:
00079     virtual unsigned SolveElementMapping(unsigned index) const = 0;
00080 
00088     virtual unsigned SolveBoundaryElementMapping(unsigned index) const = 0;
00089 
00091     friend class boost::serialization::access;
00092 
00104     template<class Archive>
00105     void save(Archive & archive, const unsigned int version) const
00106     {
00107         archive & boost::serialization::base_object<AbstractMesh<ELEMENT_DIM,SPACE_DIM> >(*this);
00108         archive & mMeshIsLinear;
00109         // Create a mesh writer pointing to the correct file and directory.
00110         TrianglesMeshWriter<ELEMENT_DIM,SPACE_DIM> mesh_writer(ArchiveLocationInfo::GetArchiveRelativePath(),
00111                                                                ArchiveLocationInfo::GetMeshFilename(),
00112                                                                false);
00113         //Binary meshes have similar content to the original Triangle/Tetgen format, but take up less space on disk
00114         mesh_writer.SetWriteFilesAsBinary();
00115 
00116         // Archive the mesh permutation, so we can just copy the original mesh files whenever possible.
00117         bool permutation_available = (this->rGetNodePermutation().size() != 0);
00118         archive & permutation_available;
00119 
00120         if( permutation_available )
00121         {
00122             const std::vector<unsigned>& rPermutation = this->rGetNodePermutation();
00123             archive & rPermutation;
00124         }
00125 
00126         if (!this->IsMeshOnDisk())
00127         {
00128             mesh_writer.WriteFilesUsingMesh(*(const_cast<AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>*>(this)));
00129         }
00130         else
00131         {
00132             unsigned order_of_element = (mMeshIsLinear?1:2);
00133             unsigned& order_of_boundary_element = order_of_element;
00134 
00135             // Mesh in disc, copy it to the archiving folder
00136             std::string original_file=this->GetMeshFileBaseName();
00137             GenericMeshReader<ELEMENT_DIM, SPACE_DIM> original_mesh_reader(original_file, order_of_element, order_of_boundary_element);
00138 
00139             if (original_mesh_reader.IsFileFormatBinary())
00140             {
00141                 // Mesh is in binary format, we can just copy the files across ignoring the mesh reader
00142                 std::stringstream cp_command;
00143                 cp_command << "for filename in `ls " << this->GetMeshFileBaseName() << ".*`; do " <<
00144                                  "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)
00145                                  "cp $filename " << ArchiveLocationInfo::GetArchiveDirectory() << ArchiveLocationInfo::GetMeshFilename() <<".$extension;" <<
00146                               "done";
00147 
00148                 if (PetscTools::AmMaster())
00149                 {
00150                     MPIABORTIFNON0(system, cp_command.str());
00151                 }
00152             }
00153             else
00154             {
00155                 // Mesh in text format, use the mesh writer to "binarise" it
00156                 mesh_writer.WriteFilesUsingMeshReader(original_mesh_reader);
00157             }
00158         }
00159 
00160         // Make sure that the files are written before slave processes proceed
00161         PetscTools::Barrier("AbstractTetrahedralMesh::save");
00162     }
00163 
00170     template<class Archive>
00171     void load(Archive & archive, const unsigned int version)
00172     {
00173         archive & boost::serialization::base_object<AbstractMesh<ELEMENT_DIM,SPACE_DIM> >(*this);
00174         archive & mMeshIsLinear;
00175 
00176         bool permutation_available=false;
00177         std::vector<unsigned> permutation;
00178 
00179         if(version>0)
00180         {
00181             archive & permutation_available;
00182 
00183             if( permutation_available )
00184             {
00185                 archive & permutation;
00186             }
00187         }
00188 
00189         // Store the DistributedVectorFactory loaded from the archive
00190         DistributedVectorFactory* p_factory = this->mpDistributedVectorFactory;
00191         this->mpDistributedVectorFactory = NULL;
00192         // Check whether we're migrating, or if we can use the original partition for the mesh
00193         DistributedVectorFactory* p_our_factory = NULL;
00194         if (p_factory)
00195         {
00196             p_our_factory = p_factory->GetOriginalFactory();
00197         }
00198         if (p_our_factory && p_our_factory->GetNumProcs() == p_factory->GetNumProcs())
00199         {
00200             // Specify the node distribution
00201             this->SetDistributedVectorFactory(p_our_factory);
00202         }
00203         else
00204         {
00205             // Migrating; let the mesh re-partition if it likes
00207             p_our_factory = NULL;
00208         }
00209 
00210         if (mMeshIsLinear)
00211         {
00212             //I am a linear mesh
00213             TrianglesMeshReader<ELEMENT_DIM,SPACE_DIM> mesh_reader(ArchiveLocationInfo::GetArchiveDirectory() + ArchiveLocationInfo::GetMeshFilename());
00214 
00215             if (permutation_available)
00216             {
00217                 mesh_reader.SetNodePermutation(permutation);
00218             }
00219 
00220             this->ConstructFromMeshReader(mesh_reader);
00221         }
00222         else
00223         {
00224             //I am a quadratic mesh and need quadratic information from the reader
00225             TrianglesMeshReader<ELEMENT_DIM,SPACE_DIM> mesh_reader(ArchiveLocationInfo::GetArchiveDirectory() + ArchiveLocationInfo::GetMeshFilename(), 2, 2);
00226             this->ConstructFromMeshReader(mesh_reader);
00227         }
00228 
00229         // Make sure we're using the correct vector factory
00230         if (p_factory)
00231         {
00232             if (!this->mpDistributedVectorFactory)
00233             {
00234                 // If we're not using a DistributedTetrahedralMesh, ConstructFromMeshReader won't set
00235                 // this->mpDistributedVectorFactory.
00236                 this->mpDistributedVectorFactory = p_factory;
00237             }
00238             else
00239             {
00240                 // We need to update p_factory to match this->mpDistributedVectorFactory, and then use
00241                 // p_factory, since the rest of the code (e.g. AbstractCardiacPde) will be using p_factory.
00242                 p_factory->SetFromFactory(this->mpDistributedVectorFactory);
00243                 if (p_our_factory != this->mpDistributedVectorFactory)
00244                 {
00245                     // Avoid memory leak
00246                     delete this->mpDistributedVectorFactory;
00247                 }
00248                 this->mpDistributedVectorFactory = p_factory;
00249             }
00250         }
00251     }
00252     BOOST_SERIALIZATION_SPLIT_MEMBER()
00253 
00254 
00255 protected:  // Give access of these variables to subclasses
00256 
00258     std::vector<Element<ELEMENT_DIM, SPACE_DIM> *> mElements;
00259 
00261     std::vector<BoundaryElement<ELEMENT_DIM-1, SPACE_DIM> *> mBoundaryElements;
00262 
00270     void SetElementOwnerships();
00271 public:
00272 
00274     //                            Iterators                             //
00276 
00278     typedef typename std::vector<BoundaryElement<ELEMENT_DIM-1, SPACE_DIM> *>::const_iterator BoundaryElementIterator;
00279 
00281     class ElementIterator;
00282 
00288     inline ElementIterator GetElementIteratorBegin(bool skipDeletedElements=true);
00289 
00293     inline ElementIterator GetElementIteratorEnd();
00294 
00296     //                             Methods                              //
00298 
00302     AbstractTetrahedralMesh();
00303 
00307     virtual ~AbstractTetrahedralMesh();
00308 
00309 
00313     virtual unsigned GetNumElements() const;
00314 
00318     virtual unsigned GetNumLocalElements() const;
00319 
00323     virtual unsigned GetNumBoundaryElements() const;
00324 
00328     unsigned GetNumAllElements() const;
00329 
00333     unsigned GetNumAllBoundaryElements() const;
00334 
00340     virtual unsigned GetNumCableElements() const;
00341 
00348     Element<ELEMENT_DIM, SPACE_DIM>* GetElement(unsigned index) const;
00349 
00356     BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>* GetBoundaryElement(unsigned index) const;
00357 
00358 
00365     virtual void ConstructFromMeshReader(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader)=0;
00366 
00375     void ConstructFromMesh(AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>& rOtherMesh);
00376 
00377 
00381     BoundaryElementIterator GetBoundaryElementIteratorBegin() const;
00382 
00387     BoundaryElementIterator GetBoundaryElementIteratorEnd() const;
00388 
00397     virtual void GetInverseJacobianForElement(unsigned elementIndex, c_matrix<double, SPACE_DIM, ELEMENT_DIM>& rJacobian,
00398                                               double& rJacobianDeterminant,
00399                                               c_matrix<double, ELEMENT_DIM, SPACE_DIM>& rInverseJacobian) const;
00400 
00409     virtual void GetWeightedDirectionForBoundaryElement(unsigned elementIndex,
00410                                                         c_vector<double, SPACE_DIM>& rWeightedDirection,
00411                                                         double& rJacobianDeterminant) const;
00412 
00413 
00426     virtual void ConstructLinearMesh(unsigned width);
00427 
00428 
00429 
00445     virtual void ConstructRectangularMesh(unsigned width, unsigned height, bool stagger=true);
00446 
00447 
00448 
00460     virtual void ConstructCuboid(unsigned width, unsigned height, unsigned depth);
00461 
00462 
00463 
00474     void ConstructRegularSlabMesh(double spaceStep, double width, double height=0, double depth=0);
00475 
00476 
00477 
00484     virtual bool CalculateDesignatedOwnershipOfBoundaryElement( unsigned faceIndex );
00485 
00492     virtual bool CalculateDesignatedOwnershipOfElement( unsigned elementIndex );
00493 
00501     unsigned CalculateMaximumNodeConnectivityPerProcess() const;
00502 
00509     virtual void GetHaloNodeIndices(std::vector<unsigned>& rHaloIndices) const;
00510 
00524      void CalculateNodeExchange( std::vector<std::vector<unsigned> >& rNodesToSendPerProcess,
00525                                  std::vector<std::vector<unsigned> >& rNodesToReceivePerProcess);
00526 
00527 
00529     //                         Nested classes                           //
00531 
00532 
00536     class ElementIterator
00537     {
00538     public:
00544         inline Element<ELEMENT_DIM, SPACE_DIM>& operator*();
00545 
00549         inline Element<ELEMENT_DIM, SPACE_DIM>* operator->();
00550 
00556         inline bool operator!=(const AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator& rOther);
00557 
00561         inline ElementIterator& operator++();
00562 
00573         ElementIterator(AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>& rMesh,
00574                         typename std::vector<Element<ELEMENT_DIM, SPACE_DIM> *>::iterator elementIter,
00575                         bool skipDeletedElements=true);
00576 
00577     private:
00579         AbstractTetrahedralMesh& mrMesh;
00580 
00582         typename std::vector<Element<ELEMENT_DIM, SPACE_DIM> *>::iterator mElementIter;
00583 
00585         bool mSkipDeletedElements;
00586 
00590         inline bool IsAtEnd();
00591 
00595         inline bool IsAllowedElement();
00596     };
00597 
00598 };
00599 
00600 TEMPLATED_CLASS_IS_ABSTRACT_2_UNSIGNED(AbstractTetrahedralMesh)
00601 
00602 namespace boost {
00603 namespace serialization {
00610 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00611 struct version<AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM> >
00612 {
00614     CHASTE_VERSION_CONTENT(1);
00615 };
00616 } // namespace serialization
00617 } // namespace boost
00618 
00619 
00621 //      ElementIterator class implementation - most methods are inlined     //
00623 
00624 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00625 typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetElementIteratorBegin(
00626         bool skipDeletedElements)
00627 {
00628     return ElementIterator(*this, mElements.begin(), skipDeletedElements);
00629 }
00630 
00631 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00632 typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetElementIteratorEnd()
00633 {
00634     return ElementIterator(*this, mElements.end());
00635 }
00636 
00637 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00638 Element<ELEMENT_DIM, SPACE_DIM>& AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::operator*()
00639 {
00640     assert(!IsAtEnd());
00641     return **mElementIter;
00642 }
00643 
00644 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00645 Element<ELEMENT_DIM, SPACE_DIM>* AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::operator->()
00646 {
00647     assert(!IsAtEnd());
00648     return *mElementIter;
00649 }
00650 
00651 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00652 bool AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::operator!=(const AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator& rOther)
00653 {
00654     return mElementIter != rOther.mElementIter;
00655 }
00656 
00657 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00658 typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator& AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::operator++()
00659 {
00660     do
00661     {
00662         ++mElementIter;
00663     }
00664     while (!IsAtEnd() && !IsAllowedElement());
00665 
00666     return (*this);
00667 }
00668 
00669 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00670 AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::ElementIterator(
00671         AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>& rMesh,
00672         typename std::vector<Element<ELEMENT_DIM, SPACE_DIM> *>::iterator elementIter,
00673         bool skipDeletedElements)
00674     : mrMesh(rMesh),
00675       mElementIter(elementIter),
00676       mSkipDeletedElements(skipDeletedElements)
00677 {
00678     if (mrMesh.mElements.size() == 0)
00679     {
00680         // Cope with empty meshes
00681         mElementIter = mrMesh.mElements.end();
00682     }
00683     else
00684     {
00685         // Make sure we start at an allowed element
00686         if (mElementIter == mrMesh.mElements.begin() && !IsAllowedElement())
00687         {
00688             ++(*this);
00689         }
00690     }
00691 }
00692 
00693 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00694 bool AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::IsAtEnd()
00695 {
00696     return mElementIter == mrMesh.mElements.end();
00697 }
00698 
00699 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00700 bool AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::IsAllowedElement()
00701 {
00702     return !(mSkipDeletedElements && (*this)->IsDeleted());
00703 }
00704 
00705 
00706 #endif /*ABSTRACTTETRAHEDRALMESH_HPP_*/

Generated on Tue May 31 14:31:48 2011 for Chaste by  doxygen 1.5.5