diff --git a/.github/workflows/core_testmodels.yml b/.github/workflows/core_testmodels.yml
index 9679cbbf8..91d5f6e3f 100644
--- a/.github/workflows/core_testmodels.yml
+++ b/.github/workflows/core_testmodels.yml
@@ -29,7 +29,7 @@ jobs:
- x64
steps:
- uses: actions/checkout@v4
- - uses: julia-actions/cache@v1
+ - uses: julia-actions/cache@v2
with:
cache-compiled: "true"
cache-registries: "true"
diff --git a/.github/workflows/core_tests.yml b/.github/workflows/core_tests.yml
index 2ba330004..921469bc4 100644
--- a/.github/workflows/core_tests.yml
+++ b/.github/workflows/core_tests.yml
@@ -29,7 +29,7 @@ jobs:
- x64
steps:
- uses: actions/checkout@v4
- - uses: julia-actions/cache@v1
+ - uses: julia-actions/cache@v2
with:
cache-compiled: "true"
cache-registries: "true"
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index ccd50d8e5..45bb7d427 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -20,7 +20,7 @@ jobs:
contents: write
steps:
- uses: actions/checkout@v4
- - uses: julia-actions/cache@v1
+ - uses: julia-actions/cache@v2
with:
cache-compiled: "true"
cache-registries: "true"
@@ -33,9 +33,6 @@ jobs:
- name: Check Quarto installation and all engines
run: pixi run quarto-check
- - name: Generate Julia docs
- run: pixi run build-julia-docs
-
- name: Render Quarto Project
run: pixi run quarto-render
diff --git a/.gitignore b/.gitignore
index 5e8b06ffc..7e2d4e441 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,10 +5,6 @@
# Files generated by invoking Julia with --track-allocation
*.jl.mem
-# Build artifacts for creating documentation generated by the Documenter package
-docs/build/
-docs/site/
-
/generated_testmodels
build/ribasim/
build/cli/target
diff --git a/.teamcity/Ribasim_Linux/buildTypes/Ribasim_Linux_TestRibasimBinaries.xml b/.teamcity/Ribasim_Linux/buildTypes/Ribasim_Linux_TestRibasimBinaries.xml
index a49348465..c8c7e38e7 100644
--- a/.teamcity/Ribasim_Linux/buildTypes/Ribasim_Linux_TestRibasimBinaries.xml
+++ b/.teamcity/Ribasim_Linux/buildTypes/Ribasim_Linux_TestRibasimBinaries.xml
@@ -16,8 +16,7 @@
source /usr/share/Modules/init/bash
module load pixi
-pixi --version
-pixi run install-python]]>
+pixi --version]]>
@@ -30,7 +29,6 @@ pixi run install-python]]>
source /usr/share/Modules/init/bash
module load pixi
-pixi run --environment=dev install
pixi run test-ribasim-api
pixi run test-ribasim-cli]]>
diff --git a/.teamcity/Ribasim_Windows/buildTypes/Ribasim_Windows_TestRibasimBinaries.xml b/.teamcity/Ribasim_Windows/buildTypes/Ribasim_Windows_TestRibasimBinaries.xml
index 23a1e8ca0..86e53b375 100644
--- a/.teamcity/Ribasim_Windows/buildTypes/Ribasim_Windows_TestRibasimBinaries.xml
+++ b/.teamcity/Ribasim_Windows/buildTypes/Ribasim_Windows_TestRibasimBinaries.xml
@@ -10,7 +10,7 @@
-
+
@@ -18,8 +18,7 @@
-
diff --git a/Manifest.toml b/Manifest.toml
index cdb214bc6..5ca38ecd5 100644
--- a/Manifest.toml
+++ b/Manifest.toml
@@ -2,18 +2,13 @@
julia_version = "1.10.3"
manifest_format = "2.0"
-project_hash = "045162196d64ccb59bdab2af0422fde0b0e83c77"
+project_hash = "dc6d536cc58558be9be8b5e2e4d511d0451ed14f"
[[deps.ADTypes]]
git-tree-sha1 = "016833eb52ba2d6bea9fcb50ca295980e728ee24"
uuid = "47edcb42-4c32-4615-8424-f2b9edc5f35b"
version = "0.2.7"
-[[deps.ANSIColoredPrinters]]
-git-tree-sha1 = "574baf8110975760d391c710b6341da1afa48d8c"
-uuid = "a4c015fc-c6ff-483c-b24f-f7ea428134e9"
-version = "0.0.1"
-
[[deps.AbstractTrees]]
git-tree-sha1 = "2d9c9a55f9c93e8887ad391fbae72f8ef55e1177"
uuid = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
@@ -438,18 +433,6 @@ git-tree-sha1 = "2fb1e02f2b635d0845df5d7c167fec4dd739b00d"
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
version = "0.9.3"
-[[deps.Documenter]]
-deps = ["ANSIColoredPrinters", "Base64", "Dates", "DocStringExtensions", "IOCapture", "InteractiveUtils", "JSON", "LibGit2", "Logging", "Markdown", "REPL", "Test", "Unicode"]
-git-tree-sha1 = "39fd748a73dce4c05a9655475e437170d8fb1b67"
-uuid = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
-version = "0.27.25"
-
-[[deps.DocumenterMarkdown]]
-deps = ["Documenter"]
-git-tree-sha1 = "9af057a98652336e30586d8092fac06f8b28ecdc"
-uuid = "997ab1e6-3595-5248-9280-8efb232c3433"
-version = "0.2.2"
-
[[deps.Downloads]]
deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"]
uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
@@ -498,9 +481,9 @@ version = "0.3.2"
[[deps.FastLapackInterface]]
deps = ["LinearAlgebra"]
-git-tree-sha1 = "0a59c7d1002f3131de53dc4568a47d15a44daef7"
+git-tree-sha1 = "f4102aab9c7df8691ed09f9c42e34f5ab5458ab9"
uuid = "29a986be-02c6-4525-aec4-84b980013641"
-version = "2.0.2"
+version = "2.0.3"
[[deps.FileIO]]
deps = ["Pkg", "Requires", "UUIDs"]
@@ -626,12 +609,6 @@ git-tree-sha1 = "47ac8cc196b81001a711f4b2c12c97372338f00c"
uuid = "7073ff75-c697-5162-941a-fcdaad2a7d2a"
version = "1.24.2"
-[[deps.IOCapture]]
-deps = ["Logging", "Random"]
-git-tree-sha1 = "8b72179abc660bfab5e28472e019392b97d0985c"
-uuid = "b5f81e59-6552-4d32-b1f0-c071b021bf89"
-version = "0.2.4"
-
[[deps.IfElse]]
git-tree-sha1 = "debdd00ffef04665ccbb3e150747a77560e8fad1"
uuid = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173"
@@ -753,9 +730,9 @@ version = "0.6.0"
[[deps.Krylov]]
deps = ["LinearAlgebra", "Printf", "SparseArrays"]
-git-tree-sha1 = "8a6837ec02fe5fb3def1abc907bb802ef11a0729"
+git-tree-sha1 = "267dad6b4b7b5d529c76d40ff48d33f7e94cb834"
uuid = "ba0b0d4f-ebba-5204-a429-3ac8c609bfb7"
-version = "0.9.5"
+version = "0.9.6"
[[deps.LaTeXStrings]]
git-tree-sha1 = "50901ebc375ed41dbf8058da26f9de442febbbec"
@@ -1211,9 +1188,9 @@ version = "1.3.4"
[[deps.RecursiveArrayTools]]
deps = ["Adapt", "ArrayInterface", "DocStringExtensions", "GPUArraysCore", "IteratorInterfaceExtensions", "LinearAlgebra", "RecipesBase", "SparseArrays", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "Tables"]
-git-tree-sha1 = "d8f131090f2e44b145084928856a561c83f43b27"
+git-tree-sha1 = "6305b6fe0391eeb4f280a4a403ac0c350b82c718"
uuid = "731186ca-8d62-57ce-b412-fbd966d074cd"
-version = "3.13.0"
+version = "3.15.0"
[deps.RecursiveArrayTools.extensions]
RecursiveArrayToolsFastBroadcastExt = "FastBroadcast"
@@ -1303,9 +1280,9 @@ version = "3.45.0+0"
[[deps.SciMLBase]]
deps = ["ADTypes", "ArrayInterface", "CommonSolve", "ConstructionBase", "Distributed", "DocStringExtensions", "EnumX", "FunctionWrappersWrappers", "IteratorInterfaceExtensions", "LinearAlgebra", "Logging", "Markdown", "PrecompileTools", "Preferences", "Printf", "RecipesBase", "RecursiveArrayTools", "Reexport", "RuntimeGeneratedFunctions", "SciMLOperators", "SciMLStructures", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "Tables"]
-git-tree-sha1 = "beb1f94b08c4976ed1db0ca01b9e6bac89706faf"
+git-tree-sha1 = "397367599b9526a49cc06a4db70835807498b561"
uuid = "0bca4576-84f4-4d90-8ffe-ffa030f20462"
-version = "2.35.0"
+version = "2.36.1"
[deps.SciMLBase.extensions]
SciMLBaseChainRulesCoreExt = "ChainRulesCore"
@@ -1530,10 +1507,10 @@ uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c"
version = "7.2.1+1"
[[deps.SymbolicIndexingInterface]]
-deps = ["Accessors", "ArrayInterface", "MacroTools", "RuntimeGeneratedFunctions", "StaticArraysCore"]
-git-tree-sha1 = "7a7be02e16d11c17e2407bab80c2dd1410f774cb"
+deps = ["Accessors", "ArrayInterface", "RuntimeGeneratedFunctions", "StaticArraysCore"]
+git-tree-sha1 = "b479c7a16803f08779ac5b7f9844a42621baeeda"
uuid = "2efcf032-c050-4f8e-a9bb-153293bab1f5"
-version = "0.3.17"
+version = "0.3.21"
[[deps.TOML]]
deps = ["Dates"]
diff --git a/Project.toml b/Project.toml
index 3b2e47a5b..97269cbb7 100644
--- a/Project.toml
+++ b/Project.toml
@@ -17,8 +17,6 @@ DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Dictionaries = "85a47980-9c8c-11e8-2b9f-f7ca1fa99fb4"
DiffEqCallbacks = "459566f4-90b8-5000-8ac3-15dfb0a30def"
-Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
-DocumenterMarkdown = "997ab1e6-3595-5248-9280-8efb232c3433"
EnumX = "4e289a0a-7415-4d19-859d-a7e5c4648b56"
FiniteDiff = "6a86dc24-6348-571c-b903-95158fe2bd41"
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
diff --git a/core/Project.toml b/core/Project.toml
index 4d7b647a2..1a9fb12e3 100644
--- a/core/Project.toml
+++ b/core/Project.toml
@@ -56,7 +56,6 @@ DataStructures = "0.18"
Dates = "<0.0.1,1"
Dictionaries = "0.3.25, 0.4"
DiffEqCallbacks = "3.6"
-Documenter = "0.27,1"
EnumX = "1.0"
FiniteDiff = "2.21"
ForwardDiff = "0.10"
@@ -74,7 +73,7 @@ OrdinaryDiffEq = "6.7"
PreallocationTools = "0.4"
ReTestItems = "1.20"
SQLite = "1.5.1"
-SciMLBase = "1.60, 2"
+SciMLBase = "2.36"
SparseArrays = "<0.0.1,1"
StructArrays = "0.6.13"
TOML = "<0.0.1,1"
@@ -89,7 +88,6 @@ julia = "1.10"
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
-Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
IOCapture = "b5f81e59-6552-4d32-b1f0-c071b021bf89"
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
ReTestItems = "817f1d60-ba6b-4fd5-9520-3cf149f6a823"
@@ -111,4 +109,4 @@ PrecompileNonStiff = false
PrecompileStiff = false
[targets]
-test = ["Aqua", "CSV", "DataFrames", "Documenter", "IOCapture", "Logging", "ReTestItems", "TerminalLoggers", "Test", "TOML"]
+test = ["Aqua", "CSV", "DataFrames", "IOCapture", "Logging", "ReTestItems", "TerminalLoggers", "Test", "TOML"]
diff --git a/core/src/Ribasim.jl b/core/src/Ribasim.jl
index f8d027f63..a761c4b34 100644
--- a/core/src/Ribasim.jl
+++ b/core/src/Ribasim.jl
@@ -55,6 +55,7 @@ using SciMLBase:
init,
solve!,
step!,
+ check_error!,
SciMLBase,
ReturnCode,
successful_retcode,
diff --git a/core/src/model.jl b/core/src/model.jl
index 602503dd6..dec8c6480 100644
--- a/core/src/model.jl
+++ b/core/src/model.jl
@@ -229,12 +229,7 @@ function SciMLBase.solve!(model::Model)::Model
update_allocation!(integrator)
step!(integrator, timestep, true)
end
-
- if integrator.sol.retcode != ReturnCode.Default
- return model
- end
- # TODO replace with `check_error!` https://github.com/SciML/SciMLBase.jl/issues/669
- integrator.sol = SciMLBase.solution_new_retcode(integrator.sol, ReturnCode.Success)
+ check_error!(integrator)
else
solve!(integrator)
end
diff --git a/core/src/schema.jl b/core/src/schema.jl
index 9ca14f9c6..1b6c8b42d 100644
--- a/core/src/schema.jl
+++ b/core/src/schema.jl
@@ -8,12 +8,17 @@
@schema "ribasim.basin.profile" BasinProfile
@schema "ribasim.basin.state" BasinState
@schema "ribasim.basin.subgrid" BasinSubgrid
+@schema "ribasim.basin.concentration" BasinConcentration
+@schema "ribasim.basin.concentrationexternal" BasinConcentrationExternal
+@schema "ribasim.basin.concentrationstate" BasinConcentrationState
@schema "ribasim.terminal.static" TerminalStatic
@schema "ribasim.fractionalflow.static" FractionalFlowStatic
@schema "ribasim.flowboundary.static" FlowBoundaryStatic
@schema "ribasim.flowboundary.time" FlowBoundaryTime
+@schema "ribasim.flowboundary.concentration" FlowBoundaryConcentration
@schema "ribasim.levelboundary.static" LevelBoundaryStatic
@schema "ribasim.levelboundary.time" LevelBoundaryTime
+@schema "ribasim.levelboundary.concentration" LevelBoundaryConcentration
@schema "ribasim.linearresistance.static" LinearResistanceStatic
@schema "ribasim.manningresistance.static" ManningResistanceStatic
@schema "ribasim.pidcontrol.static" PidControlStatic
@@ -99,6 +104,21 @@ end
urban_runoff::Union{Missing, Float64}
end
+@version BasinConcentrationV1 begin
+ node_id::Int32
+ time::DateTime
+ substance::String
+ drainage::Union{Missing, Float64}
+ precipitation::Union{Missing, Float64}
+end
+
+@version BasinConcentrationExternalV1 begin
+ node_id::Int32
+ time::DateTime
+ substance::String
+ concentration::Union{Missing, Float64}
+end
+
@version BasinProfileV1 begin
node_id::Int32
area::Float64
@@ -110,6 +130,12 @@ end
level::Float64
end
+@version BasinConcentrationStateV1 begin
+ node_id::Int32
+ substance::String
+ concentration::Union{Missing, Float64}
+end
+
@version BasinSubgridV1 begin
subgrid_id::Int32
node_id::Int32
@@ -135,6 +161,13 @@ end
level::Float64
end
+@version LevelBoundaryConcentrationV1 begin
+ node_id::Int32
+ time::DateTime
+ substance::String
+ concentration::Float64
+end
+
@version FlowBoundaryStaticV1 begin
node_id::Int32
active::Union{Missing, Bool}
@@ -147,6 +180,13 @@ end
flow_rate::Float64
end
+@version FlowBoundaryConcentrationV1 begin
+ node_id::Int32
+ time::DateTime
+ substance::String
+ concentration::Float64
+end
+
@version LinearResistanceStaticV1 begin
node_id::Int32
active::Union{Missing, Bool}
diff --git a/core/test/docs_test.jl b/core/test/docs_test.jl
deleted file mode 100644
index 1f2e78f8c..000000000
--- a/core/test/docs_test.jl
+++ /dev/null
@@ -1,7 +0,0 @@
-@testitem "Doctests" begin
- using Documenter
-
- DocMeta.setdocmeta!(Ribasim, :DocTestSetup, :(using Ribasim); recursive = true)
-
- doctest(Ribasim; manual = false)
-end
diff --git a/docs/.gitignore b/docs/.gitignore
index 0c28493e0..c8f1e55fb 100644
--- a/docs/.gitignore
+++ b/docs/.gitignore
@@ -4,5 +4,4 @@
python/reference/
python/data/
*.html
-/Manifest.toml
objects.json
diff --git a/docs/_quarto.yml b/docs/_quarto.yml
index e3cd0e3e5..b360503d7 100644
--- a/docs/_quarto.yml
+++ b/docs/_quarto.yml
@@ -32,7 +32,6 @@ website:
- core/equations.qmd
- core/allocation.qmd
- core/numerics.qmd
- - build/index.md
- title: "Python tooling"
contents:
- python/index.qmd
diff --git a/docs/contribute/core.qmd b/docs/contribute/core.qmd
index ef4e52fc3..35485aff0 100644
--- a/docs/contribute/core.qmd
+++ b/docs/contribute/core.qmd
@@ -75,11 +75,6 @@ The first run will be slow.
## Render documentation
Example models are created and simulated as part of the rendering of the documentation.
-The Julia API reference is created using Documenter.jl by running this command:
-
-```bash
-pixi run build-julia-docs
-```
In order to preview documentation you can run the following command from the `docs/` folder.
Afterwards, a browser tab will open with the rendered documentation, updating it as you
diff --git a/docs/make.jl b/docs/make.jl
deleted file mode 100644
index 07942b191..000000000
--- a/docs/make.jl
+++ /dev/null
@@ -1,17 +0,0 @@
-cd(@__DIR__)
-
-using Documenter, Ribasim
-using DocumenterMarkdown
-
-DocMeta.setdocmeta!(Ribasim, :DocTestSetup, :(using Ribasim); recursive = true)
-
-makedocs(;
- modules = [Ribasim, Ribasim.config],
- format = Markdown(),
- repo = "https://github.com/Deltares/Ribasim.jl/blob/{commit}{path}#L{line}",
- sitename = "Ribasim.jl",
- authors = "Deltares and contributors",
- doctest = false, # we doctest as part of normal CI
-)
-
-# TODO Make fully compatible with Quarto, like LaTeX and references
diff --git a/docs/src/index.md b/docs/src/index.md
deleted file mode 100644
index dc071f5c4..000000000
--- a/docs/src/index.md
+++ /dev/null
@@ -1,45 +0,0 @@
-# API Reference
-*This is the private internal documentation of the Ribasim API.*
-
-```@contents
-```
-
-## Modules
-
-```@autodocs
-Modules = [Ribasim, Ribasim.config]
-Order = [:module]
-```
-
-## Types
-
-```@autodocs
-Modules = [Ribasim, Ribasim.config]
-Order = [:type]
-```
-
-## Functions
-
-```@autodocs
-Modules = [Ribasim, Ribasim.config]
-Order = [:function]
-```
-
-## Constants
-
-```@autodocs
-Modules = [Ribasim, Ribasim.config]
-Order = [:constant]
-```
-
-## Macros
-
-```@autodocs
-Modules = [Ribasim, Ribasim.config]
-Order = [:macro]
-```
-
-## Index
-
-```@index
-```
diff --git a/python/ribasim/ribasim/config.py b/python/ribasim/ribasim/config.py
index d36416862..9572db9c2 100644
--- a/python/ribasim/ribasim/config.py
+++ b/python/ribasim/ribasim/config.py
@@ -16,6 +16,9 @@
# These schemas are autogenerated
from ribasim.schemas import (
+ BasinConcentrationExternalSchema,
+ BasinConcentrationSchema,
+ BasinConcentrationStateSchema,
BasinProfileSchema,
BasinStateSchema,
BasinStaticSchema,
@@ -24,11 +27,13 @@
DiscreteControlConditionSchema,
DiscreteControlLogicSchema,
DiscreteControlVariableSchema,
+ FlowBoundaryConcentrationSchema,
FlowBoundaryStaticSchema,
FlowBoundaryTimeSchema,
FlowDemandStaticSchema,
FlowDemandTimeSchema,
FractionalFlowStaticSchema,
+ LevelBoundaryConcentrationSchema,
LevelBoundaryStaticSchema,
LevelBoundaryTimeSchema,
LevelDemandStaticSchema,
@@ -189,6 +194,10 @@ class LevelBoundary(MultiNodeModel):
default_factory=TableModel[LevelBoundaryTimeSchema],
json_schema_extra={"sort_keys": ["node_id", "time"]},
)
+ concentration: TableModel[LevelBoundaryConcentrationSchema] = Field(
+ default_factory=TableModel[LevelBoundaryConcentrationSchema],
+ json_schema_extra={"sort_keys": ["node_id", "substance", "time"]},
+ )
class Pump(MultiNodeModel):
@@ -240,6 +249,10 @@ class FlowBoundary(MultiNodeModel):
default_factory=TableModel[FlowBoundaryTimeSchema],
json_schema_extra={"sort_keys": ["node_id", "time"]},
)
+ concentration: TableModel[FlowBoundaryConcentrationSchema] = Field(
+ default_factory=TableModel[FlowBoundaryConcentrationSchema],
+ json_schema_extra={"sort_keys": ["node_id", "substance", "time"]},
+ )
class FlowDemand(MultiNodeModel):
@@ -278,6 +291,18 @@ class Basin(MultiNodeModel):
default_factory=SpatialTableModel[BasinAreaSchema],
json_schema_extra={"sort_keys": ["node_id"]},
)
+ concentration: TableModel[BasinConcentrationSchema] = Field(
+ default_factory=TableModel[BasinConcentrationSchema],
+ json_schema_extra={"sort_keys": ["node_id", "substance", "time"]},
+ )
+ concentration_external: TableModel[BasinConcentrationExternalSchema] = Field(
+ default_factory=TableModel[BasinConcentrationExternalSchema],
+ json_schema_extra={"sort_keys": ["node_id", "substance", "time"]},
+ )
+ concentration_state: TableModel[BasinConcentrationStateSchema] = Field(
+ default_factory=TableModel[BasinConcentrationStateSchema],
+ json_schema_extra={"sort_keys": ["node_id", "substance"]},
+ )
class ManningResistance(MultiNodeModel):
diff --git a/python/ribasim/ribasim/nodes/basin.py b/python/ribasim/ribasim/nodes/basin.py
index 0e529cdc1..f155f848b 100644
--- a/python/ribasim/ribasim/nodes/basin.py
+++ b/python/ribasim/ribasim/nodes/basin.py
@@ -4,6 +4,9 @@
from ribasim.geometry.area import BasinAreaSchema
from ribasim.input_base import TableModel
from ribasim.schemas import (
+ BasinConcentrationExternalSchema,
+ BasinConcentrationSchema,
+ BasinConcentrationStateSchema,
BasinProfileSchema,
BasinStateSchema,
BasinStaticSchema,
@@ -11,7 +14,15 @@
BasinTimeSchema,
)
-__all__ = ["Static", "Time", "State", "Profile", "Subgrid", "Area"]
+__all__ = [
+ "Static",
+ "Time",
+ "State",
+ "Profile",
+ "Subgrid",
+ "Area",
+ "Concentration",
+]
class Static(TableModel[BasinStaticSchema]):
@@ -42,3 +53,18 @@ def __init__(self, **kwargs):
class Area(TableModel[BasinAreaSchema]):
def __init__(self, **kwargs):
super().__init__(df=GeoDataFrame(dict(**kwargs)))
+
+
+class Concentration(TableModel[BasinConcentrationSchema]):
+ def __init__(self, **kwargs):
+ super().__init__(df=GeoDataFrame(dict(**kwargs)))
+
+
+class ConcentrationExternal(TableModel[BasinConcentrationExternalSchema]):
+ def __init__(self, **kwargs):
+ super().__init__(df=GeoDataFrame(dict(**kwargs)))
+
+
+class ConcentrationState(TableModel[BasinConcentrationStateSchema]):
+ def __init__(self, **kwargs):
+ super().__init__(df=GeoDataFrame(dict(**kwargs)))
diff --git a/python/ribasim/ribasim/nodes/flow_boundary.py b/python/ribasim/ribasim/nodes/flow_boundary.py
index 12ec8c028..096652f6f 100644
--- a/python/ribasim/ribasim/nodes/flow_boundary.py
+++ b/python/ribasim/ribasim/nodes/flow_boundary.py
@@ -2,11 +2,12 @@
from ribasim.input_base import TableModel
from ribasim.schemas import (
+ FlowBoundaryConcentrationSchema,
FlowBoundaryStaticSchema,
FlowBoundaryTimeSchema,
)
-__all__ = ["Static", "Time"]
+__all__ = ["Static", "Time", "Concentration"]
class Static(TableModel[FlowBoundaryStaticSchema]):
@@ -17,3 +18,8 @@ def __init__(self, **kwargs):
class Time(TableModel[FlowBoundaryTimeSchema]):
def __init__(self, **kwargs):
super().__init__(df=DataFrame(dict(**kwargs)))
+
+
+class Concentration(TableModel[FlowBoundaryConcentrationSchema]):
+ def __init__(self, **kwargs):
+ super().__init__(df=DataFrame(dict(**kwargs)))
diff --git a/python/ribasim/ribasim/nodes/level_boundary.py b/python/ribasim/ribasim/nodes/level_boundary.py
index da23c3c61..1fb9d5d81 100644
--- a/python/ribasim/ribasim/nodes/level_boundary.py
+++ b/python/ribasim/ribasim/nodes/level_boundary.py
@@ -2,11 +2,12 @@
from ribasim.input_base import TableModel
from ribasim.schemas import (
+ LevelBoundaryConcentrationSchema,
LevelBoundaryStaticSchema,
LevelBoundaryTimeSchema,
)
-__all__ = ["Static", "Time"]
+__all__ = ["Static", "Time", "Concentration"]
class Static(TableModel[LevelBoundaryStaticSchema]):
@@ -17,3 +18,8 @@ def __init__(self, **kwargs):
class Time(TableModel[LevelBoundaryTimeSchema]):
def __init__(self, **kwargs):
super().__init__(df=DataFrame(dict(**kwargs)))
+
+
+class Concentration(TableModel[LevelBoundaryConcentrationSchema]):
+ def __init__(self, **kwargs):
+ super().__init__(df=DataFrame(dict(**kwargs)))
diff --git a/python/ribasim/ribasim/schemas.py b/python/ribasim/ribasim/schemas.py
index 40f0e0a38..3686b2398 100644
--- a/python/ribasim/ribasim/schemas.py
+++ b/python/ribasim/ribasim/schemas.py
@@ -11,6 +11,27 @@ class Config:
coerce = True
+class BasinConcentrationExternalSchema(_BaseSchema):
+ node_id: Series[Int32] = pa.Field(nullable=False, default=0)
+ time: Series[Timestamp] = pa.Field(nullable=False)
+ substance: Series[str] = pa.Field(nullable=False)
+ concentration: Series[float] = pa.Field(nullable=True)
+
+
+class BasinConcentrationStateSchema(_BaseSchema):
+ node_id: Series[Int32] = pa.Field(nullable=False, default=0)
+ substance: Series[str] = pa.Field(nullable=False)
+ concentration: Series[float] = pa.Field(nullable=True)
+
+
+class BasinConcentrationSchema(_BaseSchema):
+ node_id: Series[Int32] = pa.Field(nullable=False, default=0)
+ time: Series[Timestamp] = pa.Field(nullable=False)
+ substance: Series[str] = pa.Field(nullable=False)
+ drainage: Series[float] = pa.Field(nullable=True)
+ precipitation: Series[float] = pa.Field(nullable=True)
+
+
class BasinProfileSchema(_BaseSchema):
node_id: Series[Int32] = pa.Field(nullable=False, default=0)
area: Series[float] = pa.Field(nullable=False)
@@ -70,6 +91,13 @@ class DiscreteControlVariableSchema(_BaseSchema):
look_ahead: Series[float] = pa.Field(nullable=True)
+class FlowBoundaryConcentrationSchema(_BaseSchema):
+ node_id: Series[Int32] = pa.Field(nullable=False, default=0)
+ time: Series[Timestamp] = pa.Field(nullable=False)
+ substance: Series[str] = pa.Field(nullable=False)
+ concentration: Series[float] = pa.Field(nullable=False)
+
+
class FlowBoundaryStaticSchema(_BaseSchema):
node_id: Series[Int32] = pa.Field(nullable=False, default=0)
active: Series[pa.BOOL] = pa.Field(nullable=True)
@@ -101,6 +129,13 @@ class FractionalFlowStaticSchema(_BaseSchema):
control_state: Series[str] = pa.Field(nullable=True)
+class LevelBoundaryConcentrationSchema(_BaseSchema):
+ node_id: Series[Int32] = pa.Field(nullable=False, default=0)
+ time: Series[Timestamp] = pa.Field(nullable=False)
+ substance: Series[str] = pa.Field(nullable=False)
+ concentration: Series[float] = pa.Field(nullable=False)
+
+
class LevelBoundaryStaticSchema(_BaseSchema):
node_id: Series[Int32] = pa.Field(nullable=False, default=0)
active: Series[pa.BOOL] = pa.Field(nullable=True)
diff --git a/python/ribasim_testmodels/ribasim_testmodels/basic.py b/python/ribasim_testmodels/ribasim_testmodels/basic.py
index 3fe92ebf8..48f857199 100644
--- a/python/ribasim_testmodels/ribasim_testmodels/basic.py
+++ b/python/ribasim_testmodels/ribasim_testmodels/basic.py
@@ -1,3 +1,4 @@
+from collections.abc import Sequence
from pathlib import Path
from typing import Any
@@ -37,6 +38,16 @@ def basic_model() -> ribasim.Model:
potential_evaporation=[0.001 / 86400], precipitation=[0.002 / 86400]
),
basin.State(level=[0.04471158417652035]),
+ basin.Concentration(
+ time="2020-01-01 00:00:00",
+ substance=["Cl"],
+ drainage=[0.0],
+ precipitation=[0.0],
+ ),
+ basin.ConcentrationState(substance=["Cl"], concentration=[0.0]),
+ basin.ConcentrationExternal(
+ time="2020-01-01 00:00:00", substance=["Cl"], concentration=[0.0]
+ ),
]
node_ids = [1, 3, 6, 9]
node_geometries = [
@@ -107,16 +118,33 @@ def basic_model() -> ribasim.Model:
model.pump.add(Node(7, Point(4.0, 1.0)), [pump.Static(flow_rate=[0.5 / 3600])])
# Setup flow boundary
- flow_boundary_data = [flow_boundary.Static(flow_rate=[1e-4])]
+ flow_boundary_data: Sequence[TableModel[Any]] = [
+ flow_boundary.Static(flow_rate=[1e-4]),
+ flow_boundary.Concentration(
+ time="2020-01-01 00:00:00", substance=["Tracer"], concentration=[1.0]
+ ),
+ ]
model.flow_boundary.add(Node(15, Point(3.0, 3.0)), flow_boundary_data)
model.flow_boundary.add(Node(16, Point(0.0, 1.0)), flow_boundary_data)
# Setup level boundary
model.level_boundary.add(
- Node(11, Point(2.0, 2.0)), [level_boundary.Static(level=[1.0])]
+ Node(11, Point(2.0, 2.0)),
+ [
+ level_boundary.Static(level=[1.0]),
+ level_boundary.Concentration(
+ time="2020-01-01 00:00:00", substance=["Cl"], concentration=[34.0]
+ ),
+ ],
)
model.level_boundary.add(
- Node(17, Point(6.0, 1.0)), [level_boundary.Static(level=[1.5])]
+ Node(17, Point(6.0, 1.0)),
+ [
+ level_boundary.Static(level=[1.5]),
+ level_boundary.Concentration(
+ time="2020-01-01 00:00:00", substance=["Cl"], concentration=[34.0]
+ ),
+ ],
)
# Setup terminal
@@ -340,9 +368,9 @@ def outlet_model():
[
level_boundary.Time(
time=[
- "2020-01-01",
- "2020-06-01",
- "2021-01-01",
+ "2020-01-01 00:00:00",
+ "2020-06-01 00:00:00",
+ "2021-01-01 00:00:00",
],
level=[1.0, 3.0, 3.0],
)
diff --git a/ribasim_qgis/metadata.txt b/ribasim_qgis/metadata.txt
index 1478f2aad..9363b34f2 100644
--- a/ribasim_qgis/metadata.txt
+++ b/ribasim_qgis/metadata.txt
@@ -4,7 +4,7 @@
# This file should be included when you package your plugin.# Mandatory items:
[general]
-name=Ribasim-QGIS
+name=Ribasim
qgisMinimumVersion=3.0
description=QGIS plugin to setup Ribasim models
version=2024.7.0