1
- import xarray
1
+ import os
2
+
2
3
import numpy
4
+ import progressbar
3
5
import scipy .sparse
4
6
import scipy .sparse .linalg
5
- import progressbar
6
- import os
7
+ import xarray
7
8
from mpas_tools .io import write_netcdf
8
9
9
- from compass .step import Step
10
10
from compass .ocean .tests .isomip_plus .viz import file_complete
11
+ from compass .step import Step
11
12
12
13
13
14
class Streamfunction (Step ):
@@ -117,14 +118,14 @@ def _compute_overturning_streamfunction(dsMesh, ds, out_dir, dx=2e3, dz=5.,
117
118
if file_complete (ds , osfFileName ):
118
119
return
119
120
120
- xMin = 320e3 + 0.5 * dx
121
- xMax = 800e3 - 0.5 * dx
122
- nx = int ((xMax - xMin )/ dx + 1 )
121
+ xMin = 320e3 + 0.5 * dx
122
+ xMax = 800e3 - 0.5 * dx
123
+ nx = int ((xMax - xMin ) / dx + 1 )
123
124
x = numpy .linspace (xMin , xMax , nx )
124
125
125
- zMin = - 720.0 + 0.5 * dz
126
- zMax = 0.0 - 0.5 * dz
127
- nz = int ((zMax - zMin )/ dz + 1 )
126
+ zMin = - 720.0 + 0.5 * dz
127
+ zMax = 0.0 - 0.5 * dz
128
+ nz = int ((zMax - zMin ) / dz + 1 )
128
129
z = numpy .linspace (zMax , zMin , nz )
129
130
130
131
try :
@@ -173,8 +174,8 @@ def _compute_barotropic_transport(dsMesh, ds):
173
174
normalVelocity = ds .timeMonthly_avg_normalVelocity [:, innerEdges , :].chunk (
174
175
chunks = {'Time' : 1 })
175
176
176
- layerThicknessEdge = 0.5 * (layerThickness [:, cell0 , :] +
177
- layerThickness [:, cell1 , :])
177
+ layerThicknessEdge = 0.5 * (layerThickness [:, cell0 , :] +
178
+ layerThickness [:, cell1 , :])
178
179
transport = dsMesh .dvEdge [innerEdges ] * \
179
180
(layerThicknessEdge * normalVelocity ).sum (dim = 'nVertLevels' )
180
181
@@ -200,28 +201,28 @@ def _compute_barotropic_streamfunction_vertex(dsMesh, ds, show_progress):
200
201
nBoundaryVertices = len (boundaryVertices )
201
202
nInnerEdges = len (innerEdges )
202
203
203
- indices = numpy .zeros ((2 , 2 * nInnerEdges + nBoundaryVertices ), dtype = int )
204
- data = numpy .zeros (2 * nInnerEdges + nBoundaryVertices , dtype = float )
204
+ indices = numpy .zeros ((2 , 2 * nInnerEdges + nBoundaryVertices ), dtype = int )
205
+ data = numpy .zeros (2 * nInnerEdges + nBoundaryVertices , dtype = float )
205
206
206
207
# The difference between the streamfunction at vertices on an inner edge
207
208
# should be equal to the transport
208
209
v0 = verticesOnEdge [innerEdges , 0 ].values
209
210
v1 = verticesOnEdge [innerEdges , 1 ].values
210
211
211
212
ind = numpy .arange (nInnerEdges )
212
- indices [0 , 2 * ind ] = ind
213
- indices [1 , 2 * ind ] = v1
214
- data [2 * ind ] = 1.
213
+ indices [0 , 2 * ind ] = ind
214
+ indices [1 , 2 * ind ] = v1
215
+ data [2 * ind ] = 1.
215
216
216
- indices [0 , 2 * ind + 1 ] = ind
217
- indices [1 , 2 * ind + 1 ] = v0
218
- data [2 * ind + 1 ] = - 1.
217
+ indices [0 , 2 * ind + 1 ] = ind
218
+ indices [1 , 2 * ind + 1 ] = v0
219
+ data [2 * ind + 1 ] = - 1.
219
220
220
221
# the streamfunction should be zero at all boundary vertices
221
222
ind = numpy .arange (nBoundaryVertices )
222
- indices [0 , 2 * nInnerEdges + ind ] = nInnerEdges + ind
223
- indices [1 , 2 * nInnerEdges + ind ] = boundaryVertices
224
- data [2 * nInnerEdges + ind ] = 1.
223
+ indices [0 , 2 * nInnerEdges + ind ] = nInnerEdges + ind
224
+ indices [1 , 2 * nInnerEdges + ind ] = boundaryVertices
225
+ data [2 * nInnerEdges + ind ] = 1.
225
226
226
227
bsfVertex = xarray .DataArray (numpy .zeros ((nTime , nVertices )),
227
228
dims = ('Time' , 'nVertices' ))
@@ -235,24 +236,24 @@ def _compute_barotropic_streamfunction_vertex(dsMesh, ds, show_progress):
235
236
bar = None
236
237
237
238
for tIndex in range (nTime ):
238
- rhs = numpy .zeros (nInnerEdges + nBoundaryVertices , dtype = float )
239
+ rhs = numpy .zeros (nInnerEdges + nBoundaryVertices , dtype = float )
239
240
240
241
# convert to Sv
241
242
ind = numpy .arange (nInnerEdges )
242
- rhs [ind ] = 1e-6 * transport .isel (Time = tIndex )
243
+ rhs [ind ] = 1e-6 * transport .isel (Time = tIndex )
243
244
244
245
ind = numpy .arange (nBoundaryVertices )
245
246
rhs [nInnerEdges + ind ] = 0.
246
247
247
248
M = scipy .sparse .csr_matrix ((data , indices ),
248
- shape = (nInnerEdges + nBoundaryVertices ,
249
+ shape = (nInnerEdges + nBoundaryVertices ,
249
250
nVertices ))
250
251
251
252
solution = scipy .sparse .linalg .lsqr (M , rhs )
252
253
253
254
bsfVertex [tIndex , :] = - solution [0 ]
254
255
if show_progress :
255
- bar .update (tIndex + 1 )
256
+ bar .update (tIndex + 1 )
256
257
if show_progress :
257
258
bar .finish ()
258
259
@@ -266,13 +267,13 @@ def _compute_barotropic_streamfunction_cell(dsMesh, bsfVertex):
266
267
nEdgesOnCell = dsMesh .nEdgesOnCell
267
268
edgesOnCell = dsMesh .edgesOnCell - 1
268
269
verticesOnCell = dsMesh .verticesOnCell - 1
269
- areaEdge = dsMesh .dcEdge * dsMesh .dvEdge
270
+ areaEdge = dsMesh .dcEdge * dsMesh .dvEdge
270
271
prevEdgesOnCell = edgesOnCell .copy (deep = True )
271
272
prevEdgesOnCell [:, 1 :] = edgesOnCell [:, 0 :- 1 ]
272
- prevEdgesOnCell [:, 0 ] = edgesOnCell [:, nEdgesOnCell - 1 ]
273
+ prevEdgesOnCell [:, 0 ] = edgesOnCell [:, nEdgesOnCell - 1 ]
273
274
274
275
mask = verticesOnCell >= 0
275
- areaVert = mask * 0.5 * (areaEdge [edgesOnCell ] + areaEdge [prevEdgesOnCell ])
276
+ areaVert = mask * 0.5 * (areaEdge [edgesOnCell ] + areaEdge [prevEdgesOnCell ])
276
277
277
278
bsfCell = ((areaVert * bsfVertex [:, verticesOnCell ]).sum (dim = 'maxEdges' ) /
278
279
areaVert .sum (dim = 'maxEdges' ))
@@ -327,17 +328,18 @@ def _compute_horizontal_transport_mpas(ds, dsMesh, outFileName):
327
328
minLevelEdgeBot = minLevelEdgeBot .chunk (chunks )
328
329
maxLevelEdgeTop = maxLevelEdgeTop .chunk (chunks )
329
330
dvEdge = dsMesh .dvEdge [internalEdgeIndices ].chunk (chunks )
330
- bottomDepthEdge = 0.5 * (bottomDepth [cell0 ] +
331
- bottomDepth [cell1 ]).chunk (chunks )
331
+ bottomDepthEdge = 0.5 * (bottomDepth [cell0 ] +
332
+ bottomDepth [cell1 ]).chunk (chunks )
332
333
333
334
chunks = {'Time' : 1 , 'nInternalEdges' : 1024 }
334
335
335
336
normalVelocity = ds .timeMonthly_avg_normalVelocity .isel (
336
337
nEdges = internalEdgeIndices ).chunk (chunks )
337
338
layerThickness = ds .timeMonthly_avg_layerThickness .chunk ()
338
339
339
- layerThicknessEdge = 0.5 * (layerThickness .isel (nCells = cell0 ) +
340
- layerThickness .isel (nCells = cell1 )).chunk (chunks )
340
+ layerThicknessEdge = (
341
+ 0.5 * (layerThickness .isel (nCells = cell0 ) +
342
+ layerThickness .isel (nCells = cell1 )).chunk (chunks ))
341
343
342
344
mask = numpy .logical_and (vertIndex >= minLevelEdgeBot ,
343
345
vertIndex <= maxLevelEdgeTop )
@@ -356,7 +358,7 @@ def _compute_horizontal_transport_mpas(ds, dsMesh, outFileName):
356
358
zInterfaceEdge .rename ({'nVertLevels' : 'nVertLevelsP1' })],
357
359
dim = 'nVertLevelsP1' )
358
360
359
- transportPerDepth = dvEdge * normalVelocity
361
+ transportPerDepth = dvEdge * normalVelocity
360
362
361
363
dsOut = xarray .Dataset ()
362
364
dsOut ['xtime_startMonthly' ] = ds .xtime_startMonthly
@@ -365,7 +367,7 @@ def _compute_horizontal_transport_mpas(ds, dsMesh, outFileName):
365
367
dsOut ['layerThicknessEdge' ] = layerThicknessEdge
366
368
dsOut ['transportPerDepth' ] = transportPerDepth
367
369
dsOut ['transportVertSum' ] = \
368
- (transportPerDepth * layerThicknessEdge ).sum (dim = 'nVertLevels' )
370
+ (transportPerDepth * layerThicknessEdge ).sum (dim = 'nVertLevels' )
369
371
370
372
dsOut = dsOut .transpose ('Time' , 'nInternalEdges' , 'nVertLevels' ,
371
373
'nVertLevelsP1' )
@@ -401,7 +403,7 @@ def _interpolate_horizontal_transport_zlevel(ds, z, outFileName,
401
403
nVertLevels = ds .sizes ['nVertLevels' ]
402
404
403
405
if show_progress :
404
- widgets = ['interpolating tansport on z-level grid: ' ,
406
+ widgets = ['interpolating transport on z-level grid: ' ,
405
407
progressbar .Percentage (), ' ' , progressbar .Bar (), ' ' ,
406
408
progressbar .ETA ()]
407
409
bar = progressbar .ProgressBar (widgets = widgets , maxval = nTime ).start ()
@@ -417,25 +419,26 @@ def _interpolate_horizontal_transport_zlevel(ds, z, outFileName,
417
419
continue
418
420
419
421
outTransport = xarray .DataArray (
420
- numpy .zeros ((nInternalEdges , nz - 1 )),
422
+ numpy .zeros ((nInternalEdges , nz - 1 )),
421
423
dims = ('nInternalEdges' , 'nzM1' ))
422
424
423
425
dzSum = xarray .DataArray (
424
- numpy .zeros ((nInternalEdges , nz - 1 )),
426
+ numpy .zeros ((nInternalEdges , nz - 1 )),
425
427
dims = ('nInternalEdges' , 'nzM1' ))
426
428
427
429
dsIn = ds .isel (Time = tIndex )
428
430
for inZIndex in range (nVertLevels ):
429
431
zTop = dsIn .zInterfaceEdge .isel (nVertLevelsP1 = inZIndex )
430
- zBot = dsIn .zInterfaceEdge .isel (nVertLevelsP1 = inZIndex + 1 )
432
+ zBot = dsIn .zInterfaceEdge .isel (nVertLevelsP1 = inZIndex + 1 )
431
433
inTransportPerDepth = \
432
434
dsIn .transportPerDepth .isel (nVertLevels = inZIndex )
435
+ inTransportPerDepth = inTransportPerDepth .fillna (value = 0. )
433
436
434
437
zt = numpy .minimum (zTop , z0 )
435
438
zb = numpy .maximum (zBot , z1 )
436
439
dz = numpy .maximum (zt - zb , 0. )
437
440
438
- outTransport = outTransport + dz * inTransportPerDepth
441
+ outTransport = outTransport + dz * inTransportPerDepth
439
442
440
443
dzSum = dzSum + dz
441
444
@@ -453,7 +456,7 @@ def _interpolate_horizontal_transport_zlevel(ds, z, outFileName,
453
456
454
457
write_netcdf (dsOut , fileName )
455
458
456
- assert ( numpy .abs (dsOut .transportVertSumCheck ).max ().values < 1e-9 )
459
+ assert numpy .abs (dsOut .transportVertSumCheck ).max ().values < 1e-9
457
460
458
461
if show_progress :
459
462
bar .update (tIndex + 1 )
@@ -503,7 +506,7 @@ def _vertical_cumsum_horizontal_transport(ds, outFileName):
503
506
# with either the output layer above or the one below
504
507
mask = ds .mask .rename ({'nzM1' : 'nz' })
505
508
maskTop = mask .isel (nz = 0 )
506
- maskBot = mask .isel (nz = nz - 2 )
509
+ maskBot = mask .isel (nz = nz - 2 )
507
510
508
511
outMask = xarray .concat ([maskTop ,
509
512
numpy .logical_or (mask [:, 0 :- 1 , :],
@@ -602,12 +605,13 @@ def _horizontally_bin_overturning_streamfunction(ds, dsMesh, x, osfFileName,
602
605
603
606
if len (edgeIndices ) == 0 :
604
607
605
- localOSF = numpy .nan * xarray .DataArray (numpy .ones ((nTime , nz )),
606
- dims = ('Time' , 'nz' ))
608
+ localOSF = numpy .nan * xarray .DataArray (numpy .ones ((nTime , nz )),
609
+ dims = ('Time' , 'nz' ))
607
610
else :
608
611
# convert to Sv
609
- transportSum = 1e-6 * \
610
- edgeSigns * ds .transportSum .isel (nInternalEdges = edgeIndices )
612
+ transportSum = (
613
+ 1e-6 * edgeSigns *
614
+ ds .transportSum .isel (nInternalEdges = edgeIndices ))
611
615
612
616
localOSF = transportSum .sum (dim = 'nInternalEdges' )
613
617
@@ -620,7 +624,7 @@ def _horizontally_bin_overturning_streamfunction(ds, dsMesh, x, osfFileName,
620
624
write_netcdf (dsOSF , fileName )
621
625
622
626
if showProgress :
623
- bar .update (xIndex + 1 )
627
+ bar .update (xIndex + 1 )
624
628
625
629
if showProgress :
626
630
bar .finish ()
0 commit comments