ParMetisPartitioner.h 3.95 KB
Newer Older
1 2 3 4
// ============================================================================
// ==                                                                        ==
// == AMDiS - Adaptive multidimensional simulations                          ==
// ==                                                                        ==
5
// ==  http://www.amdis-fem.org                                              ==
6 7
// ==                                                                        ==
// ============================================================================
8 9 10 11 12 13 14 15 16 17 18 19
//
// Software License for AMDiS
//
// Copyright (c) 2010 Dresden University of Technology 
// All rights reserved.
// Authors: Simon Vey, Thomas Witkowski et al.
//
// This file is part of AMDiS
//
// See also license.opensource.txt in the distribution.


20 21 22

/** \file ParMetisPartitioner.h */

23 24
#ifndef AMDIS_PARMETIS_PARTITIONER_H
#define AMDIS_PARMETIS_PARTITIONER_H
25 26 27

#include <map>
#include <set>
28 29 30
#include <parmetis.h>
#include <mpi.h>

31
#include "AMDiS_fwd.h"
32
#include "Global.h"
33
#include "parallel/MeshPartitioner.h"
34
#include "parallel/ParallelDofMapping.h"
35

36 37
namespace AMDiS {

38
  using namespace std;
39 40 41 42 43 44

  class ParMetisGraph;

  class ParMetisMesh
  {
  public:
45
    ParMetisMesh(Mesh *mesh, MPI::Intracomm *comm, 
46
		 map<int, bool>& elementInRank,
47
		 DofMap *mapLocalGlobal);
48 49 50

    ~ParMetisMesh();

51 52
    inline void setParMetisIndex(int amdisIndex, int parMetisIndex) 
    {
Thomas Witkowski's avatar
Thomas Witkowski committed
53
      elem_a2p[amdisIndex] = parMetisIndex + 1;
54
    }
55

56 57
    inline int getParMetisIndex(int amdisIndex) 
    {
Thomas Witkowski's avatar
Thomas Witkowski committed
58
      int result = elem_a2p[amdisIndex];
59 60
      TEST_EXIT(result > 0)("invalid index\n");
      return result - 1;
61
    }
62

63 64
    inline void setAMDiSIndex(int parMetisIndex, int amdisIndex) 
    {
Thomas Witkowski's avatar
Thomas Witkowski committed
65
      elem_p2a[parMetisIndex] = amdisIndex;
66
    }
67

68 69
    inline int getAMDiSIndex(int parMetisIndex) 
    {
Thomas Witkowski's avatar
Thomas Witkowski committed
70
      return elem_p2a[parMetisIndex];
71
    }
72

73 74
    inline int *getAMDiSIndices() 
    {
Thomas Witkowski's avatar
Thomas Witkowski committed
75
      return elem_p2a;
76
    }
77

78 79
    inline int *getElementPtr() 
    { 
Thomas Witkowski's avatar
Thomas Witkowski committed
80
      return eptr; 
81
    }
82

83 84
    inline int *getElementInd() 
    { 
Thomas Witkowski's avatar
Thomas Witkowski committed
85
      return eind; 
86
    }
87

88 89
    inline int *getElementDist() 
    { 
90
      return elmdist; 
91
    }
92

93 94
    inline int getDim() 
    { 
Thomas Witkowski's avatar
Thomas Witkowski committed
95
      return dim; 
96
    }
97

98 99
    inline float *getXYZ() 
    { 
Thomas Witkowski's avatar
Thomas Witkowski committed
100
      return xyz; 
101
    }
102

103 104
    inline int getNumElements() 
    { 
105
      return nElements; 
106
    }
107 108

  protected:
Thomas Witkowski's avatar
Thomas Witkowski committed
109
    int *eptr;
110

Thomas Witkowski's avatar
Thomas Witkowski committed
111
    int *eind;
112

113 114 115 116 117 118 119 120 121
    /* \brief
     * Array that specifies the distribution of the mesh elements.
     *
     * elmdist[0] = 0;
     * elmdist[1] = number of elements of proc 0;
     * elmdist[2] = elmdist[1] + number of elements of proc 1;
     *    ...
     */
    int *elmdist;
122

Thomas Witkowski's avatar
Thomas Witkowski committed
123
    int dim;
124

Thomas Witkowski's avatar
Thomas Witkowski committed
125
    float *xyz;
126

127
    int nElements;
128

129
    map<int, int> elem_a2p;
130

Thomas Witkowski's avatar
Thomas Witkowski committed
131
    int *elem_p2a;
132

133
    /// The MPI communicator that should be used for mesh partition.
134
    MPI::Intracomm *mpiComm;
135 136
  };

137

138 139 140 141
  class ParMetisGraph
  {
  public:
    ParMetisGraph(ParMetisMesh *parMetisMesh,
142
		  MPI::Intracomm *comm,
143 144 145 146
		  int ncommonnodes = -1);

    ~ParMetisGraph();

147 148
    inline int *getXAdj() 
    { 
Thomas Witkowski's avatar
Thomas Witkowski committed
149
      return xadj; 
150
    }
151

152 153
    inline int *getAdjncy() 
    { 
Thomas Witkowski's avatar
Thomas Witkowski committed
154
      return adjncy; 
155
    }
156

157 158
    void print();

159
  protected:
160
    ParMetisMesh *parMetisMesh;
161

Thomas Witkowski's avatar
Thomas Witkowski committed
162 163 164
    int *xadj;

    int *adjncy;
165 166
  };

167

168
  class ParMetisPartitioner : public MeshPartitioner
169 170
  {
  public:
171
    ParMetisPartitioner(MPI::Intracomm *comm)
172
      : MeshPartitioner(comm),
173
        parMetisMesh(NULL),
174
	itr(1000000.0)
175
    {}
176

177 178
    ~ParMetisPartitioner();

179
    /// \ref MeshPartitioner::partition
180 181
    bool partition(map<int, double> &elemWeights,
		   PartitionMode mode = INITIAL);
182

183 184
    void createPartitionMap(map<int, int>& partitionMap);

185
    void setItr(double value)
186
    {
187
      itr = value;
188 189
    }

190
  protected:
191 192 193
    // Returns true, if the mesh partitioning could be distributed. If this is not the
    // case, i.e., because there are empty partitions, the function returns false.
    bool distributePartitioning(int *part);
194 195

  protected:
196
    ParMetisMesh *parMetisMesh;
197

198
    double itr;
199 200 201 202
  };
}

#endif