SpeedyWeather / SpeedyWeather.jl

Play atmospheric modelling like it's LEGO.
https://speedyweather.github.io/SpeedyWeather.jl/dev
MIT License
439 stars 29 forks source link

Away from monolithic `run_speedy()`? #320

Closed milankl closed 1 year ago

milankl commented 1 year ago

At the moment we have a monolithic interface

run_speedy(param1,param2,...)

which makes it difficult to pass on a struct in which array sizes depend on, e.g. the size of the grid. For example

Base.@kwdef struct MyParameterization{T<:AbstractFloat} <: ParameterizationClass{T}
    parameter1::Float64 = 1    # user should be able to change those at initialisation 
    parameter2::Float64 = 2

    n::Int = 0                 # size of arrays that may not be known at initialisation
    some_constant_array::Vector{T} = zeros(T,n)
end

because MyParameterization.some_constant_array is of length n which in general is only known after run_speedy is called.

Alternatively, we could go the Oceananigans approach to (1) first define an object geometry that contains that information before (2) creating a model which is then (3) run

geometry = Geometry(OctahedralGaussianGrid,trunc=31,nlev=8,dealiasing=2)
model = PrimitiveDryCoreModel(geometry;param1,param2,param3,...)
run!(model)
milankl commented 1 year ago

In the above example we could then do

using SpeedyWeather

# define your own parameterization, part 1.1: struct
Base.@kwdef struct MyParameterization{T<:AbstractFloat} <: ParameterizationClass{T}
    parameter1::Float64 = 1    # user should be able to change those at initialisation 
    parameter2::Float64 = 2

    n::Int = 0                 # size of arrays that may not be known at initialisation
    some_constant_array::Vector{T} = zeros(T,n)
end

# part 1.2: method to use the information from Geometry
MyParameterization(geometry::Geometry;kwargs...) = MyParameterization(nlev=geometry.nlev,kwargs...)

# part 2: define initialisor
initialize!(scheme::MyParameterization,model::Model) = ...

# part 3: define algorithm
convection!(column::ColumnVariables,scheme::MyParameterization,model::Model) = ...

# now initiliase geometry, parameterization, model and run
geometry = Geometry(...)
myparam = MyParameterization(geometry,a=1)
model = PrimitiveDryCoreModel(geometry,convection=myparam)
run!(model)

@glwagner I agree that would solve a lot of issues, and makes model components very self-contained and therefore easily extendible @maximilian-gelbrecht we talked a lot about structure before, what do you think ☝🏼

glwagner commented 1 year ago

This talk might help provide some background:

https://docs.google.com/presentation/d/1eOZm1TOWQFrRSrNJ7KYmsJR_x1yXQCgr62txRAY3JSE/edit?usp=sharing

There's also some discussion about user interface design for codes like SpeedyWeather in the Trixi announcement:

https://discourse.julialang.org/t/ann-trixi-jl-a-tree-based-numerical-simulation-framework-for-hyperbolic-pdes/45886/7

I'd be curious to see other discussion about user API for CFD / geophysical simulation out there on the internets