Skip to content

Commit

Permalink
Add helper functions in core_diagnostics
Browse files Browse the repository at this point in the history
  • Loading branch information
Sbozzolo committed Sep 13, 2023
1 parent 0bb2928 commit 973b07a
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 4 deletions.
28 changes: 25 additions & 3 deletions docs/src/diagnostics.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ function `compute!`. Schematically, a `compute!` has to look like
```julia
function compute!(out, state, cache, time)
# FIXME: Remove this line when ClimaCore implements the broadcasting to enable this
out .= # Calculcations with the state and the cache
out .= # Calculations with the state and the cache
end
```

Expand Down Expand Up @@ -253,13 +253,13 @@ function compute_relative_humidity!(
return TD.relative_humidity.(thermo_params, integrator.p.ᶜts)
end

compute_relative_humidity!(out, integrator) =
compute_relative_humidity!(out, state, cache, time) =
compute_relative_humidity!(
out,
state,
cache,
time,
cache.atmos,
cache.atmos.moisture_model,
)
```

Expand All @@ -268,6 +268,28 @@ it cannot be computed. We could specialize
`compute_relative_humidity` further if the relative humidity
were computed differently for `EquilMoistModel` and `NonEquilMoistModel`.

In `ClimaAtmos`, we define some helper functions to produce error messages, so
the above code can be written as
```julia
compute_relative_humidity!(out, state, cache, time) =
compute_relative_humidity!(out, state, cache, time, cache.atmos.moisture_model)
compute_relative_humidity!(_, _, _, _, model::T) where {T} =
error_diagnostic_variable("relative_humidity", model)

function compute_relative_humidity!(
out,
state,
cache,
time,
::T,
) where {T <: Union{EquilMoistModel, NonEquilMoistModel}}
# FIXME: Avoid extra allocations when ClimaCore overloads .= for this use case
# We will want: out .= integrator.u.c.ρ
thermo_params = CAP.thermodynamics_params(cache.params)
return TD.relative_humidity.(thermo_params, cache.ᶜts)
end
```

### Adding to the `ALL_DIAGNOSTICS` dictionary

`ClimaAtmos` comes with a collection of pre-defined `DiagnosticVariable` in the
Expand Down
46 changes: 45 additions & 1 deletion src/diagnostics/core_diagnostics.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,50 @@
# This file is included in Diagnostics.jl
#
# README: Adding a new core diagnostic:
#
# In addition to the metadata (names, comments, ...), the most important step in adding a
# new DiagnosticVariable is defining its compute! function. `compute!` has to take four
# arguments: (out, state, cache, time), and as to write the diagnostic in place into the
# `out` variable.
#
# Often, it is possible to compute certain diagnostics only for specific models (e.g.,
# humidity for moist models). For that, it is convenient to adopt the following pattern:
#
# 1. Define a catch base function that does the computation we want to do for the case we know
# how to handle, for example
#
# function compute_relative_humidity!(
# out,
# state,
# cache,
# time,
# ::T,
# ) where {T <: Union{EquilMoistModel, NonEquilMoistModel}}
# thermo_params = CAP.thermodynamics_params(cache.params)
# out .= TD.relative_humidity.(thermo_params, cache.ᶜts)
# end
#
# 2. Define a function that has the correct signature and calls this function
#
# compute_relative_humidity!(out, state, cache, time) =
# compute_relative_humidity!(out, state, cache, time, cache.moisture_model)
#
# 3. Define a function that returns an error when the model is incorrect
#
# compute_relative_humidity!(_, _, _, _, model::T) where {T} =
# error_diagnostic_variable("relative_humidity", model)
#
# We can also output a specific error message
#
# compute_relative_humidity!(_, _, _, _, model::T) where {T} =
# error_diagnostic_variable("relative humidity makes sense only for moist models")

# Rho
# General helper functions for undefined diagnostics for a particular model
error_diagnostic_variable(
message = "Cannot compute $variable with model = $T",
) = error(message)
error_diagnostic_variable(variable, model::T) where {T} =
error_diagnostic_variable("Cannot compute $variable with model = $T")

# FIXME: Gabriele wrote this as an example. Gabriele doesn't know anything about the
# physics. Please fix this!
Expand Down

0 comments on commit 973b07a

Please sign in to comment.