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/__init__.py +52 -0
- turbx/bl.py +620 -0
- turbx/blasius.py +64 -0
- turbx/cli.py +19 -0
- turbx/composite_profile.py +243 -0
- turbx/confidence_interval.py +64 -0
- turbx/eas3.py +420 -0
- turbx/eas4.py +567 -0
- turbx/fig_ax_constructor.py +52 -0
- turbx/freestream_parameters.py +268 -0
- turbx/gradient.py +391 -0
- turbx/grid_metric.py +272 -0
- turbx/h5.py +236 -0
- turbx/mvp.py +385 -0
- turbx/rgd.py +2693 -0
- turbx/rgd_mean.py +523 -0
- turbx/rgd_testing.py +354 -0
- turbx/rgd_xpln_ccor.py +701 -0
- turbx/rgd_xpln_coh.py +992 -0
- turbx/rgd_xpln_mean_dim.py +336 -0
- turbx/rgd_xpln_spectrum.py +940 -0
- turbx/rgd_xpln_stats.py +738 -0
- turbx/rgd_xpln_turb_budget.py +1193 -0
- turbx/set_mpl_env.py +85 -0
- turbx/signal.py +277 -0
- turbx/spd.py +1206 -0
- turbx/spd_wall_ccor.py +629 -0
- turbx/spd_wall_ci.py +406 -0
- turbx/spd_wall_import.py +676 -0
- turbx/spd_wall_spectrum.py +638 -0
- turbx/spd_wall_stats.py +618 -0
- turbx/utils.py +84 -0
- turbx/ztmd.py +2224 -0
- turbx/ztmd_analysis.py +2337 -0
- turbx/ztmd_loader.py +56 -0
- turbx-1.0.2.dist-info/LICENSE +21 -0
- turbx-1.0.2.dist-info/METADATA +120 -0
- turbx-1.0.2.dist-info/RECORD +41 -0
- turbx-1.0.2.dist-info/WHEEL +5 -0
- turbx-1.0.2.dist-info/entry_points.txt +2 -0
- turbx-1.0.2.dist-info/top_level.txt +1 -0
turbx/spd_wall_import.py
ADDED
|
@@ -0,0 +1,676 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import timeit
|
|
4
|
+
|
|
5
|
+
import h5py
|
|
6
|
+
import numpy as np
|
|
7
|
+
from tqdm import tqdm
|
|
8
|
+
|
|
9
|
+
from .eas4 import eas4
|
|
10
|
+
from .gradient import gradient
|
|
11
|
+
from .h5 import h5_ds_force_allocate_chunks, h5_print_contents
|
|
12
|
+
from .utils import even_print, format_time_string
|
|
13
|
+
|
|
14
|
+
# ======================================================================
|
|
15
|
+
|
|
16
|
+
def _init_from_eas4_wall(self, fn_eas4, **kwargs):
|
|
17
|
+
'''
|
|
18
|
+
Initialize 'wall' SPD from an EAS4
|
|
19
|
+
'''
|
|
20
|
+
verbose = kwargs.get('verbose',True)
|
|
21
|
+
if (self.rank!=0):
|
|
22
|
+
verbose=False
|
|
23
|
+
|
|
24
|
+
if verbose: print('\n'+'spd.init_from_eas4_wall()'+'\n'+72*'-')
|
|
25
|
+
t_start_func = timeit.default_timer()
|
|
26
|
+
|
|
27
|
+
#if (self.rank==0):
|
|
28
|
+
with eas4(fn_eas4,'r',comm=self.comm,driver=self.driver) as hfr:
|
|
29
|
+
|
|
30
|
+
if (hfr.x.ndim!=1):
|
|
31
|
+
raise RuntimeError('hfr.x.ndim!=1')
|
|
32
|
+
if (hfr.z.ndim!=1):
|
|
33
|
+
raise RuntimeError('hfr.z.ndim!=1')
|
|
34
|
+
|
|
35
|
+
## Primary attributes
|
|
36
|
+
ats = ['Ma','Re','Pr','kappa','R','p_inf','T_inf','S_Suth','mu_Suth_ref','T_Suth_ref',]
|
|
37
|
+
for at in ats:
|
|
38
|
+
self.attrs[at] = hfr.udef[at]
|
|
39
|
+
|
|
40
|
+
## Derived attributes
|
|
41
|
+
ats = ['C_Suth','mu_inf','rho_inf','nu_inf','a_inf','U_inf','cp','cv','lchar','tchar','uchar','M_inf',]
|
|
42
|
+
for at in ats:
|
|
43
|
+
if at in hfr.attrs:
|
|
44
|
+
self.attrs[at] = hfr.attrs[at]
|
|
45
|
+
|
|
46
|
+
## 3D polydata grid coordinates : shape (nx,nz,3)
|
|
47
|
+
xyz = np.zeros((hfr.nx,hfr.nz,3), dtype=np.float64)
|
|
48
|
+
xyz[:,:,0] = hfr.x[:,np.newaxis]
|
|
49
|
+
xyz[:,:,1] = 0.
|
|
50
|
+
xyz[:,:,2] = hfr.z[np.newaxis,:]
|
|
51
|
+
|
|
52
|
+
self.create_dataset(
|
|
53
|
+
name='dims/xyz',
|
|
54
|
+
chunks=(1,hfr.nz,1), ## (x,z,3)
|
|
55
|
+
#shape=(hfr.nx, hfr.nz, 3),
|
|
56
|
+
#dtype=np.float64,
|
|
57
|
+
data=xyz,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
self.flush()
|
|
61
|
+
xyz = None; del xyz
|
|
62
|
+
|
|
63
|
+
## 1D [x],[y],[z] vector
|
|
64
|
+
self.create_dataset('dims/x', data=hfr.x, chunks=None)
|
|
65
|
+
self.create_dataset('dims/z', data=hfr.z, chunks=None)
|
|
66
|
+
self.create_dataset('dims/y', data=np.array([0.,],dtype=np.float64), chunks=None)
|
|
67
|
+
|
|
68
|
+
## Add attributes
|
|
69
|
+
self.attrs['ni'] = hfr.nx
|
|
70
|
+
self.attrs['nj'] = hfr.nz
|
|
71
|
+
self.attrs['n_quads'] = ( hfr.nx - 1 ) * ( hfr.nz - 1 )
|
|
72
|
+
self.attrs['n_pts'] = hfr.nx * hfr.nz
|
|
73
|
+
#self.attrs['nt'] = hfr.nt
|
|
74
|
+
self.attrs['nt'] = 0 ## overwritten later
|
|
75
|
+
|
|
76
|
+
if self.usingmpi:
|
|
77
|
+
self.comm.Barrier()
|
|
78
|
+
|
|
79
|
+
self.get_header(verbose=True)
|
|
80
|
+
if verbose: print(72*'-')
|
|
81
|
+
|
|
82
|
+
if (self.rank==0):
|
|
83
|
+
with h5py.File(self.fname,'r') as hf:
|
|
84
|
+
h5_print_contents(hf)
|
|
85
|
+
if self.usingmpi:
|
|
86
|
+
self.comm.Barrier()
|
|
87
|
+
|
|
88
|
+
## Report
|
|
89
|
+
if verbose:
|
|
90
|
+
print(72*'-')
|
|
91
|
+
even_print( os.path.basename(self.fname), f'{(os.path.getsize(self.fname)/1024**3):0.1f} [GB]')
|
|
92
|
+
if verbose: print(72*'-')
|
|
93
|
+
if verbose: print('total time : spd.init_from_eas4_wall() : %s'%format_time_string((timeit.default_timer() - t_start_func)))
|
|
94
|
+
if verbose: print(72*'-')
|
|
95
|
+
return
|
|
96
|
+
|
|
97
|
+
def _import_eas4_wall(self, fn_eas4_list, **kwargs):
|
|
98
|
+
'''
|
|
99
|
+
Directly import to 'wall' SPD file from EAS4s
|
|
100
|
+
- only parallelize in [x]
|
|
101
|
+
'''
|
|
102
|
+
|
|
103
|
+
if (self.rank!=0):
|
|
104
|
+
verbose=False
|
|
105
|
+
else:
|
|
106
|
+
verbose=True
|
|
107
|
+
|
|
108
|
+
if verbose: print('\n'+'spd.import_eas4_wall()'+'\n'+72*'-')
|
|
109
|
+
t_start_func = timeit.default_timer()
|
|
110
|
+
|
|
111
|
+
## dont actually copy over data, just initialize datasets with 0's
|
|
112
|
+
init_dsets_only = kwargs.get('init_dsets_only',False)
|
|
113
|
+
|
|
114
|
+
## import from EAS4 as 3D unchunked datasets
|
|
115
|
+
## - have to convert to 4D later
|
|
116
|
+
## - necessary workaround for disk space with 'huge' datasets
|
|
117
|
+
threeD = kwargs.get('threeD',False)
|
|
118
|
+
fn_h5_3D = kwargs.get('fn_h5_3D',None)
|
|
119
|
+
fi_min = kwargs.get('fi_min',0) ## minimum 'file' ID (for restarting MOVE)
|
|
120
|
+
|
|
121
|
+
if fn_h5_3D is not None:
|
|
122
|
+
if not os.path.isfile(fn_h5_3D):
|
|
123
|
+
raise FileNotFoundError(fn_h5_3D)
|
|
124
|
+
|
|
125
|
+
# if not self.usingmpi:
|
|
126
|
+
# if verbose: print('this function has not been implemented in non-MPI mode')
|
|
127
|
+
# sys.exit(1)
|
|
128
|
+
|
|
129
|
+
# if not h5py.h5.get_config().mpi:
|
|
130
|
+
# if verbose: print('h5py was not compiled for parallel usage! exiting.')
|
|
131
|
+
# sys.exit(1)
|
|
132
|
+
|
|
133
|
+
acc = kwargs.get('acc',4)
|
|
134
|
+
edge_stencil = kwargs.get('edge_stencil','full')
|
|
135
|
+
chunks = kwargs.get('chunks',None)
|
|
136
|
+
|
|
137
|
+
if chunks is None:
|
|
138
|
+
#chunks = (4, self.nj, 50) ## (x,z,t)
|
|
139
|
+
chunks = (1,self.nj,1) ## (x,z,t) --> probably a bad default!
|
|
140
|
+
print("WARNING! Not providing 'chunk' could result in very bad performance")
|
|
141
|
+
if not isinstance(chunks,tuple):
|
|
142
|
+
raise ValueError("'chunks' must be tuple")
|
|
143
|
+
if len(chunks)!=3:
|
|
144
|
+
raise ValueError("len(chunks)!=3")
|
|
145
|
+
|
|
146
|
+
## delete EAS4s after import --> DANGER!
|
|
147
|
+
## ... only actually deletes files if 'do_delete.txt' is present
|
|
148
|
+
delete_after_import = kwargs.get('delete_after_import',False)
|
|
149
|
+
|
|
150
|
+
## check that the passed list of EAS4 files is OK
|
|
151
|
+
if not isinstance(fn_eas4_list, list):
|
|
152
|
+
raise ValueError("'fn_eas4_list' must be list")
|
|
153
|
+
#if not hasattr(fn_eas4_list, '__iter__'):
|
|
154
|
+
# raise ValueError("'fn_eas4_list' must be iterable")
|
|
155
|
+
for fn_eas4 in fn_eas4_list:
|
|
156
|
+
if not os.path.isfile(fn_eas4):
|
|
157
|
+
raise FileNotFoundError(fn_eas4)
|
|
158
|
+
|
|
159
|
+
## n ranks per direction
|
|
160
|
+
rx = kwargs.get('rx',1)
|
|
161
|
+
if (rx != self.n_ranks):
|
|
162
|
+
raise AssertionError('rx != self.n_ranks')
|
|
163
|
+
|
|
164
|
+
## nx = ni
|
|
165
|
+
if not hasattr(self,'ni'):
|
|
166
|
+
raise ValueError('attribute ni not found.')
|
|
167
|
+
else:
|
|
168
|
+
self.nx = self.ni
|
|
169
|
+
|
|
170
|
+
## nz = nj
|
|
171
|
+
if not hasattr(self,'nj'):
|
|
172
|
+
raise ValueError('attribute nj not found.')
|
|
173
|
+
else:
|
|
174
|
+
self.nz = self.nj
|
|
175
|
+
|
|
176
|
+
## distribute in [x]
|
|
177
|
+
if self.usingmpi:
|
|
178
|
+
rxl_ = np.array_split(np.arange(self.nx,dtype=np.int64),min(rx,self.nx))
|
|
179
|
+
rxl = [[b[0],b[-1]+1] for b in rxl_ ]
|
|
180
|
+
rx1, rx2 = rxl[self.rank]
|
|
181
|
+
nxr = rx2 - rx1
|
|
182
|
+
else:
|
|
183
|
+
rx1,rx2 = 0,self.nx
|
|
184
|
+
nxr = self.nx
|
|
185
|
+
|
|
186
|
+
## Get all time info & check
|
|
187
|
+
# ==============================================================
|
|
188
|
+
|
|
189
|
+
if len(fn_eas4_list) == 0:
|
|
190
|
+
if not hasattr(self,'t') or not hasattr(self,'nt'):
|
|
191
|
+
raise RuntimeError("if fn_eas4_list=[], then t should exist")
|
|
192
|
+
nt = self.nt
|
|
193
|
+
t = np.copy(self.t)
|
|
194
|
+
|
|
195
|
+
else:
|
|
196
|
+
if (self.rank==0):
|
|
197
|
+
t = np.array([], dtype=np.float64)
|
|
198
|
+
for fn_eas4 in fn_eas4_list:
|
|
199
|
+
with eas4(fn_eas4, 'r', verbose=False) as hf_eas4:
|
|
200
|
+
t_ = np.copy(hf_eas4.t)
|
|
201
|
+
t = np.concatenate((t,t_))
|
|
202
|
+
else:
|
|
203
|
+
t = np.array([], dtype=np.float64) ## 't' must exist on all ranks before bcast
|
|
204
|
+
|
|
205
|
+
if self.usingmpi:
|
|
206
|
+
self.comm.Barrier()
|
|
207
|
+
t = self.comm.bcast(t, root=0)
|
|
208
|
+
nt = t.shape[0]
|
|
209
|
+
self.nt = nt
|
|
210
|
+
self.t = t
|
|
211
|
+
assert self.t.dtype == np.float64, f'Array dtype is {str(t.dtype)}, expected np.float64'
|
|
212
|
+
|
|
213
|
+
if len(fn_eas4_list) > 0:
|
|
214
|
+
if verbose: even_print('n EAS4 files','%i'%len(fn_eas4_list))
|
|
215
|
+
if verbose: even_print('nt all files','%i'%nt)
|
|
216
|
+
if verbose: even_print('delete after import',str(delete_after_import))
|
|
217
|
+
else:
|
|
218
|
+
if verbose: even_print('nt',f'{nt:d}')
|
|
219
|
+
if verbose: print(72*'-')
|
|
220
|
+
|
|
221
|
+
# ==============================================================
|
|
222
|
+
|
|
223
|
+
## check [t] & Δt
|
|
224
|
+
if (nt>1):
|
|
225
|
+
|
|
226
|
+
## check no zero distance elements
|
|
227
|
+
if (np.diff(t).size - np.count_nonzero(np.diff(t))) != 0.:
|
|
228
|
+
raise AssertionError('t arr has zero-distance elements')
|
|
229
|
+
else:
|
|
230
|
+
if verbose: even_print('check: Δt!=0','passed')
|
|
231
|
+
|
|
232
|
+
## check monotonically increasing
|
|
233
|
+
if not np.all(np.diff(t) > 0.):
|
|
234
|
+
raise AssertionError('t arr not monotonically increasing')
|
|
235
|
+
else:
|
|
236
|
+
if verbose: even_print('check: t mono increasing','passed')
|
|
237
|
+
|
|
238
|
+
## check constant Δt
|
|
239
|
+
dt0 = np.diff(t)[0]
|
|
240
|
+
if not np.all(np.isclose(np.diff(t), dt0, rtol=1e-3)):
|
|
241
|
+
if (self.rank==0):
|
|
242
|
+
print(np.diff(t))
|
|
243
|
+
#raise AssertionError('t arr not uniformly spaced')
|
|
244
|
+
if verbose:
|
|
245
|
+
even_print('check: constant Δt','failed')
|
|
246
|
+
print('WARNING: [t] not uniformly spaced!!')
|
|
247
|
+
else:
|
|
248
|
+
if verbose: even_print('check: constant Δt','passed')
|
|
249
|
+
|
|
250
|
+
## (over)write [t]
|
|
251
|
+
if len(fn_eas4_list) > 0:
|
|
252
|
+
if self.usingmpi: self.comm.Barrier()
|
|
253
|
+
if 'dims/t' in self:
|
|
254
|
+
del self['dims/t']
|
|
255
|
+
self.create_dataset('dims/t', data=t, chunks=None, dtype=np.float64)
|
|
256
|
+
self.attrs['nt'] = nt
|
|
257
|
+
self.attrs['dt'] = dt0
|
|
258
|
+
self.attrs['duration'] = dt0 * (nt - 1)
|
|
259
|
+
self.flush()
|
|
260
|
+
if self.usingmpi: self.comm.Barrier()
|
|
261
|
+
if verbose: print(72*'-')
|
|
262
|
+
|
|
263
|
+
else:
|
|
264
|
+
return ## nothing to do
|
|
265
|
+
|
|
266
|
+
# ==============================================================
|
|
267
|
+
# Initialize datasets (harmless if they exist)
|
|
268
|
+
# ==============================================================
|
|
269
|
+
|
|
270
|
+
if not threeD: ## ...because '3D' mode doesnt require pre-initialization
|
|
271
|
+
|
|
272
|
+
scalars = [
|
|
273
|
+
'tau_uy','tau_vy','tau_wy',
|
|
274
|
+
'u_tau','v_tau','w_tau',
|
|
275
|
+
'T','mu','nu','rho','p',
|
|
276
|
+
]
|
|
277
|
+
|
|
278
|
+
dtype = np.dtype(np.float32)
|
|
279
|
+
shape = (self.nx, self.nz, self.nt)
|
|
280
|
+
data_gb = np.prod(shape) * dtype.itemsize / 1024**3
|
|
281
|
+
|
|
282
|
+
if verbose:
|
|
283
|
+
progress_bar = tqdm(
|
|
284
|
+
total=len(scalars),
|
|
285
|
+
ncols=100,
|
|
286
|
+
desc='initialize dsets',
|
|
287
|
+
leave=True,
|
|
288
|
+
file=sys.stdout,
|
|
289
|
+
mininterval=0.1,
|
|
290
|
+
smoothing=0.,
|
|
291
|
+
#bar_format="\033[B{l_bar}{bar}| {n}/{total} [{percentage:.1f}%] {elapsed}/{remaining}\033[A\n\b",
|
|
292
|
+
bar_format="{l_bar}{bar}| {n}/{total} [{percentage:.1f}%] {elapsed}/{remaining}",
|
|
293
|
+
ascii="░█",
|
|
294
|
+
colour='#FF6600',
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
## Initialize output datasets
|
|
298
|
+
for scalar in scalars:
|
|
299
|
+
|
|
300
|
+
dsn = f'data/{scalar}'
|
|
301
|
+
if dsn not in self:
|
|
302
|
+
if self.usingmpi: self.comm.Barrier()
|
|
303
|
+
t_start = timeit.default_timer()
|
|
304
|
+
|
|
305
|
+
if verbose:
|
|
306
|
+
tqdm.write( even_print(f'initializing data/{scalar}', f'{str(shape)} / {data_gb:0.1f} [GB]', s=True) )
|
|
307
|
+
|
|
308
|
+
dset = self.create_dataset(
|
|
309
|
+
dsn,
|
|
310
|
+
shape=shape,
|
|
311
|
+
dtype=dtype,
|
|
312
|
+
chunks=chunks,
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
## write dummy data to dataset to ensure that it is truly initialized
|
|
316
|
+
if not self.usingmpi:
|
|
317
|
+
h5_ds_force_allocate_chunks(dset,verbose=verbose) #,quick=True)
|
|
318
|
+
|
|
319
|
+
if self.usingmpi: self.comm.Barrier()
|
|
320
|
+
t_delta = timeit.default_timer() - t_start
|
|
321
|
+
if verbose:
|
|
322
|
+
tqdm.write( even_print(f'initialize data/{scalar}', f'{data_gb:0.2f} [GB] {t_delta:0.2f} [s] {(data_gb/t_delta):0.3f} [GB/s]', s=True) )
|
|
323
|
+
|
|
324
|
+
chunk_kb_ = np.prod(dset.chunks) * dset.dtype.itemsize / 1024. ## actual
|
|
325
|
+
if verbose:
|
|
326
|
+
tqdm.write( even_print('chunk shape (x,z,t)', str(dset.chunks), s=True) )
|
|
327
|
+
tqdm.write( even_print('chunk size', f'{int(round(chunk_kb_)):d} [KB]', s=True) )
|
|
328
|
+
|
|
329
|
+
if verbose: progress_bar.update()
|
|
330
|
+
|
|
331
|
+
if self.usingmpi:
|
|
332
|
+
self.comm.Barrier()
|
|
333
|
+
if verbose:
|
|
334
|
+
progress_bar.close()
|
|
335
|
+
print(72*'-')
|
|
336
|
+
|
|
337
|
+
# ==============================================================
|
|
338
|
+
# Read,process,write (from EAS4)
|
|
339
|
+
# ==============================================================
|
|
340
|
+
|
|
341
|
+
if not init_dsets_only and fn_h5_3D is None:
|
|
342
|
+
|
|
343
|
+
if verbose:
|
|
344
|
+
progress_bar = tqdm(
|
|
345
|
+
total=len(fn_eas4_list),
|
|
346
|
+
ncols=100,
|
|
347
|
+
desc='import',
|
|
348
|
+
leave=True,
|
|
349
|
+
file=sys.stdout,
|
|
350
|
+
mininterval=0.1,
|
|
351
|
+
smoothing=0.,
|
|
352
|
+
#bar_format="\033[B{l_bar}{bar}| {n}/{total} [{percentage:.1f}%] {elapsed}/{remaining}\033[A\n\b",
|
|
353
|
+
bar_format="{l_bar}{bar}| {n}/{total} [{percentage:.1f}%] {elapsed}/{remaining}",
|
|
354
|
+
ascii="░█",
|
|
355
|
+
colour='#FF6600',
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
tii = 0 ## timestep index counter full series
|
|
359
|
+
|
|
360
|
+
for i_eas4,fn_eas4 in enumerate(fn_eas4_list):
|
|
361
|
+
|
|
362
|
+
with eas4(fn_eas4, 'r', verbose=False, driver=self.driver, comm=self.comm) as hf_eas4:
|
|
363
|
+
|
|
364
|
+
## dimensional coordinates
|
|
365
|
+
#x = np.copy( hf_eas4.x * hf_eas4.lchar )
|
|
366
|
+
y = np.copy( hf_eas4.y * hf_eas4.lchar )
|
|
367
|
+
#z = np.copy( hf_eas4.z * hf_eas4.lchar )
|
|
368
|
+
|
|
369
|
+
nx = hf_eas4.nx
|
|
370
|
+
ny = hf_eas4.ny
|
|
371
|
+
nz = hf_eas4.nz
|
|
372
|
+
nt = hf_eas4.nt ## OVERWRITING ABOVE!!!
|
|
373
|
+
|
|
374
|
+
if verbose:
|
|
375
|
+
tqdm.write(even_print(os.path.basename(fn_eas4), f'{(os.path.getsize(fn_eas4)/1024**3):0.1f} [GB]', s=True))
|
|
376
|
+
|
|
377
|
+
## rank-local data read buffer for this EAS4
|
|
378
|
+
scalars = ['rho','u','v','w','T','p']
|
|
379
|
+
#formats = [ np.dtype(np.float32) for s in scalars ]
|
|
380
|
+
formats = [ np.dtype(np.float64) for s in scalars ] ## do arithmetic in double
|
|
381
|
+
data = np.zeros(shape=(nxr,ny,nz,nt), dtype={'names':scalars, 'formats':formats})
|
|
382
|
+
|
|
383
|
+
## read (FULL file)
|
|
384
|
+
self.comm.Barrier()
|
|
385
|
+
t_start = timeit.default_timer()
|
|
386
|
+
for ti in range(hf_eas4.nt): ## timesteps in EAS4
|
|
387
|
+
for scalar in scalars:
|
|
388
|
+
dset_path = f'Data/DOMAIN_000000/ts_{ti:06d}/par_{hf_eas4.scalar_n_map[scalar]:06d}'
|
|
389
|
+
dset = hf_eas4[dset_path]
|
|
390
|
+
with dset.collective:
|
|
391
|
+
if hf_eas4.dform==1:
|
|
392
|
+
data[scalar][:,:,:,ti] = dset[rx1:rx2,:,:]
|
|
393
|
+
elif hf_eas4.dform==2:
|
|
394
|
+
data[scalar][:,:,:,ti] = dset[:,:,rx1:rx2].T
|
|
395
|
+
else:
|
|
396
|
+
raise RuntimeError
|
|
397
|
+
|
|
398
|
+
self.comm.Barrier()
|
|
399
|
+
t_delta = timeit.default_timer() - t_start
|
|
400
|
+
|
|
401
|
+
data_gb = os.path.getsize(fn_eas4)/1024**3
|
|
402
|
+
if verbose:
|
|
403
|
+
#msg = even_print('read {os.path.basename(fn_eas4)}', f'{data_gb:0.2f} [GB] {t_delta:0.2f} [s] {(data_gb/t_delta):0.3f} [GB/s]', s=True)
|
|
404
|
+
msg = even_print('read', f'{data_gb:0.2f} [GB] {t_delta:0.2f} [s] {(data_gb/t_delta):0.3f} [GB/s]', s=True)
|
|
405
|
+
tqdm.write(msg)
|
|
406
|
+
|
|
407
|
+
## re-dimensionalize EAS4 data
|
|
408
|
+
data['rho'][:,:,:,:] *= hf_eas4.rho_inf
|
|
409
|
+
data['u'][:,:,:,:] *= hf_eas4.U_inf
|
|
410
|
+
data['v'][:,:,:,:] *= hf_eas4.U_inf
|
|
411
|
+
data['w'][:,:,:,:] *= hf_eas4.U_inf
|
|
412
|
+
data['T'][:,:,:,:] *= hf_eas4.T_inf
|
|
413
|
+
data['p'][:,:,:,:] *= hf_eas4.rho_inf * hf_eas4.U_inf**2
|
|
414
|
+
|
|
415
|
+
## calculate μ and ν (dimensional)
|
|
416
|
+
mu = np.zeros(shape=(nxr,ny,nz,nt), dtype=np.float64)
|
|
417
|
+
nu = np.zeros(shape=(nxr,ny,nz,nt), dtype=np.float64)
|
|
418
|
+
mu[:,:,:,:] = hf_eas4.mu_Suth_ref * ( data['T'][:,:,:,:] / hf_eas4.T_Suth_ref )**(3/2) * ( ( hf_eas4.T_Suth_ref + hf_eas4.S_Suth ) / ( data['T'][:,:,:,:] + hf_eas4.S_Suth ) )
|
|
419
|
+
nu[:,:,:,:] = mu / data['rho'][:,:,:,:]
|
|
420
|
+
|
|
421
|
+
# ==========================================================
|
|
422
|
+
|
|
423
|
+
## Dimensional wall strains
|
|
424
|
+
ddy_u = gradient( data['u'][:,:,:,:], y, axis=1, acc=acc, edge_stencil=edge_stencil, d=1)
|
|
425
|
+
ddy_v = gradient( data['v'][:,:,:,:], y, axis=1, acc=acc, edge_stencil=edge_stencil, d=1)
|
|
426
|
+
ddy_w = gradient( data['w'][:,:,:,:], y, axis=1, acc=acc, edge_stencil=edge_stencil, d=1)
|
|
427
|
+
ddy_u_wall = np.copy( ddy_u[:,0,:,:] )
|
|
428
|
+
ddy_v_wall = np.copy( ddy_v[:,0,:,:] )
|
|
429
|
+
ddy_w_wall = np.copy( ddy_w[:,0,:,:] )
|
|
430
|
+
|
|
431
|
+
if (ddy_u_wall.ndim!=3): ## (x,z,t)
|
|
432
|
+
raise ValueError
|
|
433
|
+
if (ddy_u_wall.shape!=(nxr,nz,nt)): ## (x,z,t)
|
|
434
|
+
raise ValueError
|
|
435
|
+
|
|
436
|
+
## Dimensional wall quantities
|
|
437
|
+
rho_wall = np.copy( data['rho'][:,0,:,:] )
|
|
438
|
+
mu_wall = np.copy( mu[:,0,:,:] )
|
|
439
|
+
nu_wall = np.copy( nu[:,0,:,:] )
|
|
440
|
+
T_wall = np.copy( data['T'][:,0,:,:] )
|
|
441
|
+
p_wall = np.copy( data['p'][:,0,:,:] )
|
|
442
|
+
|
|
443
|
+
if (mu_wall.ndim!=3): ## (x,z,t)
|
|
444
|
+
raise ValueError
|
|
445
|
+
if (mu_wall.shape!=(nxr,nz,nt)): ## (x,z,t)
|
|
446
|
+
raise ValueError
|
|
447
|
+
|
|
448
|
+
if (rho_wall.ndim!=3): ## (x,z,t)
|
|
449
|
+
raise ValueError
|
|
450
|
+
if (rho_wall.shape!=(nxr,nz,nt)): ## (x,z,t)
|
|
451
|
+
raise ValueError
|
|
452
|
+
|
|
453
|
+
tau_uy = np.copy( mu_wall * ddy_u_wall ) ## INSTANTANEOUS τw
|
|
454
|
+
tau_vy = np.copy( mu_wall * ddy_v_wall )
|
|
455
|
+
tau_wy = np.copy( mu_wall * ddy_w_wall )
|
|
456
|
+
|
|
457
|
+
u_tau = np.copy( np.sign(tau_uy) * np.sqrt( np.abs(tau_uy) / rho_wall ) ) ## INSTANTANEOUS uτ
|
|
458
|
+
v_tau = np.copy( np.sign(tau_vy) * np.sqrt( np.abs(tau_vy) / rho_wall ) ) ## INSTANTANEOUS vτ
|
|
459
|
+
w_tau = np.copy( np.sign(tau_wy) * np.sqrt( np.abs(tau_wy) / rho_wall ) ) ## INSTANTANEOUS wτ
|
|
460
|
+
|
|
461
|
+
#grp = self['data']
|
|
462
|
+
#scalars = list(grp.keys())
|
|
463
|
+
scalars = [
|
|
464
|
+
'tau_uy','tau_vy','tau_wy',
|
|
465
|
+
'u_tau','v_tau','w_tau',
|
|
466
|
+
'T','mu','nu','rho','p',
|
|
467
|
+
]
|
|
468
|
+
|
|
469
|
+
## 3D [scalar][x,z,t] numpy structured array
|
|
470
|
+
## rank-local data buffer for write
|
|
471
|
+
formats = [ np.dtype(np.float32) for s in scalars ] ## casting to single
|
|
472
|
+
data4spd = np.zeros(shape=(nxr,hf_eas4.nz,hf_eas4.nt), dtype={'names':scalars, 'formats':formats})
|
|
473
|
+
data4spd['tau_uy'][:,:,:] = tau_uy / ( self.rho_inf * self.U_inf**2 )
|
|
474
|
+
data4spd['tau_vy'][:,:,:] = tau_vy / ( self.rho_inf * self.U_inf**2 )
|
|
475
|
+
data4spd['tau_wy'][:,:,:] = tau_wy / ( self.rho_inf * self.U_inf**2 )
|
|
476
|
+
data4spd['T'][:,:,:] = T_wall / self.T_inf
|
|
477
|
+
data4spd['rho'][:,:,:] = rho_wall / self.rho_inf
|
|
478
|
+
data4spd['p'][:,:,:] = p_wall / ( self.rho_inf * self.U_inf**2 )
|
|
479
|
+
data4spd['mu'][:,:,:] = mu_wall / self.mu_inf
|
|
480
|
+
data4spd['nu'][:,:,:] = nu_wall / self.nu_inf
|
|
481
|
+
data4spd['u_tau'][:,:,:] = u_tau / self.U_inf
|
|
482
|
+
data4spd['v_tau'][:,:,:] = v_tau / self.U_inf
|
|
483
|
+
data4spd['w_tau'][:,:,:] = w_tau / self.U_inf
|
|
484
|
+
|
|
485
|
+
tiA = tii
|
|
486
|
+
tiB = tiA + nt
|
|
487
|
+
tii += nt ## increment tii by this EAS4's nt
|
|
488
|
+
|
|
489
|
+
## write
|
|
490
|
+
self.comm.Barrier()
|
|
491
|
+
t_start = timeit.default_timer()
|
|
492
|
+
|
|
493
|
+
if not threeD:
|
|
494
|
+
|
|
495
|
+
#for scalar in data4spd.dtype.names:
|
|
496
|
+
for scalar in scalars:
|
|
497
|
+
dset = self[f'data/{scalar}']
|
|
498
|
+
with dset.collective:
|
|
499
|
+
dset[rx1:rx2,:,tiA:tiB] = data4spd[scalar][:,:,:]
|
|
500
|
+
|
|
501
|
+
else: ## Write as chunkless dset per-file
|
|
502
|
+
|
|
503
|
+
for scalar in scalars:
|
|
504
|
+
dsn = f'data/{i_eas4:d}/{scalar}'
|
|
505
|
+
shape = ( self.nx, self.nz, nt ) ## 'nt' here is from EAS4
|
|
506
|
+
dtype = np.dtype(np.float32)
|
|
507
|
+
|
|
508
|
+
dset = self.create_dataset(
|
|
509
|
+
dsn,
|
|
510
|
+
shape=shape,
|
|
511
|
+
dtype=dtype,
|
|
512
|
+
chunks=None,
|
|
513
|
+
)
|
|
514
|
+
|
|
515
|
+
with dset.collective: ## do actual collective write
|
|
516
|
+
dset[rx1:rx2,:,:] = data4spd[scalar][:,:,:]
|
|
517
|
+
|
|
518
|
+
self.comm.Barrier()
|
|
519
|
+
t_delta = timeit.default_timer() - t_start
|
|
520
|
+
|
|
521
|
+
## Report write speed
|
|
522
|
+
data_gb = self.n_ranks * data4spd.nbytes / 1024**3
|
|
523
|
+
if verbose:
|
|
524
|
+
msg = even_print('write', f'{data_gb:0.2f} [GB] {t_delta:0.2f} [s] {(data_gb/t_delta):0.3f} [GB/s]', s=True)
|
|
525
|
+
tqdm.write(msg)
|
|
526
|
+
|
|
527
|
+
## Delete source file (under restrictive conditions)
|
|
528
|
+
if delete_after_import:
|
|
529
|
+
if os.path.isfile('do_delete.txt'):
|
|
530
|
+
if (self.rank==0):
|
|
531
|
+
tqdm.write(even_print('deleting', fn_eas4, s=True))
|
|
532
|
+
os.remove(fn_eas4)
|
|
533
|
+
self.comm.Barrier()
|
|
534
|
+
|
|
535
|
+
if verbose: progress_bar.update()
|
|
536
|
+
if verbose: progress_bar.close()
|
|
537
|
+
|
|
538
|
+
# ==============================================================
|
|
539
|
+
# MOVE from 3D, chunkless HDF5 file to CHUNKED SPD file
|
|
540
|
+
# ==============================================================
|
|
541
|
+
|
|
542
|
+
if not init_dsets_only and fn_h5_3D is not None:
|
|
543
|
+
|
|
544
|
+
# ## report contents of 3D file
|
|
545
|
+
# if (self.rank==0):
|
|
546
|
+
# with h5py.File(fn_h5_3D, 'r') as hfr:
|
|
547
|
+
# h5_print_contents(hfr)
|
|
548
|
+
# if self.usingmpi:
|
|
549
|
+
# self.comm.Barrier()
|
|
550
|
+
|
|
551
|
+
## Get 'file indices' -- 'indices' are digits in 'data/%d/...' dset names
|
|
552
|
+
if (self.rank==0):
|
|
553
|
+
fi = []
|
|
554
|
+
with h5py.File(fn_h5_3D, 'r') as hfr:
|
|
555
|
+
gpd = hfr['data']
|
|
556
|
+
fi_list = sorted([int(name) for name in gpd.keys() if name.isdigit()])
|
|
557
|
+
nfi_actual = len([ fi for fi in fi_list if fi >= fi_min ]) ## n files to actually process
|
|
558
|
+
fi = np.array(fi_list, dtype=np.int32)
|
|
559
|
+
else:
|
|
560
|
+
fi = np.array([], dtype=np.int32) ## 'fi' must exist on all ranks before bcast
|
|
561
|
+
if self.usingmpi:
|
|
562
|
+
self.comm.Barrier()
|
|
563
|
+
fi = self.comm.bcast(fi, root=0)
|
|
564
|
+
|
|
565
|
+
if fi.shape[0]==0:
|
|
566
|
+
raise RuntimeError
|
|
567
|
+
|
|
568
|
+
nx = self.nx
|
|
569
|
+
#ny = self.ny ## doesnt exist
|
|
570
|
+
nz = self.nz
|
|
571
|
+
#nt = self.nt ## no!
|
|
572
|
+
|
|
573
|
+
scalars = [
|
|
574
|
+
'tau_uy','tau_vy','tau_wy',
|
|
575
|
+
'u_tau','v_tau','w_tau',
|
|
576
|
+
'T','mu','nu','rho','p',
|
|
577
|
+
]
|
|
578
|
+
|
|
579
|
+
if verbose:
|
|
580
|
+
progress_bar = tqdm(
|
|
581
|
+
#total=fi.shape[0]*len(scalars),
|
|
582
|
+
total=nfi_actual*len(scalars),
|
|
583
|
+
ncols=100,
|
|
584
|
+
desc='import',
|
|
585
|
+
leave=True,
|
|
586
|
+
file=sys.stdout,
|
|
587
|
+
mininterval=1/24,
|
|
588
|
+
smoothing=0.3,
|
|
589
|
+
#bar_format="\033[B{l_bar}{bar}| {n}/{total} [{percentage:.1f}%] {elapsed}/{remaining}\033[A\n\b",
|
|
590
|
+
bar_format="{l_bar}{bar}| {n}/{total} [{percentage:.1f}%] {elapsed}/{remaining}",
|
|
591
|
+
ascii="░█",
|
|
592
|
+
colour='#FF6600',
|
|
593
|
+
)
|
|
594
|
+
|
|
595
|
+
tii = 0 ## timestep index counter full series
|
|
596
|
+
|
|
597
|
+
with h5py.File(fn_h5_3D, 'r', driver=self.driver, comm=self.comm) as hfr:
|
|
598
|
+
for fii in fi:
|
|
599
|
+
for scalar in scalars:
|
|
600
|
+
|
|
601
|
+
## dataset name & handle in HDF5 file composed of chunkless dsets
|
|
602
|
+
dsn = f'data/{fii:d}/{scalar}'
|
|
603
|
+
dset = hfr[dsn]
|
|
604
|
+
nt = dset.shape[2] ## nt of corresponding chunkless dset (EAS4)
|
|
605
|
+
|
|
606
|
+
## time range for this EAS4 data
|
|
607
|
+
tiA = tii
|
|
608
|
+
tiB = tiA + nt
|
|
609
|
+
#if verbose:
|
|
610
|
+
# tqdm.write(f'tiA={tiA:d},tiB={tiB:d}')
|
|
611
|
+
|
|
612
|
+
if fii >= fi_min: ## do read / write
|
|
613
|
+
|
|
614
|
+
data_gb = nx * nz * nt * dset.dtype.itemsize / 1024**3
|
|
615
|
+
|
|
616
|
+
## COLLECTIVE read
|
|
617
|
+
if self.usingmpi: self.comm.Barrier()
|
|
618
|
+
t_start = timeit.default_timer()
|
|
619
|
+
if self.usingmpi:
|
|
620
|
+
with dset.collective:
|
|
621
|
+
dd = np.copy( dset[rx1:rx2,:,:] )
|
|
622
|
+
else:
|
|
623
|
+
dd = np.copy( dset[()] )
|
|
624
|
+
if self.usingmpi: self.comm.Barrier()
|
|
625
|
+
t_delta = timeit.default_timer() - t_start
|
|
626
|
+
|
|
627
|
+
if verbose:
|
|
628
|
+
tqdm.write(even_print(f'read: {fii:d}/{scalar}', '%0.3f [GB] %0.3f [s] %0.3f [GB/s]'%(data_gb,t_delta,(data_gb/t_delta)), s=True))
|
|
629
|
+
|
|
630
|
+
## assert shape
|
|
631
|
+
if ( dd.shape != (nxr,nz,nt) ):
|
|
632
|
+
print(f'rank {self.rank:d}: shape violation')
|
|
633
|
+
if self.usingmpi: self.comm.Abort(1)
|
|
634
|
+
raise ValueError
|
|
635
|
+
|
|
636
|
+
## dataset name & handle in SPD file
|
|
637
|
+
dsn = f'data/{scalar}'
|
|
638
|
+
dset = self[dsn]
|
|
639
|
+
|
|
640
|
+
## COLLECTIVE write
|
|
641
|
+
if self.usingmpi: self.comm.Barrier()
|
|
642
|
+
t_start = timeit.default_timer()
|
|
643
|
+
if self.usingmpi:
|
|
644
|
+
with dset.collective:
|
|
645
|
+
dset[rx1:rx2,:,tiA:tiB] = dd[:,:,:]
|
|
646
|
+
else:
|
|
647
|
+
dset[:,:,tiA:tiB] = dd[:,:,:]
|
|
648
|
+
if self.usingmpi: self.comm.Barrier()
|
|
649
|
+
t_delta = timeit.default_timer() - t_start
|
|
650
|
+
|
|
651
|
+
if verbose:
|
|
652
|
+
tqdm.write(even_print(f'write: data/{scalar}', '%0.3f [GB] %0.3f [s] %0.3f [GB/s]'%(data_gb,t_delta,(data_gb/t_delta)), s=True))
|
|
653
|
+
if verbose:
|
|
654
|
+
progress_bar.update()
|
|
655
|
+
|
|
656
|
+
if os.path.isfile('stop.txt'):
|
|
657
|
+
break
|
|
658
|
+
|
|
659
|
+
tii += nt ## increment tii by this EAS4's nt
|
|
660
|
+
|
|
661
|
+
if os.path.isfile('stop.txt'):
|
|
662
|
+
break
|
|
663
|
+
|
|
664
|
+
if verbose:
|
|
665
|
+
progress_bar.close()
|
|
666
|
+
|
|
667
|
+
## Report file
|
|
668
|
+
if self.usingmpi:
|
|
669
|
+
self.comm.Barrier()
|
|
670
|
+
if verbose:
|
|
671
|
+
print(72*'-')
|
|
672
|
+
even_print( os.path.basename(self.fname), f'{(os.path.getsize(self.fname)/1024**3):0.1f} [GB]')
|
|
673
|
+
if verbose: print(72*'-')
|
|
674
|
+
if verbose: print('total time : spd.import_eas4_wall() : %s'%format_time_string((timeit.default_timer() - t_start_func)))
|
|
675
|
+
if verbose: print(72*'-')
|
|
676
|
+
return
|