Time Derivatives¶
Time derivative operators approximate \(D\phi/Dt\) or \(DF/Dt\) for transient
solvers. All operators share a common interface: update_pre_solve(dt)
before each timestep, bdf() for the BDF approximation in the weak form,
and update_post_solve(dt) after the solve completes.
History is initialised automatically on the first solve call, and BDF order
ramps from 1 up to the requested order over the first few timesteps.
For analytical-IC benchmarks (no startup transient) or checkpoint restarts,
set_initial_history(values, dt=...) plants the BDF history directly and
bypasses the order ramp, so the first solve runs at full BDF order.
Base Class¶
Symbolic¶
- class underworld3.systems.ddt.Symbolic[source]¶
Bases:
_DDtBaseSymbolic history manager for time derivative approximations.
Manages the update of a variable \(\psi\) across timesteps. The history operator stores \(\psi\) over several timesteps (given by
order) so that it can compute backward differentiation (BDF) or Adams-Moulton expressions.The history operator is defined as:
\[\begin{split}\psi_p^{t-n\Delta t} &\leftarrow \psi_p^{t-(n-1)\Delta t} \\ \psi_p^{t-(n-1)\Delta t} &\leftarrow \psi_p^{t-(n-2)\Delta t} \cdots \\ \psi_p^{t-\Delta t} &\leftarrow \psi_p^{t}\end{split}\]This is a purely symbolic history manager that operates on sympy expressions without mesh or swarm storage. It is useful for tracking symbolic expressions through time-stepping algorithms.
- Parameters:
psi_fn (sympy.Basic) – The sympy expression to track. Can be scalar or matrix form.
theta (float, optional) – Implicitness parameter for Adams-Moulton order 1 (default
0.5). Values: 0 = explicit, 1 = implicit, 0.5 = Crank-Nicolson.varsymbol (str, optional) – LaTeX symbol for display (default
r"\\psi").verbose (bool, optional) – Enable verbose output (default
False).bcs (list, optional) – Accepted for interface parity with the projection-backed flavors (
Eulerian/SemiLagrangian); Symbolic has no projection solver, so this is stored but unused (default[]).order (int, optional) – Order of time integration (1-3) (default
1).smoothing (float, optional) – Accepted for interface parity with the projection-backed flavors; stored but unused by Symbolic (default
0.0).
Notes
The
Symbolicclass is the base for understanding BDF and Adams-Moulton formulas without the complexity of mesh or swarm storage. It is primarily useful for:Understanding time-stepping algorithm behavior
Debugging symbolic expressions in time-dependent problems
Prototyping before implementing with mesh/swarm storage
For actual simulations, use
Eulerian,SemiLagrangian, orLagrangianwhich store history on computational meshes or swarms.See also
EulerianMesh-based history with BDF time-stepping.
SemiLagrangianNodal-swarm approach for advection-dominated problems.
LagrangianSwarm-based material tracking.
- __init__(psi_fn, theta=0.5, varsymbol='\\psi', verbose=False, bcs=[], order=1, smoothing=0.0)[source]¶
- property state: DDtSymbolicState¶
Return a snapshot-of-state dataclass for this DDt instance.
- property psi_fn¶
Current symbolic expression \(\psi\) being tracked.
- initialise_history()[source]¶
Initialize all history slots to the current value of \(\psi\).
Called automatically on the first
update_pre_solve. Can also be called manually after setting initial conditions.
- update_pre_solve(dt, evalf=False, verbose=False)[source]¶
Pre-solve update hook. Auto-initialises history on first call.
- update_post_solve(dt, evalf=False, verbose=False)[source]¶
Shift history chain after solve: \(\psi^{*n} \leftarrow \psi^{*(n-1)}\).
- update_exp_coefficients(dt, tau_eff)[source]¶
Update the ETD-2 (exponential) coefficient values for this step.
Sets
self._exp_coeffs[0].sym = αandself._exp_coeffs[1].sym = φfrom currentdtandtau_eff(Maxwell relaxation time \(\tau = \eta_\mathrm{eff}/\mu\)). Called by the constitutive model (which owns τ_eff) before each solve, peer to the BDF/AM coefficient updates that happen automatically inupdate_pre_solve.
Eulerian Derivatives¶
Eulerian¶
- class underworld3.systems.ddt.Eulerian[source]¶
Bases:
_DDtBaseEulerian (mesh-based) history manager for time derivatives.
Manages the update of a variable \(\psi\) on the mesh across timesteps, storing history values on mesh variables for backward differentiation.
\[\begin{split}\psi_p^{t-n\Delta t} &\leftarrow \psi_p^{t-(n-1)\Delta t} \\ \psi_p^{t-(n-1)\Delta t} &\leftarrow \psi_p^{t-(n-2)\Delta t} \cdots \\ \psi_p^{t-\Delta t} &\leftarrow \psi_p^{t}\end{split}\]When
V_fnis provided, theupdate_pre_solvemethod applies an explicit advection correction so thatbdf()approximates the full material derivative \(D\psi/Dt = \partial\psi/\partial t + \mathbf{u}\cdot\nabla\psi\) rather than the partial time derivative alone.Note
The optional advection capability (V_fn parameter) is suitable for problems where the advection is weak or where a purely grid-based approach is desired (e.g., Richards equation with no transport). For advection-dominated problems, SemiLagrangian is more mature and generally preferred.
- Parameters:
mesh (underworld3.discretisation.Mesh) – The computational mesh.
psi_fn (MeshVariable or sympy.Basic) – The quantity to track. Can be a mesh variable or symbolic expression.
vtype (VarType) – Variable type (SCALAR, VECTOR, etc.) for history storage.
degree (int) – Polynomial degree for history mesh variables.
continuous (bool) – Whether history variables are continuous across element boundaries.
V_fn (sympy.Basic, optional) – Velocity field for grid-based advection correction. If None (default), computes pure ∂ψ/∂t. If set, computes D/Dt = ∂/∂t + u·∇ via operator splitting.
evalf (bool, default=False) – If True, evaluate expressions numerically during updates.
theta (float, default=0.5) – Time-stepping parameter for implicit/explicit blending. theta=0 is fully explicit, theta=1 is fully implicit.
varsymbol (str, default=r"u") – LaTeX symbol for display.
verbose (bool, default=False) – Enable verbose output during updates.
bcs (list, default=[]) – Boundary conditions to apply to projections.
order (int, default=1) – Number of history timesteps to store (for multi-step methods).
smoothing (float, default=0.0) – Smoothing parameter for projections.
See also
SemiLagrangianFor advection-dominated problems with nodal swarm.
LagrangianFor full Lagrangian tracking on swarms.
SymbolicFor purely symbolic history (no mesh storage).
- __init__(mesh, psi_fn, vtype, degree, continuous, V_fn=None, evalf=False, theta=0.5, varsymbol='u', verbose=False, bcs=[], order=1, smoothing=0.0)[source]¶
- property state: DDtEulerianState¶
Return a snapshot-of-state dataclass for this Eulerian DDt.
- property psi_fn¶
Current symbolic expression \(\psi\) being tracked.
- update_history_fn()[source]¶
Copy current \(\psi\) to
psi_star[0]via evaluation or projection.Three routes, in order of preference: direct nodal copy when tracking a mesh variable with the same layout; pointwise evaluation of
psi_fn; an L2 projection for expressions thatevaluatecannot handle (e.g. containing derivatives).
- initialise_history()[source]¶
Initialize all history slots to the current value of \(\psi\).
Called automatically on the first
update_pre_solve. Can also be called manually after setting initial conditions to ensure the history chain starts from the correct state.
- set_initial_history(values, dt=None)[source]¶
Plant history values for BDF restart or analytical IC.
Bypasses the automatic
effective_orderramp so the very first solve runs at the full BDF order rather than starting at BDF-1. Use this when you have known values at \(t\) and past times — e.g. an analytical periodic solution, or a checkpointed history loaded from disk.- Parameters:
values (sequence of length
self.order) –values[k]is \(\psi\) at \(t - k\,\Delta t\), i.e.values[0]is the current state. Each entry must be assignable topsi_star[k].array— either an array of matching shape, or a scalar that broadcasts.dt (float, optional) – Uniform timestep assumed between history slots. Required for
order >= 2to seed correct multistep coefficients on the first solve. Ignored fororder = 1.
- update_pre_solve(dt, evalf=False, verbose=False)[source]¶
Pre-solve: auto-initialise history and apply advection correction.
On the first call, automatically initialises history from the current field values. If V_fn is set, also applies an explicit grid-based advection correction so that bdf() approximates the material derivative Dφ/Dt rather than ∂φ/∂t.
Lagrangian Derivatives¶
SemiLagrangian¶
- class underworld3.systems.ddt.SemiLagrangian[source]¶
Bases:
_DDtBaseSemi-Lagrangian history manager using nodal swarm.
Manages the semi-Lagrangian update of a mesh variable \(\psi\) across timesteps. Uses a nodal swarm to track departure points and interpolate values back to the mesh.
\[\begin{split}\psi_p^{t-n\Delta t} &\leftarrow \psi_p^{t-(n-1)\Delta t} \\ \psi_p^{t-(n-1)\Delta t} &\leftarrow \psi_p^{t-(n-2)\Delta t} \cdots \\ \psi_p^{t-\Delta t} &\leftarrow \psi_p^{t}\end{split}\]The semi-Lagrangian method traces characteristics backward in time to find departure points, providing stable advection without CFL restrictions while maintaining accuracy.
- Parameters:
mesh (underworld3.discretisation.Mesh) – The computational mesh.
psi_fn (sympy.Function) – The quantity to advect (typically a mesh variable’s symbolic form).
V_fn (sympy.Function) – Velocity field for advection (e.g.,
stokes.u.sym).vtype (VarType) – Variable type (SCALAR, VECTOR, SYM_TENSOR, etc.).
degree (int) – Polynomial degree for mesh variable storage.
continuous (bool) – Whether variables are continuous across element boundaries.
swarm_degree (int, optional) – Polynomial degree for swarm interpolation. Defaults to
degree.swarm_continuous (bool, optional) – Continuity for swarm variables. Defaults to
continuous.varsymbol (str, optional) – LaTeX symbol for display.
verbose (bool, default=False) – Enable verbose output during updates.
bcs (list, default=[]) – Boundary conditions for projections.
order (int, default=1) –
Number of history timesteps and, for the time-derivative operator, the order of the BDF backward-difference stencil taken along the characteristic:
order = 1→[1, -1]: single-step difference(ψ^{n+1} - ψ*)/Δt. Paired with a trapezoidal (Crank-Nicolson,theta=0.5) flux this is the standard SLCN scheme — second- order accurate even though the stencil and the departure point are first-order, because the trapezoidal-along-the-trajectory structure recovers the order (Spiegelman & Katz, 2006).order = 2→[3/2, -2, 1/2]: BDF2 stencil(3/2 ψ^{n+1} - 2 ψ* + 1/2 ψ**)/Δt, using two departure points. This is the SL-BDF2 scheme. BDF2 is a one-sided implicit method: it expects the flux evaluated atn+1only, i.e. a Backward-Euler-centred flux (theta=1.0), not Crank-Nicolson. SL-BDF2 reaches the same second order as SLCN but avoids the spurious resonance/ringing CN can show on stiff modes (Bonaventura et al., 2021).
Important
BDF (time-derivative) and Adams-Moulton/θ (flux) are distinct multistep families and must be paired consistently: SLCN =
order=1+theta=0.5; SL-BDF2 =order=2+theta=1.0. Mixing a BDF2 stencil with a Crank-Nicolson flux (order=2+theta=0.5) centres the two sides at different times and is not a consistent second-order scheme. InSNES_AdvectionDiffusionthe advectiveDuDtcarries this BDForderwhile the diffusiveDFDtcarries the θ-method flux — set them as a matched pair.smoothing (float, default=0.0) – Smoothing parameter for projections.
preserve_moments (bool, default=False) – Not implemented. Passing
TrueraisesNotImplementedError. (The moment-preserving projection this promised was never wired in; the parameter is retained so existing call signatures keep working.)with_forcing_history (bool, default=False) – When True, allocate an additional
forcing_starMeshVariable (matchingpsi_star[0]’s shape, vtype, degree, continuity) to store one history slot for the strain-rate forcing. Required by ETD-2 exponential integration of the Maxwell relaxation operator; ignored for BDF/AM. Populated each step viaupdate_forcing_history()(direct nodal evaluation offorcing_fn— typically the constitutive model’s strain-rate symbol).theta (float, default=0.5) –
Adams-Moulton θ for the implicit flux integrator at order 1. The order-1 AM coefficients are
[θ, 1-θ]:θ = 0.5→ Crank-Nicolson (trapezoidal, second-order accurate, A-stable). Default, matches legacy SLCN behaviour.θ = 1.0→ Backward Euler (L-stable, monotone for diffusion, first-order accurate). Use for stiff parabolic terms (under-resolved sharp gradients on deformed cells) where CN’s lack of L-stability causes sign-flip ringing on stiff modes.
Settable after construction as a property:
adv_diff.DuDt.theta = 1.0.
Notes
The semi-Lagrangian method is particularly useful for:
Advection-dominated problems (high Péclet number)
Problems where CFL stability is restrictive
Viscoelastic stress advection
The time-derivative (BDF
order) and the diffusive flux integrator (Adams-Moultontheta) are separate choices that must be paired consistently — seeorderandthetaabove and the discussion indocs/advanced/semi-lagrangian-time-integration.md.References
Spiegelman, M., & Katz, R. F. (2006). A semi-Lagrangian Crank-Nicolson algorithm for the numerical solution of advection-diffusion problems. Geochemistry, Geophysics, Geosystems, 7(4). https://doi.org/10.1029/2005GC001073
Bonaventura, L., Calzola, E., Carlini, E., & Ferretti, R. (2021). Second order fully semi-Lagrangian discretizations of advection-diffusion-reaction systems. Journal of Scientific Computing, 88, 23. https://doi.org/10.1007/s10915-021-01518-8 — SL-BDF2 reaches second order while avoiding the spurious resonance of CN-type schemes.
See also
EulerianFor fixed-mesh time derivatives without advection.
LagrangianFor full particle-following Lagrangian tracking.
- __init__(mesh, psi_fn, V_fn, vtype, degree, continuous, swarm_degree=None, swarm_continuous=None, varsymbol=None, verbose=False, bcs=[], order=1, smoothing=0.0, preserve_moments=False, with_forcing_history=False, monotone_mode=None, theta=0.5, old_frame_traceback=False)[source]¶
- Parameters:
- on_remesh(ctx)[source]¶
Adapt-time hook: ALE for the SL history stack.
Two branches:
Standard ALE (smooth adapt). The SL-owned vars (
psi_star[i],forcing_star,_workVar, the flattening view_psi_star_flat_var) are CARRY + operator-managed — the generic per-variable pass already skipped them, and we leave their.datauntouched here. Accumulatectx.total_dispontoself._pending_v_mesh_dispso the nextupdate_pre_solve()runs the SL trace-back along(V_fn − v_mesh)withv_mesh = Δx / dt— that subtraction is exactly what compensates for the arbitrary mesh motion when reading the CARRY’d history. One-step pulse: the next solve consumes Δx and clears it.Opt-out (discrete-jump adapts). When the adapt is a discrete jump rather than a smooth displacement (
ctx.scratch.get("ale_opt_out")), the linearΔx/dt → v_meshinterpretation breaks down. Fall back to Phase-1 REMAP for this DDt’s managed vars: callremap_var_set()with the pre-move snapshot inctx.managed_snapshot. The pendingv_meshis cleared because REMAP already brought the history onto the new positions.
Accumulation across multiple adapts before one solve is linear:
v_mesh_disp += ctx.total_disp. The trace-back uses the SUM divided by the nextdt, which is the correct node-frame velocity for that step.
- property state: DDtSemiLagrangianState¶
- property psi_fn¶
Current symbolic expression \(\psi\) being tracked.
- enable_source_snapshot()[source]¶
Enable snapshot substitution in the projection’s source field.
Call this once when the source expression (
psi_fn) referencespsi_star[0]itself — without it the projection’s residual(target − flux(psi_star[0]))·weightis implicit in the target because target and source share the same data field. With Min-mode plasticity at the yield kink, the implicit projection admits two fixed points (elastic and yield branches); under timestep change the iteration drifts to the elastic-branch fixed point and σ violates the yield surface.The snapshot is a separate mesh variable matching
psi_star[0]’s shape/vtype/degree. Each call toupdate_pre_solvecopiespsi_star[0].array → psi_snapshot.array, freezing the source’s input for the upcoming projection. Substitution makes the projection’s compiled C code read frompsi_snapshot.arrayinstead ofpsi_star[0].array— there’s no recompile per step, just a memcpy.Idempotent: safe to call more than once.
- initialise_history()[source]¶
Initialize all history slots to the current value of \(\psi\).
Called automatically on the first
update_pre_solve. Can also be called manually after setting initial conditions.
- set_initial_history(values, dt=None)[source]¶
Plant history values for BDF restart or analytical IC.
Bypasses the automatic
effective_orderramp so the very first solve runs at the full BDF order rather than starting at BDF-1. Use this when you have known values at \(t\) and past times — e.g. an analytical periodic solution, or a checkpointed history loaded from disk.- Parameters:
values (sequence of length
self.order) –values[k]is \(\psi\) at \(t - k\,\Delta t\), i.e.values[0]is the current state. Each entry must be assignable topsi_star[k].array— either an array of matching shape, or a scalar that broadcasts.dt (float, optional) – Uniform timestep assumed between history slots. Required for
order >= 2to seed correct multistep coefficients on the first solve. Ignored fororder = 1.
- update(dt, evalf=False, verbose=False, dt_physical=None)[source]¶
Update history (alias for
update_pre_solve).
- update_post_solve(dt, evalf=False, verbose=False, dt_physical=None)[source]¶
Post-solve: record timestep and increment solve counter.
- update_pre_solve(dt, evalf=False, verbose=False, dt_physical=None, store_result=True, monotone_mode='__instance__')[source]¶
Sample upstream values along characteristics before solve.
On the first call, automatically initialises history from the current field values so that bdf() returns zero on the first step.
The method reads as its four phases: shift the history chain (
_shift_history_with_blend()), record the current field (_record_current_field_into_history()), trace the characteristics back (_trace_departure_points()), and sample the history at the departure points (_sample_history_at_departure()).- Parameters:
store_result (bool, optional) – If True (default), evaluate psi_fn at current positions and store in psi_star[0] before advection — the standard DDt behaviour. If False, skip this step and the history shift: only advect the existing psi_star levels upstream. Used by VE_Stokes where psi_star[0] already contains the projected actual stress from the previous solve.
monotone_mode (str or None, optional) – Override the instance
self.monotone_modefor this call. Default"__instance__"(sentinel) means “use whatever is on the instance”. PassNone,"clamp", or"pick"to force a particular mode for one call.dt (float)
evalf (bool | None)
verbose (bool | None)
dt_physical (float | None)
- update_exp_coefficients(dt, tau_eff)[source]¶
Update the scalar ETD-2 (exponential) coefficient UWexpressions.
Sets
self._exp_coeffs[0].sym = α = exp(-Δt/τ_eff)andself._exp_coeffs[1].sym = φ = (1-α)/(Δt/τ_eff)so the next solve uses the correct exponential coefficients via PetscDSSetConstants on the next_update_constantscall.
- update_forcing_history(forcing_fn=None, evalf=False, verbose=False)[source]¶
Refresh
forcing_starfromforcing_fnvia direct nodal evaluation.Used by ETD-2 exponential integration to store the current strain-rate field as \(\dot\varepsilon^{n}\) for the next step’s history term. Called by the constitutive model from the solver’s post-solve hook. Direct nodal evaluation (rather than an L2 projection through SNES) is sufficient because the strain rate is \(\nabla\mathbf{u}\), well-defined at nodes, with no history-coupled term that would make a projection implicit.
Unit handling¶
forcing_staris allocated withunits=None(see__init__). When the model is unit-aware,forcing_fnis a symbolic expression of the velocity field whose evaluation returns aUnitAwareArraycarrying strain-rate units (1/time). We non-dimensionalise that result via the active scaling system before assigning toforcing_star.array, which keeps the stored values consistent with the rest of the variable storage (codebase convention: variable storage is non-dimensional; units are re-attached at the.datainterface). When the model is not unit-aware, the evaluation returns a plain ndarray and assignment is a straight numpy copy.- param forcing_fn:
Symbolic strain-rate field to evaluate at each node. If None, falls back to
self._forcing_fn(set by the constitutive model at solve-attach time). No-op if neither is set orwith_forcing_history=False.- type forcing_fn:
sympy expression, optional
- param evalf:
Forwarded to
uw.function.evaluate(forces numerical evaluation when True).- type evalf:
bool, optional
- param verbose:
Enable verbose output.
- type verbose:
bool, optional
Lagrangian¶
- class underworld3.systems.ddt.Lagrangian[source]¶
Bases:
_DDtBaseSwarm-based Lagrangian history manager for material tracking.
Manages the update of a Lagrangian variable \(\psi\) on a swarm across timesteps. Creates and manages its own internal swarm for tracking material properties through the flow.
\[ \begin{align}\begin{aligned}\psi_p^{t-n\Delta t} \leftarrow \psi_p^{t-(n-1)\Delta t}\\\psi_p^{t-(n-1)\Delta t} \leftarrow \psi_p^{t-(n-2)\Delta t} \cdots\\\psi_p^{t-\Delta t} \leftarrow \psi_p^{t}\end{aligned}\end{align} \]The Lagrangian approach follows material points through the flow, avoiding numerical diffusion in advection. History values are stored on swarm variables with proxy mesh variables for solver integration.
- Parameters:
mesh (underworld3.discretisation.Mesh) – The computational mesh.
psi_fn (sympy.Function) – The quantity to track (e.g., stress tensor
stokes.stress).V_fn (sympy.Function) – Velocity field for particle advection.
vtype (VarType) – Variable type (SCALAR, VECTOR, SYM_TENSOR, etc.).
degree (int) – Polynomial degree for proxy mesh variables.
continuous (bool) – Whether proxy variables are continuous across elements.
varsymbol (str, default=r"u") – LaTeX symbol for display.
verbose (bool, default=False) – Enable verbose output during updates.
bcs (list, default=[]) – Boundary conditions (currently unused for swarm variables).
order (int, default=1) – Number of history timesteps to store.
smoothing (float, default=0.0) – Smoothing parameter for projections.
fill_param (int, default=3) – Fill parameter for swarm population density.
Notes
The Lagrangian method is ideal for:
Viscoelastic stress history tracking
Material property advection without diffusion
Tracking compositional fields
The internal swarm is automatically advected during updates.
See also
SemiLagrangianMesh-based semi-Lagrangian with departure points.
Lagrangian_SwarmFor user-provided swarms.
- instances = 0¶
- __init__(mesh, psi_fn, V_fn, vtype, degree, continuous, varsymbol='u', verbose=False, bcs=[], order=1, smoothing=0.0, fill_param=3)[source]¶
- on_remesh(ctx)[source]¶
Adapt-time hook (Phase 1 no-op).
Lagrangian history is carried by the underlying swarm (each particle holds its own
psi_starvalues), so there is no mesh-side state to transfer on an adapt — the swarm’s particle positions stay put and the new cells re-claim them. Method is defined so the registration shim has a target.
- property state: DDtLagrangianState¶
- initialise_history()[source]¶
Initialize all history slots to the current value of \(\psi\).
Called automatically on the first
update_pre_solve. Can also be called manually after setting initial conditions.
Lagrangian_Swarm¶
- class underworld3.systems.ddt.Lagrangian_Swarm[source]¶
Bases:
_DDtBaseSwarm-based Lagrangian history manager (user-provided swarm).
Manages the update of a Lagrangian variable \(\psi\) on a user-supplied swarm across timesteps:
\[ \begin{align}\begin{aligned}\psi_p^{t-n\Delta t} \leftarrow \psi_p^{t-(n-1)\Delta t}\\\psi_p^{t-(n-1)\Delta t} \leftarrow \psi_p^{t-(n-2)\Delta t} \cdots\\\psi_p^{t-\Delta t} \leftarrow \psi_p^{t}\end{aligned}\end{align} \]Unlike
Lagrangian, this class uses a user-provided swarm rather than creating its own. The swarm should already be populated and configured for tracking material points.- Parameters:
swarm (underworld3.swarm.Swarm) – User-provided swarm for material point tracking.
psi_fn (sympy.Function) – The quantity to track (e.g., stress tensor from a solver).
vtype (underworld3.VarType) – Variable type (SCALAR, VECTOR, SYM_TENSOR, etc.).
degree (int) – Interpolation degree for proxy mesh variables.
continuous (bool) – Whether proxy mesh variables should be continuous.
varsymbol (str, optional) – LaTeX symbol for display (default
"u").verbose (bool, optional) – Enable verbose output (default
False).bcs (list, optional) – Boundary conditions (currently unused, default
[]).order (int, optional) – Order of time integration (1-3) (default
1).smoothing (float, optional) – Smoothing parameter (default
0.0).step_averaging (int, optional) – Number of steps for history averaging (default
2).
- mesh¶
Reference to the computational mesh (from swarm).
- swarm¶
The user-provided swarm.
- Type:
- psi_fn¶
Symbolic expression for the tracked quantity.
- Type:
sympy.Function
Notes
Key differences from
Lagrangianclass:Uses user-provided swarm (not internally created)
Swarm advection is NOT performed (user’s responsibility)
Step averaging for smoothing history updates
Suitable when swarm is shared between multiple history managers
The
step_averagingparameter scales the BDF formula to account for updates that occur over multiple sub-steps within a timestep.See also
LagrangianCreates and manages its own swarm with advection.
SemiLagrangianNodal-swarm approach for advection-dominated problems.
EulerianPure mesh-based history (no particle tracking).
- instances = 0¶
- __init__(swarm, psi_fn, vtype, degree, continuous, varsymbol='u', verbose=False, bcs=[], order=1, smoothing=0.0, step_averaging=2)[source]¶
- property state: DDtLagrangianSwarmState¶
- initialise_history()[source]¶
Initialize all history slots to the current value of \(\psi\).
Called automatically on the first
update_pre_solve. Can also be called manually after setting initial conditions.
Convenience Aliases¶
The following aliases are available via underworld3.systems:
Lagrangian_DDt→LagrangianSemiLagragian_DDt→SemiLagrangianLagrangian_Swarm_DDt→Lagrangian_SwarmEulerian_DDt→Eulerian