cuwave 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cuwave/__init__.py +8 -0
- cuwave/anisotropic.py +337 -0
- cuwave/boundary.py +255 -0
- cuwave/elastic.py +342 -0
- cuwave/evals.py +130 -0
- cuwave/geometry.py +226 -0
- cuwave/kernels/__init__.py +0 -0
- cuwave/kernels/anisotropic.cu +174 -0
- cuwave/kernels/anisotropic_sensitivity.cu +226 -0
- cuwave/kernels/common.cuh +95 -0
- cuwave/kernels/elastic.cu +225 -0
- cuwave/kernels/elastic_sensitivity.cu +217 -0
- cuwave/kernels/maxwell.cu +154 -0
- cuwave/kernels/maxwell_sensitivity.cu +139 -0
- cuwave/kernels/scalar.cu +164 -0
- cuwave/kernels/scalar_sensitivity.cu +140 -0
- cuwave/maxwell.py +416 -0
- cuwave/nn.py +99 -0
- cuwave/optimization.py +123 -0
- cuwave/postprocessing.py +181 -0
- cuwave/regularization.py +243 -0
- cuwave/scalar.py +224 -0
- cuwave/sensitivity.py +535 -0
- cuwave/signals.py +71 -0
- cuwave/stencils.py +48 -0
- cuwave/utils.py +472 -0
- cuwave/wave.py +518 -0
- cuwave-0.1.0.dist-info/METADATA +134 -0
- cuwave-0.1.0.dist-info/RECORD +32 -0
- cuwave-0.1.0.dist-info/WHEEL +5 -0
- cuwave-0.1.0.dist-info/licenses/LICENSE +21 -0
- cuwave-0.1.0.dist-info/top_level.txt +1 -0
|
File without changes
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
// Prepended by wave.compile_kernels: stencils.preamble, then common.cuh.
|
|
2
|
+
// Compile-time configuration this file responds to:
|
|
3
|
+
// NDIM = 1 | 2 | 3
|
|
4
|
+
// USE_DAMPING
|
|
5
|
+
|
|
6
|
+
#ifndef RADIUS
|
|
7
|
+
#define RADIUS 1 // default order 2
|
|
8
|
+
#endif
|
|
9
|
+
|
|
10
|
+
// the node block a full-radius cell reaches, and the cells a node borders
|
|
11
|
+
#define BLK (2 * RADIUS)
|
|
12
|
+
#if NDIM == 1
|
|
13
|
+
#define CELLS BLK
|
|
14
|
+
#elif NDIM == 2
|
|
15
|
+
#define CELLS (BLK * BLK)
|
|
16
|
+
#else
|
|
17
|
+
#define CELLS (BLK * BLK * BLK)
|
|
18
|
+
#endif
|
|
19
|
+
#define NLOC (CELLS * NDIM)
|
|
20
|
+
|
|
21
|
+
// position along axis d of the block entry m, axis 0 running fastest
|
|
22
|
+
__device__ __forceinline__ int block_axis(int m, const int d) {
|
|
23
|
+
#pragma unroll
|
|
24
|
+
for (int k = 0; k < NDIM; ++k)
|
|
25
|
+
if (k < d)
|
|
26
|
+
m /= BLK;
|
|
27
|
+
return m % BLK;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// ----------------------------- cell assembly helpers
|
|
31
|
+
#if NDIM == 1
|
|
32
|
+
#define AXIS_PARAMS const real_t f0, const int N0
|
|
33
|
+
#define INTERIOR_OR_RETURN \
|
|
34
|
+
const int a0 = blockIdx.x * blockDim.x + threadIdx.x; \
|
|
35
|
+
if (!(a0 > 0 && a0 < N0 - 1)) \
|
|
36
|
+
return; \
|
|
37
|
+
const int idx = a0
|
|
38
|
+
#define AXIS_GEOM const int A[1] = {a0}, S[1] = {1}, NN[1] = {N0}
|
|
39
|
+
#elif NDIM == 2
|
|
40
|
+
#define AXIS_PARAMS \
|
|
41
|
+
const real_t f0, const int N0, const real_t f1, const int N1, const int s0
|
|
42
|
+
#define INTERIOR_OR_RETURN \
|
|
43
|
+
const int a1 = blockIdx.x * blockDim.x + threadIdx.x; \
|
|
44
|
+
const int a0 = blockIdx.y * blockDim.y + threadIdx.y; \
|
|
45
|
+
if (!(a0 > 0 && a0 < N0 - 1 && a1 > 0 && a1 < N1 - 1)) \
|
|
46
|
+
return; \
|
|
47
|
+
const int idx = a0 * s0 + a1
|
|
48
|
+
#define AXIS_GEOM \
|
|
49
|
+
const int A[2] = {a0, a1}, S[2] = {s0, 1}, NN[2] = {N0, N1}
|
|
50
|
+
#elif NDIM == 3
|
|
51
|
+
#define AXIS_PARAMS \
|
|
52
|
+
const real_t f0, const int N0, const real_t f1, const int N1, const int s0, \
|
|
53
|
+
const real_t f2, const int N2, const int s1
|
|
54
|
+
#define INTERIOR_OR_RETURN \
|
|
55
|
+
const int a2 = blockIdx.x * blockDim.x + threadIdx.x; \
|
|
56
|
+
const int a1 = blockIdx.y * blockDim.y + threadIdx.y; \
|
|
57
|
+
const int a0 = blockIdx.z * blockDim.z + threadIdx.z; \
|
|
58
|
+
if (!(a0 > 0 && a0 < N0 - 1 && a1 > 0 && a1 < N1 - 1 && a2 > 0 && \
|
|
59
|
+
a2 < N2 - 1)) \
|
|
60
|
+
return; \
|
|
61
|
+
const int idx = a0 * s0 + a1 * s1 + a2
|
|
62
|
+
#define AXIS_GEOM \
|
|
63
|
+
const int A[3] = {a0, a1, a2}, S[3] = {s0, s1, 1}, NN[3] = {N0, N1, N2}
|
|
64
|
+
#endif
|
|
65
|
+
|
|
66
|
+
// A cell sits inside the domain when both its own corners do. Its radius
|
|
67
|
+
// grades down towards a wall so the stencil never passes a ghost node, and
|
|
68
|
+
// the gathering node must fall inside that graded support to take from it.
|
|
69
|
+
__device__ __forceinline__ bool cell_inside(const int c, const int *A,
|
|
70
|
+
const int *NN, const int *S,
|
|
71
|
+
int &base, int &radius,
|
|
72
|
+
int &self) {
|
|
73
|
+
base = 0;
|
|
74
|
+
self = 0;
|
|
75
|
+
radius = RADIUS;
|
|
76
|
+
bool inside = true;
|
|
77
|
+
int power = 1;
|
|
78
|
+
#pragma unroll
|
|
79
|
+
for (int d = 0; d < NDIM; ++d) {
|
|
80
|
+
const int e = block_axis(c, d) - RADIUS; // low corner, from the node
|
|
81
|
+
const int low = A[d] + e;
|
|
82
|
+
inside &= (low >= 1 && low <= NN[d] - 3);
|
|
83
|
+
radius = min(radius, min(RADIUS, min(low, NN[d] - 2 - low)));
|
|
84
|
+
base += e * S[d];
|
|
85
|
+
self += (RADIUS - 1 - e) * power;
|
|
86
|
+
power *= BLK;
|
|
87
|
+
}
|
|
88
|
+
#pragma unroll
|
|
89
|
+
for (int d = 0; d < NDIM; ++d) {
|
|
90
|
+
const int e = block_axis(c, d) - RADIUS;
|
|
91
|
+
inside &= (e >= -radius && e <= radius - 1);
|
|
92
|
+
}
|
|
93
|
+
return inside;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// offset of block entry l of cell c from the gathering node, and whether
|
|
97
|
+
// that entry falls inside the cell's graded support at all
|
|
98
|
+
__device__ __forceinline__ bool block_offset(const int c, const int l,
|
|
99
|
+
const int radius, const int *S,
|
|
100
|
+
int &off) {
|
|
101
|
+
off = 0;
|
|
102
|
+
bool carries = true;
|
|
103
|
+
#pragma unroll
|
|
104
|
+
for (int d = 0; d < NDIM; ++d) {
|
|
105
|
+
const int m = block_axis(l, d);
|
|
106
|
+
carries &= (m >= RADIUS - radius && m <= RADIUS + radius - 1);
|
|
107
|
+
off += (block_axis(c, d) - RADIUS + m - RADIUS + 1) * S[d];
|
|
108
|
+
}
|
|
109
|
+
return carries;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// -------------------------------------- kernels
|
|
113
|
+
extern "C" {
|
|
114
|
+
|
|
115
|
+
// ------------------------------------------------------------------------------------
|
|
116
|
+
__global__ void
|
|
117
|
+
fd_kernel(const real_t *__restrict__ u0, const real_t *__restrict__ u1,
|
|
118
|
+
real_t *__restrict__ u2, const real_t *__restrict__ minv,
|
|
119
|
+
const real_t *__restrict__ cell, const real_t *__restrict__ stencil,
|
|
120
|
+
#ifdef USE_DAMPING
|
|
121
|
+
const real_t *__restrict__ damping, const real_t dt,
|
|
122
|
+
#endif
|
|
123
|
+
const int cs, AXIS_PARAMS) {
|
|
124
|
+
INTERIOR_OR_RETURN;
|
|
125
|
+
AXIS_GEOM;
|
|
126
|
+
|
|
127
|
+
real_t force[NDIM];
|
|
128
|
+
#pragma unroll
|
|
129
|
+
for (int i = 0; i < NDIM; ++i)
|
|
130
|
+
force[i] = (real_t)0;
|
|
131
|
+
|
|
132
|
+
#pragma unroll
|
|
133
|
+
for (int c = 0; c < CELLS; ++c) {
|
|
134
|
+
int base, radius, self;
|
|
135
|
+
if (!cell_inside(c, A, NN, S, base, radius, self))
|
|
136
|
+
continue;
|
|
137
|
+
const real_t gc = cell[idx + base];
|
|
138
|
+
const real_t *__restrict__ table = stencil + (radius - 1) * NLOC * NLOC;
|
|
139
|
+
#pragma unroll
|
|
140
|
+
for (int l = 0; l < CELLS; ++l) {
|
|
141
|
+
int off;
|
|
142
|
+
if (!block_offset(c, l, radius, S, off))
|
|
143
|
+
continue;
|
|
144
|
+
#pragma unroll
|
|
145
|
+
for (int j = 0; j < NDIM; ++j) {
|
|
146
|
+
const real_t uj = u1[j * cs + idx + off];
|
|
147
|
+
#pragma unroll
|
|
148
|
+
for (int i = 0; i < NDIM; ++i)
|
|
149
|
+
force[i] -=
|
|
150
|
+
gc * table[(self * NDIM + i) * NLOC + l * NDIM + j] * uj;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const real_t mi = minv[idx];
|
|
156
|
+
#ifdef USE_DAMPING
|
|
157
|
+
const real_t beta = 0.5f * mi * damping[idx] * dt;
|
|
158
|
+
#pragma unroll
|
|
159
|
+
for (int i = 0; i < NDIM; ++i) {
|
|
160
|
+
const int n = i * cs + idx;
|
|
161
|
+
u2[n] = (2.f * u1[n] - u0[n] * (1.f - beta) + f0 * mi * force[i]) /
|
|
162
|
+
(1.f + beta);
|
|
163
|
+
}
|
|
164
|
+
#else
|
|
165
|
+
#pragma unroll
|
|
166
|
+
for (int i = 0; i < NDIM; ++i) {
|
|
167
|
+
const int n = i * cs + idx;
|
|
168
|
+
u2[n] = -u0[n] + 2.f * u1[n] + f0 * mi * force[i];
|
|
169
|
+
}
|
|
170
|
+
#endif
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
} // extern "C"
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
// Prepended by wave.compile_kernels: stencils.preamble, then common.cuh.
|
|
2
|
+
// Compile-time configuration this file responds to:
|
|
3
|
+
// NDIM = 1 | 2 | 3
|
|
4
|
+
|
|
5
|
+
#ifndef RADIUS
|
|
6
|
+
#define RADIUS 1 // default order 2
|
|
7
|
+
#endif
|
|
8
|
+
|
|
9
|
+
#define BLK (2 * RADIUS)
|
|
10
|
+
#if NDIM == 1
|
|
11
|
+
#define CELLS BLK
|
|
12
|
+
#elif NDIM == 2
|
|
13
|
+
#define CELLS (BLK * BLK)
|
|
14
|
+
#else
|
|
15
|
+
#define CELLS (BLK * BLK * BLK)
|
|
16
|
+
#endif
|
|
17
|
+
#define NLOC (CELLS * NDIM)
|
|
18
|
+
#define CORNERS (1 << NDIM)
|
|
19
|
+
|
|
20
|
+
// position along axis d of the block entry m, axis 0 running fastest
|
|
21
|
+
__device__ __forceinline__ int block_axis(int m, const int d) {
|
|
22
|
+
#pragma unroll
|
|
23
|
+
for (int k = 0; k < NDIM; ++k)
|
|
24
|
+
if (k < d)
|
|
25
|
+
m /= BLK;
|
|
26
|
+
return m % BLK;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// ----------------------------- cell assembly helpers
|
|
30
|
+
#if NDIM == 1
|
|
31
|
+
#define AXIS_PARAMS const int N0
|
|
32
|
+
#define INTERIOR_OR_RETURN \
|
|
33
|
+
const int a0 = blockIdx.x * blockDim.x + threadIdx.x; \
|
|
34
|
+
if (!(a0 > 0 && a0 < N0 - 1)) \
|
|
35
|
+
return; \
|
|
36
|
+
const int idx = a0
|
|
37
|
+
#define AXIS_GEOM const int A[1] = {a0}, S[1] = {1}, NN[1] = {N0}
|
|
38
|
+
#elif NDIM == 2
|
|
39
|
+
#define AXIS_PARAMS const int N0, const int N1, const int s0
|
|
40
|
+
#define INTERIOR_OR_RETURN \
|
|
41
|
+
const int a1 = blockIdx.x * blockDim.x + threadIdx.x; \
|
|
42
|
+
const int a0 = blockIdx.y * blockDim.y + threadIdx.y; \
|
|
43
|
+
if (!(a0 > 0 && a0 < N0 - 1 && a1 > 0 && a1 < N1 - 1)) \
|
|
44
|
+
return; \
|
|
45
|
+
const int idx = a0 * s0 + a1
|
|
46
|
+
#define AXIS_GEOM \
|
|
47
|
+
const int A[2] = {a0, a1}, S[2] = {s0, 1}, NN[2] = {N0, N1}
|
|
48
|
+
#elif NDIM == 3
|
|
49
|
+
#define AXIS_PARAMS \
|
|
50
|
+
const int N0, const int N1, const int s0, const int N2, const int s1
|
|
51
|
+
#define INTERIOR_OR_RETURN \
|
|
52
|
+
const int a2 = blockIdx.x * blockDim.x + threadIdx.x; \
|
|
53
|
+
const int a1 = blockIdx.y * blockDim.y + threadIdx.y; \
|
|
54
|
+
const int a0 = blockIdx.z * blockDim.z + threadIdx.z; \
|
|
55
|
+
if (!(a0 > 0 && a0 < N0 - 1 && a1 > 0 && a1 < N1 - 1 && a2 > 0 && \
|
|
56
|
+
a2 < N2 - 1)) \
|
|
57
|
+
return; \
|
|
58
|
+
const int idx = a0 * s0 + a1 * s1 + a2
|
|
59
|
+
#define AXIS_GEOM \
|
|
60
|
+
const int A[3] = {a0, a1, a2}, S[3] = {s0, s1, 1}, NN[3] = {N0, N1, N2}
|
|
61
|
+
#endif
|
|
62
|
+
|
|
63
|
+
// the cell this node is the low corner of, where its density accumulates, plus
|
|
64
|
+
// the radius that cell carries once graded down towards a wall
|
|
65
|
+
__device__ __forceinline__ bool own_cell(const int *A, const int *NN,
|
|
66
|
+
int &radius) {
|
|
67
|
+
radius = RADIUS;
|
|
68
|
+
bool inside = true;
|
|
69
|
+
#pragma unroll
|
|
70
|
+
for (int d = 0; d < NDIM; ++d) {
|
|
71
|
+
inside &= (A[d] >= 1 && A[d] <= NN[d] - 3);
|
|
72
|
+
radius = min(radius, min(RADIUS, min(A[d], NN[d] - 2 - A[d])));
|
|
73
|
+
}
|
|
74
|
+
return inside;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// block entry l of that cell, and whether it falls inside the graded support
|
|
78
|
+
__device__ __forceinline__ bool own_offset(const int l, const int radius,
|
|
79
|
+
const int *S, int &off) {
|
|
80
|
+
off = 0;
|
|
81
|
+
bool carries = true;
|
|
82
|
+
#pragma unroll
|
|
83
|
+
for (int d = 0; d < NDIM; ++d) {
|
|
84
|
+
const int m = block_axis(l, d);
|
|
85
|
+
carries &= (m >= RADIUS - radius && m <= RADIUS + radius - 1);
|
|
86
|
+
off += (m - RADIUS + 1) * S[d];
|
|
87
|
+
}
|
|
88
|
+
return carries;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// the 2**NDIM cells a node is a corner of: the material stays cell local,
|
|
92
|
+
// so the design chain rule runs over those, not the wide stencil block
|
|
93
|
+
__device__ __forceinline__ bool corner_cell(const int c, const int *A,
|
|
94
|
+
const int *NN, const int *S,
|
|
95
|
+
int &base) {
|
|
96
|
+
base = 0;
|
|
97
|
+
bool inside = true;
|
|
98
|
+
#pragma unroll
|
|
99
|
+
for (int d = 0; d < NDIM; ++d) {
|
|
100
|
+
const int bit = (c >> d) & 1;
|
|
101
|
+
inside &= bit ? (A[d] < NN[d] - 2) : (A[d] > 1);
|
|
102
|
+
base += (bit - 1) * S[d];
|
|
103
|
+
}
|
|
104
|
+
return inside;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// -------------------------------------- kernels
|
|
108
|
+
extern "C" {
|
|
109
|
+
|
|
110
|
+
// ------------------------------------------------------------------------------------
|
|
111
|
+
__global__ void
|
|
112
|
+
gradient_kernel(real_t *__restrict__ g_mass, real_t *__restrict__ g_cell,
|
|
113
|
+
const real_t *__restrict__ u0, const real_t *__restrict__ u1,
|
|
114
|
+
const real_t *__restrict__ u2, const real_t *__restrict__ l1,
|
|
115
|
+
const real_t *__restrict__ stencil, const real_t mass_factor,
|
|
116
|
+
const int cs, AXIS_PARAMS) {
|
|
117
|
+
INTERIOR_OR_RETURN;
|
|
118
|
+
AXIS_GEOM;
|
|
119
|
+
|
|
120
|
+
// dJ/dmass: no neighbour and no material load
|
|
121
|
+
real_t acc = (real_t)0;
|
|
122
|
+
#pragma unroll
|
|
123
|
+
for (int i = 0; i < NDIM; ++i) {
|
|
124
|
+
const int n = i * cs + idx;
|
|
125
|
+
acc += l1[n] * (u2[n] - 2.f * u1[n] + u0[n]);
|
|
126
|
+
}
|
|
127
|
+
g_mass[idx] -= mass_factor * acc;
|
|
128
|
+
|
|
129
|
+
// dJ/dcell: the cell stencil paired between the forward and adjoint fields
|
|
130
|
+
int radius;
|
|
131
|
+
if (!own_cell(A, NN, radius))
|
|
132
|
+
return;
|
|
133
|
+
const real_t *__restrict__ table = stencil + (radius - 1) * NLOC * NLOC;
|
|
134
|
+
real_t bilinear = (real_t)0;
|
|
135
|
+
#pragma unroll
|
|
136
|
+
for (int l = 0; l < CELLS; ++l) {
|
|
137
|
+
int lo;
|
|
138
|
+
if (!own_offset(l, radius, S, lo))
|
|
139
|
+
continue;
|
|
140
|
+
#pragma unroll
|
|
141
|
+
for (int m = 0; m < CELLS; ++m) {
|
|
142
|
+
int mo;
|
|
143
|
+
if (!own_offset(m, radius, S, mo))
|
|
144
|
+
continue;
|
|
145
|
+
#pragma unroll
|
|
146
|
+
for (int i = 0; i < NDIM; ++i)
|
|
147
|
+
#pragma unroll
|
|
148
|
+
for (int j = 0; j < NDIM; ++j)
|
|
149
|
+
bilinear += l1[i * cs + idx + lo] *
|
|
150
|
+
table[(l * NDIM + i) * NLOC + m * NDIM + j] *
|
|
151
|
+
u1[j * cs + idx + mo];
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
g_cell[idx] -= bilinear;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// ------------------------------------------------------------------------------------
|
|
158
|
+
__global__ void
|
|
159
|
+
frechet_kernel(real_t *__restrict__ acc_mass, real_t *__restrict__ acc_cell,
|
|
160
|
+
const real_t *__restrict__ u0, const real_t *__restrict__ u1,
|
|
161
|
+
const real_t *__restrict__ u2,
|
|
162
|
+
const real_t *__restrict__ stencil, const real_t ft,
|
|
163
|
+
const real_t fs, const int cs, AXIS_PARAMS) {
|
|
164
|
+
INTERIOR_OR_RETURN;
|
|
165
|
+
AXIS_GEOM;
|
|
166
|
+
|
|
167
|
+
real_t acc = (real_t)0;
|
|
168
|
+
#pragma unroll
|
|
169
|
+
for (int i = 0; i < NDIM; ++i) {
|
|
170
|
+
const int n = i * cs + idx;
|
|
171
|
+
const real_t dudt = u2[n] - u0[n];
|
|
172
|
+
acc += dudt * dudt;
|
|
173
|
+
}
|
|
174
|
+
acc_mass[idx] += ft * acc;
|
|
175
|
+
|
|
176
|
+
int radius;
|
|
177
|
+
if (!own_cell(A, NN, radius))
|
|
178
|
+
return;
|
|
179
|
+
const real_t *__restrict__ table = stencil + (radius - 1) * NLOC * NLOC;
|
|
180
|
+
real_t bilinear = (real_t)0;
|
|
181
|
+
#pragma unroll
|
|
182
|
+
for (int l = 0; l < CELLS; ++l) {
|
|
183
|
+
int lo;
|
|
184
|
+
if (!own_offset(l, radius, S, lo))
|
|
185
|
+
continue;
|
|
186
|
+
#pragma unroll
|
|
187
|
+
for (int m = 0; m < CELLS; ++m) {
|
|
188
|
+
int mo;
|
|
189
|
+
if (!own_offset(m, radius, S, mo))
|
|
190
|
+
continue;
|
|
191
|
+
#pragma unroll
|
|
192
|
+
for (int i = 0; i < NDIM; ++i)
|
|
193
|
+
#pragma unroll
|
|
194
|
+
for (int j = 0; j < NDIM; ++j)
|
|
195
|
+
bilinear += u1[i * cs + idx + lo] *
|
|
196
|
+
table[(l * NDIM + i) * NLOC + m * NDIM + j] *
|
|
197
|
+
u1[j * cs + idx + mo];
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
acc_cell[idx] += fs * bilinear;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// ------------------------------------------------------------------------------------
|
|
204
|
+
__global__ void cell_to_node_kernel(real_t *__restrict__ g_stiff,
|
|
205
|
+
const real_t *__restrict__ g_cell,
|
|
206
|
+
const real_t *__restrict__ cell,
|
|
207
|
+
const real_t *__restrict__ gamma,
|
|
208
|
+
const real_t share, AXIS_PARAMS) {
|
|
209
|
+
INTERIOR_OR_RETURN;
|
|
210
|
+
AXIS_GEOM;
|
|
211
|
+
|
|
212
|
+
// d(harmonic cell mean)/d(corner) is (cell / corner)^2 over the corner count
|
|
213
|
+
const real_t gn = gamma[idx];
|
|
214
|
+
real_t acc = (real_t)0;
|
|
215
|
+
#pragma unroll
|
|
216
|
+
for (int c = 0; c < CORNERS; ++c) {
|
|
217
|
+
int base;
|
|
218
|
+
if (corner_cell(c, A, NN, S, base)) {
|
|
219
|
+
const real_t ratio = cell[idx + base] / gn;
|
|
220
|
+
acc += g_cell[idx + base] * ratio * ratio;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
g_stiff[idx] += share * acc;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
} // extern "C"
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// Prelude prepended to every .cu by compile_kernels, after the stencil table.
|
|
2
|
+
// Compile-time configuration (set via -D flags and stencils.preamble):
|
|
3
|
+
// USE_FLOAT
|
|
4
|
+
// NDIM = 1 | 2 | 3
|
|
5
|
+
// STENCIL_RADIUS
|
|
6
|
+
// OP_COEFFS
|
|
7
|
+
// STAG_COEFFS
|
|
8
|
+
|
|
9
|
+
#ifdef USE_FLOAT
|
|
10
|
+
typedef float real_t;
|
|
11
|
+
#else
|
|
12
|
+
typedef double real_t;
|
|
13
|
+
#endif
|
|
14
|
+
|
|
15
|
+
// ----------------------------- finite difference helpers
|
|
16
|
+
#ifndef STENCIL_RADIUS
|
|
17
|
+
#define STENCIL_RADIUS 1 // default order 2
|
|
18
|
+
#endif
|
|
19
|
+
|
|
20
|
+
#if STENCIL_RADIUS == 1
|
|
21
|
+
#define OP_W(r, k) ((real_t)1)
|
|
22
|
+
#define CLOSURE(a, N) 1
|
|
23
|
+
#define SG_W(r, k) ((real_t)1)
|
|
24
|
+
#else
|
|
25
|
+
// cache
|
|
26
|
+
__constant__ real_t OP_C[STENCIL_RADIUS][STENCIL_RADIUS] = OP_COEFFS;
|
|
27
|
+
#define OP_W(r, k) OP_C[(r) - 1][(k) - 1] // 1-indexed adjustment
|
|
28
|
+
// grade radius down towards wall so the stencil never reaches past ghost nodes
|
|
29
|
+
#define CLOSURE(a, N) min(STENCIL_RADIUS, min(a, (N) - 1 - (a)))
|
|
30
|
+
__constant__ real_t SG_C[STENCIL_RADIUS][STENCIL_RADIUS] = STAG_COEFFS;
|
|
31
|
+
#define SG_W(r, k) SG_C[(r) - 1][(k) - 1] // 1-indexed adjustment
|
|
32
|
+
#endif
|
|
33
|
+
|
|
34
|
+
// --------------------------------- staggered lattice
|
|
35
|
+
#define NPAIRS (NDIM * (NDIM - 1) / 2)
|
|
36
|
+
#define NVOIGT (NDIM + NPAIRS)
|
|
37
|
+
#if NDIM == 3
|
|
38
|
+
#define PAIR_ROW(k, l) (NDIM + 3 - (k) - (l))
|
|
39
|
+
#else
|
|
40
|
+
#define PAIR_ROW(k, l) 2
|
|
41
|
+
#endif
|
|
42
|
+
|
|
43
|
+
// radius of the node-centred derivative of a staggered field, zero on the wall
|
|
44
|
+
__device__ __forceinline__ int rad_node(const int a, const int N) {
|
|
45
|
+
return min(STENCIL_RADIUS, min(a - 1, N - 2 - a));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// radius of a half-point derivative, whose taps may sit on the wall
|
|
49
|
+
__device__ __forceinline__ int rad_half(const int a, const int N) {
|
|
50
|
+
return min(STENCIL_RADIUS, min(a, N - 2 - a));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
__device__ __forceinline__ bool clamped_face(const int clamped, const int d,
|
|
54
|
+
const int side) {
|
|
55
|
+
return (clamped >> (2 * d + side)) & 1;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// ---------------------------------- transfer kernels
|
|
59
|
+
extern "C" {
|
|
60
|
+
|
|
61
|
+
// ------------------------------------------------------------------------------------
|
|
62
|
+
__global__ void
|
|
63
|
+
excitation_kernel(real_t *__restrict__ u, const real_t *__restrict__ source,
|
|
64
|
+
const int offset, const int *__restrict__ lin_index,
|
|
65
|
+
const int num_sources, const real_t *__restrict__ weight) {
|
|
66
|
+
const int idx = blockIdx.x * blockDim.x + threadIdx.x;
|
|
67
|
+
if (idx < num_sources) {
|
|
68
|
+
atomicAdd(&u[lin_index[idx]], weight[idx] * source[offset + idx]);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ------------------------------------------------------------------------------------
|
|
73
|
+
__global__ void get_signal_kernel(const real_t *__restrict__ u,
|
|
74
|
+
real_t *__restrict__ um, const int offset,
|
|
75
|
+
const int *__restrict__ lin_index,
|
|
76
|
+
const int num_sensors) {
|
|
77
|
+
const int idx = blockIdx.x * blockDim.x + threadIdx.x;
|
|
78
|
+
if (idx < num_sensors) {
|
|
79
|
+
um[offset + idx] = u[lin_index[idx]];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ------------------------------------------------------------------------------------
|
|
84
|
+
__global__ void set_signal_kernel(real_t *__restrict__ u,
|
|
85
|
+
const real_t *__restrict__ um,
|
|
86
|
+
const int offset,
|
|
87
|
+
const int *__restrict__ lin_index,
|
|
88
|
+
const int num_sensors) {
|
|
89
|
+
const int idx = blockIdx.x * blockDim.x + threadIdx.x;
|
|
90
|
+
if (idx < num_sensors) {
|
|
91
|
+
u[lin_index[idx]] = um[offset + idx];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
} // extern "C"
|