|
15 | 15 | from tqdm.auto import tqdm |
16 | 16 | from p_tqdm import p_map |
17 | 17 | import logging |
| 18 | +from geostat.decomp import Cholesky # Making realizations |
18 | 19 |
|
19 | 20 | # Internal imports |
20 | 21 | import pipt.misc_tools.analysis_tools as at |
|
26 | 27 | from misc.system_tools.environ_var import OpenBlasSingleThread # Single threaded OpenBLAS runs |
27 | 28 |
|
28 | 29 |
|
29 | | - |
30 | 30 | class Ensemble: |
31 | 31 | """ |
32 | 32 | Class for organizing misc. variables and simulator for an ensemble-based inversion run. Here, the forecast step |
@@ -139,15 +139,24 @@ def __init__(self, keys_en, sim, redund_sim=None): |
139 | 139 | # individually). |
140 | 140 | self.state = {key: val for key, val in tmp_load.items()} |
141 | 141 |
|
142 | | - # Find the number of ensemble members from state variable |
| 142 | + # Find the number of ensemble members from loaded state variables |
143 | 143 | tmp_ne = [] |
144 | 144 | for tmp_state in self.state.keys(): |
145 | 145 | tmp_ne.extend([self.state[tmp_state].shape[1]]) |
146 | | - if max(tmp_ne) != min(tmp_ne): |
147 | | - print('\033[1;33mInput states have different ensemble size\033[1;m') |
148 | | - sys.exit(1) |
149 | | - self.ne = min(tmp_ne) |
150 | | - |
| 146 | + |
| 147 | + if 'ne' not in self.keys_en: # NE not specified in input file |
| 148 | + if max(tmp_ne) != min(tmp_ne): #Check loaded ensembles are the same size (if more than one state variable) |
| 149 | + print('\033[1;33mInput states have different ensemble size\033[1;m') |
| 150 | + sys.exit(1) |
| 151 | + self.ne = min(tmp_ne) # Use the number of ensemble members in loaded ensemble |
| 152 | + else: |
| 153 | + # Use the number of ensemble members specified in input file (may be fewer than loaded) |
| 154 | + self.ne = int(self.keys_en['ne']) |
| 155 | + if self.ne <= min(tmp_ne): |
| 156 | + # pick correct number of ensemble members |
| 157 | + self.state = {key: val[:,:self.ne] for key, val in self.state.items()} |
| 158 | + else: |
| 159 | + print('\033[1;33mInput states are smaller than NE\033[1;m') |
151 | 160 | if 'multilevel' in self.keys_en: |
152 | 161 | ml_info = extract.extract_multilevel_info(self.keys_en) |
153 | 162 | self.multilevel, self.tot_level, self.ml_ne, self.ML_error_corr, self.error_comp_scheme, self.ML_corr_done = ml_info |
@@ -338,6 +347,20 @@ def calc_prediction(self, input_state=None, save_prediction=None): |
338 | 347 | # Index list of ensemble members |
339 | 348 | list_member_index = list(range(self.ne)) |
340 | 349 |
|
| 350 | + # modified by xluo, for including the simulation of the mean reservoir model |
| 351 | + # as used in the RLM-MAC algorithm |
| 352 | + if 'daalg' in self.keys_en and self.keys_en['daalg'][1] == 'gies': |
| 353 | + list_state.append({}) |
| 354 | + list_member_index.append(self.ne) |
| 355 | + |
| 356 | + for key in self.state.keys(): |
| 357 | + tmp_state = np.zeros(list_state[0][key].shape[0]) |
| 358 | + |
| 359 | + for i in range(self.ne): |
| 360 | + tmp_state += list_state[i][key] |
| 361 | + |
| 362 | + list_state[self.ne][key] = tmp_state / self.ne |
| 363 | + |
341 | 364 | if no_tot_run==1: # if not in parallel we use regular loop |
342 | 365 | en_pred = [self.sim.run_fwd_sim(state, member_index) for state, member_index in |
343 | 366 | tqdm(zip(list_state, list_member_index), total=len(list_state))] |
@@ -392,6 +415,7 @@ def calc_prediction(self, input_state=None, save_prediction=None): |
392 | 415 | else: # Run prediction in parallel using p_map |
393 | 416 | en_pred = p_map(self.sim.run_fwd_sim, list_state, |
394 | 417 | list_member_index, num_cpus=no_tot_run, disable=self.disable_tqdm) |
| 418 | + |
395 | 419 | # List successful runs and crashes |
396 | 420 | list_crash = [indx for indx, el in enumerate(en_pred) if el is False] |
397 | 421 | list_success = [indx for indx, el in enumerate(en_pred) if el is not False] |
|
0 commit comments