Skip to content

Commit 42b9204

Browse files
committed
split hydro functionality into runoff and discharge based
1 parent bb85cd7 commit 42b9204

2 files changed

Lines changed: 111 additions & 2 deletions

File tree

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,7 @@ paper
2929
.vscode
3030
AGENTS.md
3131
uv.lock
32+
33+
tmp
34+
test_ba
35+
data

atlite/convert.py

Lines changed: 107 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,8 +1080,7 @@ def runoff(
10801080

10811081
return result
10821082

1083-
1084-
def hydro(
1083+
def _hydro_from_runoff(
10851084
cutout,
10861085
plants,
10871086
hydrobasins,
@@ -1145,6 +1144,112 @@ def hydro(
11451144
basins, runoff, flowspeed, show_progress
11461145
)
11471146

1147+
def _hydro_from_discharge(
1148+
cutout,
1149+
plants,
1150+
):
1151+
"""
1152+
Get inflow time-series for `plants` by extracting the discharge time series for
1153+
the nearest grid points.
1154+
1155+
Parameters
1156+
----------
1157+
plants : pd.DataFrame
1158+
Run-of-river plants or dams with lon, lat columns.
1159+
"""
1160+
print("<"*100)
1161+
print("Extracting discharge time series for nearest grid points to plants...")
1162+
print("<"*100)
1163+
discharge = cutout.data.discharge
1164+
inflow = xr.DataArray(
1165+
np.zeros((len(plants), discharge.indexes["time"].size)),
1166+
[("plant", plants.index), discharge.coords["time"]],
1167+
)
1168+
for plant in plants.itertuples():
1169+
# Extract the discharge time series for the nearest point
1170+
inflow.loc[dict(plant=plant.Index)] = discharge.sel(
1171+
x=plant.lon, y=plant.lat, method="nearest"
1172+
)
1173+
return inflow
1174+
1175+
1176+
def hydro(
1177+
cutout,
1178+
plants,
1179+
module="auto",
1180+
hydrobasins=None,
1181+
flowspeed=1,
1182+
weight_with_height=False,
1183+
show_progress=False,
1184+
**kwargs,
1185+
):
1186+
"""
1187+
Get inflow time-series for `plants` by either extracting the discharge time series for
1188+
the nearest grid points or by computing runoff-based inflow time series
1189+
1190+
Parameters
1191+
----------
1192+
plants : pd.DataFrame
1193+
Run-of-river plants or dams with lon, lat columns.
1194+
module : str
1195+
The method to compute hydro time series. "auto" will prefere discharge but fall back to runoff-based computation
1196+
"glofas" will use discharge directly, "era5" will use runoff-based computation
1197+
hydrobasins : str|gpd.GeoDataFrame
1198+
Filename or GeoDataFrame of one level of the HydroBASINS dataset. Only required
1199+
for runoff-based computation.
1200+
flowspeed : float
1201+
Average speed of water flows to estimate the water travel time from
1202+
basin to plant (default: 1 m/s). Only relevant for runoff-based computation.
1203+
weight_with_height : bool
1204+
Whether surface runoff should be weighted by potential height (probably
1205+
better for coarser resolution). Only relevant for runoff-based computation.
1206+
show_progress : bool
1207+
Whether to display progressbars. Only relevant for runoff-based computation.
1208+
**kwargs
1209+
Additional arguments for runoff-based computation. Only relevant for runoff-based computation.
1210+
"""
1211+
if module == "auto":
1212+
# Check if discharge data is available in cutout, otherwise use runoff
1213+
if "discharge" in cutout.available_features.values:
1214+
return _hydro_from_discharge(
1215+
cutout,
1216+
plants,
1217+
)
1218+
if hydrobasins is None or "runoff" not in cutout.available_features.values:
1219+
raise ValueError("For runoff-based hydro time series, hydrobasins and runoff data must be provided.")
1220+
return _hydro_from_runoff(
1221+
cutout,
1222+
plants,
1223+
hydrobasins,
1224+
flowspeed=flowspeed,
1225+
weight_with_height=weight_with_height,
1226+
show_progress=show_progress,
1227+
**kwargs,
1228+
)
1229+
elif module.lower() == "glofas":
1230+
# Check if discharge data is available in cutout, otherwise raise error
1231+
if "discharge" not in cutout.data_vars:
1232+
raise ValueError("For GloFAS-based hydro time series, the cutout must include discharge data.")
1233+
return _hydro_from_discharge(
1234+
cutout,
1235+
plants,
1236+
)
1237+
elif module.lower() == "era5":
1238+
# Check if hydrobasins is provided, otherwise raise error
1239+
if hydrobasins is None:
1240+
raise ValueError("For ERA5-based hydro time series, the hydrobasins dataset must be provided.")
1241+
return _hydro_from_runoff(
1242+
cutout,
1243+
plants,
1244+
hydrobasins,
1245+
flowspeed=flowspeed,
1246+
weight_with_height=weight_with_height,
1247+
show_progress=show_progress,
1248+
**kwargs,
1249+
)
1250+
else:
1251+
raise ValueError(f'Unknown hydro module option "{module}".')
1252+
11481253

11491254
def convert_line_rating(
11501255
ds, psi, R, D=0.028, Ts=373, epsilon=0.6, alpha=0.6, per_unit=False

0 commit comments

Comments
 (0)