Skip to content

Commit

Permalink
progress
Browse files Browse the repository at this point in the history
  • Loading branch information
visr committed Sep 17, 2024
1 parent 6b52658 commit e019f62
Show file tree
Hide file tree
Showing 6 changed files with 237 additions and 142 deletions.
1 change: 1 addition & 0 deletions docs/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/_site/
/site_libs/
/reference/python/
/tutorial/crystal-basin/
guide/data/
*.html
objects.json
13 changes: 0 additions & 13 deletions docs/guide/examples.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -405,19 +405,6 @@
"ribasim basic/ribasim.toml\n",
"```\n",
"\n",
"From Python you can run it with:\n",
"\n",
"```python\n",
"import subprocess\n",
"result = subprocess.run([cli_path, toml_path], capture_output=True, encoding=\"utf-8\")\n",
"print(result.stderr)\n",
"result.check_returncode()\n",
"```\n",
"\n",
"Where `cli_path` is a string with either the full path to the Ribasim executable, like `r\"c:\\ribasim_windows\\ribasim\"`, or just `\"ribasim\"` in case you added the `ribasim_windows` folder to your PATH.\n",
"\n",
"The `print(result.stderr)` ensures you see the same logging and error messages that you would see in the terminal. And `result.check_returncode()` will throw an error when the simulation was not successful.\n",
"\n",
"After running the model, read back the results:"
]
},
Expand Down
201 changes: 125 additions & 76 deletions docs/tutorial/irrigation-demand.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"from ribasim import Model, Node\n",
"from ribasim.nodes import (\n",
" basin,\n",
" flow_boundary,\n",
" tabulated_rating_curve,\n",
" user_demand,\n",
")\n",
Expand All @@ -36,9 +37,7 @@
"metadata": {},
"outputs": [],
"source": [
"base_dir = Path(\"c:/bin/ribasim\")\n",
"model_dir = base_dir / \"Crystal_Basin\"\n",
"data_path = model_dir / \"data/input/ACTINFLW.csv\"\n",
"base_dir = Path(\"crystal-basin\")\n",
"\n",
"starttime = \"2022-01-01\"\n",
"endtime = \"2023-01-01\"\n",
Expand All @@ -49,6 +48,70 @@
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"These nodes are identical to the previous tutorial:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# FlowBoundary\n",
"data = pd.DataFrame({\n",
" \"time\": pd.date_range(start=\"2022-01-01\", end=\"2023-01-01\", freq=\"MS\"),\n",
" \"main\": [74.7, 57.9, 63.2, 183.9, 91.8, 47.5, 32.6, 27.6, 26.5, 25.1, 39.3, 37.8, 57.9],\n",
" \"minor\": [16.3, 3.8, 3.0, 37.6, 18.2, 11.1, 12.9, 12.2, 11.2, 10.8, 15.1, 14.3, 11.8]\n",
"}) # fmt: skip\n",
"data[\"total\"] = data[\"minor\"] + data[\"main\"]\n",
"main = model.flow_boundary.add(\n",
" Node(1, Point(0.0, 0.0), name=\"main\"),\n",
" [\n",
" flow_boundary.Time(\n",
" time=data.time,\n",
" flow_rate=data.main,\n",
" )\n",
" ],\n",
")\n",
"minor = model.flow_boundary.add(\n",
" Node(2, Point(-3.0, 0.0), name=\"minor\"),\n",
" [\n",
" flow_boundary.Time(\n",
" time=data.time,\n",
" flow_rate=data.minor,\n",
" )\n",
" ],\n",
")\n",
"\n",
"# Basin\n",
"confluence = model.basin.add(\n",
" Node(3, Point(-1.5, -1), name=\"confluence\"),\n",
" [\n",
" basin.Profile(area=[672000, 5600000], level=[0, 6]),\n",
" basin.State(level=[4]),\n",
" basin.Time(time=[starttime, endtime]),\n",
" ],\n",
")\n",
"\n",
"# TabulatedRatingCurve\n",
"weir = model.tabulated_rating_curve.add(\n",
" Node(4, Point(-1.5, -1.5), name=\"weir\"),\n",
" [\n",
" tabulated_rating_curve.Static(\n",
" level=[0.0, 2, 5],\n",
" flow_rate=[0.0, 50, 200],\n",
" )\n",
" ],\n",
")\n",
"\n",
"# Terminal\n",
"sea = model.terminal.add(Node(5, Point(-1.5, -3.0), name=\"sea\"))"
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand All @@ -72,7 +135,7 @@
"metadata": {},
"source": [
"### Add a second Basin node\n",
"Basin #3 will portray as the point in the river where the diversion takes place, getting the name `diversion`.\n",
"This Basin will portray as the point in the river where the diversion takes place, getting the name `diversion`.\n",
"Its profile area at this intersection is slightly smaller than at the confluence."
]
},
Expand All @@ -82,22 +145,13 @@
"metadata": {},
"outputs": [],
"source": [
"model.basin.add(\n",
" Node(3, Point(-0.75, -0.5), name=\"diversion\"),\n",
"diversion_basin = model.basin.add(\n",
" Node(6, Point(-0.75, -0.5), name=\"diversion_basin\"),\n",
" [\n",
" basin.Profile(area=[500000, 5000000], level=[0, 6]),\n",
" basin.State(level=[3]),\n",
" basin.Time(time=[starttime, endtime]),\n",
" ],\n",
")\n",
"\n",
"model.basin.add(\n",
" Node(4, Point(-1.5, -1), name=\"confluence\"),\n",
" [\n",
" basin.Profile(area=[672000, 5600000], level=[0, 6]),\n",
" basin.State(level=[4]),\n",
" basin.Time(time=[starttime, endtime]),\n",
" ],\n",
")"
]
},
Expand All @@ -106,11 +160,11 @@
"metadata": {},
"source": [
"### Add the irrigation demand\n",
"A big farm company needs to apply irrigation to its field starting from April to September.\n",
"The irrigated field is $> 17000 \\text{ ha}$ and requires around $5 \\text{ mm/day}$.\n",
"In this case the farm company diverts from the main river an average flow rate of $10 \\text{ m}^3/\\text{s}$ and $12 \\text{ m}^3/\\text{s}$ during spring and summer, respectively.\n",
"An irrigation district needs to apply irrigation to its field starting from April to September.\n",
"The irrigated area is $> 17000 \\text{ ha}$ and requires around $5 \\text{ mm/day}$.\n",
"In this case the irrigation district diverts from the main river an average flow rate of $10 \\text{ m}^3/\\text{s}$ and $12 \\text{ m}^3/\\text{s}$ during spring and summer, respectively.\n",
"Start of irrigation takes place on the 1st of April until the end of August.\n",
"The farmer taps water through a canal (demand).\n",
"The water intake is through a canal (demand).\n",
"\n",
"For now, let's assume the return flow remains $0.0$ (`return_factor`).\n",
"Meaning all the supplied water to fulfill the demand is consumed and does not return back to the river.\n",
Expand All @@ -123,8 +177,8 @@
"metadata": {},
"outputs": [],
"source": [
"model.user_demand.add(\n",
" Node(6, Point(-1.5, 1.0), name=\"IrrA\"),\n",
"irrigation = model.user_demand.add(\n",
" Node(7, Point(-1.5, 1.0), name=\"irrigation\"),\n",
" [\n",
" user_demand.Time(\n",
" demand=[0.0, 0.0, 10, 12, 12, 0.0],\n",
Expand All @@ -149,7 +203,7 @@
"metadata": {},
"source": [
"### Add a TabulatedRatingCurve\n",
"The second TabulatedRatingCurve node will simulate the rest of the water that is left after diverting a part from the main river to the farm field.\n",
"The second TabulatedRatingCurve node will simulate the rest of the water that is left after diverting a part from the main river to the irrigation disctrict.\n",
"The rest of the water will flow naturally towards the confluence:"
]
},
Expand All @@ -159,8 +213,8 @@
"metadata": {},
"outputs": [],
"source": [
"model.tabulated_rating_curve.add(\n",
" Node(7, Point(-1.125, -0.75), name=\"MainDiv\"),\n",
"diversion_weir = model.tabulated_rating_curve.add(\n",
" Node(8, Point(-1.125, -0.75), name=\"diversion_weir\"),\n",
" [\n",
" tabulated_rating_curve.Static(\n",
" level=[0.0, 1.5, 5],\n",
Expand All @@ -174,12 +228,23 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"It is up to the user to renumber the IDs of the nodes.\n",
"Applying the ID number based on the order of the nodes from up- to downstream keeps it more organized, but not necessary.\n",
"\n",
"### Adjust the Terminal node ID and edges\n",
"Adjust the Terminal node ID.\n",
"Since we added more nodes we have more edges. Add and adjust the edges:"
"### Add edges"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"model.edge.add(main, diversion_basin)\n",
"model.edge.add(minor, confluence)\n",
"model.edge.add(diversion_basin, irrigation)\n",
"model.edge.add(irrigation, confluence)\n",
"model.edge.add(diversion_basin, diversion_weir)\n",
"model.edge.add(diversion_weir, confluence)\n",
"model.edge.add(confluence, weir)\n",
"model.edge.add(weir, sea)"
]
},
{
Expand All @@ -188,16 +253,9 @@
"metadata": {},
"outputs": [],
"source": [
"model.terminal.add(Node(8, Point(-1.5, -3.0), name=\"Terminal\"))\n",
"\n",
"model.edge.add(model.flow_boundary[1], model.basin[3])\n",
"model.edge.add(model.flow_boundary[2], model.basin[4])\n",
"model.edge.add(model.basin[3], model.user_demand[6])\n",
"model.edge.add(model.user_demand[6], model.basin[4])\n",
"model.edge.add(model.basin[3], model.tabulated_rating_curve[7])\n",
"model.edge.add(model.tabulated_rating_curve[7], model.basin[4])\n",
"model.edge.add(model.basin[4], model.tabulated_rating_curve[5])\n",
"model.edge.add(model.tabulated_rating_curve[5], model.terminal[8])"
"toml_path = base_dir / \"Crystal_1.1/ribasim.toml\"\n",
"model.write(toml_path)\n",
"cli_path = \"ribasim\""
]
},
{
Expand All @@ -215,26 +273,27 @@
"metadata": {},
"outputs": [],
"source": [
"model.plot()\n",
"\n",
"toml_path = model_dir / \"Crystal_1.2/ribasim.toml\"\n",
"model.write(toml_path)\n",
"cli_path = base_dir / \"ribasim_windows/ribasim.exe\"\n",
"\n",
"subprocess.run([cli_path, toml_path], check=True)"
"model.plot();"
]
},
{
"cell_type": "markdown",
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"The schematization should look like @fig-cs12.\n",
"\n",
"![Schematization of the Crystal basin with irrigation](https://s3.deltares.nl/ribasim/doc-image/quickstart/Schematization-of-the-Crystal-basin-with-irrigation.png){fig-align=\"left\" #fig-cs12}\n",
"# | include: false\n",
"from subprocess import run\n",
"\n",
"### Name the edges and basins\n",
"The names of each nodes are defined and saved in the geopackage.\n",
"However, in the dataframe this needs to be added by creating a dictionary and map it within the dataframe."
"run(\n",
" [\n",
" \"julia\",\n",
" \"--project=../../core\",\n",
" \"--eval\",\n",
" f'using Ribasim; Ribasim.main(\"{toml_path.as_posix()}\")',\n",
" ],\n",
" check=True,\n",
")"
]
},
{
Expand All @@ -243,31 +302,21 @@
"metadata": {},
"outputs": [],
"source": [
"# Dictionary mapping node_ids to names\n",
"edge_names = {\n",
" (1, 3): \"Main\",\n",
" (2, 4): \"Minor\",\n",
" (3, 6): \"IrrA Demand\",\n",
" (6, 4): \"IrrA Drain\",\n",
" (3, 7): \"Div2Main\",\n",
" (7, 4): \"Main2Conf\",\n",
" (4, 5): \"Conf2TRC\",\n",
" (5, 8): \"TRC2Term\",\n",
"}\n",
"\n",
"# Dictionary mapping basins (node_ids) to names\n",
"node_names = {\n",
" 3: \"Div\",\n",
" 4: \"Conf\",\n",
"}"
"model.plot()\n",
"\n",
"toml_path = base_dir / \"Crystal_1.2/ribasim.toml\"\n",
"model.write(toml_path)\n",
"cli_path = \"ribasim\"\n",
"\n",
"subprocess.run([cli_path, toml_path], check=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Plot and compare the basin results\n",
"Plot the simulated levels and storages at the diverted section (basin 3) and at the confluence (basin 4)."
"### Plot and compare the Basin results\n",
"Plot the simulated levels and storages at the diverted section and at the confluence."
]
},
{
Expand All @@ -276,7 +325,7 @@
"metadata": {},
"outputs": [],
"source": [
"df_basin = pd.read_feather(model_dir / \"Crystal_1.1/results/basin.arrow\")\n",
"df_basin = pd.read_feather(base_dir / \"Crystal_1.1/results/basin.arrow\")\n",
"\n",
"# Create pivot tables and plot for basin data\n",
"df_basin_wide = df_basin.pivot_table(\n",
Expand Down Expand Up @@ -366,7 +415,7 @@
"metadata": {},
"outputs": [],
"source": [
"df_flow = pd.read_feather(model_dir / \"Crystal_1.2/results/flow.arrow\")\n",
"df_flow = pd.read_feather(base_dir / \"Crystal_1.2/results/flow.arrow\")\n",
"df_flow[\"edge\"] = list(zip(df_flow.from_node_id, df_flow.to_node_id))\n",
"df_flow[\"name\"] = df_flow[\"edge\"].map(edge_names)\n",
"\n",
Expand All @@ -379,7 +428,7 @@
")\n",
"\n",
"fig.update_layout(legend_title_text=\"Edge\")\n",
"fig.write_html(model_dir / \"Crystal_1.2/plot_edges.html\")\n",
"fig.write_html(base_dir / \"Crystal_1.2/plot_edges.html\")\n",
"fig.show()"
]
},
Expand Down
Loading

0 comments on commit e019f62

Please sign in to comment.