Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ext/OceananigansReactantExt/Models.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module Models

import Oceananigans

import Oceananigans.Models: initialization_update_state!
import Oceananigans: initialization_update_state!
import Oceananigans.Models.HydrostaticFreeSurfaceModels.SplitExplicitFreeSurfaces: maybe_extend_halos, FixedSubstepNumber
import Oceananigans: initialize!

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using OrderedCollections: OrderedDict

using Oceananigans: AbstractModel, initialization_update_state!
using Oceananigans.DistributedComputations
using Oceananigans.Architectures: AbstractArchitecture
using Oceananigans.Advection: AbstractAdvectionScheme, Centered, VectorInvariant, adapt_advection_order
Expand All @@ -10,14 +11,13 @@ using Oceananigans.Fields: Field, CenterField, tracernames, VelocityFields, Trac
using Oceananigans.Forcings: model_forcing
using Oceananigans.Grids: AbstractCurvilinearGrid, AbstractHorizontallyCurvilinearGrid, architecture, halo_size, MutableVerticalDiscretization
using Oceananigans.ImmersedBoundaries: ImmersedBoundaryGrid
using Oceananigans.Models: AbstractModel, validate_model_halo, validate_tracer_advection, extract_boundary_conditions, initialization_update_state!
using Oceananigans.Models: validate_model_halo, validate_tracer_advection, extract_boundary_conditions
using Oceananigans.TimeSteppers: Clock, TimeStepper, update_state!, AbstractLagrangianParticles, SplitRungeKutta3TimeStepper
using Oceananigans.TurbulenceClosures: validate_closure, with_tracers, build_diffusivity_fields, add_closure_specific_boundary_conditions
using Oceananigans.TurbulenceClosures: time_discretization, implicit_diffusion_solver
using Oceananigans.Utils: tupleit

import Oceananigans: initialize!
import Oceananigans.Models: total_velocities, timestepper
import Oceananigans: initialize!, total_velocities, timestepper

PressureField(grid) = (; pHY′ = CenterField(grid))

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using Oceananigans: total_velocities
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am wary of this. It's a hack to begin with and this sort of cements it. I think we want to go the other way...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean the method in general, right? Or just the fact that it's at the top-level?

using Oceananigans.Utils: instantiate, KernelParameters
using Oceananigans.Models: total_velocities
using Oceananigans.Fields: interpolator, FractionalIndices

#####
Expand Down
33 changes: 13 additions & 20 deletions src/Models/Models.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export
BoundaryConditionOperation, ForcingOperation,
seawater_density

using DocStringExtensions

using Oceananigans: AbstractModel, fields, prognostic_fields
using Oceananigans.AbstractOperations: AbstractOperation
using Oceananigans.Advection: AbstractAdvectionScheme, Centered, VectorInvariant
Expand All @@ -19,31 +21,22 @@ using Oceananigans.OutputReaders: update_field_time_series!, extract_field_time_
using Oceananigans.TimeSteppers: AbstractTimeStepper, Clock, update_state!
using Oceananigans.Utils: Time

import Oceananigans: initialize!
import Oceananigans: initialize!, timestepper, iteration
import Oceananigans.Architectures: architecture
import Oceananigans.Solvers: iteration
import Oceananigans.Simulations: timestepper
import Oceananigans.TimeSteppers: reset!, set_clock!

# A prototype interface for AbstractModel.
#
# TODO: decide if we like this.
#
# We assume that model has some properties, eg:
# - model.clock::Clock
# - model.architecture.
# - model.timestepper with timestepper.G⁻ and timestepper.Gⁿ :spiral_eyes:

iteration(model::AbstractModel) = model.clock.iteration
Base.time(model::AbstractModel) = model.clock.time
Base.eltype(model::AbstractModel) = eltype(model.grid)
"""
$SIGNATURES

Returns the device architecture defined by the underlying model `grid`.
"""
architecture(model::AbstractModel) = model.grid.architecture
initialize!(model::AbstractModel) = nothing
total_velocities(model::AbstractModel) = nothing
timestepper(model::AbstractModel) = model.timestepper
initialization_update_state!(model::AbstractModel; kw...) = update_state!(model; kw...) # fallback

# Fallback for any abstract model that does not contain `FieldTimeSeries`es
"""
$SIGNATURES

Updates all `FieldTimeSeries` fields defined on the given `model. The default implementation assumes that the `model` that does not contain any `FieldTimeSeries` and returns `nothing`.
"""
update_model_field_time_series!(model::AbstractModel, clock::Clock) = nothing

#####
Expand Down
2 changes: 1 addition & 1 deletion src/Models/NonhydrostaticModels/nonhydrostatic_model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ using Oceananigans.TurbulenceClosures.TKEBasedVerticalDiffusivities: FlavorOfCAT
using Oceananigans.Utils: tupleit
using Oceananigans.Grids: topology

import Oceananigans: total_velocities, timestepper
import Oceananigans.Architectures: architecture
import Oceananigans.Models: total_velocities, timestepper

const ParticlesOrNothing = Union{Nothing, AbstractLagrangianParticles}
const AbstractBGCOrNothing = Union{Nothing, AbstractBiogeochemistry}
Expand Down
2 changes: 1 addition & 1 deletion src/Models/ShallowWaterModels/shallow_water_model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ using Oceananigans.TimeSteppers: Clock, TimeStepper, update_state!
using Oceananigans.TurbulenceClosures: with_tracers, build_diffusivity_fields
using Oceananigans.Utils: tupleit

import Oceananigans: timestepper
import Oceananigans.Architectures: architecture
import Oceananigans.Simulations: timestepper

const RectilinearGrids = Union{RectilinearGrid, ImmersedBoundaryGrid{<:Any, <:Any, <:Any, <:Any, <:RectilinearGrid}}

Expand Down
61 changes: 60 additions & 1 deletion src/Oceananigans.jl
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ export
ConservativeFormulation, VectorInvariantFormulation,
PressureField, fields, ZCoordinate, ZStarCoordinate,

# Model interface
iteration, timesteppper,

# Hydrostatic free surface model stuff
VectorInvariant, ExplicitFreeSurface, ImplicitFreeSurface, SplitExplicitFreeSurface,
HydrostaticSphericalCoriolis, PrescribedVelocityFields,
Expand All @@ -92,7 +95,7 @@ export
Clock, TimeStepWizard, conjure_time_step_wizard!, time_step!,

# Simulations
Simulation, run!, Callback, add_callback!, iteration,
Simulation, run!, Callback, add_callback!,
iteration_limit_exceeded, stop_time_exceeded, wall_time_limit_exceeded,

# Diagnostics
Expand Down Expand Up @@ -162,9 +165,65 @@ const defaults = Defaults()
AbstractModel

Abstract supertype for models.

Models are required to have the following fields:
- `model.clock::Clock`
- `model.architecture`
- `model.timestepper` with `timestepper.G⁻` and `timestepper.Gⁿ`
Copy link
Collaborator

@simone-silvestri simone-silvestri Sep 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we want to assume a timestepper: the OceanSeaIceModel does not have a timestepper

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and timestepper.G⁻ is an AB2-specific field

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed in be79014

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about the timestepper method?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need it. It is used only in the reset!(::AbstractModel) method, which should know wether we have a timestepper or not.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, actually it is currently used in the initialize!(simulation) step... But this should call initialize!(model) and not reset!(timestepper(model))

"""
abstract type AbstractModel{TS, A} end

# Method interface for AbstractModel

"""
$SIGNATURES

Returns the current iteration of the `model.clock`.
"""
iteration(model::AbstractModel) = model.clock.iteration

"""
$SIGNATURES

TODO: what does this method do in addition to the constructor?
"""
initialize!(model::AbstractModel) = nothing

"""
$SIGNATURES

TODO
"""
total_velocities(model::AbstractModel) = nothing
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really well defined at the moment. It returns the sum of background + prognostic velocities for the non hydrostatic model and the prognostic velocities in the hydrostatic model

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in be79014

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think "velocities" should be intrinsic to the concept of a model.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, but I didn't want to rock the boat too much.


"""
$SIGNATURES

Returns the `TimeStepper` used by the given `model`.
"""
timestepper(model::AbstractModel) = model.timestepper

"""
$SIGNATURES

Defines initialization routines for the first call to `update_state!` after initialization. Defaults to invoking `update_state!(model; kw...)`.
"""
initialization_update_state!(model::AbstractModel; kw...) = update_state!(model; kw...) # fallback

"""
Base.time(model::AbstractModel)

Returns the current `time` from the given `model.clock`.
"""
Base.time(model::AbstractModel) = model.clock.time

"""
Base.eltype(model::AbstractModel)

Returns the numeric `eltype` of `model.grid` and all associated `Field`s.
"""
Base.eltype(model::AbstractModel) = eltype(model.grid)

"""
AbstractDiagnostic

Expand Down
3 changes: 0 additions & 3 deletions src/Simulations/Simulations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ using OrderedCollections: OrderedDict

import Base: show

# To be extended in the `Models` module
timestepper(model) = nothing

include("callback.jl")
include("simulation.jl")
include("run.jl")
Expand Down
2 changes: 2 additions & 0 deletions src/Solvers/Solvers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ using Oceananigans.Fields
using Oceananigans.Grids: unpack_grid, inactive_cell
using Oceananigans.Grids: XYRegularRG, XZRegularRG, YZRegularRG, XYZRegularRG

import Oceananigans: iteration

"""
ω(M, k)

Expand Down
Loading