Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check time of Ribasim and MODFLOW6 model before coupling #247

Merged
merged 3 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions pre-processing/primod/ribamod/ribamod.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import pandas as pd
import ribasim
import tomli_w
import xarray as xr
from imod.mf6 import Drainage, GroundwaterFlowModel, Modflow6Simulation, River

from primod.ribamod.exchange_creator import (
Expand Down Expand Up @@ -65,6 +66,10 @@ def __init__(
coupling_list: list[DriverCoupling],
basin_definition: gpd.GeoDataFrame,
):
self.validate_time_window(
ribasim_model=ribasim_model,
mf6_simulation=mf6_simulation,
)
self.ribasim_model = ribasim_model
self.mf6_simulation = mf6_simulation
self.coupling_list = coupling_list
Expand Down Expand Up @@ -202,6 +207,33 @@ def validate_keys(
f"present in the model: {missing}"
)

@staticmethod
def validate_time_window(
ribasim_model: ribasim.Model,
mf6_simulation: Modflow6Simulation,
) -> None:
def to_timestamp(xr_time: xr.DataArray) -> pd.Timestamp:
return pd.Timestamp(xr_time.to_numpy().item())

mf6_timedis = mf6_simulation["time_discretization"].dataset
mf6_start = to_timestamp(mf6_timedis["time"].isel(time=0)).to_pydatetime()
time_delta = pd.to_timedelta(
mf6_timedis["timestep_duration"].isel(time=-1).item(), unit="days"
)
mf6_end = (
to_timestamp(mf6_timedis["time"].isel(time=-1)) + time_delta
).to_pydatetime()

ribasim_start = ribasim_model.starttime
ribasim_end = ribasim_model.endtime
if ribasim_start != mf6_start or ribasim_end != mf6_end:
raise ValueError(
"Ribasim simulation time window does not match MODFLOW6.\n"
f"Ribasim: {ribasim_start} to {ribasim_end}\n"
f"MODFLOW6: {mf6_start} to {mf6_end}\n"
)
return

def validate_basin_node_ids(self) -> pd.Series:
assert self.ribasim_model.basin.profile.df is not None
basin_ids = np.unique(self.ribasim_model.basin.profile.df["node_id"])
Expand Down Expand Up @@ -234,6 +266,7 @@ def write_exchanges(

# Assume only one groundwater flow model
# FUTURE: Support multiple groundwater flow models.
# FUTURE: move validations to the init?
gwf_model = self.mf6_simulation[gwf_names[0]]
self.validate_keys(
gwf_model,
Expand Down
7 changes: 6 additions & 1 deletion tests/fixtures/fixture_modflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,11 @@ def mf6_bucket_model(active_idomain: xr.DataArray) -> mf6.Modflow6Simulation:
)

simulation = make_mf6_simulation(gwf_model)
# Override time discretization:
# Make model returns dates in 1970
# Ribasim bucket models is 2020-2021.
times = pd.date_range("2020-01-01", "2021-01-01", freq="D")
simulation.create_time_discretization(additional_times=times)
return simulation


Expand Down Expand Up @@ -286,7 +291,7 @@ def mf6_backwater_model() -> mf6.Modflow6Simulation:
reordering_method=None,
relaxation_factor=0.97,
)
times = pd.date_range("2020-01-01", "2030-01-01", freq="M")
times = pd.date_range("2020-01-01", "2021-01-01", freq="D")
simulation.create_time_discretization(additional_times=times)
return simulation

Expand Down
10 changes: 10 additions & 0 deletions tests/test_primod/test_preprocessing_ribamod.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ def basin_definition(mf6_bucket_model, ribasim_bucket_model) -> gpd.GeoDataFrame
return gpd.GeoDataFrame(data={"node_id": node_id}, geometry=[polygon])


def test_validate_time_window(mf6_bucket_model, ribasim_bucket_model):
times = pd.date_range("1970-01-01", "1971-01-01", freq="D")
# override time discretization
mf6_bucket_model.create_time_discretization(additional_times=times)
with pytest.raises(
ValueError, match="Ribasim simulation time window does not match MODFLOW6"
):
RibaMod.validate_time_window(ribasim_bucket_model, mf6_bucket_model)


def test_validate_keys(mf6_bucket_model):
with pytest.raises(ValueError, match="active and passive keys share members"):
RibaMod.validate_keys(
Expand Down