Skip to content

adam_fnl_poisson_fft_object ​

ADAM, FNL FFT Poisson solver on uniform periodic grids (cuFFT).

Extends poisson_fft_object (issue #81, P2): the gather to rank 0, the placement and the scatter of phi with its ghosts are the CPU ones; the spectral solve runs on rank 0's GPU through cuFFT (-D_CUFFT, -cudalib=cufft). The global source goes to the device, a D2Z transform, the division by the eigenvalues of L_h (the same host-computed lam1..3 as the CPU solver), a Z2D transform, and the potential comes back. cuFFT runs on the stream of the synchronous OpenACC queue, so the transforms and the kernel between them are ordered.

Isolated boundaries (issue #81, M8-P4): the transforms are the padded ones (m), the kernel's spectrum khat is computed once on the device (transform_kernel) and stays there (enter data, released by destroy_plans); the solve multiplies by it instead of dividing by the eigenvalues.

The distributed slab transform (issue #84, E5d) keeps the CPU redistribution and return of the block planes (adam_poisson_fft_object, on the host); the transform runs on each rank's GPU, its arrays resident there (slab_r, slab_c, pen, khat_pen, the transpose buffers: enter data with the plans): slab_r goes up, the local planes (one D2Z or Z2D plan for one plane, executed on every plane in turn), the transpose to z-lines (packed and unpacked on the device, MPI_ALLTOALLV on the device buffers: GPU-aware MPI, as the ghost exchange), the local z-lines (one Z2Z plan for one row of h1 lines, on every row in turn), the spectral solve, back, and slab_r comes down. The arithmetic of a value does not depend on the rank count.

cuFFT is NVIDIA only: built without _CUFFT (an AMD build), making the plans stops the run.

Source: src/lib/fnl/adam_fnl_poisson_fft_object.F90

Dependencies

Contents ​

Derived Types ​

poisson_fft_fnl_object ​

FNL FFT Poisson solver on uniform periodic grids (cuFFT).

Inheritance

Extends: poisson_fft_object

Components ​

NameTypeAttributesDescription
is_initializedlogicalInitialization status.
ninteger(kind=I4P)Global cells per direction.
minteger(kind=I4P)Transform cells per direction: n, or >= 2 (n + ngc) isolated.
isolatedlogicalIsolated boundaries (zero padding), else periodic.
dirichletlogicalHomogeneous Dirichlet boundaries (odd extension, #87).
bcinteger(kind=I4P)Kinds per face [lo/hi, axis] (issue #84, E1a).
extendedlogicalSome axis is extended (Dirichlet or Neumann faces).
dg_orderinteger(kind=I4P)0: the compact Laplacian; p: the wide D(G) of order p (E2a).
axis_orderinteger(kind=I4P)The operator per axis (dg_order, but in E2b's sub-problems).
pcglogicalSome axis has zero-ghost faces and the operator is wide.
freelogicalSome face has free-space ghosts (E3c).
g_freereal(kind=R8P)allocatableRank 0, E3c: the free-space ghost slabs, zero elsewhere.
null_xyzlogicalNull directions.
stencilreal(kind=R8P)The 1-D D1 D1 stencil (times h^2), offsets -p..p.
tolerancereal(kind=R8P)Relative max-norm residual to stop.
max_iterationsinteger(kind=I4P)CG iterations at most.
iterationsinteger(kind=I4P)Iterations of the last solve.
residualreal(kind=R8P)Relative residual of the last solve.
redundantlogicalEvery rank holds the global arrays and solves (#84 E5c).
wallreal(kind=R8P)Wall time (s) of solve_blocks, accumulated over calls on
nsubinteger(kind=I4P)Preconditioner sub-problems, 2^z.
sub_parinteger(kind=I4P)allocatableParity per axis of each sub-problem [3,nsub] (-1: no split).
subtype(fft_slot)allocatableThe preconditioner's sub-problems [nsub] (see fft_slot).
ntinteger(kind=I4P)Cells of the periodic transform the eigenvalues refer to: n,
nijkinteger(kind=I4P)Cells per block per direction.
ngcinteger(kind=I4P)Ghost cells per side.
levelinteger(kind=I4P)Level of every block.
dxyzreal(kind=R8P)Cell spacing per direction.
lam1real(kind=R8P)allocatableEigenvalue part along x [0:n(1)/2].
lam2real(kind=R8P)allocatableEigenvalue part along y [0:n(2)-1].
lam3real(kind=R8P)allocatableEigenvalue part along z [0:n(3)-1].
f_globalreal(kind=R8P)allocatableRank 0: the source, then the potential [m(1),m(2),m(3)].
f_sourcereal(kind=R8P)allocatableRank 0: a copy of the source, for the energy.
f_hatcomplex(kind=R8P)allocatableRank 0: the transform [m(1)/2+1,m(2),m(3)].
khatreal(kind=R8P)allocatableRank 0, isolated: the kernel's spectrum over prod(m).
plan_r2ctype(c_ptr)FFTW forward plan (rank 0).
plan_c2rtype(c_ptr)FFTW backward plan (rank 0).
slablogicalEvery rank transforms its z-planes (see the module).
h1integer(kind=I4P)Complex cells along x after r2c, m(1)/2 + 1.
zrinteger(kind=I4P)allocatableFirst z-plane (0-based) of each rank's slab [0:ranks].
yrinteger(kind=I4P)allocatableFirst y-row (0-based) of each rank's pencils [0:ranks].
zowninteger(kind=I4P)allocatableOwner rank of each z-plane [0:m(3)-1].
tmapinteger(kind=I4P)allocatablePer axis, target cell -> source cell, -1 for zero [0:,3].
tsgnreal(kind=R8P)allocatablePer axis, the sign of the image [0:,3].
slab_rreal(kind=R8P)allocatableThis rank's z-planes [m(1),m(2),planes].
slab_ccomplex(kind=R8P)allocatableTheir 2-D transforms [h1,m(2),planes].
pencomplex(kind=R8P)allocatableThis rank's z-lines [m(3),h1,rows].
khat_penreal(kind=R8P)allocatableIsolated: the kernel's spectrum in pencils [m(3),h1,rows].
w_rreal(kind=R8P)allocatableFFTW: the plane buffer [m(1),m(2)].
w_ccomplex(kind=R8P)allocatableFFTW: the transformed plane buffer [h1,m(2)].
w_lcomplex(kind=R8P)allocatableFFTW: the row-of-lines buffer [m(3),h1].
plan_pr2ctype(c_ptr)FFTW: one plane, r2c.
plan_pc2rtype(c_ptr)FFTW: one plane, c2r.
plan_lfwdtype(c_ptr)FFTW: one row of z-lines, forward.
plan_lbwdtype(c_ptr)FFTW: one row of z-lines, backward.
plan_d2zinteger(kind=c_int)cuFFT forward plan (rank 0).
plan_z2dinteger(kind=c_int)cuFFT backward plan (rank 0).
has_planslogicalThe cuFFT plans exist.
khat_on_devicelogicalkhat is on the device (isolated).
plan_sd2zinteger(kind=c_int)cuFFT slab plan: one plane, D2Z (#84 E5d).
plan_sz2dinteger(kind=c_int)cuFFT slab plan: one plane, Z2D.
plan_sz2zinteger(kind=c_int)cuFFT slab plan: one row of z-lines, Z2Z.
has_slab_planslogicalThe cuFFT slab plans exist.
slab_on_devicelogicalThe slab arrays are on the device.
yowninteger(kind=I4P)allocatableOwner rank of each y-row [0:m(2)-1].
t_sbcomplex(kind=R8P)allocatableDevice: the transpose's send buffer.
t_rbcomplex(kind=R8P)allocatableDevice: the transpose's receive buffer.

Type-Bound Procedures ​

NameAttributesDescription
destroypass(self)Destroy the solver.
initializepass(self)Check the grid, size the solver, make the plans.
solvepass(self)Solve for phi from one variable of q.
solve_packedpass(self)Solve for phi from the packed interior source.
initialize_blockspass(self)Size the solver from block counts and spacing (no grid, no field).
solve_blockspass(self)Solve from an explicit list of blocks (coordinates and source).
global_potentialpass(self)Gather the slab solution to rank 0 (diagnostics).
destroy_planspass(self)Destroy the cuFFT plans.
make_planspass(self)Make the cuFFT plans (rank 0).
transformpass(self)The spectral solve on the GPU (rank 0).
transform_kernelpass(self)The kernel's spectrum on the GPU (isolated).
root_cells_maxnopass32^3: the device smooths, the host transforms.
slab_make_planspass(self)The cuFFT slab plans (#84 E5d).
slab_destroy_planspass(self)Destroy them.
slab_planespass(self)Every local plane on the GPU.
slab_linespass(self)Every local z-line on the GPU.
slab_transposepass(self)The transpose on the GPU.
slab_spectralpass(self)The spectral solve on the GPU.
slab_keep_kernelpass(self)khat_pen on the GPU.
slab_updatepass(self)slab_r to and from the GPU.

Subroutines ​

destroy_plans_fnl ​

Destroy the cuFFT plans.

fortran
subroutine destroy_plans_fnl(self)

Arguments

NameTypeIntentAttributesDescription
selfclass(poisson_fft_fnl_object)inoutThe solver.

make_plans_fnl ​

Make the cuFFT plans (D2Z and Z2D, cuFFT is row-major: the slowest dimension first) on the synchronous queue.

fortran
subroutine make_plans_fnl(self)

Arguments

NameTypeIntentAttributesDescription
selfclass(poisson_fft_fnl_object)inoutThe solver.

Call graph

transform_fnl ​

Rank 0: f_global <- factor * L_h^-1 f_global on the GPU, the modes of zero eigenvalue (the mean) set to zero.

fortran
subroutine transform_fnl(self, factor)

Arguments

NameTypeIntentAttributesDescription
selfclass(poisson_fft_fnl_object)inoutThe solver.
factorreal(kind=R8P)inSource factor.

Call graph

transform_kernel_fnl ​

Rank 0, isolated: khat <- FFT(f_global) / prod(m) on the GPU (real: the kernel is even); khat stays on the device for every solve.

fortran
subroutine transform_kernel_fnl(self)

Arguments

NameTypeIntentAttributesDescription
selfclass(poisson_fft_fnl_object)inoutThe solver.

Call graph

slab_make_plans_fnl ​

The cuFFT slab plans (#84 E5d): one plane D2Z and Z2D, one row of z-lines Z2Z (h1 lines of m(3) cells, contiguous), on the synchronous OpenACC queue's stream; the slab arrays and the transpose buffers on the device.

fortran
subroutine slab_make_plans_fnl(self)

Arguments

NameTypeIntentAttributesDescription
selfclass(poisson_fft_fnl_object)inoutThe solver.

Call graph

slab_destroy_plans_fnl ​

Destroy the cuFFT slab plans.

fortran
subroutine slab_destroy_plans_fnl(self)

Arguments

NameTypeIntentAttributesDescription
selfclass(poisson_fft_fnl_object)inoutThe solver.

slab_planes_fnl ​

Every local plane on the GPU: forward slab_r -> slab_c (D2Z), backward slab_c -> slab_r (Z2D), on the device.

fortran
subroutine slab_planes_fnl(self, forward)

Arguments

NameTypeIntentAttributesDescription
selfclass(poisson_fft_fnl_object)inoutThe solver.
forwardlogicalinDirection.

Call graph

slab_lines_fnl ​

Every local z-line on the GPU, in place in pen (Z2Z, forward or inverse), on the device.

fortran
subroutine slab_lines_fnl(self, forward)

Arguments

NameTypeIntentAttributesDescription
selfclass(poisson_fft_fnl_object)inoutThe solver.
forwardlogicalinDirection.

Call graph

slab_transpose_fnl ​

The transpose on the device: forward slab_c(x, y, z local) -> pen(z, x, y local), backward the reverse; the blocks packed by destination rank (the CPU layout), MPI_ALLTOALLV on the device buffers (skipped on one rank).

fortran
subroutine slab_transpose_fnl(self, forward)

Arguments

NameTypeIntentAttributesDescription
selfclass(poisson_fft_fnl_object)inoutThe solver.
forwardlogicalinDirection.

Call graph

slab_spectral_fnl ​

The spectral solve on the device: the division by the eigenvalues (the zero modes dropped) or, isolated, the product with the kernel's spectrum.

fortran
subroutine slab_spectral_fnl(self, factor)

Arguments

NameTypeIntentAttributesDescription
selfclass(poisson_fft_fnl_object)inoutThe solver.
factorreal(kind=R8P)inSource factor.

Call graph

slab_keep_kernel_fnl ​

Isolated, at setup: khat_pen <- real(pen) / prod(m) on the device, where it stays.

fortran
subroutine slab_keep_kernel_fnl(self)

Arguments

NameTypeIntentAttributesDescription
selfclass(poisson_fft_fnl_object)inoutThe solver.

Call graph

slab_update_fnl ​

slab_r to (to_device) or from the device.

fortran
subroutine slab_update_fnl(self, to_device)

Arguments

NameTypeIntentAttributesDescription
selfclass(poisson_fft_fnl_object)inoutThe solver.
to_devicelogicalinDirection.

Functions ​

root_cells_max_fnl ​

The most cells of a multigrid root on cuFFT (#84 E6, E6b): 32^3 whatever the transform's growth. The multigrid smooths on the device and the root's transform goes through the host's redistribution, so a small root wins (medooza FNL, 3.9 M AMR cells, 1 / 2 / 4 GPUs: periodic 0.33 / 0.19 / 0.12 s with a 32^3 root, 0.80 / 0.45 / 0.37 s with 128^3); for the isolated root 16^3 gains only 3-10% over 32^3 (0.83 / 0.51 / 0.39 against 0.85 / 0.52 / 0.43 s), not worth a uniform 32^3 grid losing its exact one-V-cycle solve.

Attributes: pure

Returns: integer(kind=I4P)

fortran
function root_cells_max_fnl(growth) result(n)

Arguments

NameTypeIntentAttributesDescription
growthinteger(kind=I4P)inTransform cells per root cell (unused: the cap is in cells).