ParMetisPartitioner.h 3.94 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(1000.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