Skip to content

Commit 3eb66a4

Browse files
Yujin ZengYujin Zeng
authored andcommitted
change preproc to produce river_input.nc exactly used in the restarts
1 parent 61a4313 commit 3eb66a4

File tree

1 file changed

+170
-55
lines changed
  • GEOSagcm_GridComp/GEOSphysics_GridComp/GEOSsurface_GridComp/Utils/Raster/preproc/routing_model

1 file changed

+170
-55
lines changed

GEOSagcm_GridComp/GEOSphysics_GridComp/GEOSsurface_GridComp/Utils/Raster/preproc/routing_model/create_river_input.py

Lines changed: 170 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2,50 +2,175 @@
22
from netCDF4 import Dataset
33

44
# Dimensions
5-
nc = 291284
6-
nr = 7250
7-
nl = 3917
5+
nc_len = 291284
6+
nres = 7250
7+
nlake = 3917
88

99
def read_ascii(filename, count, dtype=float):
1010
return np.loadtxt(filename, dtype=dtype, max_rows=count)
1111

1212
# ---------- Catchment datasets ----------
13-
Kstr_catchment = read_ascii("temp/Pfaf_Kstr_PR_fac1_0p35_0p45_0p2_n0p2.txt", nc)
14-
Kv_catchment = read_ascii("temp/Pfaf_Kv_PR_0p35_0p45_0p2_n0p2.txt", nc)
15-
area_catchment = read_ascii("temp/Pfaf_area.txt", nc)
16-
lriv_catchment = read_ascii("temp/Pfaf_lriv_PR.txt", nc)
17-
lstr_catchment = read_ascii("temp/Pfaf_lstr_PR.txt", nc)
18-
Qin_catchment = read_ascii("temp/Pfaf_qin.txt", nc)
19-
Qri_catchment = read_ascii("temp/Pfaf_qri.txt", nc)
20-
Qstr_catchment = read_ascii("temp/Pfaf_qstr.txt", nc)
21-
tosink_catchment = read_ascii("temp/Pfaf_tosink.txt", nc, dtype=int)
22-
dnid_catchment = read_ascii("temp/downstream_1D_new_noadj.txt", nc, dtype=int)
13+
Kstr_catchment = read_ascii("temp/Pfaf_Kstr_PR_fac1_0p35_0p45_0p2_n0p2.txt", nc_len)
14+
Kv_catchment = read_ascii("temp/Pfaf_Kv_PR_0p35_0p45_0p2_n0p2.txt", nc_len)
15+
area_catchment = read_ascii("temp/Pfaf_area.txt", nc_len)
16+
lriv_catchment = read_ascii("temp/Pfaf_lriv_PR.txt", nc_len)
17+
lstr_catchment = read_ascii("temp/Pfaf_lstr_PR.txt", nc_len)
18+
Qin_catchment = read_ascii("temp/Pfaf_qin.txt", nc_len)
19+
Qri_catchment = read_ascii("temp/Pfaf_qri.txt", nc_len)
20+
Qstr_catchment = read_ascii("temp/Pfaf_qstr.txt", nc_len)
21+
tosink_catchment = read_ascii("temp/Pfaf_tosink.txt", nc_len, dtype=int)
22+
dnid_catchment = read_ascii("temp/downstream_1D_new_noadj.txt", nc_len, dtype=int)
23+
area_catchment = area_catchment * 1.e6
24+
lriv_catchment = lriv_catchment * 1.e3
25+
lstr_catchment = lstr_catchment * 1.e3
2326

2427
# ---------- Reservoir datasets ----------
25-
area_reservoir = read_ascii("temp/area_skm_grand.txt", nr)
26-
capmax_reservoir = read_ascii("temp/cap_max_grand.txt", nr)
27-
catid_reservoir = read_ascii("temp/catid_dam_corr_aca_grand5000.txt", nr, dtype=int)
28-
flag_reservoir = read_ascii("temp/flag_all_res.txt", nr, dtype=int)
29-
fldmainsec_reservoir = read_ascii("temp/fldmainsec_grand.txt", nr, dtype=int)
30-
elec_reservoir = read_ascii("temp/hydroelec_grand.txt", nr, dtype=int)
31-
irr_reservoir = read_ascii("temp/irr_grand.txt", nr, dtype=int)
32-
nav_reservoir = read_ascii("temp/nav_grand.txt", nr, dtype=int)
33-
other_reservoir = read_ascii("temp/other_grand.txt", nr, dtype=int)
34-
rec_reservoir = read_ascii("temp/rec_grand.txt", nr, dtype=int)
35-
supply_reservoir = read_ascii("temp/watersupply_grand.txt", nr, dtype=int)
28+
area_grand = read_ascii("temp/area_skm_grand.txt", nres)
29+
cap_grand = read_ascii("temp/cap_max_grand.txt", nres)
30+
catid_grand = read_ascii("temp/catid_dam_corr_aca_grand5000.txt", nres, dtype=int)
31+
flag_grand = read_ascii("temp/flag_all_res.txt", nres, dtype=int)
32+
fld_grand = read_ascii("temp/fldmainsec_grand.txt", nres, dtype=int)
33+
elec_grand = read_ascii("temp/hydroelec_grand.txt", nres, dtype=int)
34+
irr_grand = read_ascii("temp/irr_grand.txt", nres, dtype=int)
35+
nav_grand = read_ascii("temp/nav_grand.txt", nres, dtype=int)
36+
other_grand = read_ascii("temp/other_grand.txt", nres, dtype=int)
37+
rec_grand = read_ascii("temp/rec_grand.txt", nres, dtype=int)
38+
supply_grand = read_ascii("temp/watersupply_grand.txt", nres, dtype=int)
3639

3740
# ---------- Lake datasets ----------
38-
catid_lake = read_ascii("temp/lake_outlet_catid.txt", nl, dtype=int)
39-
flag_lake = read_ascii("temp/lake_outlet_flag_valid_2097.txt", nl, dtype=int)
40-
area_lake = read_ascii("temp/lake_outlet_lakearea.txt", nl)
41+
catid_lake = read_ascii("temp/lake_outlet_catid.txt", nlake, dtype=int)
42+
flag_lake = read_ascii("temp/lake_outlet_flag_valid_2097.txt", nlake, dtype=int)
43+
area_lake = read_ascii("temp/lake_outlet_lakearea.txt", nlake)
44+
45+
46+
# -------------------------------------------------------------------------
47+
# Unit Conversions
48+
# -------------------------------------------------------------------------
49+
# Convert capacity from million cubic meters (MCM) to m3
50+
cap_grand = cap_grand * 1.e6
51+
area_grand= area_grand * 1.e6
52+
area_lake = area_lake * 1.e6
53+
54+
# -------------------------------------------------------------------------
55+
# Initialize Reservoir Properties (Arrays of size nc_len)
56+
# -------------------------------------------------------------------------
57+
cap_res = np.zeros(nc_len, dtype=np.float32)
58+
area_res = np.zeros(nc_len, dtype=np.float32)
59+
area_max_res = np.zeros(nc_len, dtype=np.float32)
60+
wid_res = np.zeros(nc_len, dtype=np.float32)
61+
62+
type_res = np.zeros(nc_len, dtype=int)
63+
fld_res = np.zeros(nc_len, dtype=int)
64+
active_res = np.zeros(nc_len, dtype=int)
65+
66+
# -------------------------------------------------------------------------
67+
# Aggregation Logic
68+
# -------------------------------------------------------------------------
69+
#print("Processing reservoir aggregation...")
70+
71+
# Filter for active reservoirs (flag_grand == 1)
72+
active_mask = flag_grand == 1
73+
74+
# Get indices (adjusting Fortran 1-based index to Python 0-based index)
75+
# Using catid - 1 to map to Python array indices
76+
curr_cids = catid_grand[active_mask] - 1
77+
78+
# Verify indices are within bounds
79+
valid_idx_mask = (curr_cids >= 0) & (curr_cids < nc_len)
80+
curr_cids = curr_cids[valid_idx_mask]
81+
82+
# Slice the data arrays with the same masks
83+
# We need to filter the original arrays by active_mask, then by valid_idx_mask
84+
filtered_cap = cap_grand[active_mask][valid_idx_mask]
85+
filtered_area = area_grand[active_mask][valid_idx_mask]
86+
87+
# Sum up capacities and areas for reservoirs in the same catchment
88+
# np.add.at is equivalent to doing a loop and adding values to specific indices
89+
np.add.at(cap_res, curr_cids, filtered_cap)
90+
np.add.at(area_res, curr_cids, filtered_area)
91+
92+
# Handle flood control flag
93+
# If any active reservoir in the catchment has flood control, set fld_res to 1
94+
# We iterate to simulate the "if(fld_grand(i) == 1)" logic
95+
fld_indices = np.where((flag_grand == 1) & (fld_grand == 1))[0]
96+
fld_cids = catid_grand[fld_indices] - 1
97+
# Filter valid bounds
98+
fld_cids = fld_cids[(fld_cids >= 0) & (fld_cids < nc_len)]
99+
fld_res[fld_cids] = 1
100+
101+
# Handle missing capacity data
102+
cap_res[cap_res == 0.0] = -1.0
103+
104+
# -------------------------------------------------------------------------
105+
# Assign Reservoir Types
106+
# -------------------------------------------------------------------------
107+
# Other(6) -> Rec(5) -> Nav(4) -> Supply(3) -> Elec(2) -> Irr(1).
108+
# Later loops overwrite earlier ones if (area >= area_max).
109+
110+
#print("Assigning reservoir types...")
111+
112+
# Define the order and arrays corresponding to types 6 down to 1
113+
type_configs = [
114+
(6, other_grand),
115+
(5, rec_grand),
116+
(4, nav_grand),
117+
(3, supply_grand),
118+
(2, elec_grand),
119+
(1, irr_grand)
120+
]
121+
122+
for type_id, type_array in type_configs:
123+
# Find all active reservoirs of this type
124+
# Condition: flag_grand == 1 AND type_array == 1
125+
mask = (flag_grand == 1) & (type_array == 1)
126+
indices = np.where(mask)[0]
127+
128+
for idx in indices:
129+
cid = catid_grand[idx] - 1 # 0-based index
130+
131+
if 0 <= cid < nc_len:
132+
# Check if this reservoir is the largest processed so far for this catchment
133+
if area_grand[idx] >= area_max_res[cid]:
134+
type_res[cid] = type_id
135+
area_max_res[cid] = area_grand[idx]
136+
137+
# -------------------------------------------------------------------------
138+
# Set Up Natural Lakes
139+
# -------------------------------------------------------------------------
140+
#print("Processing natural lakes...")
141+
142+
# Filter active lakes with valid catid
143+
lake_mask = (flag_lake == 1) & (catid_lake > 0)
144+
lake_indices = np.where(lake_mask)[0]
145+
146+
for idx in lake_indices:
147+
cid = catid_lake[idx] - 1 # 0-based index
148+
149+
if 0 <= cid < nc_len:
150+
# If no reservoir type assigned yet AND no flood control
151+
if type_res[cid] == 0 and fld_res[cid] == 0:
152+
type_res[cid] = -1 # Type for lake
153+
area_res[cid] = area_lake[idx]
154+
155+
# -------------------------------------------------------------------------
156+
# Final Calculations and Cleanup
157+
# -------------------------------------------------------------------------
158+
# Compute width (sqrt of area)
159+
wid_res = np.sqrt(area_res)
160+
161+
# Mark active reservoirs based on type or flood control status
162+
active_res[:] = 0 # Ensure clean state
163+
# Condition: type_res != 0 OR fld_res == 1
164+
active_condition = (type_res != 0) | (fld_res == 1)
165+
active_res[active_condition] = 1
166+
167+
#print("Processing complete.")
41168

42169
# ---------- Create NetCDF ----------
43170
fout = Dataset("output/river_input.nc", "w", format="NETCDF4")
44171

45172
# define dimensions
46-
fout.createDimension("pfaf", nc)
47-
fout.createDimension("reservoir", nr)
48-
fout.createDimension("lake", nl)
173+
fout.createDimension("tile", nc_len)
49174

50175
# ---------- Create variables ----------
51176
def create_var(name, data, dims, units, long_name):
@@ -56,33 +181,23 @@ def create_var(name, data, dims, units, long_name):
56181
return var
57182

58183
# Catchment variables
59-
create_var("Kstr", Kstr_catchment, ("pfaf",), "1", "K parameter for local streams")
60-
create_var("K", Kv_catchment, ("pfaf",), "1", "K parameter for main rivers")
61-
create_var("lengsc", lriv_catchment, ("pfaf",), "km", "main river length scale")
62-
create_var("lstr", lstr_catchment, ("pfaf",), "km", "local streams length scale")
63-
create_var("qin_clmt", Qin_catchment, ("pfaf",), "m3/s", "climatology of catchment inflow")
64-
create_var("qri_clmt", Qri_catchment, ("pfaf",), "m3/s", "climatology of catchment outflow")
65-
create_var("qstr_clmt", Qstr_catchment, ("pfaf",), "m3/s", "climatology of catchment stream flow")
66-
create_var("downid", dnid_catchment, ("pfaf",), "1", "downstream catchment id")
67-
create_var("area_catch", area_catchment, ("pfaf",), "km2", "catchment area")
184+
create_var("KSTR", np.float32(Kstr_catchment), ("tile",), "1", "K_parameter_for_local_streams")
185+
create_var("K", np.float32(Kv_catchment), ("tile",), "1", "K_parameter_for_main_rivers")
186+
create_var("LENGSC", np.float32(lriv_catchment), ("tile",), "m", "main_river_length_scale")
187+
create_var("LSTR", np.float32(lstr_catchment), ("tile",), "m", "local_streams_length_scale")
188+
create_var("QIN_CLMT", np.float32(Qin_catchment), ("tile",), "m+3 s-1", "climatology_of_catchment_inflow")
189+
create_var("QRI_CLMT", np.float32(Qri_catchment), ("tile",), "m+3 s-1", "climatology_of_catchment_outflow")
190+
create_var("QSTR_CLMT", np.float32(Qstr_catchment), ("tile",), "m+3 s-1", "climatology_of_catchment_stream_flow")
191+
create_var("DOWNID", np.float32(dnid_catchment), ("tile",), "1", "downstream_catchment_id")
192+
create_var("AREA_CATCH", np.float32(area_catchment), ("tile",), "m+2", "catchment_area")
68193

69194
# Reservoir variables
70-
create_var("area_grand", area_reservoir, ("reservoir",), "km2", "reservoir area")
71-
create_var("cap_grand", capmax_reservoir, ("reservoir",), "million m3", "reservoir maximum capacity")
72-
create_var("catid_grand", catid_reservoir, ("reservoir",), "1", "catchment id for reservoir")
73-
create_var("flag_grand", flag_reservoir, ("reservoir",), "1", "active flag for reservoir")
74-
create_var("fld_grand", fldmainsec_reservoir, ("reservoir",), "1", "flood-control flag")
75-
create_var("elec_grand", elec_reservoir, ("reservoir",), "1", "hydro-power flag")
76-
create_var("irr_grand", irr_reservoir, ("reservoir",), "1", "irrigation flag")
77-
create_var("nav_grand", nav_reservoir, ("reservoir",), "1", "navigation flag")
78-
create_var("other_grand", other_reservoir, ("reservoir",), "1", "other use flag")
79-
create_var("rec_grand", rec_reservoir, ("reservoir",), "1", "recreation flag")
80-
create_var("supply_grand", supply_reservoir, ("reservoir",), "1", "water supply flag")
81-
82-
# Lake variables
83-
create_var("catid_lake", catid_lake, ("lake",), "1", "catchment id for lake outlet")
84-
create_var("flag_lake", flag_lake, ("lake",), "1", "active flag for lake")
85-
create_var("area_lake", area_lake, ("lake",), "km2", "lake area")
195+
create_var("ACTIVE_RES", np.float32(active_res), ("tile",), "1", "active_reservoirs")
196+
create_var("CAP_RES", np.float32(cap_res), ("tile",), "m+3", "max_capacity_of_reservoirs")
197+
create_var("FLD_RES", np.float32(fld_res), ("tile",), "1", "flood_control_flag_of_reservoirs")
198+
create_var("TYPE_RES", np.float32(type_res), ("tile",), "1", "type_of_reservoirs")
199+
create_var("WID_RES", np.float32(wid_res), ("tile",), "m", "length_scale_of_reservoirs")
200+
86201

87202
# Close file
88203
fout.close()

0 commit comments

Comments
 (0)