-
Notifications
You must be signed in to change notification settings - Fork 32
Surfacewater infiltration #843
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
base: main
Are you sure you want to change the base?
Changes from 25 commits
0393575
4cc452c
c2108d9
c9465d3
3e3d234
e141d87
6058567
37b0c22
78ff48d
9dcf097
ded6ea6
dde75b1
077f726
2aeb128
dfd4afb
d7d566c
1b34b23
84cdf22
49b9f63
23567ef
92cfb00
abecbff
b876737
8828dc0
b0b9d7b
71964b5
4a081fe
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 |
|---|---|---|
|
|
@@ -655,6 +655,7 @@ end | |
| @with_kw struct LocalInertialOverlandFlowBC | ||
| n::Int | ||
| runoff::Vector{Float64} = zeros(n) # runoff from hydrological model [m³ s⁻¹] | ||
| infiltration_volume::Vector{Float64} = zeros(n) # amount of infiltration from surface water [m³] | ||
| end | ||
|
|
||
| "Local inertial overland flow model using the local inertial method" | ||
|
|
@@ -1020,6 +1021,11 @@ function local_inertial_update_water_depth!( | |
| land_v.qx[i] + land_v.qy[yd] - land_v.qy[i] + land_bc.runoff[i] - | ||
| river_bc.abstraction[inds_river[i]] | ||
| ) * dt | ||
| # Apply surface water infiltration correction for river cells | ||
| if land_bc.infiltration_volume[i] > 0.0 | ||
| land_v.storage[i] = | ||
| max(0.0, land_v.storage[i] - land_bc.infiltration_volume[i]) | ||
|
JoostBuitink marked this conversation as resolved.
Outdated
|
||
| end | ||
| if land_v.storage[i] < 0.0 | ||
| land_v.error[i] = land_v.error[i] + abs(land_v.storage[i]) | ||
| land_v.storage[i] = 0.0 # set storage to zero | ||
|
|
@@ -1070,6 +1076,11 @@ function local_inertial_update_water_depth!( | |
| land_v.error[i] = land_v.error[i] + abs(land_v.storage[i]) | ||
| land_v.storage[i] = 0.0 # set storage to zero | ||
| end | ||
| # Apply surface water infiltration correction if available | ||
| if land_bc.infiltration_volume[i] > 0.0 | ||
|
JoostBuitink marked this conversation as resolved.
Outdated
|
||
| land_v.storage[i] = | ||
| max(0.0, land_v.storage[i] - land_bc.infiltration_volume[i]) | ||
|
JoostBuitink marked this conversation as resolved.
Outdated
|
||
| end | ||
| land_v.h[i] = land_v.storage[i] / (x_length[i] * y_length[i]) | ||
| end | ||
| end | ||
|
|
@@ -1353,3 +1364,25 @@ function FloodPlainModel( | |
| floodplain = FloodPlainModel(; parameters, variables) | ||
| return floodplain | ||
| end | ||
|
|
||
| """ | ||
| Update overland flow water level and storage for LocalInertialOverlandFlow model based on | ||
| surface water infiltration. For local inertial flow, the infiltration is applied by updating | ||
| the boundary conditions which are then used in the water depth update function. | ||
| """ | ||
| function correct_overland_flow_level!( | ||
|
Collaborator
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. I would suggest to do this as part of the update of boundary conditions of the local inertial overland flow model. Now the function name is inconsistent with the function task. If you still need to use this function for this routing type (as it is used for the kinematic wave routing) you can for example return |
||
| model::SbmSoilModel, | ||
| overland_flow::LocalInertialOverlandFlowModel, | ||
| domain::Domain, | ||
| config::Config, | ||
| ) | ||
| (; infilt_surfacewater) = model.variables | ||
| (; area) = domain.land.parameters | ||
|
|
||
| if config.model.reinfiltration_surfacewater__flag | ||
| # Update the boundary condition for surface water infiltration | ||
| # This will be used in local_inertial_update_water_depth! | ||
| overland_flow.boundary_conditions.infiltration_volume .= | ||
| infilt_surfacewater .* area .* 0.001 | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -43,6 +43,12 @@ abstract type AbstractSoilModel end | |
| infiltsoilpath::Vector{Float64} = fill(MISSING_VALUE, n) | ||
| # Infiltration excess water [mm Δt⁻¹] | ||
| infiltexcess::Vector{Float64} = fill(MISSING_VALUE, n) | ||
| # Infiltration from surface water [mm Δt⁻¹] | ||
| infilt_surfacewater::Vector{Float64} = fill(0.0, n) | ||
| # Potential infiltration originating from surface water [mm Δt⁻¹] | ||
| potential_infiltration_surfacewater::Vector{Float64} = fill(0.0, n) | ||
| # Total water available for infiltration [mm Δt⁻¹] | ||
| potential_infiltration::Vector{Float64} = fill(0.0, n) | ||
|
Collaborator
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. I think it would be a bit cleaner to add |
||
| # Water that cannot infiltrate due to saturated soil (saturation excess) [mm Δt⁻¹] | ||
| excesswater::Vector{Float64} = fill(MISSING_VALUE, n) | ||
| # Water exfiltrating during saturation excess conditions [mm Δt⁻¹] | ||
|
|
@@ -687,12 +693,13 @@ function update_bc_soil_model!( | |
| evaporation!(demand.paddy, potential_soilevaporation) | ||
| potential_soilevaporation .= potential_soilevaporation .- get_evaporation(demand.paddy) | ||
|
|
||
| water_flux_surface .= max.( | ||
| runoff.boundary_conditions.water_flux_surface .+ | ||
| get_irrigation_allocated(allocation) .- runoff.variables.runoff_river .- | ||
| runoff.variables.runoff_land .+ get_water_depth(demand.paddy), | ||
| 0.0, | ||
| ) | ||
| water_flux_surface .= | ||
| max.( | ||
| runoff.boundary_conditions.water_flux_surface .+ | ||
| get_irrigation_allocated(allocation) .- runoff.variables.runoff_river .- | ||
| runoff.variables.runoff_land .+ get_water_depth(demand.paddy), | ||
| 0.0, | ||
| ) | ||
| return nothing | ||
| end | ||
|
|
||
|
|
@@ -741,6 +748,51 @@ function infiltration_reduction_factor!( | |
| return nothing | ||
| end | ||
|
|
||
| function update_available_for_infiltration!( | ||
|
Collaborator
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. Related to comment about adding the |
||
| model::SbmSoilModel, | ||
| domain::Domain, | ||
| runoff::AbstractRunoffModel, | ||
| do_surface_water_infiltration::Bool, | ||
| ) | ||
| v = model.variables | ||
| (; water_flux_surface) = model.boundary_conditions | ||
| (; waterdepth_land) = runoff.boundary_conditions | ||
| (; river_fraction) = domain.land.parameters | ||
|
|
||
| n = length(v.potential_infiltration) | ||
| threaded_foreach(1:n; basesize = 1000) do i | ||
| v.potential_infiltration_surfacewater[i] = 0.0 | ||
| if do_surface_water_infiltration | ||
| v.potential_infiltration_surfacewater[i] = | ||
| waterdepth_land[i] * (1.0 - river_fraction[i]) * 0.95 | ||
|
Collaborator
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. Maybe add this factor of 0.95 also to the docs? And probably good to use a variable here to avoid a magic number. |
||
| water_flux_surface[i] += v.potential_infiltration_surfacewater[i] | ||
| end | ||
| v.potential_infiltration[i] = water_flux_surface[i] | ||
| end | ||
|
|
||
| return nothing | ||
| end | ||
|
|
||
| function correct_infiltration!(model::SbmSoilModel) | ||
|
JoostBuitink marked this conversation as resolved.
Outdated
|
||
| v = model.variables | ||
|
JoostBuitink marked this conversation as resolved.
Outdated
|
||
| (; water_flux_surface) = model.boundary_conditions | ||
|
|
||
| n = length(v.actinfilt) | ||
| threaded_foreach(1:n; basesize = 1000) do i | ||
| v.infilt_surfacewater[i], | ||
| v.actinfilt[i], | ||
| v.infiltexcess[i], | ||
| v.excesswater[i], | ||
| water_flux_surface[i] = correct_infiltration( | ||
| v.potential_infiltration[i], | ||
| v.potential_infiltration_surfacewater[i], | ||
| water_flux_surface[i], | ||
| v.actinfilt[i], | ||
| v.infiltexcess[i], | ||
| ) | ||
| end | ||
| end | ||
|
|
||
| """ | ||
| infiltration!(soil_model::SbmSoilMsoil | ||
|
|
||
|
|
@@ -1118,6 +1170,7 @@ transpiration, capillary flux and leakage) for a single timestep. | |
| """ | ||
| function update_soil_water_flow!( | ||
| soil_model::SbmSoilModel, | ||
| domain::Domain, | ||
| atmospheric_forcing::AtmosphericForcing, | ||
| external_models::NamedTuple, | ||
| config::Config, | ||
|
|
@@ -1138,6 +1191,14 @@ function update_soil_water_flow!( | |
| modelsnow = config.model.snow__flag, | ||
| soil_infiltration_reduction = config.model.soil_infiltration_reduction__flag, | ||
| ) | ||
| # update available for infiltration in case surface water infiltration is enabled | ||
| update_available_for_infiltration!( | ||
|
Collaborator
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. Could be moved to update soil boundary conditions (see previous comments). |
||
| soil_model, | ||
| domain, | ||
| runoff, | ||
| config.model.reinfiltration_surfacewater__flag, | ||
| ) | ||
|
|
||
| infiltration!(soil_model) | ||
| # unsaturated zone flow | ||
| unsaturated_zone_flow!(soil_model) | ||
|
|
@@ -1146,8 +1207,13 @@ function update_soil_water_flow!( | |
| transpiration!(soil_model, dt) | ||
| # actual infiltration and excess water | ||
| actual_infiltration!(soil_model) | ||
| @. v.excesswater = water_flux_surface - v.actinfilt - v.infiltexcess | ||
|
|
||
| # Correct fluxes in case of reinfiltration, also to ensure correct soil and path | ||
| # infiltration, and excesswater | ||
| correct_infiltration!(soil_model) | ||
|
JoostBuitink marked this conversation as resolved.
Outdated
|
||
|
|
||
| actual_infiltration_soil_path!(soil_model) | ||
|
|
||
| @. v.excesswatersoil = | ||
| max(water_flux_surface * (1.0 - p.pathfrac) - v.actinfiltsoil, 0.0) | ||
| @. v.excesswaterpath = max(water_flux_surface * p.pathfrac - v.actinfiltpath, 0.0) | ||
|
|
@@ -1238,8 +1304,14 @@ store `satwaterdepth` and the water exfiltrating during saturation excess condit | |
| `exfiltsatwater` are updated. Additionally, volumetric water content per soil layer and for | ||
| the root zone are updated. | ||
| """ | ||
| function update_soil_water_storage!(soil_model::SbmSoilModel, external_models::NamedTuple) | ||
| (; runoff, demand, subsurface_flow) = external_models | ||
| function update_soil_water_storage!( | ||
| soil_model::SbmSoilModel, | ||
| external_models::NamedTuple, | ||
| domain::Domain, | ||
| config::Config, | ||
| ) | ||
| (; runoff, demand, subsurface_flow, overland_flow) = external_models | ||
|
|
||
| (; runoff_land, ae_openw_l) = runoff.variables | ||
| p = soil_model.parameters | ||
| v = soil_model.variables | ||
|
|
@@ -1319,6 +1391,10 @@ function update_soil_water_storage!(soil_model::SbmSoilModel, external_models::N | |
| # and the h_max parameter of a paddy field) | ||
| update_runoff!(demand.paddy, v.runoff) | ||
| @. v.net_runoff = v.runoff - ae_openw_l | ||
|
|
||
| # correct overland flow water levels in case of reinfiltration | ||
| correct_overland_flow_level!(soil_model, overland_flow, domain, config) | ||
|
JoostBuitink marked this conversation as resolved.
Outdated
|
||
|
|
||
| return nothing | ||
| end | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.