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 private:
00293 
00299     void RegisterNode(unsigned index);
00300 
00306     void RegisterHaloNode(unsigned index);
00307 
00313     void RegisterElement(unsigned index);
00314 
00320     void RegisterBoundaryElement(unsigned index);
00321 
00327     unsigned SolveNodeMapping(unsigned index) const;
00328 
00334     unsigned SolveElementMapping(unsigned index) const;
00335 
00341     unsigned SolveBoundaryElementMapping(unsigned index) const;
00342 
00354     void ComputeMeshPartitioning(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader,
00355                                  std::set<unsigned>& rNodesOwned,
00356                                  std::set<unsigned>& rHaloNodesOwned,
00357                                  std::set<unsigned>& rElementsOwned,
00358                                  std::vector<unsigned>& rProcessorsOffset);
00359 
00367     void DumbNodePartitioning(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader,
00368                               std::set<unsigned>& rNodesOwned);
00369 
00370 
00380     void MetisLibraryNodePartitioning(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader,
00381                                       std::set<unsigned>& rNodesOwned,
00382                                       std::vector<unsigned>& rProcessorsOffset);
00383 
00393     void PetscMatrixPartitioning(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader,
00394                                  std::set<unsigned>& rNodesOwned,
00395                                  std::vector<unsigned>& rProcessorsOffset);
00407      void ParMetisLibraryNodePartitioning(AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader,
00408                                           std::set<unsigned>& rElementsOwned,
00409                                           std::set<unsigned>& rNodesOwned,
00410                                           std::set<unsigned>& rHaloNodesOwned,
00411                                           std::vector<unsigned>& rProcessorsOffset);
00412 
00419     void ReorderNodes();
00420     
00422     //                            Iterators                             //
00424 
00425 public:
00427     // The other iterators aren't (so only need to be dereferenced once). Consistency would be good...
00428 
00430     typedef typename std::vector<Node<SPACE_DIM> *>::const_iterator HaloNodeIterator;
00431     
00435     HaloNodeIterator GetHaloNodeIteratorBegin() const;
00436 
00440     HaloNodeIterator GetHaloNodeIteratorEnd() const;
00441 };
00442 
00443 #include "SerializationExportWrapper.hpp"
00444 EXPORT_TEMPLATE_CLASS_ALL_DIMS(DistributedTetrahedralMesh)
00445 
00446 namespace boost
00447 {
00448 namespace serialization
00449 {
00453 template<class Archive, unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00454 inline void save_construct_data(
00455     Archive & ar, const DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM> * t, const BOOST_PFTO unsigned int file_version)
00456 {
00457     unsigned num_procs = PetscTools::GetNumProcs();
00458     const DistributedTetrahedralMeshPartitionType::type partition_type = t->GetPartitionType();
00459     ar << num_procs;
00460     ar << partition_type;
00461 }
00462 
00467 template<class Archive, unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00468 inline void load_construct_data(
00469     Archive & ar, DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM> * t, const unsigned int file_version)
00470 {
00471     unsigned num_procs;
00472     DistributedTetrahedralMeshPartitionType::type partition_type;
00473 
00474     ar >> num_procs;
00475     ar >> partition_type;
00476 
00477     // Invoke inplace constructor to initialise instance
00479     //::new(t)DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>(partition_type);
00480     ::new(t)DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>(DistributedTetrahedralMeshPartitionType::DUMB);
00481 
00482     /*
00483      * The exception needs to be thrown after the call to ::new(t), or Boost will try
00484      * to free non-allocated memory when the exception is thrown.
00485      */
00486     if (DistributedVectorFactory::CheckNumberOfProcessesOnLoad() &&
00487         num_procs != PetscTools::GetNumProcs())
00488     {
00489         EXCEPTION("This archive was written for a different number of processors");
00490     }
00491 
00492 }
00493 }
00494 } // namespace ...
00495 
00496 #endif /*DISTRIBUTEDTETRAHEDRALMESH_HPP_*/

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