From cfcc193f8de99d488544bc7cb83d667a6f0ae386 Mon Sep 17 00:00:00 2001 From: Ben Mackay Date: Tue, 20 Apr 2021 14:48:42 -0700 Subject: [PATCH 1/8] Docs update, add figures. --- .gitignore | 21 +++++++++++---------- docs/make.jl | 3 +-- docs/src/couplerstate.md | 11 +++++++---- docs/src/images/cplsetup.png | Bin 0 -> 49923 bytes docs/src/images/cpltimestep.png | Bin 0 -> 23036 bytes docs/src/index.md | 4 ++++ docs/src/timestepping.md | 12 ++++++++++++ src/CplModel.jl | 4 ++-- 8 files changed, 37 insertions(+), 18 deletions(-) create mode 100644 docs/src/images/cplsetup.png create mode 100644 docs/src/images/cpltimestep.png diff --git a/.gitignore b/.gitignore index 12e8cd8f7..74a7c3d8a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,11 +8,22 @@ *~ TAGS +# Figs +*.png +*.jpg +*.jpeg +*.svg + +# Movies +*.gif +*.mp4 + # Docs docs/build/ docs/src/generated/ !docs/src/assets/*.png !docs/src/assets/*.svg +!docs/src/images/*.png # Data *.vtk @@ -22,15 +33,5 @@ docs/src/generated/ *.nc *.jld2 -# Figs -*.png -*.jpg -*.jpeg -*.svg - -# Movies -*.gif -*.mp4 - # Julia System Images *.so \ No newline at end of file diff --git a/docs/make.jl b/docs/make.jl index 09a24d77e..57e191caf 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -21,8 +21,7 @@ experiment_pages = [ pages = Any[ "Home" => "index.md", "Examples" => experiment_pages, - "Coupler Object" => "couplerstate.md", - "Coupled Timestepping" => "timestepping.md", + "Coupler Interface" => ["couplerstate.md", "timestepping.md"], ] diff --git a/docs/src/couplerstate.md b/docs/src/couplerstate.md index 7d488770e..c4d7d4d6f 100644 --- a/docs/src/couplerstate.md +++ b/docs/src/couplerstate.md @@ -1,9 +1,12 @@ # Coupler Object -The CouplerMachine defines a type ```CplState``` for a _container_ variable that holds information about the field -values that are being used to couple between components. Components can use a ```put!``` operation to -export a set of field values to a ```CplState``` variable. A ```get``` operation is used to retrieve -a set field values from a ```CplState``` variable. +The CouplerMachine defines a type [`CplState`](@ref) for a _container_ variable +that holds information about the field boundary values that are being used to +couple components. Components can use a [`CouplerMachine.put!`](@ref) operation to +export a set of field values to a `CplState` variable. A [`CouplerMachine.get`](@ref) +operation is used to retrieve a set field values from a `CplState` variable. +During this exchange, the coupler manages ancillary operations such as +regridding, unit conversions, or filtering. ## Coupler Object API diff --git a/docs/src/images/cplsetup.png b/docs/src/images/cplsetup.png new file mode 100644 index 0000000000000000000000000000000000000000..701b4d1eecf73655cb2b31cd9f9c600d04b752fd GIT binary patch literal 49923 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 LeYFCW8=?OLeUP{m literal 0 HcmV?d00001 diff --git a/docs/src/index.md b/docs/src/index.md index a96b80dca..d8f5d1a18 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -21,6 +21,10 @@ Functionality includes: The CouplerMachine supports coupling components that are all within the same process or coupling components (using MPI) that are running on different processes. +| ![Coupler Scheme](images/cplsetup.png) | +|:--:| +| *CouplerMachine allows for independent development of interchangeable component models.* | + ```@docs CouplerMachine ``` diff --git a/docs/src/timestepping.md b/docs/src/timestepping.md index e2853a4e5..cab3a8eb2 100644 --- a/docs/src/timestepping.md +++ b/docs/src/timestepping.md @@ -1,5 +1,17 @@ # Coupled Timestepping +`CouplerMachine` uses a concurrent timestepping framework. An outer "coupled" timestep +determines when component models synchronize and coordinate with the coupler. +Within this coupled timestep, components take an integer number of substeps, and evolve +independently from each other. + +| ![Coupled Timestepping](images/cpltimestep.png) | +|:--:| +| *Coupled timestepping with two component models.* | + +`CplSolver` extends the ODE solver API of +[ClimateMachine.ODESolvers](https://clima.github.io/ClimateMachine.jl/latest/APIs/Numerics/ODESolvers/ODESolvers/). + ```@docs CouplerMachine.CplSolver ``` \ No newline at end of file diff --git a/src/CplModel.jl b/src/CplModel.jl index cc64b94bf..56d855445 100644 --- a/src/CplModel.jl +++ b/src/CplModel.jl @@ -29,12 +29,12 @@ end Builds an instance of a coupler test model. This is a toy model used for testing and designing coupling machinery. In a full-blown coupled -experiment this model would be replaced by a full compnent model. +experiment this model would be replaced by a full component model. - `grid` the spectral element grid used by this model. - `equations` the Balance Law used by this model. - `nsteps` number of component steps to run during each coupling step. -- `boundary_z` height above or below air-sea interface of the coupled boundary. +- `boundary_z` height above or below the air-sea interface of the coupled boundary. - `dt` component timestep to use on each component step. - `timestepper` the ODE solver used to advance the system. - `NFfirstorder` numerical flux to use for first order terms. From 2a7edf55e65e40f41daafe99283545620c55e996 Mon Sep 17 00:00:00 2001 From: Ben Mackay Date: Thu, 22 Apr 2021 14:14:56 -0700 Subject: [PATCH 2/8] DUpdate docs, add CplModel page. --- docs/Manifest.toml | 2 +- docs/make.jl | 4 +++- docs/src/coupledmodel.md | 9 +++++++++ docs/src/index.md | 4 +++- src/CplModel.jl | 3 +-- src/CplState.jl | 4 +--- 6 files changed, 18 insertions(+), 8 deletions(-) create mode 100644 docs/src/coupledmodel.md diff --git a/docs/Manifest.toml b/docs/Manifest.toml index 42ceb30f6..7a6c49a69 100644 --- a/docs/Manifest.toml +++ b/docs/Manifest.toml @@ -145,7 +145,7 @@ uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9" version = "1.1.0" [[CouplerMachine]] -deps = ["CLIMAParameters", "ClimateMachine", "Dates", "JLD2", "LinearAlgebra", "MPI", "Oceananigans", "PrettyTables", "StaticArrays", "Statistics", "Unitful"] +deps = ["CLIMAParameters", "ClimateMachine", "Dates", "GaussQuadrature", "JLD2", "KernelAbstractions", "LinearAlgebra", "MPI", "Oceananigans", "PrettyTables", "StaticArrays", "Statistics", "Unitful"] path = ".." uuid = "4ade58fe-a8da-486c-bd89-46df092ec0c7" version = "0.1.0" diff --git a/docs/make.jl b/docs/make.jl index 57e191caf..6fe274cf2 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -18,10 +18,12 @@ experiment_pages = [ "Simple Two Component Test" => "generated/simple_2testcomp.md", ] +interface_pages = ["couplerstate.md", "timestepping.md", "coupledmodel.md"] + pages = Any[ "Home" => "index.md", "Examples" => experiment_pages, - "Coupler Interface" => ["couplerstate.md", "timestepping.md"], + "Coupler Interface" => interface_pages, ] diff --git a/docs/src/coupledmodel.md b/docs/src/coupledmodel.md new file mode 100644 index 000000000..3e9f5aa84 --- /dev/null +++ b/docs/src/coupledmodel.md @@ -0,0 +1,9 @@ +# Coupled Model Components + +CouplerMachine provides a wrapper for model components so that they may +connect to the coupler. The [`CplModel`](@ref) struct packages a component +model with the information needed for the [`CplSolver`](@ref) to evolve it. + +```@docs + CouplerMachine.CplModel +``` \ No newline at end of file diff --git a/docs/src/index.md b/docs/src/index.md index d8f5d1a18..611a98222 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -32,7 +32,9 @@ are running on different processes. ```@contents Pages = [ "examples.md", + "couplerstate.md" "timestepping.md", - "couplerstate.md", + "coupledmodel.md" ] +Depth = 2 ``` diff --git a/src/CplModel.jl b/src/CplModel.jl index 56d855445..ad5f62fc6 100644 --- a/src/CplModel.jl +++ b/src/CplModel.jl @@ -27,7 +27,7 @@ end NFgradient = CentralNumericalFluxGradient(), ) -Builds an instance of a coupler test model. This is a toy model +Builds an instance of a coupler test model. This is currently a toy model used for testing and designing coupling machinery. In a full-blown coupled experiment this model would be replaced by a full component model. @@ -50,7 +50,6 @@ to use for real setups). A real model might have many more flags and/or may wrap the component creation very differently. Any component should allow itself to set a number of timesteps to execute with a certain timestep to synchronize with the coupling time scale. - """ function CplModel(; grid, diff --git a/src/CplState.jl b/src/CplState.jl index ac8d3ccf2..4a5953c9d 100644 --- a/src/CplState.jl +++ b/src/CplState.jl @@ -30,9 +30,7 @@ communicate. Its role is to provide a level of indirection so that components re and so that any data communication, interpolation, reindexing/unit conversions and filtering etc... can be embeded in the intermdediate coupling layer. -To start with we can just use a dictionary key and value table that holds labelled pointers to various fields. -A field is exported by one component and imported by one or more other components. Components -can select which fields are needed by using the Dict symbols. +A field is exported by one component and imported by one or more other components. """ function CplState() return CplState(Dict{Symbol, CplFieldInfo}()) From 27d6790d2e7ba2613cc7ee743003f9d50a524308 Mon Sep 17 00:00:00 2001 From: Ben Mackay Date: Thu, 22 Apr 2021 14:15:48 -0700 Subject: [PATCH 3/8] Add to experiment docs. --- experiments/DesignTests/simple_2testcomp.jl | 25 ++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/experiments/DesignTests/simple_2testcomp.jl b/experiments/DesignTests/simple_2testcomp.jl index 75f07c444..02ab8ee29 100644 --- a/experiments/DesignTests/simple_2testcomp.jl +++ b/experiments/DesignTests/simple_2testcomp.jl @@ -1,3 +1,18 @@ +# # Diffusion Equation in a Vertical Column +# ## Setup +# - A vertical diffusive column split over two Cartesian components (atmos & ocean columns) +# - Boundary conditions used to set diffusive flux in other components have different vertical discretizations and timesteps +# - The coupler maps fields between the two components + +# ## Equations +# The RHS evaluation follows: +# ```math +# \frac{\partial \theta}{\partial t} = - \nabla \cdot [\kappa(\phi_{init}) \nabla \phi] +# ``` +# Where +# - `θ` is the tracer (e.g. potential temperature) +# - `κ` is the diffusivity tensor + # # Import packages using ClimateMachine using MPI @@ -50,6 +65,7 @@ const κᵒʰ = FT(1e3) * 0.0 const κᵒᶻ = FT(1e-4) # # Set up coupled model +# Define component models and initialize the coupler function main(::Type{FT}) where {FT} ## Domain @@ -107,8 +123,8 @@ function main(::Type{FT}) where {FT} dt = couple_dt / nstepsO, numerics..., ) - - ## Create a Coupler State object for holding import/export fields. +#+ +# Create a Coupler State object for holding import/export fields: coupler = CplState() register_cpl_field!(coupler, :Ocean_SST, deepcopy(mO.state.θ[mO.boundary]), mO.grid, DateTime(0), u"°C") register_cpl_field!(coupler, :Atmos_MeanAirSeaθFlux, deepcopy(mA.state.F_accum[mA.boundary]), mA.grid, DateTime(0), u"°C") @@ -140,6 +156,9 @@ function run(cpl_solver, numberofsteps, cbvector) end # # Define `pre_step` and `post_step` functions +# Each component model must define `pre_step` and `post_step` functions. +# In the `pre_step`, a component imports necessary boundary state and flux data from the coupler. +# In the `post_step`, a component exports boundary data to the coupler to be later received by other components. function get_components(csolver) mA = csolver.component_list.atmosphere.component_model @@ -304,4 +323,4 @@ bl_propO = (bl_propO..., coupling_lambda = coupling_lambda) simulation, cbvector = main(Float64); nsteps = 10 println("Initialized. Running...") -@time run(simulation, nsteps, cbvector) +run(simulation, nsteps, cbvector) From 7f48dd9792f26d5d411d9dafc4cdc8d753d4cf05 Mon Sep 17 00:00:00 2001 From: Ben Mackay Date: Fri, 30 Apr 2021 16:43:58 -0700 Subject: [PATCH 4/8] Add spherical advection diffusion example to docs. --- docs/make.jl | 4 +- .../AdvectionDiffusion/run_script_v2.jl | 107 +++++++++++++----- 2 files changed, 84 insertions(+), 27 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index 6fe274cf2..9b362b984 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -7,6 +7,7 @@ const OUTPUT_DIR = joinpath(@__DIR__, "..", "docs/src/generated") experiments = [ "DesignTests/simple_2testcomp.jl", + "AdvectionDiffusion/run_script_v2.jl" ] for experiment in experiments @@ -15,7 +16,8 @@ for experiment in experiments end experiment_pages = [ - "Simple Two Component Test" => "generated/simple_2testcomp.md", + "Vertical Column Heat Diffusion" => "generated/simple_2testcomp.md", + "Advection-diffusion on a Sphere" => "generated/run_script_v2.md", ] interface_pages = ["couplerstate.md", "timestepping.md", "coupledmodel.md"] diff --git a/experiments/AdvectionDiffusion/run_script_v2.jl b/experiments/AdvectionDiffusion/run_script_v2.jl index 0c029e293..cbf5c3998 100644 --- a/experiments/AdvectionDiffusion/run_script_v2.jl +++ b/experiments/AdvectionDiffusion/run_script_v2.jl @@ -1,3 +1,54 @@ +# # Advection-diffusion on a Sphere +# ## Setup +# - Passive advection of an anomaly using non-divergent horizontal flow on the sphere (currently 300km/s but switching to Williamson stream function) +# - Homogeneous tracer concentration of the outer shell couples to an inhomogeneous concentration of the inner shell + +# ## Equations +# The RHS evaluation follows: +# ```math +# \frac{\partial \theta}{\partial t} = - \nabla \cdot (\vec{u} \theta + \kappa \nabla \theta) \qquad +# ``` +# where +# - $\theta$ is the tracer (e.g. potential temperature) +# - $\vec{u}(u,0,0)$ is a constant zonal velocity +# - $\kappa$ is the diffusivity tensor. +# **Boundary Conditions** +# - External boundary conditions (Neumann): +# ```math +# \vec{n} \cdot \kappa \nabla \theta = 0 \qquad \text{at } z = 4\text{km}, -4\text{km} +# ``` +# where $\vec{n}$ is the upward pointing unit normal vector at the boundary. +# - Primary coupled boundary condition (forced by secondary domain): +# ```math +# \vec{n} \cdot \kappa_a \nabla \theta =f_a= \lambda (\theta - \theta_{secondary}) \qquad \text{at atmos } z = 0 +# ``` +# where $\lambda$ is a constant but will be replaced by a roughness coefficient factor in more complex test cases. +# $f_a$ and $\kappa_a$ are, respectively, the flux and diffusivity of the atmosphere component. +# - Secondary coupled boundary condition (accumulated flux by primary domain or prescribed flux): +# If accumulated, +# ```math +# \vec{n} \cdot \kappa_o\nabla \theta = f_o \qquad \text{at ocean } z = 0 \text{ (or pseudo subsurface)} +# and +# ``` +# ```math +# f_o = f_{accum} = \int_{\tau_0}^{\tau} f_a dt +# ``` +# where $τ-τ_0$ gives the coupling cycle length. +# $f_o$ and $\kappa_o$ are, respectively, the flux and diffusivity of the atmosphere component, with +# $f_{accum}$ being the accumulated flux. + +# ``` +# ATMOS +# ------------- θ @z=0 [lowest atmos level] +# A +# / \ f = n⋅κ_a ∇θ = λ(θ−θ_secondary​) +# | +# ------------- θ_secondary​ @z=0 [highest ocean level] +# OCEAN +# ``` + + +# # Import packages using ClimateMachine, MPI using ClimateMachine.DGMethods.NumericalFluxes using ClimateMachine.DGMethods @@ -39,18 +90,19 @@ const param_set = EarthParameterSet() ClimateMachine.init() FT = Float64 -# Shared functions +## Shared functions include("domains.jl") include("abstractions.jl") include("callbacks.jl") -# Main balance law and its components +## Main balance law and its components include("CplMainBL.jl") +# # Set simulation parameters nstepsA = 10 nstepsO = 5 -# Background atmos and ocean diffusivities +## Background atmos and ocean diffusivities const κᵃʰ = FT(1e4) * 0.0 const κᵃᶻ = FT(1e-1) const κᵒʰ = FT(1e3) * 0.0 @@ -61,14 +113,17 @@ const λ_airsea = FT(L_airsea / τ_airsea) coupling_lambda() = (λ_airsea) const u_max = FT(1e-5) # max. advective velocity in radians +# # Set up coupled model +# Define component models and initialize the coupler + function main(::Type{FT}) where {FT} - # Domain - # confusing name - better might be to use something like DeepSphericalShellDomain directly? + ## Domain - Spherical Shells + ## confusing name - better might be to use something like DeepSphericalShellDomain directly? ΩO = DeepSphericalShellDomain(radius = FT(planet_radius(param_set)) - FT(4e3), height = FT(4e3)) ΩA = DeepSphericalShellDomain(radius = FT(planet_radius(param_set)) , height = FT(4e3)) - # Grid + ## Grid nelem = (;horizontal = 8, vertical = 4) polynomialorder = (;horizontal = 5, vertical = 5) overintegrationorder = (;horizontal = 1, vertical = 1) @@ -76,23 +131,24 @@ function main(::Type{FT}) where {FT} gridA = DiscontinuousSpectralElementGrid(ΩA, nelem, polynomialorder) gridO = DiscontinuousSpectralElementGrid(ΩO, nelem, polynomialorder) - # Numerics-specific options - numerics = (NFfirstorder = CentralNumericalFluxFirstOrder(), NFsecondorder = PenaltyNumFluxDiffusive(), overint_params = (overintegrationorder, polynomialorder) ) #, NFsecondorder = CentralNumericalFluxSecondOrder() )#PenaltyNumFluxDiffusive() )#, overint_params = (overintegrationorder, polynomialorder) ) + ## Numerics-specific options + numerics = (NFfirstorder = CentralNumericalFluxFirstOrder(), NFsecondorder = PenaltyNumFluxDiffusive(), + overint_params = (overintegrationorder, polynomialorder)) - # Timestepping + ## Timestepping Δt_ = calculate_dt(gridA, wavespeed = u_max*(ΩA.radius), diffusivity = maximum([κᵃʰ, κᵃᶻ]) ) t_time, end_time = ( 0 , 20Δt_ ) - # Collect spatial info, timestepping, balance law and DGmodel for the two components + ## Collect spatial info, timestepping, balance law and DGmodel for the two components boundary_mask( xc, yc, zc ) = @. ( xc^2 + yc^2 + zc^2 )^0.5 ≈ planet_radius(param_set) - - # 1. Atmos component +#+ +# **1.** Atmos component ## Prop atmos functions to override defaults atmos_structure(λ, ϕ, r) = FT(30)#30.0 + 10.0 * cos(ϕ) * sin(5λ) atmos_θⁱⁿⁱᵗ(npt, el, x, y, z) = atmos_structure( lon(x,y,z), lat(x,y,z), rad(x,y,z) ) # Set atmosphere initial state function - #atmos_θ_shadowflux(θᵃ, θᵒ, npt, el, xc, yc, zc) = FT(0.0) + ##atmos_θ_shadowflux(θᵃ, θᵒ, npt, el, xc, yc, zc) = FT(0.0) atmos_θ_shadowflux(θᵃ, θᵒ, npt, el, xc, yc, zc) = is_surface(xc,yc,zc) ? (1.0 / τ_airsea) * (θᵃ - θᵒ) : 0.0 # Set atmosphere shadow boundary flux function atmos_calc_kappa_diff(_...) = κᵃʰ, κᵃʰ, κᵃᶻ # Set atmos diffusion coeffs atmos_source_θ(θᵃ, npt, el, xc, yc, zc, θᵒ) = FT(0.0) # Set atmos source! @@ -129,8 +185,8 @@ function main(::Type{FT}) where {FT} timestepper = LSRK54CarpenterKennedy, numerics..., ) - - # 2. Ocean component +#+ +# **2.** Ocean component ## Prop ocean functions to override defaults tropical_heating_1(λ, ϕ, r) = 30.0 + 10.0 * cos(ϕ) * sin(5λ) tropical_heating_2(λ, ϕ, r) = 30.0 + 10.0 * cos(ϕ) + 1 * sin(5λ) * cos(ϕ) @@ -165,17 +221,12 @@ function main(::Type{FT}) where {FT} timestepper = LSRK54CarpenterKennedy, numerics..., ) - - # Create a Coupler State object for holding import/export fields. - # Try using Dict here - not sure if that will be OK with GPU +#+ +# Create the coupler object for holding import/export fields and performs mappings +# and instantiate the coupled timestepper: coupler = CplState() register_cpl_field!(coupler, :Ocean_SST, deepcopy(mO.state.θ[mO.boundary]), mO.grid, DateTime(0), u"°C") register_cpl_field!(coupler, :Atmos_MeanAirSeaθFlux, deepcopy(mA.state.F_accum[mA.boundary]), mA.grid, DateTime(0), u"°C") - - - # Instantiate a coupled timestepper that steps forward the components and - # implements mapings between components export bondary states and - # other components imports. compA = (pre_step = preatmos, component_model = mA, post_step = postatmos) compO = (pre_step = preocean, component_model = mO, post_step = postocean) @@ -186,8 +237,10 @@ function main(::Type{FT}) where {FT} coupling_dt = Δt_, t0 = 0.0, ) - - # For now applying callbacks only to atmos. + +#+ +# Creat callbacks and bundle the simulation: + ## For now applying callbacks only to atmos. callbacks = ( ExponentialFiltering(), VTKOutput(( @@ -213,7 +266,7 @@ end function run(cpl_solver, numberofsteps, cbvector) - # Run the model + ## Run the model solve!( nothing, cpl_solver; @@ -222,6 +275,8 @@ function run(cpl_solver, numberofsteps, cbvector) ) end +# # Run simulation + simulation = main(Float64); nsteps = Int(simulation.simtime[2] / simulation.coupled_odesolver.dt) cbvector = create_callbacks(simulation, simulation.odesolver) From bd81f1445d99dd00d55758fb57dbb779e29066d3 Mon Sep 17 00:00:00 2001 From: Ben Mackay Date: Fri, 30 Apr 2021 16:44:43 -0700 Subject: [PATCH 5/8] Clean up vertical column example docs. --- experiments/DesignTests/simple_2testcomp.jl | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/experiments/DesignTests/simple_2testcomp.jl b/experiments/DesignTests/simple_2testcomp.jl index 02ab8ee29..85088e347 100644 --- a/experiments/DesignTests/simple_2testcomp.jl +++ b/experiments/DesignTests/simple_2testcomp.jl @@ -9,9 +9,9 @@ # ```math # \frac{\partial \theta}{\partial t} = - \nabla \cdot [\kappa(\phi_{init}) \nabla \phi] # ``` -# Where -# - `θ` is the tracer (e.g. potential temperature) -# - `κ` is the diffusivity tensor +# where +# - $\theta$ is the tracer (e.g. potential temperature) +# - $\kappa$ is the diffusivity tensor # # Import packages using ClimateMachine @@ -124,15 +124,12 @@ function main(::Type{FT}) where {FT} numerics..., ) #+ -# Create a Coupler State object for holding import/export fields: +# Create the coupler object for holding import/export fields and performs mappings +# and instantiate the coupled timestepper: coupler = CplState() register_cpl_field!(coupler, :Ocean_SST, deepcopy(mO.state.θ[mO.boundary]), mO.grid, DateTime(0), u"°C") register_cpl_field!(coupler, :Atmos_MeanAirSeaθFlux, deepcopy(mA.state.F_accum[mA.boundary]), mA.grid, DateTime(0), u"°C") - ## Instantiate a coupled timestepper that steps forward the components and - ## implements mapings between components export bondary states and - ## other components imports. - compA = (pre_step = preatmos, component_model = mA, post_step = postatmos) compO = (pre_step = preocean, component_model = mO, post_step = postocean) component_list = (atmosphere = compA, ocean = compO) From a7f68afb69cb7e9fda62088c85607a874e46d356 Mon Sep 17 00:00:00 2001 From: Ben Mackay Date: Fri, 30 Apr 2021 16:45:35 -0700 Subject: [PATCH 6/8] Remove contents block from index page. --- docs/src/index.md | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/docs/src/index.md b/docs/src/index.md index 611a98222..b4dd45dd0 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -28,13 +28,3 @@ are running on different processes. ```@docs CouplerMachine ``` - -```@contents -Pages = [ - "examples.md", - "couplerstate.md" - "timestepping.md", - "coupledmodel.md" -] -Depth = 2 -``` From 6f964f2a5f8069f93b23999feefae0c21750df76 Mon Sep 17 00:00:00 2001 From: Ben Mackay Date: Thu, 27 May 2021 11:39:42 -0700 Subject: [PATCH 7/8] Modify timestepping docs. --- docs/src/timestepping.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/src/timestepping.md b/docs/src/timestepping.md index cab3a8eb2..4c1e2f665 100644 --- a/docs/src/timestepping.md +++ b/docs/src/timestepping.md @@ -1,13 +1,14 @@ # Coupled Timestepping -`CouplerMachine` uses a concurrent timestepping framework. An outer "coupled" timestep -determines when component models synchronize and coordinate with the coupler. -Within this coupled timestep, components take an integer number of substeps, and evolve -independently from each other. +`CouplerMachine` currently uses a sequential timestepping framework in which one +component steps forward before passing its updated state to another. An outer +"coupled" timestep determines when component models synchronize and coordinate +with the coupler. Within this coupled timestep, components take an integer number +of substeps, and evolve independently from each other. | ![Coupled Timestepping](images/cpltimestep.png) | |:--:| -| *Coupled timestepping with two component models.* | +| *Sequential coupled timestepping with two component models.* | `CplSolver` extends the ODE solver API of [ClimateMachine.ODESolvers](https://clima.github.io/ClimateMachine.jl/latest/APIs/Numerics/ODESolvers/ODESolvers/). From 606b798371807ecf3418231d089f978e5a19afbb Mon Sep 17 00:00:00 2001 From: Ben Mackay Date: Wed, 9 Jun 2021 09:47:13 -0700 Subject: [PATCH 8/8] Edits to doc strings and md pages. --- docs/src/couplerstate.md | 4 +++- docs/src/index.md | 4 +--- docs/src/timestepping.md | 4 ---- src/CplModel.jl | 31 ++++++++++--------------------- src/CplSolver.jl | 19 +++++-------------- 5 files changed, 19 insertions(+), 43 deletions(-) diff --git a/docs/src/couplerstate.md b/docs/src/couplerstate.md index f2c9c7268..fcb36854d 100644 --- a/docs/src/couplerstate.md +++ b/docs/src/couplerstate.md @@ -1,4 +1,6 @@ -# Coupler Object +# Coupler State + +The coupler provides a space to store information being passed between coupled model components at their boundaries. During this exchange, the coupler manages ancillary operations such as regridding, unit conversions, filtering, etc. The CouplerMachine defines a type [`CplState`](@ref) for a _container_ variable that holds information about the field boundary values that are being used to diff --git a/docs/src/index.md b/docs/src/index.md index b4dd45dd0..e02f0ee15 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,13 +1,11 @@ # CouplerMachine.jl -![](favicon-32x32.png) *Coupling CliMA Models* - +*Coupling CliMA Models* ```@meta CurrentModule = CouplerMachine ``` - CouplerMachine.jl provides a means to couple climate model components from and within [ClimateMachine.jl](https://github.com/CliMA/ClimateMachine.jl) and [Oceananigans.jl](https://github.com/CliMA/Oceananigans.jl). It is designed to provide a flexible way to map boundary fluxes of quantities, like moisture and heat, that leave one component diff --git a/docs/src/timestepping.md b/docs/src/timestepping.md index 4c1e2f665..b11dd1e36 100644 --- a/docs/src/timestepping.md +++ b/docs/src/timestepping.md @@ -6,10 +6,6 @@ component steps forward before passing its updated state to another. An outer with the coupler. Within this coupled timestep, components take an integer number of substeps, and evolve independently from each other. -| ![Coupled Timestepping](images/cpltimestep.png) | -|:--:| -| *Sequential coupled timestepping with two component models.* | - `CplSolver` extends the ODE solver API of [ClimateMachine.ODESolvers](https://clima.github.io/ClimateMachine.jl/latest/APIs/Numerics/ODESolvers/ODESolvers/). diff --git a/src/CplModel.jl b/src/CplModel.jl index ad5f62fc6..4c042ed47 100644 --- a/src/CplModel.jl +++ b/src/CplModel.jl @@ -29,7 +29,8 @@ end Builds an instance of a coupler test model. This is currently a toy model used for testing and designing coupling machinery. In a full-blown coupled -experiment this model would be replaced by a full component model. +experiment this model would be replaced by a full component model that is +wrapped to format it for coupler compatibility. - `grid` the spectral element grid used by this model. - `equations` the Balance Law used by this model. @@ -63,13 +64,10 @@ function CplModel(; NFgradient = CentralNumericalFluxGradient(), overint_params = nothing, ) - FT = eltype(grid.vgeo) - ### - ### Create a discretization that is the union of the spatial - ### grid and the equations, plus some numerical flux settings. - ### + # Create a discretization that is the union of the spatial + # grid and the equations, plus some numerical flux settings. discretization = DGModel( equations, grid, @@ -88,14 +86,10 @@ function CplModel(; boundary(boundary_z, xc, yc, zc) = isnothing(boundary_z) ? zc .== 0 : boundary_z( xc, yc, zc ) boundary = boundary(boundary_z, xc, yc, zc) - ### - ### Invoke the spatial ODE initialization functions - ### + # Invoke the spatial ODE initialization functions state = init_ode_state(discretization, FT(0); init_on_cpu = true) - ### - ### Additional tendency hooks - ### + # Additional tendency hooks if overint_params != nothing overintegrationorder, polynomialorder = overint_params Ns = (polynomialorder.horizontal, polynomialorder.horizontal, polynomialorder.vertical) @@ -106,20 +100,15 @@ function CplModel(; discretization(tendency, x...; kw...) if overint_params != nothing overintegration_filter!(tendency, discretization, Ns, No) - #"uisng Oi" end end - ### - ### Create a timestepper of the sort needed for this component. - ### Hard coded here - but can be configurable. - ### + # Create a timestepper of the sort needed for this component. + # Hard coded here - but can be configurable. stepper = timestepper(custom_tendency, state, dt = dt, t0 = 0.0) - ### - ### Return a CplModel entity that holds all the information - ### for a component that can be driver from a coupled stepping layer. - ### + # Return a CplModel entity that holds all the information + # for a component that can be driver from a coupled stepping layer. return CplModel(grid, discretization, boundary, state, stepper, nsteps) end diff --git a/src/CplSolver.jl b/src/CplSolver.jl index 511ecf525..19a0f264c 100644 --- a/src/CplSolver.jl +++ b/src/CplSolver.jl @@ -12,22 +12,13 @@ balance law, discretization and timestepper collection. The coupler will step them forward by a nsteps substeps to advance the coupled system by a simulated time `coupling_dt`. -Components are registered with pre_step() and post_step() functions. The pre_step() -functions get fields for use in the component from the coupler name space. -The post_step() functions put fields for use by other components into -te coupler name space. -The CplSolver abstraction controls +Components interact with the coupler during `pre_step()` and `post_step()` functions. +During a `pre_step()`, a component may get fields from the coupler name space. +A component may put fields into the coupler name space during the `post_step()` for +later use by other components. The `CplSolver` abstraction controls 1. the outer time stepping sequencing of components - 2. the excution of actions mapping exports from one or more components to imports of + 2. the execution of actions mapping exports from one or more components to imports of other components through an intermediary coupler name space. - -Some notes - - -For now components need to include slightly wasteful "shadow" variables for -accumulating boundary flux terms they compute across RK stages and across -timesteps. These are defined within the component balance law. -The shadown variable is a full 3d array because of the way the current -infrastructure works. This can be tidied up later once design is settled. """ mutable struct CplSolver{CL, FT} <: AbstractODESolver "Named list of pre-defined components"