Skip to content

List of JustPIC functions ​

Here an overview of all functions in JustPIC.jl, for a complete list see here:

JustPIC.Z_COLUMN_COMM Constant
julia
_z_column_comm(comm)

Sub-communicator of comm joining the ranks that share an (x,y) column, i.e. those differing only in their third Cartesian coordinate.

The Cartesian topology is fixed for the lifetime of a global grid, so the communicator is built once and reused; MPI.Cart_sub would otherwise allocate one per time step. The cache holds the parent communicator alongside it, which both keeps that handle alive — so the identity test cannot match a recycled handle value — and rebuilds the sub-communicator when a new global grid is initialized. A dropped sub-communicator is freed by MPI.jl's finalizer; freeing it here would be a collective call on ranks that may already have moved on.

source
JustPIC.AbstractAdvectionIntegrator Type
julia
AbstractAdvectionIntegrator

Abstract supertype for time integrators used by particle, passive-marker, and marker-chain advection routines.

source
JustPIC.Euler Type
julia
Euler()

Forward-Euler advection integrator.

This is the cheapest available integrator and is mainly useful for simple tests or when first-order accuracy is sufficient.

source
JustPIC.MarkerChain Type
julia
MarkerChain{Backend,N,I,T1,T2,T3,TV} <: AbstractParticles

Container for a 2D marker chain used to represent a free surface or topographic interface as a single-valued height field y = h(x).

Markers are bucketed into the columns of a 1D grid (cell_vertices) using the same CellArray layout as Particles: each column holds up to max_xcell marker slots, and a boolean occupancy mask marks which are live.

Fields

  • coords::NTuple{N,T1}: marker coordinates, one CellArray per dimension. In 2D coords[1] is x and coords[2] is y. Empty slots hold NaN.

  • coords0::NTuple{N,T1}: marker coordinates from the previous time step.

  • h_vertices::T2: topography sampled at the grid vertices (current step).

  • h_vertices0::T2: topography at the vertices from the previous step; used by advect_markerchain!/semilagrangian_advection_markerchain! to conserve the mean height.

  • cell_vertices::TV: the horizontal grid xv that defines the columns. It must be finite and strictly increasing; the spacing may be non-uniform, in which case every operation resolves each column's width from its own pair of vertices.

  • index::T3: per-slot occupancy mask (true ⟺ the matching coords slot is live).

  • min_xcell, max_xcell::I: the minimum and maximum number of markers allowed per column; resample! refills depleted columns back up to min_xcell.

Invariants

  • A slot is live iff its mask entry is true; live slots have finite coordinates and empty slots are NaN.

  • Marker precision follows eltype(cell_vertices)/the initial elevation, so a Float32 grid yields Float32 markers (needed on Metal, which has no Float64).

Use init_markerchain to create a chain, fill_chain_from_chain! or fill_chain_from_vertices! to overwrite its geometry, and advect_markerchain! or semilagrangian_advection_markerchain! to evolve it in time.

source
JustPIC.MarkerSurface Type
julia
MarkerSurface{Backend, T2, TV, TB, TW} <: AbstractParticles

A 3D free surface tracker using a structured marker grid. The surface is represented as a 2D grid of topography values (z-heights) at corner nodes.

Fields

  • topo::T2 — topography (z-elevation) at grid vertices, size (nx+1, ny+1)

  • topo0::T2 — topography from the previous time step

  • vx::T2 — x-velocity interpolated to surface nodes

  • vy::T2 — y-velocity interpolated to surface nodes

  • vz::T2 — z-velocity interpolated to surface nodes

  • xv::TV — x-coordinates of surface grid vertices

  • yv::TV — y-coordinates of surface grid vertices

  • periodic_1::Bool — periodic boundary in x

  • periodic_2::Bool — periodic boundary in y

  • advection_valid::TB — persistent validity mask for topography advection

  • smoothing_cell_topo::TW — persistent cell-centered smoothing workspace

  • smoothing_steep::TB — persistent steep-cell mask

  • z_ownership::TW — persistent z-column ownership weights

source
JustPIC.Particles Type
julia
Particles{Backend, N, I, T1, T2, D, V} <: AbstractParticles

Main particle container used by JustPIC for material points stored cell-by-cell in CellArrays.

coords is an N-tuple of particle-coordinate arrays, index marks which slots are active inside each cell, nxcell is the target initial occupancy per cell, and min_xcell/max_xcell define the occupancy range used by injection and cleanup routines.

Use init_particles to construct this type instead of calling the inner constructor directly.

source
JustPIC.PassiveMarkers Type
julia
PassiveMarkers{Backend,T} <: AbstractParticles

Lightweight particle container for passive tracers that only store coordinates.

Unlike Particles, passive markers do not keep per-cell occupancy metadata and are intended for tracer-style advection and interpolation workflows where the markers do not feed back into the simulation.

Use init_passive_markers to construct this type.

source
JustPIC.PhaseRatios Type
julia
PhaseRatios{Backend,T}

Storage for phase-fraction fields sampled at multiple grid locations.

Depending on dimension, the container holds phase ratios at cell centers, vertices, staggered velocity nodes, and in 3D also at edge midpoints.

The fields store, for each location, the fractional occupancy of each material phase inferred from particle labels.

source
JustPIC.PhaseRatios Method
julia
PhaseRatios(T, backend, nphases, ni)
PhaseRatios(backend, nphases, ni)
PhaseRatios(nphases, ni)

Allocate a PhaseRatios container for nphases material phases on a grid of size ni.

The default element type is Float64 and the default backend is KernelAbstractions' CPU.

Arguments

  • T: scalar storage type for the phase fractions.

  • backend: backend type used to allocate the arrays.

  • nphases: number of material phases.

  • ni: number of cells in each spatial direction.

source
JustPIC.RungeKutta2 Type
julia
RungeKutta2(α = 0.5)

Second-order Runge-Kutta advection integrator.

The parameter α controls the intermediate stage location and must satisfy 0 < α < 1. The default α = 0.5 corresponds to the midpoint method.

source
JustPIC.RungeKutta4 Type
julia
RungeKutta4()

Classical fourth-order Runge-Kutta advection integrator.

source
JustPIC.SubgridDiffusionCellArrays Type
julia
SubgridDiffusionCellArrays(particles; loc = :vertex)

Allocate scratch storage used by the subgrid thermal diffusion routines.

The returned object stores old particle temperatures, per-particle temperature increments, characteristic diffusion timescales, and a grid-sized accumulation buffer.

loc selects whether the accumulation buffer should match a vertex-based (:vertex) or cell-centered (:center) grid layout. Either way the buffer is ghosted like particles.xvi/particles.xci.

source
JustPIC.CA Method
julia
CA(backend, dims; eltype = Float64)

Allocate an uninitialized CellArray of size dims on backend. Extended for the GPU backends by the package extensions.

source
JustPIC.TA Method
julia
TA()
TA(backend)

Return the plain array type associated with backend (a KernelAbstractions backend type such as CPU).

For CPU this is Array. Loading CUDA.jl / AMDGPU.jl / Metal.jl extends this for CUDA.CUDABackend, AMDGPU.ROCBackend, and Metal.MetalBackend, respectively.

source
JustPIC._check_surface_matches_grid Method
julia
_check_surface_matches_grid(surf::MarkerSurface, xvi)

Throw unless the horizontal vertex grids of xvi and surf.topo have the same size. The kernels index topo with cell indices derived from xvi, so a surface resolved differently from the volume grid would silently return wrong fractions.

source
JustPIC._control_bounds Method
julia
_control_bounds(xv, i, staggered)

Bounds (lo, hi) of the i-th control volume along the direction discretized by the vertex coordinates xv. Cell-centered volumes (Val(false)) span xv[i]:xv[i + 1]; staggered ones (Val(true)) are centered on vertex xv[i] and reach the midpoints of the neighboring cells, clipped at the boundary.

source
JustPIC._control_volume_rock_fraction Method
julia
_control_volume_rock_fraction(topo, xv, yv, zv, i, j, k, px, py, pz)

Fraction of the (i, j, k)-th control volume that lies below the surface, summed over every surface-cell quadrant the volume overlaps and clamped to [0, 1].

source
JustPIC._enforce_periodic_seam! Method
julia
_enforce_periodic_seam!(topo, periodic_1, periodic_2)

Copy the first row/column of topo onto the last one along each periodic direction, where both hold the same physical node.

source
JustPIC._find_cell_1d Method
julia
_find_cell_1d(coords, val)

Find index k such that coords[k] <= val < coords[k+1]. Returns 0 if val < coords[1], or length(coords) if val >= coords[end].

source
JustPIC._get_volume_prism Method
julia
_get_volume_prism(x1,y1,z1, x2,y2,z2, x3,y3,z3, level)

Compute double the volume of a prism above level

source
JustPIC._ghost_coord Method
julia
_ghost_coord(v, i, n, periodic)

Return the i-th coordinate of vector v (length n) allowing one ghost index on each side (i == 0 and i == n+1). Used to build the deformed-grid stencil at domain boundaries without materialising a padded array.

When periodic, the ghost coordinates are the periodic images of nodes n-1 and 2 — the same nodes _ghost_field wraps to — so that stencil coordinates and field values stay paired on nonuniform grids. Otherwise they are linear extrapolations of the boundary spacing.

source
JustPIC._ghost_field Method
julia
_ghost_field(arr, i, j, nx, ny, periodic_1, periodic_2)

Return the value of 2D field arr (size (nx, ny)) at index (i, j), allowing one ghost layer on each side (i ∈ 0:nx+1, j ∈ 0:ny+1). Ghost values wrap to the opposite boundary when periodic; otherwise they clamp to the boundary node. Matching ghost coordinates come from _ghost_coord.

source
JustPIC._interp_vel_component Method
julia
_interp_vel_component(Vcomp, xg, yg, zg, x, y, z)

Interpolate a single velocity component at point (x, y, z) by trilinear interpolation of the 3D array Vcomp over its own vertex coordinates (xg, yg, zg). Points outside the grid clamp to the boundary cell.

source
JustPIC._interpolate_triangle Method
julia
_interpolate_triangle(cx, cy, cz, tri, xp, yp; tol=convert(T, 1e-6))

Check if point (xp, yp) lies inside the triangle defined by indices tri into coordinate arrays (cx, cy, cz), and compute the barycentric interpolation of the z-coordinate.

Returns

  • (true, z_interpolated) if the point is inside the triangle

  • (false, zero(T)) otherwise

source
JustPIC._intersect_edge Method
julia
_intersect_edge(x1,y1,z1, x2,y2,z2, level, tol)

Find the intersection point of edge (p1→p2) with the horizontal plane z=level. Clamps the intersection to lie within the edge's z-range; edges spanning less than tol in z are treated as horizontal and return p1.

source
JustPIC._owned_surface_extent Method
julia
_owned_surface_extent(n, dim, gg)

Number of leading nodes along dim that this rank owns exclusively, out of the n local ones: the trailing gg.overlaps[dim] lines are shared with the next rank and belong to it, so global reductions count them once.

A local size smaller than the overlap yields a result below one. The caller must reduce that condition across the ranks before raising it: only some ranks see it, and an unreduced throw would leave the rest blocked in the next collective.

source
JustPIC._prism_volume_above_level Method
julia
_prism_volume_above_level(xa,ya,za, xb,yb,zb, xc,yc,zc, level, tol)

Compute double the volume of the triangular prism above a horizontal level plane. tol is the edge-intersection tolerance passed on to _intersect_edge.

source
JustPIC._quadrant_rock_fraction Method
julia
_quadrant_rock_fraction(topo, xv, yv, a, b, qx, qy, vcell, zlo, zhi)

Contribution of quadrant (qx, qy) of surface cell (a, b) to the rock fraction of a control volume of size vcell spanning zlo:zhi. The bilinear surface patch over the quadrant is split into the two triangles that meet at the cell center.

source
JustPIC._surface_cell_range Method
julia
_surface_cell_range(i, n, staggered)

Range of surface cells, out of n, overlapped by the i-th control volume: cell i alone when cell-centered, the two cells sharing vertex i when staggered.

source
JustPIC._surface_collective_failure Method
julia
_surface_collective_failure(local_failure)

Reduce a local failure flag over the global grid so every rank takes the same branch. Without the reduction a rank-local failure would throw on one rank only and deadlock the others in the next collective.

source
JustPIC._surface_quadrant_range Method
julia
_surface_quadrant_range(a, i, staggered)

Range of quadrants of surface cell a covered by the i-th control volume along one direction: both halves of the cell when cell-centered, otherwise only the half adjacent to vertex i.

source
JustPIC._triangle_rock_fraction Method
julia
_triangle_rock_fraction(xa, ya, za, xb, yb, zb, xc, yc, zc, vcell, bot, top)

Volume under the planar triangle (a, b, c) and inside the slab bot:top, normalized by vcell. Elevations are shifted to the slab midpoint first, so the relative tolerance of leq_r/geq_r scales with the slab rather than with the distance from z = 0.

source
JustPIC._trilinear Method
julia
_trilinear(F, i, j, k, wx, wy, wz)

Trilinear interpolation of 3D field F at cell (i,j,k) with weights (wx,wy,wz).

source
JustPIC._uniform_cell_weight Method
julia
_uniform_cell_weight(coords, val)

Cell index and interpolation weight of val within the uniformly spaced coords, computed from first/step instead of a search. Values outside the range clamp to the boundary cell.

source
JustPIC._update_surface_halo! Method
julia
_update_surface_halo!(fields...)

Exchange the x/y ImplicitGlobalGrid halo of surface-shaped fields, which may be nodal or cell-centered. No-op when no global grid is initialized.

source
JustPIC._validate_surface_coordinates Method
julia
_validate_surface_coordinates(name, x)

Throw unless x is a strictly increasing vector of at least two finite coordinates. name identifies the offending argument in the error message.

source
JustPIC._validate_surface_velocity_layout Method
julia
_validate_surface_velocity_layout(V, grid_vxi)

Throw unless each grid_vxi[d] is an (x, y, z) tuple of usable coordinate vectors whose lengths match size(V[d]) — the interpolation reads V[d] at cell indices looked up in grid_vxi[d].

source
JustPIC.add_periodic_ghost_nodes Method
julia
add_periodic_ghost_nodes(x::AbstractVector)

Extend a 1D periodic grid with one ghost node on each side.

The added coordinates preserve the spacing of the last and first physical cells, respectively, which makes this helper work for both uniform and refined grids.

Example

julia
xv = [0.0, 0.25, 0.5, 0.75, 1.0]
xv_periodic = add_periodic_ghost_nodes(xv)
source
JustPIC.advect_marker_surface! Method
julia
advect_marker_surface!(surf::MarkerSurface, V, grid_vxi, dt;
                       max_slope_angle=45)

Main driver to advect the free surface:

  1. Interpolate velocities from the 3D grid to surface nodes

  2. Advect topography using the deformed-grid triangle method

  3. Smooth topography spikes (if max_slope_angle > 0)

Arguments

  • surf : the MarkerSurface

  • V : tuple (Vx, Vy, Vz) of 3D velocity arrays

  • grid_vxi : tuple of component grids (grid_vx, grid_vy, grid_vz)

  • dt : time step

  • max_slope_angle : maximum slope angle in degrees (default 45; ≤ 0 disables smoothing)

source
JustPIC.advect_markerchain! Method
julia
advect_markerchain!(chain, method, V, grid_vxi, dt)

Advect a marker chain for one time step and rebuild its derived topography data.

This convenience wrapper runs marker advection, reassigns markers to cells, resamples the chain, updates vertex elevations, and enforces mean-height conservation.

Use this when evolving a free surface or interface represented by a MarkerChain.

source
JustPIC.advect_surface_topo! Method
julia
 advect_surface_topo!(surf::MarkerSurface, dt)

Advect the topography on the free surface mesh using the velocity field already interpolated onto the surface nodes (surf.vx, surf.vy, surf.vz).

  1. Build ghost coordinates and field values outside the domain: periodic images of the wrapped nodes when periodic, otherwise extrapolated coordinates with field values clamped to the boundary node.

  2. For each surface node, build a local 3×3 "deformed grid" using neighboring node positions displaced by dt*v.

  3. Subdivide the deformed cell into 16 triangles (9 corner + 4 midpoint nodes).

  4. Find which triangle contains the target position and perform barycentric interpolation of the z-coordinate.

text
    1 ------- 2 ------- 3
    |  \     / \     /  |
    |   \   /   \   /   |
    |    \ /     \ /    |
    |    10       11    |
    |    / \     / \    |
    |   /   \   /   \   |
    |  /     \ /     \  |
    4 ------- 5 ------- 6
    |  \     / \     /  |
    |   \   /   \   /   |
    |    \ /     \ /    |
    |    12       13    |
    |    / \     / \    |
    |   /   \   /   \   |
    |  /     \ /     \  |
    7 ------- 8 ------- 9

Arguments

  • surf : the MarkerSurface

  • dt : time step

source
JustPIC.advection! Method
julia
advection!(particles::Particles, method::AbstractAdvectionIntegrator, V, dt)
advection!(particles::Particles, method::AbstractAdvectionIntegrator, V, grid_vi, dt, dxi)

Advect particles through the staggered velocity field V over a time step dt. The particle coordinates are updated in place.

The public form reads the staggered velocity coordinate grids and spacing from particles (particles.xi_vel and particles.di.velocity), so only V and dt are supplied. The lower-level form takes those grids explicitly.

Arguments

  • particles: Particles container to advect.

  • method: time integrator such as Euler(), RungeKutta2(), or RungeKutta4().

  • V: tuple of staggered velocity component arrays.

  • dt: timestep.

  • grid_vi: tuple of coordinate tuples matching the staggering of V (lower-level form only).

  • dxi: grid spacing associated with grid_vi (lower-level form only).

  • periodic_1, periodic_2, periodic_3: enable periodic wrapping at every integration stage in the corresponding coordinate direction.

Notes

  • Use the same periodic keywords in the subsequent move_particles! call.

  • Stage-wise wrapping is required by RungeKutta2 and RungeKutta4, whose intermediate interpolation points may cross a periodic boundary.

source
JustPIC.advection! Method
julia
advection!(particles::PassiveMarkers, method::AbstractAdvectionIntegrator, V, grid_vxi, dt)

Advect passive marker coordinates through the staggered velocity field V over a time step dt. The marker coordinates are updated in place.

Unlike the Particles method, grid_vxi must be supplied explicitly, since PassiveMarkers stores only marker coordinates and no grid metadata.

Arguments

  • particles: PassiveMarkers container to advect.

  • method: time integrator such as Euler(), RungeKutta2(), or RungeKutta4().

  • V: tuple of staggered velocity component arrays.

  • grid_vxi: tuple of coordinate tuples matching the staggering of V.

  • dt: timestep.

source
JustPIC.advection! Method
julia
advection!(chain::MarkerChain, method, V, grid_vi, dt)

Advect the marker coordinates in chain through the staggered velocity field V without performing resampling or topography reconstruction.

This lower-level method is useful if you want to customize the post-advection marker-chain processing yourself.

source
JustPIC.advection_LinP! Method
julia
advection_LinP!(particles, method, V, dt; periodic_1=false, periodic_2=false, periodic_3=false)

Advect particles using the linear-plus-pressure (LinP) velocity interpolation scheme.

This variant uses the same time integrators as advection! but evaluates velocities with the LinP reconstruction near staggered pressure points.

This method is useful when you want the interpolation behavior described in the velocity-interpolation documentation under LinP.

Periodic keywords have the same meaning as in advection! and must also be passed to the subsequent move_particles! call.

source
JustPIC.advection_MQS! Method
julia
advection_MQS!(particles, method, V, dt; periodic_1=false, periodic_2=false, periodic_3=false)

Advect particles using the monotonic quadratic spline (MQS) velocity interpolation scheme.

Compared with advection!, this method reconstructs staggered velocities with MQS where enough stencil support is available.

Near boundaries or when the required stencil is unavailable, the implementation falls back to linear interpolation.

The public entry point reads the staggered velocity coordinates and spacing from particles.xi_vel and particles.di.velocity.

Periodic keywords have the same meaning as in advection! and must also be passed to the subsequent move_particles! call.

source
JustPIC.cell_array Method
julia
cell_array(backend, x, ncells::NTuple, ni::NTuple)
cell_array(x, ncells::NTuple, ni::NTuple)

Allocate a CellArray on backend (a KernelAbstractions backend type such as CPU), with ncells entries per grid cell over a grid of size ni, and fill every entry with x.

The backend form is the preferred allocation path for particle storage and phase-ratio arrays. The backend-less form allocates on CPU.

Examples

julia
index = cell_array(CPU, false, (24,), (64, 64))
field = cell_array(CPU, 0.0, (3,), (64, 64))
source
JustPIC.cell_length Method
julia
cell_length(chain::MarkerChain, i::Integer)
cell_length(chain::MarkerChain)

Return the horizontal width of column i of a 2D marker chain, that is chain.cell_vertices[i + 1] - chain.cell_vertices[i].

The one-argument method returns the width shared by every column, and is therefore defined only when chain.cell_vertices is uniformly spaced; on a refined grid it throws an ArgumentError.

source
JustPIC.cell_rock_area Method
julia
cell_rock_area(s::Segment, r::Rectangle) -> Real

Fraction of the axis-aligned cell r lying below the marker chain segment s, in [0, 1].

s spans the full width of r, runs left to right, and may leave the cell through its floor or its ceiling.

source
JustPIC.cell_width Method
julia
cell_width(xv, i)

Width of cell i of the vertex vector xv.

source
JustPIC.cellaxes Method
julia
cellaxes(A)

Return the one-based axes used to iterate over the entries inside each CellArray cell.

This is the preferred helper for loops over particle slots because it works for both scalar and multi-entry cell storage.

source
JustPIC.cellnum Method
julia
cellnum(A::CellArray)

Return the number of storage slots inside each logical cell of A.

For particle containers this is the number of particle slots reserved per grid cell, including inactive slots.

source
JustPIC.centroid2particle! Method
julia
centroid2particle!(Fp, xci, F, particles)

Interpolate cell-centered field values F to particle values Fp.

xci contains the center coordinates of the grid carrying F. The destination Fp is mutated in place and may be either a single particle field or a tuple of particle fields.

Particles lying between a domain boundary and the first centroid are interpolated from the ghost centroids, so F must always use the ghosted particles.xci layout — unlike grid2particle!, there is no opt-out.

source
JustPIC.checkpointing_particles Method
julia
checkpointing_particles(dst, particles; phases=nothing, phase_ratios=nothing, chain=nothing, t=nothing, dt=nothing, particle_args=nothing)
checkpointing_particles(dst, particles, me; phases=nothing, phase_ratios=nothing, chain=nothing, t=nothing, dt=nothing, particle_args=nothing)

Write particle state and optional companion data to a JLD2 checkpoint.

By default the file is saved as particles_checkpoint.jld2 in dst. Additional keyword arguments are serialized into the checkpoint after being converted to plain Julia arrays where needed.

Common keywords

  • phases: per-particle phase labels.

  • phase_ratios: PhaseRatios container to checkpoint.

  • chain: marker-chain state.

  • t: simulation time.

  • dt: timestep size.

  • particle_args: tuple of extra particle-carried fields.

Notes

  • Arrays are converted to plain Julia arrays before serialization so the checkpoint can be reloaded independently of the active backend.

  • Passing me writes rank-local files named after the zero-based MPI rank: particles_checkpoint0000.jld2, particles_checkpoint0001.jld2, and so on.

source
JustPIC.clean_particles! Method
julia
clean_particles!(particles, grid, args)

Remove invalid or inactive particle slots and keep particle-associated fields in args consistent with the particle storage layout.

This is typically used after particle deletion or reinjection to compact each cell's active particle block.

source
JustPIC.compute_avg_topo Method
julia
compute_avg_topo(surf::MarkerSurface)

Compute and return the average topography over all surface vertices. Duplicated periodic seam nodes are counted once. Under MPI, overlapping x/y nodes and replicated z-columns are counted once through an owned-node global reduction. Note: forces a device→host scalar transfer on GPU; call only outside hot loops.

source
JustPIC.compute_rock_fraction! Method
julia
compute_rock_fraction!(ratios, chain::MarkerChain, xvi, dxi)

Fill ratios with the fraction of each control volume that lies below the marker chain.

The result is written at cell centers, vertices, and staggered velocity nodes using the topography currently stored in chain.

xvi are the cell vertices per direction and dxi the matching spacings: either one Number per direction for a uniform grid, or one AbstractVector of per-cell widths per direction for a refined one.

source
JustPIC.compute_rock_fraction! Method
julia
compute_rock_fraction!(ratios, surf::MarkerSurface, xvi, dxi)

Compute the rock fraction (fraction of each cell volume below the free surface) at all staggered-grid positions and store them in ratios.

This is the 3D equivalent of compute_rock_fraction!(ratios, chain::MarkerChain, xvi, dxi). The ratios struct must have fields .center, .vertex, .Vx, .Vy, .Vz, .xy, .yz, and .xz.

Arguments

  • ratios : struct with center, vertex, face, and edge arrays

  • surf : the MarkerSurface

  • xvi : tuple (xv, yv, zv) of 1D vertex coordinate arrays

  • dxi : tuple (dx, dy, dz) of grid spacings (kept for API consistency with the 2D version; the 3D kernel uses xvi directly)

source
JustPIC.compute_topography_vertex! Method
julia
compute_topography_vertex!(chain::MarkerChain)

Interpolate the marker-chain geometry back to the vertex-based topography array chain.h_vertices.

This is typically called after marker advection or resampling.

source
JustPIC.compute_volume_below_surface! Method
julia
compute_volume_below_surface!(ratio, surf, xvi, px, py, pz)

Fill ratio with the fraction of each control volume lying below the surface. px, py, pz are Val(true)/Val(false) and select, per direction, whether the control volumes are centered on the vertices of xvi or span its cells.

source
JustPIC.fill_chain_from_chain! Method
julia
fill_chain_from_chain!(chain::MarkerChain, topo_x, topo_y)

Replace the marker positions in chain with coordinates sampled from an existing topographic polyline.

After the markers are reassigned, the vertex-based topography stored on the chain is recomputed and synchronized with h_vertices0.

topo_x and topo_y should describe an open polyline that spans the chain's horizontal extent.

source
JustPIC.fill_chain_from_vertices! Method
julia
fill_chain_from_vertices!(chain::MarkerChain, topo_y)

Reconstruct a marker chain from topography values given at grid vertices.

topo_y is copied into both the current and previous vertex topography fields before the marker coordinates are rebuilt.

This is useful when the interface is naturally represented on the vertex grid and you want to refresh the marker representation from that discretization.

source
JustPIC.find_parent_cell_bisection Method
julia
find_parent_cell_bisection(px::Number, x::AbstractVector, seed::Int)

Performs an iterative bisection search on the cell-edge vector x to find the index of the cell containing px, starting from the initial guess seed.

Arguments

  • px::Number: Coordinate of the point we want to locate.

  • x::AbstractVector: Monotonic vector of cell-edge coordinates.

  • seed::Int: Initial cell index guess used to start the search.

Returns

  • An integer index i such that x[i] ≤ px ≤ x[i + 1].
source
JustPIC.force_injection! Method
julia
force_injection!(particles, p_new)

Convenience method for force_injection! when no companion particle fields need to be initialized.

source
JustPIC.force_injection! Method
julia
force_injection!(particles, p_new, fields, values)

Insert particles from p_new directly into free particle slots.

Arguments

  • particles: destination Particles container.

  • p_new: per-cell collection of coordinates to inject; NaN marks empty input slots.

  • fields: tuple of particle fields to initialize together with the coordinates.

  • values: values written into each corresponding entry of fields.

Notes

  • This is a low-level routine: it does not search for nearest-neighbor values.

  • Injection only happens into currently inactive particle slots.

source
JustPIC.grid2particle! Method
julia
grid2particle!(Fp, xvi, F, particles::PassiveMarkers)

Interpolate a nodal field F to passive-marker values Fp, updated in place.

The vertex grid xvi must be supplied explicitly, since PassiveMarkers stores only marker coordinates and no grid metadata.

Arguments

  • Fp: destination marker field, or tuple of marker fields.

  • xvi: vertex coordinates of the grid on which F is defined.

  • F: source nodal field, or tuple of nodal fields matching Fp.

  • particles: PassiveMarkers container supplying marker coordinates.

source
JustPIC.grid2particle_flip! Method
julia
grid2particle_flip!(Fp, xvi, F, F0, particles; α = 0.0)

Update particle values with a PIC/FLIP blend.

α = 1 gives pure PIC, α = 0 gives pure FLIP, and intermediate values blend between the two updates.

Arguments

  • Fp: particle field to update in place.

  • F: current grid field.

  • F0: previous grid field.

  • particles: particle container.

  • α: PIC fraction in the PIC/FLIP blend.

  • ghost_1, ghost_2, ghost_3: whether F and F0 include ghost nodes in each coordinate direction. Disable a keyword for a physical-only direction.

source
JustPIC.init_cell_arrays Method
julia
init_cell_arrays(particles::Particles, ::Val{N})

Allocate N cell-aligned scratch arrays with the same cell layout as particles.coords.

This is mainly used internally to create per-particle temporary storage for quantities such as interpolated fields or time-integration work arrays.

Returns

  • An N-tuple of CellArrays with the same particle-cell layout as particles.coords.
source
JustPIC.init_marker_surface Method
julia
init_marker_surface(::Type{backend}, xv, yv, initial_elevation;
                    periodic_1=false, periodic_2=false)

Create a MarkerSurface that tracks a 3D free surface on the grid defined by vertex coordinates xv and yv.

The topography is stored at the grid vertices (corner nodes), matching LaMEM's FreeSurf approach where the surface DMDA has the same (x,y)-resolution as the staggered-grid corner nodes.

Arguments

  • backend : KernelAbstractions backend type such as CPU, CUDA, AMDGPU, Metal

  • xv : 1D array/range of x-coordinates of grid vertices (length nx+1)

  • yv : 1D array/range of y-coordinates of grid vertices (length ny+1)

  • initial_elevation : scalar or 2D array (nx+1)×(ny+1) of initial z-elevations

  • periodic_1, periodic_2 : periodic boundary conditions in x and y (default false)

Returns

A MarkerSurface instance with topography initialised to initial_elevation.

source
JustPIC.init_markerchain Method
julia
init_markerchain(backend, nxcell, min_xcell, max_xcell, xv, initial_elevation)

Create a 2D MarkerChain sampled along the horizontal grid xv.

The vertices in xv must be finite and strictly increasing; the spacing may be non-uniform, in which case each column is populated according to its own width.

nxcell controls the initial number of markers per cell, while initial_elevation can be either a scalar or a vector specifying the initial surface height.

Returns

  • A MarkerChain whose marker positions, vertex topography, and occupancy masks are initialized consistently.
source
JustPIC.init_particles Method
julia
init_particles(backend, nxcell, max_xcell, min_xcell, grid_vx, grid_vy[, grid_vz])

Initialize a Particles container from the staggered velocity grids.

Each velocity component is supplied as an N-tuple of coordinate vectors. The diagonal coordinate vector of each component defines the particle vertex grid; the off-diagonal vectors define the cell-center grid. For example, in 2D pass grid_vx = (xv, yc_extended) and grid_vy = (xc_extended, yv).

If nxcell is a number, particles are distributed randomly within cell quadrants; the count is rounded up to a multiple of the number of quadrants so that every quadrant holds the same number of particles. If it is an NTuple, it gives the number of particles placed along each coordinate direction of every cell: nxcell[d] particles sit at the centers of a uniform sub-grid of spacing dx[d] / nxcell[d], so no particle lands on a cell boundary and the spacing is uniform across the whole domain when the grid is.

In both cases max_xcell is raised to the resulting number of particles per cell if it is smaller.

The particle vertex and center grids stored in the returned container are extended with periodic ghost nodes. The staggered velocity grids are stored as provided.

Arguments

  • backend: KernelAbstractions backend type such as CPU.

  • nxcell: either the target number of particles per cell, or an NTuple describing a structured per-dimension layout.

  • max_xcell: number of particle slots reserved per cell.

  • min_xcell: minimum occupancy used by reinjection routines.

  • grid_vx, grid_vy, grid_vz: staggered velocity-grid coordinate tuples. Omit grid_vz for a 2D simulation. Each tuple must contain one coordinate vector per spatial dimension.

Returns

  • A Particles object whose coordinates and occupancy arrays are ready for advection/interpolation routines, with particles.xvi and particles.xci including one periodic ghost node on each side.

Example

julia
xv, yv = LinRange(0, 1, 33), LinRange(0, 1, 33)
dx = xv[2] - xv[1]
xc = LinRange(dx / 2, 1 - dx / 2, 32)
yc = xc
grid_vx = xv, LinRange(first(yc) - dx, last(yc) + dx, 34)
grid_vy = LinRange(first(xc) - dx, last(xc) + dx, 34), yv
particles = init_particles(CPU, 24, 48, 12, grid_vx, grid_vy)

# 5x5 regularly spaced particles per cell
particles = init_particles(CPU, (5, 5), 48, 12, grid_vx, grid_vy)
source
JustPIC.init_passive_markers Method
julia
init_passive_markers(backend, coords::NTuple{N,AbstractArray})

Construct a PassiveMarkers container on backend from marker coordinate arrays.

coords is an N-tuple of vectors, one per spatial dimension, holding the initial marker positions: marker k sits at (coords[1][k], …, coords[N][k]).

Arguments

  • backend: KernelAbstractions backend type such as CPU.

  • coords: tuple of coordinate vectors, one per dimension.

source
JustPIC.inject_particles! Method
julia
inject_particles!(particles::Particles, args)

Inject particles into cells whose occupancy falls below particles.min_xcell.

Arguments

  • particles: The particles object.

  • args: tuple of particle fields that should be populated for newly injected particles.

Notes

  • New particles are placed quadrant-by-quadrant inside the cell.

  • New field values are copied from the nearest existing particle in the same neighborhood.

  • The public entry point uses the vertex grid and cell spacing stored in particles.

source
JustPIC.inject_particles_phase! Method
julia
inject_particles_phase!(particles, particles_phases, args, fields, grid)

Inject particles into under-populated cells while also copying phase labels and field values from nearby particles.

This is the phase-aware variant of inject_particles!.

particles_phases stores a phase id per particle slot, while args/fields hold companion particle properties that must be initialized consistently for the new particles.

source
JustPIC.interpolate_velocity_to_markerchain! Method
julia
interpolate_velocity_to_markerchain!(chain::MarkerChain, chain_V::NTuple{N, CellArray}, V, grid_vi::NTuple{N, NTuple{N, T}}) where {N, T}

Interpolate the staggered velocity field V to the current marker positions in chain and store the result in chain_V.

chain_V must be preallocated with the same cell layout as the marker-chain coordinates.

source
JustPIC.interpolate_velocity_to_surface_vertices! Method
julia
interpolate_velocity_to_surface_vertices!(surf::MarkerSurface, V, grid_vxi)

Interpolate the 3D velocity field V = (Vx, Vy, Vz) onto the free surface nodes. Each surface node at position (xv[i], yv[j], topo[i,j]) receives trilinearly interpolated velocity values.

Arguments

  • surf : the MarkerSurface

  • V : tuple (Vx, Vy, Vz) of 3D velocity arrays

  • grid_vxi : tuple of component grids (grid_vx, grid_vy, grid_vz), where each component grid is its own (x, y, z) coordinate tuple

source
JustPIC.launch! Method
julia
launch!(backend, kernel!, ndrange, args...)

Instantiate and run KernelAbstractions kernel! on backend over ndrange, then block until it completes.

The trailing synchronize keeps the package's historical synchronous launch semantics: host reads, MPI halo exchanges and injection/cleanup all assume the previous kernel has finished. A later optimization pass may drop per-launch synchronization in favor of synchronizing only before host access.

source
JustPIC.lerp Method
julia
lerp(v, t::NTuple{nD,T}) where {nD,T}

Linearly interpolates the value v between the elements of the tuple t. This function is specialized for tuples of length nD.

Arguments

  • v: The value to be interpolated.

  • t: The tuple of values to interpolate between.

source
JustPIC.mean_height Method
julia
mean_height(chain::MarkerChain)

Return the domain mean of the piecewise-linear vertex topography.

source
JustPIC.move_particles! Method
julia
move_particles!(particles::AbstractParticles, args; periodic_1=false, periodic_2=false, periodic_3=false)
move_particles!(particles::AbstractParticles, grid, args, dxi; periodic_1=false, periodic_2=false, periodic_3=false)

Reassign particles to the correct parent cells after their coordinates have been updated.

This routine keeps the coordinate arrays in particles and the companion fields in args sorted by parent cell, preserving the package's spatially local memory layout.

Arguments

  • particles: particle container whose coordinates have already been modified.

  • args: tuple of per-particle fields that must move together with the particle coordinates.

  • grid: optional vertex grid coordinates used by the lower-level method.

  • dxi: optional grid spacing used by the lower-level method.

  • periodic_1, periodic_2, periodic_3: enable periodic wrapping in the corresponding coordinate direction.

Notes

  • Particles that leave a non-periodic direction are discarded.

  • Periodic directions use the ghost cells created by add_periodic_ghost_nodes to wrap coordinates and particle fields across opposite domain boundaries. The ghost cells of a periodic direction must be empty on entry, as they are after every call; otherwise an ArgumentError is thrown.

  • A particle may cross any number of cells in one call, across periodic seams included. Jumps of more than one cell make the call slower: the cells are then transferred in (2j₁ + 1) × … × (2jₙ + 1) concurrent batches, with jᵢ the largest jump along direction i, so keep the displacement per step small.

  • args must use the same cell layout as particles.coords.

  • The public entry point uses the vertex grid and spacing stored in particles.

source
JustPIC.move_particles! Method
julia
move_particles!(chain::MarkerChain)

Reassign markers to the correct columns of chain after their coordinates have been updated.

Markers that crossed column boundaries are moved into their destination column's slots, keeping the coordinate arrays consistent with the per-column occupancy mask. A marker may cross any number of columns in one call. Markers whose updated coordinates are not finite, or which left the horizontal extent of chain.cell_vertices, are deleted.

source
JustPIC.new_empty_cell Method
julia
new_empty_cell(A::CellArray)

Create a zero-valued cell payload with the same element type as A.

source
JustPIC.nphases Method
julia
nphases(x::PhaseRatios)

Return the number of phases in x::PhaseRatios.

This method returns a Val wrapper for the phase count; use numphases when you need the integer directly.

source
JustPIC.parent_cell_index Method
julia
parent_cell_index(x, xv, seed)

Return the index i of the cell of the vertex vector xv that contains x, i.e. the i such that xv[i] ≤ x < xv[i + 1], clamped to 1:length(xv) - 1.

xv may be uniformly spaced (an AbstractRange, resolved arithmetically) or refined (any other AbstractVector, resolved by bisection from the initial guess seed). seed is ignored in the uniform case.

source
JustPIC.particle2centroid! Method
julia
particle2centroid!(F, Fp, particles::Particles)
particle2centroid!(F, Fp, xci::NTuple, particles::Particles, di)

Interpolate particle-centered values Fp to cell centers F.

xci contains the 1D coordinate arrays of the cell centers. This is the cell-centered counterpart to particle2grid! and mutates F in place.

Arguments

  • F: destination centroid array, or tuple of centroid arrays.

  • Fp: particle field stored with the same cell layout as particles.

  • particles: the Particles container supplying particle coordinates. Its stored xci coordinates define the target centroid grid.

  • ghost_1, ghost_2, ghost_3: whether F includes ghost nodes in each coordinate direction. Disable a keyword for a physical-only direction.

source
JustPIC.particle2grid! Method
julia
particle2grid!(F, Fp, buffer, xi, particles::PassiveMarkers)

Interpolate passive-marker values Fp onto the grid nodes F, overwriting F in place.

Because passive markers scatter to arbitrary nodes, weights are accumulated with atomic updates into F and buffer and normalized in a final pass; buffer must be a scratch array with the same size as F. The vertex grid xi is supplied explicitly.

Arguments

  • F: destination nodal array.

  • Fp: marker field stored with the same layout as particles.coords.

  • buffer: scratch nodal array (same size as F) used to accumulate weights.

  • xi: vertex coordinates of the target grid.

  • particles: PassiveMarkers container supplying marker coordinates.

source
JustPIC.reconstruct_chain_from_vertices! Method
julia
reconstruct_chain_from_vertices!(chain::MarkerChain)

Rebuild the markers of each column by evenly distributing them along the straight segment joining the two bounding h_vertices.

The number of markers per column is preserved (empty slots are skipped, so the column need not be contiguously packed). This is the inverse of compute_topography_vertex! and is used after the vertex topography has been modified (e.g. by the mass-conservation step of advect_markerchain! or the slope limiting of semilagrangian_advection_markerchain!).

source
JustPIC.reduce_surface_velocity_z! Method
julia
reduce_surface_velocity_z!(surf::MarkerSurface, zg)

Combine the interpolated surface velocities (surf.vx/vy/vz) across a z-column of a decomposed global grid, and check that the surface lies within the vertical extent of the velocity grid.

zg is the rank-local z vertex coordinate array/range of Vz. Its range is the tightest of the three component grids, so a surface inside it also lies inside the extended-center z grids of Vx and Vy.

Under z-decomposition each rank only interpolated the surface nodes inside its own slab. Each rank marks a node as "owned" when topo[i,j] lies within its local z-extent, contributes (v·owned, owned), and an Allreduce over the z-column recovers the value by weighted average. Nodes bracketed by two ranks (shared overlap cells) hold identical velocities, so the average is exact.

Serial runs and grids with a single z-rank need no combining, since one slab spans the whole vertical extent; the surface is still checked against it.

A node lying outside every slab has no interpolated velocity to recover and raises — _interp_vel_component would otherwise clamp it to the boundary cell. Every form of the check is reduced across the ranks so they raise together.

source
JustPIC.resample! Method
julia
resample!(chain::MarkerChain)

Resample the markers within each chain cell when the chain becomes too sparse or too distorted.

This keeps the marker spacing reasonably regular, which improves interpolation quality and the stability of subsequent marker-chain operations.

source
JustPIC.semilagrangian_advection! Method
julia
semilagrangian_advection!(F, F0, method, V, grid_vi, grid, dt)

Advect a grid field with a semi-Lagrangian backtracking step.

Each destination node in F is traced backward through the velocity field V, then sampled from F0 on the vertex grid grid. grid_vi contains the staggered coordinates associated with the velocity components.

Notes

  • F is overwritten in place at the interior nodes; boundary nodes are left untouched.

  • F0 is the source field from the previous step and is only read.

  • F and F0 must not share memory, otherwise nodes read values already overwritten by their neighbours. Aliased buffers throw an ArgumentError; pass a separate copy of the previous step instead.

  • For tuple-valued fields, each component is backtracked independently.

source
JustPIC.semilagrangian_advection! Method
julia
semilagrangian_advection!(chain::MarkerChain, method, V, grid_vxi, grid, dt)

Advance only the vertex topography chain.h_vertices by one semi-Lagrangian step.

Each new vertex height is found by backtracking through the velocity field V (so method must support backtracking, i.e. RungeKutta2/RungeKutta4, not Euler). This is the raw update used by semilagrangian_advection_markerchain!; it does not apply slope limiting, mass conservation, or marker reconstruction — call the wrapper unless you need to compose those steps yourself. Departures outside the horizontal chain domain sample the nearest endpoint height; velocity interpolation extrapolates from edge cells. The old surface is piecewise linear, so RK order describes trajectory integration, not the spatial interpolation order. A failed characteristic solve throws an error without changing the chain.

source
JustPIC.semilagrangian_advection_LinP! Method
julia
semilagrangian_advection_LinP!(F, F0, method, V, grid_vi, grid, dt)

Semi-Lagrangian advection variant that evaluates backtracked velocities with the LinP interpolation scheme.

Use this when the advecting velocity should be reconstructed with the LinP scheme instead of plain linear interpolation.

Notes

  • F is overwritten in place at the interior nodes; boundary nodes are left untouched.

  • F0 is the source field from the previous step and is only read.

  • F and F0 must not share memory; aliased buffers throw an ArgumentError. See semilagrangian_advection!.

source
JustPIC.semilagrangian_advection_MQS! Method
julia
semilagrangian_advection_MQS!(F, F0, method, V, grid_vi, grid, dt)

Semi-Lagrangian advection variant that evaluates backtracked velocities with the MQS interpolation scheme.

Use this when the advecting velocity should be reconstructed with the MQS scheme instead of plain linear interpolation.

Notes

  • F is overwritten in place at the interior nodes; boundary nodes are left untouched.

  • F0 is the source field from the previous step and is only read.

  • F and F0 must not share memory; aliased buffers throw an ArgumentError. See semilagrangian_advection!.

source
JustPIC.semilagrangian_advection_markerchain! Method
julia
semilagrangian_advection_markerchain!(chain, method, V, grid_vxi, grid, dt; max_slope_angle = 45.0, conserve_mean = true)

Backtrack a marker chain through V and update the chain geometry with a semi-Lagrangian step.

Unlike advect_markerchain!, which moves the Lagrangian markers, this scheme solves for the new vertex heights whose backward trajectories land on the old surface. It then smooths slopes exceeding max_slope_angle degrees, restores the spatial mean height, and rebuilds the markers. Smoothing is a single pass, not a strict slope bound; use max_slope_angle = nothing (or 90 degrees) to disable it. Angles must be in [0, 90]. Set conserve_mean = false when the velocity field should change the mean height (for example, uniform uplift or boundary flux). Mean conservation uses cell-width weights, including on refined grids.

method must support backtracking (RungeKutta2 or RungeKutta4; Euler is not supported). grid_vxi holds the staggered velocity grids and grid the chain's vertex grid (xv, yv), whose horizontal coordinates must match chain.cell_vertices. The surface must remain single-valued; reduce dt if the characteristic solve fails.

source
JustPIC.set_precision Method
julia
set_precision(integrator, T)

Recast an integrator's stored parameters to the scalar precision T.

This is applied at the advection launch sites so that a Float32 backend (such as Metal, which has no Float64) never carries a Float64 field into a GPU kernel. It is the identity for parameter-free integrators and, on the Float64 CPU/CUDA/AMDGPU path, a no-op (the value is preserved).

source
JustPIC.set_topo_from_array! Method
julia
set_topo_from_array!(surf::MarkerSurface, z::AbstractMatrix)

Set the surface topography from a 2D array z of size (nx+1, ny+1). Also copies the values into topo0.

source
JustPIC.smooth_slopes! Method
julia
smooth_slopes!(chain::MarkerChain, max_angle::Real)

Smooth local slopes exceeding max_angle (in radians) in one pass.

Interior vertices whose left or right slope is steeper than tan(max_angle) are averaged with the linear interpolant between their neighbours. This preserves straight lines on refined grids and reduces to a 3-point average on uniform grids. This suppresses the spurious spikes that semi-Lagrangian backtracking can introduce on a steep interface; it is applied automatically inside semilagrangian_advection_markerchain!. Chains with fewer than three vertices are left untouched. This is not a strict slope bound.

source
JustPIC.smooth_surface_max_angle! Method
julia
smooth_surface_max_angle!(surf::MarkerSurface, max_slope_angle)

Smooth the topography where the slope angle exceeds max_slope_angle (in degrees, matching the MarkerChain smooth_slopes! convention).

This mirrors LaMEM's FreeSurfSmoothMaxAngle:

  1. Scan all cells, compute the max slope (tan) from the 4 corner nodes and the average cell height; mark cells exceeding tan(max_angle).

  2. For each node touching at least one marked cell, replace its topography with the average of the (up to 4) surrounding cell-center heights.

Arguments

  • surf : the MarkerSurface

  • max_slope_angle : maximum slope angle in degrees (e.g. 45.0)

source
JustPIC.staggered_grids Method
julia
staggered_grids(backend, xi_vel_cpu)

Build the device-resident grids carried by a Particles container from the staggered velocity grids: the velocity grids themselves, the cell-center and vertex grids extended with one periodic ghost node on each side, and the cell spacings together with their reciprocals.

source
JustPIC.subgrid_diffusion! Method
julia
subgrid_diffusion!(pT, T_grid, ΔT_grid, subgrid_arrays, particles, dt; d = 1.0)

Apply the vertex-based subgrid diffusion correction to particle temperatures.

Temperatures are interpolated from the grid to particles, relaxed using the local subgrid model, mapped back to the grid as a correction, and then reapplied to the particle temperatures.

Arguments

  • pT: particle temperature field updated in place.

  • T_grid: source temperature on the ghosted vertex grid, sized as length.(particles.xvi).

  • ΔT_grid: resolved-grid temperature increment carrying one ghost node per side, sized ncells .+ 2.

  • subgrid_arrays: scratch storage created with SubgridDiffusionCellArrays(particles).

  • particles: particle container.

  • dt: timestep.

  • d: dimensionless subgrid diffusion coefficient.

source
JustPIC.subgrid_diffusion_centroid! Method
julia
subgrid_diffusion_centroid!(pT, T_grid, ΔT_grid, subgrid_arrays, particles, dt; d = 1.0)

Centroid-grid variant of subgrid_diffusion!.

Use this when the resolved temperature field lives at cell centers instead of vertices. T_grid is then the ghosted centroid field sized as length.(particles.xci), while ΔT_grid keeps the same ncells .+ 2 layout as in subgrid_diffusion!.

source
JustPIC.update_cell_halo! Method
julia
update_cell_halo!(x::CellArray...)

Synchronize the overlapping MPI halo of one or more CellArrays in place.

This is the CellArray companion to ImplicitGlobalGrid.update_halo! and is typically used after particle coordinates or per-particle fields have changed on each rank.

Arguments

  • x: one or more CellArrays with the same logical grid layout.

Notes

  • Every provided CellArray is updated; this is convenient for particles.coords, particles.index, and particle field arrays returned by init_cell_arrays.

  • For MPI particle advection, halo exchange is usually required before move_particles! so that particles that crossed a rank boundary are visible to the neighboring rank.

  • With periodic boundary conditions, update_cell_halo! exchanges the overlap across the periodic domain boundaries as configured in init_global_grid.

  • If particles are reinjected with inject_particles!, refresh the halos again before reconstructing grid fields with particle2grid!.

Example

julia
advection!(particles, RungeKutta2(), V, dt)
update_cell_halo!(particles.coords...)
update_cell_halo!(particle_args...)
update_cell_halo!(particles.index)
move_particles!(particles, particle_args)
inject_particles!(particles, particle_args)
particle2grid!(T, pT, particles)
source
JustPIC.update_surface_halo! Method
julia
update_surface_halo!(surf::MarkerSurface)

Exchange the x/y MPI halo of surf.topo between neighbouring ranks of the active ImplicitGlobalGrid global grid. No-op when no global grid is initialized (serial runs).

Called automatically at the end of advect_surface_topo!, smooth_surface_max_angle!; only needed explicitly after modifying surf.topo by hand.

Notes

  • surf must be built from the local (rank) vertex coordinates.

  • Under MPI, use the global-grid periodicity (periodx/periody in init_global_grid) and leave surf.periodic_1/periodic_2 as false; the local periodic flags wrap within the rank-local array.

source
JustPIC.@idx Macro
julia
@idx(args...)

Make a linear range from 1 to args[i], with i ∈ [1, ..., n]

source