Julia core

With the term “core”, we mean the computational engine of Ribasim. As detailed in the usage documentation, it is generally used as a command line tool.

A quick overview of the model concept is available at the home page, while a more in depth discussion is available on the model concept page. The theory is described on the equations page, and more in-depth numerical considerations are described on the numerical considerations page. As allocation is a large and self-contained part of the Ribasim core, it is described on the separate allocation page. Input validation is described on the validation page.

The core is implemented in the Julia programming language, and can be found in the Ribasim repository under the core/ folder. For developers we also advise to read the developer documentation.

An overview of all components is given on the home page

1 The simulation loop

The computational process can be divided in three phases:

  • Model initialization
  • Running the simulation loop
  • Writing the output files

The figure below gives a more detailed description of the simulation loop in the form of a sequence diagram. From top to bottom, it contains the following blocks:

  • Allocation optimization; activated when the allocation timestep has been passed;
  • Control actions; activated when some discrete control callback is triggered;
  • Water balance; computing the flows over flow edges happens each timestep;
  • Time integration step; done by the integrator from OrdinaryDiffEq.jl.

sequenceDiagram
    autonumber
    participant Int as Process: Integrator
    participant Optim as Process: Allocation optimization
    participant Param as Data: Parameters
    participant State as Data: State
    participant Sim as Process: Water balance
    loop Simulation loop (OrdinaryDiffEq.jl)
        activate Int
        %% Allocation
        rect rgb(200, 200, 200)
            opt Allocation optimization, per allocation network (JuMP.jl, HiGHS)
                activate Optim
                Int->>Optim: Callback: allocation timestep has passed
                Param-->>Optim: Input
                State-->>Optim: Input
                Optim->>Optim: Optimize Basin allocations if below target level
                Optim->>Optim: Optimize UserDemand allocation, per priority
                Optim-->>Param: Set allocated flow rates
                deactivate Optim
            end
        end
        %% Control
        rect rgb(200, 200, 200)
            opt Control actions
                Int->>Int: DiscreteControl callback
                Int-->>Param: Parameter updates by control
            end
        end
        %% water_balance!
        rect rgb(200, 200, 200)
            activate Sim
            State-->>Sim: Input
            Param-->>Sim: Input
            Sim->>Sim: Compute flows over edges per node type
            Sim-->>Param: Set flows
            deactivate Sim
        end
        %% Time integration
        rect rgb(200, 200, 200)
            State-->>Int: Input
            Param-->>Int: Input
            Int->>Int: Time integration step
            Int-->>State: Update state
        end
        deactivate Int
  end

2 Nested allocation

Since water systems may be extensive, like in the Netherlands, Ribasim models may become large networks with over ten thousand nodes. To keep a proper functioning allocation concept under these circumstances, the modeller can decompose the network domain into a main network and multiple sub-networks. The allocation will then be conducted in three steps:

  1. conduct an inventory of demands from the sub-networks to inlets from the main network,
  2. allocate the available water in the main network to the subnetworks inlets,
  3. allocate the assigned water within each subnetwork to the individual demand nodes.

The demand nodes then will request this updated demand from the rule-based simulation. Whether this updated demand is indeed abstracted depends on all dry-fall control mechanism implemented in the rule-based simulation.

The following sequence diagram illustrates this calculation process within then allocation phase.

sequenceDiagram
participant boundary
participant basin
participant user_demand
participant allocation_subNetwork
participant allocation_mainNetwork

user_demand->>allocation_subNetwork: demand
loop
   allocation_subNetwork-->>allocation_mainNetwork: demand inventory at inlets
end
user_demand->>allocation_mainNetwork: demand
boundary->>allocation_mainNetwork: source availability
basin->>allocation_mainNetwork: source availability
allocation_mainNetwork-->>allocation_mainNetwork: allocate to inlets (and user_demands)
allocation_mainNetwork->>user_demand: allocated
allocation_mainNetwork->>allocation_subNetwork: allocated
loop
   allocation_subNetwork-->>allocation_subNetwork: allocate to user_demands
end
allocation_subNetwork->>user_demand: allocated
user_demand->>basin: abstracted

3 Coupling

Ribasim can also be coupled to other kernels with the help of iMOD Coupler. The corresponding documentation can be found within the iMOD Suite Documentation.