Time integration

FluxCore distinguishes physical time from pseudo-time. Physical time advances the simulated system. Pseudo-time is the nonlinear work used to converge a steady state or the implicit equations inside one physical step.

Pseudo-time step methods

class gradientdynamics.fluxcore.FixedPseudoTimeStep(*, value: float)

Use a fixed pseudo-time increment in seconds.

value: float
class gradientdynamics.fluxcore.CflPseudoTimeStep(*, cfl: float = 50.0, local: bool = True)

Choose pseudo-time increments from a requested Courant number.

cfl: float

Requested pseudo-time Courant number.

local: bool

Permit cell-local pseudo-time scales for steady convergence.

class gradientdynamics.fluxcore.AdaptiveCfl(*, initial: float = 1.0, target: float = 100.0, ramp_steps: int = 500, growth_factor: float = 1.25, retreat_factor: float = 0.5, minimum: float = 0.1, maximum: float | None = None, recovery_window: int = 8)

Residual-aware pseudo-time CFL progression.

initial: float

CFL used at the beginning of the solve or after a restart that lacks history.

target: float

Production CFL earned after stable nonlinear progress.

growth_factor: float

Largest allowed CFL increase over one successful control window.

retreat_factor: float

CFL reduction applied when progress or stability checks fail.

Steady time controls

class gradientdynamics.fluxcore.SteadyTimeControls(*, max_pseudo_steps: int = 2000, minimum_pseudo_steps: int = 100, pseudo_time_step: FixedPseudoTimeStep | CflPseudoTimeStep | AdaptiveCfl = AdaptiveCfl(), convergence: ConvergenceCriteria | None = None, output_schedule: OutputSchedule | None = None)

Pseudo-time advancement to a steady converged solution.

max_pseudo_steps: int

Maximum nonlinear pseudo-iterations.

minimum_pseudo_steps: int

Minimum iterations completed before convergence can terminate the run.

pseudo_time_step: FixedPseudoTimeStep | CflPseudoTimeStep | AdaptiveCfl

Pseudo-time step selection and progression method.

Inner pseudo-time controls

class gradientdynamics.fluxcore.PseudoTimeControls(*, maximum_steps: int = 100, minimum_steps: int = 3, residual_drop: float = 2.0, absolute_residual: float | None = None, step_method: FixedPseudoTimeStep | CflPseudoTimeStep | AdaptiveCfl = CflPseudoTimeStep(), chunk_size: int = 25, early_stop: bool = True, output_every: int | None = None)

Nonlinear convergence policy inside each physical-time step.

maximum_steps: int

Maximum pseudo-iterations permitted for one physical step.

minimum_steps: int

Minimum pseudo-iterations before early stopping is evaluated.

residual_drop: float

Required orders of residual reduction within the physical step.

absolute_residual: float | None

Optional absolute inner-convergence threshold.

chunk_size: int

Number of pseudo-iterations executed between convergence, cancellation and live-output checks.

output_every: int | None

Optional inner-history cadence in pseudo-iterations. Field and checkpoint cadences are configured with OutputSchedule.

Physical time controls

class gradientdynamics.fluxcore.PhysicalTimeControls(*, time_step: float, steps: int | None = None, end_time: float | None = None, order: int = 2, startup_steps: int = 1, predictor: str = 'extrapolate', inner: PseudoTimeControls = PseudoTimeControls(), statistics: StatisticsOutput | None = None, output_schedule: OutputSchedule | None = None)

Implicit physical-time advancement for URANS, DES and DDES simulations.

time_step: float

Physical time increment in seconds.

steps: int | None

Number of physical steps. Supply this or end_time.

end_time: float | None

Final simulated time in seconds. Supply this or steps.

order: Literal[1, 2]

Requested physical-time accuracy order.

startup_steps: int

Initial steps advanced with the startup time discretisation before the requested higher-order history is available.

predictor: Literal['previous', 'extrapolate']

Initial field prediction for each new physical step.

inner: PseudoTimeControls

Pseudo-time convergence policy applied inside every physical step.

Physical and pseudo-time example

from gradientdynamics.fluxcore import (
    AdaptiveCfl,
    OutputSchedule,
    PhysicalTimeControls,
    PseudoTimeControls,
)

time_controls = PhysicalTimeControls(
    time_step=2.5e-5,
    steps=12_000,
    order=2,
    startup_steps=1,
    predictor="extrapolate",
    inner=PseudoTimeControls(
        maximum_steps=80,
        minimum_steps=4,
        residual_drop=2.5,
        step_method=AdaptiveCfl(
            initial=1.0,
            target=75.0,
            ramp_steps=40,
        ),
        chunk_size=10,
        early_stop=True,
        output_every=5,
    ),
    output_schedule=OutputSchedule(
        history_every_pseudo_steps=5,
        fields_every_physical_steps=20,
        checkpoint_every_physical_steps=100,
    ),
)