Skip to content

Commit

Permalink
clamp reduction_factor and add it to TabulatedRatingCurve (#587)
Browse files Browse the repository at this point in the history
If the rating curve prescribes large Q even when the upstream Basin is
nearly empty, this leads to an incorrect water balance.

Replaces #562.
  • Loading branch information
visr authored Sep 12, 2023
1 parent 8b63f25 commit 9238b0c
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 8 deletions.
21 changes: 14 additions & 7 deletions core/src/solve.jl
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ function formulate!(
bottom = basin.level[i][1]
fixed_area = basin.area[i][end]
depth = max(level - bottom, 0.0)
reduction_factor = min(depth, 0.1) / 0.1
reduction_factor = clamp(depth, 0.0, 0.1) / 0.1

precipitation = fixed_area * basin.precipitation[i]
evaporation = area * reduction_factor * basin.potential_evaporation[i]
Expand Down Expand Up @@ -594,7 +594,7 @@ function continuous_control!(
controlled_node_idx = findsorted(pump.node_id, controlled_node_id)

listened_basin_storage = u.storage[listened_node_idx]
reduction_factor = min(listened_basin_storage, 10.0) / 10.0
reduction_factor = clamp(listened_basin_storage, 0.0, 10.0) / 10.0
else
controlled_node_idx = findsorted(outlet.node_id, controlled_node_id)

Expand All @@ -603,7 +603,7 @@ function continuous_control!(
has_index, upstream_basin_idx = id_index(basin.node_id, upstream_node_id)
if has_index
upstream_basin_storage = u.storage[upstream_basin_idx]
reduction_factor = min(upstream_basin_storage, 10.0) / 10.0
reduction_factor = clamp(upstream_basin_storage, 0.0, 10.0) / 10.0
else
reduction_factor = 1.0
end
Expand Down Expand Up @@ -736,19 +736,26 @@ Directed graph: outflow is positive!
function formulate_flow!(
tabulated_rating_curve::TabulatedRatingCurve,
p::Parameters,
storage::AbstractVector,
current_level::AbstractVector,
flow::AbstractMatrix,
t::Float64,
)::Nothing
(; connectivity) = p
(; basin, connectivity) = p
(; graph_flow) = connectivity
(; node_id, active, tables) = tabulated_rating_curve
for (i, id) in enumerate(node_id)
upstream_basin_id = only(inneighbors(graph_flow, id))
downstream_ids = outneighbors(graph_flow, id)

if active[i]
q = tables[i](get_level(p, upstream_basin_id, current_level, t))
hasindex, basin_idx = id_index(basin.node_id, upstream_basin_id)
@assert hasindex "TabulatedRatingCurve must be downstream of a Basin"
s = storage[basin_idx]
reduction_factor = clamp(s, 0.0, 10.0) / 10.0
q =
reduction_factor *
tables[i](get_level(p, upstream_basin_id, current_level, t))
else
q = 0.0
end
Expand Down Expand Up @@ -931,7 +938,7 @@ function formulate_flow!(
if hasindex
# Pumping from basin
s = storage[basin_idx]
reduction_factor = min(s, 10.0) / 10.0
reduction_factor = clamp(s, 0.0, 10.0) / 10.0
q = reduction_factor * rate
else
# Pumping from level boundary
Expand Down Expand Up @@ -984,7 +991,7 @@ function formulate_flows!(

formulate_flow!(linear_resistance, p, current_level, flow, t)
formulate_flow!(manning_resistance, p, current_level, flow, t)
formulate_flow!(tabulated_rating_curve, p, current_level, flow, t)
formulate_flow!(tabulated_rating_curve, p, storage, current_level, flow, t)
formulate_flow!(flow_boundary, p, flow, t)
formulate_flow!(fractional_flow, flow, p)
formulate_flow!(pump, p, flow, storage)
Expand Down
2 changes: 1 addition & 1 deletion core/test/run_models.jl
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ end
model = Ribasim.run(toml_path)
@test model isa Ribasim.Model
@test successful_retcode(model)
@test model.integrator.sol.u[end] Float32[5.951445, 727.9898] skip = Sys.isapple()
@test model.integrator.sol.u[end] Float32[8.41143, 725.5068] skip = Sys.isapple()
# the highest level in the dynamic table is updated to 1.2 from the callback
@test model.integrator.p.tabulated_rating_curve.tables[end].t[end] == 1.2
end
Expand Down

0 comments on commit 9238b0c

Please sign in to comment.