Global bucket run
The code sets up and runs the bucket model on a spherical domain, using ERA5 data.
First we import a lot of packages:
import ClimaComms
using ClimaCore
using ClimaUtilities
import Interpolations
import ClimaUtilities.TimeVaryingInputs:
TimeVaryingInput, LinearInterpolation, PeriodicCalendar
ClimaComms.@import_required_backends
import ClimaTimeSteppers as CTS
import ClimaParams as CP
using ClimaLand.Bucket:
BucketModel, BucketModelParameters, PrescribedBaregroundAlbedo
import ClimaLand
import ClimaLand.Parameters as LP
import ClimaLand.Simulations: LandSimulation, solve!
using Dates
using CairoMakie, ClimaAnalysis, GeoMakie, Printf, Statistics
import ClimaLand.LandSimVis as LandSimVis;┌ Warning: Error requiring `IntervalArithmetic` from `TaylorSeries`
│ exception =
│ LoadError: UndefVarError: `IntervalBox` not defined in `TaylorSeries`
│ Suggestion: check for spelling errors or missing imports.
│ Stacktrace:
│ [1] top-level scope
│ @ ~/.julia/packages/TaylorSeries/ZBRjU/src/intervals.jl:171
│ [2] include(mapexpr::Function, mod::Module, _path::String)
│ @ Base ./Base.jl:307
│ [3] top-level scope
│ @ ~/.julia/packages/Requires/1eCOK/src/Requires.jl:40
│ [4] eval(m::Module, e::Any)
│ @ Core ./boot.jl:489
│ [5] EvalInto
│ @ ./boot.jl:494 [inlined]
│ [6] (::TaylorSeries.var"#__init__##4#__init__##5")()
│ @ TaylorSeries ~/.julia/packages/Requires/1eCOK/src/require.jl:101
│ [7] macro expansion
│ @ ./timing.jl:461 [inlined]
│ [8] err(f::Any, listener::Module, modname::String, file::String, line::Any)
│ @ Requires ~/.julia/packages/Requires/1eCOK/src/require.jl:47
│ [9] (::TaylorSeries.var"#__init__##2#__init__##3")()
│ @ TaylorSeries ~/.julia/packages/Requires/1eCOK/src/require.jl:100
│ [10] withpath(f::Any, path::String)
│ @ Requires ~/.julia/packages/Requires/1eCOK/src/require.jl:37
│ [11] (::TaylorSeries.var"#__init__##0#__init__##1")()
│ @ TaylorSeries ~/.julia/packages/Requires/1eCOK/src/require.jl:99
│ [12] foreach(f::typeof(invokelatest), itr::Vector{Function})
│ @ Base ./abstractarray.jl:3191
│ [13] loadpkg(pkg::Base.PkgId)
│ @ Requires ~/.julia/packages/Requires/1eCOK/src/require.jl:27
│ [14] run_package_callbacks(modkey::Base.PkgId)
│ @ Base ./loading.jl:1467
│ [15] _require_search_from_serialized(pkg::Base.PkgId, sourcepath::String, build_id::UInt128, stalecheck::Bool; reasons::Dict{String, Int64}, DEPOT_PATH::Vector{String})
│ @ Base ./loading.jl:2201
│ [16] _require_search_from_serialized
│ @ ./loading.jl:2076 [inlined]
│ [17] __require_prelocked(pkg::Base.PkgId, env::String)
│ @ Base ./loading.jl:2695
│ [18] _require_prelocked(uuidkey::Base.PkgId, env::String)
│ @ Base ./loading.jl:2560
│ [19] macro expansion
│ @ ./loading.jl:2488 [inlined]
│ [20] macro expansion
│ @ ./lock.jl:376 [inlined]
│ [21] __require(into::Module, mod::Symbol)
│ @ Base ./loading.jl:2453
│ [22] require(into::Module, mod::Symbol)
│ @ Base ./loading.jl:2429
│ [23] eval(m::Module, e::Any)
│ @ Core ./boot.jl:489
│ [24] include_string(mapexpr::typeof(identity), mod::Module, code::String, filename::String)
│ @ Base ./loading.jl:2952
│ [25] include_string
│ @ ./loading.jl:2962 [inlined]
│ [26] #61
│ @ ~/.julia/packages/Literate/On3EJ/src/Literate.jl:959 [inlined]
│ [27] task_local_storage(body::Literate.var"#61#62"{String, Bool, Module, String}, key::Symbol, val::String)
│ @ Base ./task.jl:298
│ [28] #59
│ @ ~/.julia/packages/Literate/On3EJ/src/Literate.jl:955 [inlined]
│ [29] (::IOCapture.var"#12#13"{Type{Union{}}, Literate.var"#59#60"{String, Bool, Module, String}, IOContext{Base.PipeEndpoint}, IOContext{Base.PipeEndpoint}, IOContext{Base.PipeEndpoint}, IOContext{Base.PipeEndpoint}})()
│ @ IOCapture ~/.julia/packages/IOCapture/MR051/src/IOCapture.jl:170
│ [30] with_logstate(f::IOCapture.var"#12#13"{Type{Union{}}, Literate.var"#59#60"{String, Bool, Module, String}, IOContext{Base.PipeEndpoint}, IOContext{Base.PipeEndpoint}, IOContext{Base.PipeEndpoint}, IOContext{Base.PipeEndpoint}}, logstate::Base.CoreLogging.LogState)
│ @ Base.CoreLogging ./logging/logging.jl:542
│ [31] with_logger(f::Function, logger::Base.CoreLogging.ConsoleLogger)
│ @ Base.CoreLogging ./logging/logging.jl:653
│ [32] capture(f::Literate.var"#59#60"{String, Bool, Module, String}; rethrow::Type, color::Bool, passthrough::Bool, capture_buffer::IOBuffer, io_context::Vector{Any})
│ @ IOCapture ~/.julia/packages/IOCapture/MR051/src/IOCapture.jl:167
│ [33] capture
│ @ ~/.julia/packages/IOCapture/MR051/src/IOCapture.jl:100 [inlined]
│ [34] execute_block(sb::Module, block::String; inputfile::String, fake_source::String, softscope::Bool, continue_on_error::Bool)
│ @ Literate ~/.julia/packages/Literate/On3EJ/src/Literate.jl:953
│ [35] execute_block
│ @ ~/.julia/packages/Literate/On3EJ/src/Literate.jl:935 [inlined]
│ [36] execute_markdown!(io::IOBuffer, sb::Module, block::String, outputdir::String; inputfile::String, fake_source::String, flavor::Literate.DocumenterFlavor, image_formats::Vector{Tuple{MIME, String}}, file_prefix::String, softscope::Bool, continue_on_error::Bool)
│ @ Literate ~/.julia/packages/Literate/On3EJ/src/Literate.jl:683
│ [37] (::Literate.var"#42#43"{Dict{String, Any}, IOBuffer, Module, Literate.CodeChunk, Int64})()
│ @ Literate ~/.julia/packages/Literate/On3EJ/src/Literate.jl:651
│ [38] cd(f::Literate.var"#42#43"{Dict{String, Any}, IOBuffer, Module, Literate.CodeChunk, Int64}, dir::String)
│ @ Base.Filesystem ./file.jl:112
│ [39] markdown(inputfile::String, outputdir::String; config::Dict{Any, Any}, kwargs::@Kwargs{execute::Bool, documenter::Bool, preprocess::var"#mdpre#generate_tutorial##2"{String}})
│ @ Literate ~/.julia/packages/Literate/On3EJ/src/Literate.jl:650
│ [40] markdown (repeats 2 times)
│ @ ~/.julia/packages/Literate/On3EJ/src/Literate.jl:614 [inlined]
│ [41] (::var"#generate_tutorial##0#generate_tutorial##1"{String})()
│ @ Main ~/work/ClimaLand.jl/ClimaLand.jl/docs/make.jl:47
│ [42] cd(f::var"#generate_tutorial##0#generate_tutorial##1"{String}, dir::String)
│ @ Base.Filesystem ./file.jl:112
│ [43] generate_tutorial(tutorials_dir::String, tutorial::String)
│ @ Main ~/work/ClimaLand.jl/ClimaLand.jl/docs/make.jl:37
│ [44] (::var"#12#13")(t::String)
│ @ Main ~/work/ClimaLand.jl/ClimaLand.jl/docs/make.jl:66
│ [45] foreach(f::var"#12#13", itr::Vector{String})
│ @ Base ./abstractarray.jl:3191
│ [46] top-level scope
│ @ ~/work/ClimaLand.jl/ClimaLand.jl/docs/make.jl:65
│ [47] include(mod::Module, _path::String)
│ @ Base ./Base.jl:306
│ [48] exec_options(opts::Base.JLOptions)
│ @ Base ./client.jl:317
│ [49] _start()
│ @ Base ./client.jl:550
│ in expression starting at /home/runner/.julia/packages/TaylorSeries/ZBRjU/src/intervals.jl:171
└ @ Requires ~/.julia/packages/Requires/1eCOK/src/require.jl:51
Set the simulation float type, determine the context (MPI or on a single node), and device type. Create a default output directory for diagnostics.
const FT = Float64;
context = ClimaComms.context()
ClimaComms.init(context)
device = ClimaComms.device()
device_suffix = device isa ClimaComms.CPUSingleThreaded ? "cpu" : "gpu"
root_path = "bucket_longrun_$(device_suffix)"
diagnostics_outdir = joinpath(root_path, "global_diagnostics")
outdir =
ClimaUtilities.OutputPathGenerator.generate_output_path(diagnostics_outdir);Set timestep, startdate, stopdate:
Δt = 900.0
start_date = DateTime(2008)
stop_date = DateTime(2009);Create the domain - this is intentionally low resolution, about 4.5 degrees x 4.5 degrees, to run quickly when making the documentation on CPU.
nelements = (20, 7)
depth = FT(3.5)
dz_tuple = FT.((1.0, 0.05))
domain =
ClimaLand.Domains.global_domain(FT; context, nelements, depth, dz_tuple);Parameters:
toml_dict = LP.create_toml_dict(FT)
α_snow = FT(0.8)
albedo = PrescribedBaregroundAlbedo{FT}(α_snow, domain.space.surface)
bucket_parameters = BucketModelParameters(
toml_dict;
albedo,
σS_c = FT(0.2),
W_f = FT(0.2),
z_0m = FT(1e-3),
z_0b = FT(1e-3),
κ_soil = FT(1.5),
ρc_soil = FT(2e6),
τc = FT(float(Δt)),
);Low-resolution forcing data from ERA5 is used here, but high-resolution should be used for production runs.
atmos, radiation = ClimaLand.prescribed_forcing_era5(
start_date,
stop_date,
domain.space.surface,
toml_dict,
FT;
use_lowres_forcing = true,
max_wind_speed = 25.0,
time_interpolation_method = LinearInterpolation(PeriodicCalendar()),
regridder_type = :InterpolationsRegridder,
context,
);Make the model:
bucket = BucketModel(
parameters = bucket_parameters,
domain = domain,
atmosphere = atmos,
radiation = radiation,
);Create a function which sets the initial conditions. This should have the argument structure (Y,p,t, model) in order to be used by the LandSimulation struct, below:
function set_ic!(Y, p, t, bucket)
coords = ClimaCore.Fields.coordinate_field(Y.bucket.T)
T_sfc_0 = 271.0
@. Y.bucket.T = T_sfc_0 + 40 * cosd(coords.lat)^4
Y.bucket.W .= 0.15
Y.bucket.Ws .= 0.0
Y.bucket.σS .= 0.0
endset_ic! (generic function with 1 method)Define timestepper and ODE algorithm
timestepper = CTS.RK4()
timestepper = CTS.ExplicitAlgorithm(timestepper);Create the simulation and solve it:
simulation = LandSimulation(
start_date,
stop_date,
Δt,
bucket;
set_ic!,
timestepper,
outdir,
user_callbacks = (),
);
solve!(simulation);Make some plots:
short_names = ["lhf", "shf", "wsoil"]
LandSimVis.make_annual_timeseries(
simulation;
savedir = ".",
short_names,
plot_stem_name = "bucket_annual_timeseries",
)

LandSimVis.make_heatmaps(
simulation;
savedir = ".",
short_names,
date = stop_date,
plot_stem_name = "bucket_heatmap",
)

This page was generated using Literate.jl.