turbx 1.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
turbx/spd_wall_ccor.py ADDED
@@ -0,0 +1,629 @@
1
+ import os
2
+ import sys
3
+ import timeit
4
+ from pathlib import Path, PurePosixPath
5
+
6
+ import h5py
7
+ import numpy as np
8
+ import scipy as sp
9
+ from tqdm import tqdm
10
+
11
+ from .h5 import h5_print_contents
12
+ from .signal import ccor, get_overlapping_window_size, get_overlapping_windows
13
+ from .utils import even_print, format_time_string
14
+
15
+ # ======================================================================
16
+
17
+ def _calc_ccor_wall(self, **kwargs):
18
+ '''
19
+ Calculate cross-correlation [z,t] at every [x]
20
+ - designed for analyzing unsteady, pre-computed wall quantities ([y] plane)
21
+ '''
22
+
23
+ if (self.rank==0):
24
+ verbose = True
25
+ else:
26
+ verbose = False
27
+
28
+ if verbose: print('\n'+'spd.calc_ccor_wall()'+'\n'+72*'-')
29
+ t_start_func = timeit.default_timer()
30
+
31
+ if not self.usingmpi:
32
+ raise NotImplementedError('function is not implemented for non-MPI usage')
33
+
34
+ h5py_is_mpi_build = h5py.h5.get_config().mpi
35
+ if not h5py_is_mpi_build:
36
+ if verbose: print('h5py was not compiled for parallel usage! exiting.')
37
+ sys.exit(1)
38
+
39
+ ri = kwargs.get('ri',1)
40
+ rj = kwargs.get('rj',1)
41
+ rt = kwargs.get('rt',1)
42
+
43
+ fn_h5_out = kwargs.get('fn_h5_out',None) ## filename for output HDF5 (.h5) file
44
+ overlap_fac_nom = kwargs.get('overlap_fac_nom',0.50) ## nominal windows overlap factor
45
+ n_win = kwargs.get('n_win',8) ## number of segment windows for [t] ccor calc
46
+
47
+ ## check data distribution
48
+ if (rj!=1):
49
+ raise AssertionError('rj!=1')
50
+ if (rt!=1):
51
+ raise AssertionError('rt!=1')
52
+ if (ri*rj*rt != self.n_ranks):
53
+ raise AssertionError('ri*rj*rt != self.n_ranks')
54
+ if (ri>self.ni):
55
+ raise AssertionError('ri>self.ni')
56
+ if (self.ni%ri!=0):
57
+ raise AssertionError('ni currently needs to be divisible by the n ranks')
58
+
59
+ ## distribute data over [i]/[x]
60
+ ril_ = np.array_split(np.arange(self.ni,dtype=np.int64),min(ri,self.ni))
61
+ ril = [[b[0],b[-1]+1] for b in ril_ ]
62
+ ri1,ri2 = ril[self.rank]
63
+ nir = ri2 - ri1
64
+
65
+ ## output filename : HDF5 (.h5)
66
+ if (fn_h5_out is None): ## automatically determine name
67
+ fname_path = os.path.dirname(self.fname)
68
+ fname_base = os.path.basename(self.fname)
69
+ fname_root, fname_ext = os.path.splitext(fname_base)
70
+ #fname_root = re.findall(r'io\S+_mpi_[0-9]+', fname_root)[0]
71
+ fn_h5_out_base = fname_root+'_ccor.h5'
72
+ fn_h5_out = str(PurePosixPath(fname_path, fn_h5_out_base))
73
+ if (Path(fn_h5_out).suffix != '.h5'):
74
+ raise ValueError(f"fn_h5_out='{str(fn_h5_out)}' must end in .h5")
75
+ if os.path.isfile(fn_h5_out):
76
+ if (fn_h5_out == self.fname):
77
+ raise ValueError(f"fn_h5_out='{str(fn_h5_out)}' cannot be same as input filename.")
78
+
79
+ if verbose: even_print( 'fn_h5' , self.fname )
80
+ if verbose: even_print( 'fn_h5_out' , fn_h5_out )
81
+ if verbose: print(72*'-')
82
+ self.comm.Barrier()
83
+
84
+ # ===
85
+
86
+ ## the data dictionary to be written to .h5 later
87
+ data = {}
88
+
89
+ ## freestream data
90
+ #lchar = self.lchar ; data['lchar'] = self.lchar
91
+ U_inf = self.U_inf ; data['U_inf'] = self.U_inf
92
+ rho_inf = self.rho_inf ; data['rho_inf'] = self.rho_inf
93
+ T_inf = self.T_inf ; data['T_inf'] = self.T_inf
94
+ #mu_inf = self.mu_inf ; data['mu_inf'] = self.mu_inf
95
+ data['p_inf'] = self.p_inf
96
+ data['Ma'] = self.Ma
97
+ data['Pr'] = self.Pr
98
+
99
+ ## read in 1D coordinate arrays & re-dimensionalize
100
+ x = np.copy( self['dims/x'][()] * self.lchar )
101
+ z = np.copy( self['dims/z'][()] * self.lchar )
102
+ t = np.copy( self['dims/t'][()] * self.tchar )
103
+ data['x'] = x
104
+ data['z'] = z
105
+ data['t'] = t
106
+
107
+ nx = self.ni
108
+ ni = self.ni
109
+ nz = self.nj
110
+ nj = self.nj
111
+ data['ni'] = ni
112
+ data['nx'] = nx
113
+ data['nj'] = nj
114
+ data['nz'] = nz
115
+
116
+ nt = self.nt
117
+ data['nt'] = nt
118
+
119
+ ## assert constant Δz
120
+ dz0 = np.diff(z)[0]
121
+ if not np.all(np.isclose(np.diff(z), dz0, rtol=1e-6)):
122
+ raise NotImplementedError('Δz not constant')
123
+
124
+ ## get Δt, dimensional [s]
125
+ if hasattr(self,'dt'):
126
+ dt = self.dt * self.tchar
127
+ np.testing.assert_allclose(dt, t[1]-t[0], rtol=1e-12, atol=1e-12)
128
+ else:
129
+ dt = t[1] - t[0] ## already dimensional
130
+
131
+ if hasattr(self,'duration'):
132
+ t_meas = self.duration * self.tchar
133
+ np.testing.assert_allclose(t_meas, t.max()-t.min(), rtol=1e-12, atol=1e-12)
134
+ else:
135
+ t_meas = t[-1] - t[0] ## already dimensional
136
+ self.duration = t_meas / self.tchar ## non-dimensionalize for attribute
137
+
138
+ zrange = z.max() - z.min()
139
+
140
+ data['t'] = t
141
+ data['dt'] = dt
142
+ data['dz'] = dz0
143
+ data['zrange'] = zrange
144
+
145
+ if verbose: even_print( 'Δt/tchar' , f'{dt/self.tchar:0.8f}' )
146
+ if verbose: even_print( 'Δt' , f'{dt:0.3e} [s]' )
147
+ if verbose: even_print( 'duration/tchar' , f'{self.duration:0.1f}' )
148
+ if verbose: even_print( 'duration' , f'{self.duration*self.tchar:0.3e} [s]' )
149
+ if verbose: print(72*'-')
150
+
151
+ ## report
152
+ if verbose:
153
+ even_print('Δt' , f'{dt :0.5e} [s]' )
154
+ even_print('t_meas' , f'{t_meas:0.5e} [s]' )
155
+ even_print('Δz' , f'{dz0 :0.5e} [m]' )
156
+ even_print('zrange' , f'{zrange:0.5e} [m]' )
157
+ print(72*'-')
158
+
159
+ win_len, overlap = get_overlapping_window_size(nt, n_win, overlap_fac_nom)
160
+ overlap_fac = overlap / win_len
161
+ tw, n_win, n_pad = get_overlapping_windows(t, win_len, overlap)
162
+ t_meas_per_win = (win_len-1)*dt
163
+ data['win_len'] = win_len
164
+ data['overlap_fac'] = overlap_fac
165
+ data['overlap'] = overlap
166
+ data['n_win'] = n_win
167
+ data['t_meas_per_win'] = t_meas_per_win
168
+
169
+ if verbose:
170
+ even_print('overlap_fac (nominal)' , f'{overlap_fac_nom:0.5f}' )
171
+ even_print('n_win' , f'{n_win:d}' )
172
+ even_print('win_len' , f'{win_len:d}' )
173
+ even_print('overlap' , f'{overlap:d}' )
174
+ even_print('overlap_fac' , f'{overlap_fac:0.5f}' )
175
+ even_print('n_pad' , f'{n_pad:d}' )
176
+ #even_print('t_win/(δ99/uτ)' , '%0.3f [-]'%t_eddy_per_win )
177
+ print(72*'-')
178
+
179
+ ## get lags [t]
180
+ #lags_t,_ = ccor( np.ones(nt,dtype=np.float32), np.ones(nt,dtype=np.float32), get_lags=True )
181
+ lags_t,_ = ccor( np.ones(win_len,dtype=np.float32), np.ones(win_len,dtype=np.float32), get_lags=True )
182
+ #n_lags_t_ = nt*2-1
183
+ n_lags_t_ = win_len*2-1
184
+ n_lags_t = lags_t.shape[0]
185
+ if (n_lags_t!=n_lags_t_):
186
+ raise AssertionError('check lags [t]')
187
+
188
+ data['lags_t'] = lags_t
189
+ data['n_lags_t'] = n_lags_t
190
+
191
+ if verbose:
192
+ even_print('n lags (Δt)' , '%i'%(n_lags_t,))
193
+
194
+ ## get lags [z]
195
+ lags_z,_ = ccor( np.ones(nz,dtype=np.float32) , np.ones(nz,dtype=np.float32), get_lags=True )
196
+ n_lags_z_ = nz*2-1
197
+ n_lags_z = lags_z.shape[0]
198
+ if (n_lags_z!=n_lags_z_):
199
+ raise AssertionError('check lags [z]')
200
+
201
+ data['lags_z'] = lags_z
202
+ data['n_lags_z'] = n_lags_z
203
+
204
+ if verbose:
205
+ even_print('n lags (Δz)' , '%i'%(n_lags_z,))
206
+
207
+ # ==============================================================
208
+ # prepare buffers, etc.
209
+ # ==============================================================
210
+
211
+ do_density_weighting = False ## deactivated for now... would need implementation
212
+
213
+ ## cross-correlation pairs
214
+ ## [ str:var1, str:var2 ]
215
+ ccor_combis = [
216
+
217
+ [ 'u_tau' , 'u_tau' ], ## [ uτ , uτ ] --> ccor[ uτ′ , uτ′ ]
218
+ [ 'v_tau' , 'v_tau' ], ## [ vτ , vτ ] --> ccor[ vτ′ , vτ′ ]
219
+ [ 'w_tau' , 'w_tau' ], ## [ wτ , wτ ] --> ccor[ wτ′ , wτ′ ]
220
+
221
+ #[ 'u_tau' , 'v_tau' ], ## [ uτ , vτ ] --> ccor[ uτ′ , vτ′ ]
222
+ #[ 'u_tau' , 'w_tau' ], ## [ uτ , wτ ] --> ccor[ uτ′ , wτ′ ]
223
+ #[ 'v_tau' , 'w_tau' ], ## [ vτ , wτ ] --> ccor[ vτ′ , wτ′ ]
224
+
225
+ [ 'tau_uy' , 'tau_uy' ], ## [ τuy , τuy ] --> ccor[ τuy′ , τuy′ ]
226
+ [ 'tau_vy' , 'tau_vy' ], ## [ τvy , τvy ] --> ccor[ τvy′ , τvy′ ]
227
+ [ 'tau_wy' , 'tau_wy' ], ## [ τwy , τwy ] --> ccor[ τwy′ , τwy′ ]
228
+
229
+ #[ 'tau_uy' , 'tau_vy' ], ## [ τuy , τvy ] --> ccor[ τuy′ , τvy′ ]
230
+ #[ 'tau_uy' , 'tau_wy' ], ## [ τuy , τwy ] --> ccor[ τuy′ , τwy′ ]
231
+ #[ 'tau_vy' , 'tau_wy' ], ## [ τvy , τwy ] --> ccor[ τvy′ , τwy′ ]
232
+
233
+ [ 'p' , 'p' ], ## [p,p] --> ccor[ p′ , p′ ]
234
+ [ 'T' , 'T' ], ## [T,T] --> ccor[ T′ , T′ ]
235
+ [ 'rho' , 'rho' ], ## [ρ,ρ] --> ccor[ ρ′ , ρ′ ]
236
+
237
+ [ 'u_tau' , 'p' ], ## [uτ,p] --> ccor[ uτ′ , p′ ]
238
+ [ 'tau_uy' , 'p' ], ## [τuy,p] --> ccor[ τuy′ , p′ ]
239
+
240
+ ]
241
+
242
+ ## generate cross-correlation scalar names
243
+ scalars = []
244
+ for ccor_combi in ccor_combis:
245
+ #s1,s2,do_density_weighting = ccor_combi
246
+ s1,s2 = ccor_combi
247
+ if do_density_weighting:
248
+ raise NotImplementedError
249
+ else:
250
+ scalars.append(f"{s1.replace('_','')}I_{s2.replace('_','')}I")
251
+
252
+ scalars_dtypes = [ np.dtype(np.float64) for s in scalars ]
253
+
254
+ ## generate AVG scalar names
255
+ scalars_Re_avg = []
256
+ #scalars_Fv_avg = []
257
+ for ccor_combi in ccor_combis:
258
+ #s1,s2,do_density_weighting = ccor_combi
259
+ s1,s2 = ccor_combi
260
+ if do_density_weighting and ('rho' not in scalars_Re_avg):
261
+ scalars_Re_avg.append('rho')
262
+ if do_density_weighting:
263
+ #if (s1 not in scalars_Fv_avg):
264
+ # scalars_Fv_avg.append(s1)
265
+ #if (s2 not in scalars_Fv_avg):
266
+ # scalars_Fv_avg.append(s2)
267
+ raise NotImplementedError
268
+ else:
269
+ if (s1 not in scalars_Re_avg):
270
+ scalars_Re_avg.append(s1)
271
+ if (s2 not in scalars_Re_avg):
272
+ scalars_Re_avg.append(s2)
273
+
274
+ ## numpy formatted arrays: buffers for PSD & other data (rank-local)
275
+ Rz = np.zeros(shape=(nir, n_lags_z ) , dtype={'names':scalars, 'formats':scalars_dtypes})
276
+ Rt = np.zeros(shape=(nir, n_lags_t ) , dtype={'names':scalars, 'formats':scalars_dtypes})
277
+ covariance = np.zeros(shape=(nir, ) , dtype={'names':scalars, 'formats':scalars_dtypes})
278
+ avg_Re = np.zeros(shape=(nir, ) , dtype={'names':scalars_Re_avg, 'formats':[ np.dtype(np.float64) for s in scalars_Re_avg ]})
279
+ #avg_Fv = np.zeros(shape=(nir, ) , dtype={'names':scalars_Fv_avg, 'formats':[ np.dtype(np.float64) for s in scalars_Fv_avg ]})
280
+
281
+ if verbose:
282
+ even_print('n cross-correlation scalar combinations' , '%i'%(len(ccor_combis),))
283
+ print(72*'-')
284
+
285
+ ## window for [z] -- rectangular because [z] is assumed periodic already
286
+ window_z = np.ones(nz,dtype=np.float64)
287
+ mean_sq_win_z = np.mean(window_z**2)
288
+ if verbose:
289
+ even_print('mean(window_z**2)', '%0.5f'%(mean_sq_win_z,))
290
+
291
+ ## window function for [t]
292
+ window_type = None
293
+ if (window_type=='tukey'):
294
+ window_t = sp.signal.windows.tukey(win_len,alpha=0.5,sym=False) ## α=0:rectangular, α=1:Hann
295
+ elif (window_type=='hann'):
296
+ window_t = sp.signal.windows.hann(win_len,sym=False)
297
+ elif (window_type is None):
298
+ window_t = np.ones(win_len, dtype=np.float64)
299
+ else:
300
+ raise ValueError
301
+
302
+ if verbose:
303
+ even_print('window type [t]', '\'%s\''%str(window_type))
304
+
305
+ ## Not needed for normalization for cross-correlation
306
+ ## ... but report anyway
307
+ mean_sq_win_t = np.mean(window_t**2)
308
+ if verbose:
309
+ even_print('mean(window_t**2)', '%0.5f'%(mean_sq_win_t,))
310
+
311
+ # ==============================================================
312
+ # Main loop
313
+ # ==============================================================
314
+
315
+ if verbose:
316
+ progress_bar = tqdm(
317
+ total=len(ccor_combis)*nir,
318
+ ncols=100,
319
+ desc='ccor',
320
+ leave=True,
321
+ file=sys.stdout,
322
+ mininterval=0.1,
323
+ smoothing=0.,
324
+ #bar_format="\033[B{l_bar}{bar}| {n}/{total} [{percentage:.1f}%] {elapsed}/{remaining}\033[A\n\b",
325
+ bar_format="{l_bar}{bar}| {n}/{total} [{percentage:.1f}%] {elapsed}/{remaining}",
326
+ ascii="░█",
327
+ colour='#FF6600',
328
+ )
329
+
330
+ for cci,cc in enumerate(ccor_combis): ## ccor pairs
331
+
332
+ if verbose: tqdm.write(72*'-')
333
+
334
+ scalar_L, scalar_R = cc
335
+
336
+ msg = f'ccor[{scalar_L}′,{scalar_R}′]'
337
+ if verbose:
338
+ tqdm.write(even_print('computing',msg,s=True,))
339
+
340
+ dset_L = self[f'data/{scalar_L}']
341
+ dset_R = self[f'data/{scalar_R}']
342
+ data_gb_1x = self.n_ranks * 1 * self.nj * self.nt * dset_L.dtype.itemsize / 1024**3
343
+
344
+ scalar = scalars[cci]
345
+
346
+ ## assert scalar name
347
+ scalar_ = f"{scalar_L.replace('_','')}I_{scalar_R.replace('_','')}I"
348
+ if (scalar != scalar_):
349
+ raise ValueError
350
+
351
+ ## assert scalar name
352
+ if do_density_weighting:
353
+ #if (f'r{scalar_L}II_r{scalar_R}II' != scalar ):
354
+ # raise ValueError
355
+ raise NotImplementedError
356
+ else:
357
+ if (f"{scalar_L.replace('_','')}I_{scalar_R.replace('_','')}I" != scalar ):
358
+ raise ValueError
359
+
360
+ ## [x] loop --> each rank works on part of global [x]/[i] range
361
+ for ii in range(ri1,ri2):
362
+
363
+ iii = ii - ri1 ## [x] index local
364
+
365
+ data_L = np.zeros( (nz,nt) , dtype=np.float64 )
366
+ data_R = np.zeros( (nz,nt) , dtype=np.float64 )
367
+
368
+ self.comm.Barrier()
369
+ t_start = timeit.default_timer()
370
+
371
+ ## read data L
372
+ n_scalars_read = 1 ## initialize
373
+ scalar_str = scalar_L ## initialize
374
+ with dset_L.collective:
375
+ data_L[:,:] = np.copy( dset_L[ii,:,:] ).astype(np.float64)
376
+ self.comm.Barrier()
377
+
378
+ ## read data R (if != data L)
379
+ if (scalar_L==scalar_R):
380
+ data_R[:,:] = np.copy( data_L )
381
+ else:
382
+ n_scalars_read += 1
383
+ scalar_str += f',{scalar_R}'
384
+ with dset_R.collective:
385
+ data_R[:,:] = np.copy( dset_R[ii,:,:] ).astype(np.float64)
386
+ self.comm.Barrier()
387
+
388
+ self.comm.Barrier()
389
+ t_delta = timeit.default_timer() - t_start
390
+ data_gb = data_gb_1x * n_scalars_read
391
+
392
+ if verbose:
393
+ tqdm.write(even_print(f'read: {scalar_str}', f'{data_gb:0.3f} [GB] {t_delta:0.3f} [s] {data_gb/t_delta:0.3f} [GB/s]', s=True))
394
+
395
+ ## data_L and data_R shape should be (nz,nt)
396
+ if ( data_L.shape != (nz,nt) ) or ( data_R.shape != (nz,nt) ):
397
+ print(f'rank {self.rank:d}: shape violation')
398
+ self.comm.Abort(1)
399
+
400
+ # === redimensionalize
401
+
402
+ if scalar_L in ['tau_uy','tau_vy','tau_wy',]:
403
+ data_L *= rho_inf * U_inf**2
404
+ elif scalar_L in ['u_tau','v_tau','w_tau',]:
405
+ data_L *= U_inf
406
+ elif scalar_L in ['p',]:
407
+ data_L *= rho_inf * U_inf**2
408
+ elif scalar_L in ['T',]:
409
+ data_L *= T_inf
410
+ elif scalar_L in ['rho',]:
411
+ data_L *= rho_inf
412
+ else:
413
+ raise ValueError
414
+
415
+ if scalar_R in ['tau_uy','tau_vy','tau_wy',]:
416
+ data_R *= rho_inf * U_inf**2
417
+ elif scalar_R in ['u_tau','v_tau','w_tau',]:
418
+ data_R *= U_inf
419
+ elif scalar_R in ['p',]:
420
+ data_R *= rho_inf * U_inf**2
421
+ elif scalar_R in ['T',]:
422
+ data_R *= T_inf
423
+ elif scalar_R in ['rho',]:
424
+ data_R *= rho_inf
425
+ else:
426
+ raise ValueError
427
+
428
+ ## data_L and data_R shape should be (nz,nt)
429
+ if ( data_L.shape != (nz,nt) ) or ( data_R.shape != (nz,nt) ):
430
+ print(f'rank {self.rank:d}: shape violation')
431
+ self.comm.Abort(1)
432
+
433
+ # === compute mean-removed data
434
+
435
+ ## avg(□) or avg(ρ·□)/avg(ρ) in [t]
436
+ if do_density_weighting:
437
+ #rho_avg = np.mean( rho , axis=-1, dtype=np.float64, keepdims=True)
438
+ #data_L_avg = np.mean( rho*data_L , axis=-1, dtype=np.float64, keepdims=True)
439
+ #data_L_avg /= rho_avg
440
+ #data_R_avg = np.mean( rho*data_R , axis=-1, dtype=np.float64, keepdims=True)
441
+ #data_R_avg /= rho_avg
442
+ raise NotImplementedError
443
+ else:
444
+ data_L_avg = np.mean( data_L , axis=-1, dtype=np.float64, keepdims=True) ## (nz,1)
445
+ data_R_avg = np.mean( data_R , axis=-1, dtype=np.float64, keepdims=True) ## (nz,1)
446
+
447
+ ## data_L_avg and data_R_avg shape should be (nz,1)
448
+ if ( data_L_avg.shape != (nz,1) ) or ( data_R_avg.shape != (nz,1) ):
449
+ print(f'rank {self.rank:d}: shape violation')
450
+ self.comm.Abort(1)
451
+
452
+ ## Reynolds prime □′ or Favre prime □″ --> shape (nz,nt)
453
+ data_L -= data_L_avg
454
+ data_R -= data_R_avg
455
+
456
+ ## data_L and data_R shape should be (nz,nt)
457
+ if ( data_L.shape != (nz,nt) ) or ( data_R.shape != (nz,nt) ):
458
+ print(f'rank {self.rank:d}: shape violation')
459
+ self.comm.Abort(1)
460
+
461
+ ## assert stationarity / definition averaging
462
+ ## avg(□′)==0 or avg(ρ·□″)==0
463
+ if do_density_weighting:
464
+ #a_ = np.mean(rho*data_L, axis=-1, dtype=np.float64, keepdims=True)
465
+ #b_ = np.mean(rho*data_R, axis=-1, dtype=np.float64, keepdims=True)
466
+ raise NotImplementedError
467
+ else:
468
+ a_ = np.mean(data_L, axis=-1, dtype=np.float64, keepdims=True) ## average in [t] --> (nz,1)
469
+ b_ = np.mean(data_R, axis=-1, dtype=np.float64, keepdims=True)
470
+ if not np.allclose( a_, np.zeros_like(a_), atol=1e-6 ) or not np.allclose( b_, np.zeros_like(b_), atol=1e-6 ):
471
+ print(f'rank {self.rank:d}: avg(□′)!=0 or avg(ρ·□″)!=0')
472
+ self.comm.Abort(1)
473
+
474
+ ## covariance: <□′□′>
475
+ if do_density_weighting:
476
+ #covariance_ = np.mean( rho*data_L * rho*data_R , axis=-1 , dtype=np.float64, keepdims=True)
477
+ raise NotImplementedError
478
+ else:
479
+ covariance_ = np.mean( data_L*data_R , axis=-1 , dtype=np.float64, keepdims=True) ## average in [t] --> (nz,1)
480
+
481
+ if ( covariance_.shape != (nz,1) ):
482
+ print(f'rank {self.rank:d}: shape violation')
483
+ self.comm.Abort(1)
484
+
485
+ ## write this chunk/scalar's covariance to covariance buffer
486
+ ## avg over [z,t] --> np.float64()
487
+ covariance[scalar][iii] = np.mean( covariance_ , axis=(0,1) , dtype=np.float64)
488
+
489
+ ## write (rank-local) 1D [x] average
490
+ if do_density_weighting:
491
+ #avg_Fv[scalar_L][iii] = np.mean( data_L_avg , axis=(0,1) , dtype=np.float64) )
492
+ #avg_Fv[scalar_R][iii] = np.mean( data_R_avg , axis=(0,1) , dtype=np.float64) )
493
+ #avg_Re['rho'][iii] = np.mean( rho_avg , axis=(0,1) , dtype=np.float64) )
494
+ raise ValueError
495
+ else:
496
+ avg_Re[scalar_L][iii] = np.mean( data_L_avg , axis=(0,1) , dtype=np.float64)
497
+ avg_Re[scalar_R][iii] = np.mean( data_R_avg , axis=(0,1) , dtype=np.float64)
498
+
499
+ # ===============================================================================
500
+ # At this point you have 4D [x,y,z,t] □′ data
501
+ # ===============================================================================
502
+
503
+
504
+ ## do [z] cross-correlation for every [t]
505
+ Rz_buf = np.zeros((nt,n_lags_z), dtype=np.float64)
506
+ for ti in range(nt):
507
+ uL = np.copy( data_L[:,ti] )
508
+ uR = np.copy( data_R[:,ti] )
509
+ Rz_buf[ti,:] = ccor(uL,uR)
510
+
511
+ Rz[scalar][iii,:] = np.mean(Rz_buf, axis=0, dtype=np.float64) ## mean across [t] --> (n_lags_z,)
512
+
513
+
514
+ ## ## do [t] cross-correlation for every [z]
515
+ ## Rt_buf = np.zeros((nz,n_lags_t), dtype=np.float64)
516
+ ## for zi in range(nz):
517
+ ## uL = np.copy( data_L[zi,:] )
518
+ ## uR = np.copy( data_R[zi,:] )
519
+ ## Rt_buf[zi,:] = ccor(uL,uR)
520
+ ##
521
+ ## Rt[scalar][iii,:] = np.mean(Rt_buf, axis=0, dtype=np.float64) ## mean across [z] --> (n_lags_t,)
522
+
523
+
524
+ ## do [t] cross-correlation for every [z]
525
+ Rt_buf = np.zeros((nz,n_lags_t), dtype=np.float64)
526
+ for zi in range(nz):
527
+ uL = np.copy( data_L[zi,:] )
528
+ uR = np.copy( data_R[zi,:] )
529
+ #Rt_buf[zi,:] = ccor(uL,uR)
530
+
531
+ uL_, nw, n_pad = get_overlapping_windows(uL, win_len, overlap)
532
+ uR_, nw, n_pad = get_overlapping_windows(uR, win_len, overlap)
533
+
534
+ ## Per-segment buffer
535
+ Rt_buf_win = np.zeros((nw,n_lags_t), dtype=np.float64)
536
+ for wi in range(nw):
537
+ A1 = np.copy( uL_[wi,:] * window_t )
538
+ A2 = np.copy( uR_[wi,:] * window_t )
539
+ Rt_buf_win[wi,:] = ccor(A1,A2)
540
+ Rt_buf[zi,:] = np.mean(Rt_buf_win, axis=0, dtype=np.float64) ## mean across windows --> (n_lags_t,)
541
+
542
+ Rt[scalar][iii,:] = np.mean(Rt_buf, axis=0, dtype=np.float64) ## mean across [z] --> (n_lags_t,)
543
+
544
+
545
+ self.comm.Barrier() ## [x] loop ('ii' within this rank's range)
546
+ if verbose: progress_bar.update()
547
+
548
+ #break ## DEBUG
549
+ #break ## DEBUG
550
+
551
+ self.comm.Barrier()
552
+ if verbose:
553
+ progress_bar.close()
554
+ print(72*'-')
555
+
556
+ # ==============================================================
557
+ # Write HDF5 (.h5) file
558
+ # ==============================================================
559
+
560
+ ## Overwrite outfile!
561
+ ## - first, open on rank 0 and to write attributes and initialize datasets
562
+ if (self.rank==0):
563
+ with h5py.File(fn_h5_out, 'w') as hfw:
564
+
565
+ ## write floats,ints as top-level attributes
566
+ for key,val in data.items():
567
+ if isinstance(data[key], (int,np.int32,np.int64)):
568
+ hfw.attrs[key] = val
569
+ elif isinstance(data[key], (float,np.float32,np.float64)):
570
+ hfw.attrs[key] = val
571
+ elif isinstance(data[key], np.ndarray):
572
+ pass
573
+ else:
574
+ print(f'key {key} is type {str(type(data[key]))}')
575
+ self.comm.Abort(1)
576
+
577
+ ## write numpy arrays
578
+ hfw.create_dataset( 'dims/x' , data=x ) ## [m]
579
+ hfw.create_dataset( 'dims/z' , data=z ) ## [m]
580
+ hfw.create_dataset( 'dims/t' , data=t ) ## [s]
581
+ hfw.create_dataset( 'dims/lags_z' , data=lags_z )
582
+ hfw.create_dataset( 'dims/lags_t' , data=lags_t )
583
+
584
+ ## initialize datasets : covariance,Rz,Rt
585
+ for scalar in scalars:
586
+ hfw.create_dataset( f'covariance/{scalar}' , shape=(nx,) , dtype=np.float64 , chunks=None , data=np.full((nx,),0.,np.float64) )
587
+ hfw.create_dataset( f'Rz/{scalar}' , shape=(nx,n_lags_z) , dtype=np.float64 , chunks=(1,n_lags_z) , data=np.full((nx,n_lags_z),0.,np.float64) )
588
+ hfw.create_dataset( f'Rt/{scalar}' , shape=(nx,n_lags_t) , dtype=np.float64 , chunks=(1,n_lags_t) , data=np.full((nx,n_lags_t),0.,np.float64) )
589
+
590
+ ## initialize datasets : 1D [x] mean
591
+ for scalar in avg_Re.dtype.names:
592
+ hfw.create_dataset( f'avg/Re/{scalar}', shape=(nx,), dtype=np.float64, chunks=None, data=np.full((nx,),0.,np.float64) )
593
+
594
+ self.comm.Barrier()
595
+
596
+ ## re-open in parallel for data writes
597
+ with h5py.File(fn_h5_out, 'a', driver='mpio', comm=self.comm) as hfw:
598
+
599
+ ## collectively write covariance,Rz,Rt
600
+ for scalar in scalars:
601
+ dset = hfw[f'covariance/{scalar}']
602
+ with dset.collective:
603
+ dset[ri1:ri2] = covariance[scalar][:]
604
+ dset = hfw[f'Rz/{scalar}']
605
+ with dset.collective:
606
+ dset[ri1:ri2,:] = Rz[scalar][:,:]
607
+ dset = hfw[f'Rt/{scalar}']
608
+ with dset.collective:
609
+ dset[ri1:ri2,:] = Rt[scalar][:,:]
610
+
611
+ ## collectively write 1D [z] avgs
612
+ for scalar in avg_Re.dtype.names:
613
+ dset = hfw[f'avg/Re/{scalar}']
614
+ with dset.collective:
615
+ dset[ri1:ri2] = avg_Re[scalar][:]
616
+
617
+ ## report file contents
618
+ self.comm.Barrier()
619
+ if (self.rank==0):
620
+ even_print( os.path.basename(fn_h5_out) , f'{(os.path.getsize(fn_h5_out)/1024**2):0.1f} [MB]' )
621
+ print(72*'-')
622
+ with h5py.File(fn_h5_out,'r') as hfr:
623
+ h5_print_contents(hfr)
624
+ self.comm.Barrier()
625
+
626
+ if verbose: print(72*'-')
627
+ if verbose: print('total time : spd.calc_ccor_wall() : %s'%format_time_string((timeit.default_timer() - t_start_func)))
628
+ if verbose: print(72*'-')
629
+ return