-
Notifications
You must be signed in to change notification settings - Fork 113
Expand file tree
/
Copy pathdomain_decomposition.h
More file actions
152 lines (123 loc) · 4.68 KB
/
domain_decomposition.h
File metadata and controls
152 lines (123 loc) · 4.68 KB
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
#pragma once
#include "declare_enum.h"
namespace quda
{
// using namespace quda;
DECLARE_ENUM(DD, // name of the enum class
reset, // No domain decomposition. It sets all flags to zero.
red_black_type, // Flags used by red_black
red_active, // if red blocks are active
black_active, // if black blocks are active
no_block_hopping, // if hopping between red and black is allowed
);
// Params for domain decompation
struct DDParam {
QudaDDType type = QUDA_DD_NO;
array<bool, static_cast<int>(DD::size)> flags = {}; // the default value of all flags is 0
array<int, QUDA_MAX_DIM> block_dim = {}; // the size of the block per direction
// Default constructor
DDParam() = default;
// returns false if in use
constexpr bool operator!() const { return type == QUDA_DD_NO; }
// returns value of given flag
constexpr bool is(const DD &flag) const { return flags[(int)flag]; }
// sets given flag to true
constexpr void set(const DD &flag)
{
flags[(int)flag] = true;
if ((int)flag == (int)DD::reset) {
flags = {};
type = QUDA_DD_NO;
} else if ((int)flag >= (int)DD::red_black_type) {
type = QUDA_DD_RED_BLACK;
}
}
template <typename... Args> constexpr void set(const DD &flag, const Args &...args)
{
set(flag);
set(args...);
}
// Pretty print the args struct
void print() const
{
if (not *this) {
printfQuda("DD not in use\n");
return;
}
printfQuda("Printing DDParam\n");
for (int i = 0; i < (int)DD::size; i++)
printfQuda("flags[DD::%s] = %s\n", to_string((DD)i).c_str(), flags[i] ? "true" : "false");
for (int i = 0; i < QUDA_MAX_DIM; i++) printfQuda("block_dim[%d] = %d\n", i, static_cast<int>(block_dim[i]));
}
// Checks if this matches to given DDParam
template <typename F> inline bool check(const F &field, bool verbose = false) const
{
if (not *this) return true;
if (type == QUDA_DD_RED_BLACK) {
for (int i = 0; i < field.Ndim(); i++) {
if (block_dim[i] < 0) {
if (verbose) printfQuda("block_dim[%d] = %d is negative\n", i, block_dim[i]);
return false;
}
if (block_dim[i] > 0) {
int globalDim = comm_dim(i) * field.full_dim(i);
if (globalDim % block_dim[i] != 0) {
if (verbose) printfQuda("block_dim[%d] = %d does not divide %d \n", i, block_dim[i], globalDim);
return false;
}
if ((globalDim / block_dim[i]) % 2 != 0) {
if (verbose)
printfQuda("block_dim[%d] = %d does not divide %d **evenly** \n", i, block_dim[i], globalDim);
return false;
}
}
}
if (block_dim[0] % 2) {
if (verbose) printfQuda("block_dim[0] = %d must be even \n", block_dim[0]);
return false;
}
}
return true;
}
// Checks if this matches to given DDParam
inline bool match(const DDParam &dd, bool verbose = false) const
{
// if one of the two is not in use we return true, i.e. one of the two is a full field
if (not *this or not dd) return true;
// false if type does not match
if (type != dd.type) {
if (verbose) printfQuda("DD type do not match (%d != %d)\n", type, dd.type);
return false;
}
if (type == QUDA_DD_RED_BLACK) {
for (int i = 0; i < QUDA_MAX_DIM; i++)
if (block_dim[i] != dd.block_dim[i]) {
if (verbose) printfQuda("block_dim[%d] = %d != %d \n", i, block_dim[i], dd.block_dim[i]);
return false;
}
if (is(DD::no_block_hopping) != dd.is(DD::no_block_hopping)) {
if (verbose) printfQuda("no_block_hopping do not match.\n");
return false;
}
}
return true;
}
// Checks if this is equal to given DDParam
inline bool operator==(const DDParam &dd) const
{
// if both are not in use we return true
if (not *this and not dd) return true;
// false if type does not match
if (type != dd.type) return false;
// checking all flags matches (note this should be actually type-wise)
for (int i = 0; i < (int)DD::size; i++)
if (flags[i] != dd.flags[i]) return false;
// checking block_dim matches when needed
if (type == QUDA_DD_RED_BLACK)
for (int i = 0; i < QUDA_MAX_DIM; i++)
if (block_dim[i] != dd.block_dim[i]) return false;
return true;
}
inline bool operator!=(const DDParam &dd) const { return !(*this == dd); }
};
} // namespace quda