Skip to content

Commit

Permalink
Validate Pump min_upstream_level (#1802)
Browse files Browse the repository at this point in the history
This is like #1607, but now
running the same validation for Pump instead of only Outlet, because
Pump now also supports `min_upstream_level`.
  • Loading branch information
visr authored Sep 9, 2024
1 parent 104e738 commit 6347146
Show file tree
Hide file tree
Showing 7 changed files with 27 additions and 22 deletions.
12 changes: 8 additions & 4 deletions core/src/model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,21 @@ function Model(config::Config)::Model
error("Invalid discrete control state definition(s).")
end

(; pid_control, graph, outlet, basin, tabulated_rating_curve) = parameters
(; pid_control, graph, outlet, pump, basin, tabulated_rating_curve) = parameters
if !valid_pid_connectivity(pid_control.node_id, pid_control.listen_node_id, graph)
error("Invalid PidControl connectivity.")
end

if !valid_outlet_crest_level!(graph, outlet, basin)
error("Invalid minimum crest level of outlet")
if !valid_min_upstream_level!(graph, outlet, basin)
error("Invalid minimum upstream level of Outlet.")
end

if !valid_min_upstream_level!(graph, pump, basin)
error("Invalid minimum upstream level of Pump.")
end

if !valid_tabulated_curve_level(graph, tabulated_rating_curve, basin)
error("Invalid level of tabulated rating curve")
error("Invalid level of TabulatedRatingCurve.")
end

# tell the solver to stop when new data comes in
Expand Down
18 changes: 11 additions & 7 deletions core/src/validation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -357,18 +357,22 @@ function valid_demand(
end

"""
Validate Outlet crest level and fill in default values
Validate Outlet or Pump `min_upstream_level` and fill in default values
"""
function valid_outlet_crest_level!(graph::MetaGraph, outlet::Outlet, basin::Basin)::Bool
function valid_min_upstream_level!(
graph::MetaGraph,
node::Union{Outlet, Pump},
basin::Basin,
)::Bool
errors = false
for (id, crest) in zip(outlet.node_id, outlet.min_upstream_level)
for (id, min_upstream_level) in zip(node.node_id, node.min_upstream_level)
id_in = inflow_id(graph, id)
if id_in.type == NodeType.Basin
basin_bottom_level = basin_bottom(basin, id_in)[2]
if crest == -Inf
outlet.min_upstream_level[id.idx] = basin_bottom_level
elseif crest < basin_bottom_level
@error "Minimum crest level of $id is lower than bottom of upstream $id_in" crest basin_bottom_level
if min_upstream_level == -Inf
node.min_upstream_level[id.idx] = basin_bottom_level
elseif min_upstream_level < basin_bottom_level
@error "Minimum upstream level of $id is lower than bottom of upstream $id_in" min_upstream_level basin_bottom_level
errors = true
end
end
Expand Down
2 changes: 1 addition & 1 deletion core/test/run_models_test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ end
t_min_upstream_level =
level.t[2] * (outlet.min_upstream_level[1] - level.u[1]) / (level.u[2] - level.u[1])

# No outlet flow when upstream level is below minimum crest level
# No outlet flow when upstream level is below minimum upstream level
@test all(@. outlet_flow.flow_rate[t <= t_min_upstream_level] == 0)

t = Ribasim.tsaves(model)
Expand Down
6 changes: 3 additions & 3 deletions core/test/validation_test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ end
end

@testitem "Outlet upstream level validation" begin
using Ribasim: valid_outlet_crest_level!
using Ribasim: valid_min_upstream_level!
using Logging

toml_path = normpath(
Expand All @@ -422,13 +422,13 @@ end

logger = TestLogger()
with_logger(logger) do
@test !Ribasim.valid_outlet_crest_level!(graph, outlet, basin)
@test !Ribasim.valid_min_upstream_level!(graph, outlet, basin)
end

@test length(logger.logs) == 1
@test logger.logs[1].level == Error
@test logger.logs[1].message ==
"Minimum crest level of Outlet #4 is lower than bottom of upstream Basin #3"
"Minimum upstream level of Outlet #4 is lower than bottom of upstream Basin #3"
end

@testitem "Convergence bottleneck" begin
Expand Down
2 changes: 1 addition & 1 deletion docs/changelog.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ For this release we said goodbye to the problematic FractionalFlow node, but wel
- Control: Add ContinuousControl node type. #1602
- Control: Support listening to flow through connector nodes. #1594
- Validate that TabulatedRatingCurve levels are above Basin bottom. #1607
- Validate that Outlet crest levels are above Basin bottom. #1607
- Validate that Outlet minimum upstream levels are above Basin bottom. #1607
- Always show convergence bottlenecks. #1636
- Docstrings for Ribasim Python. #1643
- Allocate to UserDemand from directly connected Basin if possible. #1581
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/examples.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -1785,7 +1785,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"According to the description of situation 1 and 2, the water in one polder basin needs to be able to flow to the downstream basin if the current basin has too much water (i.e. the water level is above the setpoint) or if the downstream basin is below setpoint and needs more water. This could be modelled with an uncontrolled TabulatedRatingCurve node with Q=0 at the setpoint level (and Q rising when the level rises above setpoint) , or with an Outlet node where the minimum crest is specified at or just below the setpoint. In this example, we've chosen for the Outlet where we specify the minimum crest level 5 cm below the setpoint. For example: the Outlet of polder basin 1 (node 4) is specified with a minimum crest level of 1.95 meter."
"According to the description of situation 1 and 2, the water in one polder basin needs to be able to flow to the downstream basin if the current basin has too much water (i.e. the water level is above the setpoint) or if the downstream basin is below setpoint and needs more water. This could be modelled with an uncontrolled TabulatedRatingCurve node with Q=0 at the setpoint level (and Q rising when the level rises above setpoint) , or with an Outlet node where the `min_upstream_level` is specified at or just below the setpoint. In this example, we've chosen for the Outlet where we specify the minimum upstream level 5 cm below the setpoint. For example: the Outlet of polder basin 1 (node 4) is specified with a minimum upstream level of 1.95 meter."
]
},
{
Expand Down
7 changes: 2 additions & 5 deletions docs/reference/node/outlet.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@ title: "Outlet"
---

The Outlet lets water flow downstream with a prescribed flow rate.
It is similar to the Pump, with two additional physical constraints:
It is similar to the Pump, except that water only flows down, by gravity.

1. Water only flows down, by gravity
2. The upstream level must be above the minimum crest level if the upstream level is defined.

When PID controlled, the outlet must point towards the controlled basin in terms of edges.
When PID controlled, the Outlet must point towards the controlled Basin in terms of edges.

# Tables

Expand Down

0 comments on commit 6347146

Please sign in to comment.