Skip to content

Commit

Permalink
Negative storage check (#1425)
Browse files Browse the repository at this point in the history
Fixes #1406.
  • Loading branch information
SouthEndMusic authored Apr 23, 2024
1 parent 5d3b795 commit 2be7d93
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 1 deletion.
21 changes: 21 additions & 0 deletions core/src/callback.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ function create_callbacks(
(; starttime, basin, tabulated_rating_curve, discrete_control) = parameters
callbacks = SciMLBase.DECallback[]

negative_storage_cb = FunctionCallingCallback(check_negative_storage)
push!(callbacks, negative_storage_cb)

integrating_flows_cb = FunctionCallingCallback(integrate_flows!; func_start = false)
push!(callbacks, integrating_flows_cb)

Expand Down Expand Up @@ -65,6 +68,24 @@ function create_callbacks(
return callback, saved
end

function check_negative_storage(u, t, integrator)::Nothing
(; basin) = integrator.p
(; node_id) = basin
errors = false
for (i, id) in enumerate(node_id)
if u.storage[i] < 0
@error "Negative storage detected in $id"
errors = true
end
end

if errors
t_datetime = datetime_since(integrator.t, integrator.p.starttime)
error("Negative storages found at $t_datetime.")
end
return nothing
end

"""
Integrate flows over the last timestep
"""
Expand Down
2 changes: 1 addition & 1 deletion core/test/allocation_test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ end
@__DIR__,
"../../generated_testmodels/fractional_flow_subnetwork/ribasim.toml",
)
model = Ribasim.BMI.initialize(Ribasim.Model, toml_path)
model = Ribasim.Model(toml_path)
problem = model.integrator.p.allocation.allocation_models[1].problem
F = problem[:F]
constraints_fractional_flow = problem[:fractional_flow]
Expand Down
20 changes: 20 additions & 0 deletions core/test/validation_test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -438,3 +438,23 @@ end
@test logger.logs[1].message ==
"Demand of UserDemand #1 with priority 1 should be non-negative"
end

@testitem "negative storage" begin
import BasicModelInterface as BMI
toml_path =
normpath(@__DIR__, "../../generated_testmodels/linear_resistance/ribasim.toml")
@test ispath(toml_path)
dt = 1e10

config = Ribasim.Config(
toml_path;
solver_algorithm = "Euler",
solver_dt = dt,
solver_saveat = Inf,
)
model = Ribasim.Model(config)
@test_throws "Negative storages found at 2021-01-01T00:00:00." BMI.update_until(
model,
dt,
)
end

0 comments on commit 2be7d93

Please sign in to comment.