Write a model with ready-made bricks

Use this tutorial when the physics you need is already available as compiled PoPS bricks or presets. The Python code selects typed descriptors and assembles a case; the C++ runtime executes the loops.

Build the pieces

from pops.mesh import CartesianMesh
from pops.mesh.layouts import Uniform
from pops.numerics.riemann import Rusanov
from pops.numerics.reconstruction import MUSCL
from pops.numerics.reconstruction.limiters import Minmod
from pops.time import Program
from pops.lib.time import ssprk3
from pops.codegen import Production

mesh = CartesianMesh(n=128, L=1.0, periodic=True)
layout = Uniform(mesh)

spatial = pops.FiniteVolume(
    riemann=Rusanov(),
    reconstruction=MUSCL(limiter=Minmod()),
)

Use a ready-made physics model from pops.lib.models when one exists:

from pops.lib.models import diocotron

model = diocotron.scalar_exb(background_density=n_i0)

The exact model preset depends on the library catalog. If no preset matches, write the physics with pops.physics.Model and lower it to pops.model.

Add a field solve

from pops.fields import PoissonProblem
from pops.fields.bcs import Periodic
from pops.fields.rhs import ChargeDensity
from pops.math import laplacian
from pops.solvers.elliptic import GeometricMG

phi = "phi"
poisson = PoissonProblem(
    name="phi",
    unknown=phi,
    equation=(-laplacian(phi) == ChargeDensity.from_blocks("electrons")),
    bcs=(Periodic(),),
    solver=GeometricMG(),
)

Assemble and run

program = Program("ssprk3")
ssprk3(program, "electrons")

case = (
    pops.Case(layout=layout, name="diocotron")
    .block("electrons", physics=model, spatial=spatial)
    .field(poisson)
    .time(program)
)

compiled = pops.compile(case, backend=Production())
sim = pops.bind(compiled, state={"electrons": ne0})
sim.run(t_final=0.1, cfl=0.4)

Switch to AMR

from pops.mesh.layouts import AMR
from pops.mesh.amr import Refine, RegridEvery

layout = AMR(
    base=mesh,
    max_levels=2,
    ratio=2,
    regrid=RegridEvery(4),
    refine=Refine.on("density").above(0.05),
)

Keep the same model, field problem, spatial descriptors, and time program. The layout descriptor selects the AMR C++ route during compile and bind.