From 9da6d7f3088ff8574df6a37e25c316a9cbf15c08 Mon Sep 17 00:00:00 2001
From: visr # Ribasim.config is a submodule of solve!
BMI.finalize
Ribasim.config
— Module.module config
Ribasim
to handle the configuration of a Ribasim model. It is implemented using the Configurations package. A full configuration is represented by Config
, which is the main API. Ribasim.config is a submodule mainly to avoid name clashes between the configuration sections and the rest of Ribasim.#
Ribasim.AllocationModel
— Type.
Store information for a subnetwork used for allocation.
objectivetype: The name of the type of objective used allocationnetworkid: The ID of this allocation network nodeid: All the IDs of the nodes that are in this subnetwork nodeidmapping: Mapping Dictionary; modelnodeid => AGnodeid where such a correspondence exists (all AG node ids are in the values) nodeidmappinginverse: The inverse of nodeidmapping, Dictionary; AG node ID => model node ID allocgraphedgeidsuserdemand: AG user node ID => AG user inflow edge ID Source edge mapping: AG source node ID => subnetwork source edge ID graphallocation: The graph used for the allocation problems capacity: The capacity per edge of the allocation graph, as constrained by nodes that have a maxflowrate problem: The JuMP.jl model for solving the allocation problem Δt_allocation: The time interval between consecutive allocation solves
- +# Ribasim.AllocationModel
— Method.
Construct the JuMP.jl problem for allocation.
Definitions
@@ -287,7 +287,7 @@# Ribasim.Basin
— Type.
Requirements:
# Ribasim.Connectivity
— Type.
Store the connectivity information
graphflow, graphcontrol: directed graph with vertices equal to ids flow: store the flow on every flow edge edgeidsflow, edgeidscontrol: get the external edge id from (src, dst) edgeconnectiontypeflow, edgeconnectiontypescontrol: get (srcnodetype, dstnodetype) from edge id
if autodiff T = DiffCache{SparseArrays.SparseMatrixCSC{Float64, Int64}, Vector{Float64}} else T = SparseMatrixCSC{Float64, Int} end
- +# Ribasim.DiscreteControl
— Type.
nodeid: node ID of the DiscreteControl node; these are not unique but repeated by the amount of conditions of this DiscreteControl node listenfeatureid: the ID of the node/edge being condition on variable: the name of the variable in the condition greaterthan: The threshold value in the condition conditionvalue: The current value of each condition controlstate: Dictionary: node ID => (control state, control state start) logic_mapping: Dictionary: (control node ID, truth state) => control state record: Namedtuple with discrete control information for results
- +# Ribasim.FlatVector
— Type.
struct FlatVector{T} <: AbstractVector{T}
A FlatVector is an AbstractVector that iterates the T of a Vector{Vector{T}}
.
Each inner vector is assumed to be of equal length.
It is similar to Iterators.flatten
, though that doesn’t work with the Tables.Column
interface, which needs length
and getindex
support.
# Ribasim.FlowBoundary
— Type.
nodeid: node ID of the FlowBoundary node active: whether this node is active and thus contributes flow flowrate: target flow rate
- +# Ribasim.FractionalFlow
— Type.
Requirements:
# Ribasim.LevelBoundary
— Type.
node_id: node ID of the LevelBoundary node active: whether this node is active level: the fixed level of this ‘infinitely big basin’
- +# Ribasim.LinearResistance
— Type.
Requirements:
# Ribasim.ManningResistance
— Type.
This is a simple Manning-Gauckler reach connection.
# Ribasim.Model
— Type.
Model(config_path::AbstractString)
Model(config::Config)
Initialize a Model.
The Model struct is an initialized model, combined with the Config
used to create it and saved results. The Basic Model Interface (BMI) is implemented on the Model. A Model can be created from the path to a TOML configuration file, or a Config object.
# Ribasim.Outlet
— Type.
nodeid: node ID of the Outlet node active: whether this node is active and thus contributes flow flowrate: target flow rate minflowrate: The minimal flow rate of the outlet maxflowrate: The maximum flow rate of the outlet controlmapping: dictionary from (nodeid, controlstate) to target flow rate ispid_controlled: whether the flow rate of this outlet is governed by PID control
- +# Ribasim.PidControl
— Type.
PID control currently only supports regulating basin levels.
nodeid: node ID of the PidControl node active: whether this node is active and thus sets flow rates listennodeid: the id of the basin being controlled pidparams: a vector interpolation for parameters changing over time. The parameters are respectively target, proportional, integral, derivative, where the last three are the coefficients for the PID equation. error: the current error; basintarget - currentlevel
- +# Ribasim.Pump
— Type.
nodeid: node ID of the Pump node active: whether this node is active and thus contributes flow flowrate: target flow rate minflowrate: The minimal flow rate of the pump maxflowrate: The maximum flow rate of the pump controlmapping: dictionary from (nodeid, controlstate) to target flow rate ispid_controlled: whether the flow rate of this pump is governed by PID control
- +# Ribasim.TabulatedRatingCurve
— Type.
struct TabulatedRatingCurve{C}
Rating curve from level to discharge. The rating curve is a lookup table with linear interpolation in between. Relation can be updated in time, which is done by moving data from the time
field into the tables
, which is done in the update_tabulated_rating_curve
callback.
Type parameter C indicates the content backing the StructVector, which can be a NamedTuple of Vectors or Arrow Primitives, and is added to avoid type instabilities.
nodeid: node ID of the TabulatedRatingCurve node active: whether this node is active and thus contributes flows tables: The current Q(h) relationships time: The time table used for updating the tables controlmapping: dictionary from (nodeid, controlstate) to Q(h) and/or active state
- +# Ribasim.Terminal
— Type.
node_id: node ID of the Terminal node
- +# Ribasim.User
— Type.
demand: water flux demand of user per priority over time active: whether this node is active and thus demands water allocated: water flux currently allocated to user per priority returnfactor: the factor in [0,1] of how much of the abstracted water is given back to the system minlevel: The level of the source basin below which the user does not abstract priorities: All used priority values. Each user has a demand for all these priorities, which is 0.0 if it is not provided explicitly. record: Collected data of allocation optimizations for output file.
- +# Ribasim.config.Config
— Method.
Config(config_path::AbstractString; kwargs...)
Parse a TOML file to a Config. Keys can be overruled using keyword arguments. To overrule keys from a subsection, e.g. dt
from the solver
section, use underscores: solver_dt
.
BasicModelInterface.finalize
— Method.
finalize(model::Model)::Model BMI.
Write all results to the configured files.
- +# BasicModelInterface.initialize
— Method.
initialize(T::Type{Model}, config_path::AbstractString)::Model BMI.
Initialize a Model
from the path to the TOML configuration file.
# BasicModelInterface.initialize
— Method.
initialize(T::Type{Model}, config::Config)::Model BMI.
Initialize a Model
from a Config
.
# CommonSolve.solve!
— Method.
solve!(model::Model)::ODESolution
Solve a Model until the configured endtime
.
# Ribasim.add_constraints_absolute_value!
— Method.
Minimizing |expr| can be achieved by introducing a new variable exprabs and posing the following constraints: exprabs >= expr expr_abs >= -expr
- +# Ribasim.add_constraints_basin_allocation!
— Method.
Add the basin allocation constraints to the allocation problem; the allocations to the basins are bounded from above by the basin demand (these are set before each allocation solve). The constraint indices are allocation graph basin node IDs.
Constraint: allocation to basin <= basin demand
- +# Ribasim.add_constraints_capacity!
— Method.
Add the flow capacity constraints to the allocation problem. Only finite capacities get a constraint. The constraint indices are the allocation graph edge IDs.
Constraint: flow over edge <= edge capacity
- +# Ribasim.add_constraints_flow_conservation!
— Method.
Add the flow conservation constraints to the allocation problem. The constraint indices are allocgraph user node IDs.
Constraint: sum(flows out of node node) <= flows into node + flow from storage and vertical fluxes
- +# Ribasim.add_constraints_source!
— Method.
Add the source constraints to the allocation problem. The actual threshold values will be set before each allocation solve. The constraint indices are the allocation graph source node IDs.
Constraint: flow over source edge <= source flow in subnetwork
- +# Ribasim.add_constraints_user_returnflow!
— Method.
Add the user returnflow constraints to the allocation problem. The constraint indices are allocation graph user node IDs.
Constraint: outflow from user = return factor * inflow to user
- +# Ribasim.add_variables_absolute_value!
— Method.
Certain allocation distribution types use absolute values in the objective function. Since most optimization packages do not support the absolute value function directly, New variables are introduced that act as the absolute value of an expression by posing the appropriate constraints.
- +# Ribasim.add_variables_flow!
— Method.
Add the flow variables F to the allocation problem. The variable indices are the allocation graph edge IDs. Non-negativivity constraints are also immediately added to the flow variables.
- +# Ribasim.adjust_edge_capacities!
— Method.
Set the values of the edge capacities. 2 cases:
# Ribasim.allocate!
— Method.
Update the allocation optimization problem for the given subnetwork with the problem state and flows, solve the allocation problem and assign the results to the users.
- +# Ribasim.allocation_graph
— Method.
Build the graph used for the allocation problem.
- +# Ribasim.allocation_problem
— Method.
Construct the allocation problem for the current subnetwork as a JuMP.jl model.
- +# Ribasim.allocation_table
— Method.
Create an allocation result table for the saved data
- +# Ribasim.assign_allocations!
— Method.
Assign the allocations to the users as determined by the solution of the allocation problem.
- +# Ribasim.avoid_using_own_returnflow!
— Method.
Remove user return flow edges that are upstream of the user itself, and collect the IDs of the allocation graph node IDs of the users that do not have this problem.
- +# Ribasim.basin_bottom
— Method.
Return the bottom elevation of the basin with index i, or nothing if it doesn’t exist
- +# Ribasim.basin_bottoms
— Method.
Get the bottom on both ends of a node. If only one has a bottom, use that for both.
- +# Ribasim.basin_table
— Method.
Create the basin result table from the saved data
- +# Ribasim.create_callbacks
— Method.
Create the different callbacks that are used to store results and feed the simulation with new data. The different callbacks are combined to a CallbackSet that goes to the integrator. Returns the CallbackSet and the SavedValues for flow.
- +# Ribasim.create_graph
— Method.
Return a directed graph, and a mapping from source and target nodes to edge fid.
- +# Ribasim.create_storage_tables
— Method.
Read the Basin / profile table and return all area and level and computed storage values
- +# Ribasim.datetime_since
— Method.
datetime_since(t::Real, t0::DateTime)::DateTime
Convert a Real that represents the seconds passed since the simulation start to the nearest DateTime. This is used to convert between the solver’s inner float time, and the calendar.
- +# Ribasim.datetimes
— Method.
Get all saved times as a Vector{DateTime}
- +# Ribasim.discrete_control_affect!
— Method.
Change parameters based on the control logic.
- +# Ribasim.discrete_control_affect_downcrossing!
— Method.
An downcrossing means that a condition (always greater than) becomes false.
- +# Ribasim.discrete_control_affect_upcrossing!
— Method.
An upcrossing means that a condition (always greater than) becomes true.
- +# Ribasim.discrete_control_condition
— Method.
Listens for changes in condition truths.
- +# Ribasim.discrete_control_table
— Method.
Create a discrete control result table from the saved data
- +# Ribasim.expand_logic_mapping
— Method.
Replace the truth states in the logic mapping which contain wildcards with all possible explicit truth states.
- +# Ribasim.find_allocation_graph_edges!
— Method.
This loop finds allocgraph edges in several ways:
# Ribasim.findlastgroup
— Method.
For an element id
and a vector of elements ids
, get the range of indices of the last consecutive block of id
. Returns the empty range 1:0
if id
is not in ids
.
# 1 2 3 4 5 6 7 8 9
findlastgroup(2, [5,4,2,2,5,2,2,2,1])
Ribasim.# output
6:8
# Ribasim.findsorted
— Method.
Find the index of element x in a sorted collection a. Returns the index of x if it exists, or nothing if it doesn’t. If x occurs more than once, throw an error.
- +# Ribasim.flow_table
— Method.
Create a flow result table from the saved data
- +# Ribasim.formulate_basins!
— Method.
Smoothly let the evaporation flux go to 0 when at small water depths Currently at less than 0.1 m.
- +# Ribasim.formulate_flow!
— Method.
Directed graph: outflow is positive!
- +# Ribasim.formulate_flow!
— Method.
Conservation of energy for two basins, a and b:
h_a + v_a^2 / (2 * g) = h_b + v_b^2 / (2 * g) + S_f * L + C / 2 * g * (v_b^2 - v_a^2)
@@ -569,91 +569,91 @@ # Ribasim.formulate_flow!
— Method.
Directed graph: outflow is positive!
- +# Ribasim.get_area_and_level
— Method.
Compute the area and level of a basin given its storage. Also returns darea/dlevel as it is needed for the Jacobian.
- +# Ribasim.get_compressor
— Method.
Get the compressor based on the Results section
- +# Ribasim.get_fractional_flow_connected_basins
— Method.
Get the node type specific indices of the fractional flows and basins, that are consecutively connected to a node of given id.
- +# Ribasim.get_jac_prototype
— Method.
Get a sparse matrix whose sparsity matches the sparsity of the Jacobian of the ODE problem. All nodes are taken into consideration, also the ones that are inactive.
In Ribasim the Jacobian is typically sparse because each state only depends on a small number of other states.
Note: the name ‘prototype’ does not mean this code is a prototype, it comes from the naming convention of this sparsity structure in the differentialequations.jl docs.
- +# Ribasim.get_level
— Method.
Get the current water level of a node ID. The ID can belong to either a Basin or a LevelBoundary. storage: tells ForwardDiff whether this call is for differentiation or not
- +# Ribasim.get_node_id_mapping
— Method.
Get:
# Ribasim.get_node_in_out_edges
— Method.
Get two dictionaries, where:
# Ribasim.get_scalar_interpolation
— Method.
Linear interpolation of a scalar with constant extrapolation.
- +# Ribasim.get_storage_from_level
— Method.
Get the storage of a basin from its level.
- +# Ribasim.get_storages_and_levels
— Method.
Get the storage and level of all basins as matrices of nbasin × ntime
- +# Ribasim.get_storages_from_levels
— Method.
Compute the storages of the basins based on the water level of the basins.
- +# Ribasim.get_tstops
— Method.
From an iterable of DateTimes, find the times the solver needs to stop
- +# Ribasim.get_value
— Method.
Get a value for a condition. Currently supports getting levels from basins and flows from flow boundaries.
- +# Ribasim.id_index
— Method.
Get the index of an ID in a set of indices.
- +# Ribasim.input_path
— Method.
Construct a path relative to both the TOML directory and the optional input_dir
# Ribasim.is_flow_constraining
— Method.
Whether the given node node is flow constraining by having a maximum flow rate.
- +# Ribasim.is_flow_direction_constraining
— Method.
Whether the given node is flow direction constraining (only in direction of edges).
- +# Ribasim.load_data
— Method.
load_data(db::DB, config::Config, nodetype::Symbol, kind::Symbol)::Union{Table, Query, Nothing}
Load data from Arrow files if available, otherwise the database. Returns either an Arrow.Table
, SQLite.Query
or nothing
if the data is not present.
# Ribasim.load_structvector
— Method.
load_structvector(db::DB, config::Config, ::Type{T})::StructVector{T}
Load data from Arrow files if available, otherwise the database. Always returns a StructVector of the given struct type T, which is empty if the table is not found. This function validates the schema, and enforces the required sort order.
- +# Ribasim.nodefields
— Method.
Get all node fieldnames of the parameter object.
- +# Ribasim.nodetype
— Method.
From a SchemaVersion(“ribasim.flowboundary.static”, 1) return (:FlowBoundary, :static)
- +# Ribasim.parse_static_and_time
— Method.
Process the data in the static and time tables for a given node type. The ‘defaults’ named tuple dictates how missing data is filled in. ‘time_interpolatables’ is a vector of Symbols of parameter names for which a time interpolation (linear) object must be constructed. The control mapping for DiscreteControl is also constructed in this function. This function currently does not support node states that are defined by more than one row in a table, as is the case for TabulatedRatingCurve.
- +# Ribasim.path_exists_in_graph
— Method.
Find out whether a path exists between a start node and end node in the given graph.
- +# Ribasim.process_allocation_graph_edges!
— Method.
For the composite allocgraph edges:
# Ribasim.profile_storage
— Method.
Calculate a profile storage by integrating the areas over the levels
- +# Ribasim.qh_interpolation
— Method.
From a table with columns nodeid, discharge (Q) and level (h), create a LinearInterpolation from level to discharge for a given nodeid.
- +# Ribasim.reduction_factor
— Method.
Function that goes smoothly from 0 to 1 in the interval [0,threshold], and is constant outside this interval.
- +# Ribasim.results_path
— Method.
Construct a path relative to both the TOML directory and the optional results_dir
# Ribasim.run
— Method.
run(config_file::AbstractString)::Model
run(config::Config)::Model
Run a Model
, given a path to a TOML configuration file, or a Config object. Running a model includes initialization, solving to the end with [
solve!](@ref)
and writing results with BMI.finalize
.
# Ribasim.save_flow
— Method.
Copy the current flow to the SavedValues
- +# Ribasim.scalar_interpolation_derivative
— Method.
Derivative of scalar interpolation.
- +# Ribasim.seconds_since
— Method.
seconds_since(t::DateTime, t0::DateTime)::Float64
Convert a DateTime to a float that is the number of seconds since the start of the simulation. This is used to convert between the solver’s inner float time, and the calendar.
- +# Ribasim.set_current_value!
— Method.
From a timeseries table time
, load the most recent applicable data into table
. table
must be a NamedTuple of vectors with all variables that must be loaded. The most recent applicable data is non-NaN data for a given ID that is on or before t
.
# Ribasim.set_objective_priority!
— Method.
Set the objective for the given priority. For an objective with absolute values this also involves adjusting constraints.
- +# Ribasim.set_source_flows!
— Method.
Set the source flows as capacities on edges in the AG.
- +# Ribasim.set_static_value!
— Method.
Load data from a source table static
into a destination table
. Data is matched based on the node_id, which is sorted.
# Ribasim.set_table_row!
— Method.
Update table
at row index i
, with the values of a given row. table
must be a NamedTuple of vectors with all variables that must be loaded. The row must contain all the column names that are present in the table. If a value is NaN, it is not set.
# Ribasim.sorted_table!
— Method.
Depending on if a table can be sorted, either sort it or assert that it is sorted.
Tables loaded from the database into memory can be sorted. Tables loaded from Arrow files are memory mapped and can therefore not be sorted.
- +# Ribasim.timesteps
— Method.
Get all saved times in seconds since start
- +# Ribasim.update_allocation!
— Method.
Solve the allocation problem for all users and assign allocated abstractions to user nodes.
- +# Ribasim.update_basin
— Method.
Load updates from ‘Basin / time’ into the parameters
- +# Ribasim.update_jac_prototype!
— Method.
Method for nodes that do not contribute to the Jacobian
- +# Ribasim.update_jac_prototype!
— Method.
The controlled basin affects itself and the basins upstream and downstream of the controlled pump affect eachother if there is a basin upstream of the pump. The state for the integral term and the controlled basin affect eachother, and the same for the integral state and the basin upstream of the pump if it is indeed a basin.
- +# Ribasim.update_jac_prototype!
— Method.
If both the unique node upstream and the unique node downstream of these nodes are basins, then these directly depend on eachother and affect the Jacobian 2x Basins always depend on themselves.
- +# Ribasim.update_jac_prototype!
— Method.
If both the unique node upstream and the nodes down stream (or one node further if a fractional flow is in between) are basins, then the downstream basin depends on the upstream basin(s) and affect the Jacobian as many times as there are downstream basins Upstream basins always depend on themselves.
- +# Ribasim.update_tabulated_rating_curve!
— Method.
Load updates from ‘TabulatedRatingCurve / time’ into the parameters
- +# Ribasim.valid_discrete_control
— Method.
Check:
# Ribasim.valid_edge_types
— Method.
Check that only supported edge types are declared.
- +# Ribasim.valid_edges
— Method.
Test for each node given its node type whether the nodes that
are downstream (‘down-edge’) of this node are of an allowed type
- +# Ribasim.valid_flow_rates
— Method.
Test whether static or discrete controlled flow rates are indeed non-negative.
- +# Ribasim.valid_fractional_flow
— Method.
Check that nodes that have fractional flow outneighbors do not have any other type of outneighbor, that the fractions leaving a node add up to ≈1 and that the fractions are non-negative.
- +# Ribasim.valid_n_neighbors
— Method.
Test for each node given its node type whether it has an allowed number of flow/control inneighbors and outneighbors
- +# Ribasim.valid_profiles
— Method.
Check whether the profile data has no repeats in the levels and the areas start positive.
- +# Ribasim.valid_sources
— Method.
The source nodes must only have one outneighbor.
- +# Ribasim.water_balance!
— Method.
The right hand side function of the system of ODEs set up by Ribasim.
- +# Ribasim.write_arrow
— Method.
Write a result table to disk as an Arrow file
- +# Ribasim.config.algorithm
— Method.
Create an OrdinaryDiffEqAlgorithm from solver config
- +# Ribasim.config.snake_case
— Method.
Convert a string from CamelCase to snake_case.
- + @@ -794,7 +794,7 @@# Ribasim.config.@addfields
— Macro.
Add fieldnames with Union{String, Nothing} type to struct expression. Requires (option?) use before it.
- +# Ribasim.config.@addnodetypes
— Macro.
Add all TableOption subtypes as fields to struct expression. Requires (option?) use before it.
- + @@ -875,8 +875,8 @@Ribasim.flow_table
Ribasim.formulate_basins!
Ribasim.formulate_flow!
Ribasim.formulate_flow!
Ribasim.formulate_flow!
Ribasim.formulate_flow!
Ribasim.get_area_and_level
Ribasim.get_compressor
Ribasim.get_fractional_flow_connected_basins
Ribasim.timesteps
Ribasim.update_allocation!
Ribasim.update_basin
Ribasim.update_jac_prototype!
Ribasim.update_jac_prototype!
Ribasim.update_jac_prototype!
Ribasim.update_jac_prototype!
Ribasim.update_jac_prototype!
Ribasim.update_jac_prototype!
Ribasim.update_tabulated_rating_curve!
Ribasim.valid_discrete_control
Ribasim.valid_edge_types
<>:31: SyntaxWarning: invalid escape sequence '\p'
<>:31: SyntaxWarning: invalid escape sequence '\p'
-/tmp/ipykernel_4374/665069857.py:31: SyntaxWarning: invalid escape sequence '\p'
+/tmp/ipykernel_4389/665069857.py:31: SyntaxWarning: invalid escape sequence '\p'
ax.set_ylabel("$\phi(x;p)$", fontsize=fontsize)
<matplotlib.legend.Legend at 0x7f4612481c40>
+<matplotlib.legend.Legend at 0x7f32cbb52240>