DistributedTetrahedralMesh.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 DISTRIBUTEDTETRAHEDRALMESH_HPP_
00030 #define DISTRIBUTEDTETRAHEDRALMESH_HPP_
00031 
00032 #include <map>
00033 #include <vector>
00034 #include <set>
00035 
00036 #include "ChasteSerialization.hpp"
00037 #include <boost/serialization/base_object.hpp>
00038 
00039 #include "AbstractTetrahedralMesh.hpp"
00040 #include "Node.hpp"
00041 #include "AbstractMeshReader.hpp"
00042 
00043 #define UNASSIGNED_NODE UINT_MAX
00044 
00045 /*
00046  * The following definition fixes an odd incompatibility of METIS 4.0 and Chaste. Since
00047  * the library was compiled with a plain-C compiler, it fails to link using a C++ compiler.
00048  * Note that METIS 4.0 fails to compile with g++ or icpc, so a C compiler should be used.
00049  *
00050  * Somebody had this problem before: http://www-users.cs.umn.edu/~karypis/.discus/messages/15/113.html?1119486445
00051  *
00052  * Note that it is necessary to define the function header before the #include statement.
00053 */
00054 extern "C" {
00055 extern void METIS_PartMeshNodal(int*, int*, int*, int*, int*, int*, int*, int*, int*);
00056 };
00057 #include <parmetis.h>
00058 
00066 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00067 class DistributedTetrahedralMesh : public AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM>
00068 {
00069     friend class TestDistributedTetrahedralMesh;
00070 
00071 public:
00072 
00078     typedef enum
00079     {
00080         DUMB=0,
00081         PARMETIS_LIBRARY=1,
00082         METIS_LIBRARY=2 
00083     } PartitionType;
00084 
00085 private:
00086 
00088     unsigned mTotalNumElements;
00089 
00091     unsigned mTotalNumBoundaryElements;
00092 
00094     unsigned mTotalNumNodes;
00095 
00097     std::vector<Node<SPACE_DIM>* > mHaloNodes;
00098 
00100     std::map<unsigned, unsigned> mNodesMapping;
00101 
00103     std::map<unsigned, unsigned> mHaloNodesMapping;
00104 
00106     std::map<unsigned, unsigned> mElementsMapping;
00107 
00109     std::map<unsigned, unsigned> mBoundaryElementsMapping;
00110 
00112     PartitionType mMetisPartitioning;
00113 
00115     friend class boost::serialization::access;
00122     template<class Archive>
00123     void serialize(Archive & archive, const unsigned int version)
00124     {
00125         archive & boost::serialization::base_object<AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM> >(*this);
00126     }
00127 
00128 
00129 
00130 public:
00131 
00137     DistributedTetrahedralMesh(PartitionType metisPartitioning=METIS_LIBRARY);
00138 
00142     virtual ~DistributedTetrahedralMesh();
00143 
00150     void SetDistributedVectorFactory(DistributedVectorFactory* pFactory);
00151 
00157     void ConstructFromMeshReader(AbstractMeshReader<ELEMENT_DIM,SPACE_DIM>& rMeshReader);
00158 
00163     unsigned GetNumLocalNodes() const;
00164 
00169     unsigned GetNumLocalElements() const;
00170 
00175     unsigned GetNumLocalBoundaryElements() const;
00176 
00180     unsigned GetNumNodes() const;
00181 
00185     unsigned GetNumAllNodes() const;
00186 
00190     unsigned GetNumElements() const;
00191 
00197     PartitionType GetPartitionType() const;
00198 
00202     unsigned GetNumBoundaryElements() const;
00203 
00208     void GetHaloNodeIndices(std::vector<unsigned>& rHaloIndices) const;
00209 
00219     void SetElementOwnerships(unsigned lo, unsigned hi);
00220 
00221 
00228     bool CalculateDesignatedOwnershipOfElement( unsigned elementIndex );
00229 
00236     bool CalculateDesignatedOwnershipOfBoundaryElement( unsigned faceIndex );
00237 
00245      void ConstructLinearMesh(unsigned width);
00246 
00257     void ConstructRectangularMesh(unsigned width, unsigned height, bool stagger=true);
00258 
00266     void ConstructCuboid(unsigned width, unsigned height, unsigned depth);
00275     virtual void Scale(const double xFactor=1.0, const double yFactor=1.0, const double zFactor=1.0);
00276 
00286     Node<SPACE_DIM>* GetAnyNode(unsigned index) const;
00287 
00288 private:
00289 
00295     void RegisterNode(unsigned index);
00296 
00302     void RegisterHaloNode(unsigned index);
00303 
00309     void RegisterElement(unsigned index);
00310 
00316     void RegisterBoundaryElement(unsigned index);
00317 
00323     unsigned SolveNodeMapping(unsigned index) const;
00324 
00330     unsigned SolveElementMapping(unsigned index) const;
00331 
00337     unsigned SolveBoundaryElementMapping(unsigned index) const;
00338 
00350     void ComputeMeshPartitioning(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader,
00351                                  std::set<unsigned>& rNodesOwned,
00352                                  std::set<unsigned>& rHaloNodesOwned,
00353                                  std::set<unsigned>& rElementsOwned,
00354                                  std::vector<unsigned>& rProcessorsOffset);
00355 
00363     void DumbNodePartitioning(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader,
00364                               std::set<unsigned>& rNodesOwned);
00365 
00366 
00376     void MetisLibraryNodePartitioning(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader,
00377                                       std::set<unsigned>& rNodesOwned,
00378                                       std::vector<unsigned>& rProcessorsOffset);
00379 
00391      void ParMetisLibraryNodePartitioning(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader,
00392                                           std::set<unsigned>& rElementsOwned,
00393                                           std::set<unsigned>& rNodesOwned,
00394                                           std::set<unsigned>& rHaloNodesOwned,
00395                                           std::vector<unsigned>& rProcessorsOffset);
00396 
00403     void ReorderNodes();
00404 };
00405 
00406 #include "SerializationExportWrapper.hpp"
00407 EXPORT_TEMPLATE_CLASS_ALL_DIMS(DistributedTetrahedralMesh);
00408 
00409 namespace boost
00410 {
00411 namespace serialization
00412 {
00416 template<class Archive, unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00417 inline void save_construct_data(
00418     Archive & ar, const DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM> * t, const BOOST_PFTO unsigned int file_version)
00419 {
00420     unsigned num_procs = PetscTools::GetNumProcs();
00421     const typename DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::PartitionType partition_type = t->GetPartitionType();
00422     ar << num_procs;
00423     ar << partition_type;
00424 }
00425 
00430 template<class Archive, unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00431 inline void load_construct_data(
00432     Archive & ar, DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM> * t, const unsigned int file_version)
00433 {
00434     unsigned num_procs;
00435     typename DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::PartitionType partition_type;
00436 
00437     ar >> num_procs;
00438     ar >> partition_type;
00439 
00440     // Invoke inplace constructor to initialise instance
00442     //::new(t)DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>(partition_type);
00443     ::new(t)DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>(DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::DUMB);
00444 
00445     /*
00446      * The exception needs to be thrown after the call to ::new(t), or Boost will try
00447      * to free non-allocated memory when the exception is thrown.
00448      */
00449     if (DistributedVectorFactory::CheckNumberOfProcessesOnLoad() &&
00450         num_procs != PetscTools::GetNumProcs())
00451     {
00452         EXCEPTION("This archive was written for a different number of processors");
00453     }
00454 
00455 }
00456 }
00457 } // namespace ...
00458 
00459 #endif /*DISTRIBUTEDTETRAHEDRALMESH_HPP_*/

Generated by  doxygen 1.6.2