@@ -334,17 +334,15 @@ def __init__(
334
334
baseregridder : xESMF BaseRegridder object
335
335
336
336
"""
337
- self .grid_in = grid_in
338
- self .grid_out = grid_out
339
337
self .method = method
340
338
self .reuse_weights = reuse_weights
341
339
self .extrap_method = extrap_method
342
340
self .extrap_dist_exponent = extrap_dist_exponent
343
341
self .extrap_num_src_pnts = extrap_num_src_pnts
344
342
self .ignore_degenerate = ignore_degenerate
345
- self .periodic = getattr (self . grid_in , 'periodic_dim' , None ) is not None
346
- self .sequence_in = isinstance (self . grid_in , (LocStream , Mesh ))
347
- self .sequence_out = isinstance (self . grid_out , (LocStream , Mesh ))
343
+ self .periodic = getattr (grid_in , 'periodic_dim' , None ) is not None
344
+ self .sequence_in = isinstance (grid_in , (LocStream , Mesh ))
345
+ self .sequence_out = isinstance (grid_out , (LocStream , Mesh ))
348
346
349
347
if input_dims is not None and len (input_dims ) != int (not self .sequence_in ) + 1 :
350
348
raise ValueError (f'Wrong number of dimension names in `input_dims` ({ len (input_dims )} .' )
@@ -358,8 +356,8 @@ def __init__(
358
356
359
357
# record grid shape information
360
358
# We need to invert Grid shapes to respect xESMF's convention (y, x).
361
- self .shape_in = self . grid_in .get_shape ()[::- 1 ]
362
- self .shape_out = self . grid_out .get_shape ()[::- 1 ]
359
+ self .shape_in = grid_in .get_shape ()[::- 1 ]
360
+ self .shape_out = grid_out .get_shape ()[::- 1 ]
363
361
self .n_in = self .shape_in [0 ] * self .shape_in [1 ]
364
362
self .n_out = self .shape_out [0 ] * self .shape_out [1 ]
365
363
@@ -369,7 +367,7 @@ def __init__(
369
367
370
368
if not parallel :
371
369
if not reuse_weights and weights is None :
372
- weights = self ._compute_weights () # Dictionary of weights
370
+ weights = self ._compute_weights (grid_in , grid_out ) # Dictionary of weights
373
371
else :
374
372
weights = filename if filename is not None else weights
375
373
@@ -380,7 +378,7 @@ def __init__(
380
378
381
379
# replace zeros by NaN for weight matrix entries of unmapped target cells if specified or a mask is present
382
380
if (
383
- (self . grid_out .mask is not None ) and (self . grid_out .mask [0 ] is not None )
381
+ (grid_out .mask is not None ) and (grid_out .mask [0 ] is not None )
384
382
) or unmapped_to_nan is True :
385
383
self .weights = add_nans_to_weights (self .weights )
386
384
@@ -435,10 +433,10 @@ def _get_default_filename(self):
435
433
436
434
return filename
437
435
438
- def _compute_weights (self ):
436
+ def _compute_weights (self , grid_in , grid_out ):
439
437
regrid = esmf_regrid_build (
440
- self . grid_in ,
441
- self . grid_out ,
438
+ grid_in ,
439
+ grid_out ,
442
440
self .method ,
443
441
extrap_method = self .extrap_method ,
444
442
extrap_dist_exponent = self .extrap_dist_exponent ,
@@ -934,6 +932,9 @@ def __init__(
934
932
parallel = parallel ,
935
933
** kwargs ,
936
934
)
935
+ # Weights are computed, we do not need the grids anymore
936
+ grid_in .destroy ()
937
+ grid_out .destroy ()
937
938
938
939
# Record output grid and metadata
939
940
lon_out , lat_out = _get_lon_lat (ds_out )
@@ -1109,13 +1110,6 @@ def _format_xroutput(self, out, new_dims=None):
1109
1110
1110
1111
return out
1111
1112
1112
- def __del__ (self ):
1113
- # Memory leak issue when regridding over a large number of datasets with xESMF
1114
- # https://github.com/JiaweiZhuang/xESMF/issues/53
1115
- if hasattr (self , 'grid_in' ): # If the init has failed, grid_in isn't there
1116
- self .grid_in .destroy ()
1117
- self .grid_out .destroy ()
1118
-
1119
1113
1120
1114
class SpatialAverager (BaseRegridder ):
1121
1115
def __init__ (
@@ -1249,6 +1243,9 @@ def __init__(
1249
1243
ignore_degenerate = ignore_degenerate ,
1250
1244
unmapped_to_nan = False ,
1251
1245
)
1246
+ # Weights are computed, we do not need the grids anymore
1247
+ grid_in .destroy ()
1248
+ locstream_out .destroy ()
1252
1249
1253
1250
@staticmethod
1254
1251
def _check_polys_length (polys , threshold = 1 ):
@@ -1267,12 +1264,12 @@ def _check_polys_length(polys, threshold=1):
1267
1264
stacklevel = 2 ,
1268
1265
)
1269
1266
1270
- def _compute_weights_and_area (self , mesh_out ):
1267
+ def _compute_weights_and_area (self , grid_in , mesh_out ):
1271
1268
"""Return the weights and the area of the destination mesh cells."""
1272
1269
1273
1270
# Build the regrid object
1274
1271
regrid = esmf_regrid_build (
1275
- self . grid_in ,
1272
+ grid_in ,
1276
1273
mesh_out ,
1277
1274
method = 'conservative' ,
1278
1275
ignore_degenerate = self .ignore_degenerate ,
@@ -1286,10 +1283,9 @@ def _compute_weights_and_area(self, mesh_out):
1286
1283
regrid .dstfield .get_area ()
1287
1284
dstarea = regrid .dstfield .data .copy ()
1288
1285
1289
- esmf_regrid_finalize (regrid )
1290
1286
return w , dstarea
1291
1287
1292
- def _compute_weights (self ):
1288
+ def _compute_weights (self , grid_in , grid_out ):
1293
1289
"""Return weight sparse matrix.
1294
1290
1295
1291
This function first explodes the geometries into a flat list of Polygon exterior objects:
@@ -1315,14 +1311,16 @@ def _compute_weights(self):
1315
1311
mesh_ext = Mesh .from_polygons (exteriors )
1316
1312
1317
1313
# Get weights for external polygons
1318
- w , area = self ._compute_weights_and_area (mesh_ext )
1314
+ w , area = self ._compute_weights_and_area (grid_in , mesh_ext )
1315
+ mesh_ext .destroy () # release mesh memory
1319
1316
1320
1317
# Get weights for interiors and append them to weights from exteriors as a negative contribution.
1321
1318
if len (interiors ) > 0 and not self .ignore_holes :
1322
1319
mesh_int = Mesh .from_polygons (interiors )
1323
1320
1324
1321
# Get weights for interiors
1325
- w_int , area_int = self ._compute_weights_and_area (mesh_int )
1322
+ w_int , area_int = self ._compute_weights_and_area (grid_in , mesh_int )
1323
+ mesh_int .destroy () # release mesh memory
1326
1324
1327
1325
# Append weights from holes as negative weights
1328
1326
# In sparse >= 0.16, a fill_value of -0.0 is different from 0.0 and the concat would fail
@@ -1382,10 +1380,3 @@ def _format_xroutput(self, out, new_dims=None):
1382
1380
out .coords [self ._lat_out_name ] = xr .DataArray (self ._lat_out , dims = (self .geom_dim_name ,))
1383
1381
out .attrs ['regrid_method' ] = self .method
1384
1382
return out
1385
-
1386
- def __del__ (self ):
1387
- # Memory leak issue when regridding over a large number of datasets with xESMF
1388
- # https://github.com/JiaweiZhuang/xESMF/issues/53
1389
- if hasattr (self , 'grid_in' ): # If the init has failed, grid_in isn't there
1390
- self .grid_in .destroy ()
1391
- self .grid_out .destroy ()
0 commit comments