From bfe2d81ceccff94aa3488ed69031474b6d41b033 Mon Sep 17 00:00:00 2001 From: Hofer-Julian Date: Fri, 9 Feb 2024 12:04:20 +0000 Subject: [PATCH] deploy: 936ec871212af107ad4b8aaeb6ef49dfc8a462ec --- build/index.html | 326 +++++++++--------- core/allocation.html | 22 +- python/examples.html | 18 +- schema/Allocation.schema.json | 35 -- schema/BasinProfile.schema.json | 32 -- schema/BasinState.schema.json | 27 -- schema/BasinStatic.schema.json | 77 ----- schema/BasinSubgrid.schema.json | 37 -- schema/BasinTime.schema.json | 82 ----- schema/DiscreteControlCondition.schema.json | 48 --- schema/DiscreteControlLogic.schema.json | 32 -- schema/Edge.schema.json | 53 --- schema/FlowBoundaryStatic.schema.json | 38 -- schema/FlowBoundaryTime.schema.json | 32 -- schema/FractionalFlowStatic.schema.json | 38 -- schema/LevelBoundaryStatic.schema.json | 38 -- schema/LevelBoundaryTime.schema.json | 32 -- schema/LinearResistanceStatic.schema.json | 49 --- schema/Logging.schema.json | 23 -- schema/ManningResistanceStatic.schema.json | 64 ---- schema/Node.schema.json | 43 --- schema/OutletStatic.schema.json | 82 ----- schema/PIDControlStatic.schema.json | 69 ---- schema/PidControlTime.schema.json | 63 ---- schema/PumpStatic.schema.json | 71 ---- schema/Results.schema.json | 41 --- schema/Solver.schema.json | 106 ------ schema/TabulatedRatingCurveStatic.schema.json | 54 --- schema/TabulatedRatingCurveTime.schema.json | 37 -- schema/TerminalStatic.schema.json | 22 -- schema/Toml.schema.json | 186 ---------- schema/UserStatic.schema.json | 53 --- schema/UserTime.schema.json | 47 --- schema/basin.schema.json | 71 ---- schema/discrete_control.schema.json | 35 -- schema/flow_boundary.schema.json | 35 -- schema/fractional_flow.schema.json | 23 -- schema/level_boundary.schema.json | 35 -- schema/linear_resistance.schema.json | 23 -- schema/manning_resistance.schema.json | 23 -- schema/outlet.schema.json | 23 -- schema/pid_control.schema.json | 35 -- schema/pump.schema.json | 23 -- schema/root.schema.json | 84 ----- schema/tabulated_rating_curve.schema.json | 35 -- schema/terminal.schema.json | 23 -- schema/user.schema.json | 35 -- search.json | 4 +- 48 files changed, 185 insertions(+), 2299 deletions(-) delete mode 100644 schema/Allocation.schema.json delete mode 100644 schema/BasinProfile.schema.json delete mode 100644 schema/BasinState.schema.json delete mode 100644 schema/BasinStatic.schema.json delete mode 100644 schema/BasinSubgrid.schema.json delete mode 100644 schema/BasinTime.schema.json delete mode 100644 schema/DiscreteControlCondition.schema.json delete mode 100644 schema/DiscreteControlLogic.schema.json delete mode 100644 schema/Edge.schema.json delete mode 100644 schema/FlowBoundaryStatic.schema.json delete mode 100644 schema/FlowBoundaryTime.schema.json delete mode 100644 schema/FractionalFlowStatic.schema.json delete mode 100644 schema/LevelBoundaryStatic.schema.json delete mode 100644 schema/LevelBoundaryTime.schema.json delete mode 100644 schema/LinearResistanceStatic.schema.json delete mode 100644 schema/Logging.schema.json delete mode 100644 schema/ManningResistanceStatic.schema.json delete mode 100644 schema/Node.schema.json delete mode 100644 schema/OutletStatic.schema.json delete mode 100644 schema/PIDControlStatic.schema.json delete mode 100644 schema/PidControlTime.schema.json delete mode 100644 schema/PumpStatic.schema.json delete mode 100644 schema/Results.schema.json delete mode 100644 schema/Solver.schema.json delete mode 100644 schema/TabulatedRatingCurveStatic.schema.json delete mode 100644 schema/TabulatedRatingCurveTime.schema.json delete mode 100644 schema/TerminalStatic.schema.json delete mode 100644 schema/Toml.schema.json delete mode 100644 schema/UserStatic.schema.json delete mode 100644 schema/UserTime.schema.json delete mode 100644 schema/basin.schema.json delete mode 100644 schema/discrete_control.schema.json delete mode 100644 schema/flow_boundary.schema.json delete mode 100644 schema/fractional_flow.schema.json delete mode 100644 schema/level_boundary.schema.json delete mode 100644 schema/linear_resistance.schema.json delete mode 100644 schema/manning_resistance.schema.json delete mode 100644 schema/outlet.schema.json delete mode 100644 schema/pid_control.schema.json delete mode 100644 schema/pump.schema.json delete mode 100644 schema/root.schema.json delete mode 100644 schema/tabulated_rating_curve.schema.json delete mode 100644 schema/terminal.schema.json delete mode 100644 schema/user.schema.json diff --git a/build/index.html b/build/index.html index 73c7668d0..3c5778f84 100644 --- a/build/index.html +++ b/build/index.html @@ -270,11 +270,11 @@

solve!
  • write_results
  • -

    source

    +

    source

    # Ribasim.configModule.

    module config

    Ribasim.config is a submodule of Ribasim to handle the configuration of a Ribasim model. It is implemented using the Configurations package. A full configuration is represented by Config, which is the main API. Ribasim.config is a submodule mainly to avoid name clashes between the configuration sections and the rest of Ribasim.

    -

    source

    +

    source

    @@ -282,18 +282,18 @@

    1.2 Types

    # Ribasim.AllocationType.

    Object for all information about allocation allocationnetworkids: The unique sorted allocation network IDs allocation models: The allocation models for the main network and subnetworks corresponding to allocationnetworkids mainnetworkconnections: (fromid, toid) from the main network to the subnetwork per subnetwork subnetwork_demands: The demand of an edge from the main network to a subnetwork record: A record of all flows computed by allocation optimization, eventually saved to output file

    -

    source

    +

    source

    # Ribasim.AllocationModelType.

    Store information for a subnetwork used for allocation.

    objectivetype: The name of the type of objective used allocationnetworkid: The ID of this allocation network capacity: The capacity per edge of the allocation graph, as constrained by nodes that have a maxflowrate problem: The JuMP.jl model for solving the allocation problem Δtallocation: The time interval between consecutive allocation solves

    -

    source

    +

    source

    # Ribasim.AllocationModelMethod.

    Construct the JuMP.jl problem for allocation.

    Inputs

    config: The model configuration with allocation configuration in config.allocation p: Ribasim problem parameters Δt_allocation: The timestep between successive allocation solves

    Outputs

    An AllocationModel object.

    -

    source

    +

    source

    # Ribasim.BasinType.

    Requirements:

      @@ -303,22 +303,22 @@

      source

      +

      source

      # Ribasim.DiscreteControlType.

      nodeid: node ID of the DiscreteControl node; these are not unique but repeated by the amount of conditions of this DiscreteControl node listennodeid: the ID of the node being condition on variable: the name of the variable in the condition greaterthan: The threshold value in the condition conditionvalue: The current value of each condition controlstate: Dictionary: node ID => (control state, control state start) logic_mapping: Dictionary: (control node ID, truth state) => control state record: Namedtuple with discrete control information for results

      -

      source

      +

      source

      # Ribasim.EdgeMetadataType.

      Type for storing metadata of edges in the graph: id: ID of the edge (only used for labeling flow output) type: type of the edge allocationnetworkidsource: ID of allocation network where this edge is a source (0 if not a source) fromid: the node ID of the source node toid: the node ID of the destination node allocationflow: whether this edge has a flow in an allocation graph node_ids: if this edge has allocation flow, these are all the nodes from the physical layer this edge consists of

      -

      source

      +

      source

      # Ribasim.FlatVectorType.

      struct FlatVector{T} <: AbstractVector{T}

      A FlatVector is an AbstractVector that iterates the T of a Vector{Vector{T}}.

      Each inner vector is assumed to be of equal length.

      It is similar to Iterators.flatten, though that doesn’t work with the Tables.Column interface, which needs length and getindex support.

      -

      source

      +

      source

      # Ribasim.FlowBoundaryType.

      nodeid: node ID of the FlowBoundary node active: whether this node is active and thus contributes flow flowrate: target flow rate

      -

      source

      +

      source

      # Ribasim.FractionalFlowType.

      Requirements:

        @@ -327,13 +327,13 @@

        source

        +

        source

        # Ribasim.InNeighborsType.

        Iterate over incoming neighbors of a given label in a MetaGraph, only for edges of edge_type

        -

        source

        +

        source

        # Ribasim.LevelBoundaryType.

        node_id: node ID of the LevelBoundary node active: whether this node is active level: the fixed level of this ‘infinitely big basin’

        -

        source

        +

        source

        # Ribasim.LinearResistanceType.

        Requirements:

          @@ -341,7 +341,7 @@

          source

          +

          source

          # Ribasim.ManningResistanceType.

          This is a simple Manning-Gauckler reach connection.

            @@ -371,48 +371,48 @@

            source

            +

            source

            # Ribasim.ModelType.

            Model(config_path::AbstractString)
             Model(config::Config)

            Initialize a Model.

            The Model struct is an initialized model, combined with the Config used to create it and saved results. The Basic Model Interface (BMI) is implemented on the Model. A Model can be created from the path to a TOML configuration file, or a Config object.

            -

            source

            +

            source

            # Ribasim.NodeMetadataType.

            Type for storing metadata of nodes in the graph type: type of the node allocationnetworkid: Allocation network ID (0 if not in subnetwork)

            -

            source

            +

            source

            # Ribasim.OutNeighborsType.

            Iterate over outgoing neighbors of a given label in a MetaGraph, only for edges of edge_type

            -

            source

            +

            source

            # Ribasim.OutletType.

            nodeid: node ID of the Outlet node active: whether this node is active and thus contributes flow flowrate: target flow rate minflowrate: The minimal flow rate of the outlet maxflowrate: The maximum flow rate of the outlet controlmapping: dictionary from (nodeid, controlstate) to target flow rate ispid_controlled: whether the flow rate of this outlet is governed by PID control

            -

            source

            +

            source

            # Ribasim.PidControlType.

            PID control currently only supports regulating basin levels.

            nodeid: node ID of the PidControl node active: whether this node is active and thus sets flow rates listennodeid: the id of the basin being controlled pidparams: a vector interpolation for parameters changing over time. The parameters are respectively target, proportional, integral, derivative, where the last three are the coefficients for the PID equation. error: the current error; basintarget - currentlevel

            -

            source

            +

            source

            # Ribasim.PumpType.

            nodeid: node ID of the Pump node active: whether this node is active and thus contributes flow flowrate: target flow rate minflowrate: The minimal flow rate of the pump maxflowrate: The maximum flow rate of the pump controlmapping: dictionary from (nodeid, controlstate) to target flow rate ispid_controlled: whether the flow rate of this pump is governed by PID control

            -

            source

            +

            source

            # Ribasim.SubgridType.

            Subgrid linearly interpolates basin levels.

            -

            source

            +

            source

            # Ribasim.TabulatedRatingCurveType.

            struct TabulatedRatingCurve{C}

            Rating curve from level to flow rate. The rating curve is a lookup table with linear interpolation in between. Relation can be updated in time, which is done by moving data from the time field into the tables, which is done in the update_tabulated_rating_curve callback.

            Type parameter C indicates the content backing the StructVector, which can be a NamedTuple of Vectors or Arrow Primitives, and is added to avoid type instabilities.

            nodeid: node ID of the TabulatedRatingCurve node active: whether this node is active and thus contributes flows tables: The current Q(h) relationships time: The time table used for updating the tables controlmapping: dictionary from (nodeid, controlstate) to Q(h) and/or active state

            -

            source

            +

            source

            # Ribasim.TerminalType.

            node_id: node ID of the Terminal node

            -

            source

            +

            source

            # Ribasim.UserType.

            demand: water flux demand of user per priority over time active: whether this node is active and thus demands water allocated: water flux currently allocated to user per priority returnfactor: the factor in [0,1] of how much of the abstracted water is given back to the system minlevel: The level of the source basin below which the user does not abstract priorities: All used priority values. Each user has a demand for all these priorities, which is 0.0 if it is not provided explicitly. record: Collected data of allocation optimizations for output file.

            -

            source

            +

            source

            # Ribasim.config.ConfigMethod.

            Config(config_path::AbstractString; kwargs...)

            Parse a TOML file to a Config. Keys can be overruled using keyword arguments. To overrule keys from a subsection, e.g. dt from the solver section, use underscores: solver_dt.

            -

            source

            +

            source

            @@ -421,166 +421,166 @@

            # BasicModelInterface.finalizeMethod.

            BMI.finalize(model::Model)::Model

            Write all results to the configured files.

            -

            source

            +

            source

            # BasicModelInterface.initializeMethod.

            BMI.initialize(T::Type{Model}, config_path::AbstractString)::Model

            Initialize a Model from the path to the TOML configuration file.

            -

            source

            +

            source

            # CommonSolve.solve!Method.

            solve!(model::Model)::ODESolution

            Solve a Model until the configured endtime.

            -

            source

            +

            source

            # Ribasim.add_constraints_absolute_value!Method.

            Minimizing |expr| can be achieved by introducing a new variable exprabs and posing the following constraints: exprabs >= expr expr_abs >= -expr

            -

            source

            +

            source

            # Ribasim.add_constraints_capacity!Method.

            Add the flow capacity constraints to the allocation problem. Only finite capacities get a constraint. The constraint indices are (edgesourceid, edgedstid).

            Constraint: flow over edge <= edge capacity

            -

            source

            +

            source

            # Ribasim.add_constraints_flow_conservation!Method.

            Add the flow conservation constraints to the allocation problem. The constraint indices are user node IDs.

            Constraint: sum(flows out of node node) <= flows into node + flow from storage and vertical fluxes

            -

            source

            +

            source

            # Ribasim.add_constraints_fractional_flow!Method.

            Add the fractional flow constraints to the allocation problem. The constraint indices are allocation edges over a fractional flow node.

            Constraint: flow after fractional_flow node <= fraction * inflow

            -

            source

            +

            source

            # Ribasim.add_constraints_source!Method.

            Add the source constraints to the allocation problem. The actual threshold values will be set before each allocation solve. The constraint indices are (edgesourceid, edgedstid).

            Constraint: flow over source edge <= source flow in subnetwork

            -

            source

            +

            source

            # Ribasim.add_constraints_user_returnflow!Method.

            Add the user returnflow constraints to the allocation problem. The constraint indices are user node IDs.

            Constraint: outflow from user <= return factor * inflow to user

            -

            source

            +

            source

            # Ribasim.add_flow!Method.

            Add the given flow q to the flow over the edge on the horizontal (self-loop) edge from id to id.

            -

            source

            +

            source

            # Ribasim.add_flow!Method.

            Add the given flow q to the existing flow over the edge between the given nodes.

            -

            source

            +

            source

            # Ribasim.add_subnetwork_connections!Method.

            Add the edges connecting the main network work to a subnetwork to both the main network and subnetwork allocation graph.

            -

            source

            +

            source

            # Ribasim.add_user_term!Method.

            Add a term to the expression of the objective function corresponding to the demand of a user.

            -

            source

            +

            source

            # Ribasim.add_variables_absolute_value!Method.

            Certain allocation distribution types use absolute values in the objective function. Since most optimization packages do not support the absolute value function directly, New variables are introduced that act as the absolute value of an expression by posing the appropriate constraints.

            -

            source

            +

            source

            # Ribasim.add_variables_flow!Method.

            Add 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.

            -

            source

            +

            source

            # Ribasim.adjust_edge_capacities!Method.

            Set the values of the edge capacities. 2 cases:

            • Before the first allocation solve, set the edge capacities to their full capacity;
            • Before an allocation solve, subtract the flow used by allocation for the previous priority from the edge capacities.
            -

            source

            +

            source

            # Ribasim.adjust_source_capacities!Method.

            Adjust the source flows.

            -

            source

            +

            source

            # Ribasim.all_neighbor_labels_typeMethod.

            Get the in- and outneighbor node IDs of the given node ID (label) over the given edge type in the graph.

            -

            source

            +

            source

            # Ribasim.allocate!Method.

            Update the allocation optimization problem for the given subnetwork with the problem state and flows, solve the allocation problem and assign the results to the users.

            -

            source

            +

            source

            # Ribasim.allocation_graphMethod.

            Build the graph used for the allocation problem.

            -

            source

            +

            source

            # Ribasim.allocation_graph_used_nodes!Method.

            Find all nodes in the subnetwork which will be used in the allocation network. Some nodes are skipped to optimize allocation optimization.

            -

            source

            +

            source

            # Ribasim.allocation_path_exists_in_graphMethod.

            Find out whether a path exists between a start node and end node in the given allocation graph.

            -

            source

            +

            source

            # Ribasim.allocation_problemMethod.

            Construct the allocation problem for the current subnetwork as a JuMP.jl model.

            -

            source

            +

            source

            # Ribasim.allocation_tableMethod.

            Create an allocation result table for the saved data

            -

            source

            +

            source

            # Ribasim.assign_allocations!Method.

            Assign the allocations to the users as determined by the solution of the allocation problem.

            -

            source

            +

            source

            # Ribasim.avoid_using_own_returnflow!Method.

            Remove allocation user return flow edges that are upstream of the user itself.

            -

            source

            +

            source

            # Ribasim.basin_bottomMethod.

            Return the bottom elevation of the basin with index i, or nothing if it doesn’t exist

            -

            source

            +

            source

            # Ribasim.basin_bottomsMethod.

            Get the bottom on both ends of a node. If only one has a bottom, use that for both.

            -

            source

            +

            source

            # Ribasim.basin_tableMethod.

            Create the basin result table from the saved data

            -

            source

            +

            source

            # Ribasim.create_callbacksMethod.

            Create the different callbacks that are used to store results and feed the simulation with new data. The different callbacks are combined to a CallbackSet that goes to the integrator. Returns the CallbackSet and the SavedValues for flow.

            -

            source

            +

            source

            # Ribasim.create_graphMethod.

            Return a directed metagraph with data of nodes (NodeMetadata): NodeMetadata

            and data of edges (EdgeMetadata): EdgeMetadata

            -

            source

            +

            source

            # Ribasim.create_storage_tablesMethod.

            Read the Basin / profile table and return all area and level and computed storage values

            -

            source

            +

            source

            # Ribasim.datetime_sinceMethod.

            datetime_since(t::Real, t0::DateTime)::DateTime

            Convert a Real that represents the seconds passed since the simulation start to the nearest DateTime. This is used to convert between the solver’s inner float time, and the calendar.

            -

            source

            +

            source

            # Ribasim.datetimesMethod.

            Get all saved times as a Vector{DateTime}

            -

            source

            +

            source

            # Ribasim.discrete_control_affect!Method.

            Change parameters based on the control logic.

            -

            source

            +

            source

            # Ribasim.discrete_control_affect_downcrossing!Method.

            An downcrossing means that a condition (always greater than) becomes false.

            -

            source

            +

            source

            # Ribasim.discrete_control_affect_upcrossing!Method.

            An upcrossing means that a condition (always greater than) becomes true.

            -

            source

            +

            source

            # Ribasim.discrete_control_conditionMethod.

            Listens for changes in condition truths.

            -

            source

            +

            source

            # Ribasim.discrete_control_tableMethod.

            Create a discrete control result table from the saved data

            -

            source

            +

            source

            # Ribasim.expand_logic_mappingMethod.

            Replace the truth states in the logic mapping which contain wildcards with all possible explicit truth states.

            -

            source

            +

            source

            # Ribasim.find_allocation_graph_edges!Method.

            This loop finds allocation graph edges in several ways:

            • Between allocation graph nodes whose equivalent in the subnetwork are directly connected
            • Between allocation graph nodes whose equivalent in the subnetwork are connected with one or more allocation graph nodes in between
            -

            source

            +

            source

            # Ribasim.find_subnetwork_connections!Method.

            Find the edges from the main network to a subnetwork.

            -

            source

            +

            source

            # Ribasim.findlastgroupMethod.

            For an element id and a vector of elements ids, get the range of indices of the last consecutive block of id. Returns the empty range 1:0 if id is not in ids.

            #                         1 2 3 4 5 6 7 8 9
             Ribasim.findlastgroup(2, [5,4,2,2,5,2,2,2,1])
             # output
             6:8
            -

            source

            +

            source

            # Ribasim.findsortedMethod.

            Find the index of element x in a sorted collection a. Returns the index of x if it exists, or nothing if it doesn’t. If x occurs more than once, throw an error.

            -

            source

            +

            source

            # Ribasim.flow_tableMethod.

            Create a flow result table from the saved data

            -

            source

            +

            source

            # Ribasim.formulate_basins!Method.

            Smoothly let the evaporation flux go to 0 when at small water depths Currently at less than 0.1 m.

            -

            source

            +

            source

            # Ribasim.formulate_flow!Method.

            Directed graph: outflow is positive!

            -

            source

            +

            source

            # Ribasim.formulate_flow!Method.

            Conservation of energy for two basins, a and b:

            h_a + v_a^2 / (2 * g) = h_b + v_b^2 / (2 * g) + S_f * L + C / 2 * g * (v_b^2 - v_a^2)
            @@ -608,135 +608,135 @@

            source

            +

            source

            # Ribasim.formulate_flow!Method.

            Directed graph: outflow is positive!

            -

            source

            +

            source

            # Ribasim.get_area_and_levelMethod.

            Compute the area and level of a basin given its storage. Also returns darea/dlevel as it is needed for the Jacobian.

            -

            source

            +

            source

            # Ribasim.get_chunk_sizesMethod.

            Get the chunk sizes for DiffCache; differentiation w.r.t. u and t (the latter only if a Rosenbrock algorithm is used).

            -

            source

            +

            source

            # Ribasim.get_compressorMethod.

            Get the compressor based on the Results section

            -

            source

            +

            source

            # Ribasim.get_flowMethod.

            Get the flow over the given horizontal (selfloop) edge (val is needed for get_tmp from ForwardDiff.jl).

            -

            source

            +

            source

            # Ribasim.get_flowMethod.

            Get the flow over the given edge (val is needed for get_tmp from ForwardDiff.jl).

            -

            source

            +

            source

            # Ribasim.get_fractional_flow_connected_basinsMethod.

            Get the node type specific indices of the fractional flows and basins, that are consecutively connected to a node of given id.

            -

            source

            +

            source

            # Ribasim.get_jac_prototypeMethod.

            Get a sparse matrix whose sparsity matches the sparsity of the Jacobian of the ODE problem. All nodes are taken into consideration, also the ones that are inactive.

            In Ribasim the Jacobian is typically sparse because each state only depends on a small number of other states.

            Note: the name ‘prototype’ does not mean this code is a prototype, it comes from the naming convention of this sparsity structure in the differentialequations.jl docs.

            -

            source

            +

            source

            # Ribasim.get_levelMethod.

            Get the current water level of a node ID. The ID can belong to either a Basin or a LevelBoundary. storage: tells ForwardDiff whether this call is for differentiation or not

            -

            source

            +

            source

            # Ribasim.get_scalar_interpolationMethod.

            Linear interpolation of a scalar with constant extrapolation.

            -

            source

            +

            source

            # Ribasim.get_storage_from_levelMethod.

            Get the storage of a basin from its level.

            -

            source

            +

            source

            # Ribasim.get_storages_and_levelsMethod.

            Get the storage and level of all basins as matrices of nbasin × ntime

            -

            source

            +

            source

            # Ribasim.get_storages_from_levelsMethod.

            Compute the storages of the basins based on the water level of the basins.

            -

            source

            +

            source

            # Ribasim.get_tstopsMethod.

            From an iterable of DateTimes, find the times the solver needs to stop

            -

            source

            +

            source

            # Ribasim.get_valueMethod.

            Get a value for a condition. Currently supports getting levels from basins and flows from flow boundaries.

            -

            source

            +

            source

            # Ribasim.id_indexMethod.

            Get the index of an ID in a set of indices.

            -

            source

            +

            source

            # Ribasim.indicate_allocation_flow!Method.

            Add to the edge metadata that the given edge is used for allocation flow. If the edge does not exist, it is created.

            -

            source

            +

            source

            # Ribasim.inflow_idMethod.

            Get the unique inneighbor over a flow edge.

            -

            source

            +

            source

            # Ribasim.inflow_idsMethod.

            Get the inneighbors over flow edges.

            -

            source

            +

            source

            # Ribasim.inflow_ids_allocationMethod.

            Get the inneighbors of the given ID such that the connecting edge is an allocation flow edge.

            -

            source

            +

            source

            # Ribasim.inneighbor_labels_typeMethod.

            Get the inneighbor node IDs of the given node ID (label) over the given edge type in the graph.

            -

            source

            +

            source

            # Ribasim.inoutflow_idsMethod.

            Get the in- and outneighbors over flow edges.

            -

            source

            +

            source

            # Ribasim.is_allocation_sourceMethod.

            Find out whether the given edge is a source for an allocation network.

            -

            source

            +

            source

            # Ribasim.is_current_moduleMethod.

            is_current_module(log::LogMessageType)::Bool
             Returns true if the log message is from the current module or a submodule.
             
             See https://github.com/JuliaLogging/LoggingExtras.jl/blob/d35e7c8cfc197853ee336ace17182e6ed36dca24/src/CompositionalLoggers/earlyfiltered.jl#L39
             for the information available in log.
            -

            source

            +

            source

            # Ribasim.is_flow_constrainingMethod.

            Whether the given node node is flow constraining by having a maximum flow rate.

            -

            source

            +

            source

            # Ribasim.is_flow_direction_constrainingMethod.

            Whether the given node is flow direction constraining (only in direction of edges).

            -

            source

            +

            source

            # Ribasim.load_dataMethod.

            load_data(db::DB, config::Config, nodetype::Symbol, kind::Symbol)::Union{Table, Query, Nothing}

            Load data from Arrow files if available, otherwise the database. Returns either an Arrow.Table, SQLite.Query or nothing if the data is not present.

            -

            source

            +

            source

            # Ribasim.load_structvectorMethod.

            load_structvector(db::DB, config::Config, ::Type{T})::StructVector{T}

            Load data from Arrow files if available, otherwise the database. Always returns a StructVector of the given struct type T, which is empty if the table is not found. This function validates the schema, and enforces the required sort order.

            -

            source

            +

            source

            # Ribasim.low_storage_factorMethod.

            If id is a Basin with storage below the threshold, return a reduction factor != 1

            -

            source

            +

            source

            # Ribasim.mainMethod.

            main(toml_path::AbstractString)::Cint
             main(ARGS::Vector{String})::Cint
             main()::Cint

            This 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.

            -

            source

            +

            source

            # Ribasim.metadata_from_edgeMethod.

            Get the metadata of an edge in the graph from an edge of the underlying DiGraph.

            -

            source

            +

            source

            # Ribasim.nodefieldsMethod.

            Get all node fieldnames of the parameter object.

            -

            source

            +

            source

            # Ribasim.nodetypeMethod.

            From a SchemaVersion(“ribasim.flowboundary.static”, 1) return (:FlowBoundary, :static)

            -

            source

            +

            source

            # Ribasim.outflow_idMethod.

            Get the unique outneighbor over a flow edge.

            -

            source

            +

            source

            # Ribasim.outflow_idsMethod.

            Get the outneighbors over flow edges.

            -

            source

            +

            source

            # Ribasim.outflow_ids_allocationMethod.

            Get the outneighbors of the given ID such that the connecting edge is an allocation flow edge.

            -

            source

            +

            source

            # Ribasim.outneighbor_labels_typeMethod.

            Get the outneighbor node IDs of the given node ID (label) over the given edge type in the graph.

            -

            source

            +

            source

            # Ribasim.parse_static_and_timeMethod.

            Process the data in the static and time tables for a given node type. The ‘defaults’ named tuple dictates how missing data is filled in. ‘time_interpolatables’ is a vector of Symbols of parameter names for which a time interpolation (linear) object must be constructed. The control mapping for DiscreteControl is also constructed in this function. This function currently does not support node states that are defined by more than one row in a table, as is the case for TabulatedRatingCurve.

            -

            source

            +

            source

            # Ribasim.pkgversionMethod.

            Get the package version of a given module

            -

            source

            +

            source

            # Ribasim.process_allocation_graph_edges!Method.

            For the composite allocation graph edges:

              @@ -744,89 +744,89 @@

              source

              +

              source

              # Ribasim.profile_storageMethod.

              Calculate a profile storage by integrating the areas over the levels

              -

              source

              +

              source

              # Ribasim.qh_interpolationMethod.

              From a table with columns nodeid, flowrate (Q) and level (h), create a LinearInterpolation from level to flow rate for a given node_id.

              -

              source

              +

              source

              # Ribasim.reduction_factorMethod.

              Function that goes smoothly from 0 to 1 in the interval [0,threshold], and is constant outside this interval.

              -

              source

              +

              source

              # Ribasim.runMethod.

              run(config_file::AbstractString)::Model
               run(config::Config)::Model

              Run a Model, given a path to a TOML configuration file, or a Config object. Running a model includes initialization, solving to the end with [solve!](@ref) and writing results with write_results.

              -

              source

              +

              source

              # Ribasim.save_allocation_flows!Method.

              Save the allocation flows per physical edge.

              -

              source

              +

              source

              # Ribasim.save_flowMethod.

              Copy the current flow to the SavedValues

              -

              source

              +

              source

              # Ribasim.save_subgrid_levelMethod.

              Interpolate the levels and save them to SavedValues

              -

              source

              +

              source

              # Ribasim.scalar_interpolation_derivativeMethod.

              Derivative of scalar interpolation.

              -

              source

              +

              source

              # Ribasim.seconds_sinceMethod.

              seconds_since(t::DateTime, t0::DateTime)::Float64

              Convert a DateTime to a float that is the number of seconds since the start of the simulation. This is used to convert between the solver’s inner float time, and the calendar.

              -

              source

              +

              source

              # Ribasim.set_current_value!Method.

              From a timeseries table time, load the most recent applicable data into table. table must be a NamedTuple of vectors with all variables that must be loaded. The most recent applicable data is non-NaN data for a given ID that is on or before t.

              -

              source

              +

              source

              # Ribasim.set_flow!Method.

              Set the given flow q on the horizontal (self-loop) edge from id to id.

              -

              source

              +

              source

              # Ribasim.set_flow!Method.

              Set the given flow q over the edge between the given nodes.

              -

              source

              +

              source

              # Ribasim.set_fractional_flow_in_allocation!Method.

              Update the fractional flow fractions in an allocation problem.

              -

              source

              +

              source

              # Ribasim.set_initial_discrete_controlled_parameters!Method.

              Set parameters of nodes that are controlled by DiscreteControl to the values corresponding to the initial state of the model.

              -

              source

              +

              source

              # Ribasim.set_objective_priority!Method.

              Set the objective for the given priority. For an objective with absolute values this also involves adjusting constraints.

              -

              source

              +

              source

              # Ribasim.set_static_value!Method.

              Load data from a source table static into a destination table. Data is matched based on the node_id, which is sorted.

              -

              source

              +

              source

              # Ribasim.set_table_row!Method.

              Update table at row index i, with the values of a given row. table must be a NamedTuple of vectors with all variables that must be loaded. The row must contain all the column names that are present in the table. If a value is missing, it is not set.

              -

              source

              +

              source

              # Ribasim.sorted_table!Method.

              Depending on if a table can be sorted, either sort it or assert that it is sorted.

              Tables loaded from the database into memory can be sorted. Tables loaded from Arrow files are memory mapped and can therefore not be sorted.

              -

              source

              +

              source

              # Ribasim.timestepsMethod.

              Get all saved times in seconds since start

              -

              source

              +

              source

              # Ribasim.update_allocation!Method.

              Solve the allocation problem for all users and assign allocated abstractions to user nodes.

              -

              source

              +

              source

              # Ribasim.update_basinMethod.

              Load updates from ‘Basin / time’ into the parameters

              -

              source

              +

              source

              # Ribasim.update_jac_prototype!Method.

              Method for nodes that do not contribute to the Jacobian

              -

              source

              +

              source

              # Ribasim.update_jac_prototype!Method.

              The controlled basin affects itself and the basins upstream and downstream of the controlled pump affect eachother if there is a basin upstream of the pump. The state for the integral term and the controlled basin affect eachother, and the same for the integral state and the basin upstream of the pump if it is indeed a basin.

              -

              source

              +

              source

              # Ribasim.update_jac_prototype!Method.

              If both the unique node upstream and the unique node downstream of these nodes are basins, then these directly depend on eachother and affect the Jacobian 2x Basins always depend on themselves.

              -

              source

              +

              source

              # Ribasim.update_jac_prototype!Method.

              If both the unique node upstream and the nodes down stream (or one node further if a fractional flow is in between) are basins, then the downstream basin depends on the upstream basin(s) and affect the Jacobian as many times as there are downstream basins Upstream basins always depend on themselves.

              -

              source

              +

              source

              # Ribasim.update_tabulated_rating_curve!Method.

              Load updates from ‘TabulatedRatingCurve / time’ into the parameters

              -

              source

              +

              source

              # Ribasim.valid_discrete_controlMethod.

              Check:

                @@ -834,54 +834,54 @@

                source

                +

                source

                # Ribasim.valid_edge_typesMethod.

                Check that only supported edge types are declared.

                -

                source

                +

                source

                # Ribasim.valid_edgesMethod.

                Test for each node given its node type whether the nodes that

                are downstream (‘down-edge’) of this node are of an allowed type

                -

                source

                +

                source

                # Ribasim.valid_flow_ratesMethod.

                Test whether static or discrete controlled flow rates are indeed non-negative.

                -

                source

                +

                source

                # Ribasim.valid_fractional_flowMethod.

                Check that nodes that have fractional flow outneighbors do not have any other type of outneighbor, that the fractions leaving a node add up to ≈1 and that the fractions are non-negative.

                -

                source

                +

                source

                # Ribasim.valid_n_neighborsMethod.

                Test for each node given its node type whether it has an allowed number of flow/control inneighbors and outneighbors

                -

                source

                +

                source

                # Ribasim.valid_profilesMethod.

                Check whether the profile data has no repeats in the levels and the areas start positive.

                -

                source

                +

                source

                # Ribasim.valid_sourcesMethod.

                The source nodes must only have one allocation outneighbor and no allocation inneighbors.

                -

                source

                +

                source

                # Ribasim.valid_subgridMethod.

                Validate the entries for a single subgrid element.

                -

                source

                +

                source

                # Ribasim.water_balance!Method.

                The right hand side function of the system of ODEs set up by Ribasim.

                -

                source

                +

                source

                # Ribasim.write_arrowMethod.

                Write a result table to disk as an Arrow file

                -

                source

                +

                source

                # Ribasim.write_resultsMethod.

                write_results(model::Model)::Model

                Write all results to the Arrow files as specified in the model configuration.

                -

                source

                +

                source

                # Ribasim.config.algorithmMethod.

                Create an OrdinaryDiffEqAlgorithm from solver config

                -

                source

                +

                source

                # Ribasim.config.input_pathMethod.

                Construct a path relative to both the TOML directory and the optional input_dir

                -

                source

                +

                source

                # Ribasim.config.results_pathMethod.

                Construct a path relative to both the TOML directory and the optional results_dir

                -

                source

                +

                source

                # Ribasim.config.snake_caseMethod.

                Convert a string from CamelCase to snake_case.

                -

                source

                +

                source

                @@ -902,7 +902,7 @@

                source

                +

                source

                @@ -910,10 +910,10 @@

                1.5 Macros

                # Ribasim.config.@addfieldsMacro.

                Add fieldnames with Union{String, Nothing} type to struct expression. Requires (option?) use before it.

                -

                source

                +

                source

                # Ribasim.config.@addnodetypesMacro.

                Add all TableOption subtypes as fields to struct expression. Requires (option?) use before it.

                -

                source

                +

                source

                @@ -997,14 +997,14 @@

                Ribasim.findsorted
              • Ribasim.flow_table
              • Ribasim.formulate_basins!
              • -
              • Ribasim.formulate_flow!
              • Ribasim.formulate_flow!
              • +
              • Ribasim.formulate_flow!
              • Ribasim.formulate_flow!
              • Ribasim.get_area_and_level
              • Ribasim.get_chunk_sizes
              • Ribasim.get_compressor
              • -
              • Ribasim.get_flow
              • Ribasim.get_flow
              • +
              • Ribasim.get_flow
              • Ribasim.get_fractional_flow_connected_basins
              • Ribasim.get_jac_prototype
              • Ribasim.get_level
              • @@ -1049,8 +1049,8 @@

                Ribasim.scalar_interpolation_derivative
              • Ribasim.seconds_since
              • Ribasim.set_current_value!
              • -
              • Ribasim.set_flow!
              • Ribasim.set_flow!
              • +
              • Ribasim.set_flow!
              • Ribasim.set_fractional_flow_in_allocation!
              • Ribasim.set_initial_discrete_controlled_parameters!
              • Ribasim.set_objective_priority!
              • @@ -1062,8 +1062,8 @@

                Ribasim.update_basin
              • Ribasim.update_jac_prototype!
              • Ribasim.update_jac_prototype!
              • -
              • Ribasim.update_jac_prototype!
              • Ribasim.update_jac_prototype!
              • +
              • Ribasim.update_jac_prototype!
              • Ribasim.update_tabulated_rating_curve!
              • Ribasim.valid_discrete_control
              • Ribasim.valid_edge_types
              • diff --git a/core/allocation.html b/core/allocation.html index 0c0b93f9b..7af65f723 100644 --- a/core/allocation.html +++ b/core/allocation.html @@ -574,29 +574,29 @@

                println(p.allocation.allocation_models[1].problem)
                -
                Min 0.05 F[(#5, #2)] + 0.05 F[(#1, #2)] + 0.05 F[(#7, #12)] + 0.05 F[(#2, #3)] + 0.05 F[(#2, #5)] + 0.05 F[(#12, #13)] + 0.05 F[(#5, #7)] + 0.05 F[(#5, #6)] + 0.05 F[(#13, #10)] + 0.05 F[(#7, #10)] + F_abs[#6] + F_abs[#13] + F_abs[#3]
                +
                Min 0.05 F[(#1, #2)] + 0.05 F[(#2, #3)] + 0.05 F[(#12, #13)] + 0.05 F[(#2, #5)] + 0.05 F[(#5, #7)] + 0.05 F[(#7, #12)] + 0.05 F[(#13, #10)] + 0.05 F[(#5, #6)] + 0.05 F[(#7, #10)] + 0.05 F[(#5, #2)] + F_abs[#13] + F_abs[#6] + F_abs[#3]
                 Subject to
                  source[(#1, #2)] : F[(#1, #2)] ≤ 1
                - flow_conservation[#2] : -F[(#5, #2)] - F[(#1, #2)] + F[(#2, #3)] + F[(#2, #5)] ≤ 0
                - flow_conservation[#12] : -F[(#7, #12)] + F[(#12, #13)] ≤ 0
                - flow_conservation[#5] : F[(#5, #2)] - F[(#2, #5)] + F[(#5, #7)] + F[(#5, #6)] ≤ 0
                + flow_conservation[#12] : F[(#12, #13)] - F[(#7, #12)] ≤ 0
                + flow_conservation[#2] : -F[(#1, #2)] + F[(#2, #3)] + F[(#2, #5)] - F[(#5, #2)] ≤ 0
                + flow_conservation[#5] : -F[(#2, #5)] + F[(#5, #7)] + F[(#5, #6)] + F[(#5, #2)] ≤ 0
                  return_flow[#13] : F[(#13, #10)] ≤ 0
                - fractional_flow[(#7, #12)] : F[(#7, #12)] - 0.4 F[(#5, #7)] ≤ 0
                - F[(#5, #2)] ≥ 0
                + fractional_flow[(#7, #12)] : -0.4 F[(#5, #7)] + F[(#7, #12)] ≤ 0
                  F[(#1, #2)] ≥ 0
                - F[(#7, #12)] ≥ 0
                  F[(#2, #3)] ≥ 0
                - F[(#2, #5)] ≥ 0
                  F[(#12, #13)] ≥ 0
                + F[(#2, #5)] ≥ 0
                  F[(#5, #7)] ≥ 0
                - F[(#5, #6)] ≥ 0
                + F[(#7, #12)] ≥ 0
                  F[(#13, #10)] ≥ 0
                + F[(#5, #6)] ≥ 0
                  F[(#7, #10)] ≥ 0
                - abs_positive[#6] : -F[(#5, #6)] + F_abs[#6] ≥ -1.5
                + F[(#5, #2)] ≥ 0
                  abs_positive[#13] : -F[(#12, #13)] + F_abs[#13] ≥ 0
                + abs_positive[#6] : -F[(#5, #6)] + F_abs[#6] ≥ -1.5
                  abs_positive[#3] : -F[(#2, #3)] + F_abs[#3] ≥ 0
                - abs_negative[#6] : F[(#5, #6)] + F_abs[#6] ≥ 1.5
                  abs_negative[#13] : F[(#12, #13)] + F_abs[#13] ≥ 0
                + abs_negative[#6] : F[(#5, #6)] + F_abs[#6] ≥ 1.5
                  abs_negative[#3] : F[(#2, #3)] + F_abs[#3] ≥ 0
                 
                diff --git a/python/examples.html b/python/examples.html index 5559ed18d..deeab497a 100644 --- a/python/examples.html +++ b/python/examples.html @@ -555,7 +555,7 @@

                2 Update the basi ax = df_flow.pivot_table(index="time", columns="edge", values="flow_m3d").plot() ax.legend(bbox_to_anchor=(1.3, 1), title="Edge")
                -
                <matplotlib.legend.Legend at 0x7fd82b3b9850>
                +
                <matplotlib.legend.Legend at 0x7fabd80d6790>

                @@ -818,8 +818,8 @@

                3 Model with disc For node ID 1 (Basin): level > 15.0 This yielded control state "out": - For node ID 2 (Pump): flow_rate = 0.0 - For node ID 3 (Pump): flow_rate = 0.002 + For node ID 2 (Pump): active = <NA>, flow_rate = 0.0, min_flow_rate = nan, max_flow_rate = nan + For node ID 3 (Pump): active = <NA>, flow_rate = 0.002, min_flow_rate = nan, max_flow_rate = nan 1. At 2020-02-08 19:02:21.861000 the control node with ID 7 reached truth state TFF: For node ID 1 (Basin): level > 5.0 @@ -827,8 +827,8 @@

                3 Model with disc For node ID 1 (Basin): level < 15.0 This yielded control state "none": - For node ID 2 (Pump): flow_rate = 0.0 - For node ID 3 (Pump): flow_rate = 0.0 + For node ID 2 (Pump): active = <NA>, flow_rate = 0.0, min_flow_rate = nan, max_flow_rate = nan + For node ID 3 (Pump): active = <NA>, flow_rate = 0.0, min_flow_rate = nan, max_flow_rate = nan 2. At 2020-07-05 08:56:10.319000 the control node with ID 7 reached truth state FFF: For node ID 1 (Basin): level < 5.0 @@ -836,8 +836,8 @@

                3 Model with disc For node ID 1 (Basin): level < 15.0 This yielded control state "in": - For node ID 2 (Pump): flow_rate = 0.002 - For node ID 3 (Pump): flow_rate = 0.0 + For node ID 2 (Pump): active = <NA>, flow_rate = 0.002, min_flow_rate = nan, max_flow_rate = nan + For node ID 3 (Pump): active = <NA>, flow_rate = 0.0, min_flow_rate = nan, max_flow_rate = nan 3. At 2020-08-11 06:05:15.592000 the control node with ID 7 reached truth state TTF: For node ID 1 (Basin): level > 5.0 @@ -845,8 +845,8 @@

                3 Model with disc For node ID 1 (Basin): level < 15.0 This yielded control state "none": - For node ID 2 (Pump): flow_rate = 0.0 - For node ID 3 (Pump): flow_rate = 0.0 + For node ID 2 (Pump): active = <NA>, flow_rate = 0.0, min_flow_rate = nan, max_flow_rate = nan + For node ID 3 (Pump): active = <NA>, flow_rate = 0.0, min_flow_rate = nan, max_flow_rate = nan

                diff --git a/schema/Allocation.schema.json b/schema/Allocation.schema.json deleted file mode 100644 index b608a31eb..000000000 --- a/schema/Allocation.schema.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/Allocation.schema.json", - "title": "Allocation", - "description": "A Allocation object based on Ribasim.config.Allocation", - "type": "object", - "properties": { - "timestep": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ], - "default": null - }, - "use_allocation": { - "format": "default", - "type": "boolean", - "default": false - }, - "objective_type": { - "format": "default", - "type": "string", - "default": "linear_absolute" - } - }, - "required": [ - "use_allocation", - "objective_type" - ] -} diff --git a/schema/BasinProfile.schema.json b/schema/BasinProfile.schema.json deleted file mode 100644 index aede486b5..000000000 --- a/schema/BasinProfile.schema.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/BasinProfile.schema.json", - "title": "BasinProfile", - "description": "A BasinProfile object based on Ribasim.BasinProfileV1", - "type": "object", - "properties": { - "node_id": { - "format": "default", - "type": "integer" - }, - "area": { - "format": "double", - "type": "number" - }, - "level": { - "format": "double", - "type": "number" - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "node_id", - "area", - "level" - ] -} diff --git a/schema/BasinState.schema.json b/schema/BasinState.schema.json deleted file mode 100644 index e5ca6dd60..000000000 --- a/schema/BasinState.schema.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/BasinState.schema.json", - "title": "BasinState", - "description": "A BasinState object based on Ribasim.BasinStateV1", - "type": "object", - "properties": { - "node_id": { - "format": "default", - "type": "integer" - }, - "level": { - "format": "double", - "type": "number" - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "node_id", - "level" - ] -} diff --git a/schema/BasinStatic.schema.json b/schema/BasinStatic.schema.json deleted file mode 100644 index 747de6602..000000000 --- a/schema/BasinStatic.schema.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/BasinStatic.schema.json", - "title": "BasinStatic", - "description": "A BasinStatic object based on Ribasim.BasinStaticV1", - "type": "object", - "properties": { - "node_id": { - "format": "default", - "type": "integer" - }, - "drainage": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ] - }, - "potential_evaporation": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ] - }, - "infiltration": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ] - }, - "precipitation": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ] - }, - "urban_runoff": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ] - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "node_id" - ] -} diff --git a/schema/BasinSubgrid.schema.json b/schema/BasinSubgrid.schema.json deleted file mode 100644 index 244ab8189..000000000 --- a/schema/BasinSubgrid.schema.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/BasinSubgrid.schema.json", - "title": "BasinSubgrid", - "description": "A BasinSubgrid object based on Ribasim.BasinSubgridV1", - "type": "object", - "properties": { - "subgrid_id": { - "format": "default", - "type": "integer" - }, - "node_id": { - "format": "default", - "type": "integer" - }, - "basin_level": { - "format": "double", - "type": "number" - }, - "subgrid_level": { - "format": "double", - "type": "number" - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "subgrid_id", - "node_id", - "basin_level", - "subgrid_level" - ] -} diff --git a/schema/BasinTime.schema.json b/schema/BasinTime.schema.json deleted file mode 100644 index bfbcb03e2..000000000 --- a/schema/BasinTime.schema.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/BasinTime.schema.json", - "title": "BasinTime", - "description": "A BasinTime object based on Ribasim.BasinTimeV1", - "type": "object", - "properties": { - "node_id": { - "format": "default", - "type": "integer" - }, - "time": { - "format": "date-time", - "type": "string" - }, - "drainage": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ] - }, - "potential_evaporation": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ] - }, - "infiltration": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ] - }, - "precipitation": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ] - }, - "urban_runoff": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ] - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "node_id", - "time" - ] -} diff --git a/schema/DiscreteControlCondition.schema.json b/schema/DiscreteControlCondition.schema.json deleted file mode 100644 index e7e6b14df..000000000 --- a/schema/DiscreteControlCondition.schema.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/DiscreteControlCondition.schema.json", - "title": "DiscreteControlCondition", - "description": "A DiscreteControlCondition object based on Ribasim.DiscreteControlConditionV1", - "type": "object", - "properties": { - "node_id": { - "format": "default", - "type": "integer" - }, - "listen_feature_id": { - "format": "default", - "type": "integer" - }, - "variable": { - "format": "default", - "type": "string" - }, - "greater_than": { - "format": "double", - "type": "number" - }, - "look_ahead": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ] - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "node_id", - "listen_feature_id", - "variable", - "greater_than" - ] -} diff --git a/schema/DiscreteControlLogic.schema.json b/schema/DiscreteControlLogic.schema.json deleted file mode 100644 index e7e42b565..000000000 --- a/schema/DiscreteControlLogic.schema.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/DiscreteControlLogic.schema.json", - "title": "DiscreteControlLogic", - "description": "A DiscreteControlLogic object based on Ribasim.DiscreteControlLogicV1", - "type": "object", - "properties": { - "node_id": { - "format": "default", - "type": "integer" - }, - "truth_state": { - "format": "default", - "type": "string" - }, - "control_state": { - "format": "default", - "type": "string" - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "node_id", - "truth_state", - "control_state" - ] -} diff --git a/schema/Edge.schema.json b/schema/Edge.schema.json deleted file mode 100644 index 96f434e7e..000000000 --- a/schema/Edge.schema.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/Edge.schema.json", - "title": "Edge", - "description": "A Edge object based on Ribasim.EdgeV1", - "type": "object", - "properties": { - "fid": { - "format": "default", - "type": "integer" - }, - "name": { - "format": "default", - "type": "string" - }, - "from_node_id": { - "format": "default", - "type": "integer" - }, - "to_node_id": { - "format": "default", - "type": "integer" - }, - "edge_type": { - "format": "default", - "type": "string" - }, - "allocation_network_id": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "integer" - } - ] - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "fid", - "name", - "from_node_id", - "to_node_id", - "edge_type" - ] -} diff --git a/schema/FlowBoundaryStatic.schema.json b/schema/FlowBoundaryStatic.schema.json deleted file mode 100644 index 8ff56bd1f..000000000 --- a/schema/FlowBoundaryStatic.schema.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/FlowBoundaryStatic.schema.json", - "title": "FlowBoundaryStatic", - "description": "A FlowBoundaryStatic object based on Ribasim.FlowBoundaryStaticV1", - "type": "object", - "properties": { - "node_id": { - "format": "default", - "type": "integer" - }, - "active": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "boolean" - } - ] - }, - "flow_rate": { - "format": "double", - "type": "number" - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "node_id", - "flow_rate" - ] -} diff --git a/schema/FlowBoundaryTime.schema.json b/schema/FlowBoundaryTime.schema.json deleted file mode 100644 index 7f1d00465..000000000 --- a/schema/FlowBoundaryTime.schema.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/FlowBoundaryTime.schema.json", - "title": "FlowBoundaryTime", - "description": "A FlowBoundaryTime object based on Ribasim.FlowBoundaryTimeV1", - "type": "object", - "properties": { - "node_id": { - "format": "default", - "type": "integer" - }, - "time": { - "format": "date-time", - "type": "string" - }, - "flow_rate": { - "format": "double", - "type": "number" - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "node_id", - "time", - "flow_rate" - ] -} diff --git a/schema/FractionalFlowStatic.schema.json b/schema/FractionalFlowStatic.schema.json deleted file mode 100644 index 60cf463ab..000000000 --- a/schema/FractionalFlowStatic.schema.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/FractionalFlowStatic.schema.json", - "title": "FractionalFlowStatic", - "description": "A FractionalFlowStatic object based on Ribasim.FractionalFlowStaticV1", - "type": "object", - "properties": { - "node_id": { - "format": "default", - "type": "integer" - }, - "fraction": { - "format": "double", - "type": "number" - }, - "control_state": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "node_id", - "fraction" - ] -} diff --git a/schema/LevelBoundaryStatic.schema.json b/schema/LevelBoundaryStatic.schema.json deleted file mode 100644 index 8c1e30d27..000000000 --- a/schema/LevelBoundaryStatic.schema.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/LevelBoundaryStatic.schema.json", - "title": "LevelBoundaryStatic", - "description": "A LevelBoundaryStatic object based on Ribasim.LevelBoundaryStaticV1", - "type": "object", - "properties": { - "node_id": { - "format": "default", - "type": "integer" - }, - "active": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "boolean" - } - ] - }, - "level": { - "format": "double", - "type": "number" - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "node_id", - "level" - ] -} diff --git a/schema/LevelBoundaryTime.schema.json b/schema/LevelBoundaryTime.schema.json deleted file mode 100644 index 89c8dfea2..000000000 --- a/schema/LevelBoundaryTime.schema.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/LevelBoundaryTime.schema.json", - "title": "LevelBoundaryTime", - "description": "A LevelBoundaryTime object based on Ribasim.LevelBoundaryTimeV1", - "type": "object", - "properties": { - "node_id": { - "format": "default", - "type": "integer" - }, - "time": { - "format": "date-time", - "type": "string" - }, - "level": { - "format": "double", - "type": "number" - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "node_id", - "time", - "level" - ] -} diff --git a/schema/LinearResistanceStatic.schema.json b/schema/LinearResistanceStatic.schema.json deleted file mode 100644 index 655f2d3c3..000000000 --- a/schema/LinearResistanceStatic.schema.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/LinearResistanceStatic.schema.json", - "title": "LinearResistanceStatic", - "description": "A LinearResistanceStatic object based on Ribasim.LinearResistanceStaticV1", - "type": "object", - "properties": { - "node_id": { - "format": "default", - "type": "integer" - }, - "active": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "boolean" - } - ] - }, - "resistance": { - "format": "double", - "type": "number" - }, - "control_state": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "node_id", - "resistance" - ] -} diff --git a/schema/Logging.schema.json b/schema/Logging.schema.json deleted file mode 100644 index 3db246070..000000000 --- a/schema/Logging.schema.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/Logging.schema.json", - "title": "Logging", - "description": "A Logging object based on Ribasim.config.Logging", - "type": "object", - "properties": { - "verbosity": { - "format": "default", - "type": "string", - "default": "info" - }, - "timing": { - "format": "default", - "type": "boolean", - "default": false - } - }, - "required": [ - "verbosity", - "timing" - ] -} diff --git a/schema/ManningResistanceStatic.schema.json b/schema/ManningResistanceStatic.schema.json deleted file mode 100644 index 12cc0ce38..000000000 --- a/schema/ManningResistanceStatic.schema.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/ManningResistanceStatic.schema.json", - "title": "ManningResistanceStatic", - "description": "A ManningResistanceStatic object based on Ribasim.ManningResistanceStaticV1", - "type": "object", - "properties": { - "node_id": { - "format": "default", - "type": "integer" - }, - "active": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "boolean" - } - ] - }, - "length": { - "format": "double", - "type": "number" - }, - "manning_n": { - "format": "double", - "type": "number" - }, - "profile_width": { - "format": "double", - "type": "number" - }, - "profile_slope": { - "format": "double", - "type": "number" - }, - "control_state": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "node_id", - "length", - "manning_n", - "profile_width", - "profile_slope" - ] -} diff --git a/schema/Node.schema.json b/schema/Node.schema.json deleted file mode 100644 index bf3d3d1b8..000000000 --- a/schema/Node.schema.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/Node.schema.json", - "title": "Node", - "description": "A Node object based on Ribasim.NodeV1", - "type": "object", - "properties": { - "fid": { - "format": "default", - "type": "integer" - }, - "name": { - "format": "default", - "type": "string" - }, - "type": { - "format": "default", - "type": "string" - }, - "allocation_network_id": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "integer" - } - ] - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "fid", - "name", - "type" - ] -} diff --git a/schema/OutletStatic.schema.json b/schema/OutletStatic.schema.json deleted file mode 100644 index de101f2d1..000000000 --- a/schema/OutletStatic.schema.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/OutletStatic.schema.json", - "title": "OutletStatic", - "description": "A OutletStatic object based on Ribasim.OutletStaticV1", - "type": "object", - "properties": { - "node_id": { - "format": "default", - "type": "integer" - }, - "active": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "boolean" - } - ] - }, - "flow_rate": { - "format": "double", - "type": "number" - }, - "min_flow_rate": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ] - }, - "max_flow_rate": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ] - }, - "min_crest_level": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ] - }, - "control_state": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "node_id", - "flow_rate" - ] -} diff --git a/schema/PIDControlStatic.schema.json b/schema/PIDControlStatic.schema.json deleted file mode 100644 index 293e7f0b8..000000000 --- a/schema/PIDControlStatic.schema.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/PidControlStatic.schema.json", - "title": "PidControlStatic", - "description": "A PidControlStatic object based on Ribasim.PidControlStaticV1", - "type": "object", - "properties": { - "node_id": { - "format": "default", - "type": "integer" - }, - "active": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "boolean" - } - ] - }, - "listen_node_id": { - "format": "default", - "type": "integer" - }, - "target": { - "format": "double", - "type": "number" - }, - "proportional": { - "format": "double", - "type": "number" - }, - "integral": { - "format": "double", - "type": "number" - }, - "derivative": { - "format": "double", - "type": "number" - }, - "control_state": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "node_id", - "listen_node_id", - "target", - "proportional", - "integral", - "derivative" - ] -} diff --git a/schema/PidControlTime.schema.json b/schema/PidControlTime.schema.json deleted file mode 100644 index 6666066a5..000000000 --- a/schema/PidControlTime.schema.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/PidControlTime.schema.json", - "title": "PidControlTime", - "description": "A PidControlTime object based on Ribasim.PidControlTimeV1", - "type": "object", - "properties": { - "node_id": { - "format": "default", - "type": "integer" - }, - "listen_node_id": { - "format": "default", - "type": "integer" - }, - "time": { - "format": "date-time", - "type": "string" - }, - "target": { - "format": "double", - "type": "number" - }, - "proportional": { - "format": "double", - "type": "number" - }, - "integral": { - "format": "double", - "type": "number" - }, - "derivative": { - "format": "double", - "type": "number" - }, - "control_state": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "node_id", - "listen_node_id", - "time", - "target", - "proportional", - "integral", - "derivative" - ] -} diff --git a/schema/PumpStatic.schema.json b/schema/PumpStatic.schema.json deleted file mode 100644 index 100c3a922..000000000 --- a/schema/PumpStatic.schema.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/PumpStatic.schema.json", - "title": "PumpStatic", - "description": "A PumpStatic object based on Ribasim.PumpStaticV1", - "type": "object", - "properties": { - "node_id": { - "format": "default", - "type": "integer" - }, - "active": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "boolean" - } - ] - }, - "flow_rate": { - "format": "double", - "type": "number" - }, - "min_flow_rate": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ] - }, - "max_flow_rate": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ] - }, - "control_state": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "node_id", - "flow_rate" - ] -} diff --git a/schema/Results.schema.json b/schema/Results.schema.json deleted file mode 100644 index eb23d21b6..000000000 --- a/schema/Results.schema.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/Results.schema.json", - "title": "Results", - "description": "A Results object based on Ribasim.config.Results", - "type": "object", - "properties": { - "outstate": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - }, - "compression": { - "format": "default", - "type": "string", - "default": "zstd" - }, - "compression_level": { - "format": "default", - "type": "integer", - "default": 6 - }, - "subgrid": { - "format": "default", - "type": "boolean", - "default": false - } - }, - "required": [ - "compression", - "compression_level", - "subgrid" - ] -} diff --git a/schema/Solver.schema.json b/schema/Solver.schema.json deleted file mode 100644 index 4b3f6c236..000000000 --- a/schema/Solver.schema.json +++ /dev/null @@ -1,106 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/Solver.schema.json", - "title": "Solver", - "description": "A Solver object based on Ribasim.config.Solver", - "type": "object", - "properties": { - "algorithm": { - "format": "default", - "type": "string", - "default": "QNDF" - }, - "saveat": { - "format": "default", - "anyOf": [ - { - "type": "number" - }, - { - "type": "array", - "items": { - "type": "number" - } - } - ], - "default": [ - ] - }, - "adaptive": { - "format": "default", - "type": "boolean", - "default": true - }, - "dt": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ], - "default": null - }, - "dtmin": { - "format": "double", - "type": "number", - "default": 0 - }, - "dtmax": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "number" - } - ], - "default": null - }, - "force_dtmin": { - "format": "default", - "type": "boolean", - "default": false - }, - "abstol": { - "format": "double", - "type": "number", - "default": 1.0e-6 - }, - "reltol": { - "format": "double", - "type": "number", - "default": 1.0e-5 - }, - "maxiters": { - "format": "default", - "type": "integer", - "default": 1000000000 - }, - "sparse": { - "format": "default", - "type": "boolean", - "default": true - }, - "autodiff": { - "format": "default", - "type": "boolean", - "default": true - } - }, - "required": [ - "algorithm", - "saveat", - "adaptive", - "dtmin", - "force_dtmin", - "abstol", - "reltol", - "maxiters", - "sparse", - "autodiff" - ] -} diff --git a/schema/TabulatedRatingCurveStatic.schema.json b/schema/TabulatedRatingCurveStatic.schema.json deleted file mode 100644 index 319d37d8c..000000000 --- a/schema/TabulatedRatingCurveStatic.schema.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/TabulatedRatingCurveStatic.schema.json", - "title": "TabulatedRatingCurveStatic", - "description": "A TabulatedRatingCurveStatic object based on Ribasim.TabulatedRatingCurveStaticV1", - "type": "object", - "properties": { - "node_id": { - "format": "default", - "type": "integer" - }, - "active": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "boolean" - } - ] - }, - "level": { - "format": "double", - "type": "number" - }, - "flow_rate": { - "format": "double", - "type": "number" - }, - "control_state": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ] - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "node_id", - "level", - "flow_rate" - ] -} diff --git a/schema/TabulatedRatingCurveTime.schema.json b/schema/TabulatedRatingCurveTime.schema.json deleted file mode 100644 index 52a07a442..000000000 --- a/schema/TabulatedRatingCurveTime.schema.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/TabulatedRatingCurveTime.schema.json", - "title": "TabulatedRatingCurveTime", - "description": "A TabulatedRatingCurveTime object based on Ribasim.TabulatedRatingCurveTimeV1", - "type": "object", - "properties": { - "node_id": { - "format": "default", - "type": "integer" - }, - "time": { - "format": "date-time", - "type": "string" - }, - "level": { - "format": "double", - "type": "number" - }, - "flow_rate": { - "format": "double", - "type": "number" - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "node_id", - "time", - "level", - "flow_rate" - ] -} diff --git a/schema/TerminalStatic.schema.json b/schema/TerminalStatic.schema.json deleted file mode 100644 index 844d715c7..000000000 --- a/schema/TerminalStatic.schema.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/TerminalStatic.schema.json", - "title": "TerminalStatic", - "description": "A TerminalStatic object based on Ribasim.TerminalStaticV1", - "type": "object", - "properties": { - "node_id": { - "format": "default", - "type": "integer" - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "node_id" - ] -} diff --git a/schema/Toml.schema.json b/schema/Toml.schema.json deleted file mode 100644 index 1fce57eba..000000000 --- a/schema/Toml.schema.json +++ /dev/null @@ -1,186 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/Toml.schema.json", - "title": "Toml", - "description": "A Toml object based on Ribasim.config.Toml", - "type": "object", - "properties": { - "starttime": { - "format": "date-time", - "type": "string" - }, - "endtime": { - "format": "date-time", - "type": "string" - }, - "input_dir": { - "format": "default", - "type": "string" - }, - "results_dir": { - "format": "default", - "type": "string" - }, - "database": { - "format": "default", - "type": "string", - "default": "database.gpkg" - }, - "allocation": { - "$ref": "https://deltares.github.io/Ribasim/schema/Allocation.schema.json", - "default": { - "timestep": null, - "use_allocation": false, - "objective_type": "linear_absolute" - } - }, - "solver": { - "$ref": "https://deltares.github.io/Ribasim/schema/Solver.schema.json", - "default": { - "algorithm": "QNDF", - "saveat": [ - ], - "adaptive": true, - "dt": null, - "dtmin": 0, - "dtmax": null, - "force_dtmin": false, - "abstol": 1.0e-6, - "reltol": 1.0e-5, - "maxiters": 1000000000, - "sparse": true, - "autodiff": true - } - }, - "logging": { - "$ref": "https://deltares.github.io/Ribasim/schema/Logging.schema.json", - "default": { - "verbosity": { - "level": 0 - }, - "timing": false - } - }, - "results": { - "$ref": "https://deltares.github.io/Ribasim/schema/Results.schema.json", - "default": { - "outstate": null, - "compression": "zstd", - "compression_level": 6, - "subgrid": false - } - }, - "terminal": { - "$ref": "https://deltares.github.io/Ribasim/schema/terminal.schema.json", - "default": { - "static": null - } - }, - "pid_control": { - "$ref": "https://deltares.github.io/Ribasim/schema/pid_control.schema.json", - "default": { - "static": null, - "time": null - } - }, - "level_boundary": { - "$ref": "https://deltares.github.io/Ribasim/schema/level_boundary.schema.json", - "default": { - "static": null, - "time": null - } - }, - "pump": { - "$ref": "https://deltares.github.io/Ribasim/schema/pump.schema.json", - "default": { - "static": null - } - }, - "tabulated_rating_curve": { - "$ref": "https://deltares.github.io/Ribasim/schema/tabulated_rating_curve.schema.json", - "default": { - "static": null, - "time": null - } - }, - "user": { - "$ref": "https://deltares.github.io/Ribasim/schema/user.schema.json", - "default": { - "static": null, - "time": null - } - }, - "flow_boundary": { - "$ref": "https://deltares.github.io/Ribasim/schema/flow_boundary.schema.json", - "default": { - "static": null, - "time": null - } - }, - "basin": { - "$ref": "https://deltares.github.io/Ribasim/schema/basin.schema.json", - "default": { - "profile": null, - "state": null, - "static": null, - "subgrid": null, - "time": null - } - }, - "manning_resistance": { - "$ref": "https://deltares.github.io/Ribasim/schema/manning_resistance.schema.json", - "default": { - "static": null - } - }, - "discrete_control": { - "$ref": "https://deltares.github.io/Ribasim/schema/discrete_control.schema.json", - "default": { - "condition": null, - "logic": null - } - }, - "outlet": { - "$ref": "https://deltares.github.io/Ribasim/schema/outlet.schema.json", - "default": { - "static": null - } - }, - "linear_resistance": { - "$ref": "https://deltares.github.io/Ribasim/schema/linear_resistance.schema.json", - "default": { - "static": null - } - }, - "fractional_flow": { - "$ref": "https://deltares.github.io/Ribasim/schema/fractional_flow.schema.json", - "default": { - "static": null - } - } - }, - "required": [ - "starttime", - "endtime", - "input_dir", - "results_dir", - "database", - "allocation", - "solver", - "logging", - "results", - "terminal", - "pid_control", - "level_boundary", - "pump", - "tabulated_rating_curve", - "user", - "flow_boundary", - "basin", - "manning_resistance", - "discrete_control", - "outlet", - "linear_resistance", - "fractional_flow" - ] -} diff --git a/schema/UserStatic.schema.json b/schema/UserStatic.schema.json deleted file mode 100644 index 35a22871a..000000000 --- a/schema/UserStatic.schema.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/UserStatic.schema.json", - "title": "UserStatic", - "description": "A UserStatic object based on Ribasim.UserStaticV1", - "type": "object", - "properties": { - "node_id": { - "format": "default", - "type": "integer" - }, - "active": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "boolean" - } - ] - }, - "demand": { - "format": "double", - "type": "number" - }, - "return_factor": { - "format": "double", - "type": "number" - }, - "min_level": { - "format": "double", - "type": "number" - }, - "priority": { - "format": "default", - "type": "integer" - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "node_id", - "demand", - "return_factor", - "min_level", - "priority" - ] -} diff --git a/schema/UserTime.schema.json b/schema/UserTime.schema.json deleted file mode 100644 index a68256d4a..000000000 --- a/schema/UserTime.schema.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/UserTime.schema.json", - "title": "UserTime", - "description": "A UserTime object based on Ribasim.UserTimeV1", - "type": "object", - "properties": { - "node_id": { - "format": "default", - "type": "integer" - }, - "time": { - "format": "date-time", - "type": "string" - }, - "demand": { - "format": "double", - "type": "number" - }, - "return_factor": { - "format": "double", - "type": "number" - }, - "min_level": { - "format": "double", - "type": "number" - }, - "priority": { - "format": "default", - "type": "integer" - }, - "remarks": { - "description": "a hack for pandera", - "type": "string", - "format": "default", - "default": "" - } - }, - "required": [ - "node_id", - "time", - "demand", - "return_factor", - "min_level", - "priority" - ] -} diff --git a/schema/basin.schema.json b/schema/basin.schema.json deleted file mode 100644 index ce36b64ec..000000000 --- a/schema/basin.schema.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/basin.schema.json", - "title": "basin", - "description": "A basin object based on Ribasim.config.basin", - "type": "object", - "properties": { - "profile": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - }, - "state": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - }, - "static": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - }, - "subgrid": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - }, - "time": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - } - }, - "required": [ - ] -} diff --git a/schema/discrete_control.schema.json b/schema/discrete_control.schema.json deleted file mode 100644 index 5dad798e4..000000000 --- a/schema/discrete_control.schema.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/discrete_control.schema.json", - "title": "discrete_control", - "description": "A discrete_control object based on Ribasim.config.discrete_control", - "type": "object", - "properties": { - "condition": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - }, - "logic": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - } - }, - "required": [ - ] -} diff --git a/schema/flow_boundary.schema.json b/schema/flow_boundary.schema.json deleted file mode 100644 index fb14390c2..000000000 --- a/schema/flow_boundary.schema.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/flow_boundary.schema.json", - "title": "flow_boundary", - "description": "A flow_boundary object based on Ribasim.config.flow_boundary", - "type": "object", - "properties": { - "static": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - }, - "time": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - } - }, - "required": [ - ] -} diff --git a/schema/fractional_flow.schema.json b/schema/fractional_flow.schema.json deleted file mode 100644 index fb3846df0..000000000 --- a/schema/fractional_flow.schema.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/fractional_flow.schema.json", - "title": "fractional_flow", - "description": "A fractional_flow object based on Ribasim.config.fractional_flow", - "type": "object", - "properties": { - "static": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - } - }, - "required": [ - ] -} diff --git a/schema/level_boundary.schema.json b/schema/level_boundary.schema.json deleted file mode 100644 index f90b610e7..000000000 --- a/schema/level_boundary.schema.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/level_boundary.schema.json", - "title": "level_boundary", - "description": "A level_boundary object based on Ribasim.config.level_boundary", - "type": "object", - "properties": { - "static": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - }, - "time": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - } - }, - "required": [ - ] -} diff --git a/schema/linear_resistance.schema.json b/schema/linear_resistance.schema.json deleted file mode 100644 index 8aefd274f..000000000 --- a/schema/linear_resistance.schema.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/linear_resistance.schema.json", - "title": "linear_resistance", - "description": "A linear_resistance object based on Ribasim.config.linear_resistance", - "type": "object", - "properties": { - "static": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - } - }, - "required": [ - ] -} diff --git a/schema/manning_resistance.schema.json b/schema/manning_resistance.schema.json deleted file mode 100644 index 03bba823d..000000000 --- a/schema/manning_resistance.schema.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/manning_resistance.schema.json", - "title": "manning_resistance", - "description": "A manning_resistance object based on Ribasim.config.manning_resistance", - "type": "object", - "properties": { - "static": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - } - }, - "required": [ - ] -} diff --git a/schema/outlet.schema.json b/schema/outlet.schema.json deleted file mode 100644 index 137d0a6d4..000000000 --- a/schema/outlet.schema.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/outlet.schema.json", - "title": "outlet", - "description": "A outlet object based on Ribasim.config.outlet", - "type": "object", - "properties": { - "static": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - } - }, - "required": [ - ] -} diff --git a/schema/pid_control.schema.json b/schema/pid_control.schema.json deleted file mode 100644 index 75e6763c6..000000000 --- a/schema/pid_control.schema.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/pid_control.schema.json", - "title": "pid_control", - "description": "A pid_control object based on Ribasim.config.pid_control", - "type": "object", - "properties": { - "static": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - }, - "time": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - } - }, - "required": [ - ] -} diff --git a/schema/pump.schema.json b/schema/pump.schema.json deleted file mode 100644 index d1851de89..000000000 --- a/schema/pump.schema.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/pump.schema.json", - "title": "pump", - "description": "A pump object based on Ribasim.config.pump", - "type": "object", - "properties": { - "static": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - } - }, - "required": [ - ] -} diff --git a/schema/root.schema.json b/schema/root.schema.json deleted file mode 100644 index e9089cc68..000000000 --- a/schema/root.schema.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "properties": { - "basinprofile": { - "$ref": "basinprofile.schema.json" - }, - "basinstate": { - "$ref": "basinstate.schema.json" - }, - "basinstatic": { - "$ref": "basinstatic.schema.json" - }, - "basinsubgrid": { - "$ref": "basinsubgrid.schema.json" - }, - "basintime": { - "$ref": "basintime.schema.json" - }, - "discretecontrolcondition": { - "$ref": "discretecontrolcondition.schema.json" - }, - "discretecontrollogic": { - "$ref": "discretecontrollogic.schema.json" - }, - "edge": { - "$ref": "edge.schema.json" - }, - "flowboundarystatic": { - "$ref": "flowboundarystatic.schema.json" - }, - "flowboundarytime": { - "$ref": "flowboundarytime.schema.json" - }, - "fractionalflowstatic": { - "$ref": "fractionalflowstatic.schema.json" - }, - "levelboundarystatic": { - "$ref": "levelboundarystatic.schema.json" - }, - "levelboundarytime": { - "$ref": "levelboundarytime.schema.json" - }, - "linearresistancestatic": { - "$ref": "linearresistancestatic.schema.json" - }, - "manningresistancestatic": { - "$ref": "manningresistancestatic.schema.json" - }, - "node": { - "$ref": "node.schema.json" - }, - "outletstatic": { - "$ref": "outletstatic.schema.json" - }, - "pidcontrolstatic": { - "$ref": "pidcontrolstatic.schema.json" - }, - "pidcontroltime": { - "$ref": "pidcontroltime.schema.json" - }, - "pumpstatic": { - "$ref": "pumpstatic.schema.json" - }, - "tabulatedratingcurvestatic": { - "$ref": "tabulatedratingcurvestatic.schema.json" - }, - "tabulatedratingcurvetime": { - "$ref": "tabulatedratingcurvetime.schema.json" - }, - "terminalstatic": { - "$ref": "terminalstatic.schema.json" - }, - "userstatic": { - "$ref": "userstatic.schema.json" - }, - "usertime": { - "$ref": "usertime.schema.json" - } - }, - "$id": "https://deltares.github.io/Ribasim/schema/root.schema.json", - "title": "root", - "description": "All Ribasim Node types", - "type": "object" -} diff --git a/schema/tabulated_rating_curve.schema.json b/schema/tabulated_rating_curve.schema.json deleted file mode 100644 index efbb836dd..000000000 --- a/schema/tabulated_rating_curve.schema.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/tabulated_rating_curve.schema.json", - "title": "tabulated_rating_curve", - "description": "A tabulated_rating_curve object based on Ribasim.config.tabulated_rating_curve", - "type": "object", - "properties": { - "static": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - }, - "time": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - } - }, - "required": [ - ] -} diff --git a/schema/terminal.schema.json b/schema/terminal.schema.json deleted file mode 100644 index b889f7f4d..000000000 --- a/schema/terminal.schema.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/terminal.schema.json", - "title": "terminal", - "description": "A terminal object based on Ribasim.config.terminal", - "type": "object", - "properties": { - "static": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - } - }, - "required": [ - ] -} diff --git a/schema/user.schema.json b/schema/user.schema.json deleted file mode 100644 index 911f49214..000000000 --- a/schema/user.schema.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/user.schema.json", - "title": "user", - "description": "A user object based on Ribasim.config.user", - "type": "object", - "properties": { - "static": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - }, - "time": { - "format": "default", - "anyOf": [ - { - "type": "null" - }, - { - "type": "string" - } - ], - "default": null - } - }, - "required": [ - ] -} diff --git a/search.json b/search.json index 88a09e547..d33b2fc49 100644 --- a/search.json +++ b/search.json @@ -326,7 +326,7 @@ "href": "python/examples.html", "title": "Examples", "section": "", - "text": "1 Basic model with static forcing\n\nfrom pathlib import Path\n\nimport geopandas as gpd\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nimport ribasim\n\nSetup the basins:\n\nprofile = pd.DataFrame(\n data={\n \"node_id\": [1, 1, 3, 3, 6, 6, 9, 9],\n \"area\": [0.01, 1000.0] * 4,\n \"level\": [0.0, 1.0] * 4,\n }\n)\n\n# Convert steady forcing to m/s\n# 2 mm/d precipitation, 1 mm/d evaporation\nseconds_in_day = 24 * 3600\nprecipitation = 0.002 / seconds_in_day\nevaporation = 0.001 / seconds_in_day\n\nstatic = pd.DataFrame(\n data={\n \"node_id\": [0],\n \"drainage\": [0.0],\n \"potential_evaporation\": [evaporation],\n \"infiltration\": [0.0],\n \"precipitation\": [precipitation],\n \"urban_runoff\": [0.0],\n }\n)\nstatic = static.iloc[[0, 0, 0, 0]]\nstatic[\"node_id\"] = [1, 3, 6, 9]\n\nbasin = ribasim.Basin(profile=profile, static=static)\n\nSetup linear resistance:\n\nlinear_resistance = ribasim.LinearResistance(\n static=pd.DataFrame(\n data={\"node_id\": [10, 12], \"resistance\": [5e3, (3600.0 * 24) / 100.0]}\n )\n)\n\nSetup Manning resistance:\n\nmanning_resistance = ribasim.ManningResistance(\n static=pd.DataFrame(\n data={\n \"node_id\": [2],\n \"length\": [900.0],\n \"manning_n\": [0.04],\n \"profile_width\": [6.0],\n \"profile_slope\": [3.0],\n }\n )\n)\n\nSet up a rating curve node:\n\n# Discharge: lose 1% of storage volume per day at storage = 1000.0.\nq1000 = 1000.0 * 0.01 / seconds_in_day\n\nrating_curve = ribasim.TabulatedRatingCurve(\n static=pd.DataFrame(\n data={\n \"node_id\": [4, 4],\n \"level\": [0.0, 1.0],\n \"flow_rate\": [0.0, q1000],\n }\n )\n)\n\nSetup fractional flows:\n\nfractional_flow = ribasim.FractionalFlow(\n static=pd.DataFrame(\n data={\n \"node_id\": [5, 8, 13],\n \"fraction\": [0.3, 0.6, 0.1],\n }\n )\n)\n\nSetup pump:\n\npump = ribasim.Pump(\n static=pd.DataFrame(\n data={\n \"node_id\": [7],\n \"flow_rate\": [0.5 / 3600],\n }\n )\n)\n\nSetup level boundary:\n\nlevel_boundary = ribasim.LevelBoundary(\n static=pd.DataFrame(\n data={\n \"node_id\": [11, 17],\n \"level\": [0.5, 1.5],\n }\n )\n)\n\nSetup flow boundary:\n\nflow_boundary = ribasim.FlowBoundary(\n static=pd.DataFrame(\n data={\n \"node_id\": [15, 16],\n \"flow_rate\": [1e-4, 1e-4],\n }\n )\n)\n\nSetup terminal:\n\nterminal = ribasim.Terminal(\n static=pd.DataFrame(\n data={\n \"node_id\": [14],\n }\n )\n)\n\nSet up the nodes:\n\nxy = np.array(\n [\n (0.0, 0.0), # 1: Basin,\n (1.0, 0.0), # 2: ManningResistance\n (2.0, 0.0), # 3: Basin\n (3.0, 0.0), # 4: TabulatedRatingCurve\n (3.0, 1.0), # 5: FractionalFlow\n (3.0, 2.0), # 6: Basin\n (4.0, 1.0), # 7: Pump\n (4.0, 0.0), # 8: FractionalFlow\n (5.0, 0.0), # 9: Basin\n (6.0, 0.0), # 10: LinearResistance\n (2.0, 2.0), # 11: LevelBoundary\n (2.0, 1.0), # 12: LinearResistance\n (3.0, -1.0), # 13: FractionalFlow\n (3.0, -2.0), # 14: Terminal\n (3.0, 3.0), # 15: FlowBoundary\n (0.0, 1.0), # 16: FlowBoundary\n (6.0, 1.0), # 17: LevelBoundary\n ]\n)\nnode_xy = gpd.points_from_xy(x=xy[:, 0], y=xy[:, 1])\n\nnode_id, node_type = ribasim.Node.node_ids_and_types(\n basin,\n manning_resistance,\n rating_curve,\n pump,\n fractional_flow,\n linear_resistance,\n level_boundary,\n flow_boundary,\n terminal,\n)\n\n# Make sure the feature id starts at 1: explicitly give an index.\nnode = ribasim.Node(\n df=gpd.GeoDataFrame(\n data={\"type\": node_type},\n index=pd.Index(node_id, name=\"fid\"),\n geometry=node_xy,\n crs=\"EPSG:28992\",\n )\n)\n\nSetup the edges:\n\nfrom_id = np.array(\n [1, 2, 3, 4, 4, 5, 6, 8, 7, 9, 11, 12, 4, 13, 15, 16, 10], dtype=np.int64\n)\nto_id = np.array(\n [2, 3, 4, 5, 8, 6, 7, 9, 9, 10, 12, 3, 13, 14, 6, 1, 17], dtype=np.int64\n)\nlines = node.geometry_from_connectivity(from_id, to_id)\nedge = ribasim.Edge(\n df=gpd.GeoDataFrame(\n data={\n \"from_node_id\": from_id,\n \"to_node_id\": to_id,\n \"edge_type\": len(from_id) * [\"flow\"],\n },\n geometry=lines,\n crs=\"EPSG:28992\",\n )\n)\n\nSetup a model:\n\nmodel = ribasim.Model(\n network=ribasim.Network(\n node=node,\n edge=edge,\n ),\n basin=basin,\n level_boundary=level_boundary,\n flow_boundary=flow_boundary,\n pump=pump,\n linear_resistance=linear_resistance,\n manning_resistance=manning_resistance,\n tabulated_rating_curve=rating_curve,\n fractional_flow=fractional_flow,\n terminal=terminal,\n starttime=\"2020-01-01 00:00:00\",\n endtime=\"2021-01-01 00:00:00\",\n)\n\nLet’s take a look at the model:\n\nmodel.plot()\n\n<Axes: >\n\n\n\n\n\nWrite the model to a TOML and GeoPackage:\n\ndatadir = Path(\"data\")\nmodel.write(datadir / \"basic/ribasim.toml\")\n\nPosixPath('data/basic/ribasim.toml')\n\n\n\n\n2 Update the basic model with transient forcing\nThis assumes you have already created the basic model with static forcing.\n\nimport numpy as np\nimport pandas as pd\nimport ribasim\nimport xarray as xr\n\n\nmodel = ribasim.Model(filepath=datadir / \"basic/ribasim.toml\")\n\n\ntime = pd.date_range(model.starttime, model.endtime)\nday_of_year = time.day_of_year.to_numpy()\nseconds_per_day = 24 * 60 * 60\nevaporation = (\n (-1.0 * np.cos(day_of_year / 365.0 * 2 * np.pi) + 1.0) * 0.0025 / seconds_per_day\n)\nrng = np.random.default_rng(seed=0)\nprecipitation = (\n rng.lognormal(mean=-1.0, sigma=1.7, size=time.size) * 0.001 / seconds_per_day\n)\n\nWe’ll use xarray to easily broadcast the values.\n\ntimeseries = (\n pd.DataFrame(\n data={\n \"node_id\": 1,\n \"time\": pd.date_range(model.starttime, model.endtime),\n \"drainage\": 0.0,\n \"potential_evaporation\": evaporation,\n \"infiltration\": 0.0,\n \"precipitation\": precipitation,\n \"urban_runoff\": 0.0,\n }\n )\n .set_index(\"time\")\n .to_xarray()\n)\n\nbasin_ids = model.basin.static.df[\"node_id\"].to_numpy()\nbasin_nodes = xr.DataArray(\n np.ones(len(basin_ids)), coords={\"node_id\": basin_ids}, dims=[\"node_id\"]\n)\nforcing = (timeseries * basin_nodes).to_dataframe().reset_index()\n\n\nstate = pd.DataFrame(\n data={\n \"node_id\": basin_ids,\n \"level\": 1.4,\n }\n)\n\n\nmodel.basin.time.df = forcing\nmodel.basin.state.df = state\n\n\nmodel.write(datadir / \"basic_transient/ribasim.toml\")\n\nPosixPath('data/basic_transient/ribasim.toml')\n\n\nNow run the model with ribasim basic_transient/ribasim.toml. After running the model, read back the results:\n\ndf_basin = pd.read_feather(datadir / \"basic_transient/results/basin.arrow\")\ndf_basin_wide = df_basin.pivot_table(\n index=\"time\", columns=\"node_id\", values=[\"storage\", \"level\"]\n)\ndf_basin_wide[\"level\"].plot()\n\n<Axes: xlabel='time'>\n\n\n\n\n\n\ndf_flow = pd.read_feather(datadir / \"basic_transient/results/flow.arrow\")\ndf_flow[\"edge\"] = list(zip(df_flow.from_node_id, df_flow.to_node_id))\ndf_flow[\"flow_m3d\"] = df_flow.flow * 86400\nax = df_flow.pivot_table(index=\"time\", columns=\"edge\", values=\"flow_m3d\").plot()\nax.legend(bbox_to_anchor=(1.3, 1), title=\"Edge\")\n\n<matplotlib.legend.Legend at 0x7fd82b3b9850>\n\n\n\n\n\n\ntype(df_flow)\n\npandas.core.frame.DataFrame\n\n\n\n\n3 Model with discrete control\nThe model constructed below consists of a single basin which slowly drains trough a TabulatedRatingCurve, but is held within a range around a target level (setpoint) by two connected pumps. These two pumps behave like a reversible pump. When pumping can be done in only one direction, and the other direction is only possible under gravity, use an Outlet for that direction.\nSet up the nodes:\n\nxy = np.array(\n [\n (0.0, 0.0), # 1: Basin\n (1.0, 1.0), # 2: Pump\n (1.0, -1.0), # 3: Pump\n (2.0, 0.0), # 4: LevelBoundary\n (-1.0, 0.0), # 5: TabulatedRatingCurve\n (-2.0, 0.0), # 6: Terminal\n (1.0, 0.0), # 7: DiscreteControl\n ]\n)\n\nnode_xy = gpd.points_from_xy(x=xy[:, 0], y=xy[:, 1])\n\nnode_type = [\n \"Basin\",\n \"Pump\",\n \"Pump\",\n \"LevelBoundary\",\n \"TabulatedRatingCurve\",\n \"Terminal\",\n \"DiscreteControl\",\n]\n\n# Make sure the feature id starts at 1: explicitly give an index.\nnode = ribasim.Node(\n df=gpd.GeoDataFrame(\n data={\"type\": node_type},\n index=pd.Index(np.arange(len(xy)) + 1, name=\"fid\"),\n geometry=node_xy,\n crs=\"EPSG:28992\",\n )\n)\n\nSetup the edges:\n\nfrom_id = np.array([1, 3, 4, 2, 1, 5, 7, 7], dtype=np.int64)\nto_id = np.array([3, 4, 2, 1, 5, 6, 2, 3], dtype=np.int64)\n\nedge_type = 6 * [\"flow\"] + 2 * [\"control\"]\n\nlines = node.geometry_from_connectivity(from_id, to_id)\nedge = ribasim.Edge(\n df=gpd.GeoDataFrame(\n data={\"from_node_id\": from_id, \"to_node_id\": to_id, \"edge_type\": edge_type},\n geometry=lines,\n crs=\"EPSG:28992\",\n )\n)\n\nSetup the basins:\n\nprofile = pd.DataFrame(\n data={\n \"node_id\": [1, 1],\n \"area\": [1000.0, 1000.0],\n \"level\": [0.0, 1.0],\n }\n)\n\nstatic = pd.DataFrame(\n data={\n \"node_id\": [1],\n \"drainage\": [0.0],\n \"potential_evaporation\": [0.0],\n \"infiltration\": [0.0],\n \"precipitation\": [0.0],\n \"urban_runoff\": [0.0],\n }\n)\n\nstate = pd.DataFrame(data={\"node_id\": [1], \"level\": [20.0]})\n\nbasin = ribasim.Basin(profile=profile, static=static, state=state)\n\nSetup the discrete control:\n\ncondition = pd.DataFrame(\n data={\n \"node_id\": 3 * [7],\n \"listen_feature_id\": 3 * [1],\n \"variable\": 3 * [\"level\"],\n \"greater_than\": [5.0, 10.0, 15.0], # min, setpoint, max\n }\n)\n\nlogic = pd.DataFrame(\n data={\n \"node_id\": 5 * [7],\n \"truth_state\": [\"FFF\", \"U**\", \"T*F\", \"**D\", \"TTT\"],\n \"control_state\": [\"in\", \"in\", \"none\", \"out\", \"out\"],\n }\n)\n\ndiscrete_control = ribasim.DiscreteControl(condition=condition, logic=logic)\n\nThe above control logic can be summarized as follows: - If the level gets above the maximum, activate the control state “out” until the setpoint is reached; - If the level gets below the minimum, active the control state “in” until the setpoint is reached; - Otherwise activate the control state “none”.\nSetup the pump:\n\npump = ribasim.Pump(\n static=pd.DataFrame(\n data={\n \"node_id\": 3 * [2] + 3 * [3],\n \"control_state\": 2 * [\"none\", \"in\", \"out\"],\n \"flow_rate\": [0.0, 2e-3, 0.0, 0.0, 0.0, 2e-3],\n }\n )\n)\n\nThe pump data defines the following:\n\n\n\nControl state\nPump #2 flow rate (m/s)\nPump #3 flow rate (m/s)\n\n\n\n\n“none”\n0.0\n0.0\n\n\n“in”\n2e-3\n0.0\n\n\n“out”\n0.0\n2e-3\n\n\n\nSetup the level boundary:\n\nlevel_boundary = ribasim.LevelBoundary(\n static=pd.DataFrame(data={\"node_id\": [4], \"level\": [10.0]})\n)\n\nSetup the rating curve:\n\nrating_curve = ribasim.TabulatedRatingCurve(\n static=pd.DataFrame(\n data={\"node_id\": 2 * [5], \"level\": [2.0, 15.0], \"flow_rate\": [0.0, 1e-3]}\n )\n)\n\nSetup the terminal:\n\nterminal = ribasim.Terminal(static=pd.DataFrame(data={\"node_id\": [6]}))\n\nSetup a model:\n\nmodel = ribasim.Model(\n network=ribasim.Network(\n node=node,\n edge=edge,\n ),\n basin=basin,\n pump=pump,\n level_boundary=level_boundary,\n tabulated_rating_curve=rating_curve,\n terminal=terminal,\n discrete_control=discrete_control,\n starttime=\"2020-01-01 00:00:00\",\n endtime=\"2021-01-01 00:00:00\",\n)\n\nLet’s take a look at the model:\n\nmodel.plot()\n\n<Axes: >\n\n\n\n\n\nListen edges are plotted with a dashed line since they are not present in the “Edge / static” schema but only in the “Control / condition” schema.\n\ndatadir = Path(\"data\")\nmodel.write(datadir / \"level_setpoint_with_minmax/ribasim.toml\")\n\nPosixPath('data/level_setpoint_with_minmax/ribasim.toml')\n\n\nNow run the model with level_setpoint_with_minmax/ribasim.toml. After running the model, read back the results:\n\nfrom matplotlib.dates import date2num\n\ndf_basin = pd.read_feather(datadir / \"level_setpoint_with_minmax/results/basin.arrow\")\ndf_basin_wide = df_basin.pivot_table(\n index=\"time\", columns=\"node_id\", values=[\"storage\", \"level\"]\n)\n\nax = df_basin_wide[\"level\"].plot()\n\ngreater_than = model.discrete_control.condition.df.greater_than\n\nax.hlines(\n greater_than,\n df_basin.time[0],\n df_basin.time.max(),\n lw=1,\n ls=\"--\",\n color=\"k\",\n)\n\ndf_control = pd.read_feather(\n datadir / \"level_setpoint_with_minmax/results/control.arrow\"\n)\n\ny_min, y_max = ax.get_ybound()\nax.fill_between(df_control.time[:2], 2 * [y_min], 2 * [y_max], alpha=0.2, color=\"C0\")\nax.fill_between(df_control.time[2:4], 2 * [y_min], 2 * [y_max], alpha=0.2, color=\"C0\")\n\nax.set_xticks(\n date2num(df_control.time).tolist(),\n df_control.control_state.tolist(),\n rotation=50,\n)\n\nax.set_yticks(greater_than, [\"min\", \"setpoint\", \"max\"])\nax.set_ylabel(\"level\")\nplt.show()\n\n\n\n\nThe highlighted regions show where a pump is active.\nLet’s print an overview of what happened with control:\n\nmodel.print_discrete_control_record(\n datadir / \"level_setpoint_with_minmax/results/control.arrow\"\n)\n\n0. At 2020-01-01 00:00:00 the control node with ID 7 reached truth state TTT:\n For node ID 1 (Basin): level > 5.0\n For node ID 1 (Basin): level > 10.0\n For node ID 1 (Basin): level > 15.0\n\n This yielded control state \"out\":\n For node ID 2 (Pump): flow_rate = 0.0\n For node ID 3 (Pump): flow_rate = 0.002\n\n1. At 2020-02-08 19:02:21.861000 the control node with ID 7 reached truth state TFF:\n For node ID 1 (Basin): level > 5.0\n For node ID 1 (Basin): level < 10.0\n For node ID 1 (Basin): level < 15.0\n\n This yielded control state \"none\":\n For node ID 2 (Pump): flow_rate = 0.0\n For node ID 3 (Pump): flow_rate = 0.0\n\n2. At 2020-07-05 08:56:10.319000 the control node with ID 7 reached truth state FFF:\n For node ID 1 (Basin): level < 5.0\n For node ID 1 (Basin): level < 10.0\n For node ID 1 (Basin): level < 15.0\n\n This yielded control state \"in\":\n For node ID 2 (Pump): flow_rate = 0.002\n For node ID 3 (Pump): flow_rate = 0.0\n\n3. At 2020-08-11 06:05:15.592000 the control node with ID 7 reached truth state TTF:\n For node ID 1 (Basin): level > 5.0\n For node ID 1 (Basin): level > 10.0\n For node ID 1 (Basin): level < 15.0\n\n This yielded control state \"none\":\n For node ID 2 (Pump): flow_rate = 0.0\n For node ID 3 (Pump): flow_rate = 0.0\n\n\n\nNote that crossing direction specific truth states (containing “U”, “D”) are not present in this overview even though they are part of the control logic. This is because in the control logic for this model these truth states are only used to sustain control states, while the overview only shows changes in control states.\n\n\n4 Model with PID control\nSet up the nodes:\n\nxy = np.array(\n [\n (0.0, 0.0), # 1: FlowBoundary\n (1.0, 0.0), # 2: Basin\n (2.0, 0.5), # 3: Pump\n (3.0, 0.0), # 4: LevelBoundary\n (1.5, 1.0), # 5: PidControl\n (2.0, -0.5), # 6: outlet\n (1.5, -1.0), # 7: PidControl\n ]\n)\n\nnode_xy = gpd.points_from_xy(x=xy[:, 0], y=xy[:, 1])\n\nnode_type = [\n \"FlowBoundary\",\n \"Basin\",\n \"Pump\",\n \"LevelBoundary\",\n \"PidControl\",\n \"Outlet\",\n \"PidControl\",\n]\n\n# Make sure the feature id starts at 1: explicitly give an index.\nnode = ribasim.Node(\n df=gpd.GeoDataFrame(\n data={\"type\": node_type},\n index=pd.Index(np.arange(len(xy)) + 1, name=\"fid\"),\n geometry=node_xy,\n crs=\"EPSG:28992\",\n )\n)\n\nSetup the edges:\n\nfrom_id = np.array([1, 2, 3, 4, 6, 5, 7], dtype=np.int64)\nto_id = np.array([2, 3, 4, 6, 2, 3, 6], dtype=np.int64)\n\nlines = node.geometry_from_connectivity(from_id, to_id)\nedge = ribasim.Edge(\n df=gpd.GeoDataFrame(\n data={\n \"from_node_id\": from_id,\n \"to_node_id\": to_id,\n \"edge_type\": 5 * [\"flow\"] + 2 * [\"control\"],\n },\n geometry=lines,\n crs=\"EPSG:28992\",\n )\n)\n\nSetup the basins:\n\nprofile = pd.DataFrame(\n data={\"node_id\": [2, 2], \"level\": [0.0, 1.0], \"area\": [1000.0, 1000.0]}\n)\n\nstatic = pd.DataFrame(\n data={\n \"node_id\": [2],\n \"drainage\": [0.0],\n \"potential_evaporation\": [0.0],\n \"infiltration\": [0.0],\n \"precipitation\": [0.0],\n \"urban_runoff\": [0.0],\n }\n)\n\nstate = pd.DataFrame(\n data={\n \"node_id\": [2],\n \"level\": [6.0],\n }\n)\n\nbasin = ribasim.Basin(profile=profile, static=static, state=state)\n\nSetup the pump:\n\npump = ribasim.Pump(\n static=pd.DataFrame(\n data={\n \"node_id\": [3],\n \"flow_rate\": [0.0], # Will be overwritten by PID controller\n }\n )\n)\n\nSetup the outlet:\n\noutlet = ribasim.Outlet(\n static=pd.DataFrame(\n data={\n \"node_id\": [6],\n \"flow_rate\": [0.0], # Will be overwritten by PID controller\n }\n )\n)\n\nSetup flow boundary:\n\nflow_boundary = ribasim.FlowBoundary(\n static=pd.DataFrame(data={\"node_id\": [1], \"flow_rate\": [1e-3]})\n)\n\nSetup flow boundary:\n\nlevel_boundary = ribasim.LevelBoundary(\n static=pd.DataFrame(\n data={\n \"node_id\": [4],\n \"level\": [1.0], # Not relevant\n }\n )\n)\n\nSetup PID control:\n\npid_control = ribasim.PidControl(\n time=pd.DataFrame(\n data={\n \"node_id\": 4 * [5, 7],\n \"time\": [\n \"2020-01-01 00:00:00\",\n \"2020-01-01 00:00:00\",\n \"2020-05-01 00:00:00\",\n \"2020-05-01 00:00:00\",\n \"2020-07-01 00:00:00\",\n \"2020-07-01 00:00:00\",\n \"2020-12-01 00:00:00\",\n \"2020-12-01 00:00:00\",\n ],\n \"listen_node_id\": 4 * [2, 2],\n \"target\": [5.0, 5.0, 5.0, 5.0, 7.5, 7.5, 7.5, 7.5],\n \"proportional\": 4 * [-1e-3, 1e-3],\n \"integral\": 4 * [-1e-7, 1e-7],\n \"derivative\": 4 * [0.0, 0.0],\n }\n )\n)\n\nNote that the coefficients for the pump and the outlet are equal in magnitude but opposite in sign. This way the pump and the outlet equally work towards the same goal, while having opposite effects on the controlled basin due to their connectivity to this basin.\nSetup a model:\n\nmodel = ribasim.Model(\n network=ribasim.Network(\n node=node,\n edge=edge,\n ),\n basin=basin,\n flow_boundary=flow_boundary,\n level_boundary=level_boundary,\n pump=pump,\n outlet=outlet,\n pid_control=pid_control,\n starttime=\"2020-01-01 00:00:00\",\n endtime=\"2020-12-01 00:00:00\",\n)\n\nLet’s take a look at the model:\n\nmodel.plot()\n\n<Axes: >\n\n\n\n\n\nWrite the model to a TOML and GeoPackage:\n\ndatadir = Path(\"data\")\nmodel.write(datadir / \"pid_control/ribasim.toml\")\n\nPosixPath('data/pid_control/ribasim.toml')\n\n\nNow run the model with ribasim pid_control/ribasim.toml. After running the model, read back the results:\n\nfrom matplotlib.dates import date2num\n\ndf_basin = pd.read_feather(datadir / \"pid_control/results/basin.arrow\")\ndf_basin_wide = df_basin.pivot_table(\n index=\"time\", columns=\"node_id\", values=[\"storage\", \"level\"]\n)\nax = df_basin_wide[\"level\"].plot()\nax.set_ylabel(\"level [m]\")\n\n# Plot target level\ntarget_levels = model.pid_control.time.df.target.to_numpy()[:4]\ntimes = date2num(model.pid_control.time.df.time)[:4]\nax.plot(times, target_levels, color=\"k\", ls=\":\", label=\"target level\")\npass\n\n\n\n\n\n\n5 Model with allocation\nSetup the nodes:\n\nxy = np.array(\n [\n (0.0, 0.0), # 1: FlowBoundary\n (1.0, 0.0), # 2: Basin\n (1.0, 1.0), # 3: User\n (2.0, 0.0), # 4: LinearResistance\n (3.0, 0.0), # 5: Basin\n (3.0, 1.0), # 6: User\n (4.0, 0.0), # 7: TabulatedRatingCurve\n (4.5, 0.0), # 8: FractionalFlow\n (4.5, 0.5), # 9: FractionalFlow\n (5.0, 0.0), # 10: Terminal\n (4.5, 0.25), # 11: DiscreteControl\n (4.5, 1.0), # 12: Basin\n (5.0, 1.0), # 13: User\n ]\n)\nnode_xy = gpd.points_from_xy(x=xy[:, 0], y=xy[:, 1])\n\nnode_type = [\n \"FlowBoundary\",\n \"Basin\",\n \"User\",\n \"LinearResistance\",\n \"Basin\",\n \"User\",\n \"TabulatedRatingCurve\",\n \"FractionalFlow\",\n \"FractionalFlow\",\n \"Terminal\",\n \"DiscreteControl\",\n \"Basin\",\n \"User\",\n]\n\n# All nodes belong to allocation network id 1\nnode = ribasim.Node(\n df=gpd.GeoDataFrame(\n data={\"type\": node_type, \"allocation_network_id\": 1},\n index=pd.Index(np.arange(len(xy)) + 1, name=\"fid\"),\n geometry=node_xy,\n crs=\"EPSG:28992\",\n )\n)\n\nSetup the edges:\n\nfrom_id = np.array(\n [1, 2, 2, 4, 5, 5, 7, 3, 6, 7, 8, 9, 12, 13, 11, 11],\n dtype=np.int64,\n)\nto_id = np.array(\n [2, 3, 4, 5, 6, 7, 8, 2, 5, 9, 10, 12, 13, 10, 8, 9],\n dtype=np.int64,\n)\n# Denote the first edge, 1 => 2, as a source edge for\n# allocation network 1\nallocation_network_id = len(from_id) * [None]\nallocation_network_id[0] = 1\nlines = node.geometry_from_connectivity(from_id, to_id)\nedge = ribasim.Edge(\n df=gpd.GeoDataFrame(\n data={\n \"from_node_id\": from_id,\n \"to_node_id\": to_id,\n \"edge_type\": (len(from_id) - 2) * [\"flow\"] + 2 * [\"control\"],\n \"allocation_network_id\": allocation_network_id,\n },\n geometry=lines,\n crs=\"EPSG:28992\",\n )\n)\n\nSetup the basins:\n\nprofile = pd.DataFrame(\n data={\n \"node_id\": [2, 2, 5, 5, 12, 12],\n \"area\": 300_000.0,\n \"level\": 3 * [0.0, 1.0],\n }\n)\n\nstatic = pd.DataFrame(\n data={\n \"node_id\": [2, 5, 12],\n \"drainage\": 0.0,\n \"potential_evaporation\": 0.0,\n \"infiltration\": 0.0,\n \"precipitation\": 0.0,\n \"urban_runoff\": 0.0,\n }\n)\n\nstate = pd.DataFrame(data={\"node_id\": [2, 5, 12], \"level\": 1.0})\n\nbasin = ribasim.Basin(profile=profile, static=static, state=state)\n\nSetup the flow boundary:\n\nflow_boundary = ribasim.FlowBoundary(\n static=pd.DataFrame(\n data={\n \"node_id\": [1],\n \"flow_rate\": 2.0,\n }\n )\n)\n\nSetup the linear resistance:\n\nlinear_resistance = ribasim.LinearResistance(\n static=pd.DataFrame(\n data={\n \"node_id\": [4],\n \"resistance\": 0.06,\n }\n )\n)\n\nSetup the tabulated rating curve:\n\ntabulated_rating_curve = ribasim.TabulatedRatingCurve(\n static=pd.DataFrame(\n data={\n \"node_id\": 7,\n \"level\": [0.0, 0.5, 1.0],\n \"flow_rate\": [0.0, 0.0, 2.0],\n }\n )\n)\n\nSetup the fractional flow:\n\nfractional_flow = ribasim.FractionalFlow(\n static=pd.DataFrame(\n data={\n \"node_id\": [8, 8, 9, 9],\n \"fraction\": [0.6, 0.9, 0.4, 0.1],\n \"control_state\": [\"divert\", \"close\", \"divert\", \"close\"],\n }\n )\n)\n\nSetup the terminal:\n\nterminal = ribasim.Terminal(\n static=pd.DataFrame(\n data={\n \"node_id\": [10],\n }\n )\n)\n\nSetup the discrete control:\n\ncondition = pd.DataFrame(\n data={\n \"node_id\": [11],\n \"listen_feature_id\": 5,\n \"variable\": \"level\",\n \"greater_than\": 0.52,\n }\n)\n\nlogic = pd.DataFrame(\n data={\n \"node_id\": 11,\n \"truth_state\": [\"T\", \"F\"],\n \"control_state\": [\"divert\", \"close\"],\n }\n)\n\ndiscrete_control = ribasim.DiscreteControl(condition=condition, logic=logic)\n\nSetup the users:\n\nuser = ribasim.User(\n static=pd.DataFrame(\n data={\n \"node_id\": [6, 13],\n \"demand\": [1.5, 1.0],\n \"return_factor\": 0.0,\n \"min_level\": -1.0,\n \"priority\": [1, 3],\n }\n ),\n time=pd.DataFrame(\n data={\n \"node_id\": [3, 3, 3, 3],\n \"demand\": [0.0, 1.0, 1.2, 1.2],\n \"priority\": [1, 1, 2, 2],\n \"return_factor\": 0.0,\n \"min_level\": -1.0,\n \"time\": 2 * [\"2020-01-01 00:00:00\", \"2020-01-20 00:00:00\"],\n }\n ),\n)\n\nSetup the allocation:\n\nallocation = ribasim.Allocation(use_allocation=True, timestep=86400)\n\nSetup a model:\n\nmodel = ribasim.Model(\n network=ribasim.Network(\n node=node,\n edge=edge,\n ),\n basin=basin,\n flow_boundary=flow_boundary,\n linear_resistance=linear_resistance,\n tabulated_rating_curve=tabulated_rating_curve,\n terminal=terminal,\n user=user,\n discrete_control=discrete_control,\n fractional_flow=fractional_flow,\n allocation=allocation,\n starttime=\"2020-01-01 00:00:00\",\n endtime=\"2020-01-20 00:00:00\",\n)\n\nLet’s take a look at the model:\n\nmodel.plot()\n\n<Axes: >\n\n\n\n\n\nWrite the model to a TOML and GeoPackage:\n\ndatadir = Path(\"data\")\nmodel.write(datadir / \"allocation_example/ribasim.toml\")\n\nPosixPath('data/allocation_example/ribasim.toml')\n\n\nNow run the model with ribasim allocation_example/ribasim.toml. After running the model, read back the results:\n\nimport matplotlib.ticker as plticker\n\ndf_allocation = pd.read_feather(datadir / \"allocation_example/results/allocation.arrow\")\ndf_allocation_wide = df_allocation.pivot_table(\n index=\"time\",\n columns=[\"user_node_id\", \"priority\"],\n values=[\"demand\", \"allocated\", \"abstracted\"],\n)\ndf_allocation_wide = df_allocation_wide.loc[:, (df_allocation_wide != 0).any(axis=0)]\n\nfig, axs = plt.subplots(1, 3, figsize=(8, 5))\nfig.suptitle(f\"Objective type: {model.allocation.objective_type}\", fontweight=\"bold\")\n\ndf_allocation_wide[\"demand\"].plot(ax=axs[0], ls=\":\")\ndf_allocation_wide[\"allocated\"].plot(ax=axs[1], ls=\"--\")\ndf_allocation_wide[\"abstracted\"].plot(ax=axs[2])\n\nfig.tight_layout()\nloc = plticker.MultipleLocator(2)\n\naxs[0].set_ylabel(\"level [m]\")\n\nfor ax, title in zip(axs, [\"Demand\", \"Allocated\", \"Abstracted\"]):\n ax.set_title(title)\n ax.set_ylim(0.0, 1.6)\n ax.xaxis.set_major_locator(loc)\n\n\n\n\nSome things to note about this plot:\n\nAbstraction behaves somewhat erratically at the start of the simulation. This is because allocation is based on flows computed in the physical layer, and at the start of the simulation these are not known yet.\nAlthough there is a plotted line for abstraction per priority, abstraction is actually accumulated over all priorities per user.\n\n\ndf_basin = pd.read_feather(datadir / \"allocation_example/results/basin.arrow\")\ndf_basin_wide = df_basin.pivot_table(\n index=\"time\", columns=\"node_id\", values=[\"storage\", \"level\"]\n)\n\nax = df_basin_wide[\"level\"].plot()\nax.set_title(\"Basin levels\")\nax.set_ylabel(\"level [m]\")\n\nText(0, 0.5, 'level [m]')" + "text": "1 Basic model with static forcing\n\nfrom pathlib import Path\n\nimport geopandas as gpd\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nimport ribasim\n\nSetup the basins:\n\nprofile = pd.DataFrame(\n data={\n \"node_id\": [1, 1, 3, 3, 6, 6, 9, 9],\n \"area\": [0.01, 1000.0] * 4,\n \"level\": [0.0, 1.0] * 4,\n }\n)\n\n# Convert steady forcing to m/s\n# 2 mm/d precipitation, 1 mm/d evaporation\nseconds_in_day = 24 * 3600\nprecipitation = 0.002 / seconds_in_day\nevaporation = 0.001 / seconds_in_day\n\nstatic = pd.DataFrame(\n data={\n \"node_id\": [0],\n \"drainage\": [0.0],\n \"potential_evaporation\": [evaporation],\n \"infiltration\": [0.0],\n \"precipitation\": [precipitation],\n \"urban_runoff\": [0.0],\n }\n)\nstatic = static.iloc[[0, 0, 0, 0]]\nstatic[\"node_id\"] = [1, 3, 6, 9]\n\nbasin = ribasim.Basin(profile=profile, static=static)\n\nSetup linear resistance:\n\nlinear_resistance = ribasim.LinearResistance(\n static=pd.DataFrame(\n data={\"node_id\": [10, 12], \"resistance\": [5e3, (3600.0 * 24) / 100.0]}\n )\n)\n\nSetup Manning resistance:\n\nmanning_resistance = ribasim.ManningResistance(\n static=pd.DataFrame(\n data={\n \"node_id\": [2],\n \"length\": [900.0],\n \"manning_n\": [0.04],\n \"profile_width\": [6.0],\n \"profile_slope\": [3.0],\n }\n )\n)\n\nSet up a rating curve node:\n\n# Discharge: lose 1% of storage volume per day at storage = 1000.0.\nq1000 = 1000.0 * 0.01 / seconds_in_day\n\nrating_curve = ribasim.TabulatedRatingCurve(\n static=pd.DataFrame(\n data={\n \"node_id\": [4, 4],\n \"level\": [0.0, 1.0],\n \"flow_rate\": [0.0, q1000],\n }\n )\n)\n\nSetup fractional flows:\n\nfractional_flow = ribasim.FractionalFlow(\n static=pd.DataFrame(\n data={\n \"node_id\": [5, 8, 13],\n \"fraction\": [0.3, 0.6, 0.1],\n }\n )\n)\n\nSetup pump:\n\npump = ribasim.Pump(\n static=pd.DataFrame(\n data={\n \"node_id\": [7],\n \"flow_rate\": [0.5 / 3600],\n }\n )\n)\n\nSetup level boundary:\n\nlevel_boundary = ribasim.LevelBoundary(\n static=pd.DataFrame(\n data={\n \"node_id\": [11, 17],\n \"level\": [0.5, 1.5],\n }\n )\n)\n\nSetup flow boundary:\n\nflow_boundary = ribasim.FlowBoundary(\n static=pd.DataFrame(\n data={\n \"node_id\": [15, 16],\n \"flow_rate\": [1e-4, 1e-4],\n }\n )\n)\n\nSetup terminal:\n\nterminal = ribasim.Terminal(\n static=pd.DataFrame(\n data={\n \"node_id\": [14],\n }\n )\n)\n\nSet up the nodes:\n\nxy = np.array(\n [\n (0.0, 0.0), # 1: Basin,\n (1.0, 0.0), # 2: ManningResistance\n (2.0, 0.0), # 3: Basin\n (3.0, 0.0), # 4: TabulatedRatingCurve\n (3.0, 1.0), # 5: FractionalFlow\n (3.0, 2.0), # 6: Basin\n (4.0, 1.0), # 7: Pump\n (4.0, 0.0), # 8: FractionalFlow\n (5.0, 0.0), # 9: Basin\n (6.0, 0.0), # 10: LinearResistance\n (2.0, 2.0), # 11: LevelBoundary\n (2.0, 1.0), # 12: LinearResistance\n (3.0, -1.0), # 13: FractionalFlow\n (3.0, -2.0), # 14: Terminal\n (3.0, 3.0), # 15: FlowBoundary\n (0.0, 1.0), # 16: FlowBoundary\n (6.0, 1.0), # 17: LevelBoundary\n ]\n)\nnode_xy = gpd.points_from_xy(x=xy[:, 0], y=xy[:, 1])\n\nnode_id, node_type = ribasim.Node.node_ids_and_types(\n basin,\n manning_resistance,\n rating_curve,\n pump,\n fractional_flow,\n linear_resistance,\n level_boundary,\n flow_boundary,\n terminal,\n)\n\n# Make sure the feature id starts at 1: explicitly give an index.\nnode = ribasim.Node(\n df=gpd.GeoDataFrame(\n data={\"type\": node_type},\n index=pd.Index(node_id, name=\"fid\"),\n geometry=node_xy,\n crs=\"EPSG:28992\",\n )\n)\n\nSetup the edges:\n\nfrom_id = np.array(\n [1, 2, 3, 4, 4, 5, 6, 8, 7, 9, 11, 12, 4, 13, 15, 16, 10], dtype=np.int64\n)\nto_id = np.array(\n [2, 3, 4, 5, 8, 6, 7, 9, 9, 10, 12, 3, 13, 14, 6, 1, 17], dtype=np.int64\n)\nlines = node.geometry_from_connectivity(from_id, to_id)\nedge = ribasim.Edge(\n df=gpd.GeoDataFrame(\n data={\n \"from_node_id\": from_id,\n \"to_node_id\": to_id,\n \"edge_type\": len(from_id) * [\"flow\"],\n },\n geometry=lines,\n crs=\"EPSG:28992\",\n )\n)\n\nSetup a model:\n\nmodel = ribasim.Model(\n network=ribasim.Network(\n node=node,\n edge=edge,\n ),\n basin=basin,\n level_boundary=level_boundary,\n flow_boundary=flow_boundary,\n pump=pump,\n linear_resistance=linear_resistance,\n manning_resistance=manning_resistance,\n tabulated_rating_curve=rating_curve,\n fractional_flow=fractional_flow,\n terminal=terminal,\n starttime=\"2020-01-01 00:00:00\",\n endtime=\"2021-01-01 00:00:00\",\n)\n\nLet’s take a look at the model:\n\nmodel.plot()\n\n<Axes: >\n\n\n\n\n\nWrite the model to a TOML and GeoPackage:\n\ndatadir = Path(\"data\")\nmodel.write(datadir / \"basic/ribasim.toml\")\n\nPosixPath('data/basic/ribasim.toml')\n\n\n\n\n2 Update the basic model with transient forcing\nThis assumes you have already created the basic model with static forcing.\n\nimport numpy as np\nimport pandas as pd\nimport ribasim\nimport xarray as xr\n\n\nmodel = ribasim.Model(filepath=datadir / \"basic/ribasim.toml\")\n\n\ntime = pd.date_range(model.starttime, model.endtime)\nday_of_year = time.day_of_year.to_numpy()\nseconds_per_day = 24 * 60 * 60\nevaporation = (\n (-1.0 * np.cos(day_of_year / 365.0 * 2 * np.pi) + 1.0) * 0.0025 / seconds_per_day\n)\nrng = np.random.default_rng(seed=0)\nprecipitation = (\n rng.lognormal(mean=-1.0, sigma=1.7, size=time.size) * 0.001 / seconds_per_day\n)\n\nWe’ll use xarray to easily broadcast the values.\n\ntimeseries = (\n pd.DataFrame(\n data={\n \"node_id\": 1,\n \"time\": pd.date_range(model.starttime, model.endtime),\n \"drainage\": 0.0,\n \"potential_evaporation\": evaporation,\n \"infiltration\": 0.0,\n \"precipitation\": precipitation,\n \"urban_runoff\": 0.0,\n }\n )\n .set_index(\"time\")\n .to_xarray()\n)\n\nbasin_ids = model.basin.static.df[\"node_id\"].to_numpy()\nbasin_nodes = xr.DataArray(\n np.ones(len(basin_ids)), coords={\"node_id\": basin_ids}, dims=[\"node_id\"]\n)\nforcing = (timeseries * basin_nodes).to_dataframe().reset_index()\n\n\nstate = pd.DataFrame(\n data={\n \"node_id\": basin_ids,\n \"level\": 1.4,\n }\n)\n\n\nmodel.basin.time.df = forcing\nmodel.basin.state.df = state\n\n\nmodel.write(datadir / \"basic_transient/ribasim.toml\")\n\nPosixPath('data/basic_transient/ribasim.toml')\n\n\nNow run the model with ribasim basic_transient/ribasim.toml. After running the model, read back the results:\n\ndf_basin = pd.read_feather(datadir / \"basic_transient/results/basin.arrow\")\ndf_basin_wide = df_basin.pivot_table(\n index=\"time\", columns=\"node_id\", values=[\"storage\", \"level\"]\n)\ndf_basin_wide[\"level\"].plot()\n\n<Axes: xlabel='time'>\n\n\n\n\n\n\ndf_flow = pd.read_feather(datadir / \"basic_transient/results/flow.arrow\")\ndf_flow[\"edge\"] = list(zip(df_flow.from_node_id, df_flow.to_node_id))\ndf_flow[\"flow_m3d\"] = df_flow.flow * 86400\nax = df_flow.pivot_table(index=\"time\", columns=\"edge\", values=\"flow_m3d\").plot()\nax.legend(bbox_to_anchor=(1.3, 1), title=\"Edge\")\n\n<matplotlib.legend.Legend at 0x7fabd80d6790>\n\n\n\n\n\n\ntype(df_flow)\n\npandas.core.frame.DataFrame\n\n\n\n\n3 Model with discrete control\nThe model constructed below consists of a single basin which slowly drains trough a TabulatedRatingCurve, but is held within a range around a target level (setpoint) by two connected pumps. These two pumps behave like a reversible pump. When pumping can be done in only one direction, and the other direction is only possible under gravity, use an Outlet for that direction.\nSet up the nodes:\n\nxy = np.array(\n [\n (0.0, 0.0), # 1: Basin\n (1.0, 1.0), # 2: Pump\n (1.0, -1.0), # 3: Pump\n (2.0, 0.0), # 4: LevelBoundary\n (-1.0, 0.0), # 5: TabulatedRatingCurve\n (-2.0, 0.0), # 6: Terminal\n (1.0, 0.0), # 7: DiscreteControl\n ]\n)\n\nnode_xy = gpd.points_from_xy(x=xy[:, 0], y=xy[:, 1])\n\nnode_type = [\n \"Basin\",\n \"Pump\",\n \"Pump\",\n \"LevelBoundary\",\n \"TabulatedRatingCurve\",\n \"Terminal\",\n \"DiscreteControl\",\n]\n\n# Make sure the feature id starts at 1: explicitly give an index.\nnode = ribasim.Node(\n df=gpd.GeoDataFrame(\n data={\"type\": node_type},\n index=pd.Index(np.arange(len(xy)) + 1, name=\"fid\"),\n geometry=node_xy,\n crs=\"EPSG:28992\",\n )\n)\n\nSetup the edges:\n\nfrom_id = np.array([1, 3, 4, 2, 1, 5, 7, 7], dtype=np.int64)\nto_id = np.array([3, 4, 2, 1, 5, 6, 2, 3], dtype=np.int64)\n\nedge_type = 6 * [\"flow\"] + 2 * [\"control\"]\n\nlines = node.geometry_from_connectivity(from_id, to_id)\nedge = ribasim.Edge(\n df=gpd.GeoDataFrame(\n data={\"from_node_id\": from_id, \"to_node_id\": to_id, \"edge_type\": edge_type},\n geometry=lines,\n crs=\"EPSG:28992\",\n )\n)\n\nSetup the basins:\n\nprofile = pd.DataFrame(\n data={\n \"node_id\": [1, 1],\n \"area\": [1000.0, 1000.0],\n \"level\": [0.0, 1.0],\n }\n)\n\nstatic = pd.DataFrame(\n data={\n \"node_id\": [1],\n \"drainage\": [0.0],\n \"potential_evaporation\": [0.0],\n \"infiltration\": [0.0],\n \"precipitation\": [0.0],\n \"urban_runoff\": [0.0],\n }\n)\n\nstate = pd.DataFrame(data={\"node_id\": [1], \"level\": [20.0]})\n\nbasin = ribasim.Basin(profile=profile, static=static, state=state)\n\nSetup the discrete control:\n\ncondition = pd.DataFrame(\n data={\n \"node_id\": 3 * [7],\n \"listen_feature_id\": 3 * [1],\n \"variable\": 3 * [\"level\"],\n \"greater_than\": [5.0, 10.0, 15.0], # min, setpoint, max\n }\n)\n\nlogic = pd.DataFrame(\n data={\n \"node_id\": 5 * [7],\n \"truth_state\": [\"FFF\", \"U**\", \"T*F\", \"**D\", \"TTT\"],\n \"control_state\": [\"in\", \"in\", \"none\", \"out\", \"out\"],\n }\n)\n\ndiscrete_control = ribasim.DiscreteControl(condition=condition, logic=logic)\n\nThe above control logic can be summarized as follows: - If the level gets above the maximum, activate the control state “out” until the setpoint is reached; - If the level gets below the minimum, active the control state “in” until the setpoint is reached; - Otherwise activate the control state “none”.\nSetup the pump:\n\npump = ribasim.Pump(\n static=pd.DataFrame(\n data={\n \"node_id\": 3 * [2] + 3 * [3],\n \"control_state\": 2 * [\"none\", \"in\", \"out\"],\n \"flow_rate\": [0.0, 2e-3, 0.0, 0.0, 0.0, 2e-3],\n }\n )\n)\n\nThe pump data defines the following:\n\n\n\nControl state\nPump #2 flow rate (m/s)\nPump #3 flow rate (m/s)\n\n\n\n\n“none”\n0.0\n0.0\n\n\n“in”\n2e-3\n0.0\n\n\n“out”\n0.0\n2e-3\n\n\n\nSetup the level boundary:\n\nlevel_boundary = ribasim.LevelBoundary(\n static=pd.DataFrame(data={\"node_id\": [4], \"level\": [10.0]})\n)\n\nSetup the rating curve:\n\nrating_curve = ribasim.TabulatedRatingCurve(\n static=pd.DataFrame(\n data={\"node_id\": 2 * [5], \"level\": [2.0, 15.0], \"flow_rate\": [0.0, 1e-3]}\n )\n)\n\nSetup the terminal:\n\nterminal = ribasim.Terminal(static=pd.DataFrame(data={\"node_id\": [6]}))\n\nSetup a model:\n\nmodel = ribasim.Model(\n network=ribasim.Network(\n node=node,\n edge=edge,\n ),\n basin=basin,\n pump=pump,\n level_boundary=level_boundary,\n tabulated_rating_curve=rating_curve,\n terminal=terminal,\n discrete_control=discrete_control,\n starttime=\"2020-01-01 00:00:00\",\n endtime=\"2021-01-01 00:00:00\",\n)\n\nLet’s take a look at the model:\n\nmodel.plot()\n\n<Axes: >\n\n\n\n\n\nListen edges are plotted with a dashed line since they are not present in the “Edge / static” schema but only in the “Control / condition” schema.\n\ndatadir = Path(\"data\")\nmodel.write(datadir / \"level_setpoint_with_minmax/ribasim.toml\")\n\nPosixPath('data/level_setpoint_with_minmax/ribasim.toml')\n\n\nNow run the model with level_setpoint_with_minmax/ribasim.toml. After running the model, read back the results:\n\nfrom matplotlib.dates import date2num\n\ndf_basin = pd.read_feather(datadir / \"level_setpoint_with_minmax/results/basin.arrow\")\ndf_basin_wide = df_basin.pivot_table(\n index=\"time\", columns=\"node_id\", values=[\"storage\", \"level\"]\n)\n\nax = df_basin_wide[\"level\"].plot()\n\ngreater_than = model.discrete_control.condition.df.greater_than\n\nax.hlines(\n greater_than,\n df_basin.time[0],\n df_basin.time.max(),\n lw=1,\n ls=\"--\",\n color=\"k\",\n)\n\ndf_control = pd.read_feather(\n datadir / \"level_setpoint_with_minmax/results/control.arrow\"\n)\n\ny_min, y_max = ax.get_ybound()\nax.fill_between(df_control.time[:2], 2 * [y_min], 2 * [y_max], alpha=0.2, color=\"C0\")\nax.fill_between(df_control.time[2:4], 2 * [y_min], 2 * [y_max], alpha=0.2, color=\"C0\")\n\nax.set_xticks(\n date2num(df_control.time).tolist(),\n df_control.control_state.tolist(),\n rotation=50,\n)\n\nax.set_yticks(greater_than, [\"min\", \"setpoint\", \"max\"])\nax.set_ylabel(\"level\")\nplt.show()\n\n\n\n\nThe highlighted regions show where a pump is active.\nLet’s print an overview of what happened with control:\n\nmodel.print_discrete_control_record(\n datadir / \"level_setpoint_with_minmax/results/control.arrow\"\n)\n\n0. At 2020-01-01 00:00:00 the control node with ID 7 reached truth state TTT:\n For node ID 1 (Basin): level > 5.0\n For node ID 1 (Basin): level > 10.0\n For node ID 1 (Basin): level > 15.0\n\n This yielded control state \"out\":\n For node ID 2 (Pump): active = <NA>, flow_rate = 0.0, min_flow_rate = nan, max_flow_rate = nan\n For node ID 3 (Pump): active = <NA>, flow_rate = 0.002, min_flow_rate = nan, max_flow_rate = nan\n\n1. At 2020-02-08 19:02:21.861000 the control node with ID 7 reached truth state TFF:\n For node ID 1 (Basin): level > 5.0\n For node ID 1 (Basin): level < 10.0\n For node ID 1 (Basin): level < 15.0\n\n This yielded control state \"none\":\n For node ID 2 (Pump): active = <NA>, flow_rate = 0.0, min_flow_rate = nan, max_flow_rate = nan\n For node ID 3 (Pump): active = <NA>, flow_rate = 0.0, min_flow_rate = nan, max_flow_rate = nan\n\n2. At 2020-07-05 08:56:10.319000 the control node with ID 7 reached truth state FFF:\n For node ID 1 (Basin): level < 5.0\n For node ID 1 (Basin): level < 10.0\n For node ID 1 (Basin): level < 15.0\n\n This yielded control state \"in\":\n For node ID 2 (Pump): active = <NA>, flow_rate = 0.002, min_flow_rate = nan, max_flow_rate = nan\n For node ID 3 (Pump): active = <NA>, flow_rate = 0.0, min_flow_rate = nan, max_flow_rate = nan\n\n3. At 2020-08-11 06:05:15.592000 the control node with ID 7 reached truth state TTF:\n For node ID 1 (Basin): level > 5.0\n For node ID 1 (Basin): level > 10.0\n For node ID 1 (Basin): level < 15.0\n\n This yielded control state \"none\":\n For node ID 2 (Pump): active = <NA>, flow_rate = 0.0, min_flow_rate = nan, max_flow_rate = nan\n For node ID 3 (Pump): active = <NA>, flow_rate = 0.0, min_flow_rate = nan, max_flow_rate = nan\n\n\n\nNote that crossing direction specific truth states (containing “U”, “D”) are not present in this overview even though they are part of the control logic. This is because in the control logic for this model these truth states are only used to sustain control states, while the overview only shows changes in control states.\n\n\n4 Model with PID control\nSet up the nodes:\n\nxy = np.array(\n [\n (0.0, 0.0), # 1: FlowBoundary\n (1.0, 0.0), # 2: Basin\n (2.0, 0.5), # 3: Pump\n (3.0, 0.0), # 4: LevelBoundary\n (1.5, 1.0), # 5: PidControl\n (2.0, -0.5), # 6: outlet\n (1.5, -1.0), # 7: PidControl\n ]\n)\n\nnode_xy = gpd.points_from_xy(x=xy[:, 0], y=xy[:, 1])\n\nnode_type = [\n \"FlowBoundary\",\n \"Basin\",\n \"Pump\",\n \"LevelBoundary\",\n \"PidControl\",\n \"Outlet\",\n \"PidControl\",\n]\n\n# Make sure the feature id starts at 1: explicitly give an index.\nnode = ribasim.Node(\n df=gpd.GeoDataFrame(\n data={\"type\": node_type},\n index=pd.Index(np.arange(len(xy)) + 1, name=\"fid\"),\n geometry=node_xy,\n crs=\"EPSG:28992\",\n )\n)\n\nSetup the edges:\n\nfrom_id = np.array([1, 2, 3, 4, 6, 5, 7], dtype=np.int64)\nto_id = np.array([2, 3, 4, 6, 2, 3, 6], dtype=np.int64)\n\nlines = node.geometry_from_connectivity(from_id, to_id)\nedge = ribasim.Edge(\n df=gpd.GeoDataFrame(\n data={\n \"from_node_id\": from_id,\n \"to_node_id\": to_id,\n \"edge_type\": 5 * [\"flow\"] + 2 * [\"control\"],\n },\n geometry=lines,\n crs=\"EPSG:28992\",\n )\n)\n\nSetup the basins:\n\nprofile = pd.DataFrame(\n data={\"node_id\": [2, 2], \"level\": [0.0, 1.0], \"area\": [1000.0, 1000.0]}\n)\n\nstatic = pd.DataFrame(\n data={\n \"node_id\": [2],\n \"drainage\": [0.0],\n \"potential_evaporation\": [0.0],\n \"infiltration\": [0.0],\n \"precipitation\": [0.0],\n \"urban_runoff\": [0.0],\n }\n)\n\nstate = pd.DataFrame(\n data={\n \"node_id\": [2],\n \"level\": [6.0],\n }\n)\n\nbasin = ribasim.Basin(profile=profile, static=static, state=state)\n\nSetup the pump:\n\npump = ribasim.Pump(\n static=pd.DataFrame(\n data={\n \"node_id\": [3],\n \"flow_rate\": [0.0], # Will be overwritten by PID controller\n }\n )\n)\n\nSetup the outlet:\n\noutlet = ribasim.Outlet(\n static=pd.DataFrame(\n data={\n \"node_id\": [6],\n \"flow_rate\": [0.0], # Will be overwritten by PID controller\n }\n )\n)\n\nSetup flow boundary:\n\nflow_boundary = ribasim.FlowBoundary(\n static=pd.DataFrame(data={\"node_id\": [1], \"flow_rate\": [1e-3]})\n)\n\nSetup flow boundary:\n\nlevel_boundary = ribasim.LevelBoundary(\n static=pd.DataFrame(\n data={\n \"node_id\": [4],\n \"level\": [1.0], # Not relevant\n }\n )\n)\n\nSetup PID control:\n\npid_control = ribasim.PidControl(\n time=pd.DataFrame(\n data={\n \"node_id\": 4 * [5, 7],\n \"time\": [\n \"2020-01-01 00:00:00\",\n \"2020-01-01 00:00:00\",\n \"2020-05-01 00:00:00\",\n \"2020-05-01 00:00:00\",\n \"2020-07-01 00:00:00\",\n \"2020-07-01 00:00:00\",\n \"2020-12-01 00:00:00\",\n \"2020-12-01 00:00:00\",\n ],\n \"listen_node_id\": 4 * [2, 2],\n \"target\": [5.0, 5.0, 5.0, 5.0, 7.5, 7.5, 7.5, 7.5],\n \"proportional\": 4 * [-1e-3, 1e-3],\n \"integral\": 4 * [-1e-7, 1e-7],\n \"derivative\": 4 * [0.0, 0.0],\n }\n )\n)\n\nNote that the coefficients for the pump and the outlet are equal in magnitude but opposite in sign. This way the pump and the outlet equally work towards the same goal, while having opposite effects on the controlled basin due to their connectivity to this basin.\nSetup a model:\n\nmodel = ribasim.Model(\n network=ribasim.Network(\n node=node,\n edge=edge,\n ),\n basin=basin,\n flow_boundary=flow_boundary,\n level_boundary=level_boundary,\n pump=pump,\n outlet=outlet,\n pid_control=pid_control,\n starttime=\"2020-01-01 00:00:00\",\n endtime=\"2020-12-01 00:00:00\",\n)\n\nLet’s take a look at the model:\n\nmodel.plot()\n\n<Axes: >\n\n\n\n\n\nWrite the model to a TOML and GeoPackage:\n\ndatadir = Path(\"data\")\nmodel.write(datadir / \"pid_control/ribasim.toml\")\n\nPosixPath('data/pid_control/ribasim.toml')\n\n\nNow run the model with ribasim pid_control/ribasim.toml. After running the model, read back the results:\n\nfrom matplotlib.dates import date2num\n\ndf_basin = pd.read_feather(datadir / \"pid_control/results/basin.arrow\")\ndf_basin_wide = df_basin.pivot_table(\n index=\"time\", columns=\"node_id\", values=[\"storage\", \"level\"]\n)\nax = df_basin_wide[\"level\"].plot()\nax.set_ylabel(\"level [m]\")\n\n# Plot target level\ntarget_levels = model.pid_control.time.df.target.to_numpy()[:4]\ntimes = date2num(model.pid_control.time.df.time)[:4]\nax.plot(times, target_levels, color=\"k\", ls=\":\", label=\"target level\")\npass\n\n\n\n\n\n\n5 Model with allocation\nSetup the nodes:\n\nxy = np.array(\n [\n (0.0, 0.0), # 1: FlowBoundary\n (1.0, 0.0), # 2: Basin\n (1.0, 1.0), # 3: User\n (2.0, 0.0), # 4: LinearResistance\n (3.0, 0.0), # 5: Basin\n (3.0, 1.0), # 6: User\n (4.0, 0.0), # 7: TabulatedRatingCurve\n (4.5, 0.0), # 8: FractionalFlow\n (4.5, 0.5), # 9: FractionalFlow\n (5.0, 0.0), # 10: Terminal\n (4.5, 0.25), # 11: DiscreteControl\n (4.5, 1.0), # 12: Basin\n (5.0, 1.0), # 13: User\n ]\n)\nnode_xy = gpd.points_from_xy(x=xy[:, 0], y=xy[:, 1])\n\nnode_type = [\n \"FlowBoundary\",\n \"Basin\",\n \"User\",\n \"LinearResistance\",\n \"Basin\",\n \"User\",\n \"TabulatedRatingCurve\",\n \"FractionalFlow\",\n \"FractionalFlow\",\n \"Terminal\",\n \"DiscreteControl\",\n \"Basin\",\n \"User\",\n]\n\n# All nodes belong to allocation network id 1\nnode = ribasim.Node(\n df=gpd.GeoDataFrame(\n data={\"type\": node_type, \"allocation_network_id\": 1},\n index=pd.Index(np.arange(len(xy)) + 1, name=\"fid\"),\n geometry=node_xy,\n crs=\"EPSG:28992\",\n )\n)\n\nSetup the edges:\n\nfrom_id = np.array(\n [1, 2, 2, 4, 5, 5, 7, 3, 6, 7, 8, 9, 12, 13, 11, 11],\n dtype=np.int64,\n)\nto_id = np.array(\n [2, 3, 4, 5, 6, 7, 8, 2, 5, 9, 10, 12, 13, 10, 8, 9],\n dtype=np.int64,\n)\n# Denote the first edge, 1 => 2, as a source edge for\n# allocation network 1\nallocation_network_id = len(from_id) * [None]\nallocation_network_id[0] = 1\nlines = node.geometry_from_connectivity(from_id, to_id)\nedge = ribasim.Edge(\n df=gpd.GeoDataFrame(\n data={\n \"from_node_id\": from_id,\n \"to_node_id\": to_id,\n \"edge_type\": (len(from_id) - 2) * [\"flow\"] + 2 * [\"control\"],\n \"allocation_network_id\": allocation_network_id,\n },\n geometry=lines,\n crs=\"EPSG:28992\",\n )\n)\n\nSetup the basins:\n\nprofile = pd.DataFrame(\n data={\n \"node_id\": [2, 2, 5, 5, 12, 12],\n \"area\": 300_000.0,\n \"level\": 3 * [0.0, 1.0],\n }\n)\n\nstatic = pd.DataFrame(\n data={\n \"node_id\": [2, 5, 12],\n \"drainage\": 0.0,\n \"potential_evaporation\": 0.0,\n \"infiltration\": 0.0,\n \"precipitation\": 0.0,\n \"urban_runoff\": 0.0,\n }\n)\n\nstate = pd.DataFrame(data={\"node_id\": [2, 5, 12], \"level\": 1.0})\n\nbasin = ribasim.Basin(profile=profile, static=static, state=state)\n\nSetup the flow boundary:\n\nflow_boundary = ribasim.FlowBoundary(\n static=pd.DataFrame(\n data={\n \"node_id\": [1],\n \"flow_rate\": 2.0,\n }\n )\n)\n\nSetup the linear resistance:\n\nlinear_resistance = ribasim.LinearResistance(\n static=pd.DataFrame(\n data={\n \"node_id\": [4],\n \"resistance\": 0.06,\n }\n )\n)\n\nSetup the tabulated rating curve:\n\ntabulated_rating_curve = ribasim.TabulatedRatingCurve(\n static=pd.DataFrame(\n data={\n \"node_id\": 7,\n \"level\": [0.0, 0.5, 1.0],\n \"flow_rate\": [0.0, 0.0, 2.0],\n }\n )\n)\n\nSetup the fractional flow:\n\nfractional_flow = ribasim.FractionalFlow(\n static=pd.DataFrame(\n data={\n \"node_id\": [8, 8, 9, 9],\n \"fraction\": [0.6, 0.9, 0.4, 0.1],\n \"control_state\": [\"divert\", \"close\", \"divert\", \"close\"],\n }\n )\n)\n\nSetup the terminal:\n\nterminal = ribasim.Terminal(\n static=pd.DataFrame(\n data={\n \"node_id\": [10],\n }\n )\n)\n\nSetup the discrete control:\n\ncondition = pd.DataFrame(\n data={\n \"node_id\": [11],\n \"listen_feature_id\": 5,\n \"variable\": \"level\",\n \"greater_than\": 0.52,\n }\n)\n\nlogic = pd.DataFrame(\n data={\n \"node_id\": 11,\n \"truth_state\": [\"T\", \"F\"],\n \"control_state\": [\"divert\", \"close\"],\n }\n)\n\ndiscrete_control = ribasim.DiscreteControl(condition=condition, logic=logic)\n\nSetup the users:\n\nuser = ribasim.User(\n static=pd.DataFrame(\n data={\n \"node_id\": [6, 13],\n \"demand\": [1.5, 1.0],\n \"return_factor\": 0.0,\n \"min_level\": -1.0,\n \"priority\": [1, 3],\n }\n ),\n time=pd.DataFrame(\n data={\n \"node_id\": [3, 3, 3, 3],\n \"demand\": [0.0, 1.0, 1.2, 1.2],\n \"priority\": [1, 1, 2, 2],\n \"return_factor\": 0.0,\n \"min_level\": -1.0,\n \"time\": 2 * [\"2020-01-01 00:00:00\", \"2020-01-20 00:00:00\"],\n }\n ),\n)\n\nSetup the allocation:\n\nallocation = ribasim.Allocation(use_allocation=True, timestep=86400)\n\nSetup a model:\n\nmodel = ribasim.Model(\n network=ribasim.Network(\n node=node,\n edge=edge,\n ),\n basin=basin,\n flow_boundary=flow_boundary,\n linear_resistance=linear_resistance,\n tabulated_rating_curve=tabulated_rating_curve,\n terminal=terminal,\n user=user,\n discrete_control=discrete_control,\n fractional_flow=fractional_flow,\n allocation=allocation,\n starttime=\"2020-01-01 00:00:00\",\n endtime=\"2020-01-20 00:00:00\",\n)\n\nLet’s take a look at the model:\n\nmodel.plot()\n\n<Axes: >\n\n\n\n\n\nWrite the model to a TOML and GeoPackage:\n\ndatadir = Path(\"data\")\nmodel.write(datadir / \"allocation_example/ribasim.toml\")\n\nPosixPath('data/allocation_example/ribasim.toml')\n\n\nNow run the model with ribasim allocation_example/ribasim.toml. After running the model, read back the results:\n\nimport matplotlib.ticker as plticker\n\ndf_allocation = pd.read_feather(datadir / \"allocation_example/results/allocation.arrow\")\ndf_allocation_wide = df_allocation.pivot_table(\n index=\"time\",\n columns=[\"user_node_id\", \"priority\"],\n values=[\"demand\", \"allocated\", \"abstracted\"],\n)\ndf_allocation_wide = df_allocation_wide.loc[:, (df_allocation_wide != 0).any(axis=0)]\n\nfig, axs = plt.subplots(1, 3, figsize=(8, 5))\nfig.suptitle(f\"Objective type: {model.allocation.objective_type}\", fontweight=\"bold\")\n\ndf_allocation_wide[\"demand\"].plot(ax=axs[0], ls=\":\")\ndf_allocation_wide[\"allocated\"].plot(ax=axs[1], ls=\"--\")\ndf_allocation_wide[\"abstracted\"].plot(ax=axs[2])\n\nfig.tight_layout()\nloc = plticker.MultipleLocator(2)\n\naxs[0].set_ylabel(\"level [m]\")\n\nfor ax, title in zip(axs, [\"Demand\", \"Allocated\", \"Abstracted\"]):\n ax.set_title(title)\n ax.set_ylim(0.0, 1.6)\n ax.xaxis.set_major_locator(loc)\n\n\n\n\nSome things to note about this plot:\n\nAbstraction behaves somewhat erratically at the start of the simulation. This is because allocation is based on flows computed in the physical layer, and at the start of the simulation these are not known yet.\nAlthough there is a plotted line for abstraction per priority, abstraction is actually accumulated over all priorities per user.\n\n\ndf_basin = pd.read_feather(datadir / \"allocation_example/results/basin.arrow\")\ndf_basin_wide = df_basin.pivot_table(\n index=\"time\", columns=\"node_id\", values=[\"storage\", \"level\"]\n)\n\nax = df_basin_wide[\"level\"].plot()\nax.set_title(\"Basin levels\")\nax.set_ylabel(\"level [m]\")\n\nText(0, 0.5, 'level [m]')" }, { "objectID": "src/index.html", @@ -606,7 +606,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 SQLite\n\ntoml_path = normpath(@__DIR__, \"../../generated_testmodels/allocation_example/ribasim.toml\")\np = Ribasim.Model(toml_path).integrator.p\n\nallocation_model = p.allocation.allocation_models[1]\nt = 0.0\npriority_idx = 1\n\nRibasim.set_flow!(p.graph, Ribasim.NodeID(1), Ribasim.NodeID(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, t, priority_idx)\n\nprintln(p.allocation.allocation_models[1].problem)\n\n\nMin 0.05 F[(#5, #2)] + 0.05 F[(#1, #2)] + 0.05 F[(#7, #12)] + 0.05 F[(#2, #3)] + 0.05 F[(#2, #5)] + 0.05 F[(#12, #13)] + 0.05 F[(#5, #7)] + 0.05 F[(#5, #6)] + 0.05 F[(#13, #10)] + 0.05 F[(#7, #10)] + F_abs[#6] + F_abs[#13] + F_abs[#3]\nSubject to\n source[(#1, #2)] : F[(#1, #2)] ≤ 1\n flow_conservation[#2] : -F[(#5, #2)] - F[(#1, #2)] + F[(#2, #3)] + F[(#2, #5)] ≤ 0\n flow_conservation[#12] : -F[(#7, #12)] + F[(#12, #13)] ≤ 0\n flow_conservation[#5] : F[(#5, #2)] - F[(#2, #5)] + F[(#5, #7)] + F[(#5, #6)] ≤ 0\n return_flow[#13] : F[(#13, #10)] ≤ 0\n fractional_flow[(#7, #12)] : F[(#7, #12)] - 0.4 F[(#5, #7)] ≤ 0\n F[(#5, #2)] ≥ 0\n F[(#1, #2)] ≥ 0\n F[(#7, #12)] ≥ 0\n F[(#2, #3)] ≥ 0\n F[(#2, #5)] ≥ 0\n F[(#12, #13)] ≥ 0\n F[(#5, #7)] ≥ 0\n F[(#5, #6)] ≥ 0\n F[(#13, #10)] ≥ 0\n F[(#7, #10)] ≥ 0\n abs_positive[#6] : -F[(#5, #6)] + F_abs[#6] ≥ -1.5\n abs_positive[#13] : -F[(#12, #13)] + F_abs[#13] ≥ 0\n abs_positive[#3] : -F[(#2, #3)] + F_abs[#3] ≥ 0\n abs_negative[#6] : F[(#5, #6)] + F_abs[#6] ≥ 1.5\n abs_negative[#13] : F[(#12, #13)] + F_abs[#13] ≥ 0\n abs_negative[#3] : F[(#2, #3)] + F_abs[#3] ≥ 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 SQLite\n\ntoml_path = normpath(@__DIR__, \"../../generated_testmodels/allocation_example/ribasim.toml\")\np = Ribasim.Model(toml_path).integrator.p\n\nallocation_model = p.allocation.allocation_models[1]\nt = 0.0\npriority_idx = 1\n\nRibasim.set_flow!(p.graph, Ribasim.NodeID(1), Ribasim.NodeID(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, t, priority_idx)\n\nprintln(p.allocation.allocation_models[1].problem)\n\n\nMin 0.05 F[(#1, #2)] + 0.05 F[(#2, #3)] + 0.05 F[(#12, #13)] + 0.05 F[(#2, #5)] + 0.05 F[(#5, #7)] + 0.05 F[(#7, #12)] + 0.05 F[(#13, #10)] + 0.05 F[(#5, #6)] + 0.05 F[(#7, #10)] + 0.05 F[(#5, #2)] + F_abs[#13] + F_abs[#6] + F_abs[#3]\nSubject to\n source[(#1, #2)] : F[(#1, #2)] ≤ 1\n flow_conservation[#12] : F[(#12, #13)] - F[(#7, #12)] ≤ 0\n flow_conservation[#2] : -F[(#1, #2)] + F[(#2, #3)] + F[(#2, #5)] - F[(#5, #2)] ≤ 0\n flow_conservation[#5] : -F[(#2, #5)] + F[(#5, #7)] + F[(#5, #6)] + F[(#5, #2)] ≤ 0\n return_flow[#13] : F[(#13, #10)] ≤ 0\n fractional_flow[(#7, #12)] : -0.4 F[(#5, #7)] + F[(#7, #12)] ≤ 0\n F[(#1, #2)] ≥ 0\n F[(#2, #3)] ≥ 0\n F[(#12, #13)] ≥ 0\n F[(#2, #5)] ≥ 0\n F[(#5, #7)] ≥ 0\n F[(#7, #12)] ≥ 0\n F[(#13, #10)] ≥ 0\n F[(#5, #6)] ≥ 0\n F[(#7, #10)] ≥ 0\n F[(#5, #2)] ≥ 0\n abs_positive[#13] : -F[(#12, #13)] + F_abs[#13] ≥ 0\n abs_positive[#6] : -F[(#5, #6)] + F_abs[#6] ≥ -1.5\n abs_positive[#3] : -F[(#2, #3)] + F_abs[#3] ≥ 0\n abs_negative[#13] : F[(#12, #13)] + F_abs[#13] ≥ 0\n abs_negative[#6] : F[(#5, #6)] + F_abs[#6] ≥ 1.5\n abs_negative[#3] : F[(#2, #3)] + F_abs[#3] ≥ 0" }, { "objectID": "core/usage.html",