From 3490cbfad02ee7d69deb72fb53f081ce836ac763 Mon Sep 17 00:00:00 2001 From: Gabriele Bozzola Date: Thu, 14 Sep 2023 08:53:26 -0700 Subject: [PATCH] Make ALL_DIAGNOSTICS an implementation detail Currently, the diagnostic variables are stored in a dictionary. We might want to be able to change the internal representation in the future. For that, we provide an interface to the database of known diagnostic variables through `set_diagnostic_variable!` and `get_diagnostic_variable`. If we want to change the internal representation in the future, we will be able to do so easily. --- docs/src/diagnostics.md | 29 ++++++++++------------ src/diagnostics/default_diagnostics.jl | 2 +- src/diagnostics/defaults/moisture_model.jl | 4 +-- src/diagnostics/diagnostic.jl | 17 ++++++++++++- src/solver/type_getters.jl | 4 +-- 5 files changed, 34 insertions(+), 22 deletions(-) diff --git a/docs/src/diagnostics.md b/docs/src/diagnostics.md index 42074c0588c..8fc7b4a50d0 100644 --- a/docs/src/diagnostics.md +++ b/docs/src/diagnostics.md @@ -51,11 +51,11 @@ Technically, the diagnostics are represented as `ScheduledDiagnostic` objects, which contain information about what variable has to be computed, how often, where to save it, and so on (read below for more information on this). You can construct your own lists of `ScheduledDiagnostic`s starting from the variables -defined by `ClimaAtmos`. The diagnostics that `ClimaAtmos` knows how to compute -are collected in a global dictionary called `ALL_DIAGNOSTICS`. The variables in -`ALL_DIAGNOSTICS` are identified with by the short and unique name, so that you -can access them directly. One way to do so is by using the provided convenience -functions for common operations, e.g., continuing the previous example +defined by `ClimaAtmos`. The `DiagnosticVariable`s in `ClimaAtmos` are +identified with by the short and unique name, so that you can access them +directly with the function `get_diagnostic_variable`. One way to do so is by +using the provided convenience functions for common operations, e.g., continuing +the previous example ```julia @@ -290,17 +290,14 @@ function compute_relative_humidity!( end ``` -### Adding to the `ALL_DIAGNOSTICS` dictionary +### The `ClimaAtmos` `DiagnosticVariable`s -`ClimaAtmos` comes with a collection of pre-defined `DiagnosticVariable` in the -`ALL_DIAGNOSTICS` dictionary. `ALL_DIAGNOSTICS` maps a `short_name` with the -corresponding `DiagnosticVariable`. - -If you are extending `ClimaAtmos` and want to add a new diagnostic variable to -`ALL_DIAGNOSTICS`, go ahead and look at the files we `include` in +`ClimaAtmos` comes with a collection of pre-defined `DiagnosticVariable`, index +with their `short_name`s. If you are extending `ClimaAtmos` and want to add a +new diagnostic variable, go ahead and look at the files we `include` in `diagnostics/Diagnostics.jl`. You can add more diagnostics in those files or add a new one. We provide a convenience function, `add_diagnostic_variable!` to add -new `DiagnosticVariable`s to the `ALL_DIAGNOSTICS` dictionary. -`add_diagnostic_variable!` take the same arguments as the constructor for -`DiagnosticVariable`, but also performs additional checks. So, use -`add_diagnostic_variable!` instead of editing the `ALL_DIAGNOSTICS` directly. +new `DiagnosticVariable`s. `add_diagnostic_variable!` take the same arguments as +the constructor for `DiagnosticVariable`, but also performs additional checks. +Similarly, if you want to retrieve a diagnostic from `ALL_DIAGNOSTICS`, use the +`get_diagnostic_variable`function. diff --git a/src/diagnostics/default_diagnostics.jl b/src/diagnostics/default_diagnostics.jl index 7800990e375..d13d8f306a6 100644 --- a/src/diagnostics/default_diagnostics.jl +++ b/src/diagnostics/default_diagnostics.jl @@ -46,7 +46,7 @@ function common_diagnostics( ) return [ ScheduledDiagnosticTime( - variable = ALL_DIAGNOSTICS[short_name], + variable = get_diagnostic_variable(short_name), compute_every = :timestep, output_every = period, # seconds reduction_time_func = reduction, diff --git a/src/diagnostics/defaults/moisture_model.jl b/src/diagnostics/defaults/moisture_model.jl index f1083f0c77b..a58129f9a75 100644 --- a/src/diagnostics/defaults/moisture_model.jl +++ b/src/diagnostics/defaults/moisture_model.jl @@ -3,14 +3,14 @@ function get_default_diagnostics(::DryModel) return [ daily_averages("air_density")..., ScheduledDiagnosticTime( - variable = ALL_DIAGNOSTICS["air_density"], + variable = get_diagnostic_variable("air_density"), compute_every = :timestep, output_every = 86400, # seconds reduction_time_func = min, output_writer = HDF5Writer(), ), ScheduledDiagnosticIterations( - variable = ALL_DIAGNOSTICS["air_density"], + variable = get_diagnostic_variable("air_density"), compute_every = 1, output_every = 1, # iteration output_writer = HDF5Writer(), diff --git a/src/diagnostics/diagnostic.jl b/src/diagnostics/diagnostic.jl index 1c2c12a5ff7..ef7939b8706 100644 --- a/src/diagnostics/diagnostic.jl +++ b/src/diagnostics/diagnostic.jl @@ -11,7 +11,8 @@ # - A dictionary `ALL_DIAGNOSTICS` with all the diagnostics we know how to compute, keyed # over their short name. If you want to add more diagnostics, look at the included files. # You can add your own file if you want to define several new diagnostics that are -# conceptually related. +# conceptually related. The dictionary `ALL_DIAGNOSTICS` should be considered an +# implementation detail. # # - The definition of what a ScheduledDiagnostics is. Conceptually, a ScheduledDiagnostics is a # DiagnosticVariable we want to compute in a given simulation. For example, it could be @@ -150,6 +151,20 @@ function add_diagnostic_variable!(; DiagnosticVariable(; short_name, long_name, units, comments, compute!) end +""" + + get_diagnostic_variable!(short_name) + + +Return a `DiagnosticVariable` from its `short_name`, if it exists. +""" +function get_diagnostic_variable(short_name) + haskey(ALL_DIAGNOSTICS, short_name) && + error("diagnostic $short_name does not exist") + + return ALL_DIAGNOSTICS[short_name] +end + # Do you want to define more diagnostics? Add them here include("core_diagnostics.jl") include("turbconv_diagnostics.jl") diff --git a/src/solver/type_getters.jl b/src/solver/type_getters.jl index bc6cc31d191..7acafdf002b 100644 --- a/src/solver/type_getters.jl +++ b/src/solver/type_getters.jl @@ -682,7 +682,7 @@ function get_diagnostics(parsed_args, atmos_model) if isnothing(name) name = CAD.get_descriptive_name( - CAD.ALL_DIAGNOSTICS[yaml_diag["short_name"]], + CAD.get_diagnostic_variable(yaml_diag["short_name"]), period_seconds, reduction_time_func, pre_output_hook!, @@ -698,7 +698,7 @@ function get_diagnostics(parsed_args, atmos_model) push!( diagnostics, CAD.ScheduledDiagnosticTime( - variable = CAD.ALL_DIAGNOSTICS[yaml_diag["short_name"]], + variable = CAD.get_diagnostic_variable(yaml_diag["short_name"]), output_every = period_seconds, compute_every = compute_every, reduction_time_func = reduction_time_func,