Time programs¶
pops.time is the temporal language. It builds a typed IR for one time step.
The generated step runs C++-side.
Ready-made schemes live in pops.lib.time.
Minimal program¶
from pops.time import Program
from pops.numerics.terms import Flux
T = Program("forward_euler")
U = T.state("U", block="plasma")
fields = T.solve_fields(U.n)
R = T.rhs(state=U.n, fields=fields, terms=[Flux()])
T.define(U.next, U.n + T.dt * R)
T.commit("plasma", U.next)
T.define materializes a state-valued IR node. T.commit marks the state that
replaces the live block at the end of the step.
Version handles¶
T.state("U", block="plasma") returns a temporal handle family:
Handle |
Meaning |
|---|---|
|
Current state at the start of the step. Read-only. |
|
Named intermediate state. Must be defined once with |
|
End-of-step state. Must be defined before |
|
History state for multistep schemes. Read-only. |
Handles contain no arrays. They resolve to IR values.
Ready schemes¶
Use pops.lib.time for provided schemes:
from pops.time import Program
from pops.lib.time import ssprk3
T = Program("advance")
ssprk3(T, "plasma")
Available families:
Function |
Family |
|---|---|
|
Explicit Euler |
|
Strong-stability-preserving RK |
|
Classic and tableau-driven explicit RK |
|
Multistep explicit schemes |
|
BDF program builder |
|
Split flows |
|
Local implicit source treatment |
|
Schur-condensed source-stage builder |
|
Predictor-corrector local-linear macro |
The functions add IR nodes to a Program. They do not compute arrays.
RHS terms¶
The public RHS builder takes typed terms:
from pops.numerics.terms import Flux, SourceTerm
electric = SourceTerm("electric")
R = T.rhs(state=U.n, fields=fields, terms=[Flux(), electric])
The string in SourceTerm("electric") names a source declared by the model. The
behavior is the typed SourceTerm object.
Operator handles¶
Programs can call model operators by handle:
fields_op = model.field_operator(...)
rate_op = model.rate(...)
T = Program("operator_step")
U = T.state("U", block="plasma")
fields = T.call(fields_op, U.n)
R = T.call(rate_op, U.n, fields)
T.define(U.next, U.n + T.dt * R)
T.commit("plasma", U.next)
Do not document string operator references. Strings may create operators; handles reference them.
Histories¶
Multistep schemes store and read history through handles or the lower-level history API:
T.keep_history("plasma.U", copy="current")
older = U.prev
History storage is runtime-owned C++ state.
Solves¶
Linear and nonlinear solves are described in the program and executed by compiled solver routes:
from pops.solvers.krylov import GMRES
phi = T.solve_linear(problem, method=GMRES(tolerance=1.0e-10))
Users configure provided solvers. Python never runs a Krylov loop.
Inspection¶
Useful methods:
print(T)
T.inspect()
T.dump_ir()
T.estimate_report()
T.scratch_liveness()
T.buffer_reuse_report()
Generated-source inspection happens on the compiled handle:
compiled.dump_ir()
compiled.dump_cpp("generated")
compiled.estimate_memory(grid=mesh)