Skip to content

adam_fnl_poisson_mg_object ​

ADAM, FNL multigrid-preconditioned conjugate-gradient Poisson solver on AMR grids (OpenACC).

Extends poisson_mg_object (issue #84, E6a): the leaves, the hierarchy and every operator are assembled on the host as there; work_place then puts the operators (the composite operator, the ghost fill, the level operators, ghost terms and transfers, CSR), the level diagonals and colours, the cell volumes, the maps of the leaves into the level spaces and the work vectors on the device, where they stay until destroy. The FCG iteration and the V-cycle run there through the hooks:

  • apply: the halo values packed on the device, exchanged by MPI_ALLTOALLV on the device buffers (GPU-aware MPI, as the ghost exchange; none on one rank), then one thread per row, its entries summed in the host's order;
  • smooth: the red-black Gauss-Seidel sweeps, one kernel per colour after its halo exchange. A row couples only to cells of the other colour (the colour is the global cell parity, the level operators are 7-point: measured, no same-colour entry), so the parallel update of a colour is the host's sequential one;
  • the vector hooks (fill, copy, combinations, dots and the max-norm by device reductions, the permutations of the leaves into the levels). The root goes through the host to the FFT solver (cuFFT by default: initialize passes poisson_fft_fnl_object when the caller gives no coarse), and so do the right-hand side, the James step and the ghost fill's placement. The results equal the host's to round-off: the dots sum in another order and the device contracts products into FMAs.

Source: src/lib/fnl/adam_fnl_poisson_mg_object.F90

Dependencies

Contents ​

Derived Types ​

poisson_mg_fnl_object ​

FNL multigrid-preconditioned CG Poisson solver on AMR grids (OpenACC).

Inheritance

Extends: poisson_mg_object

Components ​

NameTypeAttributesDescription
is_initializedlogicalInitialization status.
nijkinteger(kind=I4P)Cells per block per direction.
ncbinteger(kind=I4P)Cells per block.
ngcinteger(kind=I4P)Ghost cells per side.
ndinteger(kind=I4P)Active directions.
actinteger(kind=I4P)The active directions.
nulllogicalNull directions.
nblk0integer(kind=I4P)Blocks per direction at level 0.
dx0real(kind=R8P)Cell spacing at level 0.
lmininteger(kind=I4P)Leaf levels range.
lmaxinteger(kind=I4P)Leaf levels range.
lbotinteger(kind=I4P)The root level: lmin less the levels inside the blocks (E5c).
root_maxinteger(kind=I4P)Most cells of the root (E5c; the root solver's default).
nrinteger(kind=I4P)Ranks, this rank.
meinteger(kind=I4P)Ranks, this rank.
nleafinteger(kind=I4P)Leaves over the ranks.
leaf_cinteger(kind=I4P)allocatableLeaf block coordinates (i,j,k,level) [4,nleaf].
leaf_ownerinteger(kind=I4P)allocatableOwner rank.
leaf_locinteger(kind=I4P)allocatableLocal block index (the field's) on its owner.
leaf_hashtype(hash_table)Block key -> leaf id.
nnodeinteger(kind=I4P)Nodes.
node_cinteger(kind=I4P)allocatableNode block coordinates (i,j,k,level) [4,nnode].
node_ownerinteger(kind=I4P)allocatableOwner rank.
node_locinteger(kind=I4P)allocatableLocal block index in its level space on its owner.
node_leaflogicalallocatableThe node is a leaf.
node_hashtype(hash_table)Block key -> node id.
nloc_levinteger(kind=I4P)allocatableThis rank's blocks per level [lbot:lmax].
lev_nodeinteger(kind=I4P)allocatableThis rank's level blocks: node id [max blocks, lbot:lmax]
nleaf_locinteger(kind=I4P)This rank's leaves.
leaf_levinteger(kind=I4P)allocatableThis rank's leaf b: its level.
leaf_lev_locinteger(kind=I4P)allocatableThis rank's leaf b: its local index in its level space.
atype(dcsr)The composite operator on the leaves.
gtype(dcsr)Ghost fill: the first ghost layer of the leaves.
g_dstinteger(kind=I4P)allocatableGhost fill destinations (i,j,k,b) [4,rows].
altype(dcsr)allocatableLevel operators [lbot+1:lmax].
eltype(dcsr)allocatableLevel ghost terms from level l-1 [lbot+1:lmax].
rltype(dcsr)allocatableRestriction l -> l-1 [lbot+1:lmax].
pltype(dcsr)allocatableProlongation l-1 -> l [lbot+1:lmax].
diagtype(rvec)allocatableLevel operator diagonals [lbot+1:lmax].
colourtype(rvec)allocatableRed-black colour (0, 1) of the level cells [lbot+1:lmax].
volreal(kind=R8P)allocatableLeaf cell volumes.
bcinteger(kind=I4P)Kind per face [lo/hi, axis] (adam_flail_parameters).
periodiclogicalPeriodic axes (a null axis counts as periodic).
singularlogicalNo Dirichlet face: the operator's kernel is the constants.
eminreal(kind=R8P)Domain lower corner.
nbndinteger(kind=I4P)This rank's boundary faces.
bnd_rowinteger(kind=I4P)allocatableBoundary face: the local leaf cell (row) it bounds.
bnd_wreal(kind=R8P)allocatableBoundary face: its weight in B (see the module).
bnd_xreal(kind=R8P)allocatableBoundary face: where its value lives, ghost or face centre.
bnd_kindinteger(kind=I4P)allocatableBoundary face: its kind.
bnd_dirinteger(kind=I4P)allocatableBoundary face: the outward axis, signed (-3..3).
bnd_gsreal(kind=R8P)allocatableBoundary face: its value's weight in the ghost fill.
g_bndinteger(kind=I4P)allocatableGhost-fill row: its boundary face, 0 for an interior one.
isolatedlogicalFree-space boundaries: the ghost values by the James step.
ncinteger(kind=I4P)Cells per direction at the coarsest level.
bnd_giinteger(kind=I4P)allocatableBoundary face: its ghost cell in the widened coarsest box.
u0real(kind=R8P)allocatableThe last zero-ghost solution (warm start of the first solve).
iterations0integer(kind=I4P)Iterations of the last zero-ghost solve.
fftclass(poisson_fft_object)allocatableThe root solver, on every rank (FFTW, or the caller's backend).
gfftclass(poisson_fft_object)allocatable
tolerancereal(kind=R8P)Relative max-norm residual to stop.
max_iterationsinteger(kind=I4P)FCG iterations at most.
sweepsinteger(kind=I4P)Red-black sweeps per level, down and up.
iterationsinteger(kind=I4P)Iterations of the last solve.
residualreal(kind=R8P)Relative residual of the last solve.
tolerance_usedreal(kind=R8P)Stop tolerance of the last solve (the round-off floor of the
factor_meanreal(kind=R8P)Mean convergence factor per iteration of the last solve.
ureal(kind=R8P)allocatableThe last solution (warm start).
has_guesslogicalu holds a solution of the current grid.
wfreal(kind=R8P)allocatableprevious p and A p (leaf space).
wrreal(kind=R8P)allocatableprevious p and A p (leaf space).
wzreal(kind=R8P)allocatableprevious p and A p (leaf space).
wpreal(kind=R8P)allocatableprevious p and A p (leaf space).
wqreal(kind=R8P)allocatableprevious p and A p (leaf space).
wppreal(kind=R8P)allocatableprevious p and A p (leaf space).
wqpreal(kind=R8P)allocatableprevious p and A p (leaf space).
w1real(kind=R8P)allocatableOnes (leaf space).
wgreal(kind=R8P)allocatableGhost-fill values [g%nrow].
lrtype(rvec)allocatableV-cycle: level residual and correction [lbot:lmax].
letype(rvec)allocatableV-cycle: level residual and correction [lbot:lmax].
lt1type(rvec)allocatableV-cycle: level temporaries [lbot:lmax].
lt2type(rvec)allocatableV-cycle: level temporaries [lbot:lmax].
mlevtype(ivec)allocatablePer level: the level-space and leaf-space cells of the
mleaftype(ivec)allocatablePer level: the level-space and leaf-space cells of the
root_coordsinteger(kind=I4P)allocatableV-cycle: the root blocks [3,blocks].
root_bufreal(kind=R8P)allocatableV-cycle: the root's source and solution (host).
root_outreal(kind=R8P)allocatableV-cycle: the root's source and solution (host).
on_devicelogicalThe operators and the work vectors are on the device.
dsbreal(kind=R8P)allocatableDevice: the halo send buffer (the largest operator's).
dhbreal(kind=R8P)allocatableDevice: the halo receive buffer (the largest operator's).

Type-Bound Procedures ​

NameAttributesDescription
destroypass(self)Destroy the solver.
solvepass(self)Solve for phi from one variable of q.
solve_packedpass(self)Solve for phi from the packed interior source.
symmetry_defectpass(self)|x . A y - y . A x| / (|x| |A y|) (verification).
apply_apass(self)y = A x on the leaves (verification).
apply_bpass(self)y = B g: the boundary values onto the boundary rows.
apply_btpass(self)s = B^T x: the boundary rows onto the boundary faces.
initializepass(self)As the host's, the coarsest level on cuFFT by default.
applypass(self)y = M x on the device.
smoothpass(self)Red-black Gauss-Seidel on the device.
vec_fillnopassx(1:n) = a on the device.
vec_copynopassy(1:n) = x(1:n) on the device.
vec_lincombnopassw = x + a y on the device.
vec_axpynopassy = y + a x on the device.
vec_dotnopasssum x y on the device and the ranks.
vec_relmaxnopassmax |r / vol| on the device and the ranks.
vec_permutenopassy(iy) = x(ix) on the device.
vec_updatenopassA work vector to or from the device.
work_placepass(self)The operators and work vectors to or from the device.

Subroutines ​

initialize_fnl ​

As poisson_mg_object%initialize; without coarse, the coarsest level (and the James step's Green's function) on cuFFT.

fortran
subroutine initialize_fnl(self, grid, field, tolerance, max_iterations, coarse, isolated, bc, root_cells)

Arguments

NameTypeIntentAttributesDescription
selfclass(poisson_mg_fnl_object)inoutThe solver.
gridtype(grid_object)inThe grid.
fieldtype(field_object)inThe field (block coordinates).
tolerancereal(kind=R8P)inoptionalRelative residual to stop.
max_iterationsinteger(kind=I4P)inoptionalFCG iterations at most.
coarseclass(poisson_fft_object)inoptionalMold of the coarsest-level solver.
isolatedlogicalinoptionalFree-space boundaries (James).
bcinteger(kind=I4P)inoptionalKinds per face [lo/hi, axis].
root_cellsinteger(kind=I4P)inoptionalMost cells of the root.

Call graph

apply_fnl ​

y = M x on the device: the halo of x packed, exchanged (GPU-aware MPI_ALLTOALLV), then the local rows.

fortran
subroutine apply_fnl(self, m, x, y)

Arguments

NameTypeIntentAttributesDescription
selfclass(poisson_mg_fnl_object)inoutThe solver.
mtype(dcsr)inOperator (on the device).
xreal(kind=R8P)inLocal column-space vector (on the device).
yreal(kind=R8P)inoutResult (rows, on the device).

Call graph

smooth_fnl ​

Red-black Gauss-Seidel sweeps on level lv on the device: per colour, the halo of e, then every row of the colour (they read only the other colour's cells).

fortran
subroutine smooth_fnl(self, lv, e, rhs, order)

Arguments

NameTypeIntentAttributesDescription
selfclass(poisson_mg_fnl_object)inoutThe solver.
lvinteger(kind=I4P)inLevel.
ereal(kind=R8P)inoutCorrection (on the device).
rhsreal(kind=R8P)inRight-hand side (on the device).
orderinteger(kind=I4P)in0: colour 0 first, 1: colour 1 first.

Call graph

vec_fill_fnl ​

x(1:n) = a on the device.

fortran
subroutine vec_fill_fnl(x, a, n)

Arguments

NameTypeIntentAttributesDescription
xreal(kind=R8P)inoutVector (on the device).
areal(kind=R8P)inValue.
ninteger(kind=I4P)inEntries.

Call graph

vec_copy_fnl ​

y(1:n) = x(1:n) on the device.

fortran
subroutine vec_copy_fnl(x, y, n)

Arguments

NameTypeIntentAttributesDescription
xreal(kind=R8P)inSource (on the device).
yreal(kind=R8P)inoutDestination (on the device).
ninteger(kind=I4P)inEntries.

Call graph

vec_lincomb_fnl ​

w(1:n) = x(1:n) + a y(1:n) on the device.

fortran
subroutine vec_lincomb_fnl(x, a, y, w, n)

Arguments

NameTypeIntentAttributesDescription
xreal(kind=R8P)inFirst vector (on the device).
areal(kind=R8P)inCoefficient.
yreal(kind=R8P)inSecond vector (on the device).
wreal(kind=R8P)inoutResult (on the device).
ninteger(kind=I4P)inEntries.

Call graph

vec_axpy_fnl ​

y(1:n) = y(1:n) + a x(1:n) on the device.

fortran
subroutine vec_axpy_fnl(a, x, y, n)

Arguments

NameTypeIntentAttributesDescription
areal(kind=R8P)inCoefficient.
xreal(kind=R8P)inVector (on the device).
yreal(kind=R8P)inoutUpdated vector (on the device).
ninteger(kind=I4P)inEntries.

Call graph

vec_permute_fnl ​

y(iy(i)) = x(ix(i)), i = 1..n, on the device.

fortran
subroutine vec_permute_fnl(x, ix, y, iy, n)

Arguments

NameTypeIntentAttributesDescription
xreal(kind=R8P)inSource (on the device).
ixinteger(kind=I4P)inSource entries (on the device).
yreal(kind=R8P)inoutDestination (on the device).
iyinteger(kind=I4P)inDestination entries (on the device).
ninteger(kind=I4P)inEntries.

Call graph

vec_update_fnl ​

A work vector to (to_device) or from the device.

fortran
subroutine vec_update_fnl(x, to_device)

Arguments

NameTypeIntentAttributesDescription
xreal(kind=R8P)inoutWork vector (on the device).
to_devicelogicalinDirection.

Call graph

work_place_fnl ​

Put (attach) the operators, the level diagonals, colours and maps, the volumes and the work vectors on the device, with the halo buffers sized for the largest operator; or release them.

fortran
subroutine work_place_fnl(self, attach)

Arguments

NameTypeIntentAttributesDescription
selfclass(poisson_mg_fnl_object)inoutThe solver.
attachlogicalinPut, or release.

Call graph

halo_dev ​

The halo of x for operator m into self%dhb: x(sidx) packed into self%dsb, exchanged on the device buffers.

fortran
subroutine halo_dev(self, m, x)

Arguments

NameTypeIntentAttributesDescription
selfclass(poisson_mg_fnl_object)inoutThe solver.
mtype(dcsr)inOperator.
xreal(kind=R8P)inLocal column-space vector (on the device).

Call graph

place_csr ​

A CSR operator's arrays to (attach) or from the device (the exchange counts stay on the host).

fortran
subroutine place_csr(m, attach)

Arguments

NameTypeIntentAttributesDescription
mtype(dcsr)inoutOperator.
attachlogicalinPut, or release.

Call graph

place_r ​

A real array to (attach, copied in) or from the device (deleted); zero-size arrays stay on the host.

fortran
subroutine place_r(x, attach)

Arguments

NameTypeIntentAttributesDescription
xreal(kind=R8P)inoutArray.
attachlogicalinPut, or release.

Call graph

place_i ​

An integer array to (attach, copied in) or from the device (deleted); zero-size arrays stay on the host.

fortran
subroutine place_i(x, attach)

Arguments

NameTypeIntentAttributesDescription
xinteger(kind=I4P)inoutArray.
attachlogicalinPut, or release.

Call graph

pack_dev ​

sb(i) = x(sidx(i)), i = 1..ns, on the device.

fortran
subroutine pack_dev(ns, sidx, nx, x, nb, sb)

Arguments

NameTypeIntentAttributesDescription
nsinteger(kind=I4P)inSizes.
sidxinteger(kind=I4P)inLocal entries to send (present).
nxinteger(kind=I4P)inSizes.
xreal(kind=R8P)inVector (present).
nbinteger(kind=I4P)inSizes.
sbreal(kind=R8P)inoutSend buffer (present).

Call graph

alltoallv_dev ​

MPI_ALLTOALLV of the device buffers (GPU-aware MPI).

fortran
subroutine alltoallv_dev(ns, sb, sc, sd, nh, hb, rc, rd, ierr)

Arguments

NameTypeIntentAttributesDescription
nsinteger(kind=I4P)inBuffer sizes.
sbreal(kind=R8P)inSend buffer (present).
scinteger(kind=I4P)inCounts and displacements (values).
sdinteger(kind=I4P)inCounts and displacements (values).
nhinteger(kind=I4P)inBuffer sizes.
hbreal(kind=R8P)inoutReceive buffer (present).
rcinteger(kind=I4P)inCounts and displacements (values).
rdinteger(kind=I4P)inCounts and displacements (values).
ierrinteger(kind=I4P)outMPI error status.

Call graph

spmv_dev ​

y = M x on the device, one row per thread, the entries in the host's order.

fortran
subroutine spmv_dev(nrow, nloc, nnz, nx, ny, nh, rowptr, col, val, x, h, y)

Arguments

NameTypeIntentAttributesDescription
nrowinteger(kind=I4P)inSizes.
nlocinteger(kind=I4P)inSizes.
nnzinteger(kind=I4P)inSizes.
nxinteger(kind=I4P)inSizes.
nyinteger(kind=I4P)inSizes.
nhinteger(kind=I4P)inSizes.
rowptrinteger(kind=I4P)inRow pointers (present).
colinteger(kind=I4P)inColumn slots (present).
valreal(kind=R8P)inValues (present).
xreal(kind=R8P)inLocal columns (present).
hreal(kind=R8P)inHalo columns (present).
yreal(kind=R8P)inoutResult (present).

Call graph

sweep_dev ​

One colour of a red-black Gauss-Seidel sweep on the device: e(i) = (rhs(i) - sum_{j /= i} a_ij e_j) / a_ii for the rows of colour colr, the off-diagonal entries in the host's order.

fortran
subroutine sweep_dev(nrow, nloc, nnz, ne, nr, nh, nd, colr, rowptr, col, val, diag, colour, rhs, h, e)

Arguments

NameTypeIntentAttributesDescription
nrowinteger(kind=I4P)inSizes.
nlocinteger(kind=I4P)inSizes.
nnzinteger(kind=I4P)inSizes.
neinteger(kind=I4P)inSizes.
nrinteger(kind=I4P)inSizes.
nhinteger(kind=I4P)inSizes.
ndinteger(kind=I4P)inSizes.
colrinteger(kind=I4P)inColour of this pass.
rowptrinteger(kind=I4P)inRow pointers (present).
colinteger(kind=I4P)inColumn slots (present).
valreal(kind=R8P)inValues (present).
diagreal(kind=R8P)inDiagonal (present).
colourreal(kind=R8P)inColour of each row, 0 or 1 (present).
rhsreal(kind=R8P)inRight-hand side (present).
hreal(kind=R8P)inHalo of e (present).
ereal(kind=R8P)inoutCorrection (present).

Call graph

fill_dev ​

x(1:n) = a on the device.

fortran
subroutine fill_dev(nx, x, a, n)

Arguments

NameTypeIntentAttributesDescription
nxinteger(kind=I4P)inSizes.
xreal(kind=R8P)inoutVector (present).
areal(kind=R8P)inValue.
ninteger(kind=I4P)inSizes.

Call graph

lincomb_dev ​

w(1:n) = x(1:n) + a y(1:n) (comb) or w(1:n) = x(1:n) on the device.

fortran
subroutine lincomb_dev(nx, x, a, ny, y, nw, w, n, comb)

Arguments

NameTypeIntentAttributesDescription
nxinteger(kind=I4P)inSizes.
xreal(kind=R8P)inFirst vector (present).
areal(kind=R8P)inCoefficient.
nyinteger(kind=I4P)inSizes.
yreal(kind=R8P)inSecond vector (present).
nwinteger(kind=I4P)inSizes.
wreal(kind=R8P)inoutResult (present).
ninteger(kind=I4P)inSizes.
comblogicalinCombine, or copy x.

Call graph

axpy_dev ​

y(1:n) = y(1:n) + a x(1:n) on the device.

fortran
subroutine axpy_dev(a, nx, x, ny, y, n)

Arguments

NameTypeIntentAttributesDescription
areal(kind=R8P)inCoefficient.
nxinteger(kind=I4P)inSizes.
xreal(kind=R8P)inVector (present).
nyinteger(kind=I4P)inSizes.
yreal(kind=R8P)inoutUpdated vector (present).
ninteger(kind=I4P)inSizes.

Call graph

permute_dev ​

y(iy(i)) = x(ix(i)), i = 1..n, on the device.

fortran
subroutine permute_dev(nx, x, nix, ix, ny, y, niy, iy, n)

Arguments

NameTypeIntentAttributesDescription
nxinteger(kind=I4P)inSizes.
xreal(kind=R8P)inSource (present).
nixinteger(kind=I4P)inSizes.
ixinteger(kind=I4P)inSource entries (present).
nyinteger(kind=I4P)inSizes.
yreal(kind=R8P)inoutDestination (present).
niyinteger(kind=I4P)inSizes.
iyinteger(kind=I4P)inDestination entries (present).
ninteger(kind=I4P)inSizes.

Call graph

update_dev ​

x to (to_device) or from the device.

fortran
subroutine update_dev(nx, x, to_device)

Arguments

NameTypeIntentAttributesDescription
nxinteger(kind=I4P)inSize.
xreal(kind=R8P)inoutVector (present).
to_devicelogicalinDirection.

Call graph

Functions ​

vec_dot_fnl ​

sum_i x_i y_i over the local n entries (a device reduction) and the ranks.

Returns: real(kind=R8P)

fortran
function vec_dot_fnl(x, y, n) result(d)

Arguments

NameTypeIntentAttributesDescription
xreal(kind=R8P)inFirst vector (on the device).
yreal(kind=R8P)inSecond vector (on the device).
ninteger(kind=I4P)inLocal entries.

Call graph

vec_relmax_fnl ​

max |r / vol| over the local n entries (a device reduction) and the ranks, over fmax (when positive).

Returns: real(kind=R8P)

fortran
function vec_relmax_fnl(r, vol, n, fmax) result(rm)

Arguments

NameTypeIntentAttributesDescription
rreal(kind=R8P)inResidual (on the device).
volreal(kind=R8P)inCell volumes (on the device).
ninteger(kind=I4P)inLocal entries.
fmaxreal(kind=R8P)inNormalisation.

Call graph

dot_dev ​

sum_{i<=n} x_i y_i on the device.

Returns: real(kind=R8P)

fortran
function dot_dev(nx, x, ny, y, n) result(d)

Arguments

NameTypeIntentAttributesDescription
nxinteger(kind=I4P)inSizes.
xreal(kind=R8P)inFirst vector (present).
nyinteger(kind=I4P)inSizes.
yreal(kind=R8P)inSecond vector (present).
ninteger(kind=I4P)inSizes.

Call graph

relmax_dev ​

max_{i<=n} |r_i / vol_i| on the device.

Returns: real(kind=R8P)

fortran
function relmax_dev(nr, r, nv, vol, n) result(rm)

Arguments

NameTypeIntentAttributesDescription
nrinteger(kind=I4P)inSizes.
rreal(kind=R8P)inResidual (present).
nvinteger(kind=I4P)inSizes.
volreal(kind=R8P)inCell volumes (present).
ninteger(kind=I4P)inSizes.

Call graph