Skip to content

Commit

Permalink
Refactor river and overland flow routing structs
Browse files Browse the repository at this point in the history
Split into `boundary_conditions`, `variables` and `parameters`.
  • Loading branch information
verseve committed Nov 11, 2024
1 parent e9f1c97 commit f42907a
Show file tree
Hide file tree
Showing 23 changed files with 1,101 additions and 837 deletions.
17 changes: 9 additions & 8 deletions server/test/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ end

@testset "model information functions" begin
@test request((fn = "get_component_name",)) == Dict("component_name" => "sbm")
@test request((fn = "get_input_item_count",)) == Dict("input_item_count" => 203)
@test request((fn = "get_output_item_count",)) == Dict("output_item_count" => 203)
@test request((fn = "get_input_item_count",)) == Dict("input_item_count" => 206)
@test request((fn = "get_output_item_count",)) == Dict("output_item_count" => 206)
to_check = [
"vertical.soil.parameters.nlayers",
"vertical.soil.parameters.theta_r",
"lateral.river.q",
"lateral.river.reservoir.outflow",
"lateral.river.variables.q",
"lateral.river.boundary_conditions.reservoir.outflow",
]
retrieved_vars = request((fn = "get_input_var_names",))["input_var_names"]
@test all(x -> x in retrieved_vars, to_check)
Expand All @@ -49,12 +49,12 @@ end
zi_size = 0
vwc_1_size = 0
@testset "variable information and get and set functions" begin
@test request((fn = "get_var_itemsize", name = "lateral.subsurface.ssf")) ==
@test request((fn = "get_var_itemsize", name = "lateral.subsurface.variables.ssf")) ==
Dict("var_itemsize" => sizeof(Wflow.Float))
@test request((fn = "get_var_type", name = "vertical.n"))["status"] == "ERROR"
@test request((fn = "get_var_units", name = "vertical.soil.parameters.theta_s")) ==
Dict("var_units" => "-")
@test request((fn = "get_var_location", name = "lateral.river.q")) ==
@test request((fn = "get_var_location", name = "lateral.river.variables.q")) ==
Dict("var_location" => "node")
zi_nbytes =
request((fn = "get_var_nbytes", name = "vertical.soil.variables.zi"))["var_nbytes"]
Expand All @@ -68,14 +68,15 @@ vwc_1_size = 0
vwc_1_itemsize =
request((fn = "get_var_itemsize", name = "vertical.soil.variables.vwc[1]"))["var_itemsize"]
vwc_1_size = Int(vwc_1_nbytes / vwc_1_itemsize)
@test request((fn = "get_var_grid", name = "lateral.river.h")) == Dict("var_grid" => 3)
@test request((fn = "get_var_grid", name = "lateral.river.variables.h")) ==
Dict("var_grid" => 3)
msg = (fn = "get_value", name = "vertical.soil.variables.zi", dest = fill(0.0, zi_size))
@test mean(request(msg)["value"]) 277.3620724821974
msg = (fn = "get_value_ptr", name = "vertical.soil.parameters.theta_s")
@test mean(request(msg)["value_ptr"]) 0.4409211971535584
msg = (
fn = "get_value_at_indices",
name = "lateral.river.q",
name = "lateral.river.variables.q",
dest = [0.0, 0.0, 0.0],
inds = [1, 5, 10],
)
Expand Down
45 changes: 27 additions & 18 deletions server/test/sbm_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,18 @@ ustorelayerdepth = "ustorelayerdepth"
snow_storage = "snow"
snow_water = "snowwater"

[state.lateral.river]
[state.lateral.river.variables]
h = "h_river"
h_av = "h_av_river"
q = "q_river"

[state.lateral.river.reservoir]
[state.lateral.river.boundary_conditions.reservoir]
volume = "volume_reservoir"

[state.lateral.subsurface]
[state.lateral.subsurface.variables]
ssf = "ssf"

[state.lateral.land]
[state.lateral.land.variables]
h = "h_land"
h_av = "h_av_land"
q = "q_land"
Expand Down Expand Up @@ -112,7 +112,7 @@ offset = 0.0

[input.lateral.river]
length = "wflow_riverlength"
n = "N_River"
mannings_n = "N_River"
slope = "RiverSlope"
width = "wflow_riverwidth"
bankfull_elevation = "RiverZ"
Expand All @@ -132,7 +132,7 @@ targetminfrac = "ResTargetMinFrac"
ksathorfrac = "KsatHorFrac"

[input.lateral.land]
n = "N"
mannings_n = "N"
slope = "Slope"

[model]
Expand Down Expand Up @@ -161,17 +161,17 @@ ustorelayerdepth = "ustorelayerdepth"
snow_storage = "snow"
snow_water = "snowwater"

[output.lateral.river]
[output.lateral.river.variables]
h = "h_river"
q = "q_river"

[output.lateral.river.reservoir]
[output.lateral.river.boundary_conditions.reservoir]
volume = "volume_reservoir"

[output.lateral.subsurface]
[output.lateral.subsurface.variables]
ssf = "ssf"

[output.lateral.land]
[output.lateral.land.variables]
h = "h_land"
q = "q_land"

Expand All @@ -181,7 +181,7 @@ path = "output_scalar_moselle.nc"
[[netcdf.variable]]
name = "Q"
map = "gauges"
parameter = "lateral.river.q"
parameter = "lateral.river.variables.q"

[[netcdf.variable]]
coordinate.x = 6.255
Expand All @@ -202,13 +202,13 @@ path = "output_moselle.csv"

[[csv.column]]
header = "Q"
parameter = "lateral.river.q"
parameter = "lateral.river.variables.q"
reducer = "maximum"

[[csv.column]]
header = "volume"
index = 1
parameter = "lateral.river.reservoir.volume"
parameter = "lateral.river.boundary_conditions.reservoir.volume"

[[csv.column]]
coordinate.x = 6.255
Expand All @@ -232,7 +232,7 @@ parameter = "vertical.atmospheric_forcing.temperature"
[[csv.column]]
header = "Q"
map = "gauges"
parameter = "lateral.river.q"
parameter = "lateral.river.variables.q"

[[csv.column]]
header = "recharge"
Expand All @@ -255,8 +255,17 @@ components = [
"vertical.snow.boundary_conditions",
"vertical.snow.variables",
"vertical.snow.parameters",
"lateral.subsurface",
"lateral.land",
"lateral.river",
"lateral.river.reservoir",
"lateral.subsurface.boundary_conditions",
"lateral.subsurface.variables",
"lateral.subsurface.parameters",
"lateral.subsurface.parameters.kh_profile",
"lateral.land.boundary_conditions",
"lateral.land.variables",
"lateral.land.variables.flow",
"lateral.land.parameters",
"lateral.river.variables",
"lateral.river.parameters",
"lateral.river.parameters.flow",
"lateral.river.boundary_conditions",
"lateral.river.boundary_conditions.reservoir",
]
2 changes: 1 addition & 1 deletion src/bmi.jl
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ function BMI.get_var_grid(model::Model, name::String)
s = split(name, "[")
key = symbols(first(s))
if exchange(param(model, key))
type = typeof(param(model, key[1:(end - 1)]))
type = typeof(param(model, key[1:2]))
return if :reservoir in key
0
elseif :lake in key
Expand Down
36 changes: 19 additions & 17 deletions src/demand/water_demand.jl
Original file line number Diff line number Diff line change
Expand Up @@ -594,18 +594,20 @@ function surface_water_allocation_local!(land_allocation, demand, river, network
(; surfacewater_demand) = demand.variables
(; act_surfacewater_abst_vol, act_surfacewater_abst, available_surfacewater) =
river.allocation.variables
(; inflow) = river.boundary_conditions
(; volume) = river.variables
# maps from the land domain to the internal river domain (linear index), excluding water bodies
index_river = network.land.index_river_wb
for i in eachindex(surfacewater_demand)
if index_river[i] > 0.0
# the available volume is limited by a fixed scaling factor of 0.8 to prevent
# rivers completely drying out. check for abstraction through inflow (external
# negative inflow) and adjust available volume.
if river.inflow[index_river[i]] < 0.0
inflow = river.inflow[index_river[i]] * dt
available_volume = max(river.volume[index_river[i]] * 0.80 + inflow, 0.0)
if inflow[index_river[i]] < 0.0
river_inflow = inflow[index_river[i]] * dt
available_volume = max(volume[index_river[i]] * 0.80 + river_inflow, 0.0)
else
available_volume = river.volume[index_river[i]] * 0.80
available_volume = volume[index_river[i]] * 0.80
end
# satisfy surface water demand with available local river volume
surfacewater_demand_vol = surfacewater_demand[i] * 0.001 * network.land.area[i]
Expand Down Expand Up @@ -635,6 +637,7 @@ function surface_water_allocation_area!(land_allocation, demand, river, network)
river.allocation.variables
(; surfacewater_alloc) = land_allocation.variables
(; surfacewater_demand) = demand.variables
(; reservoir, lake) = river.boundary_conditions

# loop over allocation areas
for i in eachindex(inds_river)
Expand All @@ -649,12 +652,12 @@ function surface_water_allocation_area!(land_allocation, demand, river, network)
if res_index[j] > 0
# for reservoir locations use reservoir volume
k = res_index[j]
available_surfacewater[j] = river.reservoir.volume[k] * 0.98 # limit available reservoir volume
available_surfacewater[j] = reservoir.volume[k] * 0.98 # limit available reservoir volume
sw_available += available_surfacewater[j]
elseif lake_index[j] > 0
# for lake locations use lake volume
k = lake_index[j]
available_surfacewater[j] = river.lake.storage[k] * 0.98 # limit available lake volume
available_surfacewater[j] = lake.storage[k] * 0.98 # limit available lake volume
sw_available += available_surfacewater[j]

else
Expand Down Expand Up @@ -780,7 +783,7 @@ end
return_flow(non_irri::NoNonIrrigationDemand, nonirri_demand_gross, nonirri_alloc) = 0.0

# wrapper methods
groundwater_volume(model::LateralSSF) = model.volume
groundwater_volume(model::LateralSSF) = model.variables.volume
groundwater_volume(model) = model.flow.aquifer.volume

"""
Expand Down Expand Up @@ -815,6 +818,7 @@ function update_water_allocation!(land_allocation, demand::Demand, lateral, netw

(; frac_sw_used) = land_allocation.parameters
(; act_surfacewater_abst, act_surfacewater_abst_vol) = river.allocation.variables
(; abstraction, reservoir, lake) = river.boundary_conditions

surfacewater_alloc .= 0.0
act_surfacewater_abst .= 0.0
Expand All @@ -828,19 +832,17 @@ function update_water_allocation!(land_allocation, demand::Demand, lateral, netw
# surface water demand and allocation for areas
surface_water_allocation_area!(land_allocation, demand, river, network)

@. river.abstraction = act_surfacewater_abst_vol / dt
@. abstraction = act_surfacewater_abst_vol / dt

# for reservoir and lake locations set river abstraction at zero and abstract volume
# from reservoir and lake, including an update of lake waterlevel
if !isnothing(river.reservoir)
@. river.abstraction[res_index_f] = 0.0
@. river.reservoir.volume -= act_surfacewater_abst_vol[res_index_f]
elseif !isnothing(river.lake)
@. river.abstraction[lake_index_f] = 0.0
lakes = river.lake
@. lakes.storage -= act_surfacewater_abst_vol[lake_index_f]
@. lakes.waterlevel =
waterlevel(lakes.storfunc, lakes.area, lakes.storage, lakes.sh)
if !isnothing(reservoir)
@. abstraction[res_index_f] = 0.0
@. reservoir.volume -= act_surfacewater_abst_vol[res_index_f]
elseif !isnothing(lake)
@. abstraction[lake_index_f] = 0.0
@. lake.storage -= act_surfacewater_abst_vol[lake_index_f]
@. lake.waterlevel = waterlevel(lake.storfunc, lake.area, lake.storage, lake.sh)
end

groundwater_alloc .= 0.0
Expand Down
Loading

0 comments on commit f42907a

Please sign in to comment.