Skip to content

Commit

Permalink
add docs
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexisRenchon committed Jun 11, 2024
1 parent 0f19f60 commit f969d95
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 147 deletions.
5 changes: 5 additions & 0 deletions docs/list_diagnostics.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
diagnostics = [
"Available diagnostics" => "diagnostics/available_diagnostics.md",
"For developpers" => "diagnostics/developpers_diagnostics.md",
"For users" => "diagnostics/users_diagnostics.md",
]
3 changes: 2 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,15 @@ ext_jl2md(x) = joinpath(basename(GENERATED_DIR), replace(x, ".jl" => ".md"))
tutorials = transform_second(x -> ext_jl2md(x), tutorials)
include("list_of_apis.jl")
include("list_standalone_models.jl")
include("list_diagnostics.jl")
pages = Any[
"Home" => "index.md",
"APIs" => apis,
"Contribution guide" => "Contributing.md",
"Tutorials" => tutorials,
"Repository structure" => "folderstructure.md",
"Standalone models" => standalone_models,
"Available Diagnostics" => "available_diagnostics.md",
"Diagnostics" => diagnostics,
]


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

Autogenerate table of available diagnostics:
```@example
include("make_diagnostic_table.jl")
include("diagnostics/make_diagnostic_table.jl")
```
94 changes: 94 additions & 0 deletions docs/src/diagnostics/developpers_diagnostics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Compute methods

Each model defines all its compute methods in a script (bucket_compute_methods.jl for the bucket model, for example).
The structure of a diagnostic variable compute method is, for example:

```
function compute_albedo!(out, Y, p, t, land_model::BucketModel)
if isnothing(out)
return copy(p.bucket.α_sfc)
else
out .= p.bucket.α_sfc
end
end
```

It defines how to access your diagnostic (here, p.bucket.α_sfc), in your model type (here, ::BucketModel).

We also define helper functions returning error messages if a user tries to compute a diagnostic variable that doesn't exist in their model type.

```
error_diagnostic_variable(variable, land_model::T) where {T} =
error("Cannot compute $variable with model = $T")
compute_albedo!(_, _, _, _, land_model) =
error_diagnostic_variable("albedo", land_model)
```

# Define diagnostics

Once the compute functions have been defined, they are added to `define_diagnostics!(land_model)`, which adds diagnostics variables to ALL_DIAGNOSTICS dict,
defined in diagnostic.jl. In these functions, you also define a `short_name`, `long_name`, `standard_name`, `units` and `comment`. For example:

```
add_diagnostic_variable!(
short_name = "alpha",
long_name = "Albedo",
standard_name = "albedo",
units = "",
compute! = (out, Y, p, t) -> compute_albedo!(out, Y, p, t, land_model),
)
```

# Default diagnostics

For each model, we define a function `default_diagnostics` which will define what diagnostic variables to compute by default for a specific model, and
on what schedule (for example, hourly average). For example,

```
function default_diagnostics(land_model::BucketModel, t_start; output_writer)
define_diagnostics!(land_model)
bucket_diagnostics = [
"alpha",
"rn",
"tsfc",
"qsfc",
"lhf",
"rae",
"shf",
"vflux",
"rhosfc",
"t",
"w",
"ws",
"sigmas",
]
default_outputs =
hourly_averages(bucket_diagnostics...; output_writer, t_start)
return [default_outputs...]
end
```

is the default for the BucketModel, it will return hourly averages for the variables listed in `bucket_diagnostics` (which are all variables in the BucketModel).

# Standard diagnostic frequencies

We defined some functions of diagnostic schedule that may often be used in standard_diagnostic_frequencies.jl, for example

```
hourly_averages(short_names...; output_writer, t_start) = common_diagnostics(
60 * 60 * one(t_start),
(+),
output_writer,
t_start,
short_names...;
pre_output_hook! = average_pre_output_hook!,
)
```

will return a list of `ScheduledDiagnostics` that compute the hourly average for the given variables listed in `short_names`.
We also, so far, provide functions for mins, maxs and averages aggregated monthly, over ten days, daily, and hourly.
As a developper, you may want to add more standard diagnostics here.
File renamed without changes.
58 changes: 58 additions & 0 deletions docs/src/diagnostics/users_diagnostics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# default diagnostics

Once you have defined your model and are ready to run a simulation, and after adding ClimaDiagnostics (using ClimaDiagnostics),
you can add default diagnostics to it by doing the following steps:

1. define an output folder

```
mkdir("output")
output_dir = "output/"
```

you may want to check if this directory exist and remove it if so, so that when you re-run the simulation, you start fresh:

```
if isdir("output")
rm("output", force = true, recursive = true)
end
mkdir("output")
output_dir = "output/"
```

2. define a space

Your diagnostics will be written in time and space. These may be defined in your model, but usually land model space is a sphere with no vertical dimension.
You may have variables varying with soil depth, and so you will need:

```
space = bucket_domain.space.subsurface
```

3. define your writter

Your diagnostics will be written in a Julia Dict or a netcdf file, for example. This is up to you. For a netcdf file, you define your writter like this:

```
nc_writer = ClimaDiagnostics.Writers.NetCDFWriter(space, output_dir)
```

providing the space and output_dir defined in steps 1. and 2.

4. make your diagnostics on your model, using your writter, and define a callback

Now that you defined your model and your writter, you can create a callback function to be called when solving your model. For example:

```
diags = ClimaLand.CLD.default_diagnostics(model, 1.0; output_writer = nc_writer)
diagnostic_handler =
ClimaDiagnostics.DiagnosticsHandler(diags, Y, p, t0; dt = Δt)
diag_cb = ClimaDiagnostics.DiagnosticsCallback(diagnostic_handler)
sol = SciMLBase.solve(prob, ode_algo; dt = Δt, callback = diag_cb)
```

Your diagnostics have now been written in netcdf files in your output folder.
141 changes: 0 additions & 141 deletions src/Diagnostics/bucket_diagnostics.jl

This file was deleted.

6 changes: 2 additions & 4 deletions src/Diagnostics/diagnostic.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# export ALL_DIAGNOSTICS, add_diagnostic_variable, get_diagnostic_variable

# ClimaLand diagnostics

# - A dictionary `ALL_DIAGNOSTICS` with all the diagnostics we know how to compute, keyed
Expand Down Expand Up @@ -96,7 +94,7 @@ end

# Do you want to define more diagnostics? Add them here
include("bucket_compute_methods.jl")
include("bucket_diagnostics.jl")
include("define_diagnostics.jl")

# Default diagnostics and higher level interfaces
include("default_diagnostics.jl")
include("default_diagnostics.jl")

0 comments on commit f969d95

Please sign in to comment.