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

Add ExperimentConfig struct #76

Merged
merged 11 commits into from
Apr 8, 2024
Merged
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
2 changes: 1 addition & 1 deletion .buildkite/pipeline.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ steps:
- label: Initialize
key: init
command: |
julia --project=$exp_dir -e 'import Pkg; Pkg.instantiate(;verbose=true)'
julia --project=$exp_dir -e 'import Pkg; Pkg.build("CalibrateAtmos"); Pkg.instantiate(;verbose=true)'
EOM

if [ "$generate_data" == "true" ] ; then
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
- name: Surface Fluxes Perfect Model Test
run: |
julia --project=experiments/surface_fluxes_perfect_model -e 'using Pkg; Pkg.instantiate(;verbose=true)'
julia -t 10 --project=experiments/surface_fluxes_perfect_model test/test_sf.jl
julia --project=experiments/surface_fluxes_perfect_model test/test_sf.jl
- uses: julia-actions/julia-runtest@v1
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v3
Expand Down
4 changes: 0 additions & 4 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ ClimaParams = "5c42b081-d73a-476f-9059-fd94b934656c"
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
EnsembleKalmanProcesses = "aa8a2aa5-91d8-4396-bcef-d4f2ec43552d"
JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819"
PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462"
TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
YAML = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6"

Expand All @@ -23,8 +21,6 @@ ClimaParams = "0.10"
Distributions = "0.25"
EnsembleKalmanProcesses = "1"
JLD2 = "0.4"
PrecompileTools = "1"
Random = "1"
SciMLBase = "1, 2"
TOML = "1"
YAML = "0.4"
6 changes: 6 additions & 0 deletions docs/src/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ CalibrateAtmos.observation_map

## EnsembleKalmanProcesses Interface
```@docs
CalibrateAtmos.calibrate
CalibrateAtmos.initialize
CalibrateAtmos.save_G_ensemble
CalibrateAtmos.update_ensemble
CalibrateAtmos.ExperimentConfig
CalibrateAtmos.get_prior
CalibrateAtmos.get_param_dict
CalibrateAtmos.path_to_iteration
```
12 changes: 6 additions & 6 deletions docs/src/experiment_setup_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ Pseudocode for `observation_map(iteration)`:
function observation_map(::Val{:sphere_held_suarez_rhoe_equilmoist}, iteration)
# Get Configuration
experiment_id = "sphere_held_suarez_rhoe_equilmoist"
config = load_config(experiment_id)
ensemble_size = config["ensemble_size"]
config = ExperimentConfig(experiment_id)
ensemble_size = config.ensemble_size

# Setup output array
# dims = size of individual member observation map output
Expand Down Expand Up @@ -215,17 +215,17 @@ The EKP configuration file must contain the following:
- `n_iterations`, the number of iterations to run
- `ensemble_size`, the ensemble size
- `prior_path`, the path to the TOML file with the prior parameter distributions
- `truth_data`, the truth data
- `truth_noise`, the covariance of the truth data
- `observations`, the observational data
- `noise`, the covariance of the observational data
- `output_dir`, the folder where you want calibration data and logs to be output. This must be the same as the `output_dir` in the model configuration file.
Example:
```
output_dir: output/sphere_held_suarez_rhoe_equilmoist
prior_path: experiments/sphere_held_suarez_rhoe_equilmoist/prior.toml
ensemble_size: 10
n_iterations: 3
truth_data: experiments/sphere_held_suarez_rhoe_equilmoist/obs_mean.jld2
truth_noise: experiments/sphere_held_suarez_rhoe_equilmoist/obs_noise_cov.jld2
observations: experiments/sphere_held_suarez_rhoe_equilmoist/obs_mean.jld2
noise: experiments/sphere_held_suarez_rhoe_equilmoist/obs_noise_cov.jld2
```

## Plotting Results
Expand Down
5 changes: 1 addition & 4 deletions docs/src/precompilation.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,8 @@ import ClimaAtmos as CA
import YAML

@setup_workload begin
output = joinpath("precompilation")
job_id = "your configuration"
config_file = joinpath("experiments", job_id, "atmos_config.yml")
config_dict = YAML.load_file(config_file)
config_dict["output_dir"] = output
ExperimentConfig(job_id; output_dir = "precompilation")
@compile_workload begin
initialize(job_id)
config = CA.AtmosConfig(config_dict)
Expand Down
4 changes: 2 additions & 2 deletions experiments/sphere_held_suarez_rhoe_equilmoist/ekp_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ output_dir: output/sphere_held_suarez_rhoe_equilmoist
prior_path: experiments/sphere_held_suarez_rhoe_equilmoist/prior.toml
ensemble_size: 10
n_iterations: 3
truth_data: experiments/sphere_held_suarez_rhoe_equilmoist/obs_mean.jld2
truth_noise: experiments/sphere_held_suarez_rhoe_equilmoist/obs_noise_cov.jld2
observations: experiments/sphere_held_suarez_rhoe_equilmoist/obs_mean.jld2
noise: experiments/sphere_held_suarez_rhoe_equilmoist/obs_noise_cov.jld2
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,7 @@ Runs the atmosphere model with the given an AtmosConfig object.
Currently only has basic error handling.
"""

function run_forward_model(
::ClimaAtmosModel,
atmos_config::CA.AtmosConfig;
lk = nothing,
)
function run_forward_model(::ClimaAtmosModel, atmos_config::CA.AtmosConfig)
simulation = CA.get_simulation(atmos_config)
sol_res = CA.solve_atmos!(simulation)
if sol_res.ret_code == :simulation_crashed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ using Statistics
import YAML
import EnsembleKalmanProcesses: TOMLInterface
import JLD2
import CalibrateAtmos: observation_map, get_ekp_config
import CalibrateAtmos: observation_map, ExperimentConfig
using ClimaAnalysis
export observation_map

function observation_map(::Val{:sphere_held_suarez_rhoe_equilmoist}, iteration)
experiment_id = "sphere_held_suarez_rhoe_equilmoist"
config = get_ekp_config(experiment_id)
output_dir = config["output_dir"]
ensemble_size = config["ensemble_size"]
configuration = ExperimentConfig(experiment_id)
(; ensemble_size, output_dir) = configuration

dims = 1
G_ensemble = Array{Float64}(undef, dims..., ensemble_size)
Expand Down
60 changes: 1 addition & 59 deletions experiments/surface_fluxes_perfect_model/Manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@ julia_version = "1.10.2"
manifest_format = "2.0"
project_hash = "2edfa41926269520ea7e69208df499eef7522bd0"

[[deps.ADTypes]]
git-tree-sha1 = "41c37aa88889c171f1300ceac1313c06e891d245"
uuid = "47edcb42-4c32-4615-8424-f2b9edc5f35b"
version = "0.2.6"

[[deps.AMD]]
deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse_jll"]
git-tree-sha1 = "45a1272e3f809d36431e57ab22703c6896b8908f"
Expand Down Expand Up @@ -294,7 +289,7 @@ uuid = "83423d85-b0ee-5818-9007-b63ccbeb887a"
version = "1.16.1+1"

[[deps.CalibrateAtmos]]
deps = ["CalibrateEmulateSample", "ClimaComms", "ClimaParams", "Distributions", "EnsembleKalmanProcesses", "JLD2", "PrecompileTools", "Random", "SciMLBase", "TOML", "YAML"]
deps = ["CalibrateEmulateSample", "ClimaComms", "ClimaParams", "Distributions", "EnsembleKalmanProcesses", "JLD2", "Random", "TOML", "YAML"]
path = "../.."
uuid = "4347a170-ebd6-470c-89d3-5c705c0cacc2"
version = "0.1.0"
Expand Down Expand Up @@ -396,11 +391,6 @@ git-tree-sha1 = "08c8b6831dc00bfea825826be0bc8336fc369860"
uuid = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
version = "1.0.2"

[[deps.CommonSolve]]
git-tree-sha1 = "0eee5eb66b1cf62cd6ad1b460238e60e4b09400c"
uuid = "38540f10-b2f7-11e9-35d8-d573e4eb0ff2"
version = "0.2.4"

[[deps.CommonSubexpressions]]
deps = ["MacroTools", "Test"]
git-tree-sha1 = "7b8a93dba8af7e3b42fecabf646260105ac373f7"
Expand Down Expand Up @@ -769,17 +759,6 @@ git-tree-sha1 = "aa31987c2ba8704e23c6c8ba8a4f769d5d7e4f91"
uuid = "559328eb-81f9-559d-9380-de523a88c83c"
version = "1.0.10+0"

[[deps.FunctionWrappers]]
git-tree-sha1 = "d62485945ce5ae9c0c48f124a84998d755bae00e"
uuid = "069b7b12-0de2-55c6-9aab-29f3d0a68a2e"
version = "1.1.3"

[[deps.FunctionWrappersWrappers]]
deps = ["FunctionWrappers"]
git-tree-sha1 = "b104d487b34566608f8b4e1c39fb0b10aa279ff8"
uuid = "77dc65aa-8811-40c2-897b-53d922fa7daf"
version = "0.1.3"

[[deps.Future]]
deps = ["Random"]
uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820"
Expand Down Expand Up @@ -1879,12 +1858,6 @@ git-tree-sha1 = "40b9edad2e5287e05bd413a38f61a8ff55b9557b"
uuid = "5eaf0fd0-dfba-4ccb-bf02-d820a40db705"
version = "0.2.1"

[[deps.RuntimeGeneratedFunctions]]
deps = ["ExprTools", "SHA", "Serialization"]
git-tree-sha1 = "6aacc5eefe8415f47b3e34214c1d79d2674a0ba2"
uuid = "7e49a35a-f44a-4d26-94aa-eba1b4ca6b47"
version = "0.5.12"

[[deps.SCS]]
deps = ["MathOptInterface", "Requires", "SCS_GPU_jll", "SCS_jll", "SparseArrays"]
git-tree-sha1 = "8d908b7c81e199ee92d17b6192849e8c43d2f31d"
Expand Down Expand Up @@ -1918,37 +1891,6 @@ git-tree-sha1 = "3aac6d68c5e57449f5b9b865c9ba50ac2970c4cf"
uuid = "476501e8-09a2-5ece-8869-fb82de89a1fa"
version = "0.6.42"

[[deps.SciMLBase]]
deps = ["ADTypes", "ArrayInterface", "CommonSolve", "ConstructionBase", "Distributed", "DocStringExtensions", "EnumX", "FunctionWrappersWrappers", "IteratorInterfaceExtensions", "LinearAlgebra", "Logging", "Markdown", "PrecompileTools", "Preferences", "Printf", "RecipesBase", "RecursiveArrayTools", "Reexport", "RuntimeGeneratedFunctions", "SciMLOperators", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "Tables"]
git-tree-sha1 = "3a281a9fce9cd62b849d7f16e412933a5fe755cb"
uuid = "0bca4576-84f4-4d90-8ffe-ffa030f20462"
version = "2.29.0"

[deps.SciMLBase.extensions]
SciMLBaseChainRulesCoreExt = "ChainRulesCore"
SciMLBaseMakieExt = "Makie"
SciMLBasePartialFunctionsExt = "PartialFunctions"
SciMLBasePyCallExt = "PyCall"
SciMLBasePythonCallExt = "PythonCall"
SciMLBaseRCallExt = "RCall"
SciMLBaseZygoteExt = "Zygote"

[deps.SciMLBase.weakdeps]
ChainRules = "082447d4-558c-5d27-93f4-14fc19e9eca2"
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
PartialFunctions = "570af359-4316-4cb7-8c74-252c00c2016b"
PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0"
PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d"
RCall = "6f49c342-dc21-5d91-9882-a32aef131414"
Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f"

[[deps.SciMLOperators]]
deps = ["ArrayInterface", "DocStringExtensions", "LinearAlgebra", "MacroTools", "Setfield", "SparseArrays", "StaticArraysCore"]
git-tree-sha1 = "10499f619ef6e890f3f4a38914481cc868689cd5"
uuid = "c0aeaf25-5076-4817-a8d5-81caf7dfa961"
version = "0.3.8"

[[deps.ScientificTypesBase]]
git-tree-sha1 = "a8e18eb383b5ecf1b5e6fc237eb39255044fd92b"
uuid = "30f210dd-8aff-4c5f-94ba-8e64358c1161"
Expand Down
4 changes: 2 additions & 2 deletions experiments/surface_fluxes_perfect_model/ekp_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ output_dir: output/surface_fluxes_perfect_model
prior_path: experiments/surface_fluxes_perfect_model/prior.toml
ensemble_size: 10
n_iterations: 10
truth_data: experiments/surface_fluxes_perfect_model/data/obs_mean.jld2
truth_noise: experiments/surface_fluxes_perfect_model/data/obs_noise_cov.jld2
observations: experiments/surface_fluxes_perfect_model/data/obs_mean.jld2
noise: experiments/surface_fluxes_perfect_model/data/obs_noise_cov.jld2
generate_data: true
46 changes: 23 additions & 23 deletions experiments/surface_fluxes_perfect_model/model_interface.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import EnsembleKalmanProcesses as EKP
using CalibrateAtmos
import CalibrateAtmos:
AbstractPhysicalModel, get_config, run_forward_model, get_forward_model
AbstractPhysicalModel,
get_config,
run_forward_model,
get_forward_model,
ExperimentConfig
import YAML

"""
Expand Down Expand Up @@ -43,13 +47,12 @@ function get_config(
iteration,
experiment_id::AbstractString,
)
config_dict = YAML.load_file("experiments/$experiment_id/model_config.yml")
return get_config(model, member, iteration, config_dict)
return get_config(model, member, iteration, ExperimentConfig(experiment_id))
end

"""
get_config(member, iteration, experiment_id::AbstractString)
get_config(member, iteration, config_dict::AbstractDict)
get_config(member, iteration, experiment_config::ExperimentConfig)

Returns an config dictionary object for the given member and iteration.
If given an experiment id string, it will load the config from the corresponding YAML file.
Expand All @@ -60,22 +63,29 @@ function get_config(
::SurfaceFluxModel,
member,
iteration,
config_dict::AbstractDict,
experiment_config::ExperimentConfig,
)
# Specify member path for output_dir
output_dir = config_dict["output_dir"]
model_config = YAML.load_file(
joinpath(
"experiments",
"surface_fluxes_perfect_model",
"model_config.yml",
),
)
output_dir = (experiment_config.output_dir)
# Set TOML to use EKP parameter(s)
member_path =
EKP.TOMLInterface.path_to_ensemble_member(output_dir, iteration, member)
config_dict["output_dir"] = member_path
model_config["output_dir"] = member_path
parameter_path = joinpath(member_path, "parameters.toml")
if haskey(config_dict, "toml")
push!(config_dict["toml"], parameter_path)
if haskey(model_config, "toml")
push!(model_config["toml"], parameter_path)
else
config_dict["toml"] = [parameter_path]
model_config["toml"] = [parameter_path]
end

return config_dict
return model_config
end

"""
Expand All @@ -84,18 +94,8 @@ end
Runs the model with the given an AbstractDict object.
"""

function run_forward_model(
::SurfaceFluxModel,
config::AbstractDict;
lk = nothing,
)
x_inputs = if isnothing(lk)
load_profiles(config["x_data_file"])
else
lock(lk) do
load_profiles(config["x_data_file"])
end
end
function run_forward_model(::SurfaceFluxModel, config::AbstractDict)
x_inputs = load_profiles(config["x_data_file"])
FT = typeof(x_inputs.profiles_int[1].T)
obtain_ustar(FT, x_inputs, config)
end
8 changes: 3 additions & 5 deletions experiments/surface_fluxes_perfect_model/observation_map.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ using Statistics
import YAML
import EnsembleKalmanProcesses: TOMLInterface
import JLD2
import CalibrateAtmos: observation_map, get_ekp_config
import CalibrateAtmos: observation_map

"""
observation_map(::Val{:surface_fluxes_perfect_model}, iteration)
Expand All @@ -11,10 +11,8 @@ Returns the observation map (from the raw model output to the observable y),
as specified by process_member_data, for the given iteration.
"""
function observation_map(::Val{:surface_fluxes_perfect_model}, iteration)
experiment_id = "surface_fluxes_perfect_model"
config = get_ekp_config(experiment_id)
output_dir = config["output_dir"]
ensemble_size = config["ensemble_size"]
config = ExperimentConfig("surface_fluxes_perfect_model")
(; output_dir, ensemble_size) = config
model_output = "model_ustar_array.jld2"

dims = 1
Expand Down
11 changes: 4 additions & 7 deletions experiments/surface_fluxes_perfect_model/plot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -104,20 +104,17 @@ pkg_dir = pkgdir(CalibrateAtmos)
model_config = YAML.load_file(
joinpath(pkg_dir, "experiments", experiment_id, "model_config.yml"),
)
ekp_config = YAML.load_file(
joinpath(pkg_dir, "experiments", experiment_id, "ekp_config.yml"),
)
N_iter = ekp_config["n_iterations"]
N_mem = ekp_config["ensemble_size"]
ekp_config = ExperimentConfig(experiment_id)
N_iter = ekp_config.n_iterations
N_mem = ekp_config.ensemble_size
eki_path = joinpath(
joinpath(pkg_dir, model_config["output_dir"]),
"iteration_$(lpad(N_iter, 3, '0'))",
"eki_file.jld2",
);
eki = JLD2.load_object(eki_path);
EKP.get_u(eki)
prior_path = joinpath(pkg_dir, ekp_config["prior_path"])
prior = CalibrateAtmos.get_prior(prior_path)
prior = ekp_config.prior

theta_star_vec =
(; coefficient_a_m_businger = 4.7, coefficient_a_h_businger = 4.7)
Expand Down
Loading
Loading