Skip to content

adam_prism_fnl_pic_conserving_object ​

ADAM, PRISM charge-conserving PIC current (direct, Esirkepov, esirkepov_Q<N>), FNL backend.

Device port of the CPU charge-conserving current chain of prism_cpu_object (integrate_rk_ssp_pic_charge_conserving and the helpers it calls). Host-side twins of the CPU matrix builders/factorization live here (private) so the CPU backend is left untouched; the arithmetic of every kernel follows the CPU routine named in its header line.

Multi-block and multi-rank (single refinement level): every solver works on a virtual block, the whole domain seen as one NX x NY x NZ block (NX = nbx*ni, ...). The conserving operators are global along grid lines (the inverses of the direct/Esirkepov line matrices are dense, the modified face flux is a prefix sum from the domain boundary, the P/Q filters reach up to 7/5 cells), so a single-block solve of the whole domain is the reference result: on the virtual block the phase-1 single-block kernels run unchanged and the multi-block result equals the single-block one by construction. The real blocks are touched only at the two interfaces: (i) inputs, Esirkepov directly in global cell indices, the direct decomposition and the modified rho through the regular block deposit + reduce_ghost_local_gpu + gather of the block interiors; (ii) outputs, J (and the filtered rho) scattered from the virtual block to every real cell, ghosts included, so interface ghosts get the neighbour values and physical ghosts the single-block odd/zero values. With one block the virtual block is the block itself (same origin, spacing and cell centers): phase-1 arithmetic. Several ranks: the virtual block is replicated on every rank. Each rank adds the sources of its own particles on the virtual cells (block interiors and in-domain ghosts, so that no ghost fold is needed), the complete sources are summed over the ranks (reduce_virtual, MPI_Allreduce staged through the host), every rank runs the same virtual solve and scatters the result on its own blocks. The per-particle cleanup sums the particle currents of each rank, then reduces the virtual current.

Device layouts (FNL convention, block index first):

  • real q-like fields: [nb, 1-ngc:ni+ngc, 1-ngc:nj+ngc, 1-ngc:nk+ngc, nv];
  • virtual fields: the same with nb=1 and NX, NY, NZ (H, scratches, line buffers, the virtual current jv_gpu);
  • directional charge changes H: [1, NX, NY, NZ, 3] (interior only, the CPU solvers never read H ghosts);
  • particles: [particle, variable] (coalesced across particles).

Like the CPU reference, a particle whose support touches the domain boundary stops the run (zero-flux closure, no particle boundary conditions).

Source: src/app/prism/fnl/adam_prism_fnl_pic_conserving_object.F90

Dependencies

Contents ​

Variables ​

NameTypeAttributesDescription
CONSERVING_SOLVER_DIRECTinteger(kind=I4P)parameterDirect line-solve of D J = -H/dt.
CONSERVING_SOLVER_ESIRKEPOVinteger(kind=I4P)parameterEsirkepov face fluxes + inverse reconstruction.
CONSERVING_SOLVER_MODIFIEDinteger(kind=I4P)parameteresirkepov_Q matched current (P/Q kernels).
SHAPE_NGPinteger(kind=I4P)parameterNGP particle shape.
SHAPE_CICinteger(kind=I4P)parameterCIC particle shape.
SHAPE_TSCinteger(kind=I4P)parameterTSC particle shape.
SHAPE_CUBICinteger(kind=I4P)parameterCubic particle shape.
SHAPE_QUARTICinteger(kind=I4P)parameterQuartic particle shape.
SHAPE_QUINTICinteger(kind=I4P)parameterQuintic particle shape.
SHAPE_SEXTICinteger(kind=I4P)parameterSextic particle shape.
SHAPE_GAUSSIANinteger(kind=I4P)parameterGaussian particle shape.
MAX_SPANinteger(kind=I4P)parameterMax 1D cells touched by one particle trajectory (gang-private weights).
ERR_OUTSIDEinteger(kind=I4P)parameterParticle outside the domain.
ERR_CHARGEinteger(kind=I4P)parameterParticle charge changed during the trajectory.
ERR_BOUNDARYinteger(kind=I4P)parameterParticle shape touches the domain boundary.
ERR_FILTERinteger(kind=I4P)parameteresirkepov_Q P filter support reaches the domain boundary.
ERR_SPANinteger(kind=I4P)parameterTrajectory support wider than MAX_SPAN (FNL-only limit).
ERR_GAUSSinteger(kind=I4P)parameterEmpty Gaussian deposition support.
ERR_PUinteger(kind=I4P)parameterB-spline weights do not sum to one on the deposition stencil.
TAU_TAILreal(kind=R8P)parameterRelative tail threshold of the particle current cleanup (CPU twin).
TAU_PUreal(kind=R8P)parameterMax |raw B-spline weight sum - 1| before the closure (CPU twin).

Derived Types ​

prism_fnl_pic_conserving_object ​

Charge-conserving PIC current, device state and kernels.

Components ​

NameTypeAttributesDescription
enabledlogicalConserving current active.
preparedlogicalGeometry-dependent caches built.
solverinteger(kind=I4P)Selected solver (CONSERVING_SOLVER_*).
shapeinteger(kind=I4P)Particle shape (SHAPE_*).
filter_depositionlogicalBinomial filter on deposition.
tail_cleanuplogicalesirkepov_Q per-particle tail cleanup.
sigmareal(kind=R8P)Gaussian width.
cutoff_sigmareal(kind=R8P)Gaussian cutoff in sigma units.
gaussian_support_cellsinteger(kind=I4P)Gaussian support radius in cells.
fdv_orderinteger(kind=I4P)FD order.
hsinteger(kind=I4P)FD half stencil.
niinteger(kind=I4P)Virtual block sizes (whole domain), ghost cells.
njinteger(kind=I4P)Virtual block sizes (whole domain), ghost cells.
nkinteger(kind=I4P)Virtual block sizes (whole domain), ghost cells.
ngcinteger(kind=I4P)Virtual block sizes (whole domain), ghost cells.
nbinteger(kind=I4P)Virtual blocks (always 1).
blocks_numberinteger(kind=I4P)Virtual blocks (always 1).
bniinteger(kind=I4P)Real block sizes.
bnjinteger(kind=I4P)Real block sizes.
bnkinteger(kind=I4P)Real block sizes.
bnbinteger(kind=I4P)Real allocated blocks.
bblocksinteger(kind=I4P)Real actual blocks (cache key).
veminreal(kind=R8P)Virtual block origin (domain minimum).
vdxreal(kind=R8P)Cell size (single refinement level).
nvinteger(kind=I4P)Field variables number.
particle_numberinteger(kind=I4P)Particles number owned by this rank.
particle_number_globalinteger(kind=I4P)Particles number, all ranks.
nrkinteger(kind=I4P)RK stages number.
esirkepov_qinteger(kind=I4P)Q filter coefficients of esirkepov_Q.
solver_namecharacter(len=:)allocatableInput name of the solver (messages).
radiusinteger(kind=I4P)Modified P/Q kernels geometry.
qfirstinteger(kind=I4P)Modified P/Q kernels geometry.
nqinteger(kind=I4P)Modified P/Q kernels geometry.
shiftreal(kind=R8P)Base-shape position shift: dx/2 for the odd Q (dual nodes), 0 otherwise.
preal(kind=R8P)Modified P kernel (cell centers / transverse lines).
qwreal(kind=R8P)Modified Q kernel (normal faces to centers).
residual_maxreal(kind=R8P)Max current-solver residual of the current step.
off_gpuinteger(kind=I4P)pointerReal block origin in the virtual block, cells [bnb,3].
vx_gpureal(kind=R8P)pointerVirtual x cell centers [NX].
vy_gpureal(kind=R8P)pointerVirtual y cell centers [NY].
vz_gpureal(kind=R8P)pointerVirtual z cell centers [NZ].
jv_gpureal(kind=R8P)pointerVirtual current [1,ghosts...,3].
p_gpureal(kind=R8P)pointerP kernel [-7:7].
qw_gpureal(kind=R8P)pointerQ kernel [0:9].
fv1_gpureal(kind=R8P)pointerFV1_CC(1:hs,hs), face reconstruction coefficients.
fd1_gpureal(kind=R8P)pointerFD1_CC(1:hs,hs), centered derivative coefficients.
h_gpureal(kind=R8P)pointerStage directional charge changes [nb,ni,nj,nk,3,nrk].
q_next_gpureal(kind=R8P)pointerParticle stage target [np,8].
q_ref_gpureal(kind=R8P)pointerParticle reference (step start / t0 minus) [np,8].
q_hist_gpureal(kind=R8P)pointerParticle stage targets history [np,8,nrk].
q_mixed_gpureal(kind=R8P)pointerMixed positions, direct decomposition [np,8].
work_a_gpureal(kind=R8P)pointerInterior scratch [nb,ni,nj,nk].
work_b_gpureal(kind=R8P)pointerInterior scratch [nb,ni,nj,nk].
line_gpureal(kind=R8P)pointerLine-major scratch for line solves/scans.
rho_work_gpureal(kind=R8P)pointerReal-block charge deposit scratch, direct [bnb,ghosts...,1].
gather_gpureal(kind=R8P)pointerReal-block field copy, external-field gather [bnb,...,nv].
jp_gpureal(kind=R8P)pointerSingle-particle virtual current, cleanup [1,ghosts...,3].
src_gpureal(kind=R8P)pointerSingle-particle source, cleanup [nb,ni,nj,nk,3].
src_stage_gpureal(kind=R8P)pointerSingle-particle stage sources [nb,ni,nj,nk,3,nrk].
mat_x_gpureal(kind=R8P)pointerFactored x-line matrices [ni,ni,nb].
mat_y_gpureal(kind=R8P)pointerFactored y-line matrices [nj,nj,nb].
mat_z_gpureal(kind=R8P)pointerFactored z-line matrices [nk,nk,nb].
piv_x_gpuinteger(kind=I4P)pointerx-line pivots [ni,nb].
piv_y_gpuinteger(kind=I4P)pointery-line pivots [nj,nb].
piv_z_gpuinteger(kind=I4P)pointerz-line pivots [nk,nb].

Type-Bound Procedures ​

NameAttributesDescription
destroypass(self)Free device data.
initializepass(self)Initialize from host configuration.
preparepass(self)Build geometry-dependent caches.
allocate_gatherpass(self)Allocate the external-field gather copy.
copy_fieldpass(self)Copy a q-like device field.
copy_particlespass(self)Copy a device particle array.
build_stage_targetpass(self)q_next = q_pic + dt sum_r c_r k_r.
build_centered_trajectorypass(self)t=0 virtual trajectory q_pic -/+ dt/2 v.
esirkepov_displacementpass(self)Esirkepov directional charge change.
decomposition_displacementpass(self)Telescopic directional charge change (direct).
combine_stage_sourcepass(self)H_s = (H_s - sum_r c_r H_r)/c_s.
solve_dispatchpass(self)Select the configured current solver.
solve_linespass(self)Direct / Esirkepov line solves.
solve_modifiedpass(self)esirkepov_Q matched current.
solve_modified_with_cleanuppass(self)Per-particle modified current with tail cleanup.
deposit_modified_chargepass(self)Unfiltered deposit + P_c filter of rho.
impose_current_ghostspass(self)Odd/zero current ghosts on the physical faces of real blocks.
reduce_virtual4pass(self)Sum a rank-4 virtual-block array over the ranks.
reduce_virtual5pass(self)Sum a rank-5 virtual-block array over the ranks.
reduce_virtualSum a virtual-block array over the ranks.
build_virtual_geometrypass(self)Virtual block of the whole domain.
scatter_currentpass(self)Real q(J) = virtual J, ghosts included.
impose_virtual_ghostspass(self)Odd/zero current ghosts of the virtual block.
check_source_supportpass(self)Particle source inside its trajectory support box.

Subroutines ​

destroy ​

Free device data owned by this object.

fortran
subroutine destroy(self)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inoutConserving current object.

Call graph

initialize ​

Initialize from the host configuration and allocate the step-invariant device buffers. Twin of the CPU validation in prism_cpu_object%initialize plus the allocations of integrate_rk_ssp_pic_charge_conserving. The virtual block (whole domain) is built here: the blocks must already be in place (uniform refinement included).

fortran
subroutine initialize(self, pic, grid, field, nb, nv, nrk, fdv_order, hs)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inoutConserving current object.
pictype(prism_pic_object)inHost PIC object.
gridtype(grid_object)inGrid.
fieldtype(field_object)inHost field (block geometry).
nbinteger(kind=I4P)inAllocated real blocks.
nvinteger(kind=I4P)inField variables number.
nrkinteger(kind=I4P)inRK stages number.
fdv_orderinteger(kind=I4P)inFD order.
hsinteger(kind=I4P)inFD half stencil.

Call graph

prepare ​

Build the geometry-dependent caches: virtual block geometry and the factored line matrices. Twin of CPU ensure_esirkepov_current_solver_cache / ensure_direct_current_solver_cache (host factorization, one upload). The matrices span whole virtual lines (the domain extent), one per direction (single refinement level).

fortran
subroutine prepare(self, field, grid, force)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inoutConserving current object.
fieldtype(field_object)inHost field.
gridtype(grid_object)inGrid.
forcelogicalinoptionalRebuild even if already prepared.

Call graph

allocate_gather ​

Allocate the field copy used to gather with external fields (CPU twin: q_gather).

fortran
subroutine allocate_gather(self)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inoutConserving current object.

Call graph

copy_field ​

dst = src, full real-block q-like device field (ghosts included).

fortran
subroutine copy_field(self, src, dst)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inConserving current object.
srcreal(kind=R8P)inSource.
dstreal(kind=R8P)inoutDestination.

Call graph

copy_particles ​

dst = src, device particle arrays [np,8].

fortran
subroutine copy_particles(self, src, dst)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inConserving current object.
srcreal(kind=R8P)inSource.
dstreal(kind=R8P)inoutDestination.

Call graph

build_stage_target ​

q_next(1:6) = q_pic(1:6) + dt sum_{r<=s} coeff(r) k_r(1:6), q_next(7:8) = q_pic(7:8). CPU twin: the q_pic_next loop of integrate_rk_ssp_pic_charge_conserving (same r order).

fortran
subroutine build_stage_target(self, q_pic, q_pic_rk, s, coeff, dt)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inoutConserving current object.
q_picreal(kind=R8P)inParticles at step start [np,8].
q_pic_rkreal(kind=R8P)inStage right-hand sides [np,8,nrk].
sinteger(kind=I4P)inCurrent stage.
coeffreal(kind=R8P)inStage coefficients (1:s used).
dtreal(kind=R8P)inTime step.

Call graph

build_centered_trajectory ​

q_ref = q_pic - dt/2 v, q_next = q_pic + dt/2 v (positions only). CPU twin: initialize_pic_conserving_current_time_zero.

fortran
subroutine build_centered_trajectory(self, q_pic, dt)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inoutConserving current object.
q_picreal(kind=R8P)inParticles [np,8].
dtreal(kind=R8P)inVirtual time step.

Call graph

esirkepov_displacement ​

Symmetric Esirkepov density decomposition. CPU twin: compute_pic_esirkepov_displacement.

Parallel mapping: one gang per particle, one vector lane per cell of the particle's trajectory box. The six 1D weight vectors (3 directions x 2 endpoints) are computed once per gang into gang-private arrays (CPU recomputes them inside the triple loop for the non-Gaussian/non-quartic shapes: same values, fewer evaluations). Different particles may overlap, hence the atomic updates.

Cells are virtual-block (global) indices: a trajectory box may straddle any number of real blocks, only the domain boundary (and MAX_SPAN) limits it.

fortran
subroutine esirkepov_displacement(self, field_fnl, q_ref, q_to, h, p_first, p_last)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inConserving current object.
field_fnltype(field_fnl_object)inDevice field helper (unused: virtual geometry).
q_refreal(kind=R8P)inTrajectory start [np,8].
q_toreal(kind=R8P)inTrajectory end [np,8].
hreal(kind=R8P)inoutDirectional charge change [1,NX,NY,NZ,3].
p_firstinteger(kind=I4P)inFirst particle.
p_lastinteger(kind=I4P)inLast particle.

Call graph

decomposition_displacement ​

Directional telescopic decomposition of rho(q_to)-rho(q_ref) with the configured deposit. CPU twin: compute_pic_charge_displacement_decomposition (+ deposit_pic_charge_density). Each of the 36 deposits is the regular device deposit (grid index + particle_weighting_dev) into a single-slot real-block scratch, so no full-nv work array is allocated (the CPU allocates q_work with all nv variables). The ghost spill of each deposit is folded back onto the neighbour blocks (reduce_ghost_local_gpu), then the complete block interiors are gathered into the virtual H.

fortran
subroutine decomposition_displacement(self, pic_fnl, field_fnl, field, grid, q_ref, q_to, h)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inoutConserving current object.
pic_fnltype(prism_fnl_pic_object)inoutDevice PIC helper.
field_fnltype(field_fnl_object)inDevice field helper.
fieldtype(field_object)inHost field.
gridtype(grid_object)inGrid.
q_refreal(kind=R8P)inTrajectory start [np,8].
q_toreal(kind=R8P)inTrajectory end [np,8].
hreal(kind=R8P)inoutDirectional charge change [nb,ni,nj,nk,3].

Call graph

combine_stage_source ​

H_s = (H_s - sum_{r<s} coeff(r) H_r) / coeff(s). CPU twin: the h_q SSP combination of the conserving integrator.

fortran
subroutine combine_stage_source(self, h, s, coeff)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inConserving current object.
hreal(kind=R8P)inoutStage sources [nb,ni,nj,nk,3,nrk].
sinteger(kind=I4P)inCurrent stage.
coeffreal(kind=R8P)inStage coefficients (1:s used).

Call graph

solve_dispatch ​

Select the configured current reconstruction. CPU twin: solve_pic_charge_conserving_current_dispatch. The solve runs on the virtual block (jv_gpu), then J is scattered to the real blocks, ghosts included.

fortran
subroutine solve_dispatch(self, field_fnl, q, var_jx, hq, dt)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inoutConserving current object.
field_fnltype(field_fnl_object)inDevice field helper.
qreal(kind=R8P)inoutReal target field.
var_jxinteger(kind=I4P)inJx slot in q (Jy, Jz follow).
hqreal(kind=R8P)inDirectional source [1,NX,NY,NZ,3].
dtreal(kind=R8P)inTime step.

Call graph

solve_lines ​

Direct (D J = -H/dt) or Esirkepov (face prefix sum + inverse reconstruction) line solves along x, y, z. CPU twins: solve_pic_charge_conserving_current, solve_pic_charge_conserving_current_esirkepov, build_esirkepov_face_line, update_esirkepov_face_residual, update_current_line_solver_residual, solve_factored_matrix_pivot.

Parallel mapping: one thread per grid line (b, t1, t2), sequential LU substitution along the line against the cached factored matrix of its block (all lanes of a block read the same matrix entry: broadcast). The line is staged in a line-major scratch line(line + nl*(m-1)), so at each substitution step adjacent lanes touch adjacent words (coalesced), instead of the strided q(b,i,j,k,v) layout (stride nb*(ni+2ngc) for x-lines). The CPU flux array is not stored: the residual pass rebuilds the prefix sum in the same order.

fortran
subroutine solve_lines(self, field_fnl, q, var_jx, hq, dt)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inoutConserving current object.
field_fnltype(field_fnl_object)inDevice field helper.
qreal(kind=R8P)inoutTarget field.
var_jxinteger(kind=I4P)inJx slot in q.
hqreal(kind=R8P)inDirectional source [nb,ni,nj,nk,3].
dtreal(kind=R8P)inTime step.

Call graph

solve_modified ​

J_d = Q_d P_transverse F_d^E. CPU twins: solve_pic_charge_conserving_current_modified, filter_modified_axis, modified_current_line, build_esirkepov_face_line.

Parallel mapping: (1) the two transverse P filters are fully parallel separable convolutions (one thread per cell, zero extension outside the block interior, taps summed in the CPU order); (2) the face prefix sum F^E is a scan along each line, one thread per line, written line-major into the scratch; (3) the Q convolution F^E -> J is again one thread per cell, reading the line-major scratch with line-fastest (coalesced) indexing. Only steps (2) is sequential and it is O(n) per line.

fortran
subroutine solve_modified(self, field_fnl, q, var_jx, hq, dt)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inoutConserving current object.
field_fnltype(field_fnl_object)inDevice field helper.
qreal(kind=R8P)inoutTarget field.
var_jxinteger(kind=I4P)inJx slot in q.
hqreal(kind=R8P)inDirectional source [nb,ni,nj,nk,3].
dtreal(kind=R8P)inTime step.

Call graph

solve_modified_with_cleanup ​

Per-particle modified current with tail cleanup, then accumulation. CPU twins: solve_modified_current_with_cleanup, cleanup_modified_particle_current, report_particle_tail_error.

The particle loop stays on the host, as on the CPU (each particle needs a whole-grid modified solve, so the work per particle is already a set of grid-parallel kernels). The support box of each particle is obtained with min/max reductions (no device-to-host array copy). The tail check reports the largest offending ratio instead of the first offending cell. Everything runs on the virtual block (support boxes in global cells, so a box may straddle real blocks); the accumulated current is scattered to the real blocks at the end.

fortran
subroutine solve_modified_with_cleanup(self, pic_fnl, field_fnl, q, var_jx, q_ref, q_hist, active_stage, alph, beta, dt, mixed_source)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inoutConserving current object.
pic_fnltype(prism_fnl_pic_object)inDevice PIC helper.
field_fnltype(field_fnl_object)inDevice field helper.
qreal(kind=R8P)inoutReal target.
var_jxinteger(kind=I4P)inJx slot in q.
q_refreal(kind=R8P)inTrajectory start [np,8].
q_histreal(kind=R8P)inStage targets [np,8,>=stages].
active_stageinteger(kind=I4P)inActive stage (0 = t0 virtual step).
alphreal(kind=R8P)inSSP alpha coefficients (host).
betareal(kind=R8P)inSSP beta coefficients (host).
dtreal(kind=R8P)inTime step.
mixed_sourcereal(kind=R8P)inoptionalMixed stage source.

Call graph

deposit_modified_charge ​

Deposit the unfiltered particle shape, then apply P_c in all directions. CPU twin: deposit_pic_modified_charge. The neighbour list must be current (caller runs the grid index first, as on the CPU).

Multi-block: the regular deposit lands in the real blocks (ghost spill folded back with reduce_ghost_local_gpu), the complete interiors are gathered into the virtual block, filtered there (P reaches 7 cells, beyond ngc), and the result is scattered back to every real cell: interior and interface ghosts get the filtered values, physical ghosts 0 (as the single-block CPU, which zeroes the rho ghosts).

fortran
subroutine deposit_modified_charge(self, pic_fnl, field_fnl, field, grid, q, nv)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inoutConserving current object.
pic_fnltype(prism_fnl_pic_object)inoutDevice PIC helper.
field_fnltype(field_fnl_object)inDevice field helper.
fieldtype(field_object)inHost field.
gridtype(grid_object)inGrid.
qreal(kind=R8P)inoutReal field.
nvinteger(kind=I4P)inCharge density slot.

Call graph

impose_current_ghosts ​

Odd mirror (Esirkepov variants: zero normal face flux) or zero (direct) current ghosts on the PHYSICAL faces of the real blocks; interface ghosts are left to the ghost exchange. CPU twins: impose_odd_current_ghosts, impose_zero_current_ghosts (single block: every face is physical). Every ghost write reads a cell that is interior in the component's own direction, so all three components are imposed in one race-free kernel.

fortran
subroutine impose_current_ghosts(self, q, var_jx)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inConserving current object.
qreal(kind=R8P)inoutReal field.
var_jxinteger(kind=I4P)inJx slot in q.

Call graph

reduce_virtual4 ​

Sum a rank-4 virtual-block device array over the ranks, in place: every rank adds the sources of its own particles, the sum is the source of all the particles. Staged through the host: an MPI_Allreduce on device buffers is not portable (the UCC/UCX collectives of HPC-X read device memory as host memory on WSL, SIGSEGV). No-op on one rank. Collective.

fortran
subroutine reduce_virtual4(self, a)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inConserving current object.
areal(kind=R8P)inoutDevice array.

Call graph

reduce_virtual5 ​

Rank-5 twin of reduce_virtual4.

fortran
subroutine reduce_virtual5(self, a)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inConserving current object.
areal(kind=R8P)inoutDevice array.

Call graph

build_virtual_geometry ​

Build the virtual block of the whole domain: sizes, origin, spacing, cell centers and the origin of every local real block. Requirements (error otherwise): one refinement level (all blocks of all ranks with the same spacing), real blocks of all ranks tiling the domain exactly once. With one block the virtual block is the block itself. The virtual cell centers are the real ones of the blocks that hold them (gathered over the ranks): the Esirkepov weights use the field geometry of the run, identical on every rank.

fortran
subroutine build_virtual_geometry(self, field, grid)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inoutConserving current object.
fieldtype(field_object)inHost field.
gridtype(grid_object)inGrid.

Call graph

scatter_current ​

Real q(J) = virtual J at the same global cell, for every real cell including ghosts: interface ghosts receive the neighbour values, physical ghosts the virtual (single-block) odd/zero ghosts. Other variables are untouched.

fortran
subroutine scatter_current(self, q, var_jx)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inConserving current object.
qreal(kind=R8P)inoutReal field.
var_jxinteger(kind=I4P)inJx slot in q.

Call graph

impose_virtual_ghosts ​

Odd mirror (Esirkepov variants) or zero (direct) current ghosts of the virtual block (all its faces are physical). CPU twins: impose_odd_current_ghosts, impose_zero_current_ghosts.

fortran
subroutine impose_virtual_ghosts(self, q, var_jx)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inConserving current object.
qreal(kind=R8P)inoutVirtual field.
var_jxinteger(kind=I4P)inJx slot in q.

Call graph

check_source_support ​

Stop if the directional source of one particle has nonzero cells outside the support box built from its trajectory end points. Box and source must describe the same trajectory; a mismatch would otherwise surface downstream as a misleading "current outside theoretical support" tail error. CPU twin: the same check in solve_modified_current_with_cleanup.

fortran
subroutine check_source_support(self, h, slo, shi, particle)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inConserving current object.
hreal(kind=R8P)inParticle source [1,NX,NY,NZ,3].
slointeger(kind=I4P)inSupport box, lower cell.
shiinteger(kind=I4P)inSupport box, upper cell.
particleinteger(kind=I4P)inParticle index (report only).

Call graph

zero_h ​

h = 0 over the interior directional source.

fortran
subroutine zero_h(self, h)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inConserving current object.
hreal(kind=R8P)inoutDirectional source [nb,ni,nj,nk,3].

Call graph

zero_current ​

q(J) = 0 over the full extent (CPU: q(var_Jx:var_Jz,:,:,:😅 = 0).

fortran
subroutine zero_current(self, q, var_jx)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inConserving current object.
qreal(kind=R8P)inoutField.
var_jxinteger(kind=I4P)inJx slot in q.

Call graph

filter_axis ​

Separable P convolution along one axis, zero extension outside the block interior. CPU twin: filter_modified_axis (taps summed from -radius to +radius, as on the CPU).

fortran
subroutine filter_axis(self, input, output, axis)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inConserving current object.
inputreal(kind=R8P)inInput [nb,ni,nj,nk].
outputreal(kind=R8P)inoutOutput [nb,ni,nj,nk].
axisinteger(kind=I4P)inFilter axis.

Call graph

line_cell ​

Cell (i,j,k) of the m-th element of the line (t1,t2) along dir.

Attributes: pure

fortran
subroutine line_cell(dir, m, t1, t2, i, j, k)

Arguments

NameTypeIntentAttributesDescription
dirinteger(kind=I4P)in
minteger(kind=I4P)in
t1integer(kind=I4P)in
t2integer(kind=I4P)in
iinteger(kind=I4P)out
jinteger(kind=I4P)out
kinteger(kind=I4P)out

Call graph

shape_weights_dev ​

1D Esirkepov weights of one endpoint on the trajectory box. CPU twins: compute_esirkepov_gaussian_shape_1d, closed_shape_1d (unfiltered B-splines, closed weights of bspline_closed_weights), esirkepov_shape_weight_1d.

Attributes: pure

fortran
subroutine shape_weights_dev(shp, filter, sigma, cutoff_limit, radius, x, ic, span, dx, xc, w, perr)

Arguments

NameTypeIntentAttributesDescription
shpinteger(kind=I4P)inShape.
filterlogicalinBinomial filter on the Esirkepov shape.
sigmareal(kind=R8P)inGaussian width.
cutoff_limitreal(kind=R8P)inGaussian cutoff.
radiusinteger(kind=I4P)inSupport radius.
xreal(kind=R8P)inParticle coordinate.
icinteger(kind=I4P)inParticle cell, local box index.
spaninteger(kind=I4P)inBox cells.
dxreal(kind=R8P)inCell size.
xcreal(kind=R8P)inCell centers of the box.
wreal(kind=R8P)outWeights on the box.
perrinteger(kind=I4P)inoutError code.

Call graph

check_particle_error ​

Translate a device particle error code into the CPU error message.

fortran
subroutine check_particle_error(ierr)

Arguments

NameTypeIntentAttributesDescription
ierrinteger(kind=I4P)inError code.

Call graph

modified_kernels ​

P = A Q (base-shape nodes to centers) and Q (face prefix sums to centers) of esirkepov_Q<N>. CPU twin: modified_kernels (offsets and the half-cell shift of the odd filters documented there).

fortran
subroutine modified_kernels(esirkepov_q, p, qw, radius, qfirst, nq)

Arguments

NameTypeIntentAttributesDescription
esirkepov_qinteger(kind=I4P)in
preal(kind=R8P)out
qwreal(kind=R8P)out
radiusinteger(kind=I4P)out
qfirstinteger(kind=I4P)out
nqinteger(kind=I4P)out

Call graph

odd_mirror_index ​

Odd mirror of a line index. CPU twin: odd_mirror_index.

fortran
subroutine odd_mirror_index(idx, n, col, sgn)

Arguments

NameTypeIntentAttributesDescription
idxinteger(kind=I4P)in
ninteger(kind=I4P)in
colinteger(kind=I4P)out
sgnreal(kind=R8P)out

Call graph

build_centered_reconstruction_matrix ​

Face-reconstruction matrix R such that FD1_CC J = (R_{i+1/2}-R_{i-1/2})/dx. CPU twin of the same name.

fortran
subroutine build_centered_reconstruction_matrix(hs, n, a)

Arguments

NameTypeIntentAttributesDescription
hsinteger(kind=I4P)in
ninteger(kind=I4P)in
areal(kind=R8P)inout

Call graph

build_centered_derivative_matrix ​

Centered FD first-derivative matrix with homogeneous ghosts. CPU twin of the same name.

fortran
subroutine build_centered_derivative_matrix(hs, dx, n, a)

Arguments

NameTypeIntentAttributesDescription
hsinteger(kind=I4P)in
dxreal(kind=R8P)in
ninteger(kind=I4P)in
areal(kind=R8P)inout

Call graph

factorize_matrix_pivot ​

LU with partial pivoting, in place. CPU twin of the same name.

fortran
subroutine factorize_matrix_pivot(a, pivot, n)

Arguments

NameTypeIntentAttributesDescription
areal(kind=R8P)inout
pivotinteger(kind=I4P)out
ninteger(kind=I4P)in

Call graph

Functions ​

esirkepov_shape_weight_dev ​

Optionally binomial-filtered 1D particle shape. CPU twin: esirkepov_shape_weight_1d.

Attributes: pure

Returns: real(kind=R8P)

fortran
function esirkepov_shape_weight_dev(shp, filter, x, xc, dx) result(w)

Arguments

NameTypeIntentAttributesDescription
shpinteger(kind=I4P)in
filterlogicalin
xreal(kind=R8P)in
xcreal(kind=R8P)in
dxreal(kind=R8P)in

Call graph

particle_shape_weight_dev ​

1D particle shape (polynomial forms of the CPU). CPU twin: particle_shape_weight_1d (Gaussian not reached here).

Attributes: pure

Returns: real(kind=R8P)

fortran
function particle_shape_weight_dev(shp, x, xc, dx) result(w)

Arguments

NameTypeIntentAttributesDescription
shpinteger(kind=I4P)in
xreal(kind=R8P)in
xcreal(kind=R8P)in
dxreal(kind=R8P)in

Call graph

effective_gaussian_weight_dev ​

Optionally binomial-filtered 1D Gaussian weight. Same expressions as prism_pic_object%effective_gaussian_weight.

Attributes: pure

Returns: real(kind=R8P)

fortran
function effective_gaussian_weight_dev(r, shift, cutoff_limit, filter) result(weight)

Arguments

NameTypeIntentAttributesDescription
rreal(kind=R8P)in
shiftreal(kind=R8P)in
cutoff_limitreal(kind=R8P)in
filterlogicalin

Call graph

gaussian_weight_dev ​

Unnormalized 1D Gaussian with compact cutoff.

Attributes: pure

Returns: real(kind=R8P)

fortran
function gaussian_weight_dev(r, cutoff_limit) result(weight)

Arguments

NameTypeIntentAttributesDescription
rreal(kind=R8P)in
cutoff_limitreal(kind=R8P)in

Call graph

support_radius ​

Integer support radius of the particle shape. CPU twin: particle_weighting_radius.

Returns: integer(kind=I4P)

fortran
function support_radius(self) result(rx)

Arguments

NameTypeIntentAttributesDescription
selfclass(prism_fnl_pic_conserving_object)inConserving current object.

Call graph