Progress messengers

The ProgressMessengers submodule provides composable simulation progress reporters for use as Oceananigans Callbacks. During long-running ocean simulations, it is important to monitor quantities like the current time step, wall-clock time per iteration, maximum velocities, and CFL numbers. This module supplies individual reporter components for each of these quantities, along with pre-built combinations that cover common use cases.

The key design idea is composability: messengers are combined with two operators:

  • + concatenates messages separated by a comma (,), suitable for grouping independent quantities on one line.
  • * concatenates messages with no separator, useful for building prefixed or bracketed expressions.

This lets users build custom progress output from atomic components without writing formatting boilerplate. For example, Iteration() + SimulationTime() + TimeStep() produces output like iter = 5, time = 5 seconds, Δt = 1 second.

The module provides three levels of pre-built messengers with increasing detail:

  • BasicMessenger: percentage, simulation time, time step, wall time, advective CFL, and diffusive CFL.
  • SingleLineMessenger: adds iteration count and wall time to the basic output.
  • TimedMessenger: the most detailed, adding per-step wall time and maximum velocity components.

Example

julia> using Oceananigans, Oceanostics

julia> grid = RectilinearGrid(size=(4, 4, 4), extent=(1, 1, 1));

julia> model = NonhydrostaticModel(grid; closure=SmagorinskyLilly());

julia> simulation = Simulation(model, Δt=1, stop_time=10);

julia> progress = ProgressMessengers.Iteration() + ProgressMessengers.SimulationTime() + ProgressMessengers.AdvectiveCFLNumber();

julia> simulation.callbacks[:progress] = Callback(progress, IterationInterval(5));

julia> typeof(progress) <: Oceanostics.ProgressMessengers.AbstractProgressMessenger
true

Colored numeric output

Numeric values produced by every messenger are rendered in a distinct terminal color (light yellow by default) so they stand out from the surrounding labels and units:

using Oceananigans, Oceanostics, Oceanostics.ProgressMessengers

grid  = RectilinearGrid(size=(4, 4, 4), extent=(1, 1, 1))
model = NonhydrostaticModel(grid; closure=ScalarDiffusivity(ν=1e-6, κ=1e-7))
sim   = Simulation(model; Δt=0.01, stop_iteration=10)

println(BasicMessenger(print=false)(sim))
[000.00%] time = 0 seconds,  Δt = 10 ms,  walltime = 156.818 ms,  advective CFL = 0,  diffusive CFL = 1.6e-07

The color is controlled by a single process-global Crayon and can be changed at runtime with set_number_color!. Any messenger — pre-built or one you write yourself — picks up the new color on the next call:

set_number_color!(crayon"bold magenta")
println(BasicMessenger(print=false)(sim))
[000.00%] time = 0 seconds,  Δt = 10 ms,  walltime = 54.902 μs,  advective CFL = 0,  diffusive CFL = 1.6e-07

24-bit RGB works too:

set_number_color!(Crayon(foreground = (255, 128, 0)))   # orange
println(BasicMessenger(print=false)(sim))
[000.00%] time = 0 seconds,  Δt = 10 ms,  walltime = 50.153 μs,  advective CFL = 0,  diffusive CFL = 1.6e-07

Both the @crayon_str string macro and the Crayon constructor are re-exported from ProgressMessengers, so users don't need to add Crayons.jl as a direct dependency.

To disable colors entirely, assign a no-op crayon:

set_number_color!(Crayon())

Notes:

  • NUMBER_CRAYON is process-global; concurrent simulations in the same Julia process share one color.
  • Output captured to non-TTY destinations (log files, some CI consoles) will contain raw ANSI escape sequences. Use the no-op crayon above to keep logs plain.

Pre-built messengers

TypeDescription
BasicMessengerPercentage progress, simulation time, time step, wall time, advective CFL, diffusive CFL
SingleLineMessengerIteration count, plus everything in BasicMessenger
TimedMessengerPer-step wall time, max velocities, plus everything in SingleLineMessenger

Timing components

TypeDescription
IterationCurrent iteration number
SimulationTimeCurrent simulation time
TimeStepCurrent time step Δt
PercentageProgressProgress as a percentage (by time or iteration)
WalltimeElapsed wall-clock time since the start
StepDurationWall-clock time per time step
BasicTimeMessengerCombines PercentageProgress, SimulationTime, TimeStep, and Walltime
TimeMessengerAdds Iteration to BasicTimeMessenger
StopwatchMessengerAdds StepDuration to TimeMessenger

Velocity components

TypeDescription
MaxUVelocityMaximum absolute u velocity
MaxVVelocityMaximum absolute v velocity
MaxWVelocityMaximum absolute w velocity
MaxVelocitiesAll three components formatted as a vector

Stability components

TypeDescription
AdvectiveCFLNumberAdvective CFL number (aliased as CourantNumber)
DiffusiveCFLNumberDiffusive CFL number (aliased as NormalizedMaxViscosity)
MaxViscosityMaximum viscosity
BasicStabilityMessengerCombines advective and diffusive CFL
StabilityMessengerAdds MaxViscosity to BasicStabilityMessenger