-
Notifications
You must be signed in to change notification settings - Fork 21
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
Water balance computation #525
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,97 @@ | ||||||
struct WaterBalanceVertical{T <: AbstractFloat} # Terms in [mm] | ||||||
storage_total::Vector{T} | ||||||
storage_total_prev::Vector{T} | ||||||
inflow_total::Vector{T} | ||||||
outflow_total::Vector{T} | ||||||
balance_error::Vector{T} | ||||||
relative_error::Vector{T} | ||||||
end | ||||||
|
||||||
function WaterBalanceVertical(n::Integer, float_type::Type{T}) where {T <: AbstractFloat} | ||||||
WaterBalanceVertical(ntuple(_ -> fill(float_type(Nan), n), 6)...) | ||||||
end | ||||||
|
||||||
function compute_water_balance!(model, water_balance::WaterBalanceVertical)::Nothing | ||||||
(; | ||||||
storage_total, | ||||||
storage_total_prev, | ||||||
inflow_total, | ||||||
outflow_total, | ||||||
balance_error, | ||||||
relative_error, | ||||||
) = water_balance | ||||||
(; vertical, lateral) = model | ||||||
|
||||||
(; soil, runoff) = vertical | ||||||
(; satwaterdepth, ustoredepth, actevap) = soil.variables | ||||||
(; runoff_land, net_runoff_river) = runoff.variables | ||||||
|
||||||
(; subsurface) = lateral | ||||||
(; ssf, ssfin) = subsurface.variables | ||||||
(; flow_length, flow_width) = subsurface.parameters | ||||||
|
||||||
storage_total .= satwaterdepth | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A few storage variables are missing: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lateral snow transport is often used when snow modelling is included, see also https://github.com/Deltares/Wflow.jl/blob/master/src/sbm.jl#L88. For the water balance this means the lateral snow fluxes need to be included. |
||||||
storage_total .+= ustoredepth | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. During model initialization, |
||||||
|
||||||
inflow_total .= vertical.atmospheric_forcing.precipitation | ||||||
inflow_total .+= runoff.variables.net_runoff_river | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
inflow_total .+= 1000.0 * ssfin ./ (flow_length .* flow_width) | ||||||
|
||||||
outflow_total .= runoff_land | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
outflow_total .+= net_runoff_river | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As part of water demand computations water can be abstracted: |
||||||
outflow_total .+= actevap | ||||||
outflow_total .+= 1000.0 * ssf ./ (flow_length .* flow_width) | ||||||
|
||||||
@. balance_error = (inflow_total - outflow_total - (storage_total - storage_total_prev)) | ||||||
@. relative_error = balance_error / ((inflow_total + outflow_total) / 2) | ||||||
|
||||||
copyto!(storage_total_prev, storage_total) | ||||||
|
||||||
#TODO : What to do with results? | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For now I think it is fine to compute the errors and these variables can be written as output (netCDF (gridded and scalar) or CSV). |
||||||
|
||||||
return nothing | ||||||
end | ||||||
|
||||||
struct WaterBalanceOverLand{T <: AbstractFloat} # Terms in [?] | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be good to have water balance computations for the available routing options (suggest for example to rename to |
||||||
volume_t_prev::Vector{T} | ||||||
volume_rate::Vector{T} | ||||||
water_in::Vector{T} | ||||||
water_out::Vector{T} | ||||||
balance_error::Vector{T} | ||||||
relative_error::Vector{T} | ||||||
end | ||||||
|
||||||
function WaterBalanceOverLand(n::Integer, float_type::Type{T}) where {T <: AbstractFloat} | ||||||
WaterBalanceOverLand(ntuple(_ -> fill(float_type(Nan), n), 6)...) | ||||||
end | ||||||
|
||||||
# function compute_water_balance!(model, water_balance::WaterBalanceOverLand)::Nothing | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For most routing options an internal time step (different from the model time step) is used. The variable Kinematic wave overland flow
Kinematic wave river flow
Local inertial river flow (with optional floodplain routing scheme) Local inertial river and overland flow When many variables are involved (as for local inertial routing) it probably makes sense to compute a Kinematic wave subsurface flow Groundwater flow |
||||||
# (; vertical, lateral) = model | ||||||
# (; volume_t_prev, volume_rate, water_in, water_out, balance_error, relative_error) = water_balance_overland | ||||||
|
||||||
# (; land, river) = lateral | ||||||
# (; volume) = land.variables | ||||||
# volume_t = volume | ||||||
|
||||||
# water_in .= lateral.land.qin_av | ||||||
# @. water_in += lateral.land.qlat_av * lateral.land.dl | ||||||
|
||||||
# water_out .= lateral.land.q_av | ||||||
|
||||||
# @. volume_rate = (volume_t - volume_t_previous) / vertical.dt | ||||||
|
||||||
# @. balance_error = (water_in - water_out) - volume_rate | ||||||
|
||||||
# #TODO : What to do with results? | ||||||
|
||||||
# return nothing | ||||||
# end | ||||||
|
||||||
struct WaterBalance{T} | ||||||
water_balance_vertical::WaterBalanceVertical{T} | ||||||
water_balance_over_land::WaterBalanceOverLand{T} | ||||||
end | ||||||
|
||||||
function WaterBalance(n::Integer, float_type::Type{T}) where {T <: AbstractFloat} | ||||||
WaterBalance(WaterBalanceVertical(n, float_type), WaterBalanceOverLand(n, float_type)) | ||||||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that these variables refer to the
LateralSSF
struct (kinematic wave for lateral subsurface flow). It would be nice to also have water balance computations for thesbm_gwf
model type that makes use of Darcy groundwater flow for a single unconfined layer (see also \src\sbm_gwf_model.jl and \src\groundwater\aquifer.jl).