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
|
@@ -0,0 +1,225 @@
|
|
|
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
|
+
#if NDIM == 1
|
|
7
|
+
#define AXIS_PARAMS const real_t f0, const int N0
|
|
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_GEOM const int A[1] = {a0}, S[1] = {1}, NN[1] = {N0}
|
|
14
|
+
#define AXIS_FACTORS const real_t F[1] = {f0}
|
|
15
|
+
#elif NDIM == 2
|
|
16
|
+
#define AXIS_PARAMS \
|
|
17
|
+
const real_t f0, const int N0, const real_t f1, const int N1, const int s0
|
|
18
|
+
#define INTERIOR_OR_RETURN \
|
|
19
|
+
const int a1 = blockIdx.x * blockDim.x + threadIdx.x; \
|
|
20
|
+
const int a0 = blockIdx.y * blockDim.y + threadIdx.y; \
|
|
21
|
+
if (!(a0 > 0 && a0 < N0 - 1 && a1 > 0 && a1 < N1 - 1)) \
|
|
22
|
+
return; \
|
|
23
|
+
const int idx = a0 * s0 + a1
|
|
24
|
+
#define AXIS_GEOM \
|
|
25
|
+
const int A[2] = {a0, a1}, S[2] = {s0, 1}, NN[2] = {N0, N1}
|
|
26
|
+
#define AXIS_FACTORS const real_t F[2] = {f0, f1}
|
|
27
|
+
#elif NDIM == 3
|
|
28
|
+
#define AXIS_PARAMS \
|
|
29
|
+
const real_t f0, const int N0, const real_t f1, const int N1, const int s0, \
|
|
30
|
+
const real_t f2, const int N2, const int s1
|
|
31
|
+
#define INTERIOR_OR_RETURN \
|
|
32
|
+
const int a2 = blockIdx.x * blockDim.x + threadIdx.x; \
|
|
33
|
+
const int a1 = blockIdx.y * blockDim.y + threadIdx.y; \
|
|
34
|
+
const int a0 = blockIdx.z * blockDim.z + threadIdx.z; \
|
|
35
|
+
if (!(a0 > 0 && a0 < N0 - 1 && a1 > 0 && a1 < N1 - 1 && a2 > 0 && \
|
|
36
|
+
a2 < N2 - 1)) \
|
|
37
|
+
return; \
|
|
38
|
+
const int idx = a0 * s0 + a1 * s1 + a2
|
|
39
|
+
#define AXIS_GEOM \
|
|
40
|
+
const int A[3] = {a0, a1, a2}, S[3] = {s0, s1, 1}, NN[3] = {N0, N1, N2}
|
|
41
|
+
#define AXIS_FACTORS const real_t F[3] = {f0, f1, f2}
|
|
42
|
+
#endif
|
|
43
|
+
|
|
44
|
+
// the node's normal strains, one per axis: a wall grades to a zero row under
|
|
45
|
+
// traction (returned as a set bit) and to the antisymmetric fold when clamped
|
|
46
|
+
__device__ __forceinline__ int
|
|
47
|
+
normal_strains(const real_t *__restrict__ u, const int idx, const int cs,
|
|
48
|
+
const int *A, const int *S, const int *NN, const real_t *F,
|
|
49
|
+
const int clamped, real_t *eps) {
|
|
50
|
+
int zeroed = 0;
|
|
51
|
+
#pragma unroll
|
|
52
|
+
for (int d = 0; d < NDIM; ++d) {
|
|
53
|
+
const int r = rad_node(A[d], NN[d]);
|
|
54
|
+
const real_t *__restrict__ ud = u + d * cs;
|
|
55
|
+
if (r > 0) {
|
|
56
|
+
real_t acc = (real_t)0;
|
|
57
|
+
#pragma unroll
|
|
58
|
+
for (int k = 1; k <= STENCIL_RADIUS; ++k)
|
|
59
|
+
if (k <= r)
|
|
60
|
+
acc += SG_W(r, k) * (ud[idx + (k - 1) * S[d]] - ud[idx - k * S[d]]);
|
|
61
|
+
eps[d] = F[d] * acc;
|
|
62
|
+
} else if (A[d] == 1 && clamped_face(clamped, d, 0)) {
|
|
63
|
+
eps[d] = F[d] * 2.f * ud[idx]; // the wall holds u = 0 half a node down
|
|
64
|
+
} else if (A[d] == NN[d] - 2 && clamped_face(clamped, d, 1)) {
|
|
65
|
+
eps[d] = -F[d] * 2.f * ud[idx - S[d]];
|
|
66
|
+
} else {
|
|
67
|
+
eps[d] = (real_t)0;
|
|
68
|
+
zeroed |= 1 << d;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return zeroed;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// a traction wall condenses its axis out of the coupling: the plane stress
|
|
75
|
+
// reduction of lam, applied once per zeroed axis
|
|
76
|
+
__device__ __forceinline__ real_t condensed_lame(const real_t lam,
|
|
77
|
+
const real_t mu,
|
|
78
|
+
const int zeroed) {
|
|
79
|
+
real_t lam_eff = lam;
|
|
80
|
+
#pragma unroll
|
|
81
|
+
for (int d = 0; d < NDIM; ++d)
|
|
82
|
+
if ((zeroed >> d) & 1)
|
|
83
|
+
lam_eff = 2.f * lam_eff * mu / (lam_eff + 2.f * mu);
|
|
84
|
+
return lam_eff;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
#if NDIM >= 2
|
|
88
|
+
// the engineering shear strain of the (k, l) pair at its own staggered point
|
|
89
|
+
__device__ __forceinline__ real_t
|
|
90
|
+
shear_strain(const real_t *__restrict__ u, const int idx, const int cs,
|
|
91
|
+
const int k, const int l, const int *A, const int *S,
|
|
92
|
+
const int *NN, const real_t *F) {
|
|
93
|
+
const int r1 = rad_half(A[l], NN[l]); // d u_k / d x_l
|
|
94
|
+
const int r2 = rad_half(A[k], NN[k]); // d u_l / d x_k
|
|
95
|
+
real_t e = (real_t)0;
|
|
96
|
+
#pragma unroll
|
|
97
|
+
for (int j = 1; j <= STENCIL_RADIUS; ++j) {
|
|
98
|
+
if (j <= r1)
|
|
99
|
+
e += F[l] * SG_W(r1, j) *
|
|
100
|
+
(u[k * cs + idx + j * S[l]] - u[k * cs + idx - (j - 1) * S[l]]);
|
|
101
|
+
if (j <= r2)
|
|
102
|
+
e += F[k] * SG_W(r2, j) *
|
|
103
|
+
(u[l * cs + idx + j * S[k]] - u[l * cs + idx - (j - 1) * S[k]]);
|
|
104
|
+
}
|
|
105
|
+
return e;
|
|
106
|
+
}
|
|
107
|
+
#endif
|
|
108
|
+
|
|
109
|
+
// -------------------------------------- kernels
|
|
110
|
+
extern "C" {
|
|
111
|
+
|
|
112
|
+
// ------------------------------------------------------------------------------------
|
|
113
|
+
__global__ void
|
|
114
|
+
stress_kernel(const real_t *__restrict__ u1, real_t *__restrict__ sigma,
|
|
115
|
+
const real_t *__restrict__ gnode,
|
|
116
|
+
#if NDIM >= 2
|
|
117
|
+
const real_t *__restrict__ gshear,
|
|
118
|
+
#endif
|
|
119
|
+
const real_t lam, const real_t mu, const int clamped,
|
|
120
|
+
const int cs, AXIS_PARAMS) {
|
|
121
|
+
INTERIOR_OR_RETURN;
|
|
122
|
+
AXIS_GEOM;
|
|
123
|
+
AXIS_FACTORS;
|
|
124
|
+
|
|
125
|
+
real_t eps[NDIM];
|
|
126
|
+
const int zeroed = normal_strains(u1, idx, cs, A, S, NN, F, clamped, eps);
|
|
127
|
+
const real_t lam_eff = condensed_lame(lam, mu, zeroed);
|
|
128
|
+
real_t tr = (real_t)0;
|
|
129
|
+
#pragma unroll
|
|
130
|
+
for (int d = 0; d < NDIM; ++d)
|
|
131
|
+
tr += eps[d];
|
|
132
|
+
const real_t gn = gnode[idx];
|
|
133
|
+
#pragma unroll
|
|
134
|
+
for (int d = 0; d < NDIM; ++d)
|
|
135
|
+
sigma[d * cs + idx] = ((zeroed >> d) & 1)
|
|
136
|
+
? (real_t)0
|
|
137
|
+
: gn * (2.f * mu * eps[d] + lam_eff * tr);
|
|
138
|
+
|
|
139
|
+
#if NDIM >= 2
|
|
140
|
+
#pragma unroll
|
|
141
|
+
for (int k = 0; k < NDIM - 1; ++k)
|
|
142
|
+
#pragma unroll
|
|
143
|
+
for (int l = k + 1; l < NDIM; ++l) {
|
|
144
|
+
if (A[k] > NN[k] - 3 || A[l] > NN[l] - 3)
|
|
145
|
+
continue;
|
|
146
|
+
const int v = PAIR_ROW(k, l);
|
|
147
|
+
sigma[v * cs + idx] = gshear[(v - NDIM) * cs + idx] * mu *
|
|
148
|
+
shear_strain(u1, idx, cs, k, l, A, S, NN, F);
|
|
149
|
+
}
|
|
150
|
+
#endif
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// ------------------------------------------------------------------------------------
|
|
154
|
+
__global__ void
|
|
155
|
+
fd_kernel(const real_t *__restrict__ u0, const real_t *__restrict__ u1,
|
|
156
|
+
real_t *__restrict__ u2, const real_t *__restrict__ sigma,
|
|
157
|
+
const real_t *__restrict__ minv,
|
|
158
|
+
#ifdef USE_DAMPING
|
|
159
|
+
const real_t *__restrict__ damping, const real_t dt,
|
|
160
|
+
#endif
|
|
161
|
+
const int clamped, const int cs, AXIS_PARAMS) {
|
|
162
|
+
INTERIOR_OR_RETURN;
|
|
163
|
+
AXIS_GEOM;
|
|
164
|
+
AXIS_FACTORS;
|
|
165
|
+
|
|
166
|
+
#pragma unroll
|
|
167
|
+
for (int c = 0; c < NDIM; ++c) {
|
|
168
|
+
if (A[c] > NN[c] - 3)
|
|
169
|
+
continue; // no unknown on the staggered ghost of its own axis
|
|
170
|
+
real_t force = (real_t)0;
|
|
171
|
+
{ // own normal stress along axis c, every tap keyed off the stress node
|
|
172
|
+
const real_t *__restrict__ sc = sigma + c * cs;
|
|
173
|
+
real_t acc = (real_t)0;
|
|
174
|
+
#pragma unroll
|
|
175
|
+
for (int k = 1; k <= STENCIL_RADIUS; ++k) {
|
|
176
|
+
const int ap = A[c] + k;
|
|
177
|
+
const int rp = rad_node(ap, NN[c]);
|
|
178
|
+
if (k <= rp)
|
|
179
|
+
acc += SG_W(rp, k) * sc[idx + k * S[c]];
|
|
180
|
+
else if (k == 1 && ap == NN[c] - 2 && clamped_face(clamped, c, 1))
|
|
181
|
+
acc += 2.f * sc[idx + S[c]]; // the fold of the clamped wall strain
|
|
182
|
+
const int am = A[c] - k + 1;
|
|
183
|
+
const int rm = (am >= 1) ? rad_node(am, NN[c]) : 0;
|
|
184
|
+
if (k <= rm)
|
|
185
|
+
acc -= SG_W(rm, k) * sc[idx - (k - 1) * S[c]];
|
|
186
|
+
else if (k == 1 && am == 1 && clamped_face(clamped, c, 0))
|
|
187
|
+
acc -= 2.f * sc[idx];
|
|
188
|
+
}
|
|
189
|
+
force += F[c] * acc;
|
|
190
|
+
}
|
|
191
|
+
#if NDIM >= 2
|
|
192
|
+
#pragma unroll
|
|
193
|
+
for (int l = 0; l < NDIM; ++l) { // shear stresses along the other axes
|
|
194
|
+
if (l == c)
|
|
195
|
+
continue;
|
|
196
|
+
const int v = PAIR_ROW(min(c, l), max(c, l));
|
|
197
|
+
const real_t *__restrict__ sv = sigma + v * cs;
|
|
198
|
+
real_t acc = (real_t)0;
|
|
199
|
+
#pragma unroll
|
|
200
|
+
for (int j = 1; j <= STENCIL_RADIUS; ++j) {
|
|
201
|
+
const int ap = A[l] + j - 1;
|
|
202
|
+
const int rp = (ap <= NN[l] - 3) ? rad_half(ap, NN[l]) : 0;
|
|
203
|
+
if (j <= rp)
|
|
204
|
+
acc += SG_W(rp, j) * sv[idx + (j - 1) * S[l]];
|
|
205
|
+
const int am = A[l] - j;
|
|
206
|
+
const int rm = (am >= 1) ? rad_half(am, NN[l]) : 0;
|
|
207
|
+
if (j <= rm)
|
|
208
|
+
acc -= SG_W(rm, j) * sv[idx - j * S[l]];
|
|
209
|
+
}
|
|
210
|
+
force += F[l] * acc;
|
|
211
|
+
}
|
|
212
|
+
#endif
|
|
213
|
+
const int n = c * cs + idx;
|
|
214
|
+
const real_t mi = minv[n];
|
|
215
|
+
#ifdef USE_DAMPING
|
|
216
|
+
const real_t beta = 0.5f * mi * damping[idx] * dt;
|
|
217
|
+
u2[n] = (2.f * u1[n] - u0[n] * (1.f - beta) + mi * force) / (1.f + beta);
|
|
218
|
+
#else
|
|
219
|
+
u2[n] = -u0[n] + 2.f * u1[n] + mi * force;
|
|
220
|
+
#endif
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
} // extern "C"
|
|
@@ -0,0 +1,217 @@
|
|
|
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
|
+
#if NDIM == 1
|
|
6
|
+
#define AXIS_PARAMS const real_t f0, const int N0
|
|
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_GEOM const int A[1] = {a0}, S[1] = {1}, NN[1] = {N0}
|
|
13
|
+
#define AXIS_FACTORS const real_t F[1] = {f0}
|
|
14
|
+
#elif NDIM == 2
|
|
15
|
+
#define AXIS_PARAMS \
|
|
16
|
+
const real_t f0, const int N0, const real_t f1, const int N1, const int s0
|
|
17
|
+
#define INTERIOR_OR_RETURN \
|
|
18
|
+
const int a1 = blockIdx.x * blockDim.x + threadIdx.x; \
|
|
19
|
+
const int a0 = blockIdx.y * blockDim.y + threadIdx.y; \
|
|
20
|
+
if (!(a0 > 0 && a0 < N0 - 1 && a1 > 0 && a1 < N1 - 1)) \
|
|
21
|
+
return; \
|
|
22
|
+
const int idx = a0 * s0 + a1
|
|
23
|
+
#define AXIS_GEOM \
|
|
24
|
+
const int A[2] = {a0, a1}, S[2] = {s0, 1}, NN[2] = {N0, N1}
|
|
25
|
+
#define AXIS_FACTORS const real_t F[2] = {f0, f1}
|
|
26
|
+
#elif NDIM == 3
|
|
27
|
+
#define AXIS_PARAMS \
|
|
28
|
+
const real_t f0, const int N0, const real_t f1, const int N1, const int s0, \
|
|
29
|
+
const real_t f2, const int N2, const int s1
|
|
30
|
+
#define INTERIOR_OR_RETURN \
|
|
31
|
+
const int a2 = blockIdx.x * blockDim.x + threadIdx.x; \
|
|
32
|
+
const int a1 = blockIdx.y * blockDim.y + threadIdx.y; \
|
|
33
|
+
const int a0 = blockIdx.z * blockDim.z + threadIdx.z; \
|
|
34
|
+
if (!(a0 > 0 && a0 < N0 - 1 && a1 > 0 && a1 < N1 - 1 && a2 > 0 && \
|
|
35
|
+
a2 < N2 - 1)) \
|
|
36
|
+
return; \
|
|
37
|
+
const int idx = a0 * s0 + a1 * s1 + a2
|
|
38
|
+
#define AXIS_GEOM \
|
|
39
|
+
const int A[3] = {a0, a1, a2}, S[3] = {s0, s1, 1}, NN[3] = {N0, N1, N2}
|
|
40
|
+
#define AXIS_FACTORS const real_t F[3] = {f0, f1, f2}
|
|
41
|
+
#endif
|
|
42
|
+
|
|
43
|
+
// the node's normal strains, one per axis: a wall grades to a zero row under
|
|
44
|
+
// traction (returned as a set bit) and to the antisymmetric fold when clamped
|
|
45
|
+
__device__ __forceinline__ int
|
|
46
|
+
normal_strains(const real_t *__restrict__ u, const int idx, const int cs,
|
|
47
|
+
const int *A, const int *S, const int *NN, const real_t *F,
|
|
48
|
+
const int clamped, real_t *eps) {
|
|
49
|
+
int zeroed = 0;
|
|
50
|
+
#pragma unroll
|
|
51
|
+
for (int d = 0; d < NDIM; ++d) {
|
|
52
|
+
const int r = rad_node(A[d], NN[d]);
|
|
53
|
+
const real_t *__restrict__ ud = u + d * cs;
|
|
54
|
+
if (r > 0) {
|
|
55
|
+
real_t acc = (real_t)0;
|
|
56
|
+
#pragma unroll
|
|
57
|
+
for (int k = 1; k <= STENCIL_RADIUS; ++k)
|
|
58
|
+
if (k <= r)
|
|
59
|
+
acc += SG_W(r, k) * (ud[idx + (k - 1) * S[d]] - ud[idx - k * S[d]]);
|
|
60
|
+
eps[d] = F[d] * acc;
|
|
61
|
+
} else if (A[d] == 1 && clamped_face(clamped, d, 0)) {
|
|
62
|
+
eps[d] = F[d] * 2.f * ud[idx]; // the wall holds u = 0 half a node down
|
|
63
|
+
} else if (A[d] == NN[d] - 2 && clamped_face(clamped, d, 1)) {
|
|
64
|
+
eps[d] = -F[d] * 2.f * ud[idx - S[d]];
|
|
65
|
+
} else {
|
|
66
|
+
eps[d] = (real_t)0;
|
|
67
|
+
zeroed |= 1 << d;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return zeroed;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// a traction wall condenses its axis out of the coupling: the plane stress
|
|
74
|
+
// reduction of lam, applied once per zeroed axis
|
|
75
|
+
__device__ __forceinline__ real_t condensed_lame(const real_t lam,
|
|
76
|
+
const real_t mu,
|
|
77
|
+
const int zeroed) {
|
|
78
|
+
real_t lam_eff = lam;
|
|
79
|
+
#pragma unroll
|
|
80
|
+
for (int d = 0; d < NDIM; ++d)
|
|
81
|
+
if ((zeroed >> d) & 1)
|
|
82
|
+
lam_eff = 2.f * lam_eff * mu / (lam_eff + 2.f * mu);
|
|
83
|
+
return lam_eff;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
#if NDIM >= 2
|
|
87
|
+
// the engineering shear strain of the (k, l) pair at its own staggered point
|
|
88
|
+
__device__ __forceinline__ real_t
|
|
89
|
+
shear_strain(const real_t *__restrict__ u, const int idx, const int cs,
|
|
90
|
+
const int k, const int l, const int *A, const int *S,
|
|
91
|
+
const int *NN, const real_t *F) {
|
|
92
|
+
const int r1 = rad_half(A[l], NN[l]); // d u_k / d x_l
|
|
93
|
+
const int r2 = rad_half(A[k], NN[k]); // d u_l / d x_k
|
|
94
|
+
real_t e = (real_t)0;
|
|
95
|
+
#pragma unroll
|
|
96
|
+
for (int j = 1; j <= STENCIL_RADIUS; ++j) {
|
|
97
|
+
if (j <= r1)
|
|
98
|
+
e += F[l] * SG_W(r1, j) *
|
|
99
|
+
(u[k * cs + idx + j * S[l]] - u[k * cs + idx - (j - 1) * S[l]]);
|
|
100
|
+
if (j <= r2)
|
|
101
|
+
e += F[k] * SG_W(r2, j) *
|
|
102
|
+
(u[l * cs + idx + j * S[k]] - u[l * cs + idx - (j - 1) * S[k]]);
|
|
103
|
+
}
|
|
104
|
+
return e;
|
|
105
|
+
}
|
|
106
|
+
#endif
|
|
107
|
+
|
|
108
|
+
// the normal bilinear form of two strain sets under the condensed coupling
|
|
109
|
+
__device__ __forceinline__ real_t normal_form(const real_t *ea,
|
|
110
|
+
const real_t *eb,
|
|
111
|
+
const real_t lam,
|
|
112
|
+
const real_t mu,
|
|
113
|
+
const int zeroed) {
|
|
114
|
+
const real_t lam_eff = condensed_lame(lam, mu, zeroed);
|
|
115
|
+
real_t tra = (real_t)0, trb = (real_t)0, dot = (real_t)0;
|
|
116
|
+
#pragma unroll
|
|
117
|
+
for (int d = 0; d < NDIM; ++d) {
|
|
118
|
+
tra += ea[d];
|
|
119
|
+
trb += eb[d];
|
|
120
|
+
dot += ea[d] * eb[d];
|
|
121
|
+
}
|
|
122
|
+
return 2.f * mu * dot + lam_eff * tra * trb;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// -------------------------------------- kernels
|
|
126
|
+
extern "C" {
|
|
127
|
+
|
|
128
|
+
// ------------------------------------------------------------------------------------
|
|
129
|
+
__global__ void gradient_kernel(real_t *__restrict__ g_mass,
|
|
130
|
+
real_t *__restrict__ g_normal,
|
|
131
|
+
#if NDIM >= 2
|
|
132
|
+
real_t *__restrict__ g_shear,
|
|
133
|
+
#endif
|
|
134
|
+
const real_t *__restrict__ u0,
|
|
135
|
+
const real_t *__restrict__ u1,
|
|
136
|
+
const real_t *__restrict__ u2,
|
|
137
|
+
const real_t *__restrict__ l1, const real_t lam,
|
|
138
|
+
const real_t mu, const real_t mf,
|
|
139
|
+
const int clamped, const int cs, AXIS_PARAMS) {
|
|
140
|
+
INTERIOR_OR_RETURN;
|
|
141
|
+
AXIS_GEOM;
|
|
142
|
+
AXIS_FACTORS;
|
|
143
|
+
|
|
144
|
+
// dJ/dmass on the component points: no neighbour and no material load
|
|
145
|
+
#pragma unroll
|
|
146
|
+
for (int c = 0; c < NDIM; ++c) {
|
|
147
|
+
if (A[c] > NN[c] - 3)
|
|
148
|
+
continue;
|
|
149
|
+
const int n = c * cs + idx;
|
|
150
|
+
g_mass[n] -= mf * l1[n] * (u2[n] - 2.f * u1[n] + u0[n]);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// dJ/dgamma on the node: forward against adjoint under the normal coupling
|
|
154
|
+
real_t eu[NDIM], el[NDIM];
|
|
155
|
+
const int zeroed = normal_strains(u1, idx, cs, A, S, NN, F, clamped, eu);
|
|
156
|
+
normal_strains(l1, idx, cs, A, S, NN, F, clamped, el);
|
|
157
|
+
g_normal[idx] -= normal_form(el, eu, lam, mu, zeroed);
|
|
158
|
+
|
|
159
|
+
#if NDIM >= 2
|
|
160
|
+
#pragma unroll
|
|
161
|
+
for (int k = 0; k < NDIM - 1; ++k) // and on each of its shear points
|
|
162
|
+
#pragma unroll
|
|
163
|
+
for (int l = k + 1; l < NDIM; ++l) {
|
|
164
|
+
if (A[k] > NN[k] - 3 || A[l] > NN[l] - 3)
|
|
165
|
+
continue;
|
|
166
|
+
const int v = PAIR_ROW(k, l);
|
|
167
|
+
g_shear[(v - NDIM) * cs + idx] -=
|
|
168
|
+
mu * shear_strain(l1, idx, cs, k, l, A, S, NN, F) *
|
|
169
|
+
shear_strain(u1, idx, cs, k, l, A, S, NN, F);
|
|
170
|
+
}
|
|
171
|
+
#endif
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// ------------------------------------------------------------------------------------
|
|
175
|
+
__global__ void frechet_kernel(real_t *__restrict__ acc_mass,
|
|
176
|
+
real_t *__restrict__ acc_normal,
|
|
177
|
+
#if NDIM >= 2
|
|
178
|
+
real_t *__restrict__ acc_shear,
|
|
179
|
+
#endif
|
|
180
|
+
const real_t *__restrict__ u0,
|
|
181
|
+
const real_t *__restrict__ u1,
|
|
182
|
+
const real_t *__restrict__ u2, const real_t lam,
|
|
183
|
+
const real_t mu, const real_t ft,
|
|
184
|
+
const real_t fs, const int clamped,
|
|
185
|
+
const int cs, AXIS_PARAMS) {
|
|
186
|
+
INTERIOR_OR_RETURN;
|
|
187
|
+
AXIS_GEOM;
|
|
188
|
+
AXIS_FACTORS;
|
|
189
|
+
|
|
190
|
+
#pragma unroll
|
|
191
|
+
for (int c = 0; c < NDIM; ++c) {
|
|
192
|
+
if (A[c] > NN[c] - 3)
|
|
193
|
+
continue;
|
|
194
|
+
const int n = c * cs + idx;
|
|
195
|
+
const real_t dudt = u2[n] - u0[n];
|
|
196
|
+
acc_mass[n] += ft * dudt * dudt;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
real_t eu[NDIM];
|
|
200
|
+
const int zeroed = normal_strains(u1, idx, cs, A, S, NN, F, clamped, eu);
|
|
201
|
+
acc_normal[idx] += fs * normal_form(eu, eu, lam, mu, zeroed);
|
|
202
|
+
|
|
203
|
+
#if NDIM >= 2
|
|
204
|
+
#pragma unroll
|
|
205
|
+
for (int k = 0; k < NDIM - 1; ++k)
|
|
206
|
+
#pragma unroll
|
|
207
|
+
for (int l = k + 1; l < NDIM; ++l) {
|
|
208
|
+
if (A[k] > NN[k] - 3 || A[l] > NN[l] - 3)
|
|
209
|
+
continue;
|
|
210
|
+
const int v = PAIR_ROW(k, l);
|
|
211
|
+
const real_t e = shear_strain(u1, idx, cs, k, l, A, S, NN, F);
|
|
212
|
+
acc_shear[(v - NDIM) * cs + idx] += fs * mu * e * e;
|
|
213
|
+
}
|
|
214
|
+
#endif
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
} // extern "C"
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// Prepended by wave.compile_kernels: stencils.preamble, then common.cuh.
|
|
2
|
+
// Compile-time configuration this file responds to:
|
|
3
|
+
// NDIM = 2 | 3
|
|
4
|
+
// USE_DAMPING
|
|
5
|
+
// USE_MAGNETIC
|
|
6
|
+
|
|
7
|
+
#if NDIM == 1
|
|
8
|
+
#error "a single in-plane component has no curl; use maxwell.ElectricWave"
|
|
9
|
+
#endif
|
|
10
|
+
|
|
11
|
+
#if NDIM == 2
|
|
12
|
+
#define AXIS_PARAMS \
|
|
13
|
+
const real_t f0, const int N0, const real_t f1, const int N1, const int s0
|
|
14
|
+
#define INTERIOR_OR_RETURN \
|
|
15
|
+
const int a1 = blockIdx.x * blockDim.x + threadIdx.x; \
|
|
16
|
+
const int a0 = blockIdx.y * blockDim.y + threadIdx.y; \
|
|
17
|
+
if (!(a0 > 0 && a0 < N0 - 1 && a1 > 0 && a1 < N1 - 1)) \
|
|
18
|
+
return; \
|
|
19
|
+
const int idx = a0 * s0 + a1
|
|
20
|
+
#define AXIS_GEOM \
|
|
21
|
+
const int A[2] = {a0, a1}, S[2] = {s0, 1}, NN[2] = {N0, N1}
|
|
22
|
+
#define AXIS_FACTORS const real_t F[2] = {f0, f1}
|
|
23
|
+
#elif NDIM == 3
|
|
24
|
+
#define AXIS_PARAMS \
|
|
25
|
+
const real_t f0, const int N0, const real_t f1, const int N1, const int s0, \
|
|
26
|
+
const real_t f2, const int N2, const int s1
|
|
27
|
+
#define INTERIOR_OR_RETURN \
|
|
28
|
+
const int a2 = blockIdx.x * blockDim.x + threadIdx.x; \
|
|
29
|
+
const int a1 = blockIdx.y * blockDim.y + threadIdx.y; \
|
|
30
|
+
const int a0 = blockIdx.z * blockDim.z + threadIdx.z; \
|
|
31
|
+
if (!(a0 > 0 && a0 < N0 - 1 && a1 > 0 && a1 < N1 - 1 && a2 > 0 && \
|
|
32
|
+
a2 < N2 - 1)) \
|
|
33
|
+
return; \
|
|
34
|
+
const int idx = a0 * s0 + a1 * s1 + a2
|
|
35
|
+
#define AXIS_GEOM \
|
|
36
|
+
const int A[3] = {a0, a1, a2}, S[3] = {s0, s1, 1}, NN[3] = {N0, N1, N2}
|
|
37
|
+
#define AXIS_FACTORS const real_t F[3] = {f0, f1, f2}
|
|
38
|
+
#endif
|
|
39
|
+
|
|
40
|
+
// ------------------------------------ curl helpers
|
|
41
|
+
// the (k, l) curl component at its own staggered point, the elastic shear
|
|
42
|
+
// strain with its first term negated: both taps are half-point differences
|
|
43
|
+
__device__ __forceinline__ real_t
|
|
44
|
+
curl_component(const real_t *__restrict__ u, const int idx, const int cs,
|
|
45
|
+
const int k, const int l, const int *A, const int *S,
|
|
46
|
+
const int *NN, const real_t *F) {
|
|
47
|
+
const int r1 = rad_half(A[l], NN[l]); // d u_k / d x_l
|
|
48
|
+
const int r2 = rad_half(A[k], NN[k]); // d u_l / d x_k
|
|
49
|
+
real_t b = (real_t)0;
|
|
50
|
+
#pragma unroll
|
|
51
|
+
for (int j = 1; j <= STENCIL_RADIUS; ++j) {
|
|
52
|
+
if (j <= r1)
|
|
53
|
+
b -= F[l] * SG_W(r1, j) *
|
|
54
|
+
(u[k * cs + idx + j * S[l]] - u[k * cs + idx - (j - 1) * S[l]]);
|
|
55
|
+
if (j <= r2)
|
|
56
|
+
b += F[k] * SG_W(r2, j) *
|
|
57
|
+
(u[l * cs + idx + j * S[k]] - u[l * cs + idx - (j - 1) * S[k]]);
|
|
58
|
+
}
|
|
59
|
+
return b;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// cell weight of a pair point, halved on the walls of the axes it does not span
|
|
63
|
+
__device__ __forceinline__ real_t pair_weight(const int k, const int l,
|
|
64
|
+
const int *A, const int *NN) {
|
|
65
|
+
real_t w = (real_t)1;
|
|
66
|
+
#pragma unroll
|
|
67
|
+
for (int d = 0; d < NDIM; ++d)
|
|
68
|
+
if (d != k && d != l && (A[d] == 1 || A[d] == NN[d] - 2))
|
|
69
|
+
w *= (real_t)0.5;
|
|
70
|
+
return w;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// -------------------------------------- kernels
|
|
74
|
+
extern "C" {
|
|
75
|
+
|
|
76
|
+
// ------------------------------------------------------------------------------------
|
|
77
|
+
__global__ void curl_kernel(const real_t *__restrict__ u1,
|
|
78
|
+
real_t *__restrict__ h,
|
|
79
|
+
#ifdef USE_MAGNETIC
|
|
80
|
+
const real_t *__restrict__ nu_pair,
|
|
81
|
+
#endif
|
|
82
|
+
const real_t nu, const int cs, AXIS_PARAMS) {
|
|
83
|
+
INTERIOR_OR_RETURN;
|
|
84
|
+
AXIS_GEOM;
|
|
85
|
+
AXIS_FACTORS;
|
|
86
|
+
|
|
87
|
+
#pragma unroll
|
|
88
|
+
for (int k = 0; k < NDIM - 1; ++k)
|
|
89
|
+
#pragma unroll
|
|
90
|
+
for (int l = k + 1; l < NDIM; ++l) {
|
|
91
|
+
if (A[k] > NN[k] - 3 || A[l] > NN[l] - 3)
|
|
92
|
+
continue; // no pair point on the staggered ghost of either axis
|
|
93
|
+
const int p = PAIR_ROW(k, l) - NDIM;
|
|
94
|
+
const real_t b = curl_component(u1, idx, cs, k, l, A, S, NN, F);
|
|
95
|
+
#ifdef USE_MAGNETIC
|
|
96
|
+
h[p * cs + idx] = nu_pair[p * cs + idx] * b; // the weight is folded in
|
|
97
|
+
#else
|
|
98
|
+
h[p * cs + idx] = nu * pair_weight(k, l, A, NN) * b;
|
|
99
|
+
#endif
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ------------------------------------------------------------------------------------
|
|
104
|
+
__global__ void
|
|
105
|
+
fd_kernel(const real_t *__restrict__ u0, const real_t *__restrict__ u1,
|
|
106
|
+
real_t *__restrict__ u2, const real_t *__restrict__ h,
|
|
107
|
+
const real_t *__restrict__ minv,
|
|
108
|
+
#ifdef USE_DAMPING
|
|
109
|
+
const real_t *__restrict__ damping, const real_t dt,
|
|
110
|
+
#endif
|
|
111
|
+
const int cs, AXIS_PARAMS) {
|
|
112
|
+
INTERIOR_OR_RETURN;
|
|
113
|
+
AXIS_GEOM;
|
|
114
|
+
AXIS_FACTORS;
|
|
115
|
+
|
|
116
|
+
#pragma unroll
|
|
117
|
+
for (int c = 0; c < NDIM; ++c) {
|
|
118
|
+
if (A[c] > NN[c] - 3)
|
|
119
|
+
continue; // no unknown on the staggered ghost of its own axis
|
|
120
|
+
real_t force = (real_t)0;
|
|
121
|
+
#pragma unroll
|
|
122
|
+
for (int m = 0; m < NDIM; ++m) { // the pairs this component belongs to
|
|
123
|
+
if (m == c)
|
|
124
|
+
continue;
|
|
125
|
+
const int p = PAIR_ROW(min(c, m), max(c, m)) - NDIM;
|
|
126
|
+
const real_t *__restrict__ hp = h + p * cs;
|
|
127
|
+
// E_c enters its pair as +d_m E_c for m < c and as -d_m E_c for m > c
|
|
128
|
+
const real_t sgn = (m < c) ? (real_t)1 : (real_t)-1;
|
|
129
|
+
real_t acc = (real_t)0;
|
|
130
|
+
#pragma unroll
|
|
131
|
+
for (int j = 1; j <= STENCIL_RADIUS; ++j) {
|
|
132
|
+
const int ap = A[m] + j - 1;
|
|
133
|
+
const int rp = (ap <= NN[m] - 3) ? rad_half(ap, NN[m]) : 0;
|
|
134
|
+
if (j <= rp)
|
|
135
|
+
acc += SG_W(rp, j) * hp[idx + (j - 1) * S[m]];
|
|
136
|
+
const int am = A[m] - j;
|
|
137
|
+
const int rm = (am >= 1) ? rad_half(am, NN[m]) : 0;
|
|
138
|
+
if (j <= rm)
|
|
139
|
+
acc -= SG_W(rm, j) * hp[idx - j * S[m]];
|
|
140
|
+
}
|
|
141
|
+
force += sgn * F[m] * acc;
|
|
142
|
+
}
|
|
143
|
+
const int n = c * cs + idx;
|
|
144
|
+
const real_t mi = minv[n];
|
|
145
|
+
#ifdef USE_DAMPING
|
|
146
|
+
const real_t beta = 0.5f * mi * damping[idx] * dt;
|
|
147
|
+
u2[n] = (2.f * u1[n] - u0[n] * (1.f - beta) + mi * force) / (1.f + beta);
|
|
148
|
+
#else
|
|
149
|
+
u2[n] = -u0[n] + 2.f * u1[n] + mi * force;
|
|
150
|
+
#endif
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
} // extern "C"
|