From 225d91254de1bd9efc2841031f340ff6adec2c30 Mon Sep 17 00:00:00 2001 From: Martijn Visser Date: Mon, 29 Apr 2024 11:03:04 +0200 Subject: [PATCH] Precalculate resistance neighbors --- core/src/parameter.jl | 20 ++++++++++++-------- core/src/read.jl | 20 ++++++++++++++------ core/src/solve.jl | 32 ++++++++++++++++---------------- 3 files changed, 42 insertions(+), 30 deletions(-) diff --git a/core/src/parameter.jl b/core/src/parameter.jl index d16b793a8..88ee5d5b1 100644 --- a/core/src/parameter.jl +++ b/core/src/parameter.jl @@ -241,12 +241,9 @@ struct TabulatedRatingCurve{C} <: AbstractParameterNode end """ -Requirements: - -* from: must be (Basin,) node -* to: must be (Basin,) node - node_id: node ID of the LinearResistance node +inflow_id: node ID across the incoming flow edge +outflow_id: node ID across the outgoing flow edge active: whether this node is active and thus contributes flows resistance: the resistance to flow; `Q_unlimited = Δh/resistance` max_flow_rate: the maximum flow rate allowed through the node; `Q = clamp(Q_unlimited, -max_flow_rate, max_flow_rate)` @@ -254,6 +251,8 @@ control_mapping: dictionary from (node_id, control_state) to resistance and/or a """ struct LinearResistance <: AbstractParameterNode node_id::Vector{NodeID} + inflow_id::Vector{NodeID} + outflow_id::Vector{NodeID} active::BitVector resistance::Vector{Float64} max_flow_rate::Vector{Float64} @@ -263,8 +262,11 @@ end """ This is a simple Manning-Gauckler reach connection. -* Length describes the reach length. -* roughness describes Manning's n in (SI units). +node_id: node ID of the ManningResistance node +inflow_id: node ID across the incoming flow edge +outflow_id: node ID across the outgoing flow edge +length: reach length +manning_n: roughness; Manning's n in (SI units). The profile is described by a trapezoid: @@ -288,13 +290,15 @@ Requirements: * from: must be (Basin,) node * to: must be (Basin,) node * length > 0 -* roughess > 0 +* manning_n > 0 * profile_width >= 0 * profile_slope >= 0 * (profile_width == 0) xor (profile_slope == 0) """ struct ManningResistance <: AbstractParameterNode node_id::Vector{NodeID} + inflow_id::Vector{NodeID} + outflow_id::Vector{NodeID} active::BitVector length::Vector{Float64} manning_n::Vector{Float64} diff --git a/core/src/read.jl b/core/src/read.jl index 9b84fed30..042454dde 100644 --- a/core/src/read.jl +++ b/core/src/read.jl @@ -230,7 +230,7 @@ function initialize_allocation!(p::Parameters, config::Config)::Nothing return nothing end -function LinearResistance(db::DB, config::Config)::LinearResistance +function LinearResistance(db::DB, config::Config, graph::MetaGraph)::LinearResistance static = load_structvector(db, config, LinearResistanceStaticV1) defaults = (; max_flow_rate = Inf, active = true) parsed_parameters, valid = @@ -242,8 +242,12 @@ function LinearResistance(db::DB, config::Config)::LinearResistance ) end + node_id = NodeID.(NodeType.LinearResistance, parsed_parameters.node_id) + return LinearResistance( - NodeID.(NodeType.LinearResistance, parsed_parameters.node_id), + node_id, + inflow_id.(Ref(graph), node_id), + outflow_id.(Ref(graph), node_id), BitVector(parsed_parameters.active), parsed_parameters.resistance, parsed_parameters.max_flow_rate, @@ -321,7 +325,7 @@ function TabulatedRatingCurve(db::DB, config::Config)::TabulatedRatingCurve return TabulatedRatingCurve(node_ids, active, interpolations, time, control_mapping) end -function ManningResistance(db::DB, config::Config)::ManningResistance +function ManningResistance(db::DB, config::Config, graph::MetaGraph)::ManningResistance static = load_structvector(db, config, ManningResistanceStaticV1) parsed_parameters, valid = parse_static_and_time(db, config, "ManningResistance"; static) @@ -330,8 +334,12 @@ function ManningResistance(db::DB, config::Config)::ManningResistance error("Errors occurred when parsing ManningResistance data.") end + node_id = NodeID.(NodeType.ManningResistance, parsed_parameters.node_id) + return ManningResistance( - NodeID.(NodeType.ManningResistance, parsed_parameters.node_id), + node_id, + inflow_id.(Ref(graph), node_id), + outflow_id.(Ref(graph), node_id), BitVector(parsed_parameters.active), parsed_parameters.length, parsed_parameters.manning_n, @@ -1029,8 +1037,8 @@ function Parameters(db::DB, config::Config)::Parameters error("Invalid edge(s) found.") end - linear_resistance = LinearResistance(db, config) - manning_resistance = ManningResistance(db, config) + linear_resistance = LinearResistance(db, config, graph) + manning_resistance = ManningResistance(db, config, graph) tabulated_rating_curve = TabulatedRatingCurve(db, config) fractional_flow = FractionalFlow(db, config) level_boundary = LevelBoundary(db, config) diff --git a/core/src/solve.jl b/core/src/solve.jl index 75c594ff4..4fb734021 100644 --- a/core/src/solve.jl +++ b/core/src/solve.jl @@ -336,24 +336,24 @@ function formulate_flow!( (; graph) = p (; node_id, active, resistance, max_flow_rate) = linear_resistance for (i, id) in enumerate(node_id) - basin_a_id = inflow_id(graph, id) - basin_b_id = outflow_id(graph, id) + inflow_id = linear_resistance.inflow_id[i] + outflow_id = linear_resistance.outflow_id[i] if active[i] - h_a = get_level(p, basin_a_id, t; storage) - h_b = get_level(p, basin_b_id, t; storage) + h_a = get_level(p, inflow_id, t; storage) + h_b = get_level(p, outflow_id, t; storage) q_unlimited = (h_a - h_b) / resistance[i] q = clamp(q_unlimited, -max_flow_rate[i], max_flow_rate[i]) # add reduction_factor on highest level if q > 0 - q *= low_storage_factor(storage, p.basin.node_id, basin_a_id, 10.0) + q *= low_storage_factor(storage, p.basin.node_id, inflow_id, 10.0) else - q *= low_storage_factor(storage, p.basin.node_id, basin_b_id, 10.0) + q *= low_storage_factor(storage, p.basin.node_id, outflow_id, 10.0) end - set_flow!(graph, basin_a_id, id, q) - set_flow!(graph, id, basin_b_id, q) + set_flow!(graph, inflow_id, id, q) + set_flow!(graph, id, outflow_id, q) end end return nothing @@ -438,17 +438,17 @@ function formulate_flow!( (; node_id, active, length, manning_n, profile_width, profile_slope) = manning_resistance for (i, id) in enumerate(node_id) - basin_a_id = inflow_id(graph, id) - basin_b_id = outflow_id(graph, id) + inflow_id = manning_resistance.inflow_id[i] + outflow_id = manning_resistance.outflow_id[i] if !active[i] continue end - h_a = get_level(p, basin_a_id, t; storage) - h_b = get_level(p, basin_b_id, t; storage) - bottom_a = basin_bottom(basin, basin_a_id) - bottom_b = basin_bottom(basin, basin_b_id) + h_a = get_level(p, inflow_id, t; storage) + h_b = get_level(p, outflow_id, t; storage) + bottom_a = basin_bottom(basin, inflow_id) + bottom_b = basin_bottom(basin, outflow_id) slope = profile_slope[i] width = profile_width[i] n = manning_n[i] @@ -478,8 +478,8 @@ function formulate_flow!( q = q_sign * A / n * R_h^(2 / 3) * sqrt(Δh / L * 2 / π * atan(k * Δh) + eps) - set_flow!(graph, basin_a_id, id, q) - set_flow!(graph, id, basin_b_id, q) + set_flow!(graph, inflow_id, id, q) + set_flow!(graph, id, outflow_id, q) end return nothing end