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 in the introduction, 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. Information on coupling can be found here.
An overview of all components is given in the installation section.
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
.
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:
- conduct an inventory of demands from the sub-networks to inlets from the main network,
- allocate the available water in the main network to the subnetworks inlets,
- 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.
3 Substance (tracer) concentrations
This is an unsupported experimental feature and is disabled by default. We advise to use the Delwaq coupling for tracer calculations. If you’re interested in using this experimental feature, please contact us.
Ribasim can calculate concentrations of conservative tracers (i.e. substances that are non-reactive). It does so by calculating the mass transports by flows for each timestep, in the update_cumulative_flows!
callback. Specifically, for each Basin at each timestep it calculates:
- all mass inflows (\(flow * source\_concentration\)) given the edge inflows
- update the concentrations in the Basin based on the added storage (\(previous storage + inflows\))
- all mass outflows (\(flow * basin\_concentration\_state\)) give the edge outflows
- update the concentrations in the Basin based on the current storage
We thus keep track of both mass and concentration of substances for each Basin. Note that we have not added the substance mass to the states, and we assume that concentrations of flows are piecewise constant over a timestep. This excludes the use of tracer injections.
By default the following source tracers are enabled.
- Continuity (mass balance, fraction of all water sources, sum of all other source tracers)
- Initial (fraction of initial storages)
- LevelBoundary, FlowBoundary, UserDemand, Drainage, Precipitation (fraction of different boundaries)