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 
00079     typedef enum
00080     {
00081         DUMB=0,
00082         PARMETIS_LIBRARY=1,
00083         METIS_LIBRARY=2,
00084         PETSC_MAT_PARTITION=3 
00085     } PartitionType;
00086 
00087 private:
00088 
00090     unsigned mTotalNumElements;
00091 
00093     unsigned mTotalNumBoundaryElements;
00094 
00096     unsigned mTotalNumNodes;
00097 
00099     std::vector<Node<SPACE_DIM>* > mHaloNodes;
00100 
00102     std::map<unsigned, unsigned> mNodesMapping;
00103 
00105     std::map<unsigned, unsigned> mHaloNodesMapping;
00106 
00108     std::map<unsigned, unsigned> mElementsMapping;
00109 
00111     std::map<unsigned, unsigned> mBoundaryElementsMapping;
00112 
00114     PartitionType mMetisPartitioning;
00115 
00117     friend class boost::serialization::access;
00124     template<class Archive>
00125     void serialize(Archive & archive, const unsigned int version)
00126     {
00127         archive & boost::serialization::base_object<AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM> >(*this);
00128     }
00129 
00130 
00131 
00132 public:
00133 
00139     DistributedTetrahedralMesh(PartitionType metisPartitioning=METIS_LIBRARY);
00140 
00144     virtual ~DistributedTetrahedralMesh();
00145 
00152     void SetDistributedVectorFactory(DistributedVectorFactory* pFactory);
00153 
00159     void ConstructFromMeshReader(AbstractMeshReader<ELEMENT_DIM,SPACE_DIM>& rMeshReader);
00160 
00165     unsigned GetNumLocalNodes() const;
00166 
00171     unsigned GetNumLocalElements() const;
00172 
00177     unsigned GetNumLocalBoundaryElements() const;
00178 
00182     unsigned GetNumNodes() const;
00183 
00187     unsigned GetNumAllNodes() const;
00188 
00192     unsigned GetNumElements() const;
00193 
00199     PartitionType GetPartitionType() const;
00200 
00204     unsigned GetNumBoundaryElements() const;
00205 
00210     void GetHaloNodeIndices(std::vector<unsigned>& rHaloIndices) const;
00211 
00221     void SetElementOwnerships(unsigned lo, unsigned hi);
00222 
00223 
00230     bool CalculateDesignatedOwnershipOfElement( unsigned elementIndex );
00231 
00238     bool CalculateDesignatedOwnershipOfBoundaryElement( unsigned faceIndex );
00239 
00247      void ConstructLinearMesh(unsigned width);
00248 
00259     void ConstructRectangularMesh(unsigned width, unsigned height, bool stagger=true);
00260 
00268     void ConstructCuboid(unsigned width, unsigned height, unsigned depth);
00277     virtual void Scale(const double xFactor=1.0, const double yFactor=1.0, const double zFactor=1.0);
00278 
00288     Node<SPACE_DIM>* GetNodeOrHaloNode(unsigned index) const;
00289     
00297     virtual ChasteCuboid<SPACE_DIM> CalculateBoundingBox() const;
00298   
00299 private:
00300 
00306     void RegisterNode(unsigned index);
00307 
00313     void RegisterHaloNode(unsigned index);
00314 
00320     void RegisterElement(unsigned index);
00321 
00327     void RegisterBoundaryElement(unsigned index);
00328 
00334     unsigned SolveNodeMapping(unsigned index) const;
00335 
00341     unsigned SolveElementMapping(unsigned index) const;
00342 
00348     unsigned SolveBoundaryElementMapping(unsigned index) const;
00349 
00361     void ComputeMeshPartitioning(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader,
00362                                  std::set<unsigned>& rNodesOwned,
00363                                  std::set<unsigned>& rHaloNodesOwned,
00364                                  std::set<unsigned>& rElementsOwned,
00365                                  std::vector<unsigned>& rProcessorsOffset);
00366 
00374     void DumbNodePartitioning(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader,
00375                               std::set<unsigned>& rNodesOwned);
00376 
00377 
00387     void MetisLibraryNodePartitioning(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader,
00388                                       std::set<unsigned>& rNodesOwned,
00389                                       std::vector<unsigned>& rProcessorsOffset);
00390 
00400     void PetscMatrixPartitioning(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader,
00401                                  std::set<unsigned>& rNodesOwned,
00402                                  std::vector<unsigned>& rProcessorsOffset);
00414      void ParMetisLibraryNodePartitioning(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader,
00415                                           std::set<unsigned>& rElementsOwned,
00416                                           std::set<unsigned>& rNodesOwned,
00417                                           std::set<unsigned>& rHaloNodesOwned,
00418                                           std::vector<unsigned>& rProcessorsOffset);
00419 
00426     void ReorderNodes();
00427 };
00428 
00429 #include "SerializationExportWrapper.hpp"
00430 EXPORT_TEMPLATE_CLASS_ALL_DIMS(DistributedTetrahedralMesh)
00431 
00432 namespace boost
00433 {
00434 namespace serialization
00435 {
00439 template<class Archive, unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00440 inline void save_construct_data(
00441     Archive & ar, const DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM> * t, const BOOST_PFTO unsigned int file_version)
00442 {
00443     unsigned num_procs = PetscTools::GetNumProcs();
00444     const typename DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::PartitionType partition_type = t->GetPartitionType();
00445     ar << num_procs;
00446     ar << partition_type;
00447 }
00448 
00453 template<class Archive, unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00454 inline void load_construct_data(
00455     Archive & ar, DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM> * t, const unsigned int file_version)
00456 {
00457     unsigned num_procs;
00458     typename DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::PartitionType partition_type;
00459 
00460     ar >> num_procs;
00461     ar >> partition_type;
00462 
00463     // Invoke inplace constructor to initialise instance
00465     //::new(t)DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>(partition_type);
00466     ::new(t)DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>(DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::DUMB);
00467 
00468     /*
00469      * The exception needs to be thrown after the call to ::new(t), or Boost will try
00470      * to free non-allocated memory when the exception is thrown.
00471      */
00472     if (DistributedVectorFactory::CheckNumberOfProcessesOnLoad() &&
00473         num_procs != PetscTools::GetNumProcs())
00474     {
00475         EXCEPTION("This archive was written for a different number of processors");
00476     }
00477 
00478 }
00479 }
00480 } // namespace ...
00481 
00482 #endif /*DISTRIBUTEDTETRAHEDRALMESH_HPP_*/

Generated on Mon Nov 1 12:35:23 2010 for Chaste by  doxygen 1.5.5