1818
1919# Internal imports
2020import pipt .misc_tools .analysis_tools as at
21+ import pipt .misc_tools .extract_tools as extract
2122from geostat .decomp import Cholesky # Making realizations
2223from pipt .misc_tools import cov_regularization
2324from pipt .misc_tools import wavelet_tools as wt
2425from misc import read_input_csv as rcsv
2526from misc .system_tools .environ_var import OpenBlasSingleThread # Single threaded OpenBLAS runs
2627
2728
29+
2830class Ensemble :
2931 """
3032 Class for organizing misc. variables and simulator for an ensemble-based inversion run. Here, the forecast step
@@ -56,11 +58,13 @@ def __init__(self, keys_en, sim, redund_sim=None):
5658 self .aux_input = None
5759
5860 # Setup logger
59- logging .basicConfig (level = logging .INFO ,
60- filename = 'pet_logger.log' ,
61- filemode = 'w' ,
62- format = '%(asctime)s : %(levelname)s : %(name)s : %(message)s' ,
63- datefmt = '%Y-%m-%d %H:%M:%S' )
61+ logging .basicConfig (
62+ level = logging .INFO ,
63+ filename = 'pet_logger.log' ,
64+ filemode = 'w' ,
65+ format = '%(asctime)s : %(levelname)s : %(name)s : %(message)s' ,
66+ datefmt = '%Y-%m-%d %H:%M:%S'
67+ )
6468 self .logger = logging .getLogger ('PET' )
6569
6670 # Check if folder contains any En_ files, and remove them!
@@ -117,7 +121,7 @@ def __init__(self, keys_en, sim, redund_sim=None):
117121 self .disable_tqdm = False
118122
119123 # extract information that is given for the prior model
120- self .prior_info = self . _extract_prior_info ( )
124+ self .prior_info = extract . extract_prior_info ( self . keys_en )
121125
122126 # Calculate initial ensemble if IMPORTSTATICVAR has not been given in init. file.
123127 # Prior info. on state variables must be given by PRIOR_<STATICVAR-name> keyword.
@@ -143,7 +147,11 @@ def __init__(self, keys_en, sim, redund_sim=None):
143147 print ('\033 [1;33mInput states have different ensemble size\033 [1;m' )
144148 sys .exit (1 )
145149 self .ne = min (tmp_ne )
146- self ._ext_ml_info ()
150+
151+ if 'multilevel' in self .keys_en :
152+ ml_info = extract .extract_multilevel_info (self .keys_en )
153+ self .multilevel , self .tot_level , self .ml_ne , self .ML_error_corr , self .error_comp_scheme , self .ML_corr_done = ml_info
154+ #self._ext_ml_info()
147155
148156 def _ext_ml_info (self ):
149157 '''
@@ -172,117 +180,7 @@ def _ext_ml_info(self):
172180 self .error_comp_scheme = self .keys_en ['multilevel' ][i ][2 ]
173181 self .ML_corr_done = False
174182
175- def _extract_prior_info (self ) -> dict :
176- '''
177- Extract prior information on STATE from keyword(s) PRIOR_<STATE entries>.
178- '''
179-
180- # Get state names as list
181- state_names = self .keys_en ['state' ]
182- if not isinstance (state_names , list ): state_names = [state_names ]
183-
184- # Check if PRIOR_<state names> exists for each entry in state
185- for name in state_names :
186- assert f'prior_{ name } ' in self .keys_en , \
187- 'PRIOR_{0} is missing! This keyword is needed to make initial ensemble for {0} entered in ' \
188- 'STATE' .format (name .upper ())
189-
190- # define dict to store prior information in
191- prior_info = {name : None for name in state_names }
192-
193- # loop over state priors
194- for name in state_names :
195- prior = self .keys_en [f'prior_{ name } ' ]
196-
197- # Check if is a list (old way)
198- if isinstance (prior , list ):
199- # list of lists - old way of inputting prior information
200- prior_dict = {}
201- for i , opt in enumerate (list (zip (* prior ))[0 ]):
202- if opt == 'limits' :
203- prior_dict [opt ] = prior [i ][1 :]
204- else :
205- prior_dict [opt ] = prior [i ][1 ]
206- prior = prior_dict
207- else :
208- assert isinstance (prior , dict ), 'PRIOR_{0} must be a dictionary or list of lists!' .format (name .upper ())
209-
210-
211- # load mean if in file
212- if isinstance (prior ['mean' ], str ):
213- assert prior ['mean' ].endswith ('.npz' ), 'File name does not end with \' .npz\' !'
214- load_file = np .load (prior ['mean' ])
215- assert len (load_file .files ) == 1 , \
216- 'More than one variable located in {0}. Only the mean vector can be stored in the .npz file!' \
217- .format (prior ['mean' ])
218- prior ['mean' ] = load_file [load_file .files [0 ]]
219- else : # Single number inputted, make it a list if not already
220- if not isinstance (prior ['mean' ], list ):
221- prior ['mean' ] = [prior ['mean' ]]
222-
223- # loop over keys in prior
224- for key in prior .keys ():
225- # ensure that entry is a list
226- if (not isinstance (prior [key ], list )) and (key != 'mean' ):
227- prior [key ] = [prior [key ]]
228-
229- # change the name of some keys
230- prior ['variance' ] = prior .pop ('var' , None )
231- prior ['corr_length' ] = prior .pop ('range' , None )
232-
233- # process grid
234- if 'grid' in prior :
235- grid_dim = prior ['grid' ]
236-
237- # check if 3D-grid
238- if (len (grid_dim ) == 3 ) and (grid_dim [2 ] > 1 ):
239- nz = int (grid_dim [2 ])
240- prior ['nz' ] = nz
241- prior ['nx' ] = int (grid_dim [0 ])
242- prior ['ny' ] = int (grid_dim [1 ])
243-
244-
245- # Check mean when values have been inputted directly (not when mean has been loaded)
246- mean = prior ['mean' ]
247- if isinstance (mean , list ) and len (mean ) < nz :
248- # Check if it is more than one entry and give error
249- assert len (mean ) == 1 , \
250- 'Information from MEAN has been given for {0} layers, whereas {1} is needed!' \
251- .format (len (mean ), nz )
252-
253- # Only 1 entry; copy this to all layers
254- print (
255- '\033 [1;33mSingle entry for MEAN will be copied to all {0} layers\033 [1;m' .format (nz ))
256- prior ['mean' ] = mean * nz
257-
258- #check if info. has been given on all layers. In the case it has not been given, we just copy the info. given.
259- for key in ['vario' , 'variance' , 'aniso' , 'angle' , 'corr_length' ]:
260- if key in prior .keys ():
261- val = prior [key ]
262- if len (val ) < nz :
263- # Check if it is more than one entry and give error
264- assert len (val ) == 1 , \
265- 'Information from {0} has been given for {1} layers, whereas {2} is needed!' \
266- .format (key .upper (), len (val ), nz )
267-
268- # Only 1 entry; copy this to all layers
269- print (
270- '\033 [1;33mSingle entry for {0} will be copied to all {1} layers\033 [1;m' .format (key .upper (), nz ))
271- prior [key ] = val * nz
272-
273- else :
274- prior ['nx' ] = int (grid_dim [0 ])
275- prior ['ny' ] = int (grid_dim [1 ])
276- prior ['nz' ] = 1
277-
278- prior .pop ('grid' , None )
279-
280- # add prior to prior_info
281- prior_info [name ] = prior
282-
283- return prior_info
284-
285-
183+
286184 def gen_init_ensemble (self ):
287185 """
288186 Generate the initial ensemble of (joint) state vectors using the GeoStat class in the "geostat" package.
@@ -353,6 +251,7 @@ def gen_init_ensemble(self):
353251 # Save the ensemble for later inspection
354252 np .savez ('prior.npz' , ** self .state )
355253
254+
356255 def get_list_assim_steps (self ):
357256 """
358257 Returns list of assimilation steps. Useful in a 'loop'-script.
0 commit comments