Skip to content

Commit

Permalink
Further addressed comments.
Browse files Browse the repository at this point in the history
  • Loading branch information
evetion committed May 17, 2024
1 parent 6b97f73 commit 4762e4a
Show file tree
Hide file tree
Showing 8 changed files with 28 additions and 226 deletions.
2 changes: 1 addition & 1 deletion coupling/delwaq/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The script can:
- Open an existing Ribasim model (hardcoded to `generated_testmodels/basic/ribasim.toml` for now)
- Convert the metadata, topology and substances to Delwaq format and put it into the `model` folder

You now should manually run Delwaq. You can do so with the Docker image.
You now should manually run Delwaq. If you're an Deltares employee, you can do so with the Docker image.
First install WSL and install docker in WSL, then create a CLI secret and log into the Deltares containers. To install docker in WSL and create a CLI secret for the following steps, follow this guide https://publicwiki.deltares.nl/display/Delft3DContainers/.

Log into Deltares containers in docker:
Expand Down
14 changes: 7 additions & 7 deletions coupling/delwaq/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,21 @@
USE_EVAP = True


def generate(modelfn: Path) -> tuple[nx.DiGraph, set[str]]:
def generate(toml_path: Path) -> tuple[nx.DiGraph, set[str]]:
"""Generate a Delwaq model from a Ribasim model and results."""

# Read in model and results
model = ribasim.Model.read(modelfn)
basins = pd.read_feather(modelfn.parent / "results" / "basin.arrow")
flows = pd.read_feather(modelfn.parent / "results" / "flow.arrow")
model = ribasim.Model.read(toml_path)
basins = pd.read_feather(toml_path.parent / "results" / "basin.arrow")
flows = pd.read_feather(toml_path.parent / "results" / "flow.arrow")

output_folder = delwaq_dir / "model"
output_folder.mkdir(exist_ok=True)

# Simplify network, only keep Basins and Boundaries
G = nx.DiGraph()
for row in model.node_table().df.itertuples():
if "Control" not in row.node_type:
if row.node_type not in ribasim.geometry.edge.SPATIALCONTROLNODETYPES:
G.add_node(
row.node_id,
type=row.node_type,
Expand Down Expand Up @@ -355,5 +355,5 @@ def make_boundary(id, type):
if __name__ == "__main__":
# Generate a Delwaq model from the default Ribasim model
repo_dir = delwaq_dir.parents[1]
modelfn = repo_dir / "generated_testmodels/basic/ribasim.toml"
graph, substances = generate(modelfn)
toml_path = repo_dir / "generated_testmodels/basic/ribasim.toml"
graph, substances = generate(toml_path)
8 changes: 4 additions & 4 deletions coupling/delwaq/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
output_folder = delwaq_dir / "model"


def parse(modelfn: Path, graph, substances):
model = ribasim.Model.read(modelfn)
def parse(toml_path: Path, graph, substances) -> ribasim.Model:
model = ribasim.Model.read(toml_path)

# Output of Delwaq
ds = xr.open_dataset(output_folder / "delwaq_map.nc")
Expand Down Expand Up @@ -45,7 +45,7 @@ def parse(modelfn: Path, graph, substances):
df = pd.concat(dfs).reset_index(drop=True)
df.sort_values(["time", "node_id"], inplace=True)

model.basin.concentrationexternal = df
df.to_feather(modelfn.parent / "results" / "basin-concentration-external.arrow")
model.basin.concentration_external = df
df.to_feather(toml_path.parent / "results" / "basin_concentration_external.arrow")

return model
8 changes: 4 additions & 4 deletions coupling/delwaq/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@

def test_offline_delwaq_coupling():
repo_dir = delwaq_dir.parents[1]
modelfn = repo_dir / "generated_testmodels/basic/ribasim.toml"
toml_path = repo_dir / "generated_testmodels/basic/ribasim.toml"

graph, substances = generate(modelfn)
graph, substances = generate(toml_path)
run_delwaq()
model = parse(modelfn, graph, substances)
df = model.basin.concentrationexternal
model = parse(toml_path, graph, substances)

df = model.basin.concentration_external.df
assert df is not None
assert df.shape[0] > 0
assert df.node_id.nunique() == 4
Expand Down
14 changes: 7 additions & 7 deletions coupling/delwaq/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
xugrid = MissingOptionalModule("xugrid")


def strfdelta(tdelta):
def strfdelta(tdelta) -> str:
# dddhhmmss format
days = tdelta.days
hours, rem = divmod(tdelta.seconds, 3600)
minutes, seconds = divmod(rem, 60)
return f"{days:03d}{hours:02d}{minutes:02d}{seconds:02d}"


def write_pointer(fn: Path | str, data: pd.DataFrame):
def write_pointer(fn: Path | str, data: pd.DataFrame) -> None:
"""Write pointer file for Delwaq.
The format is a matrix of int32 of edges
Expand All @@ -40,7 +40,7 @@ def write_pointer(fn: Path | str, data: pd.DataFrame):
f.write(struct.pack("<4i", a, b, 0, 0))


def write_lengths(fn: Path | str, data: np.ndarray[np.float32]):
def write_lengths(fn: Path | str, data: np.ndarray[np.float32]) -> None:
"""Write lengths file for Delwaq.
The format is an int defining time/edges (?)
Expand All @@ -56,7 +56,7 @@ def write_lengths(fn: Path | str, data: np.ndarray[np.float32]):
f.write(data.astype("float32").tobytes())


def write_volumes(fn: Path | str, data: pd.DataFrame, timestep: timedelta):
def write_volumes(fn: Path | str, data: pd.DataFrame, timestep: timedelta) -> None:
"""Write volumes file for Delwaq.
The format is an int defining the time
Expand All @@ -77,7 +77,7 @@ def write_volumes(fn: Path | str, data: pd.DataFrame, timestep: timedelta):
f.write(group.storage.to_numpy().astype("float32").tobytes())


def write_flows(fn: Path | str, data: pd.DataFrame, timestep: timedelta):
def write_flows(fn: Path | str, data: pd.DataFrame, timestep: timedelta) -> None:
"""Write flows file for Delwaq.
The format is an int defining the time
Expand All @@ -98,7 +98,7 @@ def write_flows(fn: Path | str, data: pd.DataFrame, timestep: timedelta):
f.write(group.flow_rate.to_numpy().astype("float32").tobytes())


def ugrid(G):
def ugrid(G) -> xugrid.UgridDataset:
# TODO Deduplicate with ribasim.Model.to_xugrid
edge_df = pd.DataFrame(G.edges(), columns=["from_node_id", "to_node_id"])
node_df = pd.DataFrame(G.nodes(), columns=["node_id"])
Expand Down Expand Up @@ -147,7 +147,7 @@ def ugrid(G):
return uds


def run_delwaq():
def run_delwaq() -> None:
d3d_home = os.environ.get("D3D_HOME")
if d3d_home is None:
raise ValueError("D3D_HOME is not set.")
Expand Down
Loading

0 comments on commit 4762e4a

Please sign in to comment.