-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add water balance output #642
Comments
The #644 takes an important first step by making sure the flow output table is complete, by including the gains and losses from non-conservative nodes. Here is a first quick script calculating the water balance error over the basic_transient test model. using Plots
using DataFrames, Dates
using Ribasim
toml_path = normpath(@__DIR__, "generated_testmodels/basic_transient/basic_transient.toml")
model = Ribasim.run(toml_path)
# use unique since some timesteps are saved multiple times
basin = unique(DataFrame(Ribasim.basin_table(model)), [:time, :node_id])
flow = DataFrame(Ribasim.flow_table(model))
time = unique(Ribasim.datetimes(model))
function water_balance_error(basin, flow, time)
wbal_errors_m3s = Float64[]
wbal_errors_m3 = Float64[]
storages = Float64[]
for (t1, t2) in zip(time[begin:(end - 1)], time[(begin + 1):end])
# we have to calculate the storage difference over time ourselves
dt = 0.001 * Dates.value(t2 - t1)
s_t1 = sum(filter(:time => t -> t == t1, basin).storage)
s_t2 = sum(filter(:time => t -> t == t2, basin).storage)
ds = s_t2 - s_t1
dsdt = ds / dt
# for the period (t1,t2) flow is defined on t2
bc_flows = filter([:time, :edge_id] => (t, e) -> t == t2 && ismissing(e), flow)
bc_flow = sum(bc_flows.flow)
wbal_error_m3s = dsdt - bc_flow
wbal_error_m3 = wbal_error_m3s * dt
push!(wbal_errors_m3s, wbal_error_m3s)
push!(wbal_errors_m3, wbal_error_m3)
push!(storages, s_t2)
end
return (; wbal_errors_m3s, wbal_errors_m3, storages)
end
(; wbal_errors_m3s, wbal_errors_m3, storages) = water_balance_error(basin, flow, time)
plot(time[2:end], wbal_errors_m3s; title = "error [m3/s]")
plot(time[2:end], cumsum(wbal_errors_m3); title = "cumulative error [m3]")
plot(time[2:end], storages; title = "total storage [m3]") The error is not huge, but seems high. Perhaps the default tolerances should be a bit lower. If I reduce them both 1000x, the cumulative error at the end becomes ~1.2 m3 instead of ~120 m3. We should probably integrate some form of this into Ribasim, to have the error as part of our output. This just does
|
First step: add the percentage error to stdout. |
Fixed by #1367 |
The level and flow output we have right now are samples in a continuous signal.
To get a good sense of the total water balance, and to check if it closes, we need to integrate these over time, to get output in m3 over the past timestep that we can sum.
I think we should implement this using the
IntegratingCallback
.Also we should clean up some leftover code from similar old functionality:
https://github.com/Deltares/Ribasim/blob/v2023.09.0/core/src/bmi.jl#L200
https://github.com/Deltares/Ribasim/blob/v2023.09.0/core/src/solve.jl#L1194
EDIT: This issue is now only about water balance calculation and output. Mean flows are #935. This can be done separately, e.g. the water balance below was calculated using sampled flows, ignoring the error for that.
The text was updated successfully, but these errors were encountered: