From 66491afc339bc296ccddc7b90cbe28cdec93914d Mon Sep 17 00:00:00 2001 From: Maarten Pronk Date: Mon, 21 Oct 2024 14:12:43 +0200 Subject: [PATCH] Introduce experimental config section and use it for concentrations. (#1909) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I almost went for StyledStrings, but the underline (here **) seems enough. ```julia ┌ Info: Starting a Ribasim simulation. │ toml_path = "/Users/evetion/Downloads/hws_2024_7_x_delwaq/hws_24h.toml" │ cli.ribasim_version = "2024.11.0" │ starttime = 2023-01-20T00:00:00 └ endtime = 2023-07-01T00:00:00 ┌ Warning: The following *experimental* features are enabled: concentration └ @ Ribasim /Users/evetion/code/Ribasim/core/src/main.jl:44 ``` --------- Co-authored-by: Martijn Visser --- core/src/config.jl | 14 ++++++++++++++ core/src/main.jl | 3 +++ core/src/write.jl | 10 ++++++---- core/test/docs.toml | 4 ++++ docs/_quarto.yml | 1 + docs/concept/core.qmd | 20 ++++++++++++++------ docs/guide/coupling.qmd | 2 +- docs/reference/usage.qmd | 17 +++++++++++++++++ python/ribasim/ribasim/config.py | 13 +++++++++++++ python/ribasim/ribasim/model.py | 3 +++ 10 files changed, 76 insertions(+), 11 deletions(-) diff --git a/core/src/config.jl b/core/src/config.jl index bf9e38c81..1fc0012e2 100644 --- a/core/src/config.jl +++ b/core/src/config.jl @@ -134,6 +134,19 @@ end use_allocation::Bool = false end +@option struct Experimental <: TableOption + concentration::Bool = false +end +# For logging enabled experimental features +function Base.iterate(exp::Experimental, state = 0) + state >= nfields(exp) && return + return Base.getfield(exp, state + 1), state + 1 +end +function Base.show(io::IO, exp::Experimental) + fields = (field for field in fieldnames(typeof(exp)) if getfield(exp, field)) + print(io, join(fields, " ")) +end + @option @addnodetypes struct Toml <: TableOption starttime::DateTime endtime::DateTime @@ -145,6 +158,7 @@ end solver::Solver = Solver() logging::Logging = Logging() results::Results = Results() + experimental::Experimental = Experimental() end struct Config diff --git a/core/src/main.jl b/core/src/main.jl index 0e613b8f1..95eb43764 100644 --- a/core/src/main.jl +++ b/core/src/main.jl @@ -40,6 +40,9 @@ function main(toml_path::AbstractString)::Cint @warn "The Ribasim version in the TOML config file does not match the used Ribasim CLI version." config.ribasim_version cli.ribasim_version end @info "Starting a Ribasim simulation." toml_path cli.ribasim_version starttime endtime + if any(config.experimental) + @warn "The following *experimental* features are enabled: $(config.experimental)" + end try model = run(config) diff --git a/core/src/write.jl b/core/src/write.jl index 87afce433..425c4beb9 100644 --- a/core/src/write.jl +++ b/core/src/write.jl @@ -5,7 +5,7 @@ Write all results to the Arrow files as specified in the model configuration. """ function write_results(model::Model)::Model (; config) = model - (; results) = model.config + (; results, experimental) = model.config compress = get_compressor(results) remove_empty_table = model.integrator.t != 0 @@ -25,9 +25,11 @@ function write_results(model::Model)::Model write_arrow(path, table, compress; remove_empty_table) # concentrations - table = concentration_table(model) - path = results_path(config, RESULTS_FILENAME.concentration) - write_arrow(path, table, compress; remove_empty_table) + if experimental.concentration + table = concentration_table(model) + path = results_path(config, RESULTS_FILENAME.concentration) + write_arrow(path, table, compress; remove_empty_table) + end # discrete control table = discrete_control_table(model) diff --git a/core/test/docs.toml b/core/test/docs.toml index 3b91105c6..ac155cebf 100644 --- a/core/test/docs.toml +++ b/core/test/docs.toml @@ -48,3 +48,7 @@ verbosity = "info" # optional, default "info", can otherwise be "debug", "warn" # These results files are always written compression = true # optional, default true, using zstd compression compression_level = 6 # optional, default 6 + +[experimental] +# Experimental features, disabled by default +concentration = false # tracer calculations diff --git a/docs/_quarto.yml b/docs/_quarto.yml index 11645a750..0804b0490 100644 --- a/docs/_quarto.yml +++ b/docs/_quarto.yml @@ -32,6 +32,7 @@ website: - install.qmd - changelog.qmd - known_issues.qmd + - contact.qmd - title: "Tutorials" contents: diff --git a/docs/concept/core.qmd b/docs/concept/core.qmd index ebfc9d201..5dbf510b5 100644 --- a/docs/concept/core.qmd +++ b/docs/concept/core.qmd @@ -120,21 +120,29 @@ allocation_subNetwork->>user_demand: allocated user_demand->>basin: abstracted ``` -# Substance (tracer) concentration calculations +# Substance (tracer) concentrations + +::: {.callout-caution} +This is an unsupported experimental feature and is disabled by default. +We advise to use the [Delwaq coupling](@sec-waterquality) for tracer calculations. +If you're interested in using this experimental feature, please [contact us](/contact.qmd). +::: Ribasim can calculate concentrations of conservative tracers (i.e. substances that are non-reactive). It does so by calculating the mass transports by flows for each timestep, in the `update_cumulative_flows!` callback. -Specifically, for each Basin at each timestep we calculate: +Specifically, for each Basin at each timestep it calculates: -- all mass inflows (flow * source_concentration) given the edge inflows -- update the concentrations in the Basin based on the added storage (previous storage + inflows) -- all mass outflows (flow * basin_concentration_state) give the edge outflows +- all mass inflows ($flow * source\_concentration$) given the edge inflows +- update the concentrations in the Basin based on the added storage ($previous storage + inflows$) +- all mass outflows ($flow * basin\_concentration\_state$) give the edge outflows - update the concentrations in the Basin based on the current storage We thus keep track of both mass and concentration of substances for each Basin. Note that we have not added the substance mass to the states, and we assume that concentrations of flows are piecewise constant over a timestep. +This excludes the use of tracer injections. + +By default the following source tracers are enabled. -By default we calculate concentrations for the following source tracers. - Continuity (mass balance, fraction of all water sources, sum of all other source tracers) - Initial (fraction of initial storages) - LevelBoundary, FlowBoundary, UserDemand, Drainage, Precipitation (fraction of different boundaries) diff --git a/docs/guide/coupling.qmd b/docs/guide/coupling.qmd index 3e9d7a7d5..da2315b3e 100644 --- a/docs/guide/coupling.qmd +++ b/docs/guide/coupling.qmd @@ -6,7 +6,7 @@ title: "Coupling" Ribasim can also be (online) coupled to other kernels with the help of iMOD Coupler. The corresponding documentation can be found within the [iMOD Suite Documentation](https://deltares.github.io/iMOD-Documentation/coupler.html). -# Water quality +# Water quality {#sec-waterquality} Ribasim can be offline coupled to Delwaq, the Deltares Water Quality model. diff --git a/docs/reference/usage.qmd b/docs/reference/usage.qmd index 3a4d782ee..63eeedd99 100644 --- a/docs/reference/usage.qmd +++ b/docs/reference/usage.qmd @@ -80,6 +80,23 @@ entry | type | description ----------------- | ------ | ----------- verbosity | String | Verbosity level: debug, info, warn, or error. +## Experimental features + +::: {.callout-important} +Experimental features are completely unsupported. They can break at any time +and results will be wrong. **Do not use them in production**. If you're interested +in using an experimental feature, please [contact us](/contact.qmd). +::: + +One can enable experimental features in the `[experimental]` section. +Currently the following features can be enabled (all are disabled by default). + +entry | type | description +----------------- | ------ | ----------- +concentration | Bool | Whether to enable tracer calculations or not. + + + # GeoPackage database and Arrow tables {#sec-geopackage} The input and output tables described below all share that they are tabular files. The Node diff --git a/python/ribasim/ribasim/config.py b/python/ribasim/ribasim/config.py index e426cf82f..78a59e85e 100644 --- a/python/ribasim/ribasim/config.py +++ b/python/ribasim/ribasim/config.py @@ -144,6 +144,19 @@ class Logging(ChildModel): verbosity: Verbosity = Verbosity.info +class Experimental(ChildModel): + """ + Defines experimental features. + + Attributes + ---------- + concentration : bool + Whether to enable tracer support (default is False) + """ + + concentration: bool = False + + class Node(pydantic.BaseModel): """ Defines a node for the model. diff --git a/python/ribasim/ribasim/model.py b/python/ribasim/ribasim/model.py index d5ab0a785..d7274a67c 100644 --- a/python/ribasim/ribasim/model.py +++ b/python/ribasim/ribasim/model.py @@ -26,6 +26,7 @@ Basin, ContinuousControl, DiscreteControl, + Experimental, FlowBoundary, FlowDemand, LevelBoundary, @@ -86,6 +87,8 @@ class Model(FileModel): allocation: Allocation = Field(default_factory=Allocation) + experimental: Experimental = Field(default_factory=Experimental) + basin: Basin = Field(default_factory=Basin) continuous_control: ContinuousControl = Field(default_factory=ContinuousControl) discrete_control: DiscreteControl = Field(default_factory=DiscreteControl)