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 
00341     Element<ELEMENT_DIM, SPACE_DIM>* GetElement(unsigned index) const;
00342 
00349     BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>* GetBoundaryElement(unsigned index) const;
00350 
00351 
00358     virtual void ConstructFromMeshReader(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader)=0;
00359 
00368     void ConstructFromMesh(AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>& rOtherMesh);
00369 
00370 
00374     BoundaryElementIterator GetBoundaryElementIteratorBegin() const;
00375 
00380     BoundaryElementIterator GetBoundaryElementIteratorEnd() const;
00381 
00390     virtual void GetInverseJacobianForElement(unsigned elementIndex, c_matrix<double, SPACE_DIM, ELEMENT_DIM>& rJacobian,
00391                                               double& rJacobianDeterminant,
00392                                               c_matrix<double, ELEMENT_DIM, SPACE_DIM>& rInverseJacobian) const;
00393 
00402     virtual void GetWeightedDirectionForBoundaryElement(unsigned elementIndex,
00403                                                         c_vector<double, SPACE_DIM>& rWeightedDirection,
00404                                                         double& rJacobianDeterminant) const;
00405 
00406 
00419     virtual void ConstructLinearMesh(unsigned width);
00420 
00421 
00422 
00438     virtual void ConstructRectangularMesh(unsigned width, unsigned height, bool stagger=true);
00439 
00440 
00441 
00453     virtual void ConstructCuboid(unsigned width, unsigned height, unsigned depth);
00454 
00455 
00456 
00467     void ConstructRegularSlabMesh(double spaceStep, double width, double height=0, double depth=0);
00468 
00469 
00470 
00477     virtual bool CalculateDesignatedOwnershipOfBoundaryElement( unsigned faceIndex );
00478 
00485     virtual bool CalculateDesignatedOwnershipOfElement( unsigned elementIndex );
00486 
00494     unsigned CalculateMaximumNodeConnectivityPerProcess() const;
00495 
00502     virtual void GetHaloNodeIndices(std::vector<unsigned>& rHaloIndices) const;
00503 
00517      void CalculateNodeExchange( std::vector<std::vector<unsigned> >& rNodesToSendPerProcess,
00518                                  std::vector<std::vector<unsigned> >& rNodesToReceivePerProcess);
00519 
00520 
00522     //                         Nested classes                           //
00524 
00525 
00529     class ElementIterator
00530     {
00531     public:
00537         inline Element<ELEMENT_DIM, SPACE_DIM>& operator*();
00538 
00542         inline Element<ELEMENT_DIM, SPACE_DIM>* operator->();
00543 
00549         inline bool operator!=(const AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator& rOther);
00550 
00554         inline ElementIterator& operator++();
00555 
00566         ElementIterator(AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>& rMesh,
00567                         typename std::vector<Element<ELEMENT_DIM, SPACE_DIM> *>::iterator elementIter,
00568                         bool skipDeletedElements=true);
00569 
00570     private:
00572         AbstractTetrahedralMesh& mrMesh;
00573 
00575         typename std::vector<Element<ELEMENT_DIM, SPACE_DIM> *>::iterator mElementIter;
00576 
00578         bool mSkipDeletedElements;
00579 
00583         inline bool IsAtEnd();
00584 
00588         inline bool IsAllowedElement();
00589     };
00590 
00591 };
00592 
00593 TEMPLATED_CLASS_IS_ABSTRACT_2_UNSIGNED(AbstractTetrahedralMesh)
00594 
00595 namespace boost {
00596 namespace serialization {
00603 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00604 struct version<AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM> >
00605 {
00607     CHASTE_VERSION_CONTENT(1);
00608 };
00609 } // namespace serialization
00610 } // namespace boost
00611 
00612 
00614 //      ElementIterator class implementation - most methods are inlined     //
00616 
00617 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00618 typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetElementIteratorBegin(
00619         bool skipDeletedElements)
00620 {
00621     return ElementIterator(*this, mElements.begin(), skipDeletedElements);
00622 }
00623 
00624 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00625 typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetElementIteratorEnd()
00626 {
00627     return ElementIterator(*this, mElements.end());
00628 }
00629 
00630 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00631 Element<ELEMENT_DIM, SPACE_DIM>& AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::operator*()
00632 {
00633     assert(!IsAtEnd());
00634     return **mElementIter;
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 bool AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::operator!=(const AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator& rOther)
00646 {
00647     return mElementIter != rOther.mElementIter;
00648 }
00649 
00650 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00651 typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator& AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::operator++()
00652 {
00653     do
00654     {
00655         ++mElementIter;
00656     }
00657     while (!IsAtEnd() && !IsAllowedElement());
00658 
00659     return (*this);
00660 }
00661 
00662 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00663 AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::ElementIterator(
00664         AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>& rMesh,
00665         typename std::vector<Element<ELEMENT_DIM, SPACE_DIM> *>::iterator elementIter,
00666         bool skipDeletedElements)
00667     : mrMesh(rMesh),
00668       mElementIter(elementIter),
00669       mSkipDeletedElements(skipDeletedElements)
00670 {
00671     if (mrMesh.mElements.size() == 0)
00672     {
00673         // Cope with empty meshes
00674         mElementIter = mrMesh.mElements.end();
00675     }
00676     else
00677     {
00678         // Make sure we start at an allowed element
00679         if (mElementIter == mrMesh.mElements.begin() && !IsAllowedElement())
00680         {
00681             ++(*this);
00682         }
00683     }
00684 }
00685 
00686 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00687 bool AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::IsAtEnd()
00688 {
00689     return mElementIter == mrMesh.mElements.end();
00690 }
00691 
00692 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00693 bool AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator::IsAllowedElement()
00694 {
00695     return !(mSkipDeletedElements && (*this)->IsDeleted());
00696 }
00697 
00698 
00699 #endif /*ABSTRACTTETRAHEDRALMESH_HPP_*/

Generated on Mon Apr 18 11:35:35 2011 for Chaste by  doxygen 1.5.5