-
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?
Conversation
(; flow_length, flow_width) = subsurface.parameters | ||
|
||
storage_total .= satwaterdepth | ||
storage_total .+= ustoredepth |
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.
During model initialization, ustoredepth
is not set based on ustorelayerdepth
(state). As discussed, it could for example be added in the initialization of the model, for that the ustoredepth!
function can be used after the states are set (after this line for the model type sbm
: https://github.com/Deltares/Wflow.jl/blob/master/src/sbm_model.jl#L390).
(; 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 comment
The reason will be displayed to describe this comment to others. Learn more.
A few storage variables are missing:
get_snow_storage(snow) .+ get_snow_water(snow)
get_glacier_store(glacier) .* get_glacier_fraction(glacier)
get_water_depth(demand.paddy)
model.land.interception.variables.canopy_storage
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.
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 | ||
|
||
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 comment
The reason will be displayed to describe this comment to others. Learn more.
net_runoff_river
is not an inflow (it is an outflow). allocation
refers to model.land.allocation
.
inflow_total .+= runoff.variables.net_runoff_river | |
inflow_total .+= get_irrigation_allocated(allocation) |
inflow_total .+= runoff.variables.net_runoff_river | ||
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 comment
The reason will be displayed to describe this comment to others. Learn more.
net_runoff
refers to model.land.soil.variables.net_runoff
outflow_total .= runoff_land | |
outflow_total .= net_runoff |
inflow_total .+= 1000.0 * ssfin ./ (flow_length .* flow_width) | ||
|
||
outflow_total .= runoff_land | ||
outflow_total .+= net_runoff_river |
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.
As part of water demand computations water can be abstracted: land.allocation.variables.act_groundwater_abst
. This should be added to outflow_total
. Suggest to use a wrapper method here similar to get_irrigation_allocated(allocation)
.
(; runoff_land, net_runoff_river) = runoff.variables | ||
|
||
(; subsurface) = lateral | ||
(; ssf, ssfin) = subsurface.variables |
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 the sbm_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).
return nothing | ||
end | ||
|
||
struct WaterBalanceOverLand{T <: AbstractFloat} # Terms in [?] |
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.
It would be good to have water balance computations for the available routing options (suggest for example to rename to WaterBalanceRouting
if this struct is used to store water balance components for the different routing options).
|
||
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 comment
The 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).
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 comment
The 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 volume
is available and initialized (either cold or warm state). Outflow variables (e.g. q_av
) are available for the model time step, but inflow variables are mostly only available at the internal time step.
Kinematic wave overland flow
- outflow:
q_av
- inflow:
qin + qlat * flow_length
(internal time step), instead ofqlat * flow_length
, inwater` can also be used (valid for model time step)
Kinematic wave river flow
- outflow:
q_av
- inflow:
q_in + (qlat + _inflow) * flow_length
(internal time step) (as for the kinematic wave overland flow,inwater
(valid for model time step) can also be used (to replaceqlat * flow_length
)
Local inertial river flow (with optional floodplain routing scheme)
A cumulative volume error is computed, see also the code starting here https://github.com/Deltares/Wflow.jl/blob/master/src/routing/surface_local_inertial.jl#L479. I think it would be useful to have also error(s) available per model time step as part of water_balance.jl. If floodplain routing is included I would recommend to compute the water balance for river and floodplain (not separated).
Local inertial river and overland flow
A cumulative error is computed, see also the code starting here https://github.com/Deltares/Wflow.jl/blob/master/src/routing/surface_local_inertial.jl#L1033. For the water balance computation per model time step it is enough to consider land_v.volume
.
When many variables are involved (as for local inertial routing) it probably makes sense to compute a net_flux
.
Kinematic wave subsurface flow
outflow: ssf + exfiltwater * flow_length * flow_width
inflow: ssfin + recharge * flow_length
Note: see for units of variables https://github.com/Deltares/Wflow.jl/blob/master/src/routing/subsurface.jl#L87.
Groundwater flow
Here Q
is used as the net flux, see also: https://github.com/Deltares/Wflow.jl/blob/master/src/groundwater/aquifer.jl#L432
Issue addressed
Fixes #90
Explanation
I created a new script
water_balance.jl
, with:vertical
andover_land
separatelyI have a few open questions about this:
storage_total_prev
after the first timestep incompute_water_balance!
for vertical processes? Is such data (i.e.satwaterdepth, ustoredept
) always initialized before start of time stepping?n
) there are (for array initialization)?Checklist
master
Additional Notes (optional)
Add any additional notes or information that may be helpful.