66import time
77import numpy as np
88from tqdm import tqdm
9- from numpy import linalg as la
10- from scipy .fft import fft
119import shutil
1210
1311
@@ -47,57 +45,23 @@ def fit(self):
4745 # loop over number of blocks and generate Fourier realizations,
4846 # if blocks are not saved in storage
4947 if not blocks_present :
50-
5148 Q_blk = np .zeros ([self ._n_DFT ,self ._nx ], dtype = 'complex_' )
52-
5349 for iBlk in range (0 ,self ._n_blocks ):
5450
55- # get time index for present block
56- offset = min ( iBlk * ( self ._n_DFT - self . _n_overlap ) + self . _n_DFT , self . _nt ) - self . _n_DFT
51+ # compute block
52+ Q_blk_hat , offset = self .compute_blocks ( iBlk )
5753
54+ # print info file
5855 print ('block ' + str (iBlk + 1 )+ '/' + str (self ._n_blocks )+ \
5956 ' (' + str (offset )+ ':' + str (self ._n_DFT + offset )+ '); ' ,
6057 ' Saving to directory: ' , self ._save_dir_blocks )
6158
62- # # build present block
63- # for ti in timeIdx:
64- # x = self._X[ti]
65- # x = x.reshape(x.size)
66- # Q_blk[ti-offset,:] = np.subtract(x[:], self._x_mean)
67-
68- Q_blk = self ._data_handler (
69- self ._data , t_0 = offset , t_end = self ._n_DFT + offset , variables = self ._variables )
70- Q_blk = Q_blk .reshape (self ._n_DFT , self ._nx * self ._nv )
71-
72- # Subtract longtime or provided mean
73- Q_blk = Q_blk [:] - self ._x_mean
74-
75- # if block mean is to be subtracted, do it now that all data is collected
76- if self ._mean_type .lower () == 'blockwise' :
77- Q_blk = Q_blk - np .mean (Q_blk , axis = 0 )
78-
79- # normalize by pointwise variance
80- if self ._normvar :
81- Q_var = np .sum ((Q_blk - np .mean (Q_blk ,axis = 0 ))** 2 , axis = 0 ) / (self ._n_DFT - 1 )
82- # address division-by-0 problem with NaNs
83- Q_var [Q_var < 4 * np .finfo (float ).eps ] = 1 ;
84- Q_blk = Q_blk / Q_var
85-
86- # window and Fourier transform block
87- self ._window = self ._window .reshape (self ._window .shape [0 ],1 )
88- Q_blk = Q_blk * self ._window
89- Q_blk_hat = (self ._winWeight / self ._n_DFT ) * np .fft .fft (Q_blk , axis = 0 );
90- Q_blk_hat = Q_blk_hat [0 :self ._n_freq ,:];
91-
92- # correct Fourier coefficients for one-sided spectrum
93- if self ._isrealx :
94- Q_blk_hat [1 :- 1 ,:] = 2 * Q_blk_hat [1 :- 1 ,:]
95-
9659 # save FFT blocks in storage memory
9760 for iFreq in range (0 ,self ._n_freq ):
9861 file = os .path .join (self ._save_dir_blocks ,'fft_block{:04d}_freq{:04d}.npy' .format (iBlk ,iFreq ))
9962 Q_blk_hat_fi = Q_blk_hat [iFreq ,:]
10063 np .save (file , Q_blk_hat_fi )
64+
10165 print ('------------------------------------' )
10266
10367
@@ -106,19 +70,18 @@ def fit(self):
10670 print (' ' )
10771 print ('Calculating SPOD (low_ram)' )
10872 print ('------------------------------------' )
109- n_modes_save = self ._n_blocks
110- if 'n_modes_save' in self ._params : n_modes_save = self ._params ['n_modes_save' ]
11173 self ._eigs = np .zeros ([self ._n_freq ,self ._n_blocks ], dtype = 'complex_' )
11274 self ._modes = dict ()
113- gb_memory_modes = self ._n_freq * self ._nx * n_modes_save * sys .getsizeof (complex ()) * BYTE_TO_GB
75+
76+ gb_memory_modes = self ._n_freq * self ._nx * self ._n_modes_save * sys .getsizeof (complex ()) * BYTE_TO_GB
11477 gb_memory_avail = shutil .disk_usage (CWD )[2 ] * BYTE_TO_GB
11578 print ('- Memory required for storing modes ~' , gb_memory_modes , 'GB' )
11679 print ('- Available storage memory ~' , gb_memory_avail , 'GB' )
11780 while gb_memory_modes >= 0.99 * gb_memory_avail :
11881 print ('Not enough storage memory to save all modes... halving modes to save.' )
119- n_modes_save = np .floor (n_modes_save / 2 )
120- gb_memory_modes = self ._n_freq * self ._nx * n_modes_save * sys .getsizeof (complex ()) * BYTE_TO_GB
121- if n_modes_save == 0 :
82+ n_modes_save = np .floor (self . _n_modes_save / 2 )
83+ gb_memory_modes = self ._n_freq * self ._nx * self . _n_modes_save * sys .getsizeof (complex ()) * BYTE_TO_GB
84+ if self . _n_modes_save == 0 :
12285 raise ValueError ('Memory required for storing at least one mode '
12386 'is equal or larger than available storage memory in your system ...\n '
12487 '... aborting computation...' )
@@ -132,40 +95,11 @@ def fit(self):
13295 file = os .path .join (self ._save_dir_blocks ,'fft_block{:04d}_freq{:04d}.npy' .format (iBlk ,iFreq ))
13396 Q_hat_f [:,iBlk ] = np .load (file )
13497
135- # compute inner product in frequency space, for given frequency
136- M = np .matmul (Q_hat_f .conj ().T , (Q_hat_f * self ._weights )) / self ._n_blocks
137-
138- # extract eigenvalues and eigenvectors
139- L ,V = la .eig (M )
140- L = np .real_if_close (L , tol = 1000000 )
141-
142- # reorder eigenvalues and eigenvectors
143- idx = np .argsort (L )[::- 1 ]
144- L = L [idx ]
145- V = V [:,idx ]
146-
147- # compute spatial modes for given frequency
148- Psi = np .matmul (Q_hat_f , np .matmul (V , np .diag (1. / np .sqrt (L ) / np .sqrt (self ._n_blocks ))))
149-
150- # save modes in storage too in case post-processing crashes
151- Psi = Psi [:,0 :n_modes_save ]
152- Psi = Psi .reshape (self ._xshape + (self ._nv ,)+ (n_modes_save ,))
153- file_psi = os .path .join (self ._save_dir_blocks ,'modes1to{:04d}_freq{:04d}.npy' .format (n_modes_save ,iFreq ))
154- np .save (file_psi , Psi )
155- self ._modes [iFreq ] = file_psi
156- self ._eigs [iFreq ,:] = abs (L )
157-
158- # get and save confidence interval if required
159- if self ._conf_interval :
160- self ._eigs_c [iFreq ,:,0 ] = self ._eigs [iFreq ,:] * 2 * self ._n_blocks / self ._xi2_lower
161- self ._eigs_c [iFreq ,:,1 ] = self ._eigs [iFreq ,:] * 2 * self ._n_blocks / self ._xi2_upper
162- self ._eigs_c_u = self ._eigs_c [:,:,0 ]
163- self ._eigs_c_l = self ._eigs_c [:,:,1 ]
164- file = os .path .join (self ._save_dir_blocks ,'spod_energy' )
165- np .savez (file , eigs = self ._eigs , eigs_c_u = self ._eigs_c_u , eigs_c_l = self ._eigs_c_l , f = self ._freq )
166- self ._n_modes = self ._eigs .shape [- 1 ]
167- self ._n_modes_saved = n_modes_save
98+ # compute standard spod
99+ self .compute_standard_spod (Q_hat_f , iFreq )
168100
101+ # store and save results
102+ self .store_and_save ()
169103
170104 # delete FFT blocks from memory if saving not required
171105 if self ._savefft == False :
0 commit comments