2828 from namelist import input_art as iart
2929
3030
31- def get_nearest_neighbors (lon_array ,
32- lat_array ,
33- lon_point ,
34- lat_point ,
35- metric = 'haversine' ):
36- """
37- Find the indices of n closest cells in a grid, relative to a given latitude/longitude.
38- The function builds a BallTree from the provided 1D or 2D array of latitude and longitude and queries it to find n nearest neghbors to a given point.
39- Borrowed from iconarray utilities
40- """
41- lon_array , lat_array , lon_point , lat_point = [
42- np .deg2rad (arr )
43- for arr in [lon_array , lat_array , lon_point , lat_point ]
44- ]
45- lon_lat_array = np .column_stack ((lon_array .flatten (), lat_array .flatten ()))
46- points = np .column_stack ((lon_point , lat_point ))
47- indices = BallTree (lon_lat_array , metric = metric ,
48- leaf_size = 3 ).query (points , k = 1 )[1 ].squeeze ()
49- return indices
50-
51-
52- def get_neighbor_index (index , lons , lats , hlon , hlat , idxs ):
53- xx = np .ones ((hlon .size ))
54- idxs [index , :] = get_nearest_neighbors (lons , lats , hlon , hlat [index ] * xx )
31+ def get_neighbor_index (index , hlon , hlat , idxs , ones , balltree ):
32+ points = np .column_stack ((hlon , hlat [index ] * ones ))
33+ idxs [index , :] = balltree .query (points , k = 1 )[1 ].squeeze ()
5534
5635
5736def get_memory_map (mat , filename_mmap ):
@@ -68,31 +47,42 @@ def generate_memory_map(raw_lus, soiltype_memmap_filename,
6847 return lus , idxs
6948
7049
71- def calculate_soil_fraction (tg , lus , idxs , ncpu = 2 ):
50+ def calculate_soil_fraction (target_grid ,
51+ soil_types_raw ,
52+ nearest_target_cell_to_raw_cells ,
53+ ncpu = 13 ):
7254 """
73- lus: LU classes from HWSD data
74- idxs: indices corrsponding to icon grid for each grid in HWSD data
75- tg: ICON grid
55+ target_grid: target ICON grid
56+ soil_types_raw: landuse class for each cell from the HWSD dataset (LU variable)
57+ nearest_target_cell_to_raw_cell: indices of the cell from the target ICON grid which is nearest to each cell of the raw grid (from HWSD dataset)
7658 """
77- soil_types = np .arange (1 , 14 )
78- fracs = np .zeros ((tg .lons .size , soil_types .size ))
79- grid_ids , grid_counts = np .unique (idxs , return_counts = True )
80-
81- def get_fraction_per_soil_type (lu ):
82- grid_class , grid_count = np .unique (np .where (lus == lu , idxs , - 1 ),
83- return_counts = True )
84- for grid_id in np .arange (tg .lons .size ):
85- frac = np .array (grid_count [grid_class == grid_id ] /
86- grid_counts [grid_ids == grid_id ])
87- if len (frac ) != 0 :
88- fracs [grid_id , lu - 1 ] = frac
89-
90- Parallel (n_jobs = ncpu ,
59+ ncells_target = target_grid .lons .size
60+ nsoil_types = 13
61+ nthreads = min (nsoil_types , ncpu )
62+
63+ soil_ids = np .arange (1 , nsoil_types + 1 )
64+ soil_fractions_target = np .zeros ((ncells_target , nsoil_types ))
65+
66+ n_nearest_raw_cells = np .bincount (nearest_target_cell_to_raw_cells .ravel (),
67+ minlength = ncells_target )
68+
69+ def get_fraction_per_soil_type (soil_id ):
70+ n_nearest_raw_cells_with_soil_type = np .bincount (
71+ nearest_target_cell_to_raw_cells [soil_types_raw == soil_id ],
72+ minlength = ncells_target )
73+
74+ np .divide (n_nearest_raw_cells_with_soil_type ,
75+ n_nearest_raw_cells ,
76+ out = soil_fractions_target [:, soil_id - 1 ],
77+ where = n_nearest_raw_cells != 0 )
78+
79+ Parallel (n_jobs = nthreads ,
9180 max_nbytes = '100M' ,
9281 mmap_mode = 'w+' ,
93- backend = 'threading' )(delayed (get_fraction_per_soil_type )(lu )
94- for lu in tqdm (soil_types ))
95- return fracs
82+ backend = 'threading' )(delayed (get_fraction_per_soil_type )(soil_id )
83+ for soil_id in tqdm (soil_ids ))
84+
85+ return soil_fractions_target
9686
9787
9888# --------------------------------------------------------------------------
@@ -171,6 +161,26 @@ def get_fraction_per_soil_type(lu):
171161lons = np .array (tg .lons )
172162lats = np .array (tg .lats )
173163
164+ vlons = np .array (tg .vlons )
165+ vlats = np .array (tg .vlats )
166+
167+ lon_min = max (np .min (vlons ), - 180.0 )
168+ lon_max = min (np .max (vlons ), 180.0 )
169+ lat_min = max (np .min (vlats ), - 90.0 )
170+ lat_max = min (np .max (vlats ), 90.0 )
171+
172+ lon_mask = (raw_lon >= lon_min ) & (raw_lon <= lon_max )
173+ lat_mask = (raw_lat >= lat_min ) & (raw_lat <= lat_max )
174+
175+ raw_lon = raw_lon [lon_mask ]
176+ raw_lat = raw_lat [lat_mask ]
177+ raw_lus = raw_lus [np .ix_ (lat_mask , lon_mask )]
178+
179+ lons = np .deg2rad (lons )
180+ lats = np .deg2rad (lats )
181+ raw_lon = np .deg2rad (raw_lon )
182+ raw_lat = np .deg2rad (raw_lat )
183+
174184# --------------------------------------------------------------------------
175185# --------------------------------------------------------------------------
176186logging .info ("" )
@@ -190,17 +200,22 @@ def get_fraction_per_soil_type(lu):
190200)
191201logging .info ("" )
192202
203+ lon_lat_array = np .column_stack ((lons .ravel (), lats .ravel ()))
204+ balltree = BallTree (lon_lat_array , metric = "haversine" , leaf_size = 3 )
205+
206+ ones = np .ones ((raw_lon .size ))
207+
193208nrows = np .arange (raw_lat .size )
194- Parallel (n_jobs = omp , max_nbytes = '100M' , mmap_mode = 'w+' )(
195- delayed ( get_neighbor_index )(i , lons , lats , raw_lon , raw_lat , neighbor_ids )
196- for i in tqdm (nrows ))
209+ Parallel (n_jobs = omp , max_nbytes = '100M' , mmap_mode = 'w+' )(delayed (
210+ get_neighbor_index )(i , raw_lon , raw_lat , neighbor_ids , ones , balltree )
211+ for i in tqdm (nrows ))
197212
198213# --------------------------------------------------------------------------
199214logging .info ("" )
200215logging .info ("============= Calculate LU Fraction for target grid ========" )
201216logging .info ("" )
202217
203- fracs = calculate_soil_fraction (tg , soil_types , neighbor_ids , ncpu = 2 )
218+ fracs = calculate_soil_fraction (tg , soil_types , neighbor_ids , ncpu = omp )
204219
205220#--------------------------------------------------------------------------
206221#--------------------------------------------------------------------------
0 commit comments