7#include "../../utils/gpu.hpp"
27 HenryPeriodic(
const int n[3],
const double lo[3],
const double hi[3],
const int m[3],
const int id[3]);
34 size_t bytes()
const {
return bytes_; }
61 void filter(
const size_t bytes,
double *
const before,
double *
const after,
const F f)
const;
71 MPI_Comm commI_, commJ_,
73 int dh_, di_, dj_, dk_;
77 cufftHandle c2ci_, c2cj_, c2rk_,
84#if defined(__HIP__) || defined(__CUDACC__)
87void HenryPeriodic::filter(
const size_t bytes,
double *
const before,
double *
const after,
const F f)
const
90 assert(
bytes >= bytes_);
92 double *
const a = after;
93 double *
const b = before;
94 cufftDoubleComplex *
const ac =
reinterpret_cast<cufftDoubleComplex *
>(a);
95 cufftDoubleComplex *
const bc =
reinterpret_cast<cufftDoubleComplex *
>(b);
99 const int di = di_, dj = dj_, dk = dk_;
100 const int dhq = dhq_, dip = dip_, djp = djp_, djq = djq_;
101 const int idi = idi_, idj = idj_, idk = idk_;
102 const int idp = idp_, idq = idq_;
103 const int mi = mi_, mj = mj_, mk = mk_;
104 const int mp = mp_, mq = mq_;
105 const int nh = nh_, ni = ni_, nj = nj_, nk = nk_;
109 const int idip = idi * mp + idp;
110 const int idjq = idj * mq + idq;
111 const int mip = mi * mp;
112 const int mjq = mj * mq;
117 mp, mq, dip, djq, dk, GPU_LAMBDA(
const int p,
const int q,
const int i,
const int j,
const int k) {
118 const int ii = p * dip + i;
119 const int jj = q * djq + j;
120 const int ia = k + dk * (j + djq * (i + dip * (q + mq * p)));
121 const int ib = k + dk * (jj + dj * ii);
127 const int countK = dip * djq * dk;
129 GPU_Error_Check(cudaMemcpy(ha_, a,
bytes, cudaMemcpyDeviceToHost));
130 MPI_Alltoall(ha_, countK, MPI_DOUBLE, hb_, countK, MPI_DOUBLE, commK_);
131 GPU_Error_Check(cudaMemcpy(b, hb_,
bytes, cudaMemcpyHostToDevice));
133 GPU_Error_Check(cudaDeviceSynchronize());
134 MPI_Alltoall(a, countK, MPI_DOUBLE, b, countK, MPI_DOUBLE, commK_);
139 const int iLo = idi * di + idp * dip;
140 const int iHi = std::min({iLo + dip, (idi + 1) * di, ni});
141 const int jLo = idj * dj + idq * djq;
142 const int jHi = std::min({jLo + djq, (idj + 1) * dj, nj});
144 iHi - iLo, jHi - jLo, mk, dk, GPU_LAMBDA(
const int i,
const int j,
const int pq,
const int k) {
145 const int kk = pq * dk + k;
147 const int ia = kk + nk * (j + djq * i);
148 const int ib = k + dk * (j + djq * (i + dip * pq));
155 GPU_Error_Check(cufftExecD2Z(r2ck_, a, bc));
159 const int iLo = idi * di + idp * dip;
160 const int iHi = std::min({iLo + dip, (idi + 1) * di, ni});
161 const int jLo = idj_ * dj_ + idq * djq;
162 const int jHi = std::min({jLo + djq, (idj + 1) * dj, nj});
164 mjq, iHi - iLo, jHi - jLo, dhq, GPU_LAMBDA(
const int q,
const int i,
const int j,
const int k) {
165 const int kk = q * dhq + k;
167 const int ia = k + dhq * (j + djq * (i + dip * q));
168 const int ib = kk + nh * (j + djq * i);
175 const int countJ = 2 * dip * djq * dhq;
177 GPU_Error_Check(cudaMemcpy(ha_, a,
bytes, cudaMemcpyDeviceToHost));
178 MPI_Alltoall(ha_, countJ, MPI_DOUBLE, hb_, countJ, MPI_DOUBLE, commJ_);
179 GPU_Error_Check(cudaMemcpy(b, hb_,
bytes, cudaMemcpyHostToDevice));
181 GPU_Error_Check(cudaDeviceSynchronize());
182 MPI_Alltoall(a, countJ, MPI_DOUBLE, b, countJ, MPI_DOUBLE, commJ_);
187 const int iLo = idi * di + idp * dip;
188 const int iHi = std::min({iLo + dip, (idi + 1) * di, ni});
189 const int kLo = idjq * dhq;
190 const int kHi = std::min(kLo + dhq, nh);
192 kHi - kLo, iHi - iLo, mj, mq, djq, GPU_LAMBDA(
const int k,
const int i,
const int r,
const int q,
const int j) {
193 const int rdj = r * dj;
194 const int jj = rdj + q * djq + j;
195 if ((jj < nj) && (jj < rdj + dj)) {
196 const int ia = jj + nj * (i + dip * k);
197 const int ib = k + dhq * (j + djq * (i + dip * (q + mq * r)));
204 GPU_Error_Check(cufftExecZ2Z(c2cj_, ac, bc, CUFFT_FORWARD));
208 const int iLo = idi * di + idp * dip;
209 const int iHi = std::min({iLo + dip, (idi + 1) * di, ni});
210 const int kLo = idjq * dhq;
211 const int kHi = std::min(kLo + dhq, nh);
213 mip, kHi - kLo, iHi - iLo, djp, GPU_LAMBDA(
const int p,
const int k,
const int i,
const int j) {
214 const int jj = p * djp + j;
216 const int ia = j + djp * (i + dip * (k + dhq * p));
217 const int ib = jj + nj * (i + dip * k);
224 const int countI = 2 * dip * djp * dhq;
226 GPU_Error_Check(cudaMemcpy(ha_, a,
bytes, cudaMemcpyDeviceToHost));
227 MPI_Alltoall(ha_, countI, MPI_DOUBLE, hb_, countI, MPI_DOUBLE, commI_);
228 GPU_Error_Check(cudaMemcpy(b, hb_,
bytes, cudaMemcpyHostToDevice));
230 GPU_Error_Check(cudaDeviceSynchronize());
231 MPI_Alltoall(a, countI, MPI_DOUBLE, b, countI, MPI_DOUBLE, commI_);
236 const int jLo = idip * djp;
237 const int jHi = std::min(jLo + djp, nj);
238 const int kLo = idjq * dhq;
239 const int kHi = std::min(kLo + dhq, nh);
241 jHi - jLo, kHi - kLo, mi, mp, dip, GPU_LAMBDA(
const int j,
const int k,
const int r,
const int p,
const int i) {
242 const int rdi = r * di;
243 const int ii = rdi + p * dip + i;
244 if ((ii < ni) && (ii < rdi + di)) {
245 const int ia = ii + ni * (k + dhq * j);
246 const int ib = j + djp * (i + dip * (k + dhq * (p + mp * r)));
253 GPU_Error_Check(cufftExecZ2Z(c2ci_, ac, bc, CUFFT_FORWARD));
257 const int jLo = idip * djp;
258 const int jHi = std::min(jLo + djp, nj);
259 const int kLo = idjq * dhq;
260 const int kHi = std::min(kLo + dhq, nh);
263 jHi - jLo, kHi - kLo, ni, GPU_LAMBDA(
const int j0,
const int k0,
const int i) {
264 const int j = jLo + j0;
265 const int k = kLo + k0;
266 const int iab = i + ni * (k0 + dhq * j0);
267 ac[iab] = f(i, j, k, bc[iab]);
271 GPU_Error_Check(cufftExecZ2Z(c2ci_, ac, bc, CUFFT_INVERSE));
275 const int jLo = idip * djp;
276 const int jHi = std::min(jLo + djp, nj);
277 const int kLo = idjq * dhq;
278 const int kHi = std::min(kLo + dhq, nh);
280 mi, mp, jHi - jLo, kHi - kLo, dip, GPU_LAMBDA(
const int r,
const int p,
const int j,
const int k,
const int i) {
281 const int rdi = r * di;
282 const int ii = rdi + p * dip + i;
283 if ((ii < ni) && (ii < rdi + di)) {
284 const int ia = i + dip * (k + dhq * (j + djp * (p + mp * r)));
285 const int ib = ii + ni * (k + dhq * j);
293 GPU_Error_Check(cudaMemcpy(ha_, a,
bytes, cudaMemcpyDeviceToHost));
294 MPI_Alltoall(ha_, countI, MPI_DOUBLE, hb_, countI, MPI_DOUBLE, commI_);
295 GPU_Error_Check(cudaMemcpy(b, hb_,
bytes, cudaMemcpyHostToDevice));
297 GPU_Error_Check(cudaDeviceSynchronize());
298 MPI_Alltoall(a, countI, MPI_DOUBLE, b, countI, MPI_DOUBLE, commI_);
303 const int iLo = idi * di + idp * dip;
304 const int iHi = std::min({iLo + dip, (idi + 1) * di, ni});
305 const int kLo = idjq * dhq;
306 const int kHi = std::min(kLo + dhq, nh);
308 kHi - kLo, iHi - iLo, mip, djp, GPU_LAMBDA(
const int k,
const int i,
const int p,
const int j) {
309 const int jj = p * djp + j;
311 const int ia = jj + nj * (i + dip * k);
312 const int ib = i + dip * (k + dhq * (j + djp * p));
319 GPU_Error_Check(cufftExecZ2Z(c2cj_, ac, bc, CUFFT_INVERSE));
323 const int iLo = idi * di + idp * dip;
324 const int iHi = std::min({iLo + dip, (idi + 1) * di, ni});
325 const int kLo = idjq * dhq;
326 const int kHi = std::min(kLo + dhq, nh);
328 mj, mq, kHi - kLo, iHi - iLo, djq, GPU_LAMBDA(
const int r,
const int q,
const int k,
const int i,
const int j) {
329 const int rdj = r * dj;
330 const int jj = rdj + q * djq + j;
331 if ((jj < nj) && (jj < rdj + dj)) {
332 const int ia = j + djq * (i + dip * (k + dhq * (q + mq * r)));
333 const int ib = jj + nj * (i + dip * k);
341 GPU_Error_Check(cudaMemcpy(ha_, a,
bytes, cudaMemcpyDeviceToHost));
342 MPI_Alltoall(ha_, countJ, MPI_DOUBLE, hb_, countJ, MPI_DOUBLE, commJ_);
343 GPU_Error_Check(cudaMemcpy(b, hb_,
bytes, cudaMemcpyHostToDevice));
345 GPU_Error_Check(cudaDeviceSynchronize());
346 MPI_Alltoall(a, countJ, MPI_DOUBLE, b, countJ, MPI_DOUBLE, commJ_);
351 const int iLo = idi * di + idp * dip;
352 const int iHi = std::min({iLo + dip, (idi + 1) * di, ni});
353 const int jLo = idj * dj + idq * djq;
354 const int jHi = std::min({jLo + djq, (idj + 1) * dj, nj});
356 iHi - iLo, jHi - jLo, mjq, dhq, GPU_LAMBDA(
const int i,
const int j,
const int q,
const int k) {
357 const int kk = q * dhq + k;
359 const int ia = kk + nh * (j + djq * i);
360 const int ib = j + djq * (i + dip * (k + dhq * q));
367 GPU_Error_Check(cufftExecZ2D(c2rk_, ac, b));
371 const int iLo = idi * di + idp * dip;
372 const int iHi = std::min({iLo + dip, (idi + 1) * di, ni});
373 const int jLo = idj * dj + idq * djq;
374 const int jHi = std::min({jLo + djq, (idj + 1) * dj, nj});
376 mk, iHi - iLo, jHi - jLo, dk, GPU_LAMBDA(
const int pq,
const int i,
const int j,
const int k) {
377 const int kk = pq * dk + k;
379 const int ia = k + dk * (j + djq * (i + dip * pq));
380 const int ib = kk + nk * (j + djq * i);
388 GPU_Error_Check(cudaMemcpy(ha_, a,
bytes, cudaMemcpyDeviceToHost));
389 MPI_Alltoall(ha_, countK, MPI_DOUBLE, hb_, countK, MPI_DOUBLE, commK_);
390 GPU_Error_Check(cudaMemcpy(b, hb_,
bytes, cudaMemcpyHostToDevice));
392 GPU_Error_Check(cudaDeviceSynchronize());
393 MPI_Alltoall(a, countK, MPI_DOUBLE, b, countK, MPI_DOUBLE, commK_);
398 const double divN = 1.0 / (double(ni) * double(nj) * double(nk));
399 const int kLo = idk * dk;
400 const int kHi = std::min(kLo + dk, nk);
402 mp, dip, mq, djq, kHi - kLo, GPU_LAMBDA(
const int p,
const int i,
const int q,
const int j,
const int k) {
403 const int ii = p * dip + i;
404 const int jj = q * djq + j;
405 if ((ii < di) && (jj < dj)) {
406 const int ia = k + dk * (jj + dj * ii);
407 const int ib = k + dk * (j + djq * (i + dip * (q + mq * p)));
408 a[ia] = divN * b[ib];
Generic distributed-memory 3D FFT filter.
Definition HenryPeriodic.hpp:13
HenryPeriodic(const int n[3], const double lo[3], const double hi[3], const int m[3], const int id[3])
size_t bytes() const
Definition HenryPeriodic.hpp:34
void filter(const size_t bytes, double *const before, double *const after, const F f) const