DiscreteControl

Set parameters of other nodes based on model state conditions (e.g. Basin level). The table below shows which parameters are controllable for a given node type.

Code
using Ribasim
using DataFrames: DataFrame
using MarkdownTables

node_names = Symbol[]
controllable_parameters = String[]

for node_type in fieldtypes(Ribasim.Parameters)
    if node_type <: Ribasim.AbstractParameterNode
        node_name = nameof(node_type)
        controllable_fields = Ribasim.controllablefields(node_name)
        controllable_fields = sort!(string.(controllable_fields))
        if node_name == :TabulatedRatingCurve
            controllable_fields = map(
                s -> replace(s, "table" => "q(h) relationship (given by level, flow_rate)"),
                controllable_fields,
            )
        end
        if !isempty(controllable_fields)
            push!(node_names, Ribasim.snake_case(node_name))
            push!(controllable_parameters, join(controllable_fields, ", "))
        end
    end
end

df = DataFrame(:node => node_names, :controllable_parameters => controllable_parameters)

markdown_table(df)
node controllable_parameters
linear_resistance active, resistance
manning_resistance active, manning_n
tabulated_rating_curve active, q(h) relationship (given by level, flow_rate)
pump active, flow_rate
outlet active, flow_rate
pid_control active, derivative, integral, proportional, target

1 Tables

1.1 Variable

The compound variable schema defines linear combinations of variables which can be used in conditions. This means that this schema defines new variables with the given compound_variable_id that look like \[ \text{weight}_1 * \text{variable}_1 + \text{weight}_2 * \text{variable}_2 + \ldots, \]

which can be for instance an average or a difference of variables. If a variable comes from a time-series, a look ahead \(\Delta t\) can be supplied.

column type unit restriction
node_id Int32 -
compound_variable_id Int32 -
listen_node_id Int32 -
variable String - must be “level” or “flow_rate”
weight Float64 - (optional, default 1.0)
look_ahead Float64 \(\text{s}\) Only on transient boundary conditions, non-negative (optional, default 0.0).

These variables can be listened to: - The level of a Basin - The level of a LevelBoundary (supports look ahead) - The flow rate through one of these node types: Pump, Outlet, TabulatedRatingCurve, LinearResistance, ManningResistance - The flow rate of a FlowBoundary (supports look ahead)

1.2 Condition

The condition schema defines conditions of the form ‘the discrete_control node with this node_id listens to whether the variable given by the node_id and compound_variable_id is greater than greater_than’ (at time \(t\)). In equation form:

\[ \text{weight}_1 * \text{variable}_1 + \text{weight}_2 * \text{variable}_2 + \ldots > \text{greater\_than}(t). \]

Multiple conditions with different greater_than values can be defined on the same compound_variable, each with their own unique condition_id.

Note the strict inequality ‘\(>\)’ in the equation above. This means for instance that if a simulation starts with a compound variable exactly at the greater_than value, the condition is false.

column type unit restriction
node_id Int32 - -
compound_variable_id Int32 - -
condition_id Int32 - -
greater_than Float64 various -
time DateTime - (optional)

When no (or only a single) time is supplied for a given condition_id, the greater_than value of this condition is unchanging over time.

1.3 Logic

The logic schema defines which control states are triggered based on the truth of the conditions a DiscreteControl node listens to. DiscreteControl is applied in the Julia core as follows:

  • During the simulation it is checked whether the truth of any of the conditions changes.
  • When a condition changes, the corresponding DiscreteControl node ID is retrieved (node_id in the condition schema above).
  • The truth value of all the conditions this DiscreteControl node listens to are retrieved, in the order of the condition IDs. This is then converted into a string of “T” for true and “F” for false. This string we call the truth state.
  • The table below determines for the given DiscreteControl node ID and truth state what the corresponding control state is.
  • For all the nodes this DiscreteControl node affects (as given by the “control” links in Links / static), their parameters are set to those parameters in NodeType / static corresponding to the determined control state.
column type unit restriction
node_id Int32 -
control_state String - -
truth_state String - Consists of the characters “T” (true), “F” (false) and “*” (any)