Basic Parameter Retrieval
There are two keys functions for parameter retrieval:
create_toml_dict
constructs a TOML dictionary which stores parameters,get_parameter_values
retrieves parameters from the TOML dictionary.
To construct a TOML dictionary, pass in the desired floating point type. This will source parameter values from the global default list stored in src/parameters.toml
import ClimaParams as CP
toml_dict = CP.create_toml_dict(Float64)
To retrieve parameters, pass in the TOML dictionary and the names that match the default parameters.
params = CP.get_parameter_values(toml_dict, ["gravitational_acceleration", "gas_constant"])
params.gravitational_acceleration
params.gas_constant
You can also pass in a single parameter name:
params = CP.get_parameter_values(toml_dict, "gravitational_acceleration")
params.gravitational_acceleration
Name Maps
Name maps are a way to map global descriptive parameter names (indexing the toml_dict) to local user-defined names. One can define a name with a NamedTuple as follows... It will return a NamedTuple of the parameters with your given variable names.
name_map = (;
:gravitational_acceleration => :g,
:angular_velocity_planet_rotation => :omega
)
params = CP.get_parameter_values(toml_dict, name_map)
params.g # gives value field of gravitational_acceleration
params.omega
A name map does not strictly need to be a NamedTuple. It can be a Dict, Vector, Tuple, or Varargs of Pairs. The entries in the name map can also be Strings instead of Symbols.
name_map = Dict("gravitational_acceleration" => "g", "angular_velocity_planet_rotation" => "omega")
params = CP.get_parameter_values(toml_dict, name_map)
params = CP.get_parameter_values(toml_dict, :gravitational_acceleration => :g,
:angular_velocity_planet_rotation => :omega)
Example Usage
An example from Thermodynamics.jl
In the user-facing driver file
import ClimaParams
using Thermodynamics
thermo_params = ThermodynamicsParameters(Float64)
In the source code for Thermodynamics.jl
Base.@kwdef struct ThermodynamicsParameters{FT}
gas_constant::FT
molmass_dryair::FT
...
# derived parameters
R_d::FT = gas_constant / molmass_dryair
end
- The struct is parameterized by
{FT}
which is a user-determined float precision. - Only relevant parameters used in
Thermodynamics
are stored here. - A keyword based constructor is provided so we do not rely on parameter order.
The constructor is as follows
# Float-type constructor
ThermodynamicsParameters(::Type{FT}) = ThermodynamicsParameters(CP.create_toml_dict(FT))
# TOML dictionary constructor
function ThermodynamicsParameters(toml_dict)
name_map = [
:temperature_triple_point => :T_triple,
:adiabatic_exponent_dry_air => :kappa_d,
:pressure_triple_point => :press_triple,
:thermodynamics_temperature_reference => :T_0,
:temperature_water_freeze => :T_freeze,
:isobaric_specific_heat_ice => :cp_i,
...
]
parameters = ClimaParams.get_parameter_values(
toml_dict,
name_map,
"Thermodynamics",
)
FT = CP.float_type(toml_dict)
return ThermodynamicsParameters{FT}(parameters...)
end
- The constructor takes in a
toml_dict
produced from reading the TOML file. - The name map maps from the globally-defined parameter names to the user-defined names.
- We obtain the NamedTuple parameters from
get_parameter_values(toml_dict, name_map, component_name)
Thecomponent_name
is a string used for the parameter log. - We return the
ThermodynamicsParameters{FT}
, where FT is an enforced float type (e.g. single or double precision).
An example with modular components from CloudMicrophysics.jl
In the user-facing driver file
Here we build a CloudMicrophysics
parameter set. In this case, the user wishes to use a 0-moment microphysics parameterization scheme.
import ClimaParams
import Thermodynamics
import CloudMicrophysics
#load defaults
toml_dict = ClimaParams.create_toml_dict(Float64)
#build the low level parameter set
param_therm = Thermodynamics.Parameters.ThermodynamicsParameters(toml_dict)
param_0M = CloudMicrophysics.Microphysics_0M_Parameters(toml_dict)
#build the hierarchical parameter set
parameter_set = CloudMicrophysics.CloudMicrophysicsParameters(
toml_dict,
param_0M,
param_therm
)
The exact APIs here are subject to change.
In the source code for CloudMicrophysics.jl
Build the different options for a Microphysics parameterizations
abstract type AbstractMicrophysicsParameters end
struct NoMicrophysicsParameters <: AbstractMicrophysicsParameters end
Base.@kwdef struct Microphysics_0M_Parameters{FT} <: AbstractMicrophysicsParameters
τ_precip::FT
qc_0::FT
S_0::FT
end
Base.@kwdef struct Microphysics_1M_Parameters{FT} <: AbstractMicrophysicsParameters
...
end
We omit their constructors (see above). The CloudMicrophysics
parameter set is built likewise
Base.@kwdef struct CloudMicrophysicsParameters{FT, AMPS <: AbstractMicrophysicsParameters}
K_therm::FT
...
MPS::AMPS
TPS::ThermodynamicsParameters{FT}
end
function CloudMicrophysicsParameters(
toml_dict,
MPS::AMPS,
TPS::ThermodynamicsParameters{FT},
) where {FT, AMPS <: AbstractMicrophysicsParameters}
parameter_names = [ "K_therm", ... ]
parameters = ClimaParams.get_parameter_values(
toml_dict,
parameter_names,
"CloudMicrophysics",
)
return CloudMicrophysicsParameters{FT, AMPS}(;
parameters...,
MPS, # Nested parameter struct
TPS, # Nested parameter struct
)
end
Parameters-as-functions
The exact APIs here are subject to change.
When building the model components, parameters are extracted by calling param_set.name
function example_cloudmicrophysics_func(param_set::CloudMicrophysicsParameters,...)
K_therm = param_set.K_therm
...
end
These parameters can be made into functions for added flexibility.
K_therm(param_set) = param_set.K_therm
This can be useful for derived parameters,
derived_param(param_set) = param_set.param1 * param_set.param2
or to forward parameters from nested parameter structs:
forwarded_param(ps::ParamSet) = ps.nested_params.forwarded_param
Functions can be autogenerated using @eval
:
for fn in fieldnames(ParamSet)
@eval $(fn)(ps::ParamSet) = ps.$(fn)
end