cuwave 0.2.0__tar.gz → 0.3.0__tar.gz
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-0.2.0 → cuwave-0.3.0}/PKG-INFO +1 -1
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/kernels/common.cuh +16 -0
- cuwave-0.3.0/cuwave/kernels/scalar_sensitivity.cu +302 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/optimization.py +9 -7
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/scalar.py +47 -2
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/sensitivity.py +52 -13
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/wave.py +31 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave.egg-info/PKG-INFO +1 -1
- {cuwave-0.2.0 → cuwave-0.3.0}/pyproject.toml +1 -1
- cuwave-0.2.0/cuwave/kernels/scalar_sensitivity.cu +0 -140
- {cuwave-0.2.0 → cuwave-0.3.0}/LICENSE +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/README.md +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/__init__.py +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/anisotropic.py +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/boundary.py +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/elastic.py +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/evals.py +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/geometry.py +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/kernels/__init__.py +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/kernels/anisotropic.cu +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/kernels/anisotropic_sensitivity.cu +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/kernels/elastic.cu +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/kernels/elastic_sensitivity.cu +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/kernels/maxwell.cu +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/kernels/maxwell_sensitivity.cu +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/kernels/scalar.cu +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/maxwell.py +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/nn.py +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/postprocessing.py +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/regularization.py +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/signals.py +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/stencils.py +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave/utils.py +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave.egg-info/SOURCES.txt +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave.egg-info/dependency_links.txt +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave.egg-info/requires.txt +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/cuwave.egg-info/top_level.txt +0 -0
- {cuwave-0.2.0 → cuwave-0.3.0}/setup.cfg +0 -0
|
@@ -69,6 +69,22 @@ excitation_kernel(real_t *__restrict__ u, const real_t *__restrict__ source,
|
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
// ------------------------------------------------------------------------------------
|
|
73
|
+
__global__ void adjoint_excitation_kernel(
|
|
74
|
+
real_t *__restrict__ l2, const real_t *__restrict__ signal,
|
|
75
|
+
const int offset, const int *__restrict__ lin_index, const int num_sensors,
|
|
76
|
+
const real_t *__restrict__ weight, real_t *__restrict__ g_mass,
|
|
77
|
+
const real_t *__restrict__ u1, const real_t mf) {
|
|
78
|
+
const int idx = blockIdx.x * blockDim.x + threadIdx.x;
|
|
79
|
+
if (idx < num_sensors) {
|
|
80
|
+
const int n = lin_index[idx];
|
|
81
|
+
const real_t load = weight[idx] * signal[offset + idx];
|
|
82
|
+
atomicAdd(&l2[n], load);
|
|
83
|
+
// the injected load is part of the second time difference of lambda
|
|
84
|
+
atomicAdd(&g_mass[n], -mf * u1[n] * load);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
72
88
|
// ------------------------------------------------------------------------------------
|
|
73
89
|
__global__ void get_signal_kernel(const real_t *__restrict__ u,
|
|
74
90
|
real_t *__restrict__ um, const int offset,
|
|
@@ -0,0 +1,302 @@
|
|
|
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
|
+
// ------------------------------- interior guard macros
|
|
7
|
+
#if NDIM == 1
|
|
8
|
+
#define INTERIOR_OR_RETURN \
|
|
9
|
+
const int a0 = blockIdx.x * blockDim.x + threadIdx.x; \
|
|
10
|
+
if (!(a0 > 0 && a0 < N0 - 1)) \
|
|
11
|
+
return; \
|
|
12
|
+
const int idx = a0
|
|
13
|
+
#define AXIS_RADII const int r0 = CLOSURE(a0, N0)
|
|
14
|
+
#define AXIS_OFFSETS const int o0 = 1
|
|
15
|
+
#elif NDIM == 2
|
|
16
|
+
#define INTERIOR_OR_RETURN \
|
|
17
|
+
const int a1 = blockIdx.x * blockDim.x + threadIdx.x; \
|
|
18
|
+
const int a0 = blockIdx.y * blockDim.y + threadIdx.y; \
|
|
19
|
+
if (!(a0 > 0 && a0 < N0 - 1 && a1 > 0 && a1 < N1 - 1)) \
|
|
20
|
+
return; \
|
|
21
|
+
const int idx = a0 * s0 + a1
|
|
22
|
+
#define AXIS_RADII const int r0 = CLOSURE(a0, N0), r1 = CLOSURE(a1, N1)
|
|
23
|
+
#define AXIS_OFFSETS const int o0 = s0, o1 = 1
|
|
24
|
+
#elif NDIM == 3
|
|
25
|
+
#define INTERIOR_OR_RETURN \
|
|
26
|
+
const int a2 = blockIdx.x * blockDim.x + threadIdx.x; \
|
|
27
|
+
const int a1 = blockIdx.y * blockDim.y + threadIdx.y; \
|
|
28
|
+
const int a0 = blockIdx.z * blockDim.z + threadIdx.z; \
|
|
29
|
+
if (!(a0 > 0 && a0 < N0 - 1 && a1 > 0 && a1 < N1 - 1 && a2 > 0 && \
|
|
30
|
+
a2 < N2 - 1)) \
|
|
31
|
+
return; \
|
|
32
|
+
const int idx = a0 * s0 + a1 * s1 + a2
|
|
33
|
+
#define AXIS_RADII \
|
|
34
|
+
const int r0 = CLOSURE(a0, N0), r1 = CLOSURE(a1, N1), r2 = CLOSURE(a2, N2)
|
|
35
|
+
#define AXIS_OFFSETS const int o0 = s0, o1 = s1, o2 = 1
|
|
36
|
+
#endif
|
|
37
|
+
|
|
38
|
+
// ---------------------------------- gradient helpers
|
|
39
|
+
__device__ __forceinline__ real_t stiffness_gradient_axis(
|
|
40
|
+
const real_t *__restrict__ u1, const real_t *__restrict__ l1,
|
|
41
|
+
const real_t *__restrict__ stiff, const int idx, const int s,
|
|
42
|
+
const real_t uc, const real_t lc, const real_t sc, const real_t factor,
|
|
43
|
+
const int r) {
|
|
44
|
+
const real_t sp = stiff[idx + s]; // plus of sc
|
|
45
|
+
const real_t sm = stiff[idx - s]; // minus of sc
|
|
46
|
+
const real_t dgp = sp * sp / ((sc + sp) * (sc + sp)); // d(harmonic mean)/dsc
|
|
47
|
+
const real_t dgm = sm * sm / ((sc + sm) * (sc + sm)); // d(harmonic mean)/dsc
|
|
48
|
+
real_t Dp = OP_W(r, 1) * (u1[idx + s] - uc); // inner grad
|
|
49
|
+
real_t Dm = OP_W(r, 1) * (uc - u1[idx - s]); // inner grad
|
|
50
|
+
#pragma unroll
|
|
51
|
+
for (int k = 2; k <= STENCIL_RADIUS; ++k)
|
|
52
|
+
if (k <= r) {
|
|
53
|
+
Dp += OP_W(r, k) * (u1[idx + k * s] - u1[idx - (k - 1) * s]);
|
|
54
|
+
Dm += OP_W(r, k) * (u1[idx + (k - 1) * s] - u1[idx - k * s]);
|
|
55
|
+
}
|
|
56
|
+
return factor * (dgp * Dp * (l1[idx + s] - lc) +
|
|
57
|
+
dgm * Dm * (lc - l1[idx - s])); // both cells of the node
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// the adjoint step's flux divergence and the stiffness gradient of one axis,
|
|
61
|
+
// sharing the cell stiffnesses
|
|
62
|
+
__device__ __forceinline__ void adjoint_gradient_axis(
|
|
63
|
+
const real_t *__restrict__ u1, const real_t *__restrict__ l1,
|
|
64
|
+
const real_t *__restrict__ stiff, const int idx, const int s,
|
|
65
|
+
const real_t uc, const real_t lc, const real_t sc, const real_t factor,
|
|
66
|
+
const int r, real_t &div_l, real_t &g) {
|
|
67
|
+
const real_t sp = stiff[idx + s]; // plus of sc
|
|
68
|
+
const real_t sm = stiff[idx - s]; // minus of sc
|
|
69
|
+
const real_t gp = sc * sp / (sc + sp); // harmonic mean
|
|
70
|
+
const real_t gm = sc * sm / (sc + sm); // harmonic mean
|
|
71
|
+
const real_t dgp = sp * sp / ((sc + sp) * (sc + sp)); // d(harmonic mean)/dsc
|
|
72
|
+
const real_t dgm = sm * sm / ((sc + sm) * (sc + sm)); // d(harmonic mean)/dsc
|
|
73
|
+
const real_t lp = l1[idx + s];
|
|
74
|
+
const real_t lm = l1[idx - s];
|
|
75
|
+
real_t Lp = OP_W(r, 1) * (lp - lc); // inner grad of lambda
|
|
76
|
+
real_t Lm = OP_W(r, 1) * (lc - lm); // inner grad of lambda
|
|
77
|
+
real_t Dp = OP_W(r, 1) * (u1[idx + s] - uc); // inner grad of u
|
|
78
|
+
real_t Dm = OP_W(r, 1) * (uc - u1[idx - s]); // inner grad of u
|
|
79
|
+
#pragma unroll
|
|
80
|
+
for (int k = 2; k <= STENCIL_RADIUS; ++k)
|
|
81
|
+
if (k <= r) {
|
|
82
|
+
Lp += OP_W(r, k) * (l1[idx + k * s] - l1[idx - (k - 1) * s]);
|
|
83
|
+
Lm += OP_W(r, k) * (l1[idx + (k - 1) * s] - l1[idx - k * s]);
|
|
84
|
+
Dp += OP_W(r, k) * (u1[idx + k * s] - u1[idx - (k - 1) * s]);
|
|
85
|
+
Dm += OP_W(r, k) * (u1[idx + (k - 1) * s] - u1[idx - k * s]);
|
|
86
|
+
}
|
|
87
|
+
div_l += factor * (Lp * gp - Lm * gm); // the step's flux divergence
|
|
88
|
+
g += factor * (dgp * Dp * (lp - lc) + dgm * Dm * (lc - lm));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// byte-identical to scalar.cu: each file is its own compilation unit
|
|
92
|
+
__device__ __forceinline__ real_t flux_divergence_axis(
|
|
93
|
+
const real_t *__restrict__ u1, const real_t *__restrict__ stiff,
|
|
94
|
+
const int idx, const int s, const real_t uc, const real_t sc,
|
|
95
|
+
const real_t factor, const int r) {
|
|
96
|
+
const real_t sp = stiff[idx + s]; // plus of sc
|
|
97
|
+
const real_t sm = stiff[idx - s]; // minus of sc
|
|
98
|
+
const real_t gp = sc * sp / (sc + sp); // harmonic mean
|
|
99
|
+
const real_t gm = sc * sm / (sc + sm); // harmonic mean
|
|
100
|
+
real_t Dp = OP_W(r, 1) * (u1[idx + s] - uc); // initialization: inner grad
|
|
101
|
+
real_t Dm = OP_W(r, 1) * (uc - u1[idx - s]); // initialization: inner grad
|
|
102
|
+
#pragma unroll
|
|
103
|
+
for (int k = 2; k <= STENCIL_RADIUS; ++k)
|
|
104
|
+
if (k <= r) {
|
|
105
|
+
Dp +=
|
|
106
|
+
OP_W(r, k) * (u1[idx + k * s] - u1[idx - (k - 1) * s]); // inner grad
|
|
107
|
+
Dm +=
|
|
108
|
+
OP_W(r, k) * (u1[idx + (k - 1) * s] - u1[idx - k * s]); // inner grad
|
|
109
|
+
}
|
|
110
|
+
return factor * (Dp * gp - Dm * gm); // outer grad (incl. inner grad)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// -------------------------------------- kernels
|
|
114
|
+
extern "C" {
|
|
115
|
+
|
|
116
|
+
// ------------------------------------------------------------------------------------
|
|
117
|
+
__global__ void
|
|
118
|
+
gradient_kernel(real_t *__restrict__ g_mass, real_t *__restrict__ g_stiff,
|
|
119
|
+
const real_t *__restrict__ u0, const real_t *__restrict__ u1,
|
|
120
|
+
const real_t *__restrict__ u2, const real_t *__restrict__ l1,
|
|
121
|
+
const real_t *__restrict__ stiff, const real_t inv_dt2,
|
|
122
|
+
const real_t F0, const int N0
|
|
123
|
+
#if NDIM >= 2
|
|
124
|
+
,
|
|
125
|
+
const real_t F1, const int N1, const int s0
|
|
126
|
+
#endif
|
|
127
|
+
#if NDIM >= 3
|
|
128
|
+
,
|
|
129
|
+
const real_t F2, const int N2, const int s1
|
|
130
|
+
#endif
|
|
131
|
+
) {
|
|
132
|
+
INTERIOR_OR_RETURN;
|
|
133
|
+
AXIS_RADII;
|
|
134
|
+
|
|
135
|
+
const real_t uc = u1[idx];
|
|
136
|
+
const real_t lc = l1[idx];
|
|
137
|
+
|
|
138
|
+
// dJ/dmass: no neighbour and no material load
|
|
139
|
+
g_mass[idx] -= inv_dt2 * lc * (u2[idx] - 2.f * uc + u0[idx]);
|
|
140
|
+
|
|
141
|
+
// dJ/dstiff: scalar.cu's harmonic cell mean differentiated in place
|
|
142
|
+
const real_t sc = stiff[idx];
|
|
143
|
+
#if NDIM == 1
|
|
144
|
+
const real_t g =
|
|
145
|
+
stiffness_gradient_axis(u1, l1, stiff, idx, 1, uc, lc, sc, F0, r0);
|
|
146
|
+
#elif NDIM == 2
|
|
147
|
+
const real_t g =
|
|
148
|
+
stiffness_gradient_axis(u1, l1, stiff, idx, s0, uc, lc, sc, F0, r0) +
|
|
149
|
+
stiffness_gradient_axis(u1, l1, stiff, idx, 1, uc, lc, sc, F1, r1);
|
|
150
|
+
#elif NDIM == 3
|
|
151
|
+
const real_t g =
|
|
152
|
+
stiffness_gradient_axis(u1, l1, stiff, idx, s0, uc, lc, sc, F0, r0) +
|
|
153
|
+
stiffness_gradient_axis(u1, l1, stiff, idx, s1, uc, lc, sc, F1, r1) +
|
|
154
|
+
stiffness_gradient_axis(u1, l1, stiff, idx, 1, uc, lc, sc, F2, r2);
|
|
155
|
+
#endif
|
|
156
|
+
g_stiff[idx] -= g;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// ------------------------------------------------------------------------------------
|
|
160
|
+
__global__ void frechet_kernel(real_t *__restrict__ acc_mass,
|
|
161
|
+
real_t *__restrict__ acc_stiff,
|
|
162
|
+
const real_t *__restrict__ u0,
|
|
163
|
+
const real_t *__restrict__ u1,
|
|
164
|
+
const real_t *__restrict__ u2, const real_t ft,
|
|
165
|
+
const real_t f0, const int N0
|
|
166
|
+
#if NDIM >= 2
|
|
167
|
+
,
|
|
168
|
+
const real_t f1, const int N1, const int s0
|
|
169
|
+
#endif
|
|
170
|
+
#if NDIM >= 3
|
|
171
|
+
,
|
|
172
|
+
const real_t f2, const int N2, const int s1
|
|
173
|
+
#endif
|
|
174
|
+
) {
|
|
175
|
+
INTERIOR_OR_RETURN;
|
|
176
|
+
AXIS_OFFSETS;
|
|
177
|
+
|
|
178
|
+
const real_t dudt = u2[idx] - u0[idx];
|
|
179
|
+
acc_mass[idx] += ft * dudt * dudt;
|
|
180
|
+
|
|
181
|
+
const real_t g0 = u1[idx + o0] - u1[idx - o0];
|
|
182
|
+
real_t sum = f0 * g0 * g0;
|
|
183
|
+
#if NDIM >= 2
|
|
184
|
+
const real_t g1 = u1[idx + o1] - u1[idx - o1];
|
|
185
|
+
sum += f1 * g1 * g1;
|
|
186
|
+
#endif
|
|
187
|
+
#if NDIM >= 3
|
|
188
|
+
const real_t g2 = u1[idx + o2] - u1[idx - o2];
|
|
189
|
+
sum += f2 * g2 * g2;
|
|
190
|
+
#endif
|
|
191
|
+
acc_stiff[idx] += sum;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ------------------------------------------------------------------------------------
|
|
195
|
+
__global__ void adjoint_gradient_kernel(
|
|
196
|
+
real_t *__restrict__ l0, const real_t *__restrict__ l1,
|
|
197
|
+
real_t *__restrict__ g_mass, real_t *__restrict__ g_stiff,
|
|
198
|
+
const real_t *__restrict__ u1, const real_t *__restrict__ stiff,
|
|
199
|
+
const real_t *__restrict__ minv, const int derive_inertia,
|
|
200
|
+
#ifdef USE_DAMPING
|
|
201
|
+
const real_t *__restrict__ damping, const real_t dt,
|
|
202
|
+
#endif
|
|
203
|
+
const real_t mf, const real_t f0, const int N0
|
|
204
|
+
#if NDIM >= 2
|
|
205
|
+
,
|
|
206
|
+
const real_t f1, const int N1, const int s0
|
|
207
|
+
#endif
|
|
208
|
+
#if NDIM >= 3
|
|
209
|
+
,
|
|
210
|
+
const real_t f2, const int N2, const int s1
|
|
211
|
+
#endif
|
|
212
|
+
) {
|
|
213
|
+
INTERIOR_OR_RETURN;
|
|
214
|
+
AXIS_RADII;
|
|
215
|
+
|
|
216
|
+
const real_t uc = u1[idx];
|
|
217
|
+
const real_t lc = l1[idx];
|
|
218
|
+
const real_t sc = stiff[idx];
|
|
219
|
+
real_t div_l = 0, g = 0;
|
|
220
|
+
#if NDIM == 1
|
|
221
|
+
adjoint_gradient_axis(u1, l1, stiff, idx, 1, uc, lc, sc, f0, r0, div_l, g);
|
|
222
|
+
#elif NDIM == 2
|
|
223
|
+
adjoint_gradient_axis(u1, l1, stiff, idx, s0, uc, lc, sc, f0, r0, div_l, g);
|
|
224
|
+
adjoint_gradient_axis(u1, l1, stiff, idx, 1, uc, lc, sc, f1, r1, div_l, g);
|
|
225
|
+
#elif NDIM == 3
|
|
226
|
+
adjoint_gradient_axis(u1, l1, stiff, idx, s0, uc, lc, sc, f0, r0, div_l, g);
|
|
227
|
+
adjoint_gradient_axis(u1, l1, stiff, idx, s1, uc, lc, sc, f1, r1, div_l, g);
|
|
228
|
+
adjoint_gradient_axis(u1, l1, stiff, idx, 1, uc, lc, sc, f2, r2, div_l, g);
|
|
229
|
+
#endif
|
|
230
|
+
|
|
231
|
+
const real_t mi = derive_inertia ? 1.f / sc : minv[idx];
|
|
232
|
+
const real_t lo = l0[idx];
|
|
233
|
+
#ifdef USE_DAMPING
|
|
234
|
+
const real_t beta = 0.5f * mi * damping[idx] * dt;
|
|
235
|
+
const real_t ln = (2.f * lc - lo * (1.f - beta) + mi * div_l) / (1.f + beta);
|
|
236
|
+
#else
|
|
237
|
+
const real_t ln = -lo + 2.f * lc + mi * div_l;
|
|
238
|
+
#endif
|
|
239
|
+
l0[idx] = ln;
|
|
240
|
+
// dJ/dmass by parts in time: u against the second difference of lambda
|
|
241
|
+
g_mass[idx] -= mf * uc * (ln - 2.f * lc + lo);
|
|
242
|
+
g_stiff[idx] -= mf * g;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// ------------------------------------------------------------------------------------
|
|
246
|
+
__global__ void superposed_kernel(
|
|
247
|
+
const real_t *__restrict__ u0, const real_t *__restrict__ u1,
|
|
248
|
+
real_t *__restrict__ u2, real_t *__restrict__ acc_mass,
|
|
249
|
+
real_t *__restrict__ acc_stiff, const real_t *__restrict__ stiff,
|
|
250
|
+
const real_t *__restrict__ minv, const int derive_inertia, const real_t ft,
|
|
251
|
+
const real_t fs, const real_t f0, const int N0
|
|
252
|
+
#if NDIM >= 2
|
|
253
|
+
,
|
|
254
|
+
const real_t f1, const int N1, const int s0
|
|
255
|
+
#endif
|
|
256
|
+
#if NDIM >= 3
|
|
257
|
+
,
|
|
258
|
+
const real_t f2, const int N2, const int s1
|
|
259
|
+
#endif
|
|
260
|
+
) {
|
|
261
|
+
INTERIOR_OR_RETURN;
|
|
262
|
+
AXIS_RADII;
|
|
263
|
+
AXIS_OFFSETS;
|
|
264
|
+
|
|
265
|
+
const real_t uc = u1[idx];
|
|
266
|
+
const real_t sc = stiff[idx];
|
|
267
|
+
#if NDIM == 1
|
|
268
|
+
const real_t laplacian =
|
|
269
|
+
flux_divergence_axis(u1, stiff, idx, 1, uc, sc, f0, r0);
|
|
270
|
+
#elif NDIM == 2
|
|
271
|
+
const real_t laplacian =
|
|
272
|
+
flux_divergence_axis(u1, stiff, idx, s0, uc, sc, f0, r0) +
|
|
273
|
+
flux_divergence_axis(u1, stiff, idx, 1, uc, sc, f1, r1);
|
|
274
|
+
#elif NDIM == 3
|
|
275
|
+
const real_t laplacian =
|
|
276
|
+
flux_divergence_axis(u1, stiff, idx, s0, uc, sc, f0, r0) +
|
|
277
|
+
flux_divergence_axis(u1, stiff, idx, s1, uc, sc, f1, r1) +
|
|
278
|
+
flux_divergence_axis(u1, stiff, idx, 1, uc, sc, f2, r2);
|
|
279
|
+
#endif
|
|
280
|
+
|
|
281
|
+
// the mass density of the triplet before, whose oldest slot u2 still holds
|
|
282
|
+
const real_t dudt = uc - u2[idx];
|
|
283
|
+
acc_mass[idx] += ft * dudt * dudt;
|
|
284
|
+
|
|
285
|
+
// the stiffness density of this triplet, its middle slot being u1
|
|
286
|
+
const real_t g0 = u1[idx + o0] - u1[idx - o0];
|
|
287
|
+
real_t sum = f0 * g0 * g0;
|
|
288
|
+
#if NDIM >= 2
|
|
289
|
+
const real_t g1 = u1[idx + o1] - u1[idx - o1];
|
|
290
|
+
sum += f1 * g1 * g1;
|
|
291
|
+
#endif
|
|
292
|
+
#if NDIM >= 3
|
|
293
|
+
const real_t g2 = u1[idx + o2] - u1[idx - o2];
|
|
294
|
+
sum += f2 * g2 * g2;
|
|
295
|
+
#endif
|
|
296
|
+
acc_stiff[idx] += fs * sum;
|
|
297
|
+
|
|
298
|
+
const real_t mi = derive_inertia ? 1.f / sc : minv[idx];
|
|
299
|
+
u2[idx] = -u0[idx] + 2.f * uc + mi * laplacian;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
} // extern "C"
|
|
@@ -68,24 +68,26 @@ class Lbfgs:
|
|
|
68
68
|
project: applied to every trial, a constraint on the design variables.
|
|
69
69
|
|
|
70
70
|
Returns:
|
|
71
|
-
(design, cost, alpha, trials) of the accepted trial
|
|
72
|
-
|
|
71
|
+
(design, cost, alpha, trials) of the accepted trial. A search that reaches
|
|
72
|
+
`min_alpha` without a decrease returns `x` and `cost` unchanged and drops
|
|
73
|
+
the secant pairs, so the next call restarts from the scaled gradient.
|
|
73
74
|
"""
|
|
74
75
|
step = self.step(x, grad) - x
|
|
75
76
|
if not self.pairs:
|
|
76
77
|
step = step * (self.first_step / float(abs(step).max()))
|
|
77
|
-
slope = float(grad.ravel() @ step.ravel())
|
|
78
78
|
|
|
79
79
|
alpha, trials = 1.0, 0
|
|
80
80
|
while True:
|
|
81
81
|
trial = project(x + alpha * step)
|
|
82
82
|
trial_cost = f(trial)
|
|
83
83
|
trials += 1
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
):
|
|
84
|
+
# projected displacement: a clipped trial moves less than alpha * step
|
|
85
|
+
slope = float(grad.ravel() @ (trial - x).ravel())
|
|
86
|
+
if trial_cost <= cost + self.armijo * slope:
|
|
88
87
|
return trial, trial_cost, alpha, trials
|
|
88
|
+
if alpha <= self.min_alpha:
|
|
89
|
+
self.pairs.clear()
|
|
90
|
+
return x, cost, alpha, trials
|
|
89
91
|
alpha *= self.shrink
|
|
90
92
|
|
|
91
93
|
def step(self, x: cpt.NDArray, grad: cpt.NDArray) -> cpt.NDArray:
|
|
@@ -67,6 +67,7 @@ class PressureWave(Simulation):
|
|
|
67
67
|
return args
|
|
68
68
|
|
|
69
69
|
gradient_names = ("mass", "stiff") # the fields the adjoint differentiates
|
|
70
|
+
fuses_adjoint = True # one kernel steps the adjoint and accumulates both gradients
|
|
70
71
|
|
|
71
72
|
def gradient_fields(self, mat: dict) -> dict[str, cpt.NDArray]:
|
|
72
73
|
"""Zeroed accumulators the adjoint kernels add into, one per material field."""
|
|
@@ -103,15 +104,59 @@ class PressureWave(Simulation):
|
|
|
103
104
|
|
|
104
105
|
return gradient_step
|
|
105
106
|
|
|
107
|
+
def define_adjoint_gradient(
|
|
108
|
+
self, kernels: cp.RawModule, mat: dict, grads: dict
|
|
109
|
+
) -> Callable:
|
|
110
|
+
"""Closure stepping the adjoint `l0` over `l1`, accumulating both gradients of `l1`."""
|
|
111
|
+
adjoint_gradient_kernel = kernels.get_function("adjoint_gradient_kernel")
|
|
112
|
+
grid, block = grid_block(self)
|
|
113
|
+
args = [None, None, grads["mass"], grads["stiff"], None]
|
|
114
|
+
args += [*self.step_kernel_args(mat), self.dtype(self.adjoint_mass_factor())]
|
|
115
|
+
args += axis_geometry(self, self.step_factors())
|
|
116
|
+
|
|
117
|
+
def adjoint_gradient_step(l0, l1, u1):
|
|
118
|
+
args[0], args[1], args[4] = l0, l1, u1
|
|
119
|
+
adjoint_gradient_kernel(grid, block, args)
|
|
120
|
+
return l0
|
|
121
|
+
|
|
122
|
+
return adjoint_gradient_step
|
|
123
|
+
|
|
124
|
+
def define_superposed(
|
|
125
|
+
self, kernels: cp.RawModule, mat: dict, accs: dict, sign: float
|
|
126
|
+
) -> Callable:
|
|
127
|
+
"""Closure stepping (u0, u1, u2), adding `sign` times the stiffness density of this triplet and the mass density of the one before."""
|
|
128
|
+
superposed_kernel = kernels.get_function("superposed_kernel")
|
|
129
|
+
grid, block = grid_block(self)
|
|
130
|
+
factors = self.step_factors()
|
|
131
|
+
# both per-axis factors go as 1 / dx**2, so their ratio is one number
|
|
132
|
+
ratios = [-sign / (2.0 * d) ** 2 / float(f) for d, f in zip(self.dx, factors)]
|
|
133
|
+
if not np.allclose(ratios, ratios[0]):
|
|
134
|
+
raise ValueError(
|
|
135
|
+
f"step factors {factors} are not proportional to 1 / dx**2"
|
|
136
|
+
)
|
|
137
|
+
args = [None, None, None, accs["mass"], accs["stiff"]]
|
|
138
|
+
args += [*self.step_kernel_args(mat), self.dtype(sign / (2.0 * self.dt) ** 2)]
|
|
139
|
+
args += [self.dtype(ratios[0]), *axis_geometry(self, factors)]
|
|
140
|
+
massless = list(args)
|
|
141
|
+
massless[8] = self.dtype(0.0)
|
|
142
|
+
|
|
143
|
+
def superposed_step(u0, u1, u2, mass=True):
|
|
144
|
+
launch = args if mass else massless
|
|
145
|
+
launch[0], launch[1], launch[2] = u0, u1, u2
|
|
146
|
+
superposed_kernel(grid, block, launch)
|
|
147
|
+
return u2
|
|
148
|
+
|
|
149
|
+
return superposed_step
|
|
150
|
+
|
|
106
151
|
def define_frechet(
|
|
107
|
-
self, kernels: cp.RawModule, accs: dict, sign: float
|
|
152
|
+
self, kernels: cp.RawModule, accs: dict, sign: float, stiffness: bool = True
|
|
108
153
|
) -> Callable:
|
|
109
154
|
"""Closure accumulating both Frechet densities of one field triplet, times `sign`."""
|
|
110
155
|
# sign is fixed per pass, so it is folded into the factors, not recomputed
|
|
111
156
|
frechet_kernel = kernels.get_function("frechet_kernel")
|
|
112
157
|
grid, block = grid_block(self)
|
|
113
158
|
# the stiffness density enters negated, so the epilogue scales both alike
|
|
114
|
-
factors = [self.dtype(-sign / (2.0 * d) ** 2) for d in self.dx]
|
|
159
|
+
factors = [self.dtype(-sign * stiffness / (2.0 * d) ** 2) for d in self.dx]
|
|
115
160
|
args = [accs["mass"], accs["stiff"], None, None, None]
|
|
116
161
|
args += [self.dtype(sign / (2.0 * self.dt) ** 2), *axis_geometry(self, factors)]
|
|
117
162
|
|
|
@@ -25,6 +25,7 @@ from .wave import (
|
|
|
25
25
|
Source,
|
|
26
26
|
Window,
|
|
27
27
|
compile_kernels,
|
|
28
|
+
define_adjoint_excitation,
|
|
28
29
|
define_excitation,
|
|
29
30
|
define_get_signal,
|
|
30
31
|
define_set_signal,
|
|
@@ -218,7 +219,6 @@ def sensitivity(
|
|
|
218
219
|
bc_step = define_boundary(sim, kernels)
|
|
219
220
|
excitation_step = define_excitation(sim, source.position, kernels, mat)
|
|
220
221
|
grads = sim.gradient_fields(mat)
|
|
221
|
-
gradient_step = sim.define_gradient(sens_kernels, mat, grads)
|
|
222
222
|
|
|
223
223
|
# ------------------------------------ forward pass -----------------------------------
|
|
224
224
|
# stepped straight into the history, so the leading zeros are u^-2 / u^-1
|
|
@@ -238,10 +238,24 @@ def sensitivity(
|
|
|
238
238
|
|
|
239
239
|
# --------------------------------- adjoint excitation --------------------------------
|
|
240
240
|
signal = adjoint_signal(sim, dphi, sensors)
|
|
241
|
-
adjoint_excitation = define_excitation(sim, sensors, kernels, mat)
|
|
242
241
|
|
|
243
242
|
# ----------------------------------- backward pass -----------------------------------
|
|
244
243
|
P = cp.zeros((2, *sim.field_shape), dtype=sim.dtype)
|
|
244
|
+
if sim.fuses_adjoint:
|
|
245
|
+
adjoint_step = sim.define_adjoint_gradient(sens_kernels, mat, grads)
|
|
246
|
+
adjoint_excitation = define_adjoint_excitation(sim, sensors, kernels, mat, grads)
|
|
247
|
+
|
|
248
|
+
# reversed, so row m is the middle slot both gradients of lambda^(n + 1) read
|
|
249
|
+
def backward(m, signal, history):
|
|
250
|
+
p = adjoint_step(P[m % 2], P[1 - m % 2], history[m]) # lambda^n
|
|
251
|
+
adjoint_excitation(p, signal, history[m], m)
|
|
252
|
+
bc_step(p)
|
|
253
|
+
|
|
254
|
+
march(sim.N, backward, [Window(signal), Window(V[::-1])])
|
|
255
|
+
return cost, sim.finalize_gradients(grads, sens_kernels), um, {}
|
|
256
|
+
|
|
257
|
+
gradient_step = sim.define_gradient(sens_kernels, mat, grads)
|
|
258
|
+
adjoint_excitation = define_excitation(sim, sensors, kernels, mat)
|
|
245
259
|
|
|
246
260
|
# reversed, so row m + 2 - i is u^(n + i) for n = N - 1 - m
|
|
247
261
|
def backward(m, signal, history):
|
|
@@ -418,13 +432,18 @@ def superposition_sensitivity(
|
|
|
418
432
|
kernels = compile_kernels(sim)
|
|
419
433
|
sens_kernels = compile_kernels(sim, sim.sensitivity_path)
|
|
420
434
|
|
|
421
|
-
fd_step = sim.define_step(kernels, mat)
|
|
422
435
|
bc_step = define_boundary(sim, kernels)
|
|
423
436
|
excitation_step = define_excitation(sim, source.position, kernels, mat)
|
|
424
437
|
get_signal = define_get_signal(sim, sensors, kernels)
|
|
425
438
|
accs = sim.gradient_fields(mat)
|
|
426
|
-
|
|
427
|
-
|
|
439
|
+
fused = sim.fuses_adjoint
|
|
440
|
+
if fused:
|
|
441
|
+
subtract_step = sim.define_superposed(sens_kernels, mat, accs, -1.0)
|
|
442
|
+
add_step = sim.define_superposed(sens_kernels, mat, accs, 1.0)
|
|
443
|
+
else:
|
|
444
|
+
fd_step = sim.define_step(kernels, mat)
|
|
445
|
+
subtract_step = sim.define_frechet(sens_kernels, accs, -1.0)
|
|
446
|
+
add_step = sim.define_frechet(sens_kernels, accs, 1.0)
|
|
428
447
|
|
|
429
448
|
U = cp.zeros((3, *sim.field_shape), dtype=sim.dtype)
|
|
430
449
|
um = cp.zeros((sim.N, sensors.shape[1]), dtype=sim.dtype)
|
|
@@ -433,13 +452,21 @@ def superposition_sensitivity(
|
|
|
433
452
|
# records the traces and subtracts the forward diagonal B(u, u)
|
|
434
453
|
def forward(t, signal, um):
|
|
435
454
|
u0, u1, u2 = U[t % 3], U[(t + 1) % 3], U[(t + 2) % 3]
|
|
436
|
-
|
|
455
|
+
if fused:
|
|
456
|
+
subtract_step(u0, u1, u2) # the mass density one triplet late
|
|
457
|
+
else:
|
|
458
|
+
fd_step(u0, u1, u2)
|
|
437
459
|
excitation_step(u2, signal, t)
|
|
438
460
|
bc_step(u2)
|
|
439
461
|
get_signal(u2, um, t)
|
|
440
|
-
|
|
462
|
+
if not fused:
|
|
463
|
+
subtract_step(u0, u1, u2)
|
|
441
464
|
|
|
442
465
|
march(sim.N, forward, [Window(source.signal), Window(um, store=True)])
|
|
466
|
+
if fused:
|
|
467
|
+
t = sim.N - 1
|
|
468
|
+
last = (U[t % 3], U[(t + 1) % 3], U[(t + 2) % 3])
|
|
469
|
+
sim.define_frechet(sens_kernels, accs, -1.0, stiffness=False)(*last)
|
|
443
470
|
|
|
444
471
|
cost, dphi = objective(um)
|
|
445
472
|
|
|
@@ -461,14 +488,26 @@ def superposition_sensitivity(
|
|
|
461
488
|
|
|
462
489
|
# ----------------------------------- backward pass -----------------------------------
|
|
463
490
|
# starting from u^(N - 1) over u^(N - 2), so the one array carries u + k lambda
|
|
464
|
-
def backward(t, signal):
|
|
491
|
+
def backward(t, signal, row, mass=True):
|
|
465
492
|
u0, u1, u2 = (U[(sim.N + i - t) % 3] for i in (1, 0, 2))
|
|
466
|
-
|
|
467
|
-
|
|
493
|
+
if fused:
|
|
494
|
+
add_step(u0, u1, u2, mass)
|
|
495
|
+
else:
|
|
496
|
+
fd_step(u0, u1, u2)
|
|
497
|
+
backward_excitation(u2, signal, row)
|
|
468
498
|
bc_step(u2)
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
499
|
+
if not fused:
|
|
500
|
+
add_step(u0, u1, u2)
|
|
501
|
+
|
|
502
|
+
def shifted(t, signal):
|
|
503
|
+
backward(t + 1, signal, t)
|
|
504
|
+
|
|
505
|
+
# outside the graph, as the first fused step's triplet before is the forward's last
|
|
506
|
+
backward(0, backward_signal, 0, mass=False)
|
|
507
|
+
march(sim.N - 1, shifted, [Window(backward_signal[1:])])
|
|
508
|
+
if fused:
|
|
509
|
+
last = (U[(1 + i) % 3] for i in (1, 0, 2))
|
|
510
|
+
sim.define_frechet(sens_kernels, accs, 1.0, stiffness=False)(*last)
|
|
472
511
|
|
|
473
512
|
after = _accumulated(accs)
|
|
474
513
|
cancellation = before / after if after > 0.0 else float("inf")
|
|
@@ -271,6 +271,7 @@ class Simulation:
|
|
|
271
271
|
dirichlet: cpt.NDArray | None = None # nodal mask held at zero, its cells left open
|
|
272
272
|
|
|
273
273
|
accepts_domain = False # whether the step kernel honours -DUSE_DOMAIN
|
|
274
|
+
fuses_adjoint = False # whether the gradients ride in the adjoint step kernels
|
|
274
275
|
|
|
275
276
|
@property
|
|
276
277
|
def compile_flags(self) -> tuple[str, ...]:
|
|
@@ -331,6 +332,10 @@ class Simulation:
|
|
|
331
332
|
f"index; coarsen the grid"
|
|
332
333
|
)
|
|
333
334
|
|
|
335
|
+
def adjoint_mass_factor(self) -> float:
|
|
336
|
+
"""Scale of the inertia gradient density: `1 / dt**2`, the residual's own."""
|
|
337
|
+
return 1.0 / self.dt**2
|
|
338
|
+
|
|
334
339
|
def define_step(self, kernels: cp.RawModule, mat: dict) -> Callable:
|
|
335
340
|
"""Closure launching the finite-difference step kernel over (u0, u1, u2)."""
|
|
336
341
|
fd_kernel = kernels.get_function("fd_kernel")
|
|
@@ -595,6 +600,32 @@ def define_excitation(
|
|
|
595
600
|
return _define_transfer(sim, "excitation_kernel", position, kernels, weight)
|
|
596
601
|
|
|
597
602
|
|
|
603
|
+
def define_adjoint_excitation(
|
|
604
|
+
sim: Simulation,
|
|
605
|
+
sensors: cpt.NDArray[cp.int32],
|
|
606
|
+
kernels: cp.RawModule,
|
|
607
|
+
mat: dict,
|
|
608
|
+
grads: dict,
|
|
609
|
+
) -> Callable:
|
|
610
|
+
"""Closure adding row `t_index` of the adjoint signal into `l2`, and its share of the inertia gradient against `u1`."""
|
|
611
|
+
lin_index = flatten_indices(sim, sensors)
|
|
612
|
+
kernel = kernels.get_function("adjoint_excitation_kernel")
|
|
613
|
+
threads = 256
|
|
614
|
+
num = sensors.shape[1]
|
|
615
|
+
blocks = ((num + threads - 1) // threads,)
|
|
616
|
+
args = [None, None, np.int32(0), lin_index, np.int32(num)]
|
|
617
|
+
args += [sim.excitation_weights(mat, lin_index), grads["mass"], None]
|
|
618
|
+
args.append(sim.dtype(sim.adjoint_mass_factor()))
|
|
619
|
+
|
|
620
|
+
def adjoint_excitation_step(l2, signal, u1, t_index):
|
|
621
|
+
args[0], args[1], args[7] = l2, signal, u1
|
|
622
|
+
args[2] = np.int32(t_index * num)
|
|
623
|
+
kernel(blocks, (threads,), args)
|
|
624
|
+
return l2
|
|
625
|
+
|
|
626
|
+
return adjoint_excitation_step
|
|
627
|
+
|
|
628
|
+
|
|
598
629
|
def define_get_signal(
|
|
599
630
|
sim: Simulation, sensors: cpt.NDArray[cp.int32], kernels: cp.RawModule
|
|
600
631
|
) -> Callable:
|
|
@@ -1,140 +0,0 @@
|
|
|
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
|
-
// ------------------------------- interior guard macros
|
|
6
|
-
#if NDIM == 1
|
|
7
|
-
#define INTERIOR_OR_RETURN \
|
|
8
|
-
const int a0 = blockIdx.x * blockDim.x + threadIdx.x; \
|
|
9
|
-
if (!(a0 > 0 && a0 < N0 - 1)) \
|
|
10
|
-
return; \
|
|
11
|
-
const int idx = a0
|
|
12
|
-
#define AXIS_RADII const int r0 = CLOSURE(a0, N0)
|
|
13
|
-
#define AXIS_OFFSETS const int o0 = 1
|
|
14
|
-
#elif NDIM == 2
|
|
15
|
-
#define INTERIOR_OR_RETURN \
|
|
16
|
-
const int a1 = blockIdx.x * blockDim.x + threadIdx.x; \
|
|
17
|
-
const int a0 = blockIdx.y * blockDim.y + threadIdx.y; \
|
|
18
|
-
if (!(a0 > 0 && a0 < N0 - 1 && a1 > 0 && a1 < N1 - 1)) \
|
|
19
|
-
return; \
|
|
20
|
-
const int idx = a0 * s0 + a1
|
|
21
|
-
#define AXIS_RADII const int r0 = CLOSURE(a0, N0), r1 = CLOSURE(a1, N1)
|
|
22
|
-
#define AXIS_OFFSETS const int o0 = s0, o1 = 1
|
|
23
|
-
#elif NDIM == 3
|
|
24
|
-
#define INTERIOR_OR_RETURN \
|
|
25
|
-
const int a2 = blockIdx.x * blockDim.x + threadIdx.x; \
|
|
26
|
-
const int a1 = blockIdx.y * blockDim.y + threadIdx.y; \
|
|
27
|
-
const int a0 = blockIdx.z * blockDim.z + threadIdx.z; \
|
|
28
|
-
if (!(a0 > 0 && a0 < N0 - 1 && a1 > 0 && a1 < N1 - 1 && a2 > 0 && \
|
|
29
|
-
a2 < N2 - 1)) \
|
|
30
|
-
return; \
|
|
31
|
-
const int idx = a0 * s0 + a1 * s1 + a2
|
|
32
|
-
#define AXIS_RADII \
|
|
33
|
-
const int r0 = CLOSURE(a0, N0), r1 = CLOSURE(a1, N1), r2 = CLOSURE(a2, N2)
|
|
34
|
-
#define AXIS_OFFSETS const int o0 = s0, o1 = s1, o2 = 1
|
|
35
|
-
#endif
|
|
36
|
-
|
|
37
|
-
// ---------------------------------- gradient helpers
|
|
38
|
-
__device__ __forceinline__ real_t stiffness_gradient_axis(
|
|
39
|
-
const real_t *__restrict__ u1, const real_t *__restrict__ l1,
|
|
40
|
-
const real_t *__restrict__ stiff, const int idx, const int s,
|
|
41
|
-
const real_t uc, const real_t lc, const real_t sc, const real_t factor,
|
|
42
|
-
const int r) {
|
|
43
|
-
const real_t sp = stiff[idx + s]; // plus of sc
|
|
44
|
-
const real_t sm = stiff[idx - s]; // minus of sc
|
|
45
|
-
const real_t dgp = sp * sp / ((sc + sp) * (sc + sp)); // d(harmonic mean)/dsc
|
|
46
|
-
const real_t dgm = sm * sm / ((sc + sm) * (sc + sm)); // d(harmonic mean)/dsc
|
|
47
|
-
real_t Dp = OP_W(r, 1) * (u1[idx + s] - uc); // inner grad
|
|
48
|
-
real_t Dm = OP_W(r, 1) * (uc - u1[idx - s]); // inner grad
|
|
49
|
-
#pragma unroll
|
|
50
|
-
for (int k = 2; k <= STENCIL_RADIUS; ++k)
|
|
51
|
-
if (k <= r) {
|
|
52
|
-
Dp += OP_W(r, k) * (u1[idx + k * s] - u1[idx - (k - 1) * s]);
|
|
53
|
-
Dm += OP_W(r, k) * (u1[idx + (k - 1) * s] - u1[idx - k * s]);
|
|
54
|
-
}
|
|
55
|
-
return factor * (dgp * Dp * (l1[idx + s] - lc) +
|
|
56
|
-
dgm * Dm * (lc - l1[idx - s])); // both cells of the node
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// -------------------------------------- kernels
|
|
60
|
-
extern "C" {
|
|
61
|
-
|
|
62
|
-
// ------------------------------------------------------------------------------------
|
|
63
|
-
__global__ void
|
|
64
|
-
gradient_kernel(real_t *__restrict__ g_mass, real_t *__restrict__ g_stiff,
|
|
65
|
-
const real_t *__restrict__ u0, const real_t *__restrict__ u1,
|
|
66
|
-
const real_t *__restrict__ u2, const real_t *__restrict__ l1,
|
|
67
|
-
const real_t *__restrict__ stiff, const real_t inv_dt2,
|
|
68
|
-
const real_t F0, const int N0
|
|
69
|
-
#if NDIM >= 2
|
|
70
|
-
,
|
|
71
|
-
const real_t F1, const int N1, const int s0
|
|
72
|
-
#endif
|
|
73
|
-
#if NDIM >= 3
|
|
74
|
-
,
|
|
75
|
-
const real_t F2, const int N2, const int s1
|
|
76
|
-
#endif
|
|
77
|
-
) {
|
|
78
|
-
INTERIOR_OR_RETURN;
|
|
79
|
-
AXIS_RADII;
|
|
80
|
-
|
|
81
|
-
const real_t uc = u1[idx];
|
|
82
|
-
const real_t lc = l1[idx];
|
|
83
|
-
|
|
84
|
-
// dJ/dmass: no neighbour and no material load
|
|
85
|
-
g_mass[idx] -= inv_dt2 * lc * (u2[idx] - 2.f * uc + u0[idx]);
|
|
86
|
-
|
|
87
|
-
// dJ/dstiff: scalar.cu's harmonic cell mean differentiated in place
|
|
88
|
-
const real_t sc = stiff[idx];
|
|
89
|
-
#if NDIM == 1
|
|
90
|
-
const real_t g =
|
|
91
|
-
stiffness_gradient_axis(u1, l1, stiff, idx, 1, uc, lc, sc, F0, r0);
|
|
92
|
-
#elif NDIM == 2
|
|
93
|
-
const real_t g =
|
|
94
|
-
stiffness_gradient_axis(u1, l1, stiff, idx, s0, uc, lc, sc, F0, r0) +
|
|
95
|
-
stiffness_gradient_axis(u1, l1, stiff, idx, 1, uc, lc, sc, F1, r1);
|
|
96
|
-
#elif NDIM == 3
|
|
97
|
-
const real_t g =
|
|
98
|
-
stiffness_gradient_axis(u1, l1, stiff, idx, s0, uc, lc, sc, F0, r0) +
|
|
99
|
-
stiffness_gradient_axis(u1, l1, stiff, idx, s1, uc, lc, sc, F1, r1) +
|
|
100
|
-
stiffness_gradient_axis(u1, l1, stiff, idx, 1, uc, lc, sc, F2, r2);
|
|
101
|
-
#endif
|
|
102
|
-
g_stiff[idx] -= g;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// ------------------------------------------------------------------------------------
|
|
106
|
-
__global__ void frechet_kernel(real_t *__restrict__ acc_mass,
|
|
107
|
-
real_t *__restrict__ acc_stiff,
|
|
108
|
-
const real_t *__restrict__ u0,
|
|
109
|
-
const real_t *__restrict__ u1,
|
|
110
|
-
const real_t *__restrict__ u2, const real_t ft,
|
|
111
|
-
const real_t f0, const int N0
|
|
112
|
-
#if NDIM >= 2
|
|
113
|
-
,
|
|
114
|
-
const real_t f1, const int N1, const int s0
|
|
115
|
-
#endif
|
|
116
|
-
#if NDIM >= 3
|
|
117
|
-
,
|
|
118
|
-
const real_t f2, const int N2, const int s1
|
|
119
|
-
#endif
|
|
120
|
-
) {
|
|
121
|
-
INTERIOR_OR_RETURN;
|
|
122
|
-
AXIS_OFFSETS;
|
|
123
|
-
|
|
124
|
-
const real_t dudt = u2[idx] - u0[idx];
|
|
125
|
-
acc_mass[idx] += ft * dudt * dudt;
|
|
126
|
-
|
|
127
|
-
const real_t g0 = u1[idx + o0] - u1[idx - o0];
|
|
128
|
-
real_t sum = f0 * g0 * g0;
|
|
129
|
-
#if NDIM >= 2
|
|
130
|
-
const real_t g1 = u1[idx + o1] - u1[idx - o1];
|
|
131
|
-
sum += f1 * g1 * g1;
|
|
132
|
-
#endif
|
|
133
|
-
#if NDIM >= 3
|
|
134
|
-
const real_t g2 = u1[idx + o2] - u1[idx - o2];
|
|
135
|
-
sum += f2 * g2 * g2;
|
|
136
|
-
#endif
|
|
137
|
-
acc_stiff[idx] += sum;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
} // extern "C"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|