forked from SCOREC/core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapfPartition.h
180 lines (162 loc) · 5.19 KB
/
apfPartition.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
* Copyright 2011 Scientific Computation Research Center
*
* This work is open source software, licensed under the terms of the
* BSD license as described in the LICENSE file in the top-level directory.
*/
#ifndef APF_PARTITION_H
#define APF_PARTITION_H
/** \file apfPartition.h
\brief tools for changing mesh partitioning */
#include "apfMesh2.h"
namespace apf {
/** \brief Splits a mesh part into many
\details usually the construction of a specific Splitter will
ask for a mesh object, which is the part to be acted upon */
class Splitter
{
public:
virtual ~Splitter() {}
/** \brief call the underlying split algorithm
\param weights a tag of one double that should be attached to all the
elements. splitters will try to balance the total element
weight of the resulting parts.
Some splitters support a weights pointer of zero, in
which case elements are weighted equally
\param tolerance a factor greater than one at such that if
max_weight < tolerance * average_weight
the splitter will consider the parts balanced
\param multiple how many output parts to generate
\returns a migration object mapping all elements in the local part
to part ids from 0 to multiple - 1.
some splitters have convenience options that will change
the resulting part ids. */
virtual Migration* split(MeshTag* weights, double tolerance,
int multiple) = 0;
};
/** \brief Load balance over all mesh parts
\details usually the construction of a specific Balancer will
ask for a mesh object, which is the mesh to be acted upon */
class Balancer
{
public:
virtual ~Balancer() {}
/** \brief call collective load balancing
\param weights a tag of one double that should be attached to all the
elements. balancers will try to balance the total element
weight of the existing parts.
Some splitters support a weights pointer of zero, in
which case elements are weighted equally
\param tolerance a factor greater than one at such that if
max_weight < tolerance * average_weight
the balancer will consider the parts balanced
\details the Balancer is responsible for running migrations
to improve the load balance by its implementation-defined
criteria. It is not allowed to modify anything besides
partitioning */
virtual void balance(MeshTag* weights, double tolerance) = 0;
};
/** \brief a map from old part ids to new part ids */
struct Remap
{
virtual int operator()(int n) = 0;
};
/** \brief divide the part id */
struct Divide : public Remap
{
Divide(int n):by(n) {}
int operator()(int n) {return n / by;}
private:
int by;
};
/** \brief multiply the part id */
struct Multiply : public Remap
{
Multiply(int n):by(n) {}
int operator()(int n) {return n * by;}
private:
int by;
};
/** \brief return part id modulo n */
struct Modulo : public Remap
{
Modulo(int n):by(n) {}
int operator()(int n) {return n % by;}
private:
int by;
};
/** \brief inverse of apf::Modulo */
struct Unmodulo : public Remap
{
Unmodulo(int original, int factor)
{
offset = (original / factor) * factor;
}
int operator()(int n) {return n + offset;}
private:
int offset;
};
/** \brief map to nearest multiple of n */
struct Round : public Remap
{
Round(int n):factor(n) {}
int operator()(int n) {return (n / factor) * factor;}
private:
int factor;
};
struct Expand : public Remap
{
Expand(int nin, int nout):
quotient(nout / nin),
remainder(nout % nin)
{}
int operator()(int in)
{
if (in < remainder)
return in * quotient + in;
return in * quotient + remainder;
}
bool shouldOutBeIn(int out)
{
if (out < remainder * (quotient + 1))
return out % (quotient + 1) == 0;
return (out - remainder * (quotient + 1)) % quotient == 0;
}
private:
int quotient;
int remainder;
};
struct Contract : public Remap
{
Contract(int nin, int nout):
quotient(nout / nin),
remainder(nout % nin)
{}
int operator()(int out)
{
if (out < remainder * (quotient + 1))
return out / (quotient + 1);
return (out - remainder * (quotient + 1)) / quotient + remainder;
}
bool isValid(int out)
{
if (out < remainder * (quotient + 1))
return out % (quotient + 1) == 0;
return (out - remainder * (quotient + 1)) % quotient == 0;
}
private:
int quotient;
int remainder;
};
/** \brief remap all part ids in the mesh structure
\details when using sub-group partitioning schemes
or splitting meshes (see Parma_SplitPartition or apf::Splitter),
it is useful to be able to update all partition model
structures in a mesh to reflect a transition from one
partitioning scheme to the next.
this function applies the given map to all part ids in the
remote copies, resident sets, and matching using the apf::Mesh2
interface */
void remapPartition(apf::Mesh2* m, Remap& remap);
}
#endif