Validation

The tables below show the validation rules applied to the input to the Julia core before running the model.

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
using DataFrames: DataFrame
using MarkdownTables

node_names_snake_case = Symbol[]
node_names_camel_case = Symbol[]
for (node_name, node_type) in
    zip(fieldnames(Ribasim.ParametersIndependent), fieldtypes(Ribasim.ParametersIndependent))
    if node_type <: Ribasim.AbstractParameterNode
        push!(node_names_snake_case, node_name)
        push!(node_names_camel_case, nameof(node_type))
    end
end

function to_symbol(b::Bool)::String
    return b ? "✓" : "x"
end

df = DataFrame()
df[!, :downstream] = node_names_snake_case

for node_name in node_names_snake_case
    df[!, node_name] = [
        (to_symbol(node_name_ in Ribasim.neighbortypes(node_name))) for
        node_name_ in node_names_snake_case
    ]
end

markdown_table(df)
downstream basin linear_resistance manning_resistance tabulated_rating_curve level_boundary flow_boundary pump outlet terminal junction discrete_control continuous_control pid_control user_demand level_demand flow_demand
basin x x x x x x x
linear_resistance x x x x x x x x x x x
manning_resistance x x x x x x x x x x x x
tabulated_rating_curve x x x x x x x x x x x
level_boundary x x x x x x x x x x
flow_boundary x x x x x x x x x x x x x x x x
pump x x x x x x x x x
outlet x x x x x x x x x
terminal x x x x x x x x x x
junction x x x x x x x
discrete_control x x x x x x x x x x x x x x x x
continuous_control x x x x x x x x x x x x x x x x
pid_control x x x x x x x x x x x x x x x
user_demand x x x x x x x x x x x x x x
level_demand x x x x x x x x x x x x x x x x
flow_demand x x x x x x x x x x x x x x x x

2 Neighbor amounts

The tables below show for each node type between which bounds the amount of in- and outneighbors must be, per link type.

Code
function unbounded(i::Int)::String
    return i == typemax(Int) ? "∞" : string(i)
end

function neighbor_bounds_table(node_names_snake_case, node_names_camel_case, bounds_fn)
    in_min = String[]
    in_max = String[]
    out_min = String[]
    out_max = String[]
    for node_name in node_names_camel_case
        bounds = bounds_fn(node_name)
        push!(in_min, string(bounds.in_min))
        push!(in_max, unbounded(bounds.in_max))
        push!(out_min, string(bounds.out_min))
        push!(out_max, unbounded(bounds.out_max))
    end
    return DataFrame(; node_type = node_names_snake_case, in_min, in_max, out_min, out_max)
end