Skip to content

Solving unsteady problems

The main entry point of the package is solve_unsteady:

julia
state, outputs = solve_unsteady(;
    setup,
    start = (; u),
    tlims = (0.0, 1.0),
    params = (; viscosity = 1e-3),
)

It steps the initial start state (a named tuple of fields, e.g. (; u) or (; u, temp)) through the time interval tlims and returns the final state and the processor outputs.

Forces and parameters

The right-hand side is a function force!(force, state, t; setup, cache, params...) passed as the force! keyword. The built-in forces are navierstokes! (convection and diffusion, the default) and boussinesq! (adds a coupled temperature equation). Physical parameters are passed in the params named tuple and forwarded to force! as keyword arguments, e.g. params = (; viscosity = 1e-3) for navierstokes!. Custom forces follow the same signature; see examples/Kolmogorov2D.jl for a custom body force and examples/ChannelFlow.jl for adding an eddy-viscosity closure model.

Time step and method

By default, the time step is chosen adaptively from a CFL condition on the convective and diffusive limits (tune with the cfl keyword); pass a fixed Δt to disable this. The time integration method defaults to the low-storage third-order Runge-Kutta method LMWray3; any explicit Runge-Kutta tableau from RKMethods can be passed via the method keyword. The theory is discussed in Spatial and temporal discretization.

For finer control than solve_unsteady, the stepping primitives create_stepper and timestep/timestep! can be called directly, e.g. to write a custom (differentiable) simulation loop.

API

IncompressibleNavierStokes.boussinesq! Method
julia
boussinesq!(
    force,
    state,
    t;
    setup,
    cache,
    viscosity,
    conductivity,
    gdir,
    gravity,
    dodissipation
)

Boussinesq forcing (Navier-Stokes + gravity for u, convection-diffusion for temp).

source
IncompressibleNavierStokes.boussinesq Method
julia
boussinesq(
    state,
    t;
    setup,
    viscosity,
    conductivity,
    gdir,
    gravity,
    dodissipation
)

Boussinesq forcing (Navier-Stokes + gravity for u, convection-diffusion for temp).

source
IncompressibleNavierStokes.get_state Method
julia
get_state(
    stepper
) -> Union{NamedTuple, DataStructures.SortedMultiDict}

Get state (; u, temp, t, n) from stepper.

source
IncompressibleNavierStokes.navierstokes! Method
julia
navierstokes!(force, state, t; setup, cache, viscosity)

Navier-Stokes momentum forcing (convection + diffusion).

source
IncompressibleNavierStokes.navierstokes Method
julia
navierstokes(state, t; setup, viscosity)

Navier-Stokes momentum forcing (convection + diffusion).

source
IncompressibleNavierStokes.solve_unsteady Method
julia
solve_unsteady(
;
    setup,
    tlims,
    start,
    force!,
    docopy,
    method,
    psolver,
    Δt,
    Δt_min,
    cfl,
    n_adapt_Δt,
    processors,
    params,
    ode_cache,
    force_cache
)

Solve unsteady problem using method.

The initial start state is a named tuple of fields, e.g. (; u) or (; u, temp). The right-hand side force! is called as force!(force, state, t; setup, cache, params...), where params is a named tuple of parameters passed as keyword arguments (e.g. params = (; viscosity) for the default navierstokes!, or (; viscosity, conductivity, gdir, gravity, dodissipation) for boussinesq!).

If Δt is a real number, it is rounded such that (t_end - t_start) / Δt is an integer. If Δt = nothing, the time step is chosen every n_adapt_Δt iteration with CFL-number cfl. If Δt_min is given, the adaptive time step never goes below it.

The processors are called after every time step.

Note that the state observable passed to the processor.initialize function contains fields living on the device, and you may have to move them back to the host using Array in the processor.

Return (; state..., t), outputs, where outputs is a named tuple with the outputs of processors with the same field names.

source

Time stepping

IncompressibleNavierStokes.AbstractODEMethod Type
julia
abstract type AbstractODEMethod{T}

Abstract ODE method.

Fields

source
IncompressibleNavierStokes.AbstractRungeKuttaMethod Type
julia
abstract type AbstractRungeKuttaMethod{T} <: IncompressibleNavierStokes.AbstractODEMethod{T}

Abstract Runge Kutta method.

Fields

source
IncompressibleNavierStokes.ExplicitRungeKuttaMethod Type
julia
struct ExplicitRungeKuttaMethod{T} <: IncompressibleNavierStokes.AbstractRungeKuttaMethod{T}

Explicit Runge Kutta method. See Sanderse [6].

Consider the velocity field u0 at a certain time t0. We will now perform one time step to t=t0+Δt. For explicit Runge-Kutta methods, this time step is divided into s sub-steps ti=t0+Δti with increment Δti=ciΔt. The final substep performs the full time step Δts=Δt such that ts=t.

For i=1,,s, the intermediate velocity ui and pressure pi are computed as follows:

ki=F(ui1,ti1)yG(ti1)vi=u0+Δtj=1iaijkjLpi=WM1cij=1iaijkj+WyM(ti)yM(t0)Δti=W(Mvi+yM(ti))(Mu0+yM(t0))Δtin=WMvi+yM(ti)Δtinui=viΔtiGpi,

where (aij)ij are the Butcher tableau coefficients of the RK-method, with the convention ci=j=1iaij.

Finally, we return us. If u0=u(t0), we get the accuracy us=u(t)+O(Δtr+1), where r is the order of the RK-method. If we perform n RK time steps instead of one, starting at exact initial conditions u0=u(0), then un=u(tn)+O(Δtr) for all n{1,,N}. Note that for a given u, the corresponding pressure p can be calculated to the same accuracy as u by doing an additional pressure projection after each outer time step Δt (if we know dyMdt(t)), or to first order accuracy by simply returning ps.

Note that each of the sub-step velocities ui is divergence free, after projecting the tentative velocities vi. This is ensured due to the judiciously chosen replacement of dyMdt(ti) with (yM(ti)yM(t0))/Δti. The space-discrete divergence-freeness is thus perfectly preserved, even though the time discretization introduces other errors.

Fields

  • A

  • b

  • c

  • r

  • p_add_solve

source
IncompressibleNavierStokes.LMWray3 Type
julia
struct LMWray3{T} <: IncompressibleNavierStokes.AbstractRungeKuttaMethod{T}

Low memory Wray 3rd order scheme [8]. Uses 3 vector fields and one scalar field.

Fields

source
IncompressibleNavierStokes.runge_kutta_method Method
julia
runge_kutta_method(
    A,
    b,
    c,
    r;
    T,
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod

Get Runge Kutta method. The function checks whether the method is explicit.

p_add_solve: whether to add a pressure solve step to the method.

For implicit RK methods: newton_type, maxiter, abstol, reltol.

source
IncompressibleNavierStokes.create_stepper Function
julia
create_stepper(method; setup, psolver, state, t, n = 0)

Create time stepper.

source
IncompressibleNavierStokes.timestep Function
julia
timestep(method, force, stepper, Δt; params = nothing)

Perform one time step.

Non-mutating/allocating/out-of-place version.

See also timestep!.

source
IncompressibleNavierStokes.timestep! Function
julia
timestep!(method, force!, stepper, Δt; params = nothing, ode_cache, force_cache)

Perform one time step.

Mutating/non-allocating/in-place version.

See also timestep.

source
IncompressibleNavierStokes.get_cache Function
julia
get_cache(method, state, setup)

Get time stepper cache for the given ODE method.

The method get_cache(force!, setup) returns the cache for a right-hand-side function force! instead.

source

Runge-Kutta methods

IncompressibleNavierStokes.RKMethods Module

Set up Butcher arrays A, b, and c, as well as and SSP coefficient r. For families of methods, optional input s is the number of stages.

Original (MATLAB) by David Ketcheson, extended by Benjamin Sanderse.

Exports

source
IncompressibleNavierStokes.RKMethods.DOPRI6 Method
julia
DOPRI6(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

Dormand-Prince pair.

source
IncompressibleNavierStokes.RKMethods.FE11 Method
julia
FE11(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

FE11 (Forward Euler).

source
IncompressibleNavierStokes.RKMethods.HEM3 Method
julia
HEM3(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

Brasey and Hairer.

source
IncompressibleNavierStokes.RKMethods.HEM3BS Method
julia
HEM3BS(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

HEM3BS.

source
IncompressibleNavierStokes.RKMethods.HEM5 Method
julia
HEM5(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

Brasey and Hairer, 5 stage, 4th order.

source
IncompressibleNavierStokes.RKMethods.Heun33 Method
julia
Heun33(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

Heun33.

source
IncompressibleNavierStokes.RKMethods.MTE22 Method
julia
MTE22(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

Minimal truncation error 22 method (Heun).

source
IncompressibleNavierStokes.RKMethods.Mid22 Method
julia
Mid22(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

Midpoint 22 method.

source
IncompressibleNavierStokes.RKMethods.NSSP21 Method
julia
NSSP21(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

NSSP21.

source
IncompressibleNavierStokes.RKMethods.NSSP32 Method
julia
NSSP32(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

NSSP32.

source
IncompressibleNavierStokes.RKMethods.NSSP33 Method
julia
NSSP33(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

NSSP33.

source
IncompressibleNavierStokes.RKMethods.NSSP53 Method
julia
NSSP53(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

NSSP53.

source
IncompressibleNavierStokes.RKMethods.RK33C2 Method
julia
RK33C2(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

RK3 satisfying C(2) for i=3.

source
IncompressibleNavierStokes.RKMethods.RK33P2 Method
julia
RK33P2(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

RK3 satisfying the second order condition for the pressure.

source
IncompressibleNavierStokes.RKMethods.RK44 Method
julia
RK44(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

Classical fourth order.

source
IncompressibleNavierStokes.RKMethods.RK44C2 Method
julia
RK44C2(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

RK4 satisfying C(2) for i=3.

source
IncompressibleNavierStokes.RKMethods.RK44C23 Method
julia
RK44C23(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

RK4 satisfying C(2) for i=3 and c2=c3.

source
IncompressibleNavierStokes.RKMethods.RK44P2 Method
julia
RK44P2(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

RK4 satisfying the second order condition for the pressure (but not third order).

source
IncompressibleNavierStokes.RKMethods.RK56 Method
julia
RK56(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

RK56.

source
IncompressibleNavierStokes.RKMethods.SSP104 Method
julia
SSP104(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

SSP104.

source
IncompressibleNavierStokes.RKMethods.SSP22 Method
julia
SSP22(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

SSP22.

source
IncompressibleNavierStokes.RKMethods.SSP33 Method
julia
SSP33(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

SSP33.

source
IncompressibleNavierStokes.RKMethods.SSP42 Method
julia
SSP42(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

SSP42.

source
IncompressibleNavierStokes.RKMethods.SSP43 Method
julia
SSP43(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

SSP43.

source
IncompressibleNavierStokes.RKMethods.Wray3 Method
julia
Wray3(
;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod{Float64}

Wray's RK3.

source
IncompressibleNavierStokes.RKMethods.rSSPs2 Function
julia
rSSPs2(
;
    ...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod
rSSPs2(
    s;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod

Rational (optimal, low-storage) s-stage 2nd order SSP.

source
IncompressibleNavierStokes.RKMethods.rSSPs3 Function
julia
rSSPs3(
;
    ...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod
rSSPs3(
    s;
    kwargs...
) -> IncompressibleNavierStokes.ExplicitRungeKuttaMethod

Rational (optimal, low-storage) s^2-stage 3rd order SSP.

source