Input validation and failure behavior
Every public entry point checks its arguments on the host before it launches a kernel that writes user data. A check that fails throws an ArgumentError or a DimensionMismatch that names the offending argument, so the input data are left unchanged. This page lists the policies these checks enforce.
Precision, backend, and shape
Precision. Every floating-point array passed together with a particle container must have the same scalar element type as the particle coordinates. Mixed precision is rejected, not converted, because a narrowing conversion inside a kernel is silent. Scalars such as
dtare converted to the particle precision.Metal and Float64. Metal has no
Float64. Constructors such asinit_particles,PhaseRatios,init_passive_markers,init_markerchain, andinit_marker_surfacethrow on the Metal backend when the grids or the requested type areFloat64.Backend. Every array argument must live on the backend of the particles. Coordinate ranges carry no device storage and are accepted on every backend.
Grid fields. Grid fields must have the size of the grid they are sampled on: the vertex grid for
particle2grid!/grid2particle!, the cell centers forparticle2centroid!/centroid2particle!. Along a direction withghost_i = true(the default) the field includes the ghost nodes; along a direction withghost_i = falseit holds only the physical nodes.Particle fields. Per-particle fields must be
CellArrays with the cell layout ofparticles.index, that is, the same grid size and the same number of slots per cell. Fields that holdNaNin empty slots (argsofmove_particles!and the injection routines) must be floating point.Tuples. A destination and its source must both be single fields or tuples of the same length.
Velocity.
Vmust be a tuple with one component per dimension, andV[d]must have the size of the staggered gridgrid_vi[d].
Grids
A coordinate vector must hold at least two finite, strictly increasing entries, and all grid coordinates must share one floating-point type. For init_particles, the off-diagonal staggered grids grid_vi[d][i] are the cell-center grids of direction i extended by one ghost center on each side, so they have one more entry than the vertex grid grid_vi[i][i].
Aliasing
Source and destination arrays must not share memory. The checks reject:
the particle coordinates among the companion fields
argsofmove_particles!and the injection routines, and any two entries ofargsthat share memory;a grid field and a particle field of an interpolation call that share memory, and entries of a tuple-valued destination that share memory;
FandF0ofsemilagrangian_advection!that share memory;the grid field, marker field, and buffer of a passive-marker scatter that share memory.
Coordinates and displacement
Material particles.
move_particles!rejectsNaNin any active coordinate slot, becauseNaNmeans an invalid velocity field or time step. An infinite coordinate is valid input: it marks a particle that left the velocity grid during advection, andmove_particles!removes it like any other particle outside the domain.Boundary escape. Particles that leave a non-periodic direction are discarded. Along a periodic direction they wrap to the opposite side; the ghost cells of a periodic direction must be empty when
move_particles!is called.Displacement. A particle may cross any number of cells in one call to
move_particles!. Large jumps are slower, not rejected; see themove_particles!docstring. If a destination cell is still full once no particle can move any more, the particle and its companion fields are dropped;verbose = trueprints the number of dropped particles.Passive markers. Passive markers have no occupancy mask.
init_passive_markersrequires finite coordinates, and interpolation and advection require every marker to lie inside the grid.advection!stops markers on the boundary instead of moving them outside.Time step and integrator.
dtmust be finite. The advection routines acceptEuler,RungeKutta2, andRungeKutta4; any other integrator is rejected.
Empty support
A grid node whose interpolation stencil contains no particle has no data. JustPIC marks such a node with NaN instead of inventing a value. This applies to:
particle2grid!andparticle2centroid!for material particles;particle2grid!for passive markers;update_phase_ratios!,phase_ratios_center!,phase_ratios_vertex!, and the face and midpoint phase ratios.
Test for NaN with isnan to detect empty support. Keep particle occupancy high enough, for example with inject_particles!, to avoid it.
Phase labels
A phase label must be an integer value in 1:nphases, where nphases is the number of phases of the PhaseRatios object. Phase labels may be stored with a floating-point element type. The phase-ratio routines count invalid labels over the active slots and throw if there is any.
MPI and ghost layout
update_cell_halo!requires an initialized ImplicitGlobalGrid.Passive markers do not support MPI runs with more than one rank.
Grid fields follow the ghost-node layout described in Grid layouts.
Unsupported combinations
The support matrix lists the combinations marked Unsupported. The entry points reject these with an error instead of running an incorrect method:
Float64on Metal, for every constructor;passive markers in MPI runs with more than one rank;
advection integrators other than
Euler,RungeKutta2, andRungeKutta4;2D or 3D mismatches between the phase ratios and the particles, and 3D-only midpoint phase ratios requested for 2D particles.