Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sketch out driver interfaces (WIP) #1068

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
82 changes: 82 additions & 0 deletions examples/minimal_driver.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Import necessary packages
import ClimaComms
import ClimaCore as CC
import ClimaAtmos as CA
import ClimaLand as CL

# Choose device to run on (CPU or GPU)
context = ClimaComms.context()
device = ClimaComms.device(context)

# Choose float type
FT = Float64

# Parse optional config file - overwrites default values
!isnothing(config_file) && parse_inputs(config_file)

# Set up exchange space - requires component models to regrid to/from this space
# Can reach out to Alistair Adcroft at GFDL for guidance (worked on MIT GCM)
space = create_sphere(FT, context) # including topography and land/sea mask

# Set up timestepping information
tspan = (; t_start = Float64(0), t_end = Float64(60 * 60 * 24)) # simulation length 1 day
dt_cpl = (400)

# Set up output directory
output_dir = "output"

# Set up parameters - need to be unified for calibration
# Default parameters, can be overwritten by TOML files or user inputs
# Tapio: allow TOML files for both physical and simulation parameters (e.g. tspan, dt_cpl)
parameters = init_params()

# Initialize component model simulations - maybe from restart
# Simulation instead of model allows each component to step/solve independently
# Optional config, TOML files passed here
atmos = CA.atmos_init(FT, space, output_dir)
land = CL.LandSimulation(FT, space, output_dir) # or stub_init()
ocean = ocean_init(FT, space, output_dir) # or stub_init()
ice = ice_init(FT, space, output_dir) # or stub_init()

# Initialize coupled simulation
coupled_simulation = CoupledSimulation(atmos, ocean, land, seaice, tspan, dt_cpl)

# Run very short/coarse simulation to display which input files are required
check_artifacts(coupled_simulation)

# Run simulation
solve_coupler!(coupled_simulation)

# Postprocessing (optional - will bring in many deps) - maybe in extension
# Dispatch on config ID
postprocess(coupled_simulation)



# Q: How can we communicate to user which input files are needed?
# One option: run short, coarse simulation first to display which files are requires

"""
CoupledSimulation
- models (atmos, ocean, land, seaice)
- clock (tspan, dt_cpl, time/iteration)
- space (exchange space)
- land/sea mask (think about resolution/space)
- callback
- diagnostics/output writers
- turbulent flux partition
- coupler exchange fields
- logging
- config ID
- job ID
- initialized/running flags
- preprocessing
"""
# Similar simulation for components

# Optional user inputs:
# - callbacks
# - logging (verbose mode?) - option for MPI pids to write outputs to files
# - config ID, job ID - useful for running ensembles and distinguishing runs
# - initialized/running flags - e.g. to keep track of consistency between state/cache when starting and stopping
# - preprocessing (gapfilling, etc.) - could include restarts
102 changes: 102 additions & 0 deletions examples/realistic_driver.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Import necessary packages
import ClimaComms
import ClimaCore as CC
import ClimaAtmos as CA
import ClimaLand as CL

# Include adapters for component models
## helpers for component models
include("../experiments/ClimaEarth/components/atmosphere/climaatmos.jl")
include("../experiments/ClimaEarth/components/land/climaland_bucket.jl")
include("../experiments/ClimaEarth/components/ocean/slab_ocean.jl")
include("../experiments/ClimaEarth/components/ocean/prescr_seaice.jl")

# Choose device to run on (CPU or GPU)
context = ClimaComms.context()
device = ClimaComms.device(context)

# Choose float type
FT = Float64

# Set up simulation space
space = create_sphere(FT, context)

# Set up timestepping information
tspan = (; t_start = Float64(0), t_end = Float64(60 * 60 * 24)) # simulation length 1 day
dt_cpl = (400)

# Initialize component models
atmos = atmos_init()
land = land_init() # or stub_init()
ocean = ocean_init() # or stub_init()
ice = ice_init() # or stub_init()

# Initialize coupled simulation
coupled_simulation = CoupledSimulation(atmos, ocean, land, seaice, tspan, dt_cpl)

# Run simulation
solve_coupler!(coupled_simulation)

# Postprocessing
postprocess(coupled_simulation)


"""
create_sphere(FT, context)

Create a spherical shell space. Use a default radius, depth, and number
of horizontal elements. For now we just create a spherical shell with depth,
representing the subsurface, and take the top of the shell to be the surface.
We should figure out how to construct subsurface, surface, and above-surface
spaces if we want all component models to inherit all 3 from the coupler.
"""
function create_sphere(FT, context)
# # TODO how can we specify number of atmos vert elements and number of land vert elements separately?
nelements = (16, 15) # 16 horizontal elements; 15 vertical elements
# h_elem = 4 # number of horizontal elements

radius = FT(6378.1e3)
depth = FT(50)

vertdomain = ClimaCore.Domains.IntervalDomain(
ClimaCore.Geometry.ZPoint(FT(-depth)),
ClimaCore.Geometry.ZPoint(FT(0));
boundary_names = (:bottom, :top),
)
if dz_tuple isa Nothing
vertmesh =
ClimaCore.Meshes.IntervalMesh(vertdomain; nelems = nelements[2])
else
vertmesh = ClimaCore.Meshes.IntervalMesh(
vertdomain,
ClimaCore.Meshes.GeneralizedExponentialStretching{FT}(
dz_tuple[1],
dz_tuple[2],
);
nelems = nelements[2],
reverse_mode = true,
)
end
device = ClimaComms.device(context)
if pkgversion(ClimaCore) >= v"0.14.10"
vert_center_space =
ClimaCore.Spaces.CenterFiniteDifferenceSpace(device, vertmesh)
else
vert_center_space =
ClimaCore.Spaces.CenterFiniteDifferenceSpace(vertmesh)
end

horzdomain = ClimaCore.Domains.SphereDomain(radius)
horzmesh = ClimaCore.Meshes.EquiangularCubedSphere(horzdomain, nelements[1])
horztopology = ClimaCore.Topologies.Topology2D(comms_ctx, horzmesh)
quad = ClimaCore.Spaces.Quadratures.GLL{npolynomial + 1}()
horzspace = ClimaCore.Spaces.SpectralElementSpace2D(horztopology, quad)

subsurface_space = ClimaCore.Spaces.ExtrudedFiniteDifferenceSpace(
horzspace,
vert_center_space,
)
boundary_space = CC.Spaces.horizontal_space(face_space)
space = (; surface = boundary_space, subsurface = subsurface_space)
return boundary_space
end