From de2203fe9635c448abe6dbecfeee2fc8673a5995 Mon Sep 17 00:00:00 2001 From: Martijn Visser Date: Fri, 23 Feb 2024 15:33:04 +0100 Subject: [PATCH] Rename TargetLevel again: LevelDemand (#1172) Follow up of https://github.com/Deltares/Ribasim/pull/1082 and #1141. As suggested by @gijsber, to go with FlowDemand of https://github.com/Deltares/Ribasim/issues/78, and renaming User to UserDemand. Not breaking since the TargetLevel node has not yet been in a release. --- core/src/allocation_optim.jl | 32 +++++++++---------- core/src/parameter.jl | 6 ++-- core/src/read.jl | 18 +++++------ core/src/schema.jl | 8 ++--- core/src/solve.jl | 4 +-- core/src/util.jl | 8 ++--- core/src/validation.jl | 6 ++-- core/test/allocation_test.jl | 6 ++-- core/test/control_test.jl | 8 ++--- docs/core/usage.qmd | 20 ++++++------ docs/python/examples.ipynb | 20 ++++++------ python/ribasim/ribasim/__init__.py | 8 ++--- python/ribasim/ribasim/config.py | 14 ++++---- python/ribasim/ribasim/geometry/node.py | 4 +-- python/ribasim/ribasim/model.py | 4 +-- python/ribasim/ribasim/schemas.py | 4 +-- .../ribasim_testmodels/__init__.py | 6 ++-- .../ribasim_testmodels/allocation.py | 10 +++--- ribasim_qgis/core/nodes.py | 16 +++++----- 19 files changed, 101 insertions(+), 101 deletions(-) diff --git a/core/src/allocation_optim.jl b/core/src/allocation_optim.jl index a44c42146..8943e92fc 100644 --- a/core/src/allocation_optim.jl +++ b/core/src/allocation_optim.jl @@ -344,7 +344,7 @@ Get several variables associated with a basin: - Its current storage - The allocation update interval - The influx (sum of instantaneous vertical fluxes of the basin) -- The index of the connected target_level node (0 if such a +- The index of the connected level_demand node (0 if such a node does not exist) - The index of the basin """ @@ -354,7 +354,7 @@ function get_basin_data( u::ComponentVector, node_id::NodeID, ) - (; graph, basin, target_level) = p + (; graph, basin, level_demand) = p (; Δt_allocation) = allocation_model @assert node_id.type == NodeType.Basin influx = get_flow(graph, node_id, 0.0) @@ -362,19 +362,19 @@ function get_basin_data( storage_basin = u.storage[basin_idx] control_inneighbors = inneighbor_labels_type(graph, node_id, EdgeType.control) if isempty(control_inneighbors) - target_level_idx = 0 + level_demand_idx = 0 else - target_level_node_id = first(control_inneighbors) - target_level_idx = findsorted(target_level.node_id, target_level_node_id) + level_demand_node_id = first(control_inneighbors) + level_demand_idx = findsorted(level_demand.node_id, level_demand_node_id) end - return storage_basin, Δt_allocation, influx, target_level_idx, basin_idx + return storage_basin, Δt_allocation, influx, level_demand_idx, basin_idx end """ Get the capacity of the basin, i.e. the maximum flow that can be abstracted from the basin if it is in a state of surplus storage (0 if no reference levels are provided by -a target_level node). +a level_demand node). Storages are converted to flows by dividing by the allocation timestep. """ function get_basin_capacity( @@ -384,14 +384,14 @@ function get_basin_capacity( t::Float64, node_id::NodeID, )::Float64 - (; target_level) = p + (; level_demand) = p @assert node_id.type == NodeType.Basin - storage_basin, Δt_allocation, influx, target_level_idx, basin_idx = + storage_basin, Δt_allocation, influx, level_demand_idx, basin_idx = get_basin_data(allocation_model, p, u, node_id) - if iszero(target_level_idx) + if iszero(level_demand_idx) return 0.0 else - level_max = target_level.max_level[target_level_idx](t) + level_max = level_demand.max_level[level_demand_idx](t) storage_max = get_storage_from_level(p.basin, basin_idx, level_max) return max(0.0, (storage_basin - storage_max) / Δt_allocation + influx) end @@ -400,7 +400,7 @@ end """ Get the demand of the basin, i.e. how large a flow the basin needs to get to its minimum target level (0 if no -reference levels are provided by a target_level node). +reference levels are provided by a level_demand node). Storages are converted to flows by dividing by the allocation timestep. """ function get_basin_demand( @@ -410,14 +410,14 @@ function get_basin_demand( t::Float64, node_id::NodeID, )::Float64 - (; target_level) = p + (; level_demand) = p @assert node_id.type == NodeType.Basin - storage_basin, Δt_allocation, influx, target_level_idx, basin_idx = + storage_basin, Δt_allocation, influx, level_demand_idx, basin_idx = get_basin_data(allocation_model, p, u, node_id) - if iszero(target_level_idx) + if iszero(level_demand_idx) return 0.0 else - level_min = target_level.min_level[target_level_idx](t) + level_min = level_demand.min_level[level_demand_idx](t) storage_min = get_storage_from_level(p.basin, basin_idx, level_min) return max(0.0, (storage_min - storage_basin) / Δt_allocation - influx) end diff --git a/core/src/parameter.jl b/core/src/parameter.jl index b996fd72f..7d2fb566e 100644 --- a/core/src/parameter.jl +++ b/core/src/parameter.jl @@ -524,12 +524,12 @@ struct User <: AbstractParameterNode end """ -node_id: node ID of the TargetLevel node +node_id: node ID of the LevelDemand node min_level: The minimum target level of the connected basin(s) max_level: The maximum target level of the connected basin(s) priority: If in a shortage state, the priority of the demand of the connected basin(s) """ -struct TargetLevel +struct LevelDemand node_id::Vector{NodeID} min_level::Vector{LinearInterpolation} max_level::Vector{LinearInterpolation} @@ -578,6 +578,6 @@ struct Parameters{T, C1, C2} discrete_control::DiscreteControl pid_control::PidControl{T} user::User - target_level::TargetLevel + level_demand::LevelDemand subgrid::Subgrid end diff --git a/core/src/read.jl b/core/src/read.jl index e201903f2..bafdeb1a3 100644 --- a/core/src/read.jl +++ b/core/src/read.jl @@ -757,25 +757,25 @@ function User(db::DB, config::Config)::User ) end -function TargetLevel(db::DB, config::Config)::TargetLevel - static = load_structvector(db, config, TargetLevelStaticV1) - time = load_structvector(db, config, TargetLevelTimeV1) +function LevelDemand(db::DB, config::Config)::LevelDemand + static = load_structvector(db, config, LevelDemandStaticV1) + time = load_structvector(db, config, LevelDemandTimeV1) parsed_parameters, valid = parse_static_and_time( db, config, - "TargetLevel"; + "LevelDemand"; static, time, time_interpolatables = [:min_level, :max_level], ) if !valid - error("Errors occurred when parsing TargetLevel data.") + error("Errors occurred when parsing LevelDemand data.") end - return TargetLevel( - NodeID.(NodeType.TargetLevel, parsed_parameters.node_id), + return LevelDemand( + NodeID.(NodeType.LevelDemand, parsed_parameters.node_id), parsed_parameters.min_level, parsed_parameters.max_level, parsed_parameters.priority, @@ -889,7 +889,7 @@ function Parameters(db::DB, config::Config)::Parameters discrete_control = DiscreteControl(db, config) pid_control = PidControl(db, config, chunk_sizes) user = User(db, config) - target_level = TargetLevel(db, config) + level_demand = LevelDemand(db, config) basin = Basin(db, config, chunk_sizes) subgrid_level = Subgrid(db, config, basin) @@ -911,7 +911,7 @@ function Parameters(db::DB, config::Config)::Parameters discrete_control, pid_control, user, - target_level, + level_demand, subgrid_level, ) diff --git a/core/src/schema.jl b/core/src/schema.jl index bb4004fe6..c7da2c14c 100644 --- a/core/src/schema.jl +++ b/core/src/schema.jl @@ -23,8 +23,8 @@ @schema "ribasim.outlet.static" OutletStatic @schema "ribasim.user.static" UserStatic @schema "ribasim.user.time" UserTime -@schema "ribasim.targetlevel.static" TargetLevelStatic -@schema "ribasim.targetlevel.time" TargetLevelTime +@schema "ribasim.leveldemand.static" LevelDemandStatic +@schema "ribasim.leveldemand.time" LevelDemandTime const delimiter = " / " tablename(sv::Type{SchemaVersion{T, N}}) where {T, N} = tablename(sv()) @@ -238,14 +238,14 @@ end priority::Int end -@version TargetLevelStaticV1 begin +@version LevelDemandStaticV1 begin node_id::Int min_level::Float64 max_level::Float64 priority::Int end -@version TargetLevelTimeV1 begin +@version LevelDemandTimeV1 begin node_id::Int time::DateTime min_level::Float64 diff --git a/core/src/solve.jl b/core/src/solve.jl index 4a8a04aa6..e1efeb497 100644 --- a/core/src/solve.jl +++ b/core/src/solve.jl @@ -190,12 +190,12 @@ function continuous_control!( end if !iszero(K_d) - dtarget_level = scalar_interpolation_derivative(target[i], t) + dlevel_demand = scalar_interpolation_derivative(target[i], t) du_listened_basin_old = du.storage[listened_node_idx] # The expression below is the solution to an implicit equation for # du_listened_basin. This equation results from the fact that if the derivative # term in the PID controller is used, the controlled pump flow rate depends on itself. - flow_rate += K_d * (dtarget_level - du_listened_basin_old / area) / D + flow_rate += K_d * (dlevel_demand - du_listened_basin_old / area) / D end # Clip values outside pump flow rate bounds diff --git a/core/src/util.jl b/core/src/util.jl index 4deafd45e..10dce7904 100644 --- a/core/src/util.jl +++ b/core/src/util.jl @@ -646,21 +646,21 @@ function get_all_priorities(db::DB, config::Config)::Vector{Int} priorities = Set{Int}() # TODO: Is there a way to automatically grab all tables with a priority column? - for type in [UserStaticV1, UserTimeV1, TargetLevelStaticV1, TargetLevelTimeV1] + for type in [UserStaticV1, UserTimeV1, LevelDemandStaticV1, LevelDemandTimeV1] union!(priorities, load_structvector(db, config, type).priority) end return sort(unique(priorities)) end function get_basin_priority_idx(p::Parameters, node_id::NodeID)::Int - (; graph, target_level, allocation) = p + (; graph, level_demand, allocation) = p @assert node_id.type == NodeType.Basin inneighbors_control = inneighbor_labels_type(graph, node_id, EdgeType.control) if isempty(inneighbors_control) return 0 else - idx = findsorted(target_level.node_id, only(inneighbors_control)) - priority = target_level.priority[idx] + idx = findsorted(level_demand.node_id, only(inneighbors_control)) + priority = level_demand.priority[idx] return findsorted(allocation.priorities, priority) end end diff --git a/core/src/validation.jl b/core/src/validation.jl index ef213b708..31d89c158 100644 --- a/core/src/validation.jl +++ b/core/src/validation.jl @@ -3,7 +3,7 @@ neighbortypes(nodetype::Symbol) = neighbortypes(Val(nodetype)) neighbortypes(::Val{:pump}) = Set((:basin, :fractional_flow, :terminal, :level_boundary)) neighbortypes(::Val{:outlet}) = Set((:basin, :fractional_flow, :terminal, :level_boundary)) neighbortypes(::Val{:user}) = Set((:basin, :fractional_flow, :terminal, :level_boundary)) -neighbortypes(::Val{:target_level}) = Set((:basin,)) +neighbortypes(::Val{:level_demand}) = Set((:basin,)) neighbortypes(::Val{:basin}) = Set(( :linear_resistance, :tabulated_rating_curve, @@ -58,7 +58,7 @@ n_neighbor_bounds_flow(::Val{:Terminal}) = n_neighbor_bounds(1, typemax(Int), 0, n_neighbor_bounds_flow(::Val{:PidControl}) = n_neighbor_bounds(0, 0, 0, 0) n_neighbor_bounds_flow(::Val{:DiscreteControl}) = n_neighbor_bounds(0, 0, 0, 0) n_neighbor_bounds_flow(::Val{:User}) = n_neighbor_bounds(1, 1, 1, 1) -n_neighbor_bounds_flow(::Val{:TargetLevel}) = n_neighbor_bounds(0, 0, 0, 0) +n_neighbor_bounds_flow(::Val{:LevelDemand}) = n_neighbor_bounds(0, 0, 0, 0) n_neighbor_bounds_flow(nodetype) = error("'n_neighbor_bounds_flow' not defined for $nodetype.") @@ -77,7 +77,7 @@ n_neighbor_bounds_control(::Val{:PidControl}) = n_neighbor_bounds(0, 1, 1, 1) n_neighbor_bounds_control(::Val{:DiscreteControl}) = n_neighbor_bounds(0, 0, 1, typemax(Int)) n_neighbor_bounds_control(::Val{:User}) = n_neighbor_bounds(0, 0, 0, 0) -n_neighbor_bounds_control(::Val{:TargetLevel}) = n_neighbor_bounds(0, 0, 1, typemax(Int)) +n_neighbor_bounds_control(::Val{:LevelDemand}) = n_neighbor_bounds(0, 0, 1, typemax(Int)) n_neighbor_bounds_control(nodetype) = error("'n_neighbor_bounds_control' not defined for $nodetype.") diff --git a/core/test/allocation_test.jl b/core/test/allocation_test.jl index 9aa5e74f6..8f5777b4b 100644 --- a/core/test/allocation_test.jl +++ b/core/test/allocation_test.jl @@ -325,7 +325,7 @@ end end @testitem "Allocation level control" begin - toml_path = normpath(@__DIR__, "../../generated_testmodels/target_level/ribasim.toml") + toml_path = normpath(@__DIR__, "../../generated_testmodels/level_demand/ribasim.toml") @test ispath(toml_path) model = Ribasim.run(toml_path) @@ -333,7 +333,7 @@ end t = Ribasim.timesteps(model) p = model.integrator.p - (; user, graph, allocation, basin, target_level) = p + (; user, graph, allocation, basin, level_demand) = p d = user.demand_itp[1][2](0) ϕ = 1e-3 # precipitation @@ -344,7 +344,7 @@ end 0, ) A = basin.area[1][1] - l_max = target_level.max_level[1](0) + l_max = level_demand.max_level[1](0) Δt_allocation = allocation.allocation_models[1].Δt_allocation # Until the first allocation solve, the user abstracts fully diff --git a/core/test/control_test.jl b/core/test/control_test.jl index 2a76aa402..bd35c147f 100644 --- a/core/test/control_test.jl +++ b/core/test/control_test.jl @@ -107,13 +107,13 @@ end idx_target_change = searchsortedlast(timesteps, t_target_change) K_p, K_i, _ = pid_control.pid_params[2](0) - target_level = pid_control.target[2](0) + level_demand = pid_control.target[2](0) A = basin.area[1][1] initial_level = level[1] flow_rate = flow_boundary.flow_rate[1].u[1] - du0 = flow_rate + K_p * (target_level - initial_level) - Δlevel = initial_level - target_level + du0 = flow_rate + K_p * (level_demand - initial_level) + Δlevel = initial_level - level_demand alpha = -K_p / (2 * A) omega = sqrt(4 * K_i / A - (K_i / A)^2) / 2 phi = atan(du0 / (A * Δlevel) - alpha) / omega @@ -122,7 +122,7 @@ end bound = @. a * exp(alpha * timesteps[1:idx_target_change]) eps = 5e-3 # Initial convergence to target level - @test all(@. abs(level[1:idx_target_change] - target_level) < bound + eps) + @test all(@. abs(level[1:idx_target_change] - level_demand) < bound + eps) # Later closeness to target level @test all( @. abs( diff --git a/docs/core/usage.qmd b/docs/core/usage.qmd index 29f224ee6..6fb8b10b7 100644 --- a/docs/core/usage.qmd +++ b/docs/core/usage.qmd @@ -198,9 +198,9 @@ name it must have in the database if it is stored there. - User: sets water usage demands at certain priorities - `User / static`: demands - `User / time`: dynamic demands -- TargetLevel: Indicates minimum and maximum target level of connected basins for allocation - - `TargetLevel / static`: static target levels - - `TargetLevel / time`: dynamic target levels +- LevelDemand: Indicates minimum and maximum target level of connected basins for allocation + - `LevelDemand / static`: static target levels + - `LevelDemand / time`: dynamic target levels - Terminal: Water sink without state or properties - `Terminal / static`: - (only node IDs) - DiscreteControl: Set parameters of other nodes based on model state conditions (e.g. basin level) @@ -466,12 +466,12 @@ demand | Float64 | $m^3 s^{-1}$ | - return_factor | Float64 | - | between [0 - 1] min_level | Float64 | $m$ | - -# TargetLevel {#sec-target_level} +# LevelDemand {#sec-level_demand} -An `TargetLevel` node associates a minimum and a maximum level with connected basins to be used by the allocation algorithm. +An `LevelDemand` node associates a minimum and a maximum level with connected basins to be used by the allocation algorithm. Below the minimum level the basin has a demand of the supplied priority, above the maximum level the basin acts as a source, used by all nodes with demands in order of priority. -The same `TargetLevel` node can be used for basins in different subnetworks. +The same `LevelDemand` node can be used for basins in different subnetworks. column | type | unit | restriction ------------- | ------- | ------------ | ----------- @@ -480,10 +480,10 @@ min_level | Float64 | $m$ | - max_level | Float64 | $m$ | - priority | Int | - | positive -## TargetLevel / time +## LevelDemand / time -This table is the transient form of the `TargetLevel` table, in which time-dependent minimum and maximum levels can be supplied. -Similar to the static version, only a single priority per `TargetLevel` node can be provided. +This table is the transient form of the `LevelDemand` table, in which time-dependent minimum and maximum levels can be supplied. +Similar to the static version, only a single priority per `LevelDemand` node can be provided. column | type | unit | restriction ------------- | ------- | ------------ | ----------- @@ -723,7 +723,7 @@ demand | Float64 allocated | Float64 realized | Float64 -For Basins the values `demand`, `allocated` and `realized` are positive if the Basin level is below the minimum level given by a `TargetLevel` node. +For Basins the values `demand`, `allocated` and `realized` are positive if the Basin level is below the minimum level given by a `LevelDemand` node. The values are negative if the Basin supplies due to a surplus of water. ::: {.callout-note} diff --git a/docs/python/examples.ipynb b/docs/python/examples.ipynb index a9d7a56cb..776ca7e52 100644 --- a/docs/python/examples.ipynb +++ b/docs/python/examples.ipynb @@ -1395,9 +1395,9 @@ "ax.set_ylabel(\"level [m]\")\n", "\n", "# Plot target level\n", - "target_levels = model.pid_control.time.df.target.to_numpy()[:4]\n", + "level_demands = model.pid_control.time.df.target.to_numpy()[:4]\n", "times = date2num(model.pid_control.time.df.time)[:4]\n", - "ax.plot(times, target_levels, color=\"k\", ls=\":\", label=\"target level\")\n", + "ax.plot(times, level_demands, color=\"k\", ls=\":\", label=\"target level\")\n", "pass" ] }, @@ -1913,13 +1913,13 @@ " (0.0, 0.0), # 1: FlowBoundary\n", " (1.0, 0.0), # 2: Basin\n", " (2.0, 0.0), # 3: User\n", - " (1.0, -1.0), # 4: TargetLevel\n", + " (1.0, -1.0), # 4: LevelDemand\n", " (2.0, -1.0), # 5: Basin\n", " ]\n", ")\n", "node_xy = gpd.points_from_xy(x=xy[:, 0], y=xy[:, 1])\n", "\n", - "node_type = [\"FlowBoundary\", \"Basin\", \"User\", \"TargetLevel\", \"Basin\"]\n", + "node_type = [\"FlowBoundary\", \"Basin\", \"User\", \"LevelDemand\", \"Basin\"]\n", "\n", "# Make sure the feature id starts at 1: explicitly give an index.\n", "node = ribasim.Node(\n", @@ -2041,7 +2041,7 @@ "metadata": {}, "outputs": [], "source": [ - "target_level = ribasim.TargetLevel(\n", + "level_demand = ribasim.LevelDemand(\n", " static=pd.DataFrame(\n", " data={\"node_id\": [4], \"priority\": 1, \"min_level\": 1.0, \"max_level\": 1.5}\n", " )\n", @@ -2107,7 +2107,7 @@ " network=ribasim.Network(node=node, edge=edge),\n", " basin=basin,\n", " flow_boundary=flow_boundary,\n", - " target_level=target_level,\n", + " level_demand=level_demand,\n", " user=user,\n", " allocation=allocation,\n", " starttime=\"2020-01-01 00:00:00\",\n", @@ -2144,7 +2144,7 @@ "metadata": {}, "outputs": [], "source": [ - "model.write(datadir / \"target_level/ribasim.toml\")" + "model.write(datadir / \"level_demand/ribasim.toml\")" ] }, { @@ -2161,7 +2161,7 @@ " \"julia\",\n", " \"--project=../../core\",\n", " \"--eval\",\n", - " f'using Ribasim; Ribasim.main(\"{datadir.as_posix()}/target_level/ribasim.toml\")',\n", + " f'using Ribasim; Ribasim.main(\"{datadir.as_posix()}/level_demand/ribasim.toml\")',\n", " ],\n", " check=True,\n", ")" @@ -2171,7 +2171,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now run the model with `ribasim target_level/ribasim.toml`.\n", + "Now run the model with `ribasim level_demand/ribasim.toml`.\n", "After running the model, read back the results:" ] }, @@ -2181,7 +2181,7 @@ "metadata": {}, "outputs": [], "source": [ - "df_basin = pd.read_feather(datadir / \"target_level/results/basin.arrow\")\n", + "df_basin = pd.read_feather(datadir / \"level_demand/results/basin.arrow\")\n", "df_basin = df_basin[df_basin.node_id == 2]\n", "df_basin_wide = df_basin.pivot_table(\n", " index=\"time\", columns=\"node_id\", values=[\"storage\", \"level\"]\n", diff --git a/python/ribasim/ribasim/__init__.py b/python/ribasim/ribasim/__init__.py index ce92f18b0..97dc9a556 100644 --- a/python/ribasim/ribasim/__init__.py +++ b/python/ribasim/ribasim/__init__.py @@ -9,6 +9,7 @@ FlowBoundary, FractionalFlow, LevelBoundary, + LevelDemand, LinearResistance, Logging, ManningResistance, @@ -18,7 +19,6 @@ Results, Solver, TabulatedRatingCurve, - TargetLevel, Terminal, User, Verbosity, @@ -29,15 +29,14 @@ __all__ = [ "Allocation", - "TargetLevel", "Basin", "DiscreteControl", "Edge", "EdgeSchema", "FlowBoundary", "FractionalFlow", - "Results", "LevelBoundary", + "LevelDemand", "LinearResistance", "Logging", "ManningResistance", @@ -48,10 +47,11 @@ "Outlet", "PidControl", "Pump", + "Results", "Solver", "TabulatedRatingCurve", - "Verbosity", "Terminal", "User", "utils", + "Verbosity", ] diff --git a/python/ribasim/ribasim/config.py b/python/ribasim/ribasim/config.py index 6f6706c7e..997bc1b11 100644 --- a/python/ribasim/ribasim/config.py +++ b/python/ribasim/ribasim/config.py @@ -18,6 +18,8 @@ FractionalFlowStaticSchema, LevelBoundaryStaticSchema, LevelBoundaryTimeSchema, + LevelDemandStaticSchema, + LevelDemandTimeSchema, LinearResistanceStaticSchema, ManningResistanceStaticSchema, OutletStaticSchema, @@ -26,8 +28,6 @@ PumpStaticSchema, TabulatedRatingCurveStaticSchema, TabulatedRatingCurveTimeSchema, - TargetLevelStaticSchema, - TargetLevelTimeSchema, TerminalStaticSchema, UserStaticSchema, UserTimeSchema, @@ -131,13 +131,13 @@ class User(NodeModel): ) -class TargetLevel(NodeModel): - static: TableModel[TargetLevelStaticSchema] = Field( - default_factory=TableModel[TargetLevelStaticSchema], +class LevelDemand(NodeModel): + static: TableModel[LevelDemandStaticSchema] = Field( + default_factory=TableModel[LevelDemandStaticSchema], json_schema_extra={"sort_keys": ["node_id", "priority"]}, ) - time: TableModel[TargetLevelTimeSchema] = Field( - default_factory=TableModel[TargetLevelTimeSchema], + time: TableModel[LevelDemandTimeSchema] = Field( + default_factory=TableModel[LevelDemandTimeSchema], json_schema_extra={"sort_keys": ["node_id", "priority", "time"]}, ) diff --git a/python/ribasim/ribasim/geometry/node.py b/python/ribasim/ribasim/geometry/node.py index 2e27707eb..7ab402189 100644 --- a/python/ribasim/ribasim/geometry/node.py +++ b/python/ribasim/ribasim/geometry/node.py @@ -216,7 +216,7 @@ def plot(self, ax=None, zorder=None) -> Any: "DiscreteControl": "*", "PidControl": "x", "User": "s", - "TargetLevel": "o", + "LevelDemand": "o", "": "o", } @@ -234,7 +234,7 @@ def plot(self, ax=None, zorder=None) -> Any: "DiscreteControl": "k", "PidControl": "k", "User": "g", - "TargetLevel": "k", + "LevelDemand": "k", "": "k", } assert self.df is not None diff --git a/python/ribasim/ribasim/model.py b/python/ribasim/ribasim/model.py index e24768103..f12aafc77 100644 --- a/python/ribasim/ribasim/model.py +++ b/python/ribasim/ribasim/model.py @@ -23,6 +23,7 @@ FlowBoundary, FractionalFlow, LevelBoundary, + LevelDemand, LinearResistance, Logging, ManningResistance, @@ -32,7 +33,6 @@ Results, Solver, TabulatedRatingCurve, - TargetLevel, Terminal, User, ) @@ -168,7 +168,7 @@ class Model(FileModel): logging: Logging = Logging() allocation: Allocation = Field(default_factory=Allocation) - target_level: TargetLevel = Field(default_factory=TargetLevel) + level_demand: LevelDemand = Field(default_factory=LevelDemand) basin: Basin = Field(default_factory=Basin) fractional_flow: FractionalFlow = Field(default_factory=FractionalFlow) level_boundary: LevelBoundary = Field(default_factory=LevelBoundary) diff --git a/python/ribasim/ribasim/schemas.py b/python/ribasim/ribasim/schemas.py index 2cbeacbe9..a97f8a1cf 100644 --- a/python/ribasim/ribasim/schemas.py +++ b/python/ribasim/ribasim/schemas.py @@ -169,14 +169,14 @@ class TabulatedRatingCurveTimeSchema(_BaseSchema): flow_rate: Series[float] = pa.Field(nullable=False) -class TargetLevelStaticSchema(_BaseSchema): +class LevelDemandStaticSchema(_BaseSchema): node_id: Series[int] = pa.Field(nullable=False) min_level: Series[float] = pa.Field(nullable=False) max_level: Series[float] = pa.Field(nullable=False) priority: Series[int] = pa.Field(nullable=False) -class TargetLevelTimeSchema(_BaseSchema): +class LevelDemandTimeSchema(_BaseSchema): node_id: Series[int] = pa.Field(nullable=False) time: Series[Timestamp] = pa.Field(nullable=False) min_level: Series[float] = pa.Field(nullable=False) diff --git a/python/ribasim_testmodels/ribasim_testmodels/__init__.py b/python/ribasim_testmodels/ribasim_testmodels/__init__.py index aa8ceb180..781ce9806 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/__init__.py +++ b/python/ribasim_testmodels/ribasim_testmodels/__init__.py @@ -8,11 +8,11 @@ from ribasim_testmodels.allocation import ( allocation_example_model, fractional_flow_subnetwork_model, + level_demand_model, looped_subnetwork_model, main_network_with_subnetworks_model, minimal_subnetwork_model, subnetwork_model, - target_level_model, user_model, ) from ribasim_testmodels.backwater import backwater_model @@ -55,7 +55,6 @@ __all__ = [ "allocation_example_model", - "target_level_model", "backwater_model", "basic_arrow_model", "basic_model", @@ -72,9 +71,11 @@ "invalid_qh_model", "leaky_bucket_model", "level_boundary_condition_model", + "level_demand_model", "level_setpoint_with_minmax_model", "linear_resistance_model", "looped_subnetwork_model", + "main_network_with_subnetworks_model", "manning_resistance_model", "minimal_subnetwork_model", "misc_nodes_model", @@ -89,7 +90,6 @@ "trivial_model", "two_basin_model", "user_model", - "main_network_with_subnetworks_model", ] # provide a mapping from model name to its constructor, so we can iterate over all models diff --git a/python/ribasim_testmodels/ribasim_testmodels/allocation.py b/python/ribasim_testmodels/ribasim_testmodels/allocation.py index 2ea3af52a..4cbdb077b 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/allocation.py +++ b/python/ribasim_testmodels/ribasim_testmodels/allocation.py @@ -1642,20 +1642,20 @@ def main_network_with_subnetworks_model(): return model -def target_level_model(): +def level_demand_model(): # Set up the nodes: xy = np.array( [ (0.0, 0.0), # 1: FlowBoundary (1.0, 0.0), # 2: Basin (2.0, 0.0), # 3: User - (1.0, -1.0), # 4: TargetLevel + (1.0, -1.0), # 4: LevelDemand (2.0, -1.0), # 5: Basin ] ) node_xy = gpd.points_from_xy(x=xy[:, 0], y=xy[:, 1]) - node_type = ["FlowBoundary", "Basin", "User", "TargetLevel", "Basin"] + node_type = ["FlowBoundary", "Basin", "User", "LevelDemand", "Basin"] # Make sure the feature id starts at 1: explicitly give an index. node = ribasim.Node( @@ -1725,7 +1725,7 @@ def target_level_model(): ) # Setup allocation level control - target_level = ribasim.TargetLevel( + level_demand = ribasim.LevelDemand( static=pd.DataFrame( data={"node_id": [4], "priority": 1, "min_level": 1.0, "max_level": 1.5} ) @@ -1751,7 +1751,7 @@ def target_level_model(): network=ribasim.Network(node=node, edge=edge), basin=basin, flow_boundary=flow_boundary, - target_level=target_level, + level_demand=level_demand, user=user, allocation=allocation, starttime="2020-01-01 00:00:00", diff --git a/ribasim_qgis/core/nodes.py b/ribasim_qgis/core/nodes.py index 2d9ba6548..dd7bd90a3 100644 --- a/ribasim_qgis/core/nodes.py +++ b/ribasim_qgis/core/nodes.py @@ -215,9 +215,9 @@ def renderer(self) -> QgsCategorizedSymbolRenderer: "DiscreteControl": (QColor("black"), "DiscreteControl", shape.Star), "PidControl": (QColor("black"), "PidControl", shape.Cross2), "User": (QColor("green"), "User", shape.Square), - "TargetLevel": ( + "LevelDemand": ( QColor("black"), - "TargetLevel", + "LevelDemand", shape.Circle, ), # All other nodes, or incomplete input @@ -787,10 +787,10 @@ def attributes(cls) -> list[QgsField]: ] -class TargetLevelStatic(Input): +class LevelDemandStatic(Input): @classmethod def input_type(cls) -> str: - return "TargetLevel / static" + return "LevelDemand / static" @classmethod def geometry_type(cls) -> str: @@ -800,15 +800,15 @@ def geometry_type(cls) -> str: def attributes(cls) -> list[QgsField]: return [ QgsField("node_id", QVariant.Int), - QgsField("target_level", QVariant.Double), + QgsField("level_demand", QVariant.Double), QgsField("priority", QVariant.Int), ] -class TargetLevelTime(Input): +class LevelDemandTime(Input): @classmethod def input_type(cls) -> str: - return "TargetLevel / time" + return "LevelDemand / time" @classmethod def geometry_type(cls) -> str: @@ -819,7 +819,7 @@ def attributes(cls) -> list[QgsField]: return [ QgsField("node_id", QVariant.Int), QgsField("time", QVariant.DateTime), - QgsField("target_level", QVariant.Double), + QgsField("level_demand", QVariant.Double), QgsField("priority", QVariant.Int), ]