TS
The TS (Time Stepping) module integrates ordinary differential equations and differential algebraic equations in time, and is the layer PETSc builds its implicit, explicit and IMEX methods on.
The interface described here is the high-level one. It owns the @cfunction trampolines, keeps your callbacks rooted for as long as the stepper lives, and frees the object for you on a sequential communicator. The low-level TS bindings remain available and unchanged.
Overview
A problem is given to TS in one of two forms, or in both at once:
- Explicit, $du/dt = G(t, u)$, through
PETSc.set_rhs_function!and optionallyPETSc.set_rhs_jacobian!. - Implicit, $F(t, u, du/dt) = 0$, through
PETSc.set_ifunction!andPETSc.set_ijacobian!. This form also covers a DAE and a problem with a mass matrix.
Setting both is how an IMEX method splits a problem into the stiff part it treats implicitly and the rest it treats explicitly.
Creating a stepper
ts = PETSc.TS(petsclib, MPI.COMM_WORLD)
# or with options, which are applied when you call solve!
ts = PETSc.TS(petsclib, MPI.COMM_WORLD;
ts_type = "bdf",
ts_adapt_type = "basic",
)Options given here are held and applied inside PETSc.solve! rather than at construction, so a DM and the callbacks attached afterwards are in place before PETSc reads them. Until then the object has no type, and PETSc.type answers nothing.
On a communicator of size 1 the garbage collector calls PETSc.destroy!. On a larger one, destruction is yours to do, since collection is asynchronous and the call is collective.
An explicit problem
Solving $du/dt = -u$ from $u(0) = 1$:
ts = PETSc.TS(petsclib, MPI.COMM_SELF)
PETSc.set_type!(ts, :rk)
u = PETSc.VecSeq(petsclib, 1)
u[1] = 1.0
PETSc.assemble!(u)
PETSc.set_rhs_function!(ts) do F, ts, t, u
PETSc.withlocalarray!((u, F); read = (true, false), write = (false, true)) do ua, Fa
Fa[1] = -ua[1]
end
return 0
end
PETSc.set_time!(ts, 0.0)
PETSc.set_timestep!(ts, 0.01)
PETSc.set_max_time!(ts, 1.0)
PETSc.solve!(u, ts)The callback comes first in the argument list, so do block syntax works. Pass it in the other order, set_rhs_function!(ts, f!), when it is already a value.
An implicit problem
The same equation written as $F(t, u, u_t) = u_t + u = 0$, stepped with backward Euler. The Jacobian asked for is $\partial F/\partial u + \sigma\, \partial F/\partial u_t$, where PETSc supplies the shift $\sigma$:
ts = PETSc.TS(petsclib, MPI.COMM_SELF)
PETSc.set_type!(ts, :beuler)
J = PETSc.MatSeqAIJ(petsclib, 1, 1, petsclib.PetscInt(1))
PETSc.set_ifunction!(ts) do F, ts, t, u, u_t
PETSc.withlocalarray!(
(u, u_t, F);
read = (true, true, false),
write = (false, false, true),
) do ua, uta, Fa
Fa[1] = uta[1] + ua[1]
end
return 0
end
PETSc.set_ijacobian!(ts, J) do A, P, ts, t, u, u_t, shift
A[1, 1] = shift + 1
PETSc.assemble!(A)
return 0
endA Jacobian callback is always handed both the Jacobian A and the preconditioning matrix P. They are the same object unless you passed two, which is worth testing with A.ptr == P.ptr before filling P a second time.
Callback signatures
| Setter | Callback |
|---|---|
PETSc.set_rhs_function! | f!(F, ts, t, u) |
PETSc.set_rhs_jacobian! | updateJ!(A, P, ts, t, u) |
PETSc.set_ifunction! | f!(F, ts, t, u, u_t) |
PETSc.set_ijacobian! | updateJ!(A, P, ts, t, u, u_t, shift) |
PETSc.set_monitor! | f(ts, step, t, u) |
Each may return a PETSc error code; any other return value counts as success.
A callback that raises a Julia exception is reported and turned into a PETSc failure rather than being allowed to escape into C, where it would take the process down with it. The error is logged with its backtrace and PETSc.solve! then raises a PetscError.
Precompilation
Each setter builds its @cfunction trampoline when you call it, so nothing here is affected by precompilation, and there is nothing you need to do about it.
It is worth knowing where the hazard is, though, because the low-level examples show the other pattern. A @cfunction yields a pointer valid only for the session that evaluated it, so this at the top level of a package:
const MY_RHS_PTR = @cfunction(my_rhs!, PetscErrorCode, (CTS, PetscReal, CVec, CVec, Ptr{Cvoid}))captures a pointer during precompilation and hands PETSc a stale one in every later session. In a script such as examples/ex16.jl it is fine, since the file is evaluated afresh each run. Inside a package it is not: build the pointer inside the function that registers it, or assign it from __init__.
Passing your own data
Anything stored with PETSc.set_user_ctx! is handed back as a trailing argument, to whichever callbacks have a method that accepts one:
PETSc.set_user_ctx!(ts, (; viscosity = 1e-3))
PETSc.set_rhs_function!(ts) do F, ts, t, u, ctx
# ctx.viscosity is available here
return 0
endThe object is held on the Julia side by ts, so it stays alive without any pinning of your own.
Watching a solve
PETSc.set_monitor!(ts) do ts, step, t, u
@printf("step %3d t = %.4f\n", step, t)
return 0
endThe monitor runs once before the first step and once after each accepted one. It does not replace the monitors PETSc installs from the options database, such as -ts_monitor.
Solving, and reading the result
PETSc.solve!(u, ts) # integrate, starting from u
PETSc.solve!(ts) # or from the vector already set on ts
PETSc.converged_reason(ts) # why it stopped
PETSc.solve_time(ts) # the time actually reached
PETSc.step_number(ts) # steps taken
PETSc.snes_iterations(ts) # nonlinear iterations, summed over the stepsThe final step lands exactly on PETSc.set_max_time! by default. This differs from PETSc, whose own default, TS_EXACTFINALTIME_UNSPECIFIED, integrates past the requested time without saying so; pass exact_final_time to the constructor or call PETSc.set_exact_final_time! to choose otherwise.
For finer control, PETSc.step! takes a single step and PETSc.interpolate! samples the solution inside the step just taken.
Cleaning up
PETSc.destroy!(ts)Safe to call more than once, and a no-op on a handle left over from a previous initialize/finalize cycle. PETSc.destroy also works, for consistency with the rest of the package.
Functions
PETSc.LibPETSc.TS — Method
TS(petsclib, comm::MPI.Comm; prefix = "", options...)Create a PETSc time stepper on the communicator comm.
Options are stored and applied in solve! rather than here, so that a DM and callbacks attached after construction are visible to TSSetFromOptions.
exact_final_time defaults to TS_EXACTFINALTIME_MATCHSTEP, so the last step lands on the time set by set_max_time!. PETSc's own default is TS_EXACTFINALTIME_UNSPECIFIED, which integrates to the wrong time without reporting an error.
If comm has size 1 the garbage collector calls destroy!. Otherwise destruction is the caller's responsibility.
External Links
- PETSc Manual:
TS/TSCreate
- PETSc Manual:
TS/TSSetExactFinalTime
PETSc.LibPETSc.TSARKIMEXRegister — Method
TSARKIMEXRegister(
petsclib,
name::String,
order,
s,
At,
bt,
ct,
A,
b,
c,
bembedt,
bembed,
pinterp,
binterpt,
binterp,
)Julia-friendly overload for registering a custom TSARKIMEX tableau. Optional PETSc arrays may be passed as nothing, which is translated to NULL.
For the stage tables At and A, PETSc expects flat vectors in row-major order, matching the layout used by C arrays. If you start from a Julia matrix, do not pass vec(A) directly since Julia stores matrices column-major; flatten row-by-row instead, for example with vec(permutedims(A)).
PETSc.LibPETSc.TSAdaptSetType — Method
TSAdaptSetType(petsclib, adapt, type::String)Convenience wrapper for setting the TS adaptivity controller using a Julia string such as "none" or "basic".
PETSc.LibPETSc.TSGetAdapt — Method
adapt = TSGetAdapt(petsclib, ts)Return the adaptive time-step controller attached to ts.
PETSc.LibPETSc.TSGetKSP — Method
TSGetKSP(petsclib, ts)Return the linear solver held by ts.
The generated three-argument form takes the solver as an input and nulls the caller's handle, so it cannot be used to read the solver back. The KSP is owned by ts and must not be destroyed.
External Links
- PETSc Manual:
TS/TSGetKSP
PETSc.LibPETSc.TSGetSNES — Method
TSGetSNES(petsclib, ts)Return the nonlinear solver held by ts.
The generated three-argument form takes the solver as an input and nulls the caller's handle, so it cannot be used to read the solver back. The SNES is owned by ts and must not be destroyed.
External Links
- PETSc Manual:
TS/TSGetSNES
PETSc.LibPETSc.TSGetSolution — Method
TSGetSolution(petsclib, ts)Return the solution vector held by ts.
The generated three-argument form takes the vector as an input and nulls the caller's handle, so it cannot be used to read the solution back. The vector is owned by ts and must not be destroyed.
External Links
- PETSc Manual:
TS/TSGetSolution
PETSc.LibPETSc.TSIRKGetNumStages — Method
TSIRKGetNumStages(petsclib, ts)Return the number of stages currently configured for a TSIRK method.
PETSc.LibPETSc.TSMonitorSet — Function
TSMonitorSet(petsclib, ts, monitor::Ptr{Cvoid}, ctx = C_NULL, mdestroy = C_NULL)Convenience overload for low-level TS monitor callbacks created with @cfunction.
PETSc.LibPETSc.TSSetIFunction — Function
TSSetIFunction(petsclib, ts, r, fptr::Ptr{Cvoid}, ctx = C_NULL)Convenience overload for low-level TS implicit-function callbacks created with @cfunction.
PETSc.LibPETSc.TSSetIJacobian — Function
TSSetIJacobian(petsclib, ts, A, P, fptr::Ptr{Cvoid}, ctx = C_NULL)Convenience overload for low-level TS implicit-Jacobian callbacks created with @cfunction.
PETSc.LibPETSc.TSSetRHSFunction — Function
TSSetRHSFunction(petsclib, ts, r, fptr::Ptr{Cvoid}, ctx = C_NULL)Convenience overload for low-level TS RHS callbacks created with @cfunction.
The generated bindings currently accept the PETSc function-wrapper type directly, while Julia's @cfunction returns a raw pointer. This overload bridges that gap so callback-based TS examples can use the low-level interface naturally.
PETSc.LibPETSc.TSSetRHSJacobian — Function
TSSetRHSJacobian(petsclib, ts, A, P, fptr::Ptr{Cvoid}, ctx = C_NULL)Convenience overload for low-level TS RHS-Jacobian callbacks created with @cfunction.
External Links
- PETSc Manual:
TS/TSSetRHSJacobian
PETSc.LibPETSc.TSSolve — Method
TSSolve(petsclib, ts, ::Nothing)Integrate ts using the solution vector already set on it.
The generated binding requires a vector. PETSc reads the solution set by TSSetSolution when it is handed NULL instead, which is what this overload passes.
External Links
- PETSc Manual:
TS/TSSolve
PETSc.comm — Method
comm(ts::AbstractTS)The MPI communicator ts was built on.
External Links
- PETSc Manual:
Sys/PetscObjectGetComm
PETSc.converged_reason — Method
converged_reason(ts::AbstractTS)Why the integration stopped, as a LibPETSc.TSConvergedReason.
External Links
- PETSc Manual:
TS/TSGetConvergedReason
PETSc.current_time — Method
PETSc.destroy! — Method
destroy!(ts::AbstractTS)Destroy ts and release the options database attached to it.
The call is a no-op when the library has been finalized or when ts predates the current initialize/finalize cycle, so a stale handle never reaches TSDestroy.
External Links
- PETSc Manual:
TS/TSDestroy
PETSc.destroy — Method
destroy(ts::AbstractTS)Destroy ts. Provided so that the spelling used by the rest of the package keeps working; destroy! is the name to prefer, since the call mutates ts.
External Links
- PETSc Manual:
TS/TSDestroy
PETSc.dm — Method
dm(ts::AbstractTS)The DM attached to ts. The DM is owned by ts.
External Links
- PETSc Manual:
TS/TSGetDM
PETSc.interpolate! — Method
interpolate!(u::AbstractPetscVec, ts::AbstractTS, t)Fill u with the solution interpolated to time t, and return it.
Only the methods that keep a dense output can do this, and t must lie inside the step just taken.
External Links
- PETSc Manual:
TS/TSInterpolate
PETSc.ksp — Method
ksp(ts::AbstractTS)The linear solver ts steps with. It is owned by ts, so do not destroy it.
PETSc only offers this for a problem declared TS_LINEAR with set_problem_type!, and raises PETSC_ERR_ARG_WRONG otherwise. The linear solver of a nonlinear problem belongs to its SNES, so reach it through snes.
External Links
- PETSc Manual:
TS/TSGetKSP
PETSc.ksp_iterations — Method
ksp_iterations(ts::AbstractTS)Total number of linear iterations taken so far, summed over the steps.
External Links
- PETSc Manual:
TS/TSGetKSPIterations
PETSc.max_steps — Method
max_steps(ts::AbstractTS)The step count at which integration stops.
External Links
- PETSc Manual:
TS/TSGetMaxSteps
PETSc.max_time — Method
max_time(ts::AbstractTS)The time at which integration stops.
External Links
- PETSc Manual:
TS/TSGetMaxTime
PETSc.reset! — Method
reset!(ts::AbstractTS)Release the work vectors and matrices ts allocated, keeping the callbacks and the options.
The clock is not part of that state: the time and the step count survive, so set them with set_time! and set_max_time! before integrating again.
External Links
- PETSc Manual:
TS/TSReset
PETSc.set_adapt_type! — Method
set_adapt_type!(ts::AbstractTS, type::Symbol)Set the timestep adaptivity controller, for example :none to hold the step size fixed, or :basic for the default error-based controller.
External Links
- PETSc Manual:
TS/TSAdaptSetType
PETSc.set_dm! — Method
PETSc.set_exact_final_time! — Method
set_exact_final_time!(ts::AbstractTS, option)Choose how the final step meets the time set by set_max_time!: TS_EXACTFINALTIME_MATCHSTEP, TS_EXACTFINALTIME_INTERPOLATE or TS_EXACTFINALTIME_STEPOVER.
External Links
- PETSc Manual:
TS/TSSetExactFinalTime
PETSc.set_from_options! — Method
set_from_options!(ts::AbstractTS)Apply the PETSc options database to ts.
External Links
- PETSc Manual:
TS/TSSetFromOptions
PETSc.set_ifunction! — Function
set_ifunction!(f!, ts::AbstractTS, r = nothing)
set_ifunction!(ts::AbstractTS, f!, r = nothing)Set the residual $F$ of an implicit problem $F(t, u, du/dt) = 0$.
f! is called as f!(F, ts, t, u, u_t), filling the vector F. If ts.user_ctx is set, f!(F, ts, t, u, u_t, user_ctx) is used instead when that method exists.
External Links
- PETSc Manual:
TS/TSSetIFunction
PETSc.set_ijacobian! — Function
set_ijacobian!(updateJ!, ts::AbstractTS, A, P = A)
set_ijacobian!(ts::AbstractTS, updateJ!, A, P = A)Set the Jacobian of the implicit residual $F$.
updateJ! is called as updateJ!(A, P, ts, t, u, u_t, shift) and should fill A with $dF/du + shift * dF/du_t$. If ts.user_ctx is set, the method taking a trailing user_ctx is used instead when it exists.
External Links
- PETSc Manual:
TS/TSSetIJacobian
PETSc.set_max_steps! — Method
set_max_steps!(ts::AbstractTS, n)Set the step count at which integration stops.
External Links
- PETSc Manual:
TS/TSSetMaxSteps
PETSc.set_max_time! — Method
set_max_time!(ts::AbstractTS, t)Set the time at which integration stops.
External Links
- PETSc Manual:
TS/TSSetMaxTime
PETSc.set_monitor! — Method
set_monitor!(f, ts::AbstractTS)
set_monitor!(ts::AbstractTS, f)Call f once after every accepted step.
f is called as f(ts, step, t, u), where step counts the steps taken, t is the time reached and u holds the solution there. If ts.user_ctx is set, f(ts, step, t, u, user_ctx) is used instead when that method exists. u is owned by ts and must not be destroyed.
Only one monitor can be set this way; a second call replaces the first. The monitors PETSc installs from the options database, such as -ts_monitor, are unaffected.
External Links
- PETSc Manual:
TS/TSMonitorSet
PETSc.set_problem_type! — Method
set_problem_type!(ts::AbstractTS, type)Declare the problem as LibPETSc.TS_LINEAR or LibPETSc.TS_NONLINEAR.
External Links
- PETSc Manual:
TS/TSSetProblemType
PETSc.set_rhs_function! — Function
set_rhs_function!(f!, ts::AbstractTS, r = nothing)
set_rhs_function!(ts::AbstractTS, f!, r = nothing)Set the right-hand side $G$ of an explicit problem $du/dt = G(t, u)$.
f! is called as f!(F, ts, t, u), filling the vector F. If ts.user_ctx is set, f!(F, ts, t, u, user_ctx) is used instead when that method exists.
r is an optional template vector for the residual.
External Links
- PETSc Manual:
TS/TSSetRHSFunction
PETSc.set_rhs_jacobian! — Function
set_rhs_jacobian!(updateJ!, ts::AbstractTS, A, P = A)
set_rhs_jacobian!(ts::AbstractTS, updateJ!, A, P = A)Set the Jacobian of the right-hand side $G$.
updateJ! is called as updateJ!(A, P, ts, t, u), filling the Jacobian A and the preconditioning matrix P. If ts.user_ctx is set, updateJ!(A, P, ts, t, u, user_ctx) is used instead when that method exists.
External Links
- PETSc Manual:
TS/TSSetRHSJacobian
PETSc.set_solution! — Method
set_solution!(ts::AbstractTS, u::AbstractPetscVec)Set the initial condition of ts.
External Links
- PETSc Manual:
TS/TSSetSolution
PETSc.set_time! — Method
PETSc.set_timestep! — Method
PETSc.set_tolerances! — Method
set_tolerances!(ts::AbstractTS; atol, rtol, vatol, vrtol)Set the local truncation error tolerances. A keyword left at nothing keeps the value ts currently has.
Pass vatol or vrtol to give per-component tolerances.
External Links
- PETSc Manual:
TS/TSSetTolerances
PETSc.set_type! — Method
set_type!(ts::AbstractTS, type::Symbol)Set the time-stepping method, for example :bdf, :rk or :arkimex.
External Links
- PETSc Manual:
TS/TSSetType
PETSc.set_user_ctx! — Method
set_user_ctx!(ts::AbstractTS, ctx)Attach ctx to ts, to be handed back as the last argument of every callback that has a method accepting it.
The object is held by ts on the Julia side, so it is kept alive and needs no pinning.
PETSc.setup! — Method
setup!(ts::AbstractTS)Complete the setup of ts. solve! calls this, so it is only needed when the setup must happen at a controlled point.
External Links
- PETSc Manual:
TS/TSSetUp
PETSc.snes — Method
snes(ts::AbstractTS)The nonlinear solver ts steps with. It is owned by ts, so do not destroy it.
Only the implicit methods build one. Asking an explicit method for its SNES creates an unused solver rather than reporting an error.
External Links
- PETSc Manual:
TS/TSGetSNES
PETSc.snes_failures — Method
snes_failures(ts::AbstractTS)Number of failed nonlinear solves.
External Links
- PETSc Manual:
TS/TSGetSNESFailures
PETSc.snes_iterations — Method
snes_iterations(ts::AbstractTS)Total number of nonlinear iterations taken so far, summed over the steps.
External Links
- PETSc Manual:
TS/TSGetSNESIterations
PETSc.solution — Method
solution(ts::AbstractTS)The solution vector held by ts. It is owned by ts, so do not destroy it.
External Links
- PETSc Manual:
TS/TSGetSolution
PETSc.solve! — Method
solve!(u::AbstractPetscVec, ts::AbstractTS)
solve!(ts::AbstractTS)Integrate ts, starting from u and returning it. The second form uses the solution vector already set on ts and returns ts.
u is registered with TSSetSolution before the solve. Passing it to TSSolve alone leaves the stepper reading an uninitialized solution vector, which the implicit methods see as an initial condition of zero.
Options passed to the TS constructor are applied here, once the DM and the callbacks are attached.
External Links
- PETSc Manual:
TS/TSSolve
- PETSc Manual:
TS/TSSetSolution
PETSc.solve_time — Method
solve_time(ts::AbstractTS)The time reached by the last solve!.
This is the time the integration actually stopped at, which is not the time asked for by set_max_time! unless the final step was made to land on it; see set_exact_final_time!.
External Links
- PETSc Manual:
TS/TSGetSolveTime
PETSc.step! — Method
step!(ts::AbstractTS)Take a single step. Unlike solve! this does not apply the options given to the constructor, and it ignores the time set by set_max_time!.
External Links
- PETSc Manual:
TS/TSStep
PETSc.step_number — Method
step_number(ts::AbstractTS)The number of steps taken so far.
External Links
- PETSc Manual:
TS/TSGetStepNumber
PETSc.step_rejections — Method
step_rejections(ts::AbstractTS)Number of steps the adaptivity controller has rejected.
External Links
- PETSc Manual:
TS/TSGetStepRejections
PETSc.timestep — Method
PETSc.tolerances — Method
tolerances(ts::AbstractTS)Local truncation error tolerances, as (; atol, rtol, vatol, vrtol).
vatol and vrtol hold per-component tolerances and carry a null pointer when only the scalar tolerances are set. Both are owned by ts.
External Links
- PETSc Manual:
TS/TSGetTolerances
PETSc.type — Function
type(ts::AbstractTS)The time-stepping method currently set on ts, as a Symbol, or nothing when none has been set yet.
PETSc reports an unset type as a null string, which the generated TSGetType cannot convert. Asking a freshly created stepper for its type is reasonable, so it is answered with nothing here.
External Links
- PETSc Manual:
TS/TSGetType
PETSc.user_ctx — Method
user_ctx(ts::AbstractTS)Whatever was stored with set_user_ctx!, or nothing.