Skip to content

Conversation

@bgroenks96
Copy link
Collaborator

Resolves #4797

@bgroenks96 bgroenks96 requested a review from glwagner September 19, 2025 08:37
@bgroenks96
Copy link
Collaborator Author

@glwagner Are you OK with moving the model interface methods out of the Models submodule up to the top-level module?

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.

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))

@glwagner
Copy link
Member

I think there needs to be some thought / intentionality about what functions belong to a "generic model" interface, versus what functions are only associated with NonhydrostaticModel / HydrostaticFreeSurfaceModel. Here are some examples

  • models should not need to have "time steppers". The intrinsic thing is a time stepping rule, ie time_step!(model, dt). It doesn't matter if there is a property model.timestepper.
  • models should not need to have grids or architectures. Its not well defined in many cases. A coupled model does not have a single grid.

To develop the scope of models I would consider the following cases:

  • a fluids model, like NonhydrostaticModel (which used to be the only model)
  • a coupled model, like an EarthSystemModel with a mixture of prescribed and prognostic componets
  • a 0D model with a very simple evolution rule, ie something like next = prev + dt * exp(next) (exponential growth). This model has neither grid nor architecture, only time_step!(model, dt).

The big danger is that we go in the opposite direction that we have been generally striving for --- a simple, useful interface which is disentangled from the "finite volume" (grids, fields) part of the code.

@glwagner
Copy link
Member

@glwagner Are you OK with moving the model interface methods out of the Models submodule up to the top-level module?

Does this move us in the direction of being able to disentangle finite volume stuff (grids, fields, etc) from model implementation? What is your vision? Usually moving things to top-level acts to further entangle...

@@ -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?

Comment on lines +35 to +38
function initialization_update_state!(model::AbstractModel; kw...)
initialize!(model)
update_state!(model; kw...) # fallback
end
Copy link
Member

Choose a reason for hiding this comment

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

I think we will be able to get rid of initialization_update_state! soon FYI. It was introduced to support work with Reactant but I do not think it is needed anymore.

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

Choose a reason for hiding this comment

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

I'm wary of baking in the notion of a time stepper

Copy link
Member

Choose a reason for hiding this comment

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

True. Is this used anywhere?

@glwagner
Copy link
Member

I said this in a chat so I'll say it here so we can all discuss --- I think that the "definition" of a model belongs to the Simulations module. This makes sense because the requirements of a model are determined by Simulation and its functions. For example, Simulation requires a model to have a function time_step!(model, dt).

I am not sure about all of the other functions. We have things like initialize!, reset!. Maybe we need finalize!. We definitely don't want any physics assumptions baked in, it total_velocities is bad. I am not even sure that we want to enshrine the notion of "prognostic fields", but that is more debatable. I'd be ok with accepting fields as a requirement.

At the top-level, I think we want to move towards an import order that looks somethin like

  1. Grids, Fields, Solvers, FieldTimeSeries, utils
  2. Simulation, OutputWriters
  3. Models

Then someday we may pull out 1 & 2 into another package. We could also have 3 packages (but that's probably overkill. Then, the "models" will basically be the only part of Oceananigans that remains (which makes sense --- ocean specific stuff).

@bgroenks96 bgroenks96 self-assigned this Sep 19, 2025
@bgroenks96 bgroenks96 added cleanup 🧹 Paying off technical debt abstractions 🎨 Whatever that means documentation 📜 The sacred scrolls labels Sep 19, 2025
bgroenks96 and others added 5 commits September 22, 2025 09:04
Co-authored-by: Navid C. Constantinou <[email protected]>
Co-authored-by: Gregory L. Wagner <[email protected]>
Co-authored-by: Navid C. Constantinou <[email protected]>
Co-authored-by: Navid C. Constantinou <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

abstractions 🎨 Whatever that means cleanup 🧹 Paying off technical debt documentation 📜 The sacred scrolls

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve documentation of AbstractModel interface

6 participants