ParMetisPartitioner.h 3.93 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

35
36
namespace AMDiS {

37
  using namespace std;
38
39
40
41
42
43

  class ParMetisGraph;

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

    ~ParMetisMesh();

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

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

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

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

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

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

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

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

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

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

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

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

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

112
113
114
115
116
117
118
119
120
    /* \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;
121

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

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

126
    int nElements;
127

128
    map<int, int> elem_a2p;
129

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

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

136

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

    ~ParMetisGraph();

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

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

156
157
    void print();

158
  protected:
159
    ParMetisMesh *parMetisMesh;
160

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

    int *adjncy;
164
165
  };

166

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

176
177
    ~ParMetisPartitioner();

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

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

184
    void setItr(float value)
185
    {
186
      itr = value;
187
188
    }

189
  protected:
190
191
192
    // 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);
193
194

  protected:
195
    ParMetisMesh *parMetisMesh;
196

197
    float itr;
198
199
200
201
  };
}

#endif