Code
using Ribasim
@@ -648,45 +648,45 @@ println(p.allocation.allocation_models[1].problem)
Min F_abs_user[User #3] + F_abs_user[User #13] + F_abs_user[User #6] + F_abs_basin[Basin #12] + F_abs_basin[Basin #5] + F_abs_basin[Basin #2]
+Min F_abs_user[User #13] + F_abs_user[User #6] + F_abs_user[User #3] + F_abs_basin[Basin #12] + F_abs_basin[Basin #2] + F_abs_basin[Basin #5]
Subject to
- flow_conservation[Basin #12] : F[(Basin #12, User #13)] - F[(TabulatedRatingCurve #7, Basin #12)] + F_basin_in[Basin #12] - F_basin_out[Basin #12] = 0
+ flow_conservation[Basin #12] : -F[(TabulatedRatingCurve #7, Basin #12)] + F[(Basin #12, User #13)] + F_basin_in[Basin #12] - F_basin_out[Basin #12] = 0
+ flow_conservation[Basin #2] : -F[(FlowBoundary #1, Basin #2)] + F[(Basin #2, User #3)] + F[(Basin #2, Basin #5)] - F[(Basin #5, Basin #2)] + F_basin_in[Basin #2] - F_basin_out[Basin #2] = 0
flow_conservation[Basin #5] : F[(Basin #5, User #6)] + F[(Basin #5, TabulatedRatingCurve #7)] - F[(Basin #2, Basin #5)] + F[(Basin #5, Basin #2)] + F_basin_in[Basin #5] - F_basin_out[Basin #5] = 0
- flow_conservation[Basin #2] : F[(Basin #2, Basin #5)] + F[(Basin #2, User #3)] - F[(Basin #5, Basin #2)] - F[(FlowBoundary #1, Basin #2)] + F_basin_in[Basin #2] - F_basin_out[Basin #2] = 0
- abs_positive_user[User #3] : -F[(Basin #2, User #3)] + F_abs_user[User #3] ≥ 0
abs_positive_user[User #13] : -F[(Basin #12, User #13)] + F_abs_user[User #13] ≥ 0
abs_positive_user[User #6] : -F[(Basin #5, User #6)] + F_abs_user[User #6] ≥ -1.5
- abs_negative_user[User #3] : F[(Basin #2, User #3)] + F_abs_user[User #3] ≥ 0
+ abs_positive_user[User #3] : -F[(Basin #2, User #3)] + F_abs_user[User #3] ≥ 0
abs_negative_user[User #13] : F[(Basin #12, User #13)] + F_abs_user[User #13] ≥ 0
abs_negative_user[User #6] : F[(Basin #5, User #6)] + F_abs_user[User #6] ≥ 1.5
+ abs_negative_user[User #3] : F[(Basin #2, User #3)] + F_abs_user[User #3] ≥ 0
abs_positive_basin[Basin #12] : -F_basin_in[Basin #12] + F_abs_basin[Basin #12] ≥ 0
- abs_positive_basin[Basin #5] : -F_basin_in[Basin #5] + F_abs_basin[Basin #5] ≥ 0
abs_positive_basin[Basin #2] : -F_basin_in[Basin #2] + F_abs_basin[Basin #2] ≥ 0
+ abs_positive_basin[Basin #5] : -F_basin_in[Basin #5] + F_abs_basin[Basin #5] ≥ 0
abs_negative_basin[Basin #12] : F_basin_in[Basin #12] + F_abs_basin[Basin #12] ≥ 0
- abs_negative_basin[Basin #5] : F_basin_in[Basin #5] + F_abs_basin[Basin #5] ≥ 0
abs_negative_basin[Basin #2] : F_basin_in[Basin #2] + F_abs_basin[Basin #2] ≥ 0
+ abs_negative_basin[Basin #5] : F_basin_in[Basin #5] + F_abs_basin[Basin #5] ≥ 0
source[(FlowBoundary #1, Basin #2)] : F[(FlowBoundary #1, Basin #2)] ≤ 1
return_flow[User #13] : F[(User #13, Terminal #10)] ≤ 0
fractional_flow[(TabulatedRatingCurve #7, Basin #12)] : -0.4 F[(Basin #5, TabulatedRatingCurve #7)] + F[(TabulatedRatingCurve #7, Basin #12)] ≤ 0
basin_outflow[Basin #12] : F_basin_out[Basin #12] ≤ 0
- basin_outflow[Basin #5] : F_basin_out[Basin #5] ≤ 0
basin_outflow[Basin #2] : F_basin_out[Basin #2] ≤ 0
+ basin_outflow[Basin #5] : F_basin_out[Basin #5] ≤ 0
+ F[(FlowBoundary #1, Basin #2)] ≥ 0
F[(Basin #5, User #6)] ≥ 0
- F[(TabulatedRatingCurve #7, Terminal #10)] ≥ 0
F[(Basin #5, TabulatedRatingCurve #7)] ≥ 0
- F[(Basin #2, Basin #5)] ≥ 0
+ F[(TabulatedRatingCurve #7, Terminal #10)] ≥ 0
+ F[(TabulatedRatingCurve #7, Basin #12)] ≥ 0
F[(Basin #2, User #3)] ≥ 0
- F[(Basin #12, User #13)] ≥ 0
F[(User #13, Terminal #10)] ≥ 0
+ F[(Basin #12, User #13)] ≥ 0
+ F[(Basin #2, Basin #5)] ≥ 0
F[(Basin #5, Basin #2)] ≥ 0
- F[(FlowBoundary #1, Basin #2)] ≥ 0
- F[(TabulatedRatingCurve #7, Basin #12)] ≥ 0
F_basin_in[Basin #12] ≥ 0
- F_basin_in[Basin #5] ≥ 0
F_basin_in[Basin #2] ≥ 0
+ F_basin_in[Basin #5] ≥ 0
F_basin_out[Basin #12] ≥ 0
- F_basin_out[Basin #5] ≥ 0
F_basin_out[Basin #2] ≥ 0
+ F_basin_out[Basin #5] ≥ 0
Here \(p > 0\) is the threshold value which determines the interval \([0,p]\) of the smooth transition between \(0\) and \(1\), see the plot below.
-
+
Code
import numpy as np
diff --git a/core/usage.html b/core/usage.html
index 59f5726c4..9867ebd86 100644
--- a/core/usage.html
+++ b/core/usage.html
@@ -399,31 +399,30 @@ 1 Configuration f
[solver]
algorithm = "QNDF" # optional, default "QNDF"
saveat = 86400 # optional, default 86400, 0 saves every timestep, inf saves only at start- and endtime
-adaptive = true # optional, default true
-dt = 0.0 # optional when adaptive = true, default automatically determined
-dtmin = 0.0 # optional, default 0.0
-dtmax = 0.0 # optional, default length of simulation
-force_dtmin = false # optional, default false
-abstol = 1e-6 # optional, default 1e-6
-reltol = 1e-5 # optional, default 1e-5
-maxiters = 1e9 # optional, default 1e9
-sparse = true # optional, default true
-autodiff = true # optional, default true
-
-[logging]
-# defines the logging level of Ribasim
-verbosity = "info" # optional, default "info", can otherwise be "debug", "warn" or "error"
-timing = false # optional, whether to log debug timing statements
-
-[results]
-# These results files are always written
-compression = true # optional, default true, using zstd compression
-compression_level = 6 # optional, default 6
+dt = 60.0 # optional, remove for adaptive time stepping
+dtmin = 0.0 # optional, default 0.0
+dtmax = 0.0 # optional, default length of simulation
+force_dtmin = false # optional, default false
+abstol = 1e-6 # optional, default 1e-6
+reltol = 1e-5 # optional, default 1e-5
+maxiters = 1e9 # optional, default 1e9
+sparse = true # optional, default true
+autodiff = true # optional, default true
+
+[logging]
+# defines the logging level of Ribasim
+verbosity = "info" # optional, default "info", can otherwise be "debug", "warn" or "error"
+timing = false # optional, whether to log debug timing statements
+
+[results]
+# These results files are always written
+compression = true # optional, default true, using zstd compression
+compression_level = 6 # optional, default 6
1.1 Solver settings
-The solver section in the configuration file is entirely optional, since we aim to use defaults that will generally work well. Common reasons to modify the solver settings are to adjust the calculation or result stepsizes: adaptive
, dt
, and saveat
. If your model does not converge, or your performance is lower than expected, it can help to adjust other solver settings as well.
-The default solver algorithm = "QNDF"
, which is a multistep method similar to Matlab’s ode15s
(Shampine and Reichelt 1997). It is an implicit method that supports the default adaptive = true
timestepping. The full list of available solvers is: QNDF
, Rosenbrock23
, TRBDF2
, Rodas5
, KenCarp4
, Tsit5
, RK4
, ImplicitEuler
, Euler
. Information on the solver algorithms can be found on the ODE solvers page.
-The dt
controls the stepsize. When adaptive = true
, dt
only applies to the initial stepsize, and by default it is automatically determined. When adaptive = false
a suitable dt
must always be provided. The value is in seconds, so dt = 3600.0
corresponds to an hourly timestep. When adaptive = true
, dtmin
and dtmax
control the minimum and maximum allowed dt
. If a smaller dt
than dtmin
is needed to meet the set error tolerances, the simulation stops, unless force_dtmin
is set to true
. force_dtmin
is off by default to ensure an accurate solution.
+The solver section in the configuration file is entirely optional, since we aim to use defaults that will generally work well. Common reasons to modify the solver settings are to adjust the calculation or result stepsizes: dt
, and saveat
. If your model does not converge, or your performance is lower than expected, it can help to adjust other solver settings as well.
+The default solver algorithm = "QNDF"
, which is a multistep method similar to Matlab’s ode15s
(Shampine and Reichelt 1997). It is an implicit method that supports the default adaptive timestepping. The full list of available solvers is: QNDF
, Rosenbrock23
, TRBDF2
, Rodas5
, KenCarp4
, Tsit5
, RK4
, ImplicitEuler
, Euler
. Information on the solver algorithms can be found on the ODE solvers page.
+By default Ribasim uses adaptive timestepping, though not all algorithms support adaptive timestepping. To use fixed timesteps, provide a timestep size in seconds; dt = 3600.0
corresponds to an hourly timestep. With adaptive timestepping, dtmin
and dtmax
control the minimum and maximum allowed dt
. If a smaller dt
than dtmin
is needed to meet the set error tolerances, the simulation stops, unless force_dtmin
is set to true
. force_dtmin
is off by default to ensure an accurate solution.
The default result stepsize, saveat = 86400
will save results after every day that passed. The calculation and result stepsize need not be the same. If you wish to save every calculation step, set saveat = 0
. If you wish to not save any intermediate steps, set saveat = inf
.
The Jacobian matrix provides information about the local sensitivity of the model with respect to changes in the states. For implicit solvers it must be calculated often, which can be expensive to do. There are several methods to do this. By default Ribasim uses a Jacobian derived automatically using ForwardDiff.jl with memory management provided by PreallocationTools.jl. If this is not used by setting autodiff = false
, the Jacobian is calculated with a finite difference method, which can be less accurate and more expensive.
By default the Jacobian matrix is a sparse matrix (sparse = true
). Since each state typically only depends on a small number of other states, this is generally more efficient, especially for larger models. The sparsity structure is calculated from the network and provided as a Jacobian prototype to the solver. For small or highly connected models it could be faster to use a dense Jacobian matrix instead by setting sparse = false
.
diff --git a/core/validation.html b/core/validation.html
index d30ab3aba..867b81575 100644
--- a/core/validation.html
+++ b/core/validation.html
@@ -262,7 +262,7 @@ Validation
1 Connectivity
In the table below, each column shows which node types are allowed to be downstream (or ‘down-control’) of the node type at the top of the column.
-
+
Code
using Ribasim
@@ -546,7 +546,7 @@ 1 Connectivity
2 Neighbor amounts
The table below shows for each node type between which bounds the amount of in- and outneighbors must be, for both flow and control edges.
-
+
Code
= Vector{String}()
diff --git a/python/examples_files/figure-html/cell-71-output-1.png b/python/examples_files/figure-html/cell-71-output-1.png
index e0f14293b..5c654f06b 100644
Binary files a/python/examples_files/figure-html/cell-71-output-1.png and b/python/examples_files/figure-html/cell-71-output-1.png differ
diff --git a/python/test-models.html b/python/test-models.html
index ce3785787..be9609a16 100644
--- a/python/test-models.html
+++ b/python/test-models.html
@@ -227,7 +227,7 @@ flow_in_min Test models
Ribasim developers use the following models in their testbench and in order to test new features.
-
+
Code
import ribasim_testmodels
diff --git a/search.json b/search.json
index 915ae6e2d..a3d89a88c 100644
--- a/search.json
+++ b/search.json
@@ -26,7 +26,7 @@
"href": "build/index.html#functions",
"title": "1 API Reference",
"section": "1.3 Functions",
- "text": "1.3 Functions\n# BasicModelInterface.finalize — Method.\nBMI.finalize(model::Model)::Model\nWrite all results to the configured files.\nsource\n# BasicModelInterface.initialize — Method.\nBMI.initialize(T::Type{Model}, config_path::AbstractString)::Model\nInitialize a Model from the path to the TOML configuration file.\nsource\n# CommonSolve.solve! — Method.\nsolve!(model::Model)::ODESolution\nSolve a Model until the configured endtime.\nsource\n# Ribasim.add_basin_term! — Method.\nAdd a term to the expression of the objective function corresponding to the demand of a basin.\nsource\n# Ribasim.add_constraints_absolute_value! — Method.\nMinimizing |expr| can be achieved by introducing a new variable exprabs and posing the following constraints: exprabs >= expr expr_abs >= -expr\nsource\n# Ribasim.add_constraints_absolute_value_basin! — Method.\nAdd constraints so that variables Fabsbasin act as the absolute value of the expression comparing flow to a basin to its demand.\nsource\n# Ribasim.add_constraints_absolute_value_user! — Method.\nAdd constraints so that variables Fabsuser act as the absolute value of the expression comparing flow to an user to its demand.\nsource\n# Ribasim.add_constraints_basin_flow! — Method.\nAdd the basin flow constraints to the allocation problem. The constraint indices are the basin node IDs.\nConstraint: flow out of basin <= basin capacity\nsource\n# Ribasim.add_constraints_capacity! — Method.\nAdd the flow capacity constraints to the allocation problem. Only finite capacities get a constraint. The constraint indices are (edgesourceid, edgedstid).\nConstraint: flow over edge <= edge capacity\nsource\n# Ribasim.add_constraints_flow_conservation! — Method.\nAdd the flow conservation constraints to the allocation problem. The constraint indices are user node IDs.\nConstraint: sum(flows out of node node) == flows into node + flow from storage and vertical fluxes\nsource\n# Ribasim.add_constraints_fractional_flow! — Method.\nAdd the fractional flow constraints to the allocation problem. The constraint indices are allocation edges over a fractional flow node.\nConstraint: flow after fractional_flow node <= fraction * inflow\nsource\n# Ribasim.add_constraints_source! — Method.\nAdd the source constraints to the allocation problem. The actual threshold values will be set before each allocation solve. The constraint indices are (edgesourceid, edgedstid).\nConstraint: flow over source edge <= source flow in subnetwork\nsource\n# Ribasim.add_constraints_user_returnflow! — Method.\nAdd the user returnflow constraints to the allocation problem. The constraint indices are user node IDs.\nConstraint: outflow from user <= return factor * inflow to user\nsource\n# Ribasim.add_flow! — Method.\nAdd the given flow q to the flow over the edge on the horizontal (self-loop) edge from id to id.\nsource\n# Ribasim.add_flow! — Method.\nAdd the given flow q to the existing flow over the edge between the given nodes.\nsource\n# Ribasim.add_objective_term! — Method.\nAdd a term to the objective function given by the objective type, depending in the provided flow variable and the associated demand.\nsource\n# Ribasim.add_subnetwork_connections! — Method.\nAdd the edges connecting the main network work to a subnetwork to both the main network and subnetwork allocation network.\nsource\n# Ribasim.add_user_term! — Method.\nAdd a term to the expression of the objective function corresponding to the demand of a user.\nsource\n# Ribasim.add_variables_absolute_value! — Method.\nCertain 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.\nsource\n# Ribasim.add_variables_basin! — Method.\nAdd the variables for supply/demand of a basin to the problem. The variable indices are the node_ids of the basins in the subnetwork.\nsource\n# Ribasim.add_variables_flow! — Method.\nAdd the flow variables F to the allocation problem. The variable indices are (edgesourceid, edgedstid). Non-negativivity constraints are also immediately added to the flow variables.\nsource\n# Ribasim.adjust_basin_capacities! — Method.\nSet the values of the basin outflows. 2 cases:\n\nBefore the first allocation solve, set the capacities to their full capacity if there is surplus storage;\nBefore an allocation solve, subtract the flow used by allocation for the previous priority from the capacities.\n\nsource\n# Ribasim.adjust_edge_capacities! — Method.\nSet the values of the edge capacities. 2 cases:\n\nBefore the first allocation solve, set the edge capacities to their full capacity;\nBefore an allocation solve, subtract the flow used by allocation for the previous priority from the edge capacities.\n\nsource\n# Ribasim.adjust_source_capacities! — Method.\nAdjust the source flows.\nsource\n# Ribasim.all_neighbor_labels_type — Method.\nGet the in- and outneighbor node IDs of the given node ID (label) over the given edge type in the graph.\nsource\n# Ribasim.allocate! — Method.\nUpdate 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.\nsource\n# Ribasim.allocation_graph — Method.\nBuild the graph used for the allocation problem.\nsource\n# Ribasim.allocation_graph_used_nodes! — Method.\nFind all nodes in the subnetwork which will be used in the allocation network. Some nodes are skipped to optimize allocation optimization.\nsource\n# Ribasim.allocation_path_exists_in_graph — Method.\nFind out whether a path exists between a start node and end node in the given allocation network.\nsource\n# Ribasim.allocation_problem — Method.\nConstruct the allocation problem for the current subnetwork as a JuMP.jl model.\nsource\n# Ribasim.allocation_table — Method.\nCreate an allocation result table for the saved data\nsource\n# Ribasim.assign_allocations! — Method.\nAssign the allocations to the users as determined by the solution of the allocation problem.\nsource\n# Ribasim.avoid_using_own_returnflow! — Method.\nRemove allocation user return flow edges that are upstream of the user itself.\nsource\n# Ribasim.basin_bottom — Method.\nReturn the bottom elevation of the basin with index i, or nothing if it doesn’t exist\nsource\n# Ribasim.basin_bottoms — Method.\nGet the bottom on both ends of a node. If only one has a bottom, use that for both.\nsource\n# Ribasim.basin_table — Method.\nCreate the basin result table from the saved data\nsource\n# Ribasim.create_callbacks — Method.\nCreate 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.\nsource\n# Ribasim.create_graph — Method.\nReturn a directed metagraph with data of nodes (NodeMetadata): NodeMetadata\nand data of edges (EdgeMetadata): EdgeMetadata\nsource\n# Ribasim.create_storage_tables — Method.\nRead the Basin / profile table and return all area and level and computed storage values\nsource\n# Ribasim.datetime_since — Method.\ndatetime_since(t::Real, t0::DateTime)::DateTime\nConvert 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.\nsource\n# Ribasim.datetimes — Method.\nGet all saved times as a Vector{DateTime}\nsource\n# Ribasim.discrete_control_affect! — Method.\nChange parameters based on the control logic.\nsource\n# Ribasim.discrete_control_affect_downcrossing! — Method.\nAn downcrossing means that a condition (always greater than) becomes false.\nsource\n# Ribasim.discrete_control_affect_upcrossing! — Method.\nAn upcrossing means that a condition (always greater than) becomes true.\nsource\n# Ribasim.discrete_control_condition — Method.\nListens for changes in condition truths.\nsource\n# Ribasim.discrete_control_table — Method.\nCreate a discrete control result table from the saved data\nsource\n# Ribasim.expand_logic_mapping — Method.\nReplace the truth states in the logic mapping which contain wildcards with all possible explicit truth states.\nsource\n# Ribasim.find_allocation_graph_edges! — Method.\nThis loop finds allocation network edges in several ways:\n\nBetween allocation network nodes whose equivalent in the subnetwork are directly connected\nBetween allocation network nodes whose equivalent in the subnetwork are connected with one or more allocation network nodes in between\n\nsource\n# Ribasim.find_subnetwork_connections! — Method.\nFind the edges from the main network to a subnetwork.\nsource\n# Ribasim.findlastgroup — Method.\nFor 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.\nsource\n# Ribasim.findsorted — Method.\nFind 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.\nsource\n# Ribasim.flow_table — Method.\nCreate a flow result table from the saved data\nsource\n# Ribasim.formulate_basins! — Method.\nSmoothly let the evaporation flux go to 0 when at small water depths Currently at less than 0.1 m.\nsource\n# Ribasim.formulate_flow! — Method.\nDirected graph: outflow is positive!\nsource\n# Ribasim.formulate_flow! — Method.\nConservation of energy for two basins, a and b:\nh_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)\nWhere:\n\nha, hb are the heads at basin a and b.\nva, vb are the velocities at basin a and b.\ng is the gravitational constant.\nS_f is the friction slope.\nC is an expansion or extraction coefficient.\n\nWe assume velocity differences are negligible (va = vb):\nh_a = h_b + S_f * L\nThe friction losses are approximated by the Gauckler-Manning formula:\nQ = A * (1 / n) * R_h^(2/3) * S_f^(1/2)\nWhere:\n\nWhere A is the cross-sectional area.\nV is the cross-sectional average velocity.\nn is the Gauckler-Manning coefficient.\nR_h is the hydraulic radius.\nS_f is the friction slope.\n\nThe hydraulic radius is defined as:\nR_h = A / P\nWhere P is the wetted perimeter.\nThe average of the upstream and downstream water depth is used to compute cross-sectional area and hydraulic radius. This ensures that a basin can receive water after it has gone dry.\nsource\n# Ribasim.formulate_flow! — Method.\nDirected graph: outflow is positive!\nsource\n# Ribasim.get_area_and_level — Method.\nCompute the area and level of a basin given its storage. Also returns darea/dlevel as it is needed for the Jacobian.\nsource\n# Ribasim.get_basin_capacity — Method.\nGet 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). Storages are converted to flows by dividing by the allocation timestep.\nsource\n# Ribasim.get_basin_data — Method.\nGet several variables associated with a basin:\n\nIts current storage\nThe allocation update interval\nThe influx (sum of instantaneous vertical fluxes of the basin)\nThe index of the connected target_level node (0 if such a node does not exist)\nThe index of the basin\n\nsource\n# Ribasim.get_basin_demand — Method.\nGet 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). Storages are converted to flows by dividing by the allocation timestep.\nsource\n# Ribasim.get_chunk_sizes — Method.\nGet the chunk sizes for DiffCache; differentiation w.r.t. u and t (the latter only if a Rosenbrock algorithm is used).\nsource\n# Ribasim.get_compressor — Method.\nGet the compressor based on the Results section\nsource\n# Ribasim.get_flow — Method.\nGet the flow over the given horizontal (selfloop) edge (val is needed for get_tmp from ForwardDiff.jl).\nsource\n# Ribasim.get_flow — Method.\nGet the flow over the given edge (val is needed for get_tmp from ForwardDiff.jl).\nsource\n# Ribasim.get_fractional_flow_connected_basins — Method.\nGet the node type specific indices of the fractional flows and basins, that are consecutively connected to a node of given id.\nsource\n# Ribasim.get_jac_prototype — Method.\nGet 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.\nIn Ribasim the Jacobian is typically sparse because each state only depends on a small number of other states.\nNote: 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.\nsource\n# Ribasim.get_level — Method.\nGet 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\nsource\n# Ribasim.get_scalar_interpolation — Method.\nLinear interpolation of a scalar with constant extrapolation.\nsource\n# Ribasim.get_storage_from_level — Method.\nGet the storage of a basin from its level.\nsource\n# Ribasim.get_storages_and_levels — Method.\nGet the storage and level of all basins as matrices of nbasin × ntime\nsource\n# Ribasim.get_storages_from_levels — Method.\nCompute the storages of the basins based on the water level of the basins.\nsource\n# Ribasim.get_tstops — Method.\nFrom an iterable of DateTimes, find the times the solver needs to stop\nsource\n# Ribasim.get_value — Method.\nGet a value for a condition. Currently supports getting levels from basins and flows from flow boundaries.\nsource\n# Ribasim.id_index — Method.\nGet the index of an ID in a set of indices.\nsource\n# Ribasim.indicate_allocation_flow! — Method.\nAdd to the edge metadata that the given edge is used for allocation flow. If the edge does not exist, it is created.\nsource\n# Ribasim.inflow_id — Method.\nGet the unique inneighbor over a flow edge.\nsource\n# Ribasim.inflow_ids — Method.\nGet the inneighbors over flow edges.\nsource\n# Ribasim.inflow_ids_allocation — Method.\nGet the inneighbors of the given ID such that the connecting edge is an allocation flow edge.\nsource\n# Ribasim.inneighbor_labels_type — Method.\nGet the inneighbor node IDs of the given node ID (label) over the given edge type in the graph.\nsource\n# Ribasim.inoutflow_ids — Method.\nGet the in- and outneighbors over flow edges.\nsource\n# Ribasim.is_allocation_source — Method.\nFind out whether the given edge is a source for an allocation network.\nsource\n# Ribasim.is_current_module — Method.\nis_current_module(log::LogMessageType)::Bool\nReturns true if the log message is from the current module or a submodule.\n\nSee https://github.com/JuliaLogging/LoggingExtras.jl/blob/d35e7c8cfc197853ee336ace17182e6ed36dca24/src/CompositionalLoggers/earlyfiltered.jl#L39\nfor the information available in log.\nsource\n# Ribasim.is_flow_constraining — Method.\nWhether the given node node is flow constraining by having a maximum flow rate.\nsource\n# Ribasim.is_flow_direction_constraining — Method.\nWhether the given node is flow direction constraining (only in direction of edges).\nsource\n# Ribasim.load_data — Method.\nload_data(db::DB, config::Config, nodetype::Symbol, kind::Symbol)::Union{Table, Query, Nothing}\nLoad data from Arrow files if available, otherwise the database. Returns either an Arrow.Table, SQLite.Query or nothing if the data is not present.\nsource\n# Ribasim.load_structvector — Method.\nload_structvector(db::DB, config::Config, ::Type{T})::StructVector{T}\nLoad 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.\nsource\n# Ribasim.low_storage_factor — Method.\nIf id is a Basin with storage below the threshold, return a reduction factor != 1\nsource\n# Ribasim.main — Method.\nmain(toml_path::AbstractString)::Cint\nmain(ARGS::Vector{String})::Cint\nmain()::Cint\nThis is the main entry point of the application. Performs argument parsing and sets up logging for both terminal and file. Calls Ribasim.run() and handles exceptions to convert to exit codes.\nsource\n# Ribasim.metadata_from_edge — Method.\nGet the metadata of an edge in the graph from an edge of the underlying DiGraph.\nsource\n# Ribasim.nodefields — Method.\nGet all node fieldnames of the parameter object.\nsource\n# Ribasim.nodetype — Method.\nFrom a SchemaVersion(“ribasim.flowboundary.static”, 1) return (:FlowBoundary, :static)\nsource\n# Ribasim.outflow_id — Method.\nGet the unique outneighbor over a flow edge.\nsource\n# Ribasim.outflow_ids — Method.\nGet the outneighbors over flow edges.\nsource\n# Ribasim.outflow_ids_allocation — Method.\nGet the outneighbors of the given ID such that the connecting edge is an allocation flow edge.\nsource\n# Ribasim.outneighbor_labels_type — Method.\nGet the outneighbor node IDs of the given node ID (label) over the given edge type in the graph.\nsource\n# Ribasim.parse_static_and_time — Method.\nProcess 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.\nsource\n# Ribasim.pkgversion — Method.\nGet the package version of a given module\nsource\n# Ribasim.process_allocation_graph_edges! — Method.\nFor the composite allocation network edges:\n\nFind out whether they are connected to allocation network nodes on both ends\nCompute their capacity\nFind out their allowed flow direction(s)\n\nsource\n# Ribasim.profile_storage — Method.\nCalculate a profile storage by integrating the areas over the levels\nsource\n# Ribasim.qh_interpolation — Method.\nFrom a table with columns nodeid, flowrate (Q) and level (h), create a LinearInterpolation from level to flow rate for a given node_id.\nsource\n# Ribasim.reduction_factor — Method.\nFunction that goes smoothly from 0 to 1 in the interval [0,threshold], and is constant outside this interval.\nsource\n# Ribasim.run — Method.\nrun(config_file::AbstractString)::Model\nrun(config::Config)::Model\nRun 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 write_results.\nsource\n# Ribasim.save_allocation_flows! — Method.\nSave the allocation flows per basin and physical edge.\nsource\n# Ribasim.save_demands_and_allocations! — Method.\nSave the demands and allocated flows for users and basins. Note: Basin supply (negative demand) is only saved for the first priority.\nsource\n# Ribasim.save_flow — Method.\nCopy the current flow to the SavedValues\nsource\n# Ribasim.save_subgrid_level — Method.\nInterpolate the levels and save them to SavedValues\nsource\n# Ribasim.scalar_interpolation_derivative — Method.\nDerivative of scalar interpolation.\nsource\n# Ribasim.seconds_since — Method.\nseconds_since(t::DateTime, t0::DateTime)::Float64\nConvert 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.\nsource\n# Ribasim.set_current_value! — Method.\nFrom 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.\nsource\n# Ribasim.set_flow! — Method.\nSet the given flow q on the horizontal (self-loop) edge from id to id.\nsource\n# Ribasim.set_flow! — Method.\nSet the given flow q over the edge between the given nodes.\nsource\n# Ribasim.set_fractional_flow_in_allocation! — Method.\nUpdate the fractional flow fractions in an allocation problem.\nsource\n# Ribasim.set_initial_discrete_controlled_parameters! — Method.\nSet parameters of nodes that are controlled by DiscreteControl to the values corresponding to the initial state of the model.\nsource\n# Ribasim.set_is_pid_controlled! — Method.\nSet ispidcontrolled to true for those pumps and outlets that are PID controlled\nsource\n# Ribasim.set_objective_priority! — Method.\nSet the objective for the given priority. For an objective with absolute values this also involves adjusting constraints.\nsource\n# Ribasim.set_static_value! — Method.\nLoad data from a source table static into a destination table. Data is matched based on the node_id, which is sorted.\nsource\n# Ribasim.set_table_row! — Method.\nUpdate 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 missing, it is not set.\nsource\n# Ribasim.sorted_table! — Method.\nDepending on if a table can be sorted, either sort it or assert that it is sorted.\nTables loaded from the database into memory can be sorted. Tables loaded from Arrow files are memory mapped and can therefore not be sorted.\nsource\n# Ribasim.timesteps — Method.\nGet all saved times in seconds since start\nsource\n# Ribasim.update_allocation! — Method.\nSolve the allocation problem for all users and assign allocated abstractions to user nodes.\nsource\n# Ribasim.update_basin — Method.\nLoad updates from ‘Basin / time’ into the parameters\nsource\n# Ribasim.update_jac_prototype! — Method.\nMethod for nodes that do not contribute to the Jacobian\nsource\n# Ribasim.update_jac_prototype! — Method.\nThe 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.\nsource\n# Ribasim.update_jac_prototype! — Method.\nIf 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.\nsource\n# Ribasim.update_jac_prototype! — Method.\nIf 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.\nsource\n# Ribasim.update_tabulated_rating_curve! — Method.\nLoad updates from ‘TabulatedRatingCurve / time’ into the parameters\nsource\n# Ribasim.valid_discrete_control — Method.\nCheck:\n\nwhether control states are defined for discrete controlled nodes;\nWhether the supplied truth states have the proper length;\nWhether look_ahead is only supplied for condition variables given by a time-series.\n\nsource\n# Ribasim.valid_edge_types — Method.\nCheck that only supported edge types are declared.\nsource\n# Ribasim.valid_edges — Method.\nTest for each node given its node type whether the nodes that\nare downstream (‘down-edge’) of this node are of an allowed type\nsource\n# Ribasim.valid_flow_rates — Method.\nTest whether static or discrete controlled flow rates are indeed non-negative.\nsource\n# Ribasim.valid_fractional_flow — Method.\nCheck 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.\nsource\n# Ribasim.valid_n_neighbors — Method.\nTest for each node given its node type whether it has an allowed number of flow/control inneighbors and outneighbors\nsource\n# Ribasim.valid_profiles — Method.\nCheck whether the profile data has no repeats in the levels and the areas start positive.\nsource\n# Ribasim.valid_sources — Method.\nThe source nodes must only have one allocation outneighbor and no allocation inneighbors.\nsource\n# Ribasim.valid_subgrid — Method.\nValidate the entries for a single subgrid element.\nsource\n# Ribasim.water_balance! — Method.\nThe right hand side function of the system of ODEs set up by Ribasim.\nsource\n# Ribasim.write_arrow — Method.\nWrite a result table to disk as an Arrow file\nsource\n# Ribasim.write_results — Method.\nwrite_results(model::Model)::Model\nWrite all results to the Arrow files as specified in the model configuration.\nsource\n# Ribasim.config.algorithm — Method.\nCreate an OrdinaryDiffEqAlgorithm from solver config\nsource\n# Ribasim.config.convert_saveat — Method.\nConvert the saveat Float64 from our Config to SciML’s saveat\nsource\n# Ribasim.config.input_path — Method.\nConstruct a path relative to both the TOML directory and the optional input_dir\nsource\n# Ribasim.config.results_path — Method.\nConstruct a path relative to both the TOML directory and the optional results_dir\nsource\n# Ribasim.config.snake_case — Method.\nConvert a string from CamelCase to snake_case.\nsource",
+ "text": "1.3 Functions\n# BasicModelInterface.finalize — Method.\nBMI.finalize(model::Model)::Model\nWrite all results to the configured files.\nsource\n# BasicModelInterface.initialize — Method.\nBMI.initialize(T::Type{Model}, config_path::AbstractString)::Model\nInitialize a Model from the path to the TOML configuration file.\nsource\n# CommonSolve.solve! — Method.\nsolve!(model::Model)::ODESolution\nSolve a Model until the configured endtime.\nsource\n# Ribasim.add_basin_term! — Method.\nAdd a term to the expression of the objective function corresponding to the demand of a basin.\nsource\n# Ribasim.add_constraints_absolute_value! — Method.\nMinimizing |expr| can be achieved by introducing a new variable exprabs and posing the following constraints: exprabs >= expr expr_abs >= -expr\nsource\n# Ribasim.add_constraints_absolute_value_basin! — Method.\nAdd constraints so that variables Fabsbasin act as the absolute value of the expression comparing flow to a basin to its demand.\nsource\n# Ribasim.add_constraints_absolute_value_user! — Method.\nAdd constraints so that variables Fabsuser act as the absolute value of the expression comparing flow to an user to its demand.\nsource\n# Ribasim.add_constraints_basin_flow! — Method.\nAdd the basin flow constraints to the allocation problem. The constraint indices are the basin node IDs.\nConstraint: flow out of basin <= basin capacity\nsource\n# Ribasim.add_constraints_capacity! — Method.\nAdd the flow capacity constraints to the allocation problem. Only finite capacities get a constraint. The constraint indices are (edgesourceid, edgedstid).\nConstraint: flow over edge <= edge capacity\nsource\n# Ribasim.add_constraints_flow_conservation! — Method.\nAdd the flow conservation constraints to the allocation problem. The constraint indices are user node IDs.\nConstraint: sum(flows out of node node) == flows into node + flow from storage and vertical fluxes\nsource\n# Ribasim.add_constraints_fractional_flow! — Method.\nAdd the fractional flow constraints to the allocation problem. The constraint indices are allocation edges over a fractional flow node.\nConstraint: flow after fractional_flow node <= fraction * inflow\nsource\n# Ribasim.add_constraints_source! — Method.\nAdd the source constraints to the allocation problem. The actual threshold values will be set before each allocation solve. The constraint indices are (edgesourceid, edgedstid).\nConstraint: flow over source edge <= source flow in subnetwork\nsource\n# Ribasim.add_constraints_user_returnflow! — Method.\nAdd the user returnflow constraints to the allocation problem. The constraint indices are user node IDs.\nConstraint: outflow from user <= return factor * inflow to user\nsource\n# Ribasim.add_flow! — Method.\nAdd the given flow q to the flow over the edge on the horizontal (self-loop) edge from id to id.\nsource\n# Ribasim.add_flow! — Method.\nAdd the given flow q to the existing flow over the edge between the given nodes.\nsource\n# Ribasim.add_objective_term! — Method.\nAdd a term to the objective function given by the objective type, depending in the provided flow variable and the associated demand.\nsource\n# Ribasim.add_subnetwork_connections! — Method.\nAdd the edges connecting the main network work to a subnetwork to both the main network and subnetwork allocation network.\nsource\n# Ribasim.add_user_term! — Method.\nAdd a term to the expression of the objective function corresponding to the demand of a user.\nsource\n# Ribasim.add_variables_absolute_value! — Method.\nCertain 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.\nsource\n# Ribasim.add_variables_basin! — Method.\nAdd the variables for supply/demand of a basin to the problem. The variable indices are the node_ids of the basins in the subnetwork.\nsource\n# Ribasim.add_variables_flow! — Method.\nAdd the flow variables F to the allocation problem. The variable indices are (edgesourceid, edgedstid). Non-negativivity constraints are also immediately added to the flow variables.\nsource\n# Ribasim.adjust_basin_capacities! — Method.\nSet the values of the basin outflows. 2 cases:\n\nBefore the first allocation solve, set the capacities to their full capacity if there is surplus storage;\nBefore an allocation solve, subtract the flow used by allocation for the previous priority from the capacities.\n\nsource\n# Ribasim.adjust_edge_capacities! — Method.\nSet the values of the edge capacities. 2 cases:\n\nBefore the first allocation solve, set the edge capacities to their full capacity;\nBefore an allocation solve, subtract the flow used by allocation for the previous priority from the edge capacities.\n\nsource\n# Ribasim.adjust_source_capacities! — Method.\nAdjust the source flows.\nsource\n# Ribasim.all_neighbor_labels_type — Method.\nGet the in- and outneighbor node IDs of the given node ID (label) over the given edge type in the graph.\nsource\n# Ribasim.allocate! — Method.\nUpdate 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.\nsource\n# Ribasim.allocation_graph — Method.\nBuild the graph used for the allocation problem.\nsource\n# Ribasim.allocation_graph_used_nodes! — Method.\nFind all nodes in the subnetwork which will be used in the allocation network. Some nodes are skipped to optimize allocation optimization.\nsource\n# Ribasim.allocation_path_exists_in_graph — Method.\nFind out whether a path exists between a start node and end node in the given allocation network.\nsource\n# Ribasim.allocation_problem — Method.\nConstruct the allocation problem for the current subnetwork as a JuMP.jl model.\nsource\n# Ribasim.allocation_table — Method.\nCreate an allocation result table for the saved data\nsource\n# Ribasim.assign_allocations! — Method.\nAssign the allocations to the users as determined by the solution of the allocation problem.\nsource\n# Ribasim.avoid_using_own_returnflow! — Method.\nRemove allocation user return flow edges that are upstream of the user itself.\nsource\n# Ribasim.basin_bottom — Method.\nReturn the bottom elevation of the basin with index i, or nothing if it doesn’t exist\nsource\n# Ribasim.basin_bottoms — Method.\nGet the bottom on both ends of a node. If only one has a bottom, use that for both.\nsource\n# Ribasim.basin_table — Method.\nCreate the basin result table from the saved data\nsource\n# Ribasim.create_callbacks — Method.\nCreate 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.\nsource\n# Ribasim.create_graph — Method.\nReturn a directed metagraph with data of nodes (NodeMetadata): NodeMetadata\nand data of edges (EdgeMetadata): EdgeMetadata\nsource\n# Ribasim.create_storage_tables — Method.\nRead the Basin / profile table and return all area and level and computed storage values\nsource\n# Ribasim.datetime_since — Method.\ndatetime_since(t::Real, t0::DateTime)::DateTime\nConvert 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.\nsource\n# Ribasim.datetimes — Method.\nGet all saved times as a Vector{DateTime}\nsource\n# Ribasim.discrete_control_affect! — Method.\nChange parameters based on the control logic.\nsource\n# Ribasim.discrete_control_affect_downcrossing! — Method.\nAn downcrossing means that a condition (always greater than) becomes false.\nsource\n# Ribasim.discrete_control_affect_upcrossing! — Method.\nAn upcrossing means that a condition (always greater than) becomes true.\nsource\n# Ribasim.discrete_control_condition — Method.\nListens for changes in condition truths.\nsource\n# Ribasim.discrete_control_table — Method.\nCreate a discrete control result table from the saved data\nsource\n# Ribasim.expand_logic_mapping — Method.\nReplace the truth states in the logic mapping which contain wildcards with all possible explicit truth states.\nsource\n# Ribasim.find_allocation_graph_edges! — Method.\nThis loop finds allocation network edges in several ways:\n\nBetween allocation network nodes whose equivalent in the subnetwork are directly connected\nBetween allocation network nodes whose equivalent in the subnetwork are connected with one or more allocation network nodes in between\n\nsource\n# Ribasim.find_subnetwork_connections! — Method.\nFind the edges from the main network to a subnetwork.\nsource\n# Ribasim.findlastgroup — Method.\nFor 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.\nsource\n# Ribasim.findsorted — Method.\nFind 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.\nsource\n# Ribasim.flow_table — Method.\nCreate a flow result table from the saved data\nsource\n# Ribasim.formulate_basins! — Method.\nSmoothly let the evaporation flux go to 0 when at small water depths Currently at less than 0.1 m.\nsource\n# Ribasim.formulate_flow! — Method.\nDirected graph: outflow is positive!\nsource\n# Ribasim.formulate_flow! — Method.\nConservation of energy for two basins, a and b:\nh_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)\nWhere:\n\nha, hb are the heads at basin a and b.\nva, vb are the velocities at basin a and b.\ng is the gravitational constant.\nS_f is the friction slope.\nC is an expansion or extraction coefficient.\n\nWe assume velocity differences are negligible (va = vb):\nh_a = h_b + S_f * L\nThe friction losses are approximated by the Gauckler-Manning formula:\nQ = A * (1 / n) * R_h^(2/3) * S_f^(1/2)\nWhere:\n\nWhere A is the cross-sectional area.\nV is the cross-sectional average velocity.\nn is the Gauckler-Manning coefficient.\nR_h is the hydraulic radius.\nS_f is the friction slope.\n\nThe hydraulic radius is defined as:\nR_h = A / P\nWhere P is the wetted perimeter.\nThe average of the upstream and downstream water depth is used to compute cross-sectional area and hydraulic radius. This ensures that a basin can receive water after it has gone dry.\nsource\n# Ribasim.formulate_flow! — Method.\nDirected graph: outflow is positive!\nsource\n# Ribasim.get_area_and_level — Method.\nCompute the area and level of a basin given its storage. Also returns darea/dlevel as it is needed for the Jacobian.\nsource\n# Ribasim.get_basin_capacity — Method.\nGet 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). Storages are converted to flows by dividing by the allocation timestep.\nsource\n# Ribasim.get_basin_data — Method.\nGet several variables associated with a basin:\n\nIts current storage\nThe allocation update interval\nThe influx (sum of instantaneous vertical fluxes of the basin)\nThe index of the connected target_level node (0 if such a node does not exist)\nThe index of the basin\n\nsource\n# Ribasim.get_basin_demand — Method.\nGet 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). Storages are converted to flows by dividing by the allocation timestep.\nsource\n# Ribasim.get_chunk_sizes — Method.\nGet the chunk sizes for DiffCache; differentiation w.r.t. u and t (the latter only if a Rosenbrock algorithm is used).\nsource\n# Ribasim.get_compressor — Method.\nGet the compressor based on the Results section\nsource\n# Ribasim.get_flow — Method.\nGet the flow over the given horizontal (selfloop) edge (val is needed for get_tmp from ForwardDiff.jl).\nsource\n# Ribasim.get_flow — Method.\nGet the flow over the given edge (val is needed for get_tmp from ForwardDiff.jl).\nsource\n# Ribasim.get_fractional_flow_connected_basins — Method.\nGet the node type specific indices of the fractional flows and basins, that are consecutively connected to a node of given id.\nsource\n# Ribasim.get_jac_prototype — Method.\nGet 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.\nIn Ribasim the Jacobian is typically sparse because each state only depends on a small number of other states.\nNote: 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.\nsource\n# Ribasim.get_level — Method.\nGet 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\nsource\n# Ribasim.get_scalar_interpolation — Method.\nLinear interpolation of a scalar with constant extrapolation.\nsource\n# Ribasim.get_storage_from_level — Method.\nGet the storage of a basin from its level.\nsource\n# Ribasim.get_storages_and_levels — Method.\nGet the storage and level of all basins as matrices of nbasin × ntime\nsource\n# Ribasim.get_storages_from_levels — Method.\nCompute the storages of the basins based on the water level of the basins.\nsource\n# Ribasim.get_tstops — Method.\nFrom an iterable of DateTimes, find the times the solver needs to stop\nsource\n# Ribasim.get_value — Method.\nGet a value for a condition. Currently supports getting levels from basins and flows from flow boundaries.\nsource\n# Ribasim.id_index — Method.\nGet the index of an ID in a set of indices.\nsource\n# Ribasim.indicate_allocation_flow! — Method.\nAdd to the edge metadata that the given edge is used for allocation flow. If the edge does not exist, it is created.\nsource\n# Ribasim.inflow_id — Method.\nGet the unique inneighbor over a flow edge.\nsource\n# Ribasim.inflow_ids — Method.\nGet the inneighbors over flow edges.\nsource\n# Ribasim.inflow_ids_allocation — Method.\nGet the inneighbors of the given ID such that the connecting edge is an allocation flow edge.\nsource\n# Ribasim.inneighbor_labels_type — Method.\nGet the inneighbor node IDs of the given node ID (label) over the given edge type in the graph.\nsource\n# Ribasim.inoutflow_ids — Method.\nGet the in- and outneighbors over flow edges.\nsource\n# Ribasim.is_allocation_source — Method.\nFind out whether the given edge is a source for an allocation network.\nsource\n# Ribasim.is_current_module — Method.\nis_current_module(log::LogMessageType)::Bool\nReturns true if the log message is from the current module or a submodule.\n\nSee https://github.com/JuliaLogging/LoggingExtras.jl/blob/d35e7c8cfc197853ee336ace17182e6ed36dca24/src/CompositionalLoggers/earlyfiltered.jl#L39\nfor the information available in log.\nsource\n# Ribasim.is_flow_constraining — Method.\nWhether the given node node is flow constraining by having a maximum flow rate.\nsource\n# Ribasim.is_flow_direction_constraining — Method.\nWhether the given node is flow direction constraining (only in direction of edges).\nsource\n# Ribasim.load_data — Method.\nload_data(db::DB, config::Config, nodetype::Symbol, kind::Symbol)::Union{Table, Query, Nothing}\nLoad data from Arrow files if available, otherwise the database. Returns either an Arrow.Table, SQLite.Query or nothing if the data is not present.\nsource\n# Ribasim.load_structvector — Method.\nload_structvector(db::DB, config::Config, ::Type{T})::StructVector{T}\nLoad 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.\nsource\n# Ribasim.low_storage_factor — Method.\nIf id is a Basin with storage below the threshold, return a reduction factor != 1\nsource\n# Ribasim.main — Method.\nmain(toml_path::AbstractString)::Cint\nmain(ARGS::Vector{String})::Cint\nmain()::Cint\nThis is the main entry point of the application. Performs argument parsing and sets up logging for both terminal and file. Calls Ribasim.run() and handles exceptions to convert to exit codes.\nsource\n# Ribasim.metadata_from_edge — Method.\nGet the metadata of an edge in the graph from an edge of the underlying DiGraph.\nsource\n# Ribasim.nodefields — Method.\nGet all node fieldnames of the parameter object.\nsource\n# Ribasim.nodetype — Method.\nFrom a SchemaVersion(“ribasim.flowboundary.static”, 1) return (:FlowBoundary, :static)\nsource\n# Ribasim.outflow_id — Method.\nGet the unique outneighbor over a flow edge.\nsource\n# Ribasim.outflow_ids — Method.\nGet the outneighbors over flow edges.\nsource\n# Ribasim.outflow_ids_allocation — Method.\nGet the outneighbors of the given ID such that the connecting edge is an allocation flow edge.\nsource\n# Ribasim.outneighbor_labels_type — Method.\nGet the outneighbor node IDs of the given node ID (label) over the given edge type in the graph.\nsource\n# Ribasim.parse_static_and_time — Method.\nProcess 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.\nsource\n# Ribasim.pkgversion — Method.\nGet the package version of a given module\nsource\n# Ribasim.process_allocation_graph_edges! — Method.\nFor the composite allocation network edges:\n\nFind out whether they are connected to allocation network nodes on both ends\nCompute their capacity\nFind out their allowed flow direction(s)\n\nsource\n# Ribasim.profile_storage — Method.\nCalculate a profile storage by integrating the areas over the levels\nsource\n# Ribasim.qh_interpolation — Method.\nFrom a table with columns nodeid, flowrate (Q) and level (h), create a LinearInterpolation from level to flow rate for a given node_id.\nsource\n# Ribasim.reduction_factor — Method.\nFunction that goes smoothly from 0 to 1 in the interval [0,threshold], and is constant outside this interval.\nsource\n# Ribasim.run — Method.\nrun(config_file::AbstractString)::Model\nrun(config::Config)::Model\nRun 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 write_results.\nsource\n# Ribasim.save_allocation_flows! — Method.\nSave the allocation flows per basin and physical edge.\nsource\n# Ribasim.save_demands_and_allocations! — Method.\nSave the demands and allocated flows for users and basins. Note: Basin supply (negative demand) is only saved for the first priority.\nsource\n# Ribasim.save_flow — Method.\nCopy the current flow to the SavedValues\nsource\n# Ribasim.save_subgrid_level — Method.\nInterpolate the levels and save them to SavedValues\nsource\n# Ribasim.scalar_interpolation_derivative — Method.\nDerivative of scalar interpolation.\nsource\n# Ribasim.seconds_since — Method.\nseconds_since(t::DateTime, t0::DateTime)::Float64\nConvert 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.\nsource\n# Ribasim.set_current_value! — Method.\nFrom 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.\nsource\n# Ribasim.set_flow! — Method.\nSet the given flow q on the horizontal (self-loop) edge from id to id.\nsource\n# Ribasim.set_flow! — Method.\nSet the given flow q over the edge between the given nodes.\nsource\n# Ribasim.set_fractional_flow_in_allocation! — Method.\nUpdate the fractional flow fractions in an allocation problem.\nsource\n# Ribasim.set_initial_discrete_controlled_parameters! — Method.\nSet parameters of nodes that are controlled by DiscreteControl to the values corresponding to the initial state of the model.\nsource\n# Ribasim.set_is_pid_controlled! — Method.\nSet ispidcontrolled to true for those pumps and outlets that are PID controlled\nsource\n# Ribasim.set_objective_priority! — Method.\nSet the objective for the given priority. For an objective with absolute values this also involves adjusting constraints.\nsource\n# Ribasim.set_static_value! — Method.\nLoad data from a source table static into a destination table. Data is matched based on the node_id, which is sorted.\nsource\n# Ribasim.set_table_row! — Method.\nUpdate 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 missing, it is not set.\nsource\n# Ribasim.sorted_table! — Method.\nDepending on if a table can be sorted, either sort it or assert that it is sorted.\nTables loaded from the database into memory can be sorted. Tables loaded from Arrow files are memory mapped and can therefore not be sorted.\nsource\n# Ribasim.timesteps — Method.\nGet all saved times in seconds since start\nsource\n# Ribasim.update_allocation! — Method.\nSolve the allocation problem for all users and assign allocated abstractions to user nodes.\nsource\n# Ribasim.update_basin — Method.\nLoad updates from ‘Basin / time’ into the parameters\nsource\n# Ribasim.update_jac_prototype! — Method.\nMethod for nodes that do not contribute to the Jacobian\nsource\n# Ribasim.update_jac_prototype! — Method.\nThe 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.\nsource\n# Ribasim.update_jac_prototype! — Method.\nIf 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.\nsource\n# Ribasim.update_jac_prototype! — Method.\nIf 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.\nsource\n# Ribasim.update_tabulated_rating_curve! — Method.\nLoad updates from ‘TabulatedRatingCurve / time’ into the parameters\nsource\n# Ribasim.valid_discrete_control — Method.\nCheck:\n\nwhether control states are defined for discrete controlled nodes;\nWhether the supplied truth states have the proper length;\nWhether look_ahead is only supplied for condition variables given by a time-series.\n\nsource\n# Ribasim.valid_edge_types — Method.\nCheck that only supported edge types are declared.\nsource\n# Ribasim.valid_edges — Method.\nTest for each node given its node type whether the nodes that\nare downstream (‘down-edge’) of this node are of an allowed type\nsource\n# Ribasim.valid_flow_rates — Method.\nTest whether static or discrete controlled flow rates are indeed non-negative.\nsource\n# Ribasim.valid_fractional_flow — Method.\nCheck 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.\nsource\n# Ribasim.valid_n_neighbors — Method.\nTest for each node given its node type whether it has an allowed number of flow/control inneighbors and outneighbors\nsource\n# Ribasim.valid_profiles — Method.\nCheck whether the profile data has no repeats in the levels and the areas start positive.\nsource\n# Ribasim.valid_sources — Method.\nThe source nodes must only have one allocation outneighbor and no allocation inneighbors.\nsource\n# Ribasim.valid_subgrid — Method.\nValidate the entries for a single subgrid element.\nsource\n# Ribasim.water_balance! — Method.\nThe right hand side function of the system of ODEs set up by Ribasim.\nsource\n# Ribasim.write_arrow — Method.\nWrite a result table to disk as an Arrow file\nsource\n# Ribasim.write_results — Method.\nwrite_results(model::Model)::Model\nWrite all results to the Arrow files as specified in the model configuration.\nsource\n# Ribasim.config.algorithm — Method.\nCreate an OrdinaryDiffEqAlgorithm from solver config\nsource\n# Ribasim.config.convert_dt — Method.\nConvert the dt from our Config to SciML stepsize control arguments\nsource\n# Ribasim.config.convert_saveat — Method.\nConvert the saveat Float64 from our Config to SciML’s saveat\nsource\n# Ribasim.config.input_path — Method.\nConstruct a path relative to both the TOML directory and the optional input_dir\nsource\n# Ribasim.config.results_path — Method.\nConstruct a path relative to both the TOML directory and the optional results_dir\nsource\n# Ribasim.config.snake_case — Method.\nConvert a string from CamelCase to snake_case.\nsource",
"crumbs": [
"Julia core",
"API Reference"
@@ -59,7 +59,7 @@
"href": "build/index.html#index",
"title": "1 API Reference",
"section": "1.6 Index",
- "text": "1.6 Index\n\nRibasim.Ribasim\nRibasim.config\nRibasim.config.algorithms\nRibasim.Allocation\nRibasim.AllocationModel\nRibasim.AllocationModel\nRibasim.Basin\nRibasim.DiscreteControl\nRibasim.EdgeMetadata\nRibasim.FlatVector\nRibasim.FlowBoundary\nRibasim.FractionalFlow\nRibasim.InNeighbors\nRibasim.LevelBoundary\nRibasim.LinearResistance\nRibasim.ManningResistance\nRibasim.Model\nRibasim.NodeMetadata\nRibasim.OutNeighbors\nRibasim.Outlet\nRibasim.PidControl\nRibasim.Pump\nRibasim.Subgrid\nRibasim.TabulatedRatingCurve\nRibasim.TargetLevel\nRibasim.Terminal\nRibasim.User\nRibasim.config.Config\nBasicModelInterface.finalize\nBasicModelInterface.initialize\nCommonSolve.solve!\nRibasim.add_basin_term!\nRibasim.add_constraints_absolute_value!\nRibasim.add_constraints_absolute_value_basin!\nRibasim.add_constraints_absolute_value_user!\nRibasim.add_constraints_basin_flow!\nRibasim.add_constraints_capacity!\nRibasim.add_constraints_flow_conservation!\nRibasim.add_constraints_fractional_flow!\nRibasim.add_constraints_source!\nRibasim.add_constraints_user_returnflow!\nRibasim.add_flow!\nRibasim.add_flow!\nRibasim.add_objective_term!\nRibasim.add_subnetwork_connections!\nRibasim.add_user_term!\nRibasim.add_variables_absolute_value!\nRibasim.add_variables_basin!\nRibasim.add_variables_flow!\nRibasim.adjust_basin_capacities!\nRibasim.adjust_edge_capacities!\nRibasim.adjust_source_capacities!\nRibasim.all_neighbor_labels_type\nRibasim.allocate!\nRibasim.allocation_graph\nRibasim.allocation_graph_used_nodes!\nRibasim.allocation_path_exists_in_graph\nRibasim.allocation_problem\nRibasim.allocation_table\nRibasim.assign_allocations!\nRibasim.avoid_using_own_returnflow!\nRibasim.basin_bottom\nRibasim.basin_bottoms\nRibasim.basin_table\nRibasim.config.algorithm\nRibasim.config.convert_saveat\nRibasim.config.input_path\nRibasim.config.results_path\nRibasim.config.snake_case\nRibasim.create_callbacks\nRibasim.create_graph\nRibasim.create_storage_tables\nRibasim.datetime_since\nRibasim.datetimes\nRibasim.discrete_control_affect!\nRibasim.discrete_control_affect_downcrossing!\nRibasim.discrete_control_affect_upcrossing!\nRibasim.discrete_control_condition\nRibasim.discrete_control_table\nRibasim.expand_logic_mapping\nRibasim.find_allocation_graph_edges!\nRibasim.find_subnetwork_connections!\nRibasim.findlastgroup\nRibasim.findsorted\nRibasim.flow_table\nRibasim.formulate_basins!\nRibasim.formulate_flow!\nRibasim.formulate_flow!\nRibasim.formulate_flow!\nRibasim.get_area_and_level\nRibasim.get_basin_capacity\nRibasim.get_basin_data\nRibasim.get_basin_demand\nRibasim.get_chunk_sizes\nRibasim.get_compressor\nRibasim.get_flow\nRibasim.get_flow\nRibasim.get_fractional_flow_connected_basins\nRibasim.get_jac_prototype\nRibasim.get_level\nRibasim.get_scalar_interpolation\nRibasim.get_storage_from_level\nRibasim.get_storages_and_levels\nRibasim.get_storages_from_levels\nRibasim.get_tstops\nRibasim.get_value\nRibasim.id_index\nRibasim.indicate_allocation_flow!\nRibasim.inflow_id\nRibasim.inflow_ids\nRibasim.inflow_ids_allocation\nRibasim.inneighbor_labels_type\nRibasim.inoutflow_ids\nRibasim.is_allocation_source\nRibasim.is_current_module\nRibasim.is_flow_constraining\nRibasim.is_flow_direction_constraining\nRibasim.load_data\nRibasim.load_structvector\nRibasim.low_storage_factor\nRibasim.main\nRibasim.metadata_from_edge\nRibasim.nodefields\nRibasim.nodetype\nRibasim.outflow_id\nRibasim.outflow_ids\nRibasim.outflow_ids_allocation\nRibasim.outneighbor_labels_type\nRibasim.parse_static_and_time\nRibasim.pkgversion\nRibasim.process_allocation_graph_edges!\nRibasim.profile_storage\nRibasim.qh_interpolation\nRibasim.reduction_factor\nRibasim.run\nRibasim.save_allocation_flows!\nRibasim.save_demands_and_allocations!\nRibasim.save_flow\nRibasim.save_subgrid_level\nRibasim.scalar_interpolation_derivative\nRibasim.seconds_since\nRibasim.set_current_value!\nRibasim.set_flow!\nRibasim.set_flow!\nRibasim.set_fractional_flow_in_allocation!\nRibasim.set_initial_discrete_controlled_parameters!\nRibasim.set_is_pid_controlled!\nRibasim.set_objective_priority!\nRibasim.set_static_value!\nRibasim.set_table_row!\nRibasim.sorted_table!\nRibasim.timesteps\nRibasim.update_allocation!\nRibasim.update_basin\nRibasim.update_jac_prototype!\nRibasim.update_jac_prototype!\nRibasim.update_jac_prototype!\nRibasim.update_jac_prototype!\nRibasim.update_tabulated_rating_curve!\nRibasim.valid_discrete_control\nRibasim.valid_edge_types\nRibasim.valid_edges\nRibasim.valid_flow_rates\nRibasim.valid_fractional_flow\nRibasim.valid_n_neighbors\nRibasim.valid_profiles\nRibasim.valid_sources\nRibasim.valid_subgrid\nRibasim.water_balance!\nRibasim.write_arrow\nRibasim.write_results\nRibasim.config.@addfields\nRibasim.config.@addnodetypes",
+ "text": "1.6 Index\n\nRibasim.Ribasim\nRibasim.config\nRibasim.config.algorithms\nRibasim.Allocation\nRibasim.AllocationModel\nRibasim.AllocationModel\nRibasim.Basin\nRibasim.DiscreteControl\nRibasim.EdgeMetadata\nRibasim.FlatVector\nRibasim.FlowBoundary\nRibasim.FractionalFlow\nRibasim.InNeighbors\nRibasim.LevelBoundary\nRibasim.LinearResistance\nRibasim.ManningResistance\nRibasim.Model\nRibasim.NodeMetadata\nRibasim.OutNeighbors\nRibasim.Outlet\nRibasim.PidControl\nRibasim.Pump\nRibasim.Subgrid\nRibasim.TabulatedRatingCurve\nRibasim.TargetLevel\nRibasim.Terminal\nRibasim.User\nRibasim.config.Config\nBasicModelInterface.finalize\nBasicModelInterface.initialize\nCommonSolve.solve!\nRibasim.add_basin_term!\nRibasim.add_constraints_absolute_value!\nRibasim.add_constraints_absolute_value_basin!\nRibasim.add_constraints_absolute_value_user!\nRibasim.add_constraints_basin_flow!\nRibasim.add_constraints_capacity!\nRibasim.add_constraints_flow_conservation!\nRibasim.add_constraints_fractional_flow!\nRibasim.add_constraints_source!\nRibasim.add_constraints_user_returnflow!\nRibasim.add_flow!\nRibasim.add_flow!\nRibasim.add_objective_term!\nRibasim.add_subnetwork_connections!\nRibasim.add_user_term!\nRibasim.add_variables_absolute_value!\nRibasim.add_variables_basin!\nRibasim.add_variables_flow!\nRibasim.adjust_basin_capacities!\nRibasim.adjust_edge_capacities!\nRibasim.adjust_source_capacities!\nRibasim.all_neighbor_labels_type\nRibasim.allocate!\nRibasim.allocation_graph\nRibasim.allocation_graph_used_nodes!\nRibasim.allocation_path_exists_in_graph\nRibasim.allocation_problem\nRibasim.allocation_table\nRibasim.assign_allocations!\nRibasim.avoid_using_own_returnflow!\nRibasim.basin_bottom\nRibasim.basin_bottoms\nRibasim.basin_table\nRibasim.config.algorithm\nRibasim.config.convert_dt\nRibasim.config.convert_saveat\nRibasim.config.input_path\nRibasim.config.results_path\nRibasim.config.snake_case\nRibasim.create_callbacks\nRibasim.create_graph\nRibasim.create_storage_tables\nRibasim.datetime_since\nRibasim.datetimes\nRibasim.discrete_control_affect!\nRibasim.discrete_control_affect_downcrossing!\nRibasim.discrete_control_affect_upcrossing!\nRibasim.discrete_control_condition\nRibasim.discrete_control_table\nRibasim.expand_logic_mapping\nRibasim.find_allocation_graph_edges!\nRibasim.find_subnetwork_connections!\nRibasim.findlastgroup\nRibasim.findsorted\nRibasim.flow_table\nRibasim.formulate_basins!\nRibasim.formulate_flow!\nRibasim.formulate_flow!\nRibasim.formulate_flow!\nRibasim.get_area_and_level\nRibasim.get_basin_capacity\nRibasim.get_basin_data\nRibasim.get_basin_demand\nRibasim.get_chunk_sizes\nRibasim.get_compressor\nRibasim.get_flow\nRibasim.get_flow\nRibasim.get_fractional_flow_connected_basins\nRibasim.get_jac_prototype\nRibasim.get_level\nRibasim.get_scalar_interpolation\nRibasim.get_storage_from_level\nRibasim.get_storages_and_levels\nRibasim.get_storages_from_levels\nRibasim.get_tstops\nRibasim.get_value\nRibasim.id_index\nRibasim.indicate_allocation_flow!\nRibasim.inflow_id\nRibasim.inflow_ids\nRibasim.inflow_ids_allocation\nRibasim.inneighbor_labels_type\nRibasim.inoutflow_ids\nRibasim.is_allocation_source\nRibasim.is_current_module\nRibasim.is_flow_constraining\nRibasim.is_flow_direction_constraining\nRibasim.load_data\nRibasim.load_structvector\nRibasim.low_storage_factor\nRibasim.main\nRibasim.metadata_from_edge\nRibasim.nodefields\nRibasim.nodetype\nRibasim.outflow_id\nRibasim.outflow_ids\nRibasim.outflow_ids_allocation\nRibasim.outneighbor_labels_type\nRibasim.parse_static_and_time\nRibasim.pkgversion\nRibasim.process_allocation_graph_edges!\nRibasim.profile_storage\nRibasim.qh_interpolation\nRibasim.reduction_factor\nRibasim.run\nRibasim.save_allocation_flows!\nRibasim.save_demands_and_allocations!\nRibasim.save_flow\nRibasim.save_subgrid_level\nRibasim.scalar_interpolation_derivative\nRibasim.seconds_since\nRibasim.set_current_value!\nRibasim.set_flow!\nRibasim.set_flow!\nRibasim.set_fractional_flow_in_allocation!\nRibasim.set_initial_discrete_controlled_parameters!\nRibasim.set_is_pid_controlled!\nRibasim.set_objective_priority!\nRibasim.set_static_value!\nRibasim.set_table_row!\nRibasim.sorted_table!\nRibasim.timesteps\nRibasim.update_allocation!\nRibasim.update_basin\nRibasim.update_jac_prototype!\nRibasim.update_jac_prototype!\nRibasim.update_jac_prototype!\nRibasim.update_jac_prototype!\nRibasim.update_tabulated_rating_curve!\nRibasim.valid_discrete_control\nRibasim.valid_edge_types\nRibasim.valid_edges\nRibasim.valid_flow_rates\nRibasim.valid_fractional_flow\nRibasim.valid_n_neighbors\nRibasim.valid_profiles\nRibasim.valid_sources\nRibasim.valid_subgrid\nRibasim.water_balance!\nRibasim.write_arrow\nRibasim.write_results\nRibasim.config.@addfields\nRibasim.config.@addnodetypes",
"crumbs": [
"Julia core",
"API Reference"
@@ -850,7 +850,7 @@
"href": "core/allocation.html#example",
"title": "Allocation",
"section": "5.1 Example",
- "text": "5.1 Example\nThe following is an example of an optimization problem for the example shown here:\n\n\nCode\nusing Ribasim\nusing Ribasim: NodeID\nusing SQLite\nusing ComponentArrays: ComponentVector\n\ntoml_path = normpath(@__DIR__, \"../../generated_testmodels/allocation_example/ribasim.toml\")\np = Ribasim.Model(toml_path).integrator.p\nu = ComponentVector(; storage = zeros(length(p.basin.node_id)))\n\nallocation_model = p.allocation.allocation_models[1]\nt = 0.0\npriority_idx = 1\n\nRibasim.set_flow!(p.graph, NodeID(:FlowBoundary, 1), NodeID(:Basin, 2), 1.0)\n\nRibasim.adjust_source_capacities!(allocation_model, p, priority_idx)\nRibasim.adjust_edge_capacities!(allocation_model, p, priority_idx)\nRibasim.set_objective_priority!(allocation_model, p, u, t, priority_idx)\n\nprintln(p.allocation.allocation_models[1].problem)\n\n\nMin F_abs_user[User #3] + F_abs_user[User #13] + F_abs_user[User #6] + F_abs_basin[Basin #12] + F_abs_basin[Basin #5] + F_abs_basin[Basin #2]\nSubject to\n flow_conservation[Basin #12] : F[(Basin #12, User #13)] - F[(TabulatedRatingCurve #7, Basin #12)] + F_basin_in[Basin #12] - F_basin_out[Basin #12] = 0\n flow_conservation[Basin #5] : F[(Basin #5, User #6)] + F[(Basin #5, TabulatedRatingCurve #7)] - F[(Basin #2, Basin #5)] + F[(Basin #5, Basin #2)] + F_basin_in[Basin #5] - F_basin_out[Basin #5] = 0\n flow_conservation[Basin #2] : F[(Basin #2, Basin #5)] + F[(Basin #2, User #3)] - F[(Basin #5, Basin #2)] - F[(FlowBoundary #1, Basin #2)] + F_basin_in[Basin #2] - F_basin_out[Basin #2] = 0\n abs_positive_user[User #3] : -F[(Basin #2, User #3)] + F_abs_user[User #3] ≥ 0\n abs_positive_user[User #13] : -F[(Basin #12, User #13)] + F_abs_user[User #13] ≥ 0\n abs_positive_user[User #6] : -F[(Basin #5, User #6)] + F_abs_user[User #6] ≥ -1.5\n abs_negative_user[User #3] : F[(Basin #2, User #3)] + F_abs_user[User #3] ≥ 0\n abs_negative_user[User #13] : F[(Basin #12, User #13)] + F_abs_user[User #13] ≥ 0\n abs_negative_user[User #6] : F[(Basin #5, User #6)] + F_abs_user[User #6] ≥ 1.5\n abs_positive_basin[Basin #12] : -F_basin_in[Basin #12] + F_abs_basin[Basin #12] ≥ 0\n abs_positive_basin[Basin #5] : -F_basin_in[Basin #5] + F_abs_basin[Basin #5] ≥ 0\n abs_positive_basin[Basin #2] : -F_basin_in[Basin #2] + F_abs_basin[Basin #2] ≥ 0\n abs_negative_basin[Basin #12] : F_basin_in[Basin #12] + F_abs_basin[Basin #12] ≥ 0\n abs_negative_basin[Basin #5] : F_basin_in[Basin #5] + F_abs_basin[Basin #5] ≥ 0\n abs_negative_basin[Basin #2] : F_basin_in[Basin #2] + F_abs_basin[Basin #2] ≥ 0\n source[(FlowBoundary #1, Basin #2)] : F[(FlowBoundary #1, Basin #2)] ≤ 1\n return_flow[User #13] : F[(User #13, Terminal #10)] ≤ 0\n fractional_flow[(TabulatedRatingCurve #7, Basin #12)] : -0.4 F[(Basin #5, TabulatedRatingCurve #7)] + F[(TabulatedRatingCurve #7, Basin #12)] ≤ 0\n basin_outflow[Basin #12] : F_basin_out[Basin #12] ≤ 0\n basin_outflow[Basin #5] : F_basin_out[Basin #5] ≤ 0\n basin_outflow[Basin #2] : F_basin_out[Basin #2] ≤ 0\n F[(Basin #5, User #6)] ≥ 0\n F[(TabulatedRatingCurve #7, Terminal #10)] ≥ 0\n F[(Basin #5, TabulatedRatingCurve #7)] ≥ 0\n F[(Basin #2, Basin #5)] ≥ 0\n F[(Basin #2, User #3)] ≥ 0\n F[(Basin #12, User #13)] ≥ 0\n F[(User #13, Terminal #10)] ≥ 0\n F[(Basin #5, Basin #2)] ≥ 0\n F[(FlowBoundary #1, Basin #2)] ≥ 0\n F[(TabulatedRatingCurve #7, Basin #12)] ≥ 0\n F_basin_in[Basin #12] ≥ 0\n F_basin_in[Basin #5] ≥ 0\n F_basin_in[Basin #2] ≥ 0\n F_basin_out[Basin #12] ≥ 0\n F_basin_out[Basin #5] ≥ 0\n F_basin_out[Basin #2] ≥ 0",
+ "text": "5.1 Example\nThe following is an example of an optimization problem for the example shown here:\n\n\nCode\nusing Ribasim\nusing Ribasim: NodeID\nusing SQLite\nusing ComponentArrays: ComponentVector\n\ntoml_path = normpath(@__DIR__, \"../../generated_testmodels/allocation_example/ribasim.toml\")\np = Ribasim.Model(toml_path).integrator.p\nu = ComponentVector(; storage = zeros(length(p.basin.node_id)))\n\nallocation_model = p.allocation.allocation_models[1]\nt = 0.0\npriority_idx = 1\n\nRibasim.set_flow!(p.graph, NodeID(:FlowBoundary, 1), NodeID(:Basin, 2), 1.0)\n\nRibasim.adjust_source_capacities!(allocation_model, p, priority_idx)\nRibasim.adjust_edge_capacities!(allocation_model, p, priority_idx)\nRibasim.set_objective_priority!(allocation_model, p, u, t, priority_idx)\n\nprintln(p.allocation.allocation_models[1].problem)\n\n\nMin F_abs_user[User #13] + F_abs_user[User #6] + F_abs_user[User #3] + F_abs_basin[Basin #12] + F_abs_basin[Basin #2] + F_abs_basin[Basin #5]\nSubject to\n flow_conservation[Basin #12] : -F[(TabulatedRatingCurve #7, Basin #12)] + F[(Basin #12, User #13)] + F_basin_in[Basin #12] - F_basin_out[Basin #12] = 0\n flow_conservation[Basin #2] : -F[(FlowBoundary #1, Basin #2)] + F[(Basin #2, User #3)] + F[(Basin #2, Basin #5)] - F[(Basin #5, Basin #2)] + F_basin_in[Basin #2] - F_basin_out[Basin #2] = 0\n flow_conservation[Basin #5] : F[(Basin #5, User #6)] + F[(Basin #5, TabulatedRatingCurve #7)] - F[(Basin #2, Basin #5)] + F[(Basin #5, Basin #2)] + F_basin_in[Basin #5] - F_basin_out[Basin #5] = 0\n abs_positive_user[User #13] : -F[(Basin #12, User #13)] + F_abs_user[User #13] ≥ 0\n abs_positive_user[User #6] : -F[(Basin #5, User #6)] + F_abs_user[User #6] ≥ -1.5\n abs_positive_user[User #3] : -F[(Basin #2, User #3)] + F_abs_user[User #3] ≥ 0\n abs_negative_user[User #13] : F[(Basin #12, User #13)] + F_abs_user[User #13] ≥ 0\n abs_negative_user[User #6] : F[(Basin #5, User #6)] + F_abs_user[User #6] ≥ 1.5\n abs_negative_user[User #3] : F[(Basin #2, User #3)] + F_abs_user[User #3] ≥ 0\n abs_positive_basin[Basin #12] : -F_basin_in[Basin #12] + F_abs_basin[Basin #12] ≥ 0\n abs_positive_basin[Basin #2] : -F_basin_in[Basin #2] + F_abs_basin[Basin #2] ≥ 0\n abs_positive_basin[Basin #5] : -F_basin_in[Basin #5] + F_abs_basin[Basin #5] ≥ 0\n abs_negative_basin[Basin #12] : F_basin_in[Basin #12] + F_abs_basin[Basin #12] ≥ 0\n abs_negative_basin[Basin #2] : F_basin_in[Basin #2] + F_abs_basin[Basin #2] ≥ 0\n abs_negative_basin[Basin #5] : F_basin_in[Basin #5] + F_abs_basin[Basin #5] ≥ 0\n source[(FlowBoundary #1, Basin #2)] : F[(FlowBoundary #1, Basin #2)] ≤ 1\n return_flow[User #13] : F[(User #13, Terminal #10)] ≤ 0\n fractional_flow[(TabulatedRatingCurve #7, Basin #12)] : -0.4 F[(Basin #5, TabulatedRatingCurve #7)] + F[(TabulatedRatingCurve #7, Basin #12)] ≤ 0\n basin_outflow[Basin #12] : F_basin_out[Basin #12] ≤ 0\n basin_outflow[Basin #2] : F_basin_out[Basin #2] ≤ 0\n basin_outflow[Basin #5] : F_basin_out[Basin #5] ≤ 0\n F[(FlowBoundary #1, Basin #2)] ≥ 0\n F[(Basin #5, User #6)] ≥ 0\n F[(Basin #5, TabulatedRatingCurve #7)] ≥ 0\n F[(TabulatedRatingCurve #7, Terminal #10)] ≥ 0\n F[(TabulatedRatingCurve #7, Basin #12)] ≥ 0\n F[(Basin #2, User #3)] ≥ 0\n F[(User #13, Terminal #10)] ≥ 0\n F[(Basin #12, User #13)] ≥ 0\n F[(Basin #2, Basin #5)] ≥ 0\n F[(Basin #5, Basin #2)] ≥ 0\n F_basin_in[Basin #12] ≥ 0\n F_basin_in[Basin #2] ≥ 0\n F_basin_in[Basin #5] ≥ 0\n F_basin_out[Basin #12] ≥ 0\n F_basin_out[Basin #2] ≥ 0\n F_basin_out[Basin #5] ≥ 0",
"crumbs": [
"Julia core",
"Allocation"
@@ -938,7 +938,7 @@
"href": "core/usage.html#sec-solver-settings",
"title": "Usage",
"section": "1.1 Solver settings",
- "text": "1.1 Solver settings\nThe solver section in the configuration file is entirely optional, since we aim to use defaults that will generally work well. Common reasons to modify the solver settings are to adjust the calculation or result stepsizes: adaptive, dt, and saveat. If your model does not converge, or your performance is lower than expected, it can help to adjust other solver settings as well.\nThe default solver algorithm = \"QNDF\", which is a multistep method similar to Matlab’s ode15s (Shampine and Reichelt 1997). It is an implicit method that supports the default adaptive = true timestepping. The full list of available solvers is: QNDF, Rosenbrock23, TRBDF2, Rodas5, KenCarp4, Tsit5, RK4, ImplicitEuler, Euler. Information on the solver algorithms can be found on the ODE solvers page.\nThe dt controls the stepsize. When adaptive = true, dt only applies to the initial stepsize, and by default it is automatically determined. When adaptive = false a suitable dt must always be provided. The value is in seconds, so dt = 3600.0 corresponds to an hourly timestep. When adaptive = true, dtmin and dtmax control the minimum and maximum allowed dt. If a smaller dt than dtmin is needed to meet the set error tolerances, the simulation stops, unless force_dtmin is set to true. force_dtmin is off by default to ensure an accurate solution.\nThe default result stepsize, saveat = 86400 will save results after every day that passed. The calculation and result stepsize need not be the same. If you wish to save every calculation step, set saveat = 0. If you wish to not save any intermediate steps, set saveat = inf.\nThe Jacobian matrix provides information about the local sensitivity of the model with respect to changes in the states. For implicit solvers it must be calculated often, which can be expensive to do. There are several methods to do this. By default Ribasim uses a Jacobian derived automatically using ForwardDiff.jl with memory management provided by PreallocationTools.jl. If this is not used by setting autodiff = false, the Jacobian is calculated with a finite difference method, which can be less accurate and more expensive.\nBy default the Jacobian matrix is a sparse matrix (sparse = true). Since each state typically only depends on a small number of other states, this is generally more efficient, especially for larger models. The sparsity structure is calculated from the network and provided as a Jacobian prototype to the solver. For small or highly connected models it could be faster to use a dense Jacobian matrix instead by setting sparse = false.\nThe total maximum number of iterations maxiters = 1e9, can normally stay as-is unless doing extremely long simulations.\nThe absolute and relative tolerance for adaptive timestepping can be set with abstol and reltol. For more information on these and other solver options, see the DifferentialEquations.jl docs.",
+ "text": "1.1 Solver settings\nThe solver section in the configuration file is entirely optional, since we aim to use defaults that will generally work well. Common reasons to modify the solver settings are to adjust the calculation or result stepsizes: dt, and saveat. If your model does not converge, or your performance is lower than expected, it can help to adjust other solver settings as well.\nThe default solver algorithm = \"QNDF\", which is a multistep method similar to Matlab’s ode15s (Shampine and Reichelt 1997). It is an implicit method that supports the default adaptive timestepping. The full list of available solvers is: QNDF, Rosenbrock23, TRBDF2, Rodas5, KenCarp4, Tsit5, RK4, ImplicitEuler, Euler. Information on the solver algorithms can be found on the ODE solvers page.\nBy default Ribasim uses adaptive timestepping, though not all algorithms support adaptive timestepping. To use fixed timesteps, provide a timestep size in seconds; dt = 3600.0 corresponds to an hourly timestep. With adaptive timestepping, dtmin and dtmax control the minimum and maximum allowed dt. If a smaller dt than dtmin is needed to meet the set error tolerances, the simulation stops, unless force_dtmin is set to true. force_dtmin is off by default to ensure an accurate solution.\nThe default result stepsize, saveat = 86400 will save results after every day that passed. The calculation and result stepsize need not be the same. If you wish to save every calculation step, set saveat = 0. If you wish to not save any intermediate steps, set saveat = inf.\nThe Jacobian matrix provides information about the local sensitivity of the model with respect to changes in the states. For implicit solvers it must be calculated often, which can be expensive to do. There are several methods to do this. By default Ribasim uses a Jacobian derived automatically using ForwardDiff.jl with memory management provided by PreallocationTools.jl. If this is not used by setting autodiff = false, the Jacobian is calculated with a finite difference method, which can be less accurate and more expensive.\nBy default the Jacobian matrix is a sparse matrix (sparse = true). Since each state typically only depends on a small number of other states, this is generally more efficient, especially for larger models. The sparsity structure is calculated from the network and provided as a Jacobian prototype to the solver. For small or highly connected models it could be faster to use a dense Jacobian matrix instead by setting sparse = false.\nThe total maximum number of iterations maxiters = 1e9, can normally stay as-is unless doing extremely long simulations.\nThe absolute and relative tolerance for adaptive timestepping can be set with abstol and reltol. For more information on these and other solver options, see the DifferentialEquations.jl docs.",
"crumbs": [
"Julia core",
"Usage"
Here \(p > 0\) is the threshold value which determines the interval \([0,p]\) of the smooth transition between \(0\) and \(1\), see the plot below.
-Code
import numpy as np
diff --git a/core/usage.html b/core/usage.html
index 59f5726c4..9867ebd86 100644
--- a/core/usage.html
+++ b/core/usage.html
@@ -399,31 +399,30 @@ 1 Configuration f
[solver]
algorithm = "QNDF" # optional, default "QNDF"
saveat = 86400 # optional, default 86400, 0 saves every timestep, inf saves only at start- and endtime
-adaptive = true # optional, default true
-dt = 0.0 # optional when adaptive = true, default automatically determined
-dtmin = 0.0 # optional, default 0.0
-dtmax = 0.0 # optional, default length of simulation
-force_dtmin = false # optional, default false
-abstol = 1e-6 # optional, default 1e-6
-reltol = 1e-5 # optional, default 1e-5
-maxiters = 1e9 # optional, default 1e9
-sparse = true # optional, default true
-autodiff = true # optional, default true
-
-[logging]
-# defines the logging level of Ribasim
-verbosity = "info" # optional, default "info", can otherwise be "debug", "warn" or "error"
-timing = false # optional, whether to log debug timing statements
-
-[results]
-# These results files are always written
-compression = true # optional, default true, using zstd compression
-compression_level = 6 # optional, default 6
1.1 Solver settings
-The solver section in the configuration file is entirely optional, since we aim to use defaults that will generally work well. Common reasons to modify the solver settings are to adjust the calculation or result stepsizes: adaptive
, dt
, and saveat
. If your model does not converge, or your performance is lower than expected, it can help to adjust other solver settings as well.
The default solver algorithm = "QNDF"
, which is a multistep method similar to Matlab’s ode15s
(Shampine and Reichelt 1997). It is an implicit method that supports the default adaptive = true
timestepping. The full list of available solvers is: QNDF
, Rosenbrock23
, TRBDF2
, Rodas5
, KenCarp4
, Tsit5
, RK4
, ImplicitEuler
, Euler
. Information on the solver algorithms can be found on the ODE solvers page.
The dt
controls the stepsize. When adaptive = true
, dt
only applies to the initial stepsize, and by default it is automatically determined. When adaptive = false
a suitable dt
must always be provided. The value is in seconds, so dt = 3600.0
corresponds to an hourly timestep. When adaptive = true
, dtmin
and dtmax
control the minimum and maximum allowed dt
. If a smaller dt
than dtmin
is needed to meet the set error tolerances, the simulation stops, unless force_dtmin
is set to true
. force_dtmin
is off by default to ensure an accurate solution.
The solver section in the configuration file is entirely optional, since we aim to use defaults that will generally work well. Common reasons to modify the solver settings are to adjust the calculation or result stepsizes: dt
, and saveat
. If your model does not converge, or your performance is lower than expected, it can help to adjust other solver settings as well.
The default solver algorithm = "QNDF"
, which is a multistep method similar to Matlab’s ode15s
(Shampine and Reichelt 1997). It is an implicit method that supports the default adaptive timestepping. The full list of available solvers is: QNDF
, Rosenbrock23
, TRBDF2
, Rodas5
, KenCarp4
, Tsit5
, RK4
, ImplicitEuler
, Euler
. Information on the solver algorithms can be found on the ODE solvers page.
By default Ribasim uses adaptive timestepping, though not all algorithms support adaptive timestepping. To use fixed timesteps, provide a timestep size in seconds; dt = 3600.0
corresponds to an hourly timestep. With adaptive timestepping, dtmin
and dtmax
control the minimum and maximum allowed dt
. If a smaller dt
than dtmin
is needed to meet the set error tolerances, the simulation stops, unless force_dtmin
is set to true
. force_dtmin
is off by default to ensure an accurate solution.
The default result stepsize, saveat = 86400
will save results after every day that passed. The calculation and result stepsize need not be the same. If you wish to save every calculation step, set saveat = 0
. If you wish to not save any intermediate steps, set saveat = inf
.
The Jacobian matrix provides information about the local sensitivity of the model with respect to changes in the states. For implicit solvers it must be calculated often, which can be expensive to do. There are several methods to do this. By default Ribasim uses a Jacobian derived automatically using ForwardDiff.jl with memory management provided by PreallocationTools.jl. If this is not used by setting autodiff = false
, the Jacobian is calculated with a finite difference method, which can be less accurate and more expensive.
By default the Jacobian matrix is a sparse matrix (sparse = true
). Since each state typically only depends on a small number of other states, this is generally more efficient, especially for larger models. The sparsity structure is calculated from the network and provided as a Jacobian prototype to the solver. For small or highly connected models it could be faster to use a dense Jacobian matrix instead by setting sparse = false
.
Validation
1 Connectivity
In the table below, each column shows which node types are allowed to be downstream (or ‘down-control’) of the node type at the top of the column.
-Code
using Ribasim
@@ -546,7 +546,7 @@ 1 Connectivity
2 Neighbor amounts
The table below shows for each node type between which bounds the amount of in- and outneighbors must be, for both flow and control edges.
-
+
Code
= Vector{String}()
diff --git a/python/examples_files/figure-html/cell-71-output-1.png b/python/examples_files/figure-html/cell-71-output-1.png
index e0f14293b..5c654f06b 100644
Binary files a/python/examples_files/figure-html/cell-71-output-1.png and b/python/examples_files/figure-html/cell-71-output-1.png differ
diff --git a/python/test-models.html b/python/test-models.html
index ce3785787..be9609a16 100644
--- a/python/test-models.html
+++ b/python/test-models.html
@@ -227,7 +227,7 @@ flow_in_min Test models
Ribasim developers use the following models in their testbench and in order to test new features.
-
+
Code
import ribasim_testmodels
diff --git a/search.json b/search.json
index 915ae6e2d..a3d89a88c 100644
--- a/search.json
+++ b/search.json
@@ -26,7 +26,7 @@
"href": "build/index.html#functions",
"title": "1 API Reference",
"section": "1.3 Functions",
- "text": "1.3 Functions\n# BasicModelInterface.finalize — Method.\nBMI.finalize(model::Model)::Model\nWrite all results to the configured files.\nsource\n# BasicModelInterface.initialize — Method.\nBMI.initialize(T::Type{Model}, config_path::AbstractString)::Model\nInitialize a Model from the path to the TOML configuration file.\nsource\n# CommonSolve.solve! — Method.\nsolve!(model::Model)::ODESolution\nSolve a Model until the configured endtime.\nsource\n# Ribasim.add_basin_term! — Method.\nAdd a term to the expression of the objective function corresponding to the demand of a basin.\nsource\n# Ribasim.add_constraints_absolute_value! — Method.\nMinimizing |expr| can be achieved by introducing a new variable exprabs and posing the following constraints: exprabs >= expr expr_abs >= -expr\nsource\n# Ribasim.add_constraints_absolute_value_basin! — Method.\nAdd constraints so that variables Fabsbasin act as the absolute value of the expression comparing flow to a basin to its demand.\nsource\n# Ribasim.add_constraints_absolute_value_user! — Method.\nAdd constraints so that variables Fabsuser act as the absolute value of the expression comparing flow to an user to its demand.\nsource\n# Ribasim.add_constraints_basin_flow! — Method.\nAdd the basin flow constraints to the allocation problem. The constraint indices are the basin node IDs.\nConstraint: flow out of basin <= basin capacity\nsource\n# Ribasim.add_constraints_capacity! — Method.\nAdd the flow capacity constraints to the allocation problem. Only finite capacities get a constraint. The constraint indices are (edgesourceid, edgedstid).\nConstraint: flow over edge <= edge capacity\nsource\n# Ribasim.add_constraints_flow_conservation! — Method.\nAdd the flow conservation constraints to the allocation problem. The constraint indices are user node IDs.\nConstraint: sum(flows out of node node) == flows into node + flow from storage and vertical fluxes\nsource\n# Ribasim.add_constraints_fractional_flow! — Method.\nAdd the fractional flow constraints to the allocation problem. The constraint indices are allocation edges over a fractional flow node.\nConstraint: flow after fractional_flow node <= fraction * inflow\nsource\n# Ribasim.add_constraints_source! — Method.\nAdd the source constraints to the allocation problem. The actual threshold values will be set before each allocation solve. The constraint indices are (edgesourceid, edgedstid).\nConstraint: flow over source edge <= source flow in subnetwork\nsource\n# Ribasim.add_constraints_user_returnflow! — Method.\nAdd the user returnflow constraints to the allocation problem. The constraint indices are user node IDs.\nConstraint: outflow from user <= return factor * inflow to user\nsource\n# Ribasim.add_flow! — Method.\nAdd the given flow q to the flow over the edge on the horizontal (self-loop) edge from id to id.\nsource\n# Ribasim.add_flow! — Method.\nAdd the given flow q to the existing flow over the edge between the given nodes.\nsource\n# Ribasim.add_objective_term! — Method.\nAdd a term to the objective function given by the objective type, depending in the provided flow variable and the associated demand.\nsource\n# Ribasim.add_subnetwork_connections! — Method.\nAdd the edges connecting the main network work to a subnetwork to both the main network and subnetwork allocation network.\nsource\n# Ribasim.add_user_term! — Method.\nAdd a term to the expression of the objective function corresponding to the demand of a user.\nsource\n# Ribasim.add_variables_absolute_value! — Method.\nCertain 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.\nsource\n# Ribasim.add_variables_basin! — Method.\nAdd the variables for supply/demand of a basin to the problem. The variable indices are the node_ids of the basins in the subnetwork.\nsource\n# Ribasim.add_variables_flow! — Method.\nAdd the flow variables F to the allocation problem. The variable indices are (edgesourceid, edgedstid). Non-negativivity constraints are also immediately added to the flow variables.\nsource\n# Ribasim.adjust_basin_capacities! — Method.\nSet the values of the basin outflows. 2 cases:\n\nBefore the first allocation solve, set the capacities to their full capacity if there is surplus storage;\nBefore an allocation solve, subtract the flow used by allocation for the previous priority from the capacities.\n\nsource\n# Ribasim.adjust_edge_capacities! — Method.\nSet the values of the edge capacities. 2 cases:\n\nBefore the first allocation solve, set the edge capacities to their full capacity;\nBefore an allocation solve, subtract the flow used by allocation for the previous priority from the edge capacities.\n\nsource\n# Ribasim.adjust_source_capacities! — Method.\nAdjust the source flows.\nsource\n# Ribasim.all_neighbor_labels_type — Method.\nGet the in- and outneighbor node IDs of the given node ID (label) over the given edge type in the graph.\nsource\n# Ribasim.allocate! — Method.\nUpdate 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.\nsource\n# Ribasim.allocation_graph — Method.\nBuild the graph used for the allocation problem.\nsource\n# Ribasim.allocation_graph_used_nodes! — Method.\nFind all nodes in the subnetwork which will be used in the allocation network. Some nodes are skipped to optimize allocation optimization.\nsource\n# Ribasim.allocation_path_exists_in_graph — Method.\nFind out whether a path exists between a start node and end node in the given allocation network.\nsource\n# Ribasim.allocation_problem — Method.\nConstruct the allocation problem for the current subnetwork as a JuMP.jl model.\nsource\n# Ribasim.allocation_table — Method.\nCreate an allocation result table for the saved data\nsource\n# Ribasim.assign_allocations! — Method.\nAssign the allocations to the users as determined by the solution of the allocation problem.\nsource\n# Ribasim.avoid_using_own_returnflow! — Method.\nRemove allocation user return flow edges that are upstream of the user itself.\nsource\n# Ribasim.basin_bottom — Method.\nReturn the bottom elevation of the basin with index i, or nothing if it doesn’t exist\nsource\n# Ribasim.basin_bottoms — Method.\nGet the bottom on both ends of a node. If only one has a bottom, use that for both.\nsource\n# Ribasim.basin_table — Method.\nCreate the basin result table from the saved data\nsource\n# Ribasim.create_callbacks — Method.\nCreate 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.\nsource\n# Ribasim.create_graph — Method.\nReturn a directed metagraph with data of nodes (NodeMetadata): NodeMetadata\nand data of edges (EdgeMetadata): EdgeMetadata\nsource\n# Ribasim.create_storage_tables — Method.\nRead the Basin / profile table and return all area and level and computed storage values\nsource\n# Ribasim.datetime_since — Method.\ndatetime_since(t::Real, t0::DateTime)::DateTime\nConvert 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.\nsource\n# Ribasim.datetimes — Method.\nGet all saved times as a Vector{DateTime}\nsource\n# Ribasim.discrete_control_affect! — Method.\nChange parameters based on the control logic.\nsource\n# Ribasim.discrete_control_affect_downcrossing! — Method.\nAn downcrossing means that a condition (always greater than) becomes false.\nsource\n# Ribasim.discrete_control_affect_upcrossing! — Method.\nAn upcrossing means that a condition (always greater than) becomes true.\nsource\n# Ribasim.discrete_control_condition — Method.\nListens for changes in condition truths.\nsource\n# Ribasim.discrete_control_table — Method.\nCreate a discrete control result table from the saved data\nsource\n# Ribasim.expand_logic_mapping — Method.\nReplace the truth states in the logic mapping which contain wildcards with all possible explicit truth states.\nsource\n# Ribasim.find_allocation_graph_edges! — Method.\nThis loop finds allocation network edges in several ways:\n\nBetween allocation network nodes whose equivalent in the subnetwork are directly connected\nBetween allocation network nodes whose equivalent in the subnetwork are connected with one or more allocation network nodes in between\n\nsource\n# Ribasim.find_subnetwork_connections! — Method.\nFind the edges from the main network to a subnetwork.\nsource\n# Ribasim.findlastgroup — Method.\nFor 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.\nsource\n# Ribasim.findsorted — Method.\nFind 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.\nsource\n# Ribasim.flow_table — Method.\nCreate a flow result table from the saved data\nsource\n# Ribasim.formulate_basins! — Method.\nSmoothly let the evaporation flux go to 0 when at small water depths Currently at less than 0.1 m.\nsource\n# Ribasim.formulate_flow! — Method.\nDirected graph: outflow is positive!\nsource\n# Ribasim.formulate_flow! — Method.\nConservation of energy for two basins, a and b:\nh_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)\nWhere:\n\nha, hb are the heads at basin a and b.\nva, vb are the velocities at basin a and b.\ng is the gravitational constant.\nS_f is the friction slope.\nC is an expansion or extraction coefficient.\n\nWe assume velocity differences are negligible (va = vb):\nh_a = h_b + S_f * L\nThe friction losses are approximated by the Gauckler-Manning formula:\nQ = A * (1 / n) * R_h^(2/3) * S_f^(1/2)\nWhere:\n\nWhere A is the cross-sectional area.\nV is the cross-sectional average velocity.\nn is the Gauckler-Manning coefficient.\nR_h is the hydraulic radius.\nS_f is the friction slope.\n\nThe hydraulic radius is defined as:\nR_h = A / P\nWhere P is the wetted perimeter.\nThe average of the upstream and downstream water depth is used to compute cross-sectional area and hydraulic radius. This ensures that a basin can receive water after it has gone dry.\nsource\n# Ribasim.formulate_flow! — Method.\nDirected graph: outflow is positive!\nsource\n# Ribasim.get_area_and_level — Method.\nCompute the area and level of a basin given its storage. Also returns darea/dlevel as it is needed for the Jacobian.\nsource\n# Ribasim.get_basin_capacity — Method.\nGet 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). Storages are converted to flows by dividing by the allocation timestep.\nsource\n# Ribasim.get_basin_data — Method.\nGet several variables associated with a basin:\n\nIts current storage\nThe allocation update interval\nThe influx (sum of instantaneous vertical fluxes of the basin)\nThe index of the connected target_level node (0 if such a node does not exist)\nThe index of the basin\n\nsource\n# Ribasim.get_basin_demand — Method.\nGet 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). Storages are converted to flows by dividing by the allocation timestep.\nsource\n# Ribasim.get_chunk_sizes — Method.\nGet the chunk sizes for DiffCache; differentiation w.r.t. u and t (the latter only if a Rosenbrock algorithm is used).\nsource\n# Ribasim.get_compressor — Method.\nGet the compressor based on the Results section\nsource\n# Ribasim.get_flow — Method.\nGet the flow over the given horizontal (selfloop) edge (val is needed for get_tmp from ForwardDiff.jl).\nsource\n# Ribasim.get_flow — Method.\nGet the flow over the given edge (val is needed for get_tmp from ForwardDiff.jl).\nsource\n# Ribasim.get_fractional_flow_connected_basins — Method.\nGet the node type specific indices of the fractional flows and basins, that are consecutively connected to a node of given id.\nsource\n# Ribasim.get_jac_prototype — Method.\nGet 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.\nIn Ribasim the Jacobian is typically sparse because each state only depends on a small number of other states.\nNote: 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.\nsource\n# Ribasim.get_level — Method.\nGet 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\nsource\n# Ribasim.get_scalar_interpolation — Method.\nLinear interpolation of a scalar with constant extrapolation.\nsource\n# Ribasim.get_storage_from_level — Method.\nGet the storage of a basin from its level.\nsource\n# Ribasim.get_storages_and_levels — Method.\nGet the storage and level of all basins as matrices of nbasin × ntime\nsource\n# Ribasim.get_storages_from_levels — Method.\nCompute the storages of the basins based on the water level of the basins.\nsource\n# Ribasim.get_tstops — Method.\nFrom an iterable of DateTimes, find the times the solver needs to stop\nsource\n# Ribasim.get_value — Method.\nGet a value for a condition. Currently supports getting levels from basins and flows from flow boundaries.\nsource\n# Ribasim.id_index — Method.\nGet the index of an ID in a set of indices.\nsource\n# Ribasim.indicate_allocation_flow! — Method.\nAdd to the edge metadata that the given edge is used for allocation flow. If the edge does not exist, it is created.\nsource\n# Ribasim.inflow_id — Method.\nGet the unique inneighbor over a flow edge.\nsource\n# Ribasim.inflow_ids — Method.\nGet the inneighbors over flow edges.\nsource\n# Ribasim.inflow_ids_allocation — Method.\nGet the inneighbors of the given ID such that the connecting edge is an allocation flow edge.\nsource\n# Ribasim.inneighbor_labels_type — Method.\nGet the inneighbor node IDs of the given node ID (label) over the given edge type in the graph.\nsource\n# Ribasim.inoutflow_ids — Method.\nGet the in- and outneighbors over flow edges.\nsource\n# Ribasim.is_allocation_source — Method.\nFind out whether the given edge is a source for an allocation network.\nsource\n# Ribasim.is_current_module — Method.\nis_current_module(log::LogMessageType)::Bool\nReturns true if the log message is from the current module or a submodule.\n\nSee https://github.com/JuliaLogging/LoggingExtras.jl/blob/d35e7c8cfc197853ee336ace17182e6ed36dca24/src/CompositionalLoggers/earlyfiltered.jl#L39\nfor the information available in log.\nsource\n# Ribasim.is_flow_constraining — Method.\nWhether the given node node is flow constraining by having a maximum flow rate.\nsource\n# Ribasim.is_flow_direction_constraining — Method.\nWhether the given node is flow direction constraining (only in direction of edges).\nsource\n# Ribasim.load_data — Method.\nload_data(db::DB, config::Config, nodetype::Symbol, kind::Symbol)::Union{Table, Query, Nothing}\nLoad data from Arrow files if available, otherwise the database. Returns either an Arrow.Table, SQLite.Query or nothing if the data is not present.\nsource\n# Ribasim.load_structvector — Method.\nload_structvector(db::DB, config::Config, ::Type{T})::StructVector{T}\nLoad 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.\nsource\n# Ribasim.low_storage_factor — Method.\nIf id is a Basin with storage below the threshold, return a reduction factor != 1\nsource\n# Ribasim.main — Method.\nmain(toml_path::AbstractString)::Cint\nmain(ARGS::Vector{String})::Cint\nmain()::Cint\nThis is the main entry point of the application. Performs argument parsing and sets up logging for both terminal and file. Calls Ribasim.run() and handles exceptions to convert to exit codes.\nsource\n# Ribasim.metadata_from_edge — Method.\nGet the metadata of an edge in the graph from an edge of the underlying DiGraph.\nsource\n# Ribasim.nodefields — Method.\nGet all node fieldnames of the parameter object.\nsource\n# Ribasim.nodetype — Method.\nFrom a SchemaVersion(“ribasim.flowboundary.static”, 1) return (:FlowBoundary, :static)\nsource\n# Ribasim.outflow_id — Method.\nGet the unique outneighbor over a flow edge.\nsource\n# Ribasim.outflow_ids — Method.\nGet the outneighbors over flow edges.\nsource\n# Ribasim.outflow_ids_allocation — Method.\nGet the outneighbors of the given ID such that the connecting edge is an allocation flow edge.\nsource\n# Ribasim.outneighbor_labels_type — Method.\nGet the outneighbor node IDs of the given node ID (label) over the given edge type in the graph.\nsource\n# Ribasim.parse_static_and_time — Method.\nProcess 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.\nsource\n# Ribasim.pkgversion — Method.\nGet the package version of a given module\nsource\n# Ribasim.process_allocation_graph_edges! — Method.\nFor the composite allocation network edges:\n\nFind out whether they are connected to allocation network nodes on both ends\nCompute their capacity\nFind out their allowed flow direction(s)\n\nsource\n# Ribasim.profile_storage — Method.\nCalculate a profile storage by integrating the areas over the levels\nsource\n# Ribasim.qh_interpolation — Method.\nFrom a table with columns nodeid, flowrate (Q) and level (h), create a LinearInterpolation from level to flow rate for a given node_id.\nsource\n# Ribasim.reduction_factor — Method.\nFunction that goes smoothly from 0 to 1 in the interval [0,threshold], and is constant outside this interval.\nsource\n# Ribasim.run — Method.\nrun(config_file::AbstractString)::Model\nrun(config::Config)::Model\nRun 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 write_results.\nsource\n# Ribasim.save_allocation_flows! — Method.\nSave the allocation flows per basin and physical edge.\nsource\n# Ribasim.save_demands_and_allocations! — Method.\nSave the demands and allocated flows for users and basins. Note: Basin supply (negative demand) is only saved for the first priority.\nsource\n# Ribasim.save_flow — Method.\nCopy the current flow to the SavedValues\nsource\n# Ribasim.save_subgrid_level — Method.\nInterpolate the levels and save them to SavedValues\nsource\n# Ribasim.scalar_interpolation_derivative — Method.\nDerivative of scalar interpolation.\nsource\n# Ribasim.seconds_since — Method.\nseconds_since(t::DateTime, t0::DateTime)::Float64\nConvert 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.\nsource\n# Ribasim.set_current_value! — Method.\nFrom 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.\nsource\n# Ribasim.set_flow! — Method.\nSet the given flow q on the horizontal (self-loop) edge from id to id.\nsource\n# Ribasim.set_flow! — Method.\nSet the given flow q over the edge between the given nodes.\nsource\n# Ribasim.set_fractional_flow_in_allocation! — Method.\nUpdate the fractional flow fractions in an allocation problem.\nsource\n# Ribasim.set_initial_discrete_controlled_parameters! — Method.\nSet parameters of nodes that are controlled by DiscreteControl to the values corresponding to the initial state of the model.\nsource\n# Ribasim.set_is_pid_controlled! — Method.\nSet ispidcontrolled to true for those pumps and outlets that are PID controlled\nsource\n# Ribasim.set_objective_priority! — Method.\nSet the objective for the given priority. For an objective with absolute values this also involves adjusting constraints.\nsource\n# Ribasim.set_static_value! — Method.\nLoad data from a source table static into a destination table. Data is matched based on the node_id, which is sorted.\nsource\n# Ribasim.set_table_row! — Method.\nUpdate 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 missing, it is not set.\nsource\n# Ribasim.sorted_table! — Method.\nDepending on if a table can be sorted, either sort it or assert that it is sorted.\nTables loaded from the database into memory can be sorted. Tables loaded from Arrow files are memory mapped and can therefore not be sorted.\nsource\n# Ribasim.timesteps — Method.\nGet all saved times in seconds since start\nsource\n# Ribasim.update_allocation! — Method.\nSolve the allocation problem for all users and assign allocated abstractions to user nodes.\nsource\n# Ribasim.update_basin — Method.\nLoad updates from ‘Basin / time’ into the parameters\nsource\n# Ribasim.update_jac_prototype! — Method.\nMethod for nodes that do not contribute to the Jacobian\nsource\n# Ribasim.update_jac_prototype! — Method.\nThe 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.\nsource\n# Ribasim.update_jac_prototype! — Method.\nIf 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.\nsource\n# Ribasim.update_jac_prototype! — Method.\nIf 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.\nsource\n# Ribasim.update_tabulated_rating_curve! — Method.\nLoad updates from ‘TabulatedRatingCurve / time’ into the parameters\nsource\n# Ribasim.valid_discrete_control — Method.\nCheck:\n\nwhether control states are defined for discrete controlled nodes;\nWhether the supplied truth states have the proper length;\nWhether look_ahead is only supplied for condition variables given by a time-series.\n\nsource\n# Ribasim.valid_edge_types — Method.\nCheck that only supported edge types are declared.\nsource\n# Ribasim.valid_edges — Method.\nTest for each node given its node type whether the nodes that\nare downstream (‘down-edge’) of this node are of an allowed type\nsource\n# Ribasim.valid_flow_rates — Method.\nTest whether static or discrete controlled flow rates are indeed non-negative.\nsource\n# Ribasim.valid_fractional_flow — Method.\nCheck 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.\nsource\n# Ribasim.valid_n_neighbors — Method.\nTest for each node given its node type whether it has an allowed number of flow/control inneighbors and outneighbors\nsource\n# Ribasim.valid_profiles — Method.\nCheck whether the profile data has no repeats in the levels and the areas start positive.\nsource\n# Ribasim.valid_sources — Method.\nThe source nodes must only have one allocation outneighbor and no allocation inneighbors.\nsource\n# Ribasim.valid_subgrid — Method.\nValidate the entries for a single subgrid element.\nsource\n# Ribasim.water_balance! — Method.\nThe right hand side function of the system of ODEs set up by Ribasim.\nsource\n# Ribasim.write_arrow — Method.\nWrite a result table to disk as an Arrow file\nsource\n# Ribasim.write_results — Method.\nwrite_results(model::Model)::Model\nWrite all results to the Arrow files as specified in the model configuration.\nsource\n# Ribasim.config.algorithm — Method.\nCreate an OrdinaryDiffEqAlgorithm from solver config\nsource\n# Ribasim.config.convert_saveat — Method.\nConvert the saveat Float64 from our Config to SciML’s saveat\nsource\n# Ribasim.config.input_path — Method.\nConstruct a path relative to both the TOML directory and the optional input_dir\nsource\n# Ribasim.config.results_path — Method.\nConstruct a path relative to both the TOML directory and the optional results_dir\nsource\n# Ribasim.config.snake_case — Method.\nConvert a string from CamelCase to snake_case.\nsource",
+ "text": "1.3 Functions\n# BasicModelInterface.finalize — Method.\nBMI.finalize(model::Model)::Model\nWrite all results to the configured files.\nsource\n# BasicModelInterface.initialize — Method.\nBMI.initialize(T::Type{Model}, config_path::AbstractString)::Model\nInitialize a Model from the path to the TOML configuration file.\nsource\n# CommonSolve.solve! — Method.\nsolve!(model::Model)::ODESolution\nSolve a Model until the configured endtime.\nsource\n# Ribasim.add_basin_term! — Method.\nAdd a term to the expression of the objective function corresponding to the demand of a basin.\nsource\n# Ribasim.add_constraints_absolute_value! — Method.\nMinimizing |expr| can be achieved by introducing a new variable exprabs and posing the following constraints: exprabs >= expr expr_abs >= -expr\nsource\n# Ribasim.add_constraints_absolute_value_basin! — Method.\nAdd constraints so that variables Fabsbasin act as the absolute value of the expression comparing flow to a basin to its demand.\nsource\n# Ribasim.add_constraints_absolute_value_user! — Method.\nAdd constraints so that variables Fabsuser act as the absolute value of the expression comparing flow to an user to its demand.\nsource\n# Ribasim.add_constraints_basin_flow! — Method.\nAdd the basin flow constraints to the allocation problem. The constraint indices are the basin node IDs.\nConstraint: flow out of basin <= basin capacity\nsource\n# Ribasim.add_constraints_capacity! — Method.\nAdd the flow capacity constraints to the allocation problem. Only finite capacities get a constraint. The constraint indices are (edgesourceid, edgedstid).\nConstraint: flow over edge <= edge capacity\nsource\n# Ribasim.add_constraints_flow_conservation! — Method.\nAdd the flow conservation constraints to the allocation problem. The constraint indices are user node IDs.\nConstraint: sum(flows out of node node) == flows into node + flow from storage and vertical fluxes\nsource\n# Ribasim.add_constraints_fractional_flow! — Method.\nAdd the fractional flow constraints to the allocation problem. The constraint indices are allocation edges over a fractional flow node.\nConstraint: flow after fractional_flow node <= fraction * inflow\nsource\n# Ribasim.add_constraints_source! — Method.\nAdd the source constraints to the allocation problem. The actual threshold values will be set before each allocation solve. The constraint indices are (edgesourceid, edgedstid).\nConstraint: flow over source edge <= source flow in subnetwork\nsource\n# Ribasim.add_constraints_user_returnflow! — Method.\nAdd the user returnflow constraints to the allocation problem. The constraint indices are user node IDs.\nConstraint: outflow from user <= return factor * inflow to user\nsource\n# Ribasim.add_flow! — Method.\nAdd the given flow q to the flow over the edge on the horizontal (self-loop) edge from id to id.\nsource\n# Ribasim.add_flow! — Method.\nAdd the given flow q to the existing flow over the edge between the given nodes.\nsource\n# Ribasim.add_objective_term! — Method.\nAdd a term to the objective function given by the objective type, depending in the provided flow variable and the associated demand.\nsource\n# Ribasim.add_subnetwork_connections! — Method.\nAdd the edges connecting the main network work to a subnetwork to both the main network and subnetwork allocation network.\nsource\n# Ribasim.add_user_term! — Method.\nAdd a term to the expression of the objective function corresponding to the demand of a user.\nsource\n# Ribasim.add_variables_absolute_value! — Method.\nCertain 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.\nsource\n# Ribasim.add_variables_basin! — Method.\nAdd the variables for supply/demand of a basin to the problem. The variable indices are the node_ids of the basins in the subnetwork.\nsource\n# Ribasim.add_variables_flow! — Method.\nAdd the flow variables F to the allocation problem. The variable indices are (edgesourceid, edgedstid). Non-negativivity constraints are also immediately added to the flow variables.\nsource\n# Ribasim.adjust_basin_capacities! — Method.\nSet the values of the basin outflows. 2 cases:\n\nBefore the first allocation solve, set the capacities to their full capacity if there is surplus storage;\nBefore an allocation solve, subtract the flow used by allocation for the previous priority from the capacities.\n\nsource\n# Ribasim.adjust_edge_capacities! — Method.\nSet the values of the edge capacities. 2 cases:\n\nBefore the first allocation solve, set the edge capacities to their full capacity;\nBefore an allocation solve, subtract the flow used by allocation for the previous priority from the edge capacities.\n\nsource\n# Ribasim.adjust_source_capacities! — Method.\nAdjust the source flows.\nsource\n# Ribasim.all_neighbor_labels_type — Method.\nGet the in- and outneighbor node IDs of the given node ID (label) over the given edge type in the graph.\nsource\n# Ribasim.allocate! — Method.\nUpdate 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.\nsource\n# Ribasim.allocation_graph — Method.\nBuild the graph used for the allocation problem.\nsource\n# Ribasim.allocation_graph_used_nodes! — Method.\nFind all nodes in the subnetwork which will be used in the allocation network. Some nodes are skipped to optimize allocation optimization.\nsource\n# Ribasim.allocation_path_exists_in_graph — Method.\nFind out whether a path exists between a start node and end node in the given allocation network.\nsource\n# Ribasim.allocation_problem — Method.\nConstruct the allocation problem for the current subnetwork as a JuMP.jl model.\nsource\n# Ribasim.allocation_table — Method.\nCreate an allocation result table for the saved data\nsource\n# Ribasim.assign_allocations! — Method.\nAssign the allocations to the users as determined by the solution of the allocation problem.\nsource\n# Ribasim.avoid_using_own_returnflow! — Method.\nRemove allocation user return flow edges that are upstream of the user itself.\nsource\n# Ribasim.basin_bottom — Method.\nReturn the bottom elevation of the basin with index i, or nothing if it doesn’t exist\nsource\n# Ribasim.basin_bottoms — Method.\nGet the bottom on both ends of a node. If only one has a bottom, use that for both.\nsource\n# Ribasim.basin_table — Method.\nCreate the basin result table from the saved data\nsource\n# Ribasim.create_callbacks — Method.\nCreate 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.\nsource\n# Ribasim.create_graph — Method.\nReturn a directed metagraph with data of nodes (NodeMetadata): NodeMetadata\nand data of edges (EdgeMetadata): EdgeMetadata\nsource\n# Ribasim.create_storage_tables — Method.\nRead the Basin / profile table and return all area and level and computed storage values\nsource\n# Ribasim.datetime_since — Method.\ndatetime_since(t::Real, t0::DateTime)::DateTime\nConvert 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.\nsource\n# Ribasim.datetimes — Method.\nGet all saved times as a Vector{DateTime}\nsource\n# Ribasim.discrete_control_affect! — Method.\nChange parameters based on the control logic.\nsource\n# Ribasim.discrete_control_affect_downcrossing! — Method.\nAn downcrossing means that a condition (always greater than) becomes false.\nsource\n# Ribasim.discrete_control_affect_upcrossing! — Method.\nAn upcrossing means that a condition (always greater than) becomes true.\nsource\n# Ribasim.discrete_control_condition — Method.\nListens for changes in condition truths.\nsource\n# Ribasim.discrete_control_table — Method.\nCreate a discrete control result table from the saved data\nsource\n# Ribasim.expand_logic_mapping — Method.\nReplace the truth states in the logic mapping which contain wildcards with all possible explicit truth states.\nsource\n# Ribasim.find_allocation_graph_edges! — Method.\nThis loop finds allocation network edges in several ways:\n\nBetween allocation network nodes whose equivalent in the subnetwork are directly connected\nBetween allocation network nodes whose equivalent in the subnetwork are connected with one or more allocation network nodes in between\n\nsource\n# Ribasim.find_subnetwork_connections! — Method.\nFind the edges from the main network to a subnetwork.\nsource\n# Ribasim.findlastgroup — Method.\nFor 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.\nsource\n# Ribasim.findsorted — Method.\nFind 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.\nsource\n# Ribasim.flow_table — Method.\nCreate a flow result table from the saved data\nsource\n# Ribasim.formulate_basins! — Method.\nSmoothly let the evaporation flux go to 0 when at small water depths Currently at less than 0.1 m.\nsource\n# Ribasim.formulate_flow! — Method.\nDirected graph: outflow is positive!\nsource\n# Ribasim.formulate_flow! — Method.\nConservation of energy for two basins, a and b:\nh_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)\nWhere:\n\nha, hb are the heads at basin a and b.\nva, vb are the velocities at basin a and b.\ng is the gravitational constant.\nS_f is the friction slope.\nC is an expansion or extraction coefficient.\n\nWe assume velocity differences are negligible (va = vb):\nh_a = h_b + S_f * L\nThe friction losses are approximated by the Gauckler-Manning formula:\nQ = A * (1 / n) * R_h^(2/3) * S_f^(1/2)\nWhere:\n\nWhere A is the cross-sectional area.\nV is the cross-sectional average velocity.\nn is the Gauckler-Manning coefficient.\nR_h is the hydraulic radius.\nS_f is the friction slope.\n\nThe hydraulic radius is defined as:\nR_h = A / P\nWhere P is the wetted perimeter.\nThe average of the upstream and downstream water depth is used to compute cross-sectional area and hydraulic radius. This ensures that a basin can receive water after it has gone dry.\nsource\n# Ribasim.formulate_flow! — Method.\nDirected graph: outflow is positive!\nsource\n# Ribasim.get_area_and_level — Method.\nCompute the area and level of a basin given its storage. Also returns darea/dlevel as it is needed for the Jacobian.\nsource\n# Ribasim.get_basin_capacity — Method.\nGet 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). Storages are converted to flows by dividing by the allocation timestep.\nsource\n# Ribasim.get_basin_data — Method.\nGet several variables associated with a basin:\n\nIts current storage\nThe allocation update interval\nThe influx (sum of instantaneous vertical fluxes of the basin)\nThe index of the connected target_level node (0 if such a node does not exist)\nThe index of the basin\n\nsource\n# Ribasim.get_basin_demand — Method.\nGet 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). Storages are converted to flows by dividing by the allocation timestep.\nsource\n# Ribasim.get_chunk_sizes — Method.\nGet the chunk sizes for DiffCache; differentiation w.r.t. u and t (the latter only if a Rosenbrock algorithm is used).\nsource\n# Ribasim.get_compressor — Method.\nGet the compressor based on the Results section\nsource\n# Ribasim.get_flow — Method.\nGet the flow over the given horizontal (selfloop) edge (val is needed for get_tmp from ForwardDiff.jl).\nsource\n# Ribasim.get_flow — Method.\nGet the flow over the given edge (val is needed for get_tmp from ForwardDiff.jl).\nsource\n# Ribasim.get_fractional_flow_connected_basins — Method.\nGet the node type specific indices of the fractional flows and basins, that are consecutively connected to a node of given id.\nsource\n# Ribasim.get_jac_prototype — Method.\nGet 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.\nIn Ribasim the Jacobian is typically sparse because each state only depends on a small number of other states.\nNote: 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.\nsource\n# Ribasim.get_level — Method.\nGet 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\nsource\n# Ribasim.get_scalar_interpolation — Method.\nLinear interpolation of a scalar with constant extrapolation.\nsource\n# Ribasim.get_storage_from_level — Method.\nGet the storage of a basin from its level.\nsource\n# Ribasim.get_storages_and_levels — Method.\nGet the storage and level of all basins as matrices of nbasin × ntime\nsource\n# Ribasim.get_storages_from_levels — Method.\nCompute the storages of the basins based on the water level of the basins.\nsource\n# Ribasim.get_tstops — Method.\nFrom an iterable of DateTimes, find the times the solver needs to stop\nsource\n# Ribasim.get_value — Method.\nGet a value for a condition. Currently supports getting levels from basins and flows from flow boundaries.\nsource\n# Ribasim.id_index — Method.\nGet the index of an ID in a set of indices.\nsource\n# Ribasim.indicate_allocation_flow! — Method.\nAdd to the edge metadata that the given edge is used for allocation flow. If the edge does not exist, it is created.\nsource\n# Ribasim.inflow_id — Method.\nGet the unique inneighbor over a flow edge.\nsource\n# Ribasim.inflow_ids — Method.\nGet the inneighbors over flow edges.\nsource\n# Ribasim.inflow_ids_allocation — Method.\nGet the inneighbors of the given ID such that the connecting edge is an allocation flow edge.\nsource\n# Ribasim.inneighbor_labels_type — Method.\nGet the inneighbor node IDs of the given node ID (label) over the given edge type in the graph.\nsource\n# Ribasim.inoutflow_ids — Method.\nGet the in- and outneighbors over flow edges.\nsource\n# Ribasim.is_allocation_source — Method.\nFind out whether the given edge is a source for an allocation network.\nsource\n# Ribasim.is_current_module — Method.\nis_current_module(log::LogMessageType)::Bool\nReturns true if the log message is from the current module or a submodule.\n\nSee https://github.com/JuliaLogging/LoggingExtras.jl/blob/d35e7c8cfc197853ee336ace17182e6ed36dca24/src/CompositionalLoggers/earlyfiltered.jl#L39\nfor the information available in log.\nsource\n# Ribasim.is_flow_constraining — Method.\nWhether the given node node is flow constraining by having a maximum flow rate.\nsource\n# Ribasim.is_flow_direction_constraining — Method.\nWhether the given node is flow direction constraining (only in direction of edges).\nsource\n# Ribasim.load_data — Method.\nload_data(db::DB, config::Config, nodetype::Symbol, kind::Symbol)::Union{Table, Query, Nothing}\nLoad data from Arrow files if available, otherwise the database. Returns either an Arrow.Table, SQLite.Query or nothing if the data is not present.\nsource\n# Ribasim.load_structvector — Method.\nload_structvector(db::DB, config::Config, ::Type{T})::StructVector{T}\nLoad 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.\nsource\n# Ribasim.low_storage_factor — Method.\nIf id is a Basin with storage below the threshold, return a reduction factor != 1\nsource\n# Ribasim.main — Method.\nmain(toml_path::AbstractString)::Cint\nmain(ARGS::Vector{String})::Cint\nmain()::Cint\nThis is the main entry point of the application. Performs argument parsing and sets up logging for both terminal and file. Calls Ribasim.run() and handles exceptions to convert to exit codes.\nsource\n# Ribasim.metadata_from_edge — Method.\nGet the metadata of an edge in the graph from an edge of the underlying DiGraph.\nsource\n# Ribasim.nodefields — Method.\nGet all node fieldnames of the parameter object.\nsource\n# Ribasim.nodetype — Method.\nFrom a SchemaVersion(“ribasim.flowboundary.static”, 1) return (:FlowBoundary, :static)\nsource\n# Ribasim.outflow_id — Method.\nGet the unique outneighbor over a flow edge.\nsource\n# Ribasim.outflow_ids — Method.\nGet the outneighbors over flow edges.\nsource\n# Ribasim.outflow_ids_allocation — Method.\nGet the outneighbors of the given ID such that the connecting edge is an allocation flow edge.\nsource\n# Ribasim.outneighbor_labels_type — Method.\nGet the outneighbor node IDs of the given node ID (label) over the given edge type in the graph.\nsource\n# Ribasim.parse_static_and_time — Method.\nProcess 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.\nsource\n# Ribasim.pkgversion — Method.\nGet the package version of a given module\nsource\n# Ribasim.process_allocation_graph_edges! — Method.\nFor the composite allocation network edges:\n\nFind out whether they are connected to allocation network nodes on both ends\nCompute their capacity\nFind out their allowed flow direction(s)\n\nsource\n# Ribasim.profile_storage — Method.\nCalculate a profile storage by integrating the areas over the levels\nsource\n# Ribasim.qh_interpolation — Method.\nFrom a table with columns nodeid, flowrate (Q) and level (h), create a LinearInterpolation from level to flow rate for a given node_id.\nsource\n# Ribasim.reduction_factor — Method.\nFunction that goes smoothly from 0 to 1 in the interval [0,threshold], and is constant outside this interval.\nsource\n# Ribasim.run — Method.\nrun(config_file::AbstractString)::Model\nrun(config::Config)::Model\nRun 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 write_results.\nsource\n# Ribasim.save_allocation_flows! — Method.\nSave the allocation flows per basin and physical edge.\nsource\n# Ribasim.save_demands_and_allocations! — Method.\nSave the demands and allocated flows for users and basins. Note: Basin supply (negative demand) is only saved for the first priority.\nsource\n# Ribasim.save_flow — Method.\nCopy the current flow to the SavedValues\nsource\n# Ribasim.save_subgrid_level — Method.\nInterpolate the levels and save them to SavedValues\nsource\n# Ribasim.scalar_interpolation_derivative — Method.\nDerivative of scalar interpolation.\nsource\n# Ribasim.seconds_since — Method.\nseconds_since(t::DateTime, t0::DateTime)::Float64\nConvert 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.\nsource\n# Ribasim.set_current_value! — Method.\nFrom 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.\nsource\n# Ribasim.set_flow! — Method.\nSet the given flow q on the horizontal (self-loop) edge from id to id.\nsource\n# Ribasim.set_flow! — Method.\nSet the given flow q over the edge between the given nodes.\nsource\n# Ribasim.set_fractional_flow_in_allocation! — Method.\nUpdate the fractional flow fractions in an allocation problem.\nsource\n# Ribasim.set_initial_discrete_controlled_parameters! — Method.\nSet parameters of nodes that are controlled by DiscreteControl to the values corresponding to the initial state of the model.\nsource\n# Ribasim.set_is_pid_controlled! — Method.\nSet ispidcontrolled to true for those pumps and outlets that are PID controlled\nsource\n# Ribasim.set_objective_priority! — Method.\nSet the objective for the given priority. For an objective with absolute values this also involves adjusting constraints.\nsource\n# Ribasim.set_static_value! — Method.\nLoad data from a source table static into a destination table. Data is matched based on the node_id, which is sorted.\nsource\n# Ribasim.set_table_row! — Method.\nUpdate 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 missing, it is not set.\nsource\n# Ribasim.sorted_table! — Method.\nDepending on if a table can be sorted, either sort it or assert that it is sorted.\nTables loaded from the database into memory can be sorted. Tables loaded from Arrow files are memory mapped and can therefore not be sorted.\nsource\n# Ribasim.timesteps — Method.\nGet all saved times in seconds since start\nsource\n# Ribasim.update_allocation! — Method.\nSolve the allocation problem for all users and assign allocated abstractions to user nodes.\nsource\n# Ribasim.update_basin — Method.\nLoad updates from ‘Basin / time’ into the parameters\nsource\n# Ribasim.update_jac_prototype! — Method.\nMethod for nodes that do not contribute to the Jacobian\nsource\n# Ribasim.update_jac_prototype! — Method.\nThe 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.\nsource\n# Ribasim.update_jac_prototype! — Method.\nIf 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.\nsource\n# Ribasim.update_jac_prototype! — Method.\nIf 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.\nsource\n# Ribasim.update_tabulated_rating_curve! — Method.\nLoad updates from ‘TabulatedRatingCurve / time’ into the parameters\nsource\n# Ribasim.valid_discrete_control — Method.\nCheck:\n\nwhether control states are defined for discrete controlled nodes;\nWhether the supplied truth states have the proper length;\nWhether look_ahead is only supplied for condition variables given by a time-series.\n\nsource\n# Ribasim.valid_edge_types — Method.\nCheck that only supported edge types are declared.\nsource\n# Ribasim.valid_edges — Method.\nTest for each node given its node type whether the nodes that\nare downstream (‘down-edge’) of this node are of an allowed type\nsource\n# Ribasim.valid_flow_rates — Method.\nTest whether static or discrete controlled flow rates are indeed non-negative.\nsource\n# Ribasim.valid_fractional_flow — Method.\nCheck 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.\nsource\n# Ribasim.valid_n_neighbors — Method.\nTest for each node given its node type whether it has an allowed number of flow/control inneighbors and outneighbors\nsource\n# Ribasim.valid_profiles — Method.\nCheck whether the profile data has no repeats in the levels and the areas start positive.\nsource\n# Ribasim.valid_sources — Method.\nThe source nodes must only have one allocation outneighbor and no allocation inneighbors.\nsource\n# Ribasim.valid_subgrid — Method.\nValidate the entries for a single subgrid element.\nsource\n# Ribasim.water_balance! — Method.\nThe right hand side function of the system of ODEs set up by Ribasim.\nsource\n# Ribasim.write_arrow — Method.\nWrite a result table to disk as an Arrow file\nsource\n# Ribasim.write_results — Method.\nwrite_results(model::Model)::Model\nWrite all results to the Arrow files as specified in the model configuration.\nsource\n# Ribasim.config.algorithm — Method.\nCreate an OrdinaryDiffEqAlgorithm from solver config\nsource\n# Ribasim.config.convert_dt — Method.\nConvert the dt from our Config to SciML stepsize control arguments\nsource\n# Ribasim.config.convert_saveat — Method.\nConvert the saveat Float64 from our Config to SciML’s saveat\nsource\n# Ribasim.config.input_path — Method.\nConstruct a path relative to both the TOML directory and the optional input_dir\nsource\n# Ribasim.config.results_path — Method.\nConstruct a path relative to both the TOML directory and the optional results_dir\nsource\n# Ribasim.config.snake_case — Method.\nConvert a string from CamelCase to snake_case.\nsource",
"crumbs": [
"Julia core",
"API Reference"
@@ -59,7 +59,7 @@
"href": "build/index.html#index",
"title": "1 API Reference",
"section": "1.6 Index",
- "text": "1.6 Index\n\nRibasim.Ribasim\nRibasim.config\nRibasim.config.algorithms\nRibasim.Allocation\nRibasim.AllocationModel\nRibasim.AllocationModel\nRibasim.Basin\nRibasim.DiscreteControl\nRibasim.EdgeMetadata\nRibasim.FlatVector\nRibasim.FlowBoundary\nRibasim.FractionalFlow\nRibasim.InNeighbors\nRibasim.LevelBoundary\nRibasim.LinearResistance\nRibasim.ManningResistance\nRibasim.Model\nRibasim.NodeMetadata\nRibasim.OutNeighbors\nRibasim.Outlet\nRibasim.PidControl\nRibasim.Pump\nRibasim.Subgrid\nRibasim.TabulatedRatingCurve\nRibasim.TargetLevel\nRibasim.Terminal\nRibasim.User\nRibasim.config.Config\nBasicModelInterface.finalize\nBasicModelInterface.initialize\nCommonSolve.solve!\nRibasim.add_basin_term!\nRibasim.add_constraints_absolute_value!\nRibasim.add_constraints_absolute_value_basin!\nRibasim.add_constraints_absolute_value_user!\nRibasim.add_constraints_basin_flow!\nRibasim.add_constraints_capacity!\nRibasim.add_constraints_flow_conservation!\nRibasim.add_constraints_fractional_flow!\nRibasim.add_constraints_source!\nRibasim.add_constraints_user_returnflow!\nRibasim.add_flow!\nRibasim.add_flow!\nRibasim.add_objective_term!\nRibasim.add_subnetwork_connections!\nRibasim.add_user_term!\nRibasim.add_variables_absolute_value!\nRibasim.add_variables_basin!\nRibasim.add_variables_flow!\nRibasim.adjust_basin_capacities!\nRibasim.adjust_edge_capacities!\nRibasim.adjust_source_capacities!\nRibasim.all_neighbor_labels_type\nRibasim.allocate!\nRibasim.allocation_graph\nRibasim.allocation_graph_used_nodes!\nRibasim.allocation_path_exists_in_graph\nRibasim.allocation_problem\nRibasim.allocation_table\nRibasim.assign_allocations!\nRibasim.avoid_using_own_returnflow!\nRibasim.basin_bottom\nRibasim.basin_bottoms\nRibasim.basin_table\nRibasim.config.algorithm\nRibasim.config.convert_saveat\nRibasim.config.input_path\nRibasim.config.results_path\nRibasim.config.snake_case\nRibasim.create_callbacks\nRibasim.create_graph\nRibasim.create_storage_tables\nRibasim.datetime_since\nRibasim.datetimes\nRibasim.discrete_control_affect!\nRibasim.discrete_control_affect_downcrossing!\nRibasim.discrete_control_affect_upcrossing!\nRibasim.discrete_control_condition\nRibasim.discrete_control_table\nRibasim.expand_logic_mapping\nRibasim.find_allocation_graph_edges!\nRibasim.find_subnetwork_connections!\nRibasim.findlastgroup\nRibasim.findsorted\nRibasim.flow_table\nRibasim.formulate_basins!\nRibasim.formulate_flow!\nRibasim.formulate_flow!\nRibasim.formulate_flow!\nRibasim.get_area_and_level\nRibasim.get_basin_capacity\nRibasim.get_basin_data\nRibasim.get_basin_demand\nRibasim.get_chunk_sizes\nRibasim.get_compressor\nRibasim.get_flow\nRibasim.get_flow\nRibasim.get_fractional_flow_connected_basins\nRibasim.get_jac_prototype\nRibasim.get_level\nRibasim.get_scalar_interpolation\nRibasim.get_storage_from_level\nRibasim.get_storages_and_levels\nRibasim.get_storages_from_levels\nRibasim.get_tstops\nRibasim.get_value\nRibasim.id_index\nRibasim.indicate_allocation_flow!\nRibasim.inflow_id\nRibasim.inflow_ids\nRibasim.inflow_ids_allocation\nRibasim.inneighbor_labels_type\nRibasim.inoutflow_ids\nRibasim.is_allocation_source\nRibasim.is_current_module\nRibasim.is_flow_constraining\nRibasim.is_flow_direction_constraining\nRibasim.load_data\nRibasim.load_structvector\nRibasim.low_storage_factor\nRibasim.main\nRibasim.metadata_from_edge\nRibasim.nodefields\nRibasim.nodetype\nRibasim.outflow_id\nRibasim.outflow_ids\nRibasim.outflow_ids_allocation\nRibasim.outneighbor_labels_type\nRibasim.parse_static_and_time\nRibasim.pkgversion\nRibasim.process_allocation_graph_edges!\nRibasim.profile_storage\nRibasim.qh_interpolation\nRibasim.reduction_factor\nRibasim.run\nRibasim.save_allocation_flows!\nRibasim.save_demands_and_allocations!\nRibasim.save_flow\nRibasim.save_subgrid_level\nRibasim.scalar_interpolation_derivative\nRibasim.seconds_since\nRibasim.set_current_value!\nRibasim.set_flow!\nRibasim.set_flow!\nRibasim.set_fractional_flow_in_allocation!\nRibasim.set_initial_discrete_controlled_parameters!\nRibasim.set_is_pid_controlled!\nRibasim.set_objective_priority!\nRibasim.set_static_value!\nRibasim.set_table_row!\nRibasim.sorted_table!\nRibasim.timesteps\nRibasim.update_allocation!\nRibasim.update_basin\nRibasim.update_jac_prototype!\nRibasim.update_jac_prototype!\nRibasim.update_jac_prototype!\nRibasim.update_jac_prototype!\nRibasim.update_tabulated_rating_curve!\nRibasim.valid_discrete_control\nRibasim.valid_edge_types\nRibasim.valid_edges\nRibasim.valid_flow_rates\nRibasim.valid_fractional_flow\nRibasim.valid_n_neighbors\nRibasim.valid_profiles\nRibasim.valid_sources\nRibasim.valid_subgrid\nRibasim.water_balance!\nRibasim.write_arrow\nRibasim.write_results\nRibasim.config.@addfields\nRibasim.config.@addnodetypes",
+ "text": "1.6 Index\n\nRibasim.Ribasim\nRibasim.config\nRibasim.config.algorithms\nRibasim.Allocation\nRibasim.AllocationModel\nRibasim.AllocationModel\nRibasim.Basin\nRibasim.DiscreteControl\nRibasim.EdgeMetadata\nRibasim.FlatVector\nRibasim.FlowBoundary\nRibasim.FractionalFlow\nRibasim.InNeighbors\nRibasim.LevelBoundary\nRibasim.LinearResistance\nRibasim.ManningResistance\nRibasim.Model\nRibasim.NodeMetadata\nRibasim.OutNeighbors\nRibasim.Outlet\nRibasim.PidControl\nRibasim.Pump\nRibasim.Subgrid\nRibasim.TabulatedRatingCurve\nRibasim.TargetLevel\nRibasim.Terminal\nRibasim.User\nRibasim.config.Config\nBasicModelInterface.finalize\nBasicModelInterface.initialize\nCommonSolve.solve!\nRibasim.add_basin_term!\nRibasim.add_constraints_absolute_value!\nRibasim.add_constraints_absolute_value_basin!\nRibasim.add_constraints_absolute_value_user!\nRibasim.add_constraints_basin_flow!\nRibasim.add_constraints_capacity!\nRibasim.add_constraints_flow_conservation!\nRibasim.add_constraints_fractional_flow!\nRibasim.add_constraints_source!\nRibasim.add_constraints_user_returnflow!\nRibasim.add_flow!\nRibasim.add_flow!\nRibasim.add_objective_term!\nRibasim.add_subnetwork_connections!\nRibasim.add_user_term!\nRibasim.add_variables_absolute_value!\nRibasim.add_variables_basin!\nRibasim.add_variables_flow!\nRibasim.adjust_basin_capacities!\nRibasim.adjust_edge_capacities!\nRibasim.adjust_source_capacities!\nRibasim.all_neighbor_labels_type\nRibasim.allocate!\nRibasim.allocation_graph\nRibasim.allocation_graph_used_nodes!\nRibasim.allocation_path_exists_in_graph\nRibasim.allocation_problem\nRibasim.allocation_table\nRibasim.assign_allocations!\nRibasim.avoid_using_own_returnflow!\nRibasim.basin_bottom\nRibasim.basin_bottoms\nRibasim.basin_table\nRibasim.config.algorithm\nRibasim.config.convert_dt\nRibasim.config.convert_saveat\nRibasim.config.input_path\nRibasim.config.results_path\nRibasim.config.snake_case\nRibasim.create_callbacks\nRibasim.create_graph\nRibasim.create_storage_tables\nRibasim.datetime_since\nRibasim.datetimes\nRibasim.discrete_control_affect!\nRibasim.discrete_control_affect_downcrossing!\nRibasim.discrete_control_affect_upcrossing!\nRibasim.discrete_control_condition\nRibasim.discrete_control_table\nRibasim.expand_logic_mapping\nRibasim.find_allocation_graph_edges!\nRibasim.find_subnetwork_connections!\nRibasim.findlastgroup\nRibasim.findsorted\nRibasim.flow_table\nRibasim.formulate_basins!\nRibasim.formulate_flow!\nRibasim.formulate_flow!\nRibasim.formulate_flow!\nRibasim.get_area_and_level\nRibasim.get_basin_capacity\nRibasim.get_basin_data\nRibasim.get_basin_demand\nRibasim.get_chunk_sizes\nRibasim.get_compressor\nRibasim.get_flow\nRibasim.get_flow\nRibasim.get_fractional_flow_connected_basins\nRibasim.get_jac_prototype\nRibasim.get_level\nRibasim.get_scalar_interpolation\nRibasim.get_storage_from_level\nRibasim.get_storages_and_levels\nRibasim.get_storages_from_levels\nRibasim.get_tstops\nRibasim.get_value\nRibasim.id_index\nRibasim.indicate_allocation_flow!\nRibasim.inflow_id\nRibasim.inflow_ids\nRibasim.inflow_ids_allocation\nRibasim.inneighbor_labels_type\nRibasim.inoutflow_ids\nRibasim.is_allocation_source\nRibasim.is_current_module\nRibasim.is_flow_constraining\nRibasim.is_flow_direction_constraining\nRibasim.load_data\nRibasim.load_structvector\nRibasim.low_storage_factor\nRibasim.main\nRibasim.metadata_from_edge\nRibasim.nodefields\nRibasim.nodetype\nRibasim.outflow_id\nRibasim.outflow_ids\nRibasim.outflow_ids_allocation\nRibasim.outneighbor_labels_type\nRibasim.parse_static_and_time\nRibasim.pkgversion\nRibasim.process_allocation_graph_edges!\nRibasim.profile_storage\nRibasim.qh_interpolation\nRibasim.reduction_factor\nRibasim.run\nRibasim.save_allocation_flows!\nRibasim.save_demands_and_allocations!\nRibasim.save_flow\nRibasim.save_subgrid_level\nRibasim.scalar_interpolation_derivative\nRibasim.seconds_since\nRibasim.set_current_value!\nRibasim.set_flow!\nRibasim.set_flow!\nRibasim.set_fractional_flow_in_allocation!\nRibasim.set_initial_discrete_controlled_parameters!\nRibasim.set_is_pid_controlled!\nRibasim.set_objective_priority!\nRibasim.set_static_value!\nRibasim.set_table_row!\nRibasim.sorted_table!\nRibasim.timesteps\nRibasim.update_allocation!\nRibasim.update_basin\nRibasim.update_jac_prototype!\nRibasim.update_jac_prototype!\nRibasim.update_jac_prototype!\nRibasim.update_jac_prototype!\nRibasim.update_tabulated_rating_curve!\nRibasim.valid_discrete_control\nRibasim.valid_edge_types\nRibasim.valid_edges\nRibasim.valid_flow_rates\nRibasim.valid_fractional_flow\nRibasim.valid_n_neighbors\nRibasim.valid_profiles\nRibasim.valid_sources\nRibasim.valid_subgrid\nRibasim.water_balance!\nRibasim.write_arrow\nRibasim.write_results\nRibasim.config.@addfields\nRibasim.config.@addnodetypes",
"crumbs": [
"Julia core",
"API Reference"
@@ -850,7 +850,7 @@
"href": "core/allocation.html#example",
"title": "Allocation",
"section": "5.1 Example",
- "text": "5.1 Example\nThe following is an example of an optimization problem for the example shown here:\n\n\nCode\nusing Ribasim\nusing Ribasim: NodeID\nusing SQLite\nusing ComponentArrays: ComponentVector\n\ntoml_path = normpath(@__DIR__, \"../../generated_testmodels/allocation_example/ribasim.toml\")\np = Ribasim.Model(toml_path).integrator.p\nu = ComponentVector(; storage = zeros(length(p.basin.node_id)))\n\nallocation_model = p.allocation.allocation_models[1]\nt = 0.0\npriority_idx = 1\n\nRibasim.set_flow!(p.graph, NodeID(:FlowBoundary, 1), NodeID(:Basin, 2), 1.0)\n\nRibasim.adjust_source_capacities!(allocation_model, p, priority_idx)\nRibasim.adjust_edge_capacities!(allocation_model, p, priority_idx)\nRibasim.set_objective_priority!(allocation_model, p, u, t, priority_idx)\n\nprintln(p.allocation.allocation_models[1].problem)\n\n\nMin F_abs_user[User #3] + F_abs_user[User #13] + F_abs_user[User #6] + F_abs_basin[Basin #12] + F_abs_basin[Basin #5] + F_abs_basin[Basin #2]\nSubject to\n flow_conservation[Basin #12] : F[(Basin #12, User #13)] - F[(TabulatedRatingCurve #7, Basin #12)] + F_basin_in[Basin #12] - F_basin_out[Basin #12] = 0\n flow_conservation[Basin #5] : F[(Basin #5, User #6)] + F[(Basin #5, TabulatedRatingCurve #7)] - F[(Basin #2, Basin #5)] + F[(Basin #5, Basin #2)] + F_basin_in[Basin #5] - F_basin_out[Basin #5] = 0\n flow_conservation[Basin #2] : F[(Basin #2, Basin #5)] + F[(Basin #2, User #3)] - F[(Basin #5, Basin #2)] - F[(FlowBoundary #1, Basin #2)] + F_basin_in[Basin #2] - F_basin_out[Basin #2] = 0\n abs_positive_user[User #3] : -F[(Basin #2, User #3)] + F_abs_user[User #3] ≥ 0\n abs_positive_user[User #13] : -F[(Basin #12, User #13)] + F_abs_user[User #13] ≥ 0\n abs_positive_user[User #6] : -F[(Basin #5, User #6)] + F_abs_user[User #6] ≥ -1.5\n abs_negative_user[User #3] : F[(Basin #2, User #3)] + F_abs_user[User #3] ≥ 0\n abs_negative_user[User #13] : F[(Basin #12, User #13)] + F_abs_user[User #13] ≥ 0\n abs_negative_user[User #6] : F[(Basin #5, User #6)] + F_abs_user[User #6] ≥ 1.5\n abs_positive_basin[Basin #12] : -F_basin_in[Basin #12] + F_abs_basin[Basin #12] ≥ 0\n abs_positive_basin[Basin #5] : -F_basin_in[Basin #5] + F_abs_basin[Basin #5] ≥ 0\n abs_positive_basin[Basin #2] : -F_basin_in[Basin #2] + F_abs_basin[Basin #2] ≥ 0\n abs_negative_basin[Basin #12] : F_basin_in[Basin #12] + F_abs_basin[Basin #12] ≥ 0\n abs_negative_basin[Basin #5] : F_basin_in[Basin #5] + F_abs_basin[Basin #5] ≥ 0\n abs_negative_basin[Basin #2] : F_basin_in[Basin #2] + F_abs_basin[Basin #2] ≥ 0\n source[(FlowBoundary #1, Basin #2)] : F[(FlowBoundary #1, Basin #2)] ≤ 1\n return_flow[User #13] : F[(User #13, Terminal #10)] ≤ 0\n fractional_flow[(TabulatedRatingCurve #7, Basin #12)] : -0.4 F[(Basin #5, TabulatedRatingCurve #7)] + F[(TabulatedRatingCurve #7, Basin #12)] ≤ 0\n basin_outflow[Basin #12] : F_basin_out[Basin #12] ≤ 0\n basin_outflow[Basin #5] : F_basin_out[Basin #5] ≤ 0\n basin_outflow[Basin #2] : F_basin_out[Basin #2] ≤ 0\n F[(Basin #5, User #6)] ≥ 0\n F[(TabulatedRatingCurve #7, Terminal #10)] ≥ 0\n F[(Basin #5, TabulatedRatingCurve #7)] ≥ 0\n F[(Basin #2, Basin #5)] ≥ 0\n F[(Basin #2, User #3)] ≥ 0\n F[(Basin #12, User #13)] ≥ 0\n F[(User #13, Terminal #10)] ≥ 0\n F[(Basin #5, Basin #2)] ≥ 0\n F[(FlowBoundary #1, Basin #2)] ≥ 0\n F[(TabulatedRatingCurve #7, Basin #12)] ≥ 0\n F_basin_in[Basin #12] ≥ 0\n F_basin_in[Basin #5] ≥ 0\n F_basin_in[Basin #2] ≥ 0\n F_basin_out[Basin #12] ≥ 0\n F_basin_out[Basin #5] ≥ 0\n F_basin_out[Basin #2] ≥ 0",
+ "text": "5.1 Example\nThe following is an example of an optimization problem for the example shown here:\n\n\nCode\nusing Ribasim\nusing Ribasim: NodeID\nusing SQLite\nusing ComponentArrays: ComponentVector\n\ntoml_path = normpath(@__DIR__, \"../../generated_testmodels/allocation_example/ribasim.toml\")\np = Ribasim.Model(toml_path).integrator.p\nu = ComponentVector(; storage = zeros(length(p.basin.node_id)))\n\nallocation_model = p.allocation.allocation_models[1]\nt = 0.0\npriority_idx = 1\n\nRibasim.set_flow!(p.graph, NodeID(:FlowBoundary, 1), NodeID(:Basin, 2), 1.0)\n\nRibasim.adjust_source_capacities!(allocation_model, p, priority_idx)\nRibasim.adjust_edge_capacities!(allocation_model, p, priority_idx)\nRibasim.set_objective_priority!(allocation_model, p, u, t, priority_idx)\n\nprintln(p.allocation.allocation_models[1].problem)\n\n\nMin F_abs_user[User #13] + F_abs_user[User #6] + F_abs_user[User #3] + F_abs_basin[Basin #12] + F_abs_basin[Basin #2] + F_abs_basin[Basin #5]\nSubject to\n flow_conservation[Basin #12] : -F[(TabulatedRatingCurve #7, Basin #12)] + F[(Basin #12, User #13)] + F_basin_in[Basin #12] - F_basin_out[Basin #12] = 0\n flow_conservation[Basin #2] : -F[(FlowBoundary #1, Basin #2)] + F[(Basin #2, User #3)] + F[(Basin #2, Basin #5)] - F[(Basin #5, Basin #2)] + F_basin_in[Basin #2] - F_basin_out[Basin #2] = 0\n flow_conservation[Basin #5] : F[(Basin #5, User #6)] + F[(Basin #5, TabulatedRatingCurve #7)] - F[(Basin #2, Basin #5)] + F[(Basin #5, Basin #2)] + F_basin_in[Basin #5] - F_basin_out[Basin #5] = 0\n abs_positive_user[User #13] : -F[(Basin #12, User #13)] + F_abs_user[User #13] ≥ 0\n abs_positive_user[User #6] : -F[(Basin #5, User #6)] + F_abs_user[User #6] ≥ -1.5\n abs_positive_user[User #3] : -F[(Basin #2, User #3)] + F_abs_user[User #3] ≥ 0\n abs_negative_user[User #13] : F[(Basin #12, User #13)] + F_abs_user[User #13] ≥ 0\n abs_negative_user[User #6] : F[(Basin #5, User #6)] + F_abs_user[User #6] ≥ 1.5\n abs_negative_user[User #3] : F[(Basin #2, User #3)] + F_abs_user[User #3] ≥ 0\n abs_positive_basin[Basin #12] : -F_basin_in[Basin #12] + F_abs_basin[Basin #12] ≥ 0\n abs_positive_basin[Basin #2] : -F_basin_in[Basin #2] + F_abs_basin[Basin #2] ≥ 0\n abs_positive_basin[Basin #5] : -F_basin_in[Basin #5] + F_abs_basin[Basin #5] ≥ 0\n abs_negative_basin[Basin #12] : F_basin_in[Basin #12] + F_abs_basin[Basin #12] ≥ 0\n abs_negative_basin[Basin #2] : F_basin_in[Basin #2] + F_abs_basin[Basin #2] ≥ 0\n abs_negative_basin[Basin #5] : F_basin_in[Basin #5] + F_abs_basin[Basin #5] ≥ 0\n source[(FlowBoundary #1, Basin #2)] : F[(FlowBoundary #1, Basin #2)] ≤ 1\n return_flow[User #13] : F[(User #13, Terminal #10)] ≤ 0\n fractional_flow[(TabulatedRatingCurve #7, Basin #12)] : -0.4 F[(Basin #5, TabulatedRatingCurve #7)] + F[(TabulatedRatingCurve #7, Basin #12)] ≤ 0\n basin_outflow[Basin #12] : F_basin_out[Basin #12] ≤ 0\n basin_outflow[Basin #2] : F_basin_out[Basin #2] ≤ 0\n basin_outflow[Basin #5] : F_basin_out[Basin #5] ≤ 0\n F[(FlowBoundary #1, Basin #2)] ≥ 0\n F[(Basin #5, User #6)] ≥ 0\n F[(Basin #5, TabulatedRatingCurve #7)] ≥ 0\n F[(TabulatedRatingCurve #7, Terminal #10)] ≥ 0\n F[(TabulatedRatingCurve #7, Basin #12)] ≥ 0\n F[(Basin #2, User #3)] ≥ 0\n F[(User #13, Terminal #10)] ≥ 0\n F[(Basin #12, User #13)] ≥ 0\n F[(Basin #2, Basin #5)] ≥ 0\n F[(Basin #5, Basin #2)] ≥ 0\n F_basin_in[Basin #12] ≥ 0\n F_basin_in[Basin #2] ≥ 0\n F_basin_in[Basin #5] ≥ 0\n F_basin_out[Basin #12] ≥ 0\n F_basin_out[Basin #2] ≥ 0\n F_basin_out[Basin #5] ≥ 0",
"crumbs": [
"Julia core",
"Allocation"
@@ -938,7 +938,7 @@
"href": "core/usage.html#sec-solver-settings",
"title": "Usage",
"section": "1.1 Solver settings",
- "text": "1.1 Solver settings\nThe solver section in the configuration file is entirely optional, since we aim to use defaults that will generally work well. Common reasons to modify the solver settings are to adjust the calculation or result stepsizes: adaptive, dt, and saveat. If your model does not converge, or your performance is lower than expected, it can help to adjust other solver settings as well.\nThe default solver algorithm = \"QNDF\", which is a multistep method similar to Matlab’s ode15s (Shampine and Reichelt 1997). It is an implicit method that supports the default adaptive = true timestepping. The full list of available solvers is: QNDF, Rosenbrock23, TRBDF2, Rodas5, KenCarp4, Tsit5, RK4, ImplicitEuler, Euler. Information on the solver algorithms can be found on the ODE solvers page.\nThe dt controls the stepsize. When adaptive = true, dt only applies to the initial stepsize, and by default it is automatically determined. When adaptive = false a suitable dt must always be provided. The value is in seconds, so dt = 3600.0 corresponds to an hourly timestep. When adaptive = true, dtmin and dtmax control the minimum and maximum allowed dt. If a smaller dt than dtmin is needed to meet the set error tolerances, the simulation stops, unless force_dtmin is set to true. force_dtmin is off by default to ensure an accurate solution.\nThe default result stepsize, saveat = 86400 will save results after every day that passed. The calculation and result stepsize need not be the same. If you wish to save every calculation step, set saveat = 0. If you wish to not save any intermediate steps, set saveat = inf.\nThe Jacobian matrix provides information about the local sensitivity of the model with respect to changes in the states. For implicit solvers it must be calculated often, which can be expensive to do. There are several methods to do this. By default Ribasim uses a Jacobian derived automatically using ForwardDiff.jl with memory management provided by PreallocationTools.jl. If this is not used by setting autodiff = false, the Jacobian is calculated with a finite difference method, which can be less accurate and more expensive.\nBy default the Jacobian matrix is a sparse matrix (sparse = true). Since each state typically only depends on a small number of other states, this is generally more efficient, especially for larger models. The sparsity structure is calculated from the network and provided as a Jacobian prototype to the solver. For small or highly connected models it could be faster to use a dense Jacobian matrix instead by setting sparse = false.\nThe total maximum number of iterations maxiters = 1e9, can normally stay as-is unless doing extremely long simulations.\nThe absolute and relative tolerance for adaptive timestepping can be set with abstol and reltol. For more information on these and other solver options, see the DifferentialEquations.jl docs.",
+ "text": "1.1 Solver settings\nThe solver section in the configuration file is entirely optional, since we aim to use defaults that will generally work well. Common reasons to modify the solver settings are to adjust the calculation or result stepsizes: dt, and saveat. If your model does not converge, or your performance is lower than expected, it can help to adjust other solver settings as well.\nThe default solver algorithm = \"QNDF\", which is a multistep method similar to Matlab’s ode15s (Shampine and Reichelt 1997). It is an implicit method that supports the default adaptive timestepping. The full list of available solvers is: QNDF, Rosenbrock23, TRBDF2, Rodas5, KenCarp4, Tsit5, RK4, ImplicitEuler, Euler. Information on the solver algorithms can be found on the ODE solvers page.\nBy default Ribasim uses adaptive timestepping, though not all algorithms support adaptive timestepping. To use fixed timesteps, provide a timestep size in seconds; dt = 3600.0 corresponds to an hourly timestep. With adaptive timestepping, dtmin and dtmax control the minimum and maximum allowed dt. If a smaller dt than dtmin is needed to meet the set error tolerances, the simulation stops, unless force_dtmin is set to true. force_dtmin is off by default to ensure an accurate solution.\nThe default result stepsize, saveat = 86400 will save results after every day that passed. The calculation and result stepsize need not be the same. If you wish to save every calculation step, set saveat = 0. If you wish to not save any intermediate steps, set saveat = inf.\nThe Jacobian matrix provides information about the local sensitivity of the model with respect to changes in the states. For implicit solvers it must be calculated often, which can be expensive to do. There are several methods to do this. By default Ribasim uses a Jacobian derived automatically using ForwardDiff.jl with memory management provided by PreallocationTools.jl. If this is not used by setting autodiff = false, the Jacobian is calculated with a finite difference method, which can be less accurate and more expensive.\nBy default the Jacobian matrix is a sparse matrix (sparse = true). Since each state typically only depends on a small number of other states, this is generally more efficient, especially for larger models. The sparsity structure is calculated from the network and provided as a Jacobian prototype to the solver. For small or highly connected models it could be faster to use a dense Jacobian matrix instead by setting sparse = false.\nThe total maximum number of iterations maxiters = 1e9, can normally stay as-is unless doing extremely long simulations.\nThe absolute and relative tolerance for adaptive timestepping can be set with abstol and reltol. For more information on these and other solver options, see the DifferentialEquations.jl docs.",
"crumbs": [
"Julia core",
"Usage"