DistributedTetrahedralMesh.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 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 #include "DistributedTetrahedralMeshPartitionType.hpp"
00043 
00044 #define UNASSIGNED_NODE UINT_MAX
00045 
00046 /*
00047  * The following definition fixes an odd incompatibility of METIS 4.0 and Chaste. Since
00048  * the library was compiled with a plain-C compiler, it fails to link using a C++ compiler.
00049  * Note that METIS 4.0 fails to compile with g++ or icpc, so a C compiler should be used.
00050  *
00051  * Somebody had this problem before: http://www-users.cs.umn.edu/~karypis/.discus/messages/15/113.html?1119486445
00052  *
00053  * Note that it is necessary to define the function header before the #include statement.
00054 */
00055 extern "C" {
00056 extern void METIS_PartMeshNodal(int*, int*, int*, int*, int*, int*, int*, int*, int*);
00057 }
00058 #include <parmetis.h>
00059 
00067 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00068 class DistributedTetrahedralMesh : public AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM>
00069 {
00070     friend class TestDistributedTetrahedralMesh;
00071 private:
00072 
00074     unsigned mTotalNumElements;
00075 
00077     unsigned mTotalNumBoundaryElements;
00078 
00080     unsigned mTotalNumNodes;
00081 
00083     std::vector<Node<SPACE_DIM>* > mHaloNodes;
00084 
00086     std::map<unsigned, unsigned> mNodesMapping;
00087 
00089     std::map<unsigned, unsigned> mHaloNodesMapping;
00090 
00092     std::map<unsigned, unsigned> mElementsMapping;
00093 
00095     std::map<unsigned, unsigned> mBoundaryElementsMapping;
00096 
00098     DistributedTetrahedralMeshPartitionType::type mMetisPartitioning;
00099 
00101     friend class boost::serialization::access;
00108     template<class Archive>
00109     void serialize(Archive & archive, const unsigned int version)
00110     {
00111         archive & boost::serialization::base_object<AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM> >(*this);
00112     }
00113 
00114 
00122     void SetElementOwnerships();
00123 
00124 
00125 public:
00126 
00132     DistributedTetrahedralMesh(DistributedTetrahedralMeshPartitionType::type partitioningMethod=DistributedTetrahedralMeshPartitionType::METIS_LIBRARY);
00133 
00137     virtual ~DistributedTetrahedralMesh();
00138 
00145     void SetDistributedVectorFactory(DistributedVectorFactory* pFactory);
00146 
00152     void ConstructFromMeshReader(AbstractMeshReader<ELEMENT_DIM,SPACE_DIM>& rMeshReader);
00153 
00158     unsigned GetNumLocalNodes() const;
00159 
00163     unsigned GetNumHaloNodes() 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     DistributedTetrahedralMeshPartitionType::type GetPartitionType() const;
00198 
00202     unsigned GetNumBoundaryElements() const;
00203 
00208     void GetHaloNodeIndices(std::vector<unsigned>& rHaloIndices) const;
00209 
00210 
00217     bool CalculateDesignatedOwnershipOfElement( unsigned elementIndex );
00218 
00225     bool CalculateDesignatedOwnershipOfBoundaryElement( unsigned faceIndex );
00226 
00234      void ConstructLinearMesh(unsigned width);
00235 
00249     void ConstructRectangularMesh(unsigned width, unsigned height, bool stagger=true);
00250 
00261     void ConstructCuboid(unsigned width, unsigned height, unsigned depth);
00270     virtual void Scale(const double xFactor=1.0, const double yFactor=1.0, const double zFactor=1.0);
00271 
00281     Node<SPACE_DIM>* GetNodeOrHaloNode(unsigned index) const;
00282 
00290     virtual ChasteCuboid<SPACE_DIM> CalculateBoundingBox() const;
00291 
00292 protected:
00298     unsigned SolveNodeMapping(unsigned index) const;
00299 
00305     unsigned SolveElementMapping(unsigned index) const;
00306 
00312     unsigned SolveBoundaryElementMapping(unsigned index) const;
00313 private:
00314 
00320     void RegisterNode(unsigned index);
00321 
00327     void RegisterHaloNode(unsigned index);
00328 
00334     void RegisterElement(unsigned index);
00335 
00341     void RegisterBoundaryElement(unsigned index);
00342 
00343 
00355     void ComputeMeshPartitioning(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader,
00356                                  std::set<unsigned>& rNodesOwned,
00357                                  std::set<unsigned>& rHaloNodesOwned,
00358                                  std::set<unsigned>& rElementsOwned,
00359                                  std::vector<unsigned>& rProcessorsOffset);
00360 
00368     void DumbNodePartitioning(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader,
00369                               std::set<unsigned>& rNodesOwned);
00370 
00371 
00381     void MetisLibraryNodePartitioning(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader,
00382                                       std::set<unsigned>& rNodesOwned,
00383                                       std::vector<unsigned>& rProcessorsOffset);
00384 
00394     void PetscMatrixPartitioning(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader,
00395                                  std::set<unsigned>& rNodesOwned,
00396                                  std::vector<unsigned>& rProcessorsOffset);
00408      void ParMetisLibraryNodePartitioning(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader,
00409                                           std::set<unsigned>& rElementsOwned,
00410                                           std::set<unsigned>& rNodesOwned,
00411                                           std::set<unsigned>& rHaloNodesOwned,
00412                                           std::vector<unsigned>& rProcessorsOffset);
00413 
00420     void ReorderNodes();
00421 
00423     //                            Iterators                             //
00425 
00426 public:
00428     // The other iterators aren't (so only need to be dereferenced once). Consistency would be good...
00429 
00431     typedef typename std::vector<Node<SPACE_DIM> *>::const_iterator HaloNodeIterator;
00432 
00436     HaloNodeIterator GetHaloNodeIteratorBegin() const;
00437 
00441     HaloNodeIterator GetHaloNodeIteratorEnd() const;
00442 };
00443 
00444 #include "SerializationExportWrapper.hpp"
00445 EXPORT_TEMPLATE_CLASS_ALL_DIMS(DistributedTetrahedralMesh)
00446 
00447 namespace boost
00448 {
00449 namespace serialization
00450 {
00454 template<class Archive, unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00455 inline void save_construct_data(
00456     Archive & ar, const DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM> * t, const BOOST_PFTO unsigned int file_version)
00457 {
00458     unsigned num_procs = PetscTools::GetNumProcs();
00459     const DistributedTetrahedralMeshPartitionType::type partition_type = t->GetPartitionType();
00460     ar << num_procs;
00461     ar << partition_type;
00462 }
00463 
00468 template<class Archive, unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00469 inline void load_construct_data(
00470     Archive & ar, DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM> * t, const unsigned int file_version)
00471 {
00472     unsigned num_procs;
00473     DistributedTetrahedralMeshPartitionType::type partition_type;
00474 
00475     ar >> num_procs;
00476     ar >> partition_type;
00477 
00478     // Invoke inplace constructor to initialise instance
00480     //::new(t)DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>(partition_type);
00481     ::new(t)DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>(DistributedTetrahedralMeshPartitionType::DUMB);
00482 
00483     /*
00484      * The exception needs to be thrown after the call to ::new(t), or Boost will try
00485      * to free non-allocated memory when the exception is thrown.
00486      */
00487     if (DistributedVectorFactory::CheckNumberOfProcessesOnLoad() &&
00488         num_procs != PetscTools::GetNumProcs())
00489     {
00490         EXCEPTION("This archive was written for a different number of processors");
00491     }
00492 
00493 }
00494 }
00495 } // namespace ...
00496 
00497 #endif /*DISTRIBUTEDTETRAHEDRALMESH_HPP_*/
Generated on Thu Dec 22 13:00:16 2011 for Chaste by  doxygen 1.6.3