From 75d38cc904cc1953034805cc681aabce7bce9c80 Mon Sep 17 00:00:00 2001 From: rleander Date: Fri, 14 Jun 2024 16:40:46 +0200 Subject: [PATCH 1/8] init work for RibaMeta, toml description --- docs/_quarto-manual.yml | 3 + docs/_quarto-website.yml | 5 + docs/coupler_ribameta_config.qmd | 183 ++++++++++++++++++++++++ docs/coupler_ribameta_preprocessing.qmd | 163 +++++++++++++++++++++ docs/coupler_ribameta_technical.qmd | 177 +++++++++++++++++++++++ 5 files changed, 531 insertions(+) create mode 100644 docs/coupler_ribameta_config.qmd create mode 100644 docs/coupler_ribameta_preprocessing.qmd create mode 100644 docs/coupler_ribameta_technical.qmd diff --git a/docs/_quarto-manual.yml b/docs/_quarto-manual.yml index c09a7ed..cbdac9d 100644 --- a/docs/_quarto-manual.yml +++ b/docs/_quarto-manual.yml @@ -26,6 +26,9 @@ book: - coupler_ribamod_config.qmd - coupler_ribamod_technical.qmd - coupler_ribamod_preprocessing.qmd + - coupler_ribameta_config.qmd + - coupler_ribameta_technical.qmd + - coupler_ribameta_preprocessing.qmd - primod_api/index.qmd - coupler_architecture.qmd - coupler_release.qmd diff --git a/docs/_quarto-website.yml b/docs/_quarto-website.yml index c151204..bcef6bb 100644 --- a/docs/_quarto-website.yml +++ b/docs/_quarto-website.yml @@ -66,6 +66,11 @@ website: - href: coupler_ribamod_config.qmd - href: coupler_ribamod_technical.qmd - href: coupler_ribamod_preprocessing.qmd + - section: "Ribasim - MetaSWAP" + contents: + - href: coupler_ribameta_config.qmd + - href: coupler_ribameta_technical.qmd + - href: coupler_ribameta_preprocessing.qmd - href: primod_api/index.qmd - href: coupler_architecture.qmd - href: coupler_release.qmd diff --git a/docs/coupler_ribameta_config.qmd b/docs/coupler_ribameta_config.qmd new file mode 100644 index 0000000..8c082b1 --- /dev/null +++ b/docs/coupler_ribameta_config.qmd @@ -0,0 +1,183 @@ +--- +title: Configuration +--- + +The configuration file is necessary to describe the model and its dependencies. It is in the [toml](https://toml.io/en/) format and should have a `.toml` extension. + +```{=html} + +``` +``` toml +timing = false +log_level = "INFO" +driver_type = "ribametamod" + +[driver.kernels.modflow6] +dll = "./kernels/modflow6/libmf6.dll" +dll_dep_dir = "./kernels/modflow6" +work_dir = "./mf6_data" + +[driver.kernels.metaswap] +dll = "./kernels/metaswap/MetaSWAP.dll" +dll_dep_dir = "./kernels/metaswap" +work_dir = "./metaswap" + +[driver.kernels.ribasim] +dll = "./kernels/ribasim/bin/libribasim.dll" +dll_dep_dir = "./kernels/ribasim/bin" +config_file = "./ribasim_data/ribasim.toml" + +[[driver.coupling]] +mf6_model = "GWF_1" +mf6_msw_node_map = "./exchanges/nodenr2svat.dxc" +mf6_msw_recharge_pkg = "rch_msw" +mf6_msw_recharge_map = "./exchanges/rchindex2svat.dxc" +mf6_msw_well_pkg = "well_msw" +mf6_msw_sprinkling_map_groundwater = "./exchanges/wellindex2svat.dxc" +rib_msw_ponding_map_surface_water = "./exchanges/msw_ponding.tsv" +rib_msw_sprinkling_map_surface_water = "./exchanges/msw_sw_sprinkling.tsv" +output_config_file = "C:\\Users\\leander\\AppData\\Local\\Temp\\pytest-of-leander\\pytest-1254\\test_ribametamod_two_basin_use0\\develop\\exchange_logging\\logging.toml" + +[driver.coupling.mf6_active_river_packages] +riv_1 = "./exchanges/riv_1.tsv" + +[driver.coupling.mf6_passive_river_packages] + +[driver.coupling.mf6_active_drainage_packages] + +[driver.coupling.mf6_passive_drainage_packages] +``` + +## Config schema + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
name descriptiontype default enum
log_level verbosity of logging str INFO DEBUG, INFO, WARNING, ERROR, CRITICAL
timing profiling active? if so, record timing boolean false
driver_type chosen coupler implementation. Typically associated with the set of coupled kernels str
driver.kernels.modflow6
dll path to the MODFLOW 6 library file str
dll_dep_dir optional path to the library's dependencies str \[..\]
workdir path to the MODFLOW 6 working directory holding the simulation name file str
driver.kernels.metaswap
dll path to the MetaSWAP library file str
dll_dep_dir optional path to the library's dependencies str \[..\]
workdir path to the MetaSWAP working directory holding the parasim.inp name file str
driver.kernels.ribasim
dll path to the Ribasim library file str
config_file path to the Ribasim config file str

driver.coupling
mf6_model name of the MODFLOW 6 model (within the simulation) to couple str
mf6_msw_node_map file with MODFLOW 6 node to MetaSWAP svat mapping str
mf6_msw_recharge_pkg name of MODFLOW 6 recharge package for coupling with MetaSWAP str
mf6_msw_recharge_map file with MODFLOW 6 recharge index to MetaSWAP svat mapping str
mf6_msw_well_pkg name of MODFLOW 6 well package for coupling with MetaSWAP groundwater sprinkling str
rib_msw_ponding_map_groundwater file with Ribasim node index to MetaSWAP svat mapping for ponding str
rib_msw_ponding_map_surface_water file with Ribasim node index to MetaSWAP svat mapping for surface water sprinkling str
rib_msw_sprinkling_map_surface_water file with Ribasim node index to MetaSWAP svat mapping for surface water sprinkling str

mf6_active_river_packages dictionary of active MODFLOW 6 river packages with couple file dict +
mf6_passive_river_packages dictionary of passive MODFLOW 6 river packages with couple file dict
mf6_active_river_packages dictionary of active MODFLOW 6 drainage packages with couple file dict
mf6_passive_river_packages dictionary of passive MODFLOW 6 drainage packages with couple file dict
output_config_file .toml specifying kernel exchanges for which to record values to output files as timeseries str
+
diff --git a/docs/coupler_ribameta_preprocessing.qmd b/docs/coupler_ribameta_preprocessing.qmd new file mode 100644 index 0000000..f5d6606 --- /dev/null +++ b/docs/coupler_ribameta_preprocessing.qmd @@ -0,0 +1,163 @@ +--- +title: Pre-processing +--- + +This document describes how to setup coupled Ribasim-MODFLOW 6 simulations. + +## The primod Python package + +To aid in setting up coupled models, we have created the `primod` Python +package. It takes both models, derives the exchange relationships between +both, and writes: + +* the Ribasim model +* the MODFLOW 6 simulation +* the exchange files +* the iMOD coupler configuration file + +The derivation of exchange connections between the models is automatic, and +based on the spatial information provided for both models. + +As `primod` is a Python package, both models must be represented in Python: + +* The MODFLOW 6 simulation is represented by the + [Modflow6Simulation](https://deltares.github.io/imod-python/api/generated/mf6/imod.mf6.Modflow6Simulation.html) + class of the `imod` Python package. +* The Ribasim model is represented by the + [Model](https://deltares.github.io/Ribasim/python/reference/#model) class of + the `ribasim` Python package. +* The combination of both models is represented by the `primod` + [RibaMod](primod_api/RibaMod.html#primod.RibaMod) + class. + +Both Python packages support reading a model from a TOML file and associated +files. + +## Abbreviated example + +The following abbreviated example: + +* Reads a Ribasim model +* Reads a MODFLOW 6 simulation +* Reads a basin definition associated with the Ribasim model +* Defines a driver coupling: which river and drainage packages are coupled +* Sets up a coupled model +* Writes the coupled model + + +``` python +import ribasim +import geopandas as gpd +import imod +import primod + + +ribasim_model = ribasim.Model.read("ribasim/ribasim.toml") +mf6_simulation = imod.mf6.Modflow6Simulation.from_file("modflow/GWF_1.toml") +basin_definition = gpd.read_file("ribasim_network.gpkg", layer="basin_areas") + +driver_coupling_active = primod.RibaModActiveDriverCoupling( + mf6_model="GWF_1", + mf6_packages=["riv-1"], + basin_definition=basin_definition, +) +driver_coupling_passve = primod.RibaModPassiveDriverCoupling( + mf6_model="GWF_1", + mf6_packages=["drn-1", "drn-2"], + basin_definition=basin_definition, +) + +ribamod_model = primod.RibaMod( + ribasim_model=ribasim_model, + mf6_simulation=mf6sim, + coupling_list=[driver_coupling_active, driver_coupling_passive], +) + +ribamod_model.write( + directory="coupled-ribamod-simulation", + modflow6_dll=r"c:\bin\imod_coupler\modflow6\libmf6.dll", + ribasim_dll=r"c:\bin\imod_coupler\ribasim\bin\libribasim.dll", + ribasim_dll_dependency=r"c:\bin\imod_coupler\ribasim\bin", +) +``` + +## Requirements + +* The start and end times of the Ribasim and MODFLOW 6 simulations must align. + `primod` will raise an error otherwise. +* Spatial extents of both models need not coincide. Part of the Ribasim basins + may be located outside of the MODFLOW 6 simulation window. Uncoupled basins + will proceed with the regular drainage and irrigation terms define in the + Basin / Static or Basin / Time tables. +* Similarly, not every River and Drainage boundary needs to be linked with + Ribasim. Boundaries outside of any basin polygon will simply use the regular + file input. + +## Exchange derivation + +The exchanges are derived based on spatial overlap of Ribasim basins and the +grid-based River and Drainage representation. For an active coupling, the x +and y locations of the subgrid elements is used to link each actively coupled +MODFLOW 6 boundary with a subgrid element. + +### Passive coupling + +The derivation of exchanges proceeds in the following steps: + +* Rasterize the basin definition polygons (provided as a + `geopandas.GeoDataFrame`) to the MODFLOW 6 model grid. +* Overlay the conductance on the rasterized basin definition, + and derive for each boundary the basin index. +* Identify the indices of the coupled MODFLOW 6 boundaries. +* Store the basin indices and boundary indices in a table. + +### Active coupling + +The derivation of active coupling exchanges proceeds largely the same, but also +locates the nearest subgrid elements: + +* Rasterize the basin definition polygons (provided as a + `geopandas.GeoDataFrame`) to the MODFLOW 6 model grid. +* Overlay the conductance on the rasterized basin definition, and derive for + each boundary the basin index. +* Identify the indices of the coupled MODFLOW 6 boundaries. +* Using the `meta_x` and `meta_y` columns in the Ribasim Basin / subgrid table, + find the nearest subgrid element for each MODFLOW 6 boundary. +* Store the basin indices, boundary indices, subgrid indices in a table. + +## Modifications to the Ribasim model + +The `primod.RibaMod` class makes the following alteration to the Ribasim input +before writing the Ribasim model: for basins that are coupled to MODFLOW 6, +the infiltration and drainage columns are set to `NaN` / `Null` (nodata) in +the Basin / Static or Basin / Time tables. + +This ensures that Ribasim does not overwrite the exchange flows while running +coupled with MODFLOW 6. + +Conceptually, it also means that when a basin is coupled, it should generally +located inside of the MODFLOW 6 model; after all, when half of the basin is +located outside of the MODFLOW 6 model, it will not receive drainage or lose +water to infiltration in that half. + +## Modifications to the MODFLOW 6 simulation + +Currently, no modifications are made in the MODFLOW 6 input. + +### Consistency between MODFLOW 6 and Ribasim subgrid + +During the coupling, water levels should not be set below the bed elevation +of the boundary. For drainage packages, this is the drainage elevation +provided in the MODFLOW 6 input; for river packages, this is the bottom +elevation provided in the MODFLOW 6 input. + +There is potential for inconsistency here, as Ribasim also describes a bed +elevation: the lowest level of the subgrid piecewise interpolation table: + +* In case the MODFLOW 6 bed elevation is higher than the subgrid elevation, + infiltration will stop before the Ribasim basin is empty. +* In case the MODFLOW 6 bed elevation is lower than the subgrid elevation, + infiltration will proceed even when the Ribasim basin is empty. + +The second is a more pressing problem, as it will results in a discrepancy +between the water balances of both models. diff --git a/docs/coupler_ribameta_technical.qmd b/docs/coupler_ribameta_technical.qmd new file mode 100644 index 0000000..db03b25 --- /dev/null +++ b/docs/coupler_ribameta_technical.qmd @@ -0,0 +1,177 @@ +--- +title: Technical Reference +--- + +This document describes the complete couple scheme Ribasim - MetaSWAP - MODFLOW 6, +the operations performed by the individual kernels as well as the exchanges between the kernels. + +```{mermaid} +sequenceDiagram + autonumber + Ribasim ->> MODFLOW6: stage [t-1][active] + MODFLOW6 ->> Ribasim: RIV flux estimate [t-1][active + passive] + + loop Ribasim-MetaSWAP subtimesteps + Note over MetaSWAP: prepare surface water timestep tsw + MetaSWAP->>Ribasim: sprinkling demand [tsw] + MetaSWAP->>Ribasim: runoff [tsw] + Note over Ribasim: solve tsw + Ribasim ->> MetaSWAP: sprinkling realised [tsw] + end + Ribasim ->> MODFLOW6: RIV realised [t][active] + MODFLOW6 ->> MetaSWAP: head [t-1] + Note over MetaSWAP, MODFLOW6: Iterate again +``` + + + + + +The following sequence diagram show the current sequential coupling scheme for +a single MODFLOW 6 stress period. + +```{mermaid} +sequenceDiagram + autonumber + Ribasim ->> MODFLOW6: exchange stage [T-1] + Note over MODFLOW6: solve T + MODFLOW6 ->> Ribasim: RIV flux [T-1] + Note over Ribasim: solve T +``` + +# Requirements + +* Ribasim only couples to the River (RIV) and Drainage (DRN) packages of + MODFLOW6. +* One or more River and Drainage boundaries can be connected with one Ribasim + basin. +* The MODFLOW6 River and Drainage entity is the smallest entity: coupling + multiple Ribasim basins to a single MODFLOW6 boundary is not supported. +* The active coupling, in which MODFLOW6 boundary levels are changed, always + requires a "subgrid" table in Ribasim. + +# Data exchanges + +## MODFLOW6 to Ribasim + +### Flows + +The computed drainage and infiltration flows to and from River and Drainage +packages are aggregated on basin level and set as: + +* infiltration: a flow from the surface water to the groundwater (positive). +* drainage: a flow from the groundwater to the surface (positive). + +These are set as the infiltration and drainage forcing on the Ribasim basins. + +## Ribasim to MODFLOW 6 + +### Levels + +Ribasim sets the stage of River packages, and the drainage elevation of Drainage +packages in MODFLOW6. + +The levels of the basins are not set directly in MODFLOW6. The levels are +interpolated using the "subgrid" functionality of Ribasim, which can be used to +e.g. create sloping water levels within a single basin. + +For simplicity of the coupling, the subgrid functionality is also used in +case of a 1:1 basin-boundary coupling. + +# Files + +The following files are required to couple the two model codes. + +## MODFLOW6 + +No specific files are required. The MODFLOW6 model must contain River or +Drainage packages which represent the surface water. + +## Ribasim + +No specific files are required. The Basin / Subgrid table must be defined. For +preprocessing with `primod`, the metadata columns `meta_x`, `meta_y` must be +included in this table to indicate the spatial location of each subgrid +element. + +## Coupler + +These files provide the mappings from the MODFLOW boundary indices to the +Ribasim basin indices. For actively coupled system (see below), it also +includes subgrid indices. + +The files are identified by the MODFLOW6 package name. + +Note that the exchange files are **tab-separated** and use 0-based indices. +They also include a header. + +### Passive coupling + +#### [package-name].tsv + + +``` +basin_index bound_index +{basin_index0} {bound_index0} +{basin_index1} {bound_index1} +... +``` + +### Active coupling + +#### [package-name].tsv + +``` +basin_index bound_index subgrid_index +{basin_index0} {bound_index0} {subgrid_index0} +{basin_index1} {bound_index1} {subgrid_index1} +... +``` + +# MODFLOW 6 surface water representation + +Ribasim is linked to the surface water representation of the MODFLOW 6 models. +Specifically, Ribasim is linked to either River (RIV) or Drainage (DRN) +packages. In a coupled simulation, Ribasim computes a surface water mass +balance and sets the water levels for the MODFLOW 6 boundaries, and MODFLOW 6 +provides the drainage and infiltration flows. These flows are collected in the +Ribasim basins. + +The RibaMod coupling only exchanges between Ribasim basins and MODFLOW 6 River +and Drainage packages. This means that for a successful coupling with Ribasim, +the surface water should **only** be represented by either River or Drainage +boundaries. + +More advanced surface water boundaries such as the Streamflow-Routing (SFR) +package or the Lake (LAK) package compute their own surface water mass balance, +and cannot be coupled to Ribasim. Such packages may be used freely in the parts +of the model domain that are **not** coupled with Ribasim, but should not be +used in the part of the model domain that is coupled to Ribasim. + +## Active versus passive coupling + +In coupling Ribasim to MODFLOW 6, we make a distinction between active and +passive coupling. + +In passive coupling, MODFLOW 6 computes drainage and infiltration flows. These +are added to the water balance of the Ribasim basins. The water levels computed +by Ribasim are **not** set back into MODFLOW 6. This type of coupling is +convenient for boundaries that show little variation in terms of drainage +elevation over time (e.g. surface runoff, or ditches with negligible water +depth). A passive coupling requires little in terms of parametrization of the +Ribasim model: all flows are simply added as a sort of "lateral" flow into the +basin. + +In the active coupling, Ribasim does set the water levels of the MODFLOW 6 +model. + +The passive coupling should generally only be applied to coupling to Drainage +packages, not River packages: in case of "over-infiltration", the water levels +in Ribasim will drop, potentially resulting in a dry basin. However, since the +water levels are not set in MODFLOW 6, no feedback can occur, and the MODFLOW 6 +model will keep infiltrating water that is not available. This creates a +discrepancy between the water balances of both models. + +In the active coupling, large infiltration flows would result in lower water +levels, and infiltration stops when the basin dries up and the River stage +reaches the bed elevation. \ No newline at end of file From 8201d4634a41af0b106ce8c4ffc8e3ca5512b526 Mon Sep 17 00:00:00 2001 From: rleander Date: Tue, 25 Jun 2024 17:22:13 +0200 Subject: [PATCH 2/8] ongoing work in technical documentation --- docs/coupler_ribameta_config.qmd | 50 +++++ docs/coupler_ribameta_technical.qmd | 284 ++++++++++++---------------- 2 files changed, 176 insertions(+), 158 deletions(-) diff --git a/docs/coupler_ribameta_config.qmd b/docs/coupler_ribameta_config.qmd index 8c082b1..7d8e926 100644 --- a/docs/coupler_ribameta_config.qmd +++ b/docs/coupler_ribameta_config.qmd @@ -181,3 +181,53 @@ riv_1 = "./exchanges/riv_1.tsv" + +# Files + +The following files are required to couple the two model codes. + +## MODFLOW6 + +No specific files are required. The MODFLOW6 model must contain River or +Drainage packages which represent the surface water. + +## Ribasim + +No specific files are required. The Basin / Subgrid table must be defined. For +preprocessing with `primod`, the metadata columns `meta_x`, `meta_y` must be +included in this table to indicate the spatial location of each subgrid +element. + +## Coupler + +These files provide the mappings from the MODFLOW boundary indices to the +Ribasim basin indices. For actively coupled system (see below), it also +includes subgrid indices. + +The files are identified by the MODFLOW6 package name. + +Note that the exchange files are **tab-separated** and use 0-based indices. +They also include a header. + +### Passive coupling + +#### [package-name].tsv + + +``` +basin_index bound_index +{basin_index0} {bound_index0} +{basin_index1} {bound_index1} +... +``` + +### Active coupling + +#### [package-name].tsv + +``` +basin_index bound_index subgrid_index +{basin_index0} {bound_index0} {subgrid_index0} +{basin_index1} {bound_index1} {subgrid_index1} +... +``` diff --git a/docs/coupler_ribameta_technical.qmd b/docs/coupler_ribameta_technical.qmd index db03b25..21877d0 100644 --- a/docs/coupler_ribameta_technical.qmd +++ b/docs/coupler_ribameta_technical.qmd @@ -2,176 +2,144 @@ title: Technical Reference --- -This document describes the complete couple scheme Ribasim - MetaSWAP - MODFLOW 6, -the operations performed by the individual kernels as well as the exchanges between the kernels. +This document describes the complete Ribasim - MetaSWAP - MODFLOW 6 coupling sequence, +the operations performed by the individual components as well as the exchanges of data among the components. ```{mermaid} sequenceDiagram autonumber - Ribasim ->> MODFLOW6: stage [t-1][active] - MODFLOW6 ->> Ribasim: RIV flux estimate [t-1][active + passive] + Ribasim ->> MODFLOW6: stage [t-1] + MODFLOW6 ->> Ribasim: estimated RIV flux, active & passive [t-1] loop Ribasim-MetaSWAP subtimesteps Note over MetaSWAP: prepare surface water timestep tsw - MetaSWAP->>Ribasim: sprinkling demand [tsw] - MetaSWAP->>Ribasim: runoff [tsw] + MetaSWAP->>Ribasim: ponding runoff [tsw] + MetaSWAP->>Ribasim: estimated sprinkling [tsw] Note over Ribasim: solve tsw - Ribasim ->> MetaSWAP: sprinkling realised [tsw] + Ribasim ->> MetaSWAP: realized sprinkling [tsw] + end + Ribasim ->> MODFLOW6: realized RIV, active [t] + loop MODFLOW6-MetaSWAP iterations + MODFLOW6 ->> MetaSWAP: head[] + Note over MetaSWAP: solve t + MetaSWAP ->> MODFLOW6: storage coefficient[] + MetaSWAP ->> MODFLOW6: recharge flux[] + MetaSWAP ->> MODFLOW6: groundwater sprinkling flux[] + Note over MODFLOW6: solve t end - Ribasim ->> MODFLOW6: RIV realised [t][active] - MODFLOW6 ->> MetaSWAP: head [t-1] - Note over MetaSWAP, MODFLOW6: Iterate again -``` - - - - - -The following sequence diagram show the current sequential coupling scheme for -a single MODFLOW 6 stress period. -```{mermaid} -sequenceDiagram - autonumber - Ribasim ->> MODFLOW6: exchange stage [T-1] - Note over MODFLOW6: solve T - MODFLOW6 ->> Ribasim: RIV flux [T-1] - Note over Ribasim: solve T ``` -# Requirements - -* Ribasim only couples to the River (RIV) and Drainage (DRN) packages of - MODFLOW6. -* One or more River and Drainage boundaries can be connected with one Ribasim - basin. -* The MODFLOW6 River and Drainage entity is the smallest entity: coupling - multiple Ribasim basins to a single MODFLOW6 boundary is not supported. -* The active coupling, in which MODFLOW6 boundary levels are changed, always - requires a "subgrid" table in Ribasim. - -# Data exchanges - -## MODFLOW6 to Ribasim - -### Flows - -The computed drainage and infiltration flows to and from River and Drainage -packages are aggregated on basin level and set as: - -* infiltration: a flow from the surface water to the groundwater (positive). -* drainage: a flow from the groundwater to the surface (positive). +The exchanges between kernels can be summerized as follows: +
    +
  1. Surface water levels (stages) for all MODFLOW6 cells with an active RIV coupling to produce an estimate of the active RIV flux. +These surface levels are obtained from a Ribasim subgrid water level profile by interpolation from the basin levels. +This interpolation requires the definition of a subgrid table within the Ribasim configuration. +
  2. +
  3. RIV flux (both active and passive) estimated by MODFLOW6, proposed to Ribasim
  4. +Ribasim-MetaSWAP sub-timestepping +
      +
    1. Runoff (ponding) from MetaSWAP added to Ribasim
    2. +
    3. Surface water sprinkling flux requested by MetaSWAP to be extracted from Ribasim, if allocated.
    4. +
    5. Surface water sprinkling flux realized by Ribasim, reported back to MetaSWAP
    6. +
    +
  5. RIV flux, realized by Ribasim, reported back to MODFLOW6
  6. +MODFLOW6-MetaSWAP iterations +
      +
    1. Head of MODFLOW6 sent to MetaSWAP
    2. +
    3. Storage coefficient from MetaSWAP sent to MODFLOW6
    4. +
    5. Recharge from MetaSWAP sent to MODFLOW6 as a source term
    6. +
    7. Groundwater sprinkling flux requested by MetaSWAP, extracted from MODFLOW6
    8. +
    +
+ + +## Some remarks +* Flows directly to or from Ribasim are communicated to the Ribasim kernel via the BMI variables infiltration for all extractions from and drainage for all additions to Ribasim basin volumes. This requires a mapping to ribasim basins. +However, amounts for infiltration and drainage are grouped and kept track off in an exchange object, rather than sent to Ribasim diretly. +The net effect of these contributions is sent to Ribasim just before solving Ribasim for the current timestep and individual contributions can also be logged. +* The surface water sprinkling is however kept separate as so-called 'user demands' applied to specific user-demand nodes in the Ribasim network. +These demands are subject to an optimalization algorithm establishing allocation of water for all requests. +* Ribasim only couples to a River (RIV package ) for and Drainage (DRN) packages of + MODFLOW6, no other packages of surface water boundaries should be active where Ribasim is coupled. +* One or more River and Drainage boundaries can be connected with one Ribasim basin. Inversely, more than one Ribasim basin couppled to a single MODFLOW6 boundary is *not* supported. -These are set as the infiltration and drainage forcing on the Ribasim basins. - -## Ribasim to MODFLOW 6 - -### Levels - -Ribasim sets the stage of River packages, and the drainage elevation of Drainage -packages in MODFLOW6. - -The levels of the basins are not set directly in MODFLOW6. The levels are -interpolated using the "subgrid" functionality of Ribasim, which can be used to -e.g. create sloping water levels within a single basin. - -For simplicity of the coupling, the subgrid functionality is also used in -case of a 1:1 basin-boundary coupling. - -# Files - -The following files are required to couple the two model codes. - -## MODFLOW6 - -No specific files are required. The MODFLOW6 model must contain River or -Drainage packages which represent the surface water. - -## Ribasim - -No specific files are required. The Basin / Subgrid table must be defined. For -preprocessing with `primod`, the metadata columns `meta_x`, `meta_y` must be -included in this table to indicate the spatial location of each subgrid -element. - -## Coupler - -These files provide the mappings from the MODFLOW boundary indices to the -Ribasim basin indices. For actively coupled system (see below), it also -includes subgrid indices. - -The files are identified by the MODFLOW6 package name. - -Note that the exchange files are **tab-separated** and use 0-based indices. -They also include a header. - -### Passive coupling - -#### [package-name].tsv - - -``` -basin_index bound_index -{basin_index0} {bound_index0} -{basin_index1} {bound_index1} -... -``` - -### Active coupling - -#### [package-name].tsv - -``` -basin_index bound_index subgrid_index -{basin_index0} {bound_index0} {subgrid_index0} -{basin_index1} {bound_index1} {subgrid_index1} -... -``` - -# MODFLOW 6 surface water representation - -Ribasim is linked to the surface water representation of the MODFLOW 6 models. -Specifically, Ribasim is linked to either River (RIV) or Drainage (DRN) -packages. In a coupled simulation, Ribasim computes a surface water mass -balance and sets the water levels for the MODFLOW 6 boundaries, and MODFLOW 6 -provides the drainage and infiltration flows. These flows are collected in the -Ribasim basins. - -The RibaMod coupling only exchanges between Ribasim basins and MODFLOW 6 River -and Drainage packages. This means that for a successful coupling with Ribasim, -the surface water should **only** be represented by either River or Drainage -boundaries. - -More advanced surface water boundaries such as the Streamflow-Routing (SFR) -package or the Lake (LAK) package compute their own surface water mass balance, -and cannot be coupled to Ribasim. Such packages may be used freely in the parts -of the model domain that are **not** coupled with Ribasim, but should not be -used in the part of the model domain that is coupled to Ribasim. ## Active versus passive coupling - -In coupling Ribasim to MODFLOW 6, we make a distinction between active and -passive coupling. - -In passive coupling, MODFLOW 6 computes drainage and infiltration flows. These -are added to the water balance of the Ribasim basins. The water levels computed -by Ribasim are **not** set back into MODFLOW 6. This type of coupling is -convenient for boundaries that show little variation in terms of drainage -elevation over time (e.g. surface runoff, or ditches with negligible water -depth). A passive coupling requires little in terms of parametrization of the -Ribasim model: all flows are simply added as a sort of "lateral" flow into the -basin. - -In the active coupling, Ribasim does set the water levels of the MODFLOW 6 -model. - -The passive coupling should generally only be applied to coupling to Drainage -packages, not River packages: in case of "over-infiltration", the water levels -in Ribasim will drop, potentially resulting in a dry basin. However, since the -water levels are not set in MODFLOW 6, no feedback can occur, and the MODFLOW 6 -model will keep infiltrating water that is not available. This creates a -discrepancy between the water balances of both models. - -In the active coupling, large infiltration flows would result in lower water -levels, and infiltration stops when the basin dries up and the River stage -reaches the bed elevation. \ No newline at end of file +In coupling Ribasim and MODFLOW6, a distinction exists between *active* and *passive* coupling. +In a passive coupling fluxes on the MODFLOW6 side are evaluated irrespective of the Ribasim waterlevels +and contribute directly to the Ribasim basins. +The Ribasim water levels are *not* required in this case, fluxes are simply regarded as "lateral" sources to the basin, +hence configuration on the Ribasim side is minimal. +The passive approach is justified for drainage packages showing little variation in terms of elevation over time (e.g. surface runoff, or ditches with negligible water depth). +On the contrary, in the case of an active coupling fluxes depend (linearly) on the Ribasim water levels. +This requires the stages in the MODFLOW6 model to be set to the subgrid water levels of Ribasim prior to evaluation of the river fluxes. + +In the case of river packages "over-infiltration" can cause Ribasim water levels can fall to zero, leaving a dry basin. +Since in the passive situation, water levels are not taken into account, no feedback occurs that limits or impedes infiltration. +The MODFLOW6 model assumes infiltration to continue, whereas the coupled Ribasim basin already ran out of water. This raises a +discrepancy in the water balance between both models. Therefore, passive couplings are unsuitable for river packages +In active couplings, infiltration stops when the basin dries up and the water level reaches the bed elevation. + +## Derivation of the realised sprinkling flux and the river flux correction. +Before performing a Ribasim update, the surface water sprinkling amounts in MetaSWAP and the active infiltration or drainage in +MODFLOW6 have been evaluated under the assumption of an unlimited availability of surface water for these processes. +After Ribasims timestep, the *realized* extraction is known in Ribasim and this information must somehow be communicated to MODFLOW6 (step 6) and MetaSWAP (step 5) in order to maintain a correct overall water balance. + +For the surface water sprinkling the following procedure is used to derive the realized fluxes for the MetaSWAP units. + +* The realized fraction $f_i$ is derived of the realized sprinkling flux $R_i$, compared to the requested flux $D_i$ for Ribasim element $i$. +i.o.w. +$$ +f_i\,=\, +\begin{align} +\begin{cases} + R_i/D_i & D_i\neq 0 \\ + 0 & D_i = 0 +\end{cases} +\end{align} +$$ + +* The real contribution of Ribasim element $i$ to MetaSWAP element $j$ was then $f_i A_{ij} M^*_j$, where $M^*$ denotes the MetaSWAP vector of demand fluxes and $A_{ij}$ refers to an element of the couple matrix. + +* So, the total realized flux $M_j$ received by MetaSWAP element $j$ is then obtained by summation over $j$: +$$ +M_j\,=\,\sum\limits_j f_i A_{ij} M^*_j +$$\,\,, +or in vector notation for all MetaSWAP elements: +$$ +\hspace{1cm} +\mathbf{M}\,=\,(A^T\mathbf{f})\odot\mathbf{M^*} +$$ + +The evaluation of the correction of the infiltration flux, for MODFLOW6 proceeds in a similar fashion, except: + +* Not the realized fraction $f_i$, but its complement $1-f_i$ is used. + +* Correction is only applied to the *negative* demands. The positive demands, representing drainage, is unlimited. +$$ +\begin{align} +M_j\,=\, +\begin{cases} +\sum\limits_j f_i A_{ij} M^*_j & M^*_j<0 \\ +\sum\limits_j M^* & M^*_j>0 +\end{cases} +\end{align} +$$ + +This must be taken into account into the realized fraction for the water balance to be correct: +$$ + +$$ + +In earlier implementation of coupling groundwater and surface water such corrections were applied proportional and applying +This can be accomplished by evaluating the realized fractions on the Ribasim side and using the mapping to convert these fractions into +fractions on the MetaSWAP or MODFLOW6 side: the reduction $\beta_i=R_i/D_i$ +now applies to that portion of the demand by node/svat $j$ that is supposed to come from Ribasim element $j$ + +The most straightforward way +Let $R_{i}$ be the realized Ribasim infiltration amount for Ribasim element $i$ +and $D_{j}$ the amount requested, $M_{j}$ the amount realized and $C_{j}$ the correction for element $j$ in the MetaSWAP or MODFLOW6 model. +$$ +\sum a_{i,j} +$$ \ No newline at end of file From 3ef10e2fa75b522878113ece97f11db4da3b984b Mon Sep 17 00:00:00 2001 From: rleander Date: Sat, 29 Jun 2024 07:36:12 +0200 Subject: [PATCH 3/8] ongoing writing --- docs/coupler_ribameta_preprocessing.qmd | 163 ------------------------ docs/coupler_ribameta_technical.qmd | 66 +++++++--- 2 files changed, 45 insertions(+), 184 deletions(-) delete mode 100644 docs/coupler_ribameta_preprocessing.qmd diff --git a/docs/coupler_ribameta_preprocessing.qmd b/docs/coupler_ribameta_preprocessing.qmd deleted file mode 100644 index f5d6606..0000000 --- a/docs/coupler_ribameta_preprocessing.qmd +++ /dev/null @@ -1,163 +0,0 @@ ---- -title: Pre-processing ---- - -This document describes how to setup coupled Ribasim-MODFLOW 6 simulations. - -## The primod Python package - -To aid in setting up coupled models, we have created the `primod` Python -package. It takes both models, derives the exchange relationships between -both, and writes: - -* the Ribasim model -* the MODFLOW 6 simulation -* the exchange files -* the iMOD coupler configuration file - -The derivation of exchange connections between the models is automatic, and -based on the spatial information provided for both models. - -As `primod` is a Python package, both models must be represented in Python: - -* The MODFLOW 6 simulation is represented by the - [Modflow6Simulation](https://deltares.github.io/imod-python/api/generated/mf6/imod.mf6.Modflow6Simulation.html) - class of the `imod` Python package. -* The Ribasim model is represented by the - [Model](https://deltares.github.io/Ribasim/python/reference/#model) class of - the `ribasim` Python package. -* The combination of both models is represented by the `primod` - [RibaMod](primod_api/RibaMod.html#primod.RibaMod) - class. - -Both Python packages support reading a model from a TOML file and associated -files. - -## Abbreviated example - -The following abbreviated example: - -* Reads a Ribasim model -* Reads a MODFLOW 6 simulation -* Reads a basin definition associated with the Ribasim model -* Defines a driver coupling: which river and drainage packages are coupled -* Sets up a coupled model -* Writes the coupled model - - -``` python -import ribasim -import geopandas as gpd -import imod -import primod - - -ribasim_model = ribasim.Model.read("ribasim/ribasim.toml") -mf6_simulation = imod.mf6.Modflow6Simulation.from_file("modflow/GWF_1.toml") -basin_definition = gpd.read_file("ribasim_network.gpkg", layer="basin_areas") - -driver_coupling_active = primod.RibaModActiveDriverCoupling( - mf6_model="GWF_1", - mf6_packages=["riv-1"], - basin_definition=basin_definition, -) -driver_coupling_passve = primod.RibaModPassiveDriverCoupling( - mf6_model="GWF_1", - mf6_packages=["drn-1", "drn-2"], - basin_definition=basin_definition, -) - -ribamod_model = primod.RibaMod( - ribasim_model=ribasim_model, - mf6_simulation=mf6sim, - coupling_list=[driver_coupling_active, driver_coupling_passive], -) - -ribamod_model.write( - directory="coupled-ribamod-simulation", - modflow6_dll=r"c:\bin\imod_coupler\modflow6\libmf6.dll", - ribasim_dll=r"c:\bin\imod_coupler\ribasim\bin\libribasim.dll", - ribasim_dll_dependency=r"c:\bin\imod_coupler\ribasim\bin", -) -``` - -## Requirements - -* The start and end times of the Ribasim and MODFLOW 6 simulations must align. - `primod` will raise an error otherwise. -* Spatial extents of both models need not coincide. Part of the Ribasim basins - may be located outside of the MODFLOW 6 simulation window. Uncoupled basins - will proceed with the regular drainage and irrigation terms define in the - Basin / Static or Basin / Time tables. -* Similarly, not every River and Drainage boundary needs to be linked with - Ribasim. Boundaries outside of any basin polygon will simply use the regular - file input. - -## Exchange derivation - -The exchanges are derived based on spatial overlap of Ribasim basins and the -grid-based River and Drainage representation. For an active coupling, the x -and y locations of the subgrid elements is used to link each actively coupled -MODFLOW 6 boundary with a subgrid element. - -### Passive coupling - -The derivation of exchanges proceeds in the following steps: - -* Rasterize the basin definition polygons (provided as a - `geopandas.GeoDataFrame`) to the MODFLOW 6 model grid. -* Overlay the conductance on the rasterized basin definition, - and derive for each boundary the basin index. -* Identify the indices of the coupled MODFLOW 6 boundaries. -* Store the basin indices and boundary indices in a table. - -### Active coupling - -The derivation of active coupling exchanges proceeds largely the same, but also -locates the nearest subgrid elements: - -* Rasterize the basin definition polygons (provided as a - `geopandas.GeoDataFrame`) to the MODFLOW 6 model grid. -* Overlay the conductance on the rasterized basin definition, and derive for - each boundary the basin index. -* Identify the indices of the coupled MODFLOW 6 boundaries. -* Using the `meta_x` and `meta_y` columns in the Ribasim Basin / subgrid table, - find the nearest subgrid element for each MODFLOW 6 boundary. -* Store the basin indices, boundary indices, subgrid indices in a table. - -## Modifications to the Ribasim model - -The `primod.RibaMod` class makes the following alteration to the Ribasim input -before writing the Ribasim model: for basins that are coupled to MODFLOW 6, -the infiltration and drainage columns are set to `NaN` / `Null` (nodata) in -the Basin / Static or Basin / Time tables. - -This ensures that Ribasim does not overwrite the exchange flows while running -coupled with MODFLOW 6. - -Conceptually, it also means that when a basin is coupled, it should generally -located inside of the MODFLOW 6 model; after all, when half of the basin is -located outside of the MODFLOW 6 model, it will not receive drainage or lose -water to infiltration in that half. - -## Modifications to the MODFLOW 6 simulation - -Currently, no modifications are made in the MODFLOW 6 input. - -### Consistency between MODFLOW 6 and Ribasim subgrid - -During the coupling, water levels should not be set below the bed elevation -of the boundary. For drainage packages, this is the drainage elevation -provided in the MODFLOW 6 input; for river packages, this is the bottom -elevation provided in the MODFLOW 6 input. - -There is potential for inconsistency here, as Ribasim also describes a bed -elevation: the lowest level of the subgrid piecewise interpolation table: - -* In case the MODFLOW 6 bed elevation is higher than the subgrid elevation, - infiltration will stop before the Ribasim basin is empty. -* In case the MODFLOW 6 bed elevation is lower than the subgrid elevation, - infiltration will proceed even when the Ribasim basin is empty. - -The second is a more pressing problem, as it will results in a discrepancy -between the water balances of both models. diff --git a/docs/coupler_ribameta_technical.qmd b/docs/coupler_ribameta_technical.qmd index 21877d0..37bafea 100644 --- a/docs/coupler_ribameta_technical.qmd +++ b/docs/coupler_ribameta_technical.qmd @@ -54,7 +54,7 @@ This interpolation requires the definition of a subgrid table within the Ribasim -## Some remarks +### Some remarks * Flows directly to or from Ribasim are communicated to the Ribasim kernel via the BMI variables infiltration for all extractions from and drainage for all additions to Ribasim basin volumes. This requires a mapping to ribasim basins. However, amounts for infiltration and drainage are grouped and kept track off in an exchange object, rather than sent to Ribasim diretly. The net effect of these contributions is sent to Ribasim just before solving Ribasim for the current timestep and individual contributions can also be logged. @@ -65,7 +65,7 @@ These demands are subject to an optimalization algorithm establishing allocation * One or more River and Drainage boundaries can be connected with one Ribasim basin. Inversely, more than one Ribasim basin couppled to a single MODFLOW6 boundary is *not* supported. -## Active versus passive coupling +### Active versus passive coupling In coupling Ribasim and MODFLOW6, a distinction exists between *active* and *passive* coupling. In a passive coupling fluxes on the MODFLOW6 side are evaluated irrespective of the Ribasim waterlevels and contribute directly to the Ribasim basins. @@ -81,9 +81,16 @@ The MODFLOW6 model assumes infiltration to continue, whereas the coupled Ribasim discrepancy in the water balance between both models. Therefore, passive couplings are unsuitable for river packages In active couplings, infiltration stops when the basin dries up and the water level reaches the bed elevation. -## Derivation of the realised sprinkling flux and the river flux correction. +### Estimated sprinkling flux +Within the Ribasim context, the sprinkling flux is implemented as a water user, the demand of which is +communicated is communicated in entries of the user demand matrix. +From the couplers perspective, this is a two-dimensional array in which every column represents a water user +and every row corresponds with a priority. The array elements are water demands for the users, with different priorities. These priorities play a role on the Ribasim side only if allocation is active. There, the users are defined as nodes in the network and in the coupler, these users are mapped onto MetaSWAP svats. +For every of those users, the water demand can be non-zero for a single priority only. This is however not checked and the resposibility of the user. + +### Realized sprinkling flux and infiltration flux correction. Before performing a Ribasim update, the surface water sprinkling amounts in MetaSWAP and the active infiltration or drainage in -MODFLOW6 have been evaluated under the assumption of an unlimited availability of surface water for these processes. +MODFLOW6 have been evaluated under the assumption of an unlimited availability of surface water for these processes (steps 2 and 4) . After Ribasims timestep, the *realized* extraction is known in Ribasim and this information must somehow be communicated to MODFLOW6 (step 6) and MetaSWAP (step 5) in order to maintain a correct overall water balance. For the surface water sprinkling the following procedure is used to derive the realized fluxes for the MetaSWAP units. @@ -114,32 +121,49 @@ $$ The evaluation of the correction of the infiltration flux, for MODFLOW6 proceeds in a similar fashion, except: -* Not the realized fraction $f_i$, but its complement $1-f_i$ is used. +* Not the realized fraction $f_i$, but its complement $1-f_i$ is used to obtain the correction $C_j$ on the infiltration flux. + +* This correction is only applied to the *negative* demands. The positive demands, associated with drainage, are always granted. -* Correction is only applied to the *negative* demands. The positive demands, representing drainage, is unlimited. +* The correction amounts represent a lack of water already infiltrated into MODFLOW6, which turned out not to be available at the end of the Ribasim timestep. Hence, this is corrected by means of a *negative* source term in MODFLOW6 in the next groundwater timestep. $$ \begin{align} -M_j\,=\, +C_j\,=\, \begin{cases} -\sum\limits_j f_i A_{ij} M^*_j & M^*_j<0 \\ -\sum\limits_j M^* & M^*_j>0 +\sum\limits_j (1-f_i) A_{ij} M^*_j & M^*_j<0 \\ +0 & M^*_j>0 \end{cases} \end{align} $$ -This must be taken into account into the realized fraction for the water balance to be correct: -$$ +This must be taken into account into the realized fraction for a correct water balance. +Therefore, the demand $D_i$ to Ribasim element $i$ is now plit into $D_{i-}$ and, $D_{i+}$, +summing fluxes over the infiltrating and draining MODFLOW6 elemnents respectively. +$$ +f_i\,=\, +\begin{align} +\begin{cases} + (R_i - D_{i+})/D_{i-} & D_{i-}\neq 0 \\ + 0 & D_{i-} = 0 +\end{cases} +\end{align} $$ -In earlier implementation of coupling groundwater and surface water such corrections were applied proportional and applying -This can be accomplished by evaluating the realized fractions on the Ribasim side and using the mapping to convert these fractions into -fractions on the MetaSWAP or MODFLOW6 side: the reduction $\beta_i=R_i/D_i$ -now applies to that portion of the demand by node/svat $j$ that is supposed to come from Ribasim element $j$ +The correction $C_j$ enters MODFLOW6 as a negative right-hand side term, i.e. extraction. + + +### Logging of exchanged values +Mainly intended for checking, the coupler class now also supports logging of the values exchanged between components. +These values are written as timeseries to separate files. +In the initialization stage of the simulation a dictionary-like structure (ExchangeCollector class) is created which holds +a collection of labelled ExchangeLogger instances. +The initialization of an ExchangeLogger creates a netcdf file with dimensions `time` and `id`, a variable `time` with dimension (`time`) +and a variable `xchg` with dimensions (`time`, `id`). The time dimension is the unlimited dimension. + +When performing an exchange, the ExchangeCollector instance is scanned +for an ExchangeLogger with the label associated with that exchange. If found, the (mapped) arrays are written to the variable `xchg` +at the appropriate time level and the current time is accordingly set in the variable `time` + + -The most straightforward way -Let $R_{i}$ be the realized Ribasim infiltration amount for Ribasim element $i$ -and $D_{j}$ the amount requested, $M_{j}$ the amount realized and $C_{j}$ the correction for element $j$ in the MetaSWAP or MODFLOW6 model. -$$ -\sum a_{i,j} -$$ \ No newline at end of file From dbdc3059c384095e26f135fdb0f5b32a86a7e1e5 Mon Sep 17 00:00:00 2001 From: rleander Date: Sat, 29 Jun 2024 07:42:12 +0200 Subject: [PATCH 4/8] renaming ribameta to ribametamod --- docs/_quarto-manual.yml | 6 +++--- docs/_quarto-website.yml | 6 +++--- ...r_ribameta_config.qmd => coupler_ribametamod_config.qmd} | 0 ...meta_technical.qmd => coupler_ribametamod_technical.qmd} | 0 4 files changed, 6 insertions(+), 6 deletions(-) rename docs/{coupler_ribameta_config.qmd => coupler_ribametamod_config.qmd} (100%) rename docs/{coupler_ribameta_technical.qmd => coupler_ribametamod_technical.qmd} (100%) diff --git a/docs/_quarto-manual.yml b/docs/_quarto-manual.yml index cbdac9d..b4aab9c 100644 --- a/docs/_quarto-manual.yml +++ b/docs/_quarto-manual.yml @@ -26,9 +26,9 @@ book: - coupler_ribamod_config.qmd - coupler_ribamod_technical.qmd - coupler_ribamod_preprocessing.qmd - - coupler_ribameta_config.qmd - - coupler_ribameta_technical.qmd - - coupler_ribameta_preprocessing.qmd + - coupler_ribametamod_config.qmd + - coupler_ribametamod_technical.qmd + - coupler_ribametamod_preprocessing.qmd - primod_api/index.qmd - coupler_architecture.qmd - coupler_release.qmd diff --git a/docs/_quarto-website.yml b/docs/_quarto-website.yml index bcef6bb..45eadf7 100644 --- a/docs/_quarto-website.yml +++ b/docs/_quarto-website.yml @@ -68,9 +68,9 @@ website: - href: coupler_ribamod_preprocessing.qmd - section: "Ribasim - MetaSWAP" contents: - - href: coupler_ribameta_config.qmd - - href: coupler_ribameta_technical.qmd - - href: coupler_ribameta_preprocessing.qmd + - href: coupler_ribametamod_config.qmd + - href: coupler_ribametamod_technical.qmd + - href: coupler_ribametamod_preprocessing.qmd - href: primod_api/index.qmd - href: coupler_architecture.qmd - href: coupler_release.qmd diff --git a/docs/coupler_ribameta_config.qmd b/docs/coupler_ribametamod_config.qmd similarity index 100% rename from docs/coupler_ribameta_config.qmd rename to docs/coupler_ribametamod_config.qmd diff --git a/docs/coupler_ribameta_technical.qmd b/docs/coupler_ribametamod_technical.qmd similarity index 100% rename from docs/coupler_ribameta_technical.qmd rename to docs/coupler_ribametamod_technical.qmd From 57e783d0e49926912bc50cc5e3b2ccaec1d71efa Mon Sep 17 00:00:00 2001 From: rleander Date: Thu, 4 Jul 2024 11:06:54 +0200 Subject: [PATCH 5/8] Adressing review comments and fixing some spelling errors --- docs/_quarto-website.yml | 2 +- docs/coupler_ribametamod_config.qmd | 49 ------------ docs/coupler_ribametamod_technical.qmd | 103 ++++++++++++------------- 3 files changed, 49 insertions(+), 105 deletions(-) diff --git a/docs/_quarto-website.yml b/docs/_quarto-website.yml index 45eadf7..4da83dd 100644 --- a/docs/_quarto-website.yml +++ b/docs/_quarto-website.yml @@ -66,7 +66,7 @@ website: - href: coupler_ribamod_config.qmd - href: coupler_ribamod_technical.qmd - href: coupler_ribamod_preprocessing.qmd - - section: "Ribasim - MetaSWAP" + - section: "Ribasim - MetaSWAP - MODFLOW 6" contents: - href: coupler_ribametamod_config.qmd - href: coupler_ribametamod_technical.qmd diff --git a/docs/coupler_ribametamod_config.qmd b/docs/coupler_ribametamod_config.qmd index 7d8e926..8b0a573 100644 --- a/docs/coupler_ribametamod_config.qmd +++ b/docs/coupler_ribametamod_config.qmd @@ -182,52 +182,3 @@ riv_1 = "./exchanges/riv_1.tsv" -# Files - -The following files are required to couple the two model codes. - -## MODFLOW6 - -No specific files are required. The MODFLOW6 model must contain River or -Drainage packages which represent the surface water. - -## Ribasim - -No specific files are required. The Basin / Subgrid table must be defined. For -preprocessing with `primod`, the metadata columns `meta_x`, `meta_y` must be -included in this table to indicate the spatial location of each subgrid -element. - -## Coupler - -These files provide the mappings from the MODFLOW boundary indices to the -Ribasim basin indices. For actively coupled system (see below), it also -includes subgrid indices. - -The files are identified by the MODFLOW6 package name. - -Note that the exchange files are **tab-separated** and use 0-based indices. -They also include a header. - -### Passive coupling - -#### [package-name].tsv - - -``` -basin_index bound_index -{basin_index0} {bound_index0} -{basin_index1} {bound_index1} -... -``` - -### Active coupling - -#### [package-name].tsv - -``` -basin_index bound_index subgrid_index -{basin_index0} {bound_index0} {subgrid_index0} -{basin_index1} {bound_index1} {subgrid_index1} -... -``` diff --git a/docs/coupler_ribametamod_technical.qmd b/docs/coupler_ribametamod_technical.qmd index 37bafea..4c1f000 100644 --- a/docs/coupler_ribametamod_technical.qmd +++ b/docs/coupler_ribametamod_technical.qmd @@ -8,90 +8,87 @@ the operations performed by the individual components as well as the exchanges o ```{mermaid} sequenceDiagram autonumber - Ribasim ->> MODFLOW6: stage [t-1] - MODFLOW6 ->> Ribasim: estimated RIV flux, active & passive [t-1] + Ribasim ->> MODFLOW 6: stage [t-1] + MODFLOW 6 ->> Ribasim: estimated RIV flux, active & passive [t-1] - loop Ribasim-MetaSWAP subtimesteps + loop Ribasim-MetaSWAP subtimesteps [tsw] Note over MetaSWAP: prepare surface water timestep tsw MetaSWAP->>Ribasim: ponding runoff [tsw] MetaSWAP->>Ribasim: estimated sprinkling [tsw] Note over Ribasim: solve tsw Ribasim ->> MetaSWAP: realized sprinkling [tsw] end - Ribasim ->> MODFLOW6: realized RIV, active [t] - loop MODFLOW6-MetaSWAP iterations - MODFLOW6 ->> MetaSWAP: head[] - Note over MetaSWAP: solve t - MetaSWAP ->> MODFLOW6: storage coefficient[] - MetaSWAP ->> MODFLOW6: recharge flux[] - MetaSWAP ->> MODFLOW6: groundwater sprinkling flux[] - Note over MODFLOW6: solve t + Ribasim ->> MODFLOW 6: realized RIV, active [t] + MODFLOW 6 ->> MetaSWAP: head [t-1] + loop MODFLOW 6-MetaSWAP iterations (solving t) + Note over MetaSWAP: solve iter + MetaSWAP ->> MODFLOW 6: storage coefficient [iter] + MetaSWAP ->> MODFLOW 6: recharge flux [iter] + MetaSWAP ->> MODFLOW 6: groundwater sprinkling flux [iter] + Note over MODFLOW 6: solve iter + MODFLOW 6 ->> MetaSWAP: head [iter] end ``` -The exchanges between kernels can be summerized as follows: +The exchanges between kernels can be summarized as follows:
    -
  1. Surface water levels (stages) for all MODFLOW6 cells with an active RIV coupling to produce an estimate of the active RIV flux. -These surface levels are obtained from a Ribasim subgrid water level profile by interpolation from the basin levels. -This interpolation requires the definition of a subgrid table within the Ribasim configuration. +
  2. +Exchange the Ribasim subgrid stage from the previous timestep to actively coupled RIV en DRN packages.
  3. -
  4. RIV flux (both active and passive) estimated by MODFLOW6, proposed to Ribasim
  5. -Ribasim-MetaSWAP sub-timestepping -
      +
    1. RIV flux (both active and passive) estimated by MODFLOW 6, proposed to Ribasim
    2. +
      +Ribasim-MetaSWAP sub-timestepping:
    3. Runoff (ponding) from MetaSWAP added to Ribasim
    4. -
    5. Surface water sprinkling flux requested by MetaSWAP to be extracted from Ribasim, if allocated.
    6. -
    7. Surface water sprinkling flux realized by Ribasim, reported back to MetaSWAP
    8. -
    -
  6. RIV flux, realized by Ribasim, reported back to MODFLOW6
  7. -MODFLOW6-MetaSWAP iterations -
      -
    1. Head of MODFLOW6 sent to MetaSWAP
    2. -
    3. Storage coefficient from MetaSWAP sent to MODFLOW6
    4. -
    5. Recharge from MetaSWAP sent to MODFLOW6 as a source term
    6. -
    7. Groundwater sprinkling flux requested by MetaSWAP, extracted from MODFLOW6
    8. +
    9. Irrigation demand from MetaSWAP svats to Ribasim water users.
    10. +
    11. Realized irrigation volume on svats based on realized volumes per water user and +distributed over svats in proportion to their demands.
    12. +
    13. Flux correction in the case that Ribasim basins are unable to meet the total infiltration demand.
    14. +
      +MODFLOW 6-MetaSWAP iterations: +
    15. Head of MODFLOW 6 to MetaSWAP
    16. +
    17. Storage coefficient from MetaSWAP sent to MODFLOW 6
    18. +
    19. Recharge from MetaSWAP sent to MODFLOW 6 as a source term
    20. +
    21. Groundwater sprinkling flux requested by MetaSWAP, extracted from MODFLOW 6
    -
- ### Some remarks -* Flows directly to or from Ribasim are communicated to the Ribasim kernel via the BMI variables infiltration for all extractions from and drainage for all additions to Ribasim basin volumes. This requires a mapping to ribasim basins. -However, amounts for infiltration and drainage are grouped and kept track off in an exchange object, rather than sent to Ribasim diretly. -The net effect of these contributions is sent to Ribasim just before solving Ribasim for the current timestep and individual contributions can also be logged. * The surface water sprinkling is however kept separate as so-called 'user demands' applied to specific user-demand nodes in the Ribasim network. These demands are subject to an optimalization algorithm establishing allocation of water for all requests. * Ribasim only couples to a River (RIV package ) for and Drainage (DRN) packages of - MODFLOW6, no other packages of surface water boundaries should be active where Ribasim is coupled. -* One or more River and Drainage boundaries can be connected with one Ribasim basin. Inversely, more than one Ribasim basin couppled to a single MODFLOW6 boundary is *not* supported. + MODFLOW 6, no other packages of surface water boundaries should be active where Ribasim is coupled. ### Active versus passive coupling -In coupling Ribasim and MODFLOW6, a distinction exists between *active* and *passive* coupling. -In a passive coupling fluxes on the MODFLOW6 side are evaluated irrespective of the Ribasim waterlevels +In coupling Ribasim and MODFLO 6, a distinction exists between *active* and *passive* coupling. +In a passive coupling fluxes on the MODFLOW 6 side are evaluated irrespective of the Ribasim waterlevels and contribute directly to the Ribasim basins. The Ribasim water levels are *not* required in this case, fluxes are simply regarded as "lateral" sources to the basin, hence configuration on the Ribasim side is minimal. The passive approach is justified for drainage packages showing little variation in terms of elevation over time (e.g. surface runoff, or ditches with negligible water depth). On the contrary, in the case of an active coupling fluxes depend (linearly) on the Ribasim water levels. -This requires the stages in the MODFLOW6 model to be set to the subgrid water levels of Ribasim prior to evaluation of the river fluxes. +This requires the stages in the MODFLOW 6 model to be set to the subgrid water levels of Ribasim prior to evaluation of the river fluxes. In the case of river packages "over-infiltration" can cause Ribasim water levels can fall to zero, leaving a dry basin. Since in the passive situation, water levels are not taken into account, no feedback occurs that limits or impedes infiltration. -The MODFLOW6 model assumes infiltration to continue, whereas the coupled Ribasim basin already ran out of water. This raises a +The MODFLOW 6 model assumes infiltration to continue, whereas the coupled Ribasim basin already ran out of water. This raises a discrepancy in the water balance between both models. Therefore, passive couplings are unsuitable for river packages In active couplings, infiltration stops when the basin dries up and the water level reaches the bed elevation. ### Estimated sprinkling flux -Within the Ribasim context, the sprinkling flux is implemented as a water user, the demand of which is -communicated is communicated in entries of the user demand matrix. +Within the Ribasim context, the sprinkling flux is implemented as a water user. +The sprinkling demand is exchanged to Ribasim through the user demand matrix. From the couplers perspective, this is a two-dimensional array in which every column represents a water user -and every row corresponds with a priority. The array elements are water demands for the users, with different priorities. These priorities play a role on the Ribasim side only if allocation is active. There, the users are defined as nodes in the network and in the coupler, these users are mapped onto MetaSWAP svats. -For every of those users, the water demand can be non-zero for a single priority only. This is however not checked and the resposibility of the user. +and every row corresponds with a priority. The array elements are water demands for the users +(also for other water users beside sprinkling), each with their own set of priorities. +Priorities play a role on the Ribasim side only if allocation is active. +Within Ribasim, water users are defined as nodes in the network and in the coupler water users are mapped onto MetaSWAP svats. +For every of those users, the water demand can be non-zero for a single priority only. ### Realized sprinkling flux and infiltration flux correction. Before performing a Ribasim update, the surface water sprinkling amounts in MetaSWAP and the active infiltration or drainage in -MODFLOW6 have been evaluated under the assumption of an unlimited availability of surface water for these processes (steps 2 and 4) . -After Ribasims timestep, the *realized* extraction is known in Ribasim and this information must somehow be communicated to MODFLOW6 (step 6) and MetaSWAP (step 5) in order to maintain a correct overall water balance. +MODFLOW 6 have been evaluated under the assumption of an unlimited availability of surface water for these processes (steps 2 and 4) . +After Ribasims timestep, the *realized* extraction is known in Ribasim and this information must somehow be communicated to MODFLOW 6 (step 6) and MetaSWAP (step 5) in order to maintain a correct overall water balance. For the surface water sprinkling the following procedure is used to derive the realized fluxes for the MetaSWAP units. @@ -119,13 +116,13 @@ $$ \mathbf{M}\,=\,(A^T\mathbf{f})\odot\mathbf{M^*} $$ -The evaluation of the correction of the infiltration flux, for MODFLOW6 proceeds in a similar fashion, except: +The evaluation of the correction of the infiltration flux, for MODFLOW 6 proceeds in a similar fashion, except: * Not the realized fraction $f_i$, but its complement $1-f_i$ is used to obtain the correction $C_j$ on the infiltration flux. * This correction is only applied to the *negative* demands. The positive demands, associated with drainage, are always granted. -* The correction amounts represent a lack of water already infiltrated into MODFLOW6, which turned out not to be available at the end of the Ribasim timestep. Hence, this is corrected by means of a *negative* source term in MODFLOW6 in the next groundwater timestep. +* The correction amounts represent a lack of water already infiltrated into MODFLOW 6, which turned out not to be available at the end of the Ribasim timestep. Hence, this is corrected by means of a *negative* source term in MODFLOW 6 in the next groundwater timestep. $$ \begin{align} C_j\,=\, @@ -138,7 +135,7 @@ $$ This must be taken into account into the realized fraction for a correct water balance. Therefore, the demand $D_i$ to Ribasim element $i$ is now plit into $D_{i-}$ and, $D_{i+}$, -summing fluxes over the infiltrating and draining MODFLOW6 elemnents respectively. +summing fluxes over the infiltrating and draining MODFLOW 6 elements respectively. $$ f_i\,=\, @@ -150,20 +147,16 @@ f_i\,=\, \end{align} $$ -The correction $C_j$ enters MODFLOW6 as a negative right-hand side term, i.e. extraction. +The correction $C_j$ enters MODFLOW 6 as a negative right-hand side term, i.e. extraction. ### Logging of exchanged values -Mainly intended for checking, the coupler class now also supports logging of the values exchanged between components. -These values are written as timeseries to separate files. +The values exchanged by the coupler for a specific variable can optionally be written to file during the simulation for inspection. +These values are written as timeseries to separate files per variable. In the initialization stage of the simulation a dictionary-like structure (ExchangeCollector class) is created which holds a collection of labelled ExchangeLogger instances. The initialization of an ExchangeLogger creates a netcdf file with dimensions `time` and `id`, a variable `time` with dimension (`time`) and a variable `xchg` with dimensions (`time`, `id`). The time dimension is the unlimited dimension. -When performing an exchange, the ExchangeCollector instance is scanned -for an ExchangeLogger with the label associated with that exchange. If found, the (mapped) arrays are written to the variable `xchg` -at the appropriate time level and the current time is accordingly set in the variable `time` - From ba1422cd34da52058668c2bc95f1b39a519ced09 Mon Sep 17 00:00:00 2001 From: HendrikKok Date: Fri, 5 Jul 2024 10:57:00 +0200 Subject: [PATCH 6/8] update --- docs/coupler_ribametamod_technical.qmd | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/docs/coupler_ribametamod_technical.qmd b/docs/coupler_ribametamod_technical.qmd index 4c1f000..280ee4b 100644 --- a/docs/coupler_ribametamod_technical.qmd +++ b/docs/coupler_ribametamod_technical.qmd @@ -36,13 +36,13 @@ The exchanges between kernels can be summarized as follows:
  • Exchange the Ribasim subgrid stage from the previous timestep to actively coupled RIV en DRN packages.
  • -
  • RIV flux (both active and passive) estimated by MODFLOW 6, proposed to Ribasim
  • +
  • Estimated RIV and DRN flux, exchanged to Ribasim basins

  • Ribasim-MetaSWAP sub-timestepping: -
  • Runoff (ponding) from MetaSWAP added to Ribasim
  • +
  • Runoff from MetaSWAP exchanged to Ribasim basins
  • Irrigation demand from MetaSWAP svats to Ribasim water users.
  • -
  • Realized irrigation volume on svats based on realized volumes per water user and -distributed over svats in proportion to their demands.
  • +
  • Irrigation volume on svats based on realized volumes per water user +
  • Flux correction in the case that Ribasim basins are unable to meet the total infiltration demand.

  • MODFLOW 6-MetaSWAP iterations: @@ -53,11 +53,9 @@ distributed over svats in proportion to their demands. ### Some remarks -* The surface water sprinkling is however kept separate as so-called 'user demands' applied to specific user-demand nodes in the Ribasim network. -These demands are subject to an optimalization algorithm establishing allocation of water for all requests. -* Ribasim only couples to a River (RIV package ) for and Drainage (DRN) packages of - MODFLOW 6, no other packages of surface water boundaries should be active where Ribasim is coupled. - +* If allocation is active in the Ribasim model, The demand-realisation cycle for irrigation is based on the user priority and the water availibility. When it's inactive its based on water availibility alone. +* For coupling surface water to Ribasim, only the RIV and DRN package can be used. Other packages like GHB are not supported and should not be present in coupled domain. + ### Active versus passive coupling In coupling Ribasim and MODFLO 6, a distinction exists between *active* and *passive* coupling. From 1ee749d577d6f991d98ce3df64d77abb310b010a Mon Sep 17 00:00:00 2001 From: rleander Date: Fri, 5 Jul 2024 11:33:27 +0200 Subject: [PATCH 7/8] moved the echange logging from the technical ribametamod description to the architecture section (higher level) under its own heading --- docs/coupler_architecture.qmd | 13 ++++++++++++- docs/coupler_ribametamod_technical.qmd | 10 ---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/docs/coupler_architecture.qmd b/docs/coupler_architecture.qmd index a4f2c20..c181dd6 100644 --- a/docs/coupler_architecture.qmd +++ b/docs/coupler_architecture.qmd @@ -40,9 +40,11 @@ flowchart BT ribasim_python[Ribasim Python] --> primod imod-python[iMOD Python] --> primod primod --> ribasim[Ribasim] - primod --> imodc + primod --> |couple tables|imodc + primod --> MetaSWAP primod --> modflow6[MODFLOW 6] ribasim --> imodc["iMOD Coupler"] + MetaSWAP --> imodc["iMOD Coupler"] modflow6 --> imodc ``` @@ -63,6 +65,15 @@ while self.get_current_time() < self.get_end_time(): self.finalize() ``` +### Logging of exchanged values + +An integral task of an iMOD Coupler driver is to support the exchange of values between hydrological kernals. +Values exchanged by the coupler for a specific variable can optionally be written to file during the simulation for inspection. +These values are written as timeseries to separate files per variable. +In the initialization stage of the simulation a dictionary-like structure (ExchangeCollector class) is created which holds +a collection of labelled ExchangeLogger instances. +The initialization of an ExchangeLogger creates a netcdf file with dimensions `time` and `id`, a variable `time` with dimension (`time`) +and a variable `xchg` with dimensions (`time`, `id`). The time dimension is the unlimited dimension. ## Continuous Integration diff --git a/docs/coupler_ribametamod_technical.qmd b/docs/coupler_ribametamod_technical.qmd index 280ee4b..0a2273a 100644 --- a/docs/coupler_ribametamod_technical.qmd +++ b/docs/coupler_ribametamod_technical.qmd @@ -148,13 +148,3 @@ $$ The correction $C_j$ enters MODFLOW 6 as a negative right-hand side term, i.e. extraction. -### Logging of exchanged values -The values exchanged by the coupler for a specific variable can optionally be written to file during the simulation for inspection. -These values are written as timeseries to separate files per variable. -In the initialization stage of the simulation a dictionary-like structure (ExchangeCollector class) is created which holds -a collection of labelled ExchangeLogger instances. -The initialization of an ExchangeLogger creates a netcdf file with dimensions `time` and `id`, a variable `time` with dimension (`time`) -and a variable `xchg` with dimensions (`time`, `id`). The time dimension is the unlimited dimension. - - - From fe4392a90d2783bd6090929ff59b1d911b93585d Mon Sep 17 00:00:00 2001 From: rleander Date: Fri, 5 Jul 2024 13:19:42 +0200 Subject: [PATCH 8/8] fix typo and spelling --- docs/coupler_architecture.qmd | 2 +- docs/coupler_ribametamod_technical.qmd | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/coupler_architecture.qmd b/docs/coupler_architecture.qmd index c181dd6..3636453 100644 --- a/docs/coupler_architecture.qmd +++ b/docs/coupler_architecture.qmd @@ -67,7 +67,7 @@ self.finalize() ``` ### Logging of exchanged values -An integral task of an iMOD Coupler driver is to support the exchange of values between hydrological kernals. +An integral task of an iMOD Coupler driver is to support the exchange of values between hydrological kernels. Values exchanged by the coupler for a specific variable can optionally be written to file during the simulation for inspection. These values are written as timeseries to separate files per variable. In the initialization stage of the simulation a dictionary-like structure (ExchangeCollector class) is created which holds diff --git a/docs/coupler_ribametamod_technical.qmd b/docs/coupler_ribametamod_technical.qmd index 0a2273a..939e3c6 100644 --- a/docs/coupler_ribametamod_technical.qmd +++ b/docs/coupler_ribametamod_technical.qmd @@ -53,7 +53,8 @@ Exchange the Ribasim subgrid stage from the previous timestep to actively couple ### Some remarks -* If allocation is active in the Ribasim model, The demand-realisation cycle for irrigation is based on the user priority and the water availibility. When it's inactive its based on water availibility alone. +* If allocation is active in the Ribasim model, the demand-realisation cycle for irrigation is based on the user priority and the water availability. +When inactive it is based on water availability alone. * For coupling surface water to Ribasim, only the RIV and DRN package can be used. Other packages like GHB are not supported and should not be present in coupled domain.