22from 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
99def 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 ----------
43170fout = 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 ----------
51176def 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
88203fout .close ()
0 commit comments