diff --git a/core/src/config.jl b/core/src/config.jl index 4099fb7c1..07c9aa78c 100644 --- a/core/src/config.jl +++ b/core/src/config.jl @@ -120,6 +120,7 @@ end @option @addnodetypes struct Toml <: TableOption starttime::DateTime endtime::DateTime + crs::String ribasim_version::String input_dir::String results_dir::String diff --git a/core/test/data/config_test.toml b/core/test/data/config_test.toml index 10a24d614..5172e746d 100644 --- a/core/test/data/config_test.toml +++ b/core/test/data/config_test.toml @@ -1,5 +1,6 @@ starttime = 2019-01-01 endtime = 2019-12-31 +crs = "EPSG:28992" input_dir = "../../generated_testmodels/lhm" results_dir = "../../generated_testmodels/lhm" ribasim_version = "2024.6.1" diff --git a/core/test/data/logging_test_loglevel_debug.toml b/core/test/data/logging_test_loglevel_debug.toml index d3af856f6..19de40d72 100644 --- a/core/test/data/logging_test_loglevel_debug.toml +++ b/core/test/data/logging_test_loglevel_debug.toml @@ -1,5 +1,6 @@ starttime = 2019-01-01 endtime = 2019-12-31 +crs = "EPSG:28992" input_dir = "." results_dir = "results" ribasim_version = "2024.6.1" diff --git a/core/test/data/logging_test_no_loglevel.toml b/core/test/data/logging_test_no_loglevel.toml index c854a8cb6..6fba3712a 100644 --- a/core/test/data/logging_test_no_loglevel.toml +++ b/core/test/data/logging_test_no_loglevel.toml @@ -1,5 +1,6 @@ starttime = 2019-01-01 endtime = 2019-12-31 +crs = "EPSG:28992" input_dir = "." results_dir = "results" ribasim_version = "2024.6.1" diff --git a/core/test/docs.toml b/core/test/docs.toml index b8bb8b066..9cd0e31fc 100644 --- a/core/test/docs.toml +++ b/core/test/docs.toml @@ -3,6 +3,11 @@ starttime = 2019-01-01 # required endtime = 2021-01-01 # required +# Coordinate Reference System +# The accepted strings are documented here: +# https://proj.org/en/9.4/development/reference/functions.html#c.proj_create +crs = "EPSG:4326" # required + # input files input_dir = "." # required results_dir = "results" # required diff --git a/core/test/io_test.jl b/core/test/io_test.jl index e113b5ccc..1de92e5db 100644 --- a/core/test/io_test.jl +++ b/core/test/io_test.jl @@ -8,6 +8,7 @@ database = "path/to/file", input_dir = ".", results_dir = "results", + crs = "EPSG:28992", ribasim_version = string(Ribasim.pkgversion(Ribasim)), ) config = Ribasim.Config(toml, "model") @@ -21,6 +22,7 @@ database = "path/to/file", input_dir = "input", results_dir = "results", + crs = "EPSG:28992", ribasim_version = string(Ribasim.pkgversion(Ribasim)), ) config = Ribasim.Config(toml, "model") @@ -34,6 +36,7 @@ database = "/path/to/file", input_dir = ".", results_dir = "results", + crs = "EPSG:28992", ribasim_version = string(Ribasim.pkgversion(Ribasim)), ) config = Ribasim.Config(toml) diff --git a/docs/python/examples.ipynb b/docs/python/examples.ipynb index 4908afb22..27f3e3727 100644 --- a/docs/python/examples.ipynb +++ b/docs/python/examples.ipynb @@ -76,7 +76,7 @@ "metadata": {}, "outputs": [], "source": [ - "model = Model(starttime=\"2020-01-01\", endtime=\"2021-01-01\")" + "model = Model(starttime=\"2020-01-01\", endtime=\"2021-01-01\", crs=\"EPSG:4326\")" ] }, { @@ -457,7 +457,7 @@ "metadata": {}, "outputs": [], "source": [ - "model = Model(starttime=\"2020-01-01\", endtime=\"2021-01-01\")" + "model = Model(starttime=\"2020-01-01\", endtime=\"2021-01-01\", crs=\"EPSG:4326\")" ] }, { @@ -771,10 +771,7 @@ "metadata": {}, "outputs": [], "source": [ - "model = Model(\n", - " starttime=\"2020-01-01\",\n", - " endtime=\"2020-12-01\",\n", - ")" + "model = Model(starttime=\"2020-01-01\", endtime=\"2020-12-01\", crs=\"EPSG:4326\")" ] }, { @@ -1037,10 +1034,7 @@ "metadata": {}, "outputs": [], "source": [ - "model = Model(\n", - " starttime=\"2020-01-01\",\n", - " endtime=\"2020-01-20\",\n", - ")" + "model = Model(starttime=\"2020-01-01\", endtime=\"2020-01-20\", crs=\"EPSG:4326\")" ] }, { @@ -1430,10 +1424,7 @@ "metadata": {}, "outputs": [], "source": [ - "model = Model(\n", - " starttime=\"2020-01-01\",\n", - " endtime=\"2020-02-01\",\n", - ")" + "model = Model(starttime=\"2020-01-01\", endtime=\"2020-02-01\", crs=\"EPSG:4326\")" ] }, { diff --git a/python/ribasim/ribasim/geometry/edge.py b/python/ribasim/ribasim/geometry/edge.py index c6199dbaf..760055d7e 100644 --- a/python/ribasim/ribasim/geometry/edge.py +++ b/python/ribasim/ribasim/geometry/edge.py @@ -10,7 +10,6 @@ from pandera.dtypes import Int32 from pandera.typing import Series from pandera.typing.geopandas import GeoDataFrame, GeoSeries -from pydantic import model_validator from shapely.geometry import LineString, MultiLineString, Point from ribasim.input_base import SpatialTableModel @@ -45,13 +44,6 @@ class Config: class EdgeTable(SpatialTableModel[EdgeSchema]): """Defines the connections between nodes.""" - @model_validator(mode="after") - def empty_table(self) -> "EdgeTable": - if self.df is None: - self.df = GeoDataFrame[EdgeSchema]() - self.df.set_geometry("geometry", inplace=True) - return self - def add( self, from_node: NodeData, @@ -68,6 +60,8 @@ def add( edge_type = ( "control" if from_node.node_type in SPATIALCONTROLNODETYPES else "flow" ) + assert self.df is not None + table_to_append = GeoDataFrame[EdgeSchema]( data={ "from_node_type": pd.Series([from_node.node_type], dtype=str), @@ -79,12 +73,10 @@ def add( "subnetwork_id": pd.Series([subnetwork_id], dtype=pd.Int32Dtype()), }, geometry=geometry_to_append, + crs=self.df.crs, ) - if self.df is None: - self.df = table_to_append - else: - self.df = GeoDataFrame[EdgeSchema](pd.concat([self.df, table_to_append])) + self.df = GeoDataFrame[EdgeSchema](pd.concat([self.df, table_to_append])) def get_where_edge_type(self, edge_type: str) -> NDArray[np.bool_]: assert self.df is not None diff --git a/python/ribasim/ribasim/input_base.py b/python/ribasim/ribasim/input_base.py index 99a5ec1b3..8f57e6067 100644 --- a/python/ribasim/ribasim/input_base.py +++ b/python/ribasim/ribasim/input_base.py @@ -1,5 +1,4 @@ import re -import warnings from abc import ABC, abstractmethod from collections.abc import Callable, Generator from contextlib import closing @@ -39,7 +38,6 @@ delimiter = " / " gpd.options.io_engine = "pyogrio" -warnings.filterwarnings("ignore", category=UserWarning, module="pyogrio") context_file_loading: ContextVar[dict[str, Any]] = ContextVar( "file_loading", default={} @@ -134,15 +132,6 @@ def set_filepath(self, filepath: Path) -> None: self.filepath = filepath self.model_config["validate_assignment"] = True - @abstractmethod - def _save(self, directory: DirectoryPath, input_dir: DirectoryPath) -> None: - """Save this instance to disk. - - This method needs to be implemented by any class deriving from - FileModel. - """ - raise NotImplementedError() - @classmethod @abstractmethod def _load(cls, filepath: Path | None) -> dict[str, Any]: @@ -227,11 +216,7 @@ def _load(cls, filepath: Path | None) -> dict[str, Any]: else: return {} - def _save( - self, - directory: DirectoryPath, - input_dir: DirectoryPath, - ) -> None: + def _save(self, directory: DirectoryPath, input_dir: DirectoryPath) -> None: # TODO directory could be used to save an arrow file db_path = context_file_loading.get().get("database") if self.filepath is not None: @@ -239,9 +224,9 @@ def _save( self._write_arrow(self.filepath, directory, input_dir) elif db_path is not None: self.sort() - self._write_table(db_path) + self._write_geopackage(db_path) - def _write_table(self, temp_path: Path) -> None: + def _write_geopackage(self, temp_path: Path) -> None: """ Write the contents of the input to a database. @@ -366,16 +351,16 @@ def _from_db(cls, path: Path, table: str): return df - def _write_table(self, path: Path) -> None: + def _write_geopackage(self, path: Path) -> None: """ - Write the contents of the input to a database. + Write the contents of the input to the GeoPackage. Parameters ---------- path : Path """ assert self.df is not None - self.df.to_file(path, layer=self.tablename(), driver="GPKG", mode="a") + self.df.to_file(path, layer=self.tablename(), driver="GPKG") class ChildModel(BaseModel): @@ -436,7 +421,7 @@ def node_ids(self) -> set[int]: node_ids.update(table.node_ids()) return node_ids - def _save(self, directory: DirectoryPath, input_dir: DirectoryPath, **kwargs): + def _save(self, directory: DirectoryPath, input_dir: DirectoryPath): for table in self._tables(): table._save(directory, input_dir) diff --git a/python/ribasim/ribasim/model.py b/python/ribasim/ribasim/model.py index 523eb9316..ccca20892 100644 --- a/python/ribasim/ribasim/model.py +++ b/python/ribasim/ribasim/model.py @@ -9,6 +9,7 @@ import tomli import tomli_w from matplotlib import pyplot as plt +from pandera.typing.geopandas import GeoDataFrame from pydantic import ( DirectoryPath, Field, @@ -39,11 +40,12 @@ Terminal, UserDemand, ) -from ribasim.geometry.edge import EdgeTable +from ribasim.geometry.edge import EdgeSchema, EdgeTable from ribasim.geometry.node import NodeTable from ribasim.input_base import ( ChildModel, FileModel, + SpatialTableModel, context_file_loading, ) from ribasim.utils import MissingOptionalModule @@ -57,6 +59,7 @@ class Model(FileModel): starttime: datetime.datetime endtime: datetime.datetime + crs: str input_dir: Path = Field(default=Path(".")) results_dir: Path = Field(default=Path("results")) @@ -97,6 +100,13 @@ def set_node_parent(self) -> "Model": setattr(v, "_parent_field", k) return self + @model_validator(mode="after") + def ensure_edge_table_is_present(self) -> "Model": + if self.edge.df is None: + self.edge.df = GeoDataFrame[EdgeSchema]() + self.edge.df.set_geometry("geometry", inplace=True, crs=self.crs) + return self + @field_serializer("input_dir", "results_dir") def serialize_path(self, path: Path) -> str: return str(path) @@ -151,6 +161,7 @@ def _write_toml(self, fn: Path) -> Path: return fn def _save(self, directory: DirectoryPath, input_dir: DirectoryPath): + self.set_crs(self.crs) db_path = directory / input_dir / "database.gpkg" db_path.parent.mkdir(parents=True, exist_ok=True) db_path.unlink(missing_ok=True) @@ -170,9 +181,19 @@ def _save(self, directory: DirectoryPath, input_dir: DirectoryPath): for sub in self._nodes(): sub._save(directory, input_dir) + def set_crs(self, crs: str) -> None: + self.crs = crs + self.edge.df = self.edge.df.set_crs(crs) + for sub in self._nodes(): + if sub.node.df is not None: + sub.node.df = sub.node.df.set_crs(crs) + for table in sub._tables(): + if isinstance(table, SpatialTableModel) and table.df is not None: + table.df = table.df.set_crs(crs) + def node_table(self) -> NodeTable: """Compute the full NodeTable from all node types.""" - df_chunks = [node.node.df for node in self._nodes()] + df_chunks = [node.node.df.set_crs(self.crs) for node in self._nodes()] df = pd.concat(df_chunks, ignore_index=True) node_table = NodeTable(df=df) node_table.sort() @@ -392,12 +413,6 @@ def to_xugrid(self): name="node_index", ) - if node_df.crs is None: - # TODO: can be removed when CRS is required, #1254 - projected = False - else: - projected = node_df.crs.is_projected - grid = xugrid.Ugrid1d( node_x=node_df.geometry.x, node_y=node_df.geometry.y, @@ -409,7 +424,7 @@ def to_xugrid(self): ) ), name="ribasim", - projected=projected, + projected=node_df.crs.is_projected, crs=node_df.crs, ) diff --git a/python/ribasim/tests/test_io.py b/python/ribasim/tests/test_io.py index e0b316106..46edcfbd6 100644 --- a/python/ribasim/tests/test_io.py +++ b/python/ribasim/tests/test_io.py @@ -117,7 +117,7 @@ def test_sort(level_setpoint_with_minmax, tmp_path): model.write(tmp_path / "basic/ribasim.toml") # write sorts the model in place assert table.df.iloc[0]["greater_than"] == 5.0 - model_loaded = ribasim.Model(filepath=tmp_path / "basic/ribasim.toml") + model_loaded = ribasim.Model.read(filepath=tmp_path / "basic/ribasim.toml") table_loaded = model_loaded.discrete_control.condition edge_loaded = model_loaded.edge assert table_loaded.df.iloc[0]["greater_than"] == 5.0 @@ -153,7 +153,9 @@ def test_roundtrip(trivial, tmp_path): def test_datetime_timezone(): # Due to a pydantic issue, a time zone was added. # https://github.com/Deltares/Ribasim/issues/1282 - model = ribasim.Model(starttime="2000-01-01", endtime="2001-01-01 00:00:00") + model = ribasim.Model( + starttime="2000-01-01", endtime="2001-01-01 00:00:00", crs="EPSG:28992" + ) assert isinstance(model.starttime, datetime) assert isinstance(model.endtime, datetime) assert model.starttime.tzinfo is None diff --git a/python/ribasim/tests/test_model.py b/python/ribasim/tests/test_model.py index 10d342b48..001ab889f 100644 --- a/python/ribasim/tests/test_model.py +++ b/python/ribasim/tests/test_model.py @@ -6,6 +6,7 @@ import pytest import xugrid from pydantic import ValidationError +from pyproj import CRS from ribasim.config import Solver from ribasim.geometry.edge import NodeData from ribasim.input_base import esc_id @@ -136,9 +137,11 @@ def test_node_ids_unsequential(basic): def test_tabulated_rating_curve_model(tabulated_rating_curve, tmp_path): model_orig = tabulated_rating_curve + model_orig.set_crs(model_orig.crs) basin_area = tabulated_rating_curve.basin.area.df assert basin_area is not None assert basin_area.geometry.geom_type.iloc[0] == "Polygon" + assert basin_area.crs == CRS.from_epsg(28992) model_orig.write(tmp_path / "tabulated_rating_curve/ribasim.toml") model_new = Model.read(tmp_path / "tabulated_rating_curve/ribasim.toml") pd.testing.assert_series_equal( @@ -186,6 +189,16 @@ def test_node_table(basic): assert df.subnetwork_id.dtype == pd.Int32Dtype() assert df.node_type.iloc[0] == "Basin" assert df.node_type.iloc[-1] == "Terminal" + assert df.crs == CRS.from_epsg(28992) + + +def test_edge_table(basic): + model = basic + df = model.edge.df + assert df.geometry.is_unique + assert df.from_node_id.dtype == np.int32 + assert df.subnetwork_id.dtype == pd.Int32Dtype() + assert df.crs == CRS.from_epsg(28992) def test_indexing(basic): @@ -224,7 +237,7 @@ def test_xugrid(basic, tmp_path): assert isinstance(uds, xugrid.UgridDataset) assert uds.grid.edge_dimension == "ribasim_nEdges" assert uds.grid.node_dimension == "ribasim_nNodes" - assert uds.grid.crs is None + assert uds.grid.crs == CRS.from_epsg(28992) assert uds.node_id.dtype == np.int32 uds.ugrid.to_netcdf(tmp_path / "ribasim.nc") uds = xugrid.open_dataset(tmp_path / "ribasim.nc") diff --git a/python/ribasim_testmodels/ribasim_testmodels/allocation.py b/python/ribasim_testmodels/ribasim_testmodels/allocation.py index 2ff7bac8b..05ce8d5d7 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/allocation.py +++ b/python/ribasim_testmodels/ribasim_testmodels/allocation.py @@ -28,6 +28,7 @@ def user_demand_model() -> Model: model = Model( starttime="2020-01-01", endtime="2021-01-01", + crs="EPSG:28992", solver=Solver(algorithm="Tsit5"), ) @@ -78,6 +79,7 @@ def subnetwork_model() -> Model: model = Model( starttime="2020-01-01", endtime="2020-04-01", + crs="EPSG:28992", allocation=Allocation(use_allocation=True, timestep=86400), ) @@ -162,6 +164,7 @@ def looped_subnetwork_model() -> Model: model = Model( starttime="2020-01-01", endtime="2021-01-01", + crs="EPSG:28992", allocation=Allocation(use_allocation=True, timestep=86400), ) @@ -288,6 +291,7 @@ def minimal_subnetwork_model() -> Model: model = Model( starttime="2020-01-01", endtime="2021-01-01", + crs="EPSG:28992", allocation=Allocation(use_allocation=True, timestep=86400), ) @@ -346,6 +350,7 @@ def fractional_flow_subnetwork_model() -> Model: model = Model( starttime="2020-01-01", endtime="2021-01-01", + crs="EPSG:28992", allocation=Allocation(use_allocation=True, timestep=86400), ) @@ -433,6 +438,7 @@ def allocation_example_model() -> Model: model = Model( starttime="2020-01-01", endtime="2020-01-20", + crs="EPSG:28992", allocation=Allocation(use_allocation=True, timestep=86400), ) @@ -545,6 +551,7 @@ def main_network_with_subnetworks_model() -> Model: model = Model( starttime="2020-01-01", endtime="2020-03-01", + crs="EPSG:28992", allocation=Allocation(use_allocation=True, timestep=86400), ) @@ -849,6 +856,7 @@ def level_demand_model() -> Model: model = Model( starttime="2020-01-01", endtime="2020-02-01", + crs="EPSG:28992", allocation=Allocation(use_allocation=True, timestep=1e5), ) model.flow_boundary.add( @@ -897,6 +905,7 @@ def flow_demand_model() -> Model: model = Model( starttime="2020-01-01 00:00:00", endtime="2021-01-01 00:00:00", + crs="EPSG:28992", allocation=Allocation(use_allocation=True, timestep=1e5), ) @@ -972,6 +981,7 @@ def linear_resistance_demand_model(): model = Model( starttime="2020-01-01 00:00:00", endtime="2021-01-01 00:00:00", + crs="EPSG:28992", allocation=Allocation(use_allocation=True), ) diff --git a/python/ribasim_testmodels/ribasim_testmodels/backwater.py b/python/ribasim_testmodels/ribasim_testmodels/backwater.py index a01d563e0..0a70a3fbb 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/backwater.py +++ b/python/ribasim_testmodels/ribasim_testmodels/backwater.py @@ -23,6 +23,7 @@ def backwater_model(): model = ribasim.Model( starttime="2020-01-01", endtime="2021-01-01", + crs="EPSG:28992", ) model.flow_boundary.add( diff --git a/python/ribasim_testmodels/ribasim_testmodels/basic.py b/python/ribasim_testmodels/ribasim_testmodels/basic.py index 3ee3e6dda..271267b76 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/basic.py +++ b/python/ribasim_testmodels/ribasim_testmodels/basic.py @@ -25,6 +25,7 @@ def basic_model() -> ribasim.Model: model = ribasim.Model( starttime="2020-01-01", endtime="2021-01-01", + crs="EPSG:28992", ) model.logging = ribasim.Logging(verbosity="debug") @@ -243,6 +244,7 @@ def tabulated_rating_curve_model() -> ribasim.Model: model = ribasim.Model( starttime="2020-01-01", endtime="2021-01-01", + crs="EPSG:28992", ) # Setup tabulated rating curve: @@ -320,6 +322,7 @@ def outlet_model(): model = ribasim.Model( starttime="2020-01-01", endtime="2021-01-01", + crs="EPSG:28992", solver=ribasim.Solver(saveat=0), ) diff --git a/python/ribasim_testmodels/ribasim_testmodels/bucket.py b/python/ribasim_testmodels/ribasim_testmodels/bucket.py index 248ed3b8f..66ffe2abb 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/bucket.py +++ b/python/ribasim_testmodels/ribasim_testmodels/bucket.py @@ -14,6 +14,7 @@ def bucket_model() -> ribasim.Model: model = ribasim.Model( starttime="2020-01-01", endtime="2021-01-01", + crs="EPSG:28992", ) model.basin.add( @@ -42,6 +43,7 @@ def leaky_bucket_model() -> ribasim.Model: model = ribasim.Model( starttime="2020-01-01", endtime="2020-01-05", + crs="EPSG:28992", ) model.basin.add( diff --git a/python/ribasim_testmodels/ribasim_testmodels/discrete_control.py b/python/ribasim_testmodels/ribasim_testmodels/discrete_control.py index ab48a4696..aae7674c9 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/discrete_control.py +++ b/python/ribasim_testmodels/ribasim_testmodels/discrete_control.py @@ -22,6 +22,7 @@ def pump_discrete_control_model() -> Model: model = Model( starttime="2020-01-01", endtime="2021-01-01", + crs="EPSG:28992", ) model.basin.add( @@ -115,6 +116,7 @@ def flow_condition_model() -> Model: model = Model( starttime="2020-01-01", endtime="2021-01-01", + crs="EPSG:28992", ) model.flow_boundary.add( @@ -175,6 +177,7 @@ def level_boundary_condition_model() -> Model: model = Model( starttime="2020-01-01", endtime="2021-01-01", + crs="EPSG:28992", ) model.level_boundary.add( @@ -246,6 +249,7 @@ def tabulated_rating_curve_control_model() -> Model: model = Model( starttime="2020-01-01", endtime="2021-01-01", + crs="EPSG:28992", ) model.basin.add( @@ -309,6 +313,7 @@ def level_setpoint_with_minmax_model() -> Model: model = Model( starttime="2020-01-01", endtime="2021-01-01", + crs="EPSG:28992", ) model.basin.add( diff --git a/python/ribasim_testmodels/ribasim_testmodels/dutch_waterways.py b/python/ribasim_testmodels/ribasim_testmodels/dutch_waterways.py index fc50e84ec..fd990957b 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/dutch_waterways.py +++ b/python/ribasim_testmodels/ribasim_testmodels/dutch_waterways.py @@ -21,6 +21,7 @@ def dutch_waterways_model() -> Model: model = Model( starttime="2020-01-01", endtime="2021-01-01", + crs="EPSG:28992", ) profile_level = np.array([1.86, 3.21, 4.91, 6.61, 8.31, 10.07, 10.17, 10.27, 11.61, 12.94, 13.05, 13.69, 14.32, 14.96, 15.59]) # fmt: skip @@ -45,30 +46,33 @@ def dutch_waterways_model() -> Model: a = 800 - b flow_rate = a * flow_rate + b - # TODO use EPSG:28992 and apply 405 - y to the y coordinates model.flow_boundary.add( - Node(1, Point(1310, 312)), + Node(1, Point(196212, 436220)), [flow_boundary.Time(time=time, flow_rate=flow_rate)], ) model.basin.add( - Node(2, Point(1281, 278), name="IJsselkop"), + Node(2, Point(194292, 439828), name="IJsselkop"), [basin.State(level=[8.31]), basin_profile], ) - model.linear_resistance.add(Node(3, Point(1283, 183)), linear_resistance_shared) - model.linear_resistance.add(Node(4, Point(1220, 186)), linear_resistance_shared) + model.linear_resistance.add( + Node(3, Point(195237, 442337)), linear_resistance_shared + ) + model.linear_resistance.add( + Node(4, Point(187489, 442384)), linear_resistance_shared + ) model.basin.add( - Node(5, Point(1342, 162), name="IJssel Westervoort"), + Node(5, Point(199198, 445557), name="IJssel Westervoort"), [basin.State(level=[7.5]), basin_profile], ) model.basin.add( - Node(6, Point(1134, 184), name="Nederrijn Arnhem"), + Node(6, Point(184906, 441999), name="Nederrijn Arnhem"), [basin.State(level=[7.5]), basin_profile], ) model.level_boundary.add( - Node(7, Point(1383, 121)), [level_boundary.Static(level=[3.0])] + Node(7, Point(208272, 454422)), [level_boundary.Static(level=[3.0])] ) model.tabulated_rating_curve.add( - Node(8, Point(1052, 201), name="Driel open"), + Node(8, Point(183819, 442076), name="Driel open"), [ tabulated_rating_curve.Static( control_state=["pump_low", "pump_high", "rating_curve", "rating_curve"], @@ -81,7 +85,7 @@ def dutch_waterways_model() -> Model: ], ) model.pump.add( - Node(9, Point(1043, 188), name="Driel gecontroleerd"), + Node(9, Point(183859, 441561), name="Driel gecontroleerd"), [ pump.Static( active=[True, True, False], @@ -91,29 +95,31 @@ def dutch_waterways_model() -> Model: ], ) model.basin.add( - Node(10, Point(920, 197)), [basin.State(level=[7.0]), basin_profile] + Node(10, Point(178532, 442187)), [basin.State(level=[7.0]), basin_profile] + ) + model.linear_resistance.add( + Node(11, Point(170775, 439396)), linear_resistance_shared ) - model.linear_resistance.add(Node(11, Point(783, 237)), linear_resistance_shared) model.basin.add( - Node(12, Point(609, 186)), [basin.State(level=[6.0]), basin_profile] + Node(12, Point(162995, 443270)), [basin.State(level=[6.0]), basin_profile] ) model.tabulated_rating_curve.add( - Node(13, Point(430, 176), name="Amerongen open"), + Node(13, Point(156421, 443460), name="Amerongen open"), [tabulated_rating_curve.Static(level=[4.45, 4.46], flow_rate=[418, 420.15])], ) model.pump.add( - Node(14, Point(442, 164), name="Amerongen gecontroleerd"), + Node(14, Point(156882, 441920), name="Amerongen gecontroleerd"), [pump.Static(flow_rate=[1.0], min_flow_rate=0.0, max_flow_rate=50.0)], ) model.basin.add( - Node(15, Point(369, 185)), [basin.State(level=[5.5]), basin_profile] + Node(15, Point(154547, 442540)), [basin.State(level=[5.5]), basin_profile] ) model.level_boundary.add( - Node(16, Point(329, 202), name="Kruising ARK"), + Node(16, Point(151776, 441465), name="Kruising ARK"), [level_boundary.Static(level=[3.0])], ) model.discrete_control.add( - Node(17, Point(1187, 276), name="Controller Driel"), + Node(17, Point(183612, 441833), name="Controller Driel"), [ discrete_control.Condition( listen_node_type="FlowBoundary", @@ -133,10 +139,14 @@ def dutch_waterways_model() -> Model: ), ], ) - model.linear_resistance.add(Node(18, Point(1362, 142)), linear_resistance_shared) - model.linear_resistance.add(Node(19, Point(349, 194)), linear_resistance_shared) + model.linear_resistance.add( + Node(18, Point(201507, 447443)), linear_resistance_shared + ) + model.linear_resistance.add( + Node(19, Point(153039, 442444)), linear_resistance_shared + ) model.pid_control.add( - Node(20, Point(511, 126), name="Controller Amerongen"), + Node(20, Point(155961, 442714), name="Controller Amerongen"), [ pid_control.Static( listen_node_type="Basin", diff --git a/python/ribasim_testmodels/ribasim_testmodels/equations.py b/python/ribasim_testmodels/ribasim_testmodels/equations.py index 47f439f1d..9ffe4c715 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/equations.py +++ b/python/ribasim_testmodels/ribasim_testmodels/equations.py @@ -24,6 +24,7 @@ def linear_resistance_model() -> Model: model = Model( starttime="2020-01-01", endtime="2021-01-01", + crs="EPSG:28992", ) model.basin.add( @@ -54,6 +55,7 @@ def rating_curve_model() -> Model: model = Model( starttime="2020-01-01", endtime="2021-01-01", + crs="EPSG:28992", ) model.basin.add( @@ -92,6 +94,7 @@ def manning_resistance_model() -> Model: model = Model( starttime="2020-01-01", endtime="2021-01-01", + crs="EPSG:28992", ) basin_profile = basin.Profile(area=[0.01, 100.0, 100.0], level=[0.0, 1.0, 2.0]) @@ -125,6 +128,7 @@ def misc_nodes_model() -> Model: model = Model( starttime="2020-01-01", endtime="2021-01-01", + crs="EPSG:28992", solver=Solver(dt=24 * 60 * 60, algorithm="Euler"), ) @@ -179,8 +183,7 @@ def pid_control_equation_model() -> Model: """Set up a model with pid control for an analytical solution test""" model = Model( - starttime="2020-01-01", - endtime="2020-01-01 00:05:00", + starttime="2020-01-01", endtime="2020-01-01 00:05:00", crs="EPSG:28992" ) model.basin.add( Node(1, Point(0, 0)), diff --git a/python/ribasim_testmodels/ribasim_testmodels/invalid.py b/python/ribasim_testmodels/ribasim_testmodels/invalid.py index 4eb92ed8d..906a7b485 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/invalid.py +++ b/python/ribasim_testmodels/ribasim_testmodels/invalid.py @@ -19,6 +19,7 @@ def invalid_qh_model() -> Model: model = Model( starttime="2020-01-01", endtime="2020-12-01", + crs="EPSG:28992", ) model.tabulated_rating_curve.add( @@ -55,6 +56,7 @@ def invalid_fractional_flow_model() -> Model: model = Model( starttime="2020-01-01", endtime="2020-12-01", + crs="EPSG:28992", ) basin_shared: list[TableModel[Any]] = [ @@ -118,6 +120,7 @@ def invalid_discrete_control_model() -> Model: model = Model( starttime="2020-01-01", endtime="2020-12-01", + crs="EPSG:28992", ) basin_shared: list[TableModel[Any]] = [ @@ -187,6 +190,7 @@ def invalid_edge_types_model() -> Model: model = Model( starttime="2020-01-01", endtime="2020-12-01", + crs="EPSG:28992", ) basin_shared: list[TableModel[Any]] = [ diff --git a/python/ribasim_testmodels/ribasim_testmodels/pid_control.py b/python/ribasim_testmodels/ribasim_testmodels/pid_control.py index 803d2872f..d8c591c09 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/pid_control.py +++ b/python/ribasim_testmodels/ribasim_testmodels/pid_control.py @@ -19,6 +19,7 @@ def pid_control_model() -> Model: model = Model( starttime="2020-01-01", endtime="2020-12-01", + crs="EPSG:28992", ) model.flow_boundary.add( @@ -92,6 +93,7 @@ def discrete_control_of_pid_control_model() -> Model: model = Model( starttime="2020-01-01", endtime="2020-12-01", + crs="EPSG:28992", ) model.level_boundary.add( diff --git a/python/ribasim_testmodels/ribasim_testmodels/time.py b/python/ribasim_testmodels/ribasim_testmodels/time.py index 4ccc0996a..64e006d8a 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/time.py +++ b/python/ribasim_testmodels/ribasim_testmodels/time.py @@ -12,6 +12,7 @@ def flow_boundary_time_model() -> Model: model = Model( starttime="2020-01-01", endtime="2021-01-01", + crs="EPSG:28992", ) model.flow_boundary.add( diff --git a/python/ribasim_testmodels/ribasim_testmodels/trivial.py b/python/ribasim_testmodels/ribasim_testmodels/trivial.py index 177d2725e..ad3669eb3 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/trivial.py +++ b/python/ribasim_testmodels/ribasim_testmodels/trivial.py @@ -10,6 +10,7 @@ def trivial_model() -> Model: model = Model( starttime="2020-01-01", endtime="2021-01-01", + crs="EPSG:28992", results=Results(subgrid=True, compression=False), ) diff --git a/python/ribasim_testmodels/ribasim_testmodels/two_basin.py b/python/ribasim_testmodels/ribasim_testmodels/two_basin.py index 7ba030edb..9cedb312f 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/two_basin.py +++ b/python/ribasim_testmodels/ribasim_testmodels/two_basin.py @@ -19,7 +19,7 @@ def two_basin_model() -> Model: The right basin fills up and discharges over the rating curve. """ - model = Model(starttime="2020-01-01", endtime="2021-01-01") + model = Model(starttime="2020-01-01", endtime="2021-01-01", crs="EPSG:28992") model.flow_boundary.add( Node(1, Point(0, 0)), [flow_boundary.Static(flow_rate=[1e-2])]