simulator.simple_models

A collection of trivial toy models.

  1"""A collection of trivial toy models."""
  2# Imports
  3import numpy as np  # Misc. numerical tools
  4import os  # Misc. system tools
  5import sys
  6import scipy.stats as sc  # Extended numerical tools
  7from copy import copy, deepcopy
  8from multiprocessing import Process, Pipe  # To be able to run Python methods in background
  9import time  # To wait a bit before loading files
 10
 11import h5py  # To load matlab .mat files
 12from scipy import interpolate
 13
 14
 15class lin_1d:
 16    """
 17    linear 1x150 model (or whatever), just make observations of the state at given positions.
 18    """
 19
 20    def __init__(self, input_dict=None, m=None):
 21        """
 22        Two inputs here. A dictionary of keys, or parameter directly.
 23
 24        Parameters
 25        ----------
 26        input_dict : dict, optional
 27            Dictionary containing all information required to run the simulator. It may come from, for example, an init file.
 28
 29        m : int, optional
 30            Parameter to make predicted data.
 31
 32        Changelog
 33        ---------
 34        - ST 7/9-15
 35        """
 36        self.input_dict = input_dict
 37
 38        assert 'reporttype' in self.input_dict, 'Reporttype is missing, please specify this'
 39        assert 'reportpoint' in self.input_dict, 'Reportpoint is missing, please specify this'
 40
 41        self.true_prim = [self.input_dict['reporttype'], self.input_dict['reportpoint']]
 42
 43        self.true_order = [self.input_dict['reporttype'], self.input_dict['reportpoint']]
 44        self.all_data_types = self.input_dict['datatype']
 45        self.l_prim = [int(i) for i in range(len(self.true_prim[1]))]
 46
 47        # Inputs
 48        self.input_dict = input_dict
 49        self.m = m
 50        self.keys = {}
 51
 52    def setup_fwd_run(self, **kwargs):
 53        self.__dict__.update(kwargs)  # parse kwargs input into class attributes
 54        assimIndex = [i for i in range(len(self.l_prim))]
 55        trueOrder = self.true_order
 56
 57        self.pred_data = [deepcopy({}) for _ in range(len(assimIndex))]
 58        for ind in self.l_prim:
 59            for key in self.all_data_types:
 60                self.pred_data[ind][key] = np.zeros((1, 1))
 61
 62        if isinstance(trueOrder[1], list):  # Check if true data prim. ind. is a list
 63            self.true_prim = [trueOrder[0], [x for x in trueOrder[1]]]
 64        else:  # Float
 65            self.true_prim = [trueOrder[0], [trueOrder[1]]]
 66
 67    def run_fwd_sim(self, state, member_i, del_folder=True):
 68        inv_param = state.keys()
 69        for prim_ind in self.l_prim:
 70            for dat in self.all_data_types:
 71                tmp_val = []
 72                for para in inv_param:
 73                    tmp_val.append(state[para][self.true_prim[1][prim_ind]])
 74                self.pred_data[prim_ind][dat] = np.array(tmp_val)
 75
 76        return self.pred_data
 77
 78
 79class nonlin_onedimmodel:
 80    """
 81    Class of simple 1D forward model for testing purposes.
 82    """
 83
 84    def __init__(self, input_dict=None):
 85        """
 86        Two inputs here. A dictionary of keys, or parameter directly.
 87
 88        Parameters
 89        ----------
 90        input_dict: dict, optional
 91            contains all information the run the simulator (may come from, e.g., an init file)
 92        """
 93        self.input_dict = input_dict
 94
 95        assert 'reporttype' in self.input_dict, 'Reporttype is missing, please specify this'
 96        assert 'reportpoint' in self.input_dict, 'Reportpoint is missing, please specify this'
 97
 98        self.true_prim = [self.input_dict['reporttype'], self.input_dict['reportpoint']]
 99
100        self.true_order = [self.input_dict['reporttype'], self.input_dict['reportpoint']]
101        self.all_data_types = self.input_dict['datatype']
102        self.l_prim = [int(i) for i in range(len(self.true_prim[1]))]
103
104    def setup_fwd_run(self, **kwargs):
105        self.__dict__.update(kwargs)  # parse kwargs input into class attributes
106        assimIndex = [i for i in range(len(self.l_prim))]
107        trueOrder = self.true_order
108
109        self.pred_data = [deepcopy({}) for _ in range(len(assimIndex))]
110        for ind in self.l_prim:
111            for key in self.all_data_types:
112                self.pred_data[ind][key] = np.zeros((1, 1))
113
114        if isinstance(trueOrder[1], list):  # Check if true data prim. ind. is a list
115            self.true_prim = [trueOrder[0], [x for x in trueOrder[1]]]
116        else:  # Float
117            self.true_prim = [trueOrder[0], [trueOrder[1]]]
118
119    def run_fwd_sim(self, state, member_i, del_folder=True):
120        # Fwd. model given by Chen & Oliver, Computat. Geosci., 17(4), p. 689-703, 2013.
121        inv_param = state.keys()
122        for prim_ind in self.l_prim:
123            for dat in self.all_data_types:
124                tmp_val = []
125                for para in inv_param:
126                    tmp_val.append(
127                        (7 / 12) * (state[para] ** 3) - (7 / 2) * (state[para] ** 2) + 8 * state[para])
128                self.pred_data[prim_ind][dat] = np.array(tmp_val)
129
130        return self.pred_data
131
132
133class sevenmountains:
134    """
135    The objective function is the elevations of the seven mountains around bergen, to test optimization algorithm
136    """
137
138    def __init__(self, input_dict=None, state=None):
139        """
140        Two inputs here. A dictionary of keys, or parameter directly.
141
142        Parameters
143        ----------
144        input_dict: dict, optional
145            contains all information the run the simulator (may come from, e.g., an init file)
146        state: any, optional
147            Parameter to make predicted data
148
149        Changelog
150        ---------
151        - ST 9/5-18
152        """
153
154        # Inputs
155        self.input_dict = input_dict
156
157        self._load_sevenmountains_data()
158
159        # If input option 1 is selected
160        if self.input_dict is not None:
161            self._extInfoInputDict()
162
163        self.state = state
164
165        # Within
166        self.m_inv = None
167
168    def _load_sevenmountains_data(self):
169        # load mountain coordinates from .mat file
170        with h5py.File('sevenMountains.mat', 'r') as f:
171            longitude = list(f['X'])
172            self.longitude = longitude[0]
173            latitude = list(f['Y'])
174            self.latitude = latitude[0]
175            elevation = list(f['Z'])
176            self.elevation = np.asarray(elevation)
177        # self.elevation = interpolate.interp2d(longitude, latitude, elevation)
178
179    def _extInfoInputDict(self):
180        """
181        Extract the manditory and optional information from the input_dict dictionary.
182
183
184        Parameters
185        ----------
186        input_dict : dict
187            Dictionary containing all information required to run the simulator. (Defined in self)
188
189        Returns
190        -------
191        filename : str
192            Name of the .mako file utilized to generate the ecl input .DATA file.
193
194        Changelog
195        ---------
196        - KF 14/9-2015
197        """
198        # In the ecl framework, all reference to the filename should be uppercase
199        # self.file = self.input_dict['runfile'].upper()
200
201        # SIMOPTIONS - simulator options
202        # TODO: Change this when more options are implemented
203        if 'simoption' in self.input_dict and self.input_dict['simoptions'][0] == 'sim_path':
204            self.options = {'sim_path': self.input_dict['simoptions'][1]}
205        else:
206            self.options = {'sim_path': ''}
207
208        if 'origbounds' in self.input_dict:
209            if isinstance(self.input_dict['origbounds'][0], list):
210                origbounds = np.array(self.input_dict['origbounds'])
211            elif self.input_dict['origbounds'] == 'auto':
212                origbounds = np.array([[np.min(self.longitude), np.max(self.longitude)],
213                                       [np.min(self.latitude), np.max(self.latitude)]])
214            else:
215                origbounds = np.array([self.input_dict['origbounds']])
216            self.orig_lb = origbounds[:, 0]
217            self.orig_ub = origbounds[:, 1]
218
219        if 'obj_const' in self.input_dict:
220            self.obj_scaling = self.input_dict['obj_const'][0][1]
221
222        # if
223        # # load mountain coordinates from .mat file and interpolate
224        # with h5py.File('sevenMountains.mat', 'r') as f:
225        #     longitude = list(f['X'])
226        #     longitude = longitude[0]
227        #     latitude = list(f['Y'])
228        #     latitude = latitude[0]
229        #     elevation = list(f['Z'])
230        #     elevation = asarray(elevation)
231        # self.elevation = interpolate.interp2d(longitude, latitude, elevation)
232
233    def setup_fwd_run(self, state, assim_ind=None, true_ind=None):
234        """
235        Set input parameters from an fwd_sim in the simulation to get predicted data. Parameters can be an ensemble or
236        a single array.
237
238        Parameters
239        ----------
240        state : dict
241            Dictionary of input parameter. It can be either a single 'state' or an ensemble of 'state'.
242
243        Other Parameters
244        ----------------
245        true_ind : list
246            The list of observed data assimilation indices.
247
248        assim_ind : list
249            List with information on assimilation order for ensemble-based methods.
250
251        Changelog
252        ---------
253        - ST 3/6-16
254        """
255
256        # Extract parameter
257        self.m_inv = state['coord']
258
259    def run_fwd_sim(self, en_member=None, folder=os.getcwd(), wait_for_proc=False):
260        """
261        Set up and run a forward simulation in an fwd_sim. The parameters for the forward simulation is set in
262        setup_fwd_run. All the steps to set up and run a forward simulation is done in this object.
263
264        Parameters
265        ----------
266        en_member : int, optional
267            Index of the ensemble member to be run.
268
269        folder : str, optional
270            Folder where the forward simulation is run.
271
272        Changelog
273        ---------
274        - ST 3/6-16
275        """
276        # Set free parameter to fixed
277        if self.m_inv.ndim > 1:  # Ensemble matrix
278            self.state = self.m_inv[:, en_member].copy()
279        else:  # Deterministic fwd_sim
280            self.state = copy(self.m_inv)
281
282        # Run forward model
283        # Use Process to run the scripts needed in the simulation
284        p = Process(target=self.call_sim, args=(folder,))
285        p.start()
286        if wait_for_proc is True:  # Use the join method of Process to wait for simulation to be finished
287            p.join()
288        else:
289            pass
290
291        return p
292
293    def call_sim(self, path=None):
294        """
295        Run the simple 1D forward model
296
297        Parameters
298        ----------
299        path : str, optional
300            Alternative folder where the MARE2DEM input files are located.
301
302        Returns
303        -------
304        d : object
305            Predicted data.
306
307        Changelog
308        ---------
309        - ST 3/6-16
310        """
311        # Save path
312        if path is not None:
313            filename = path
314        else:
315            filename = ''
316
317        func = interpolate.interp2d(self.longitude, self.latitude, self.elevation)
318
319        # Convert to original scale
320        # for i, key in enumerate(self.state):
321        control = self.orig_lb + self.state * (self.orig_ub - self.orig_lb)
322
323        if control.ndim == 1:
324            d = func(control[0], control[1])
325        elif control.ndim == 2:
326            n = control.shape[1]
327            d = []
328            for i in range(n):
329                d[i] = func(control[0][i], control[1][i])
330        else:
331            print('\033[1;31mERROR: Input to objective function has wrong dimension.\033[1;m')
332            sys.exit(1)
333        # # Calc. data
334        # d = -self.m ** 2
335
336        # Save in a numpy zip file
337        np.savez(filename + 'pred_data.npz', d=[d])
338
339    # Create static method since the following function does not use 'self'
340    @staticmethod
341    def get_sim_results(which_resp, ext_data_info=None, member=None):
342        """
343        Get forward simulation results. Simply load the numpy array...
344
345        Parameters
346        ----------
347        which_resp : str
348            Specifies which of the responses is to be outputted (just one data type in this case).
349
350        member : int, optional
351            Ensemble member that is finished.
352
353        Returns
354        -------
355        y : numpy.ndarray
356            Array containing the predicted data (response).
357
358        Changelog
359        ---------
360        - ST 3/6-16
361        """
362
363        # Ensemble runs
364        if member is not None:
365            filename = 'En_' + str(member) + os.sep
366
367        # Single run
368        else:
369            filename = ''
370
371        # Load file and get result
372        time.sleep(0.1)
373        load_file = np.load(filename + 'pred_data.npz')
374        y = np.squeeze(load_file['d'])
375
376        # Return predicted data
377        return y
378
379    # Create static method since the following function does not use 'self'
380    @staticmethod
381    def get_obj_func(obj_func_name, data_info=None, member=None):
382        # Ensemble runs
383        if member is not None:
384            filename = 'En_' + str(member) + os.sep
385
386        # Single run
387        else:
388            filename = ''
389
390        # Load file and get result
391        time.sleep(0.1)
392        load_file = np.load(filename + 'pred_data.npz')
393        y = np.squeeze(load_file['d'])
394
395        # Return predicted data
396        return y
397
398    # Create static method since the following function does not use 'self'
399    @staticmethod
400    def check_sim_end(current_run):
401        """
402        Check if a simulation that has run in the background is finished. For ensemble-based methods,
403        there can possibly be several folders with simulations, and each folder must be checked for finished runs. To
404        check if simulation is done we search for .resp file which is the output in a successful  run.
405
406        Parameters
407        ----------
408        current_run : list
409            List of ensemble members currently running simulation.
410
411        Returns
412        -------
413        member : int
414            Ensemble member that is finished.
415
416        Changelog
417        ---------
418        - ST 9/5-18
419        """
420
421        # Initialize output
422        member = None
423
424        # Search for .resp file
425        if isinstance(current_run, list):
426            for i in range(len(current_run)):  # Check all En_ folders
427                # Search with a specific En_folder
428                for file in os.listdir('En_' + str(current_run[i])):
429                    if file == 'pred_data.npz':  # If there is a output .npz file
430                        member = current_run[i]
431        else:
432            member = current_run
433
434        return member
435
436
437class noSimulation:
438
439    def __init__(self, input_dict):
440        # parse information from the input.
441        # Needs to get datatype, reporttype and reportpoint
442        self.input_dict = input_dict
443        self.true_order = None
444
445    def setup_fwd_run(self, **kwargs):
446        # do whatever initialization you need.
447        # Useful to initialize the self.pred_data variable.
448        # self.pred_data is a list of dictionaries. Where each list element represents
449        # a reportpoint and the dictionary should have the datatypes as keys.
450        # Entries in the dictionary are numpy arrays.
451        self.__dict__.update(kwargs)  # parse kwargs input into class attributes
452
453    def run_fwd_sim(self, state, member):
454        # run simulator. Called from the main function using p_map from p_tqdm package.
455        # Return pred_data if run is successfull, False if run failed.
456        return [state]
class lin_1d:
16class lin_1d:
17    """
18    linear 1x150 model (or whatever), just make observations of the state at given positions.
19    """
20
21    def __init__(self, input_dict=None, m=None):
22        """
23        Two inputs here. A dictionary of keys, or parameter directly.
24
25        Parameters
26        ----------
27        input_dict : dict, optional
28            Dictionary containing all information required to run the simulator. It may come from, for example, an init file.
29
30        m : int, optional
31            Parameter to make predicted data.
32
33        Changelog
34        ---------
35        - ST 7/9-15
36        """
37        self.input_dict = input_dict
38
39        assert 'reporttype' in self.input_dict, 'Reporttype is missing, please specify this'
40        assert 'reportpoint' in self.input_dict, 'Reportpoint is missing, please specify this'
41
42        self.true_prim = [self.input_dict['reporttype'], self.input_dict['reportpoint']]
43
44        self.true_order = [self.input_dict['reporttype'], self.input_dict['reportpoint']]
45        self.all_data_types = self.input_dict['datatype']
46        self.l_prim = [int(i) for i in range(len(self.true_prim[1]))]
47
48        # Inputs
49        self.input_dict = input_dict
50        self.m = m
51        self.keys = {}
52
53    def setup_fwd_run(self, **kwargs):
54        self.__dict__.update(kwargs)  # parse kwargs input into class attributes
55        assimIndex = [i for i in range(len(self.l_prim))]
56        trueOrder = self.true_order
57
58        self.pred_data = [deepcopy({}) for _ in range(len(assimIndex))]
59        for ind in self.l_prim:
60            for key in self.all_data_types:
61                self.pred_data[ind][key] = np.zeros((1, 1))
62
63        if isinstance(trueOrder[1], list):  # Check if true data prim. ind. is a list
64            self.true_prim = [trueOrder[0], [x for x in trueOrder[1]]]
65        else:  # Float
66            self.true_prim = [trueOrder[0], [trueOrder[1]]]
67
68    def run_fwd_sim(self, state, member_i, del_folder=True):
69        inv_param = state.keys()
70        for prim_ind in self.l_prim:
71            for dat in self.all_data_types:
72                tmp_val = []
73                for para in inv_param:
74                    tmp_val.append(state[para][self.true_prim[1][prim_ind]])
75                self.pred_data[prim_ind][dat] = np.array(tmp_val)
76
77        return self.pred_data

linear 1x150 model (or whatever), just make observations of the state at given positions.

lin_1d(input_dict=None, m=None)
21    def __init__(self, input_dict=None, m=None):
22        """
23        Two inputs here. A dictionary of keys, or parameter directly.
24
25        Parameters
26        ----------
27        input_dict : dict, optional
28            Dictionary containing all information required to run the simulator. It may come from, for example, an init file.
29
30        m : int, optional
31            Parameter to make predicted data.
32
33        Changelog
34        ---------
35        - ST 7/9-15
36        """
37        self.input_dict = input_dict
38
39        assert 'reporttype' in self.input_dict, 'Reporttype is missing, please specify this'
40        assert 'reportpoint' in self.input_dict, 'Reportpoint is missing, please specify this'
41
42        self.true_prim = [self.input_dict['reporttype'], self.input_dict['reportpoint']]
43
44        self.true_order = [self.input_dict['reporttype'], self.input_dict['reportpoint']]
45        self.all_data_types = self.input_dict['datatype']
46        self.l_prim = [int(i) for i in range(len(self.true_prim[1]))]
47
48        # Inputs
49        self.input_dict = input_dict
50        self.m = m
51        self.keys = {}

Two inputs here. A dictionary of keys, or parameter directly.

Parameters
  • input_dict (dict, optional): Dictionary containing all information required to run the simulator. It may come from, for example, an init file.
  • m (int, optional): Parameter to make predicted data.
Changelog
  • ST 7/9-15
input_dict
true_prim
true_order
all_data_types
l_prim
m
keys
def setup_fwd_run(self, **kwargs):
53    def setup_fwd_run(self, **kwargs):
54        self.__dict__.update(kwargs)  # parse kwargs input into class attributes
55        assimIndex = [i for i in range(len(self.l_prim))]
56        trueOrder = self.true_order
57
58        self.pred_data = [deepcopy({}) for _ in range(len(assimIndex))]
59        for ind in self.l_prim:
60            for key in self.all_data_types:
61                self.pred_data[ind][key] = np.zeros((1, 1))
62
63        if isinstance(trueOrder[1], list):  # Check if true data prim. ind. is a list
64            self.true_prim = [trueOrder[0], [x for x in trueOrder[1]]]
65        else:  # Float
66            self.true_prim = [trueOrder[0], [trueOrder[1]]]
def run_fwd_sim(self, state, member_i, del_folder=True):
68    def run_fwd_sim(self, state, member_i, del_folder=True):
69        inv_param = state.keys()
70        for prim_ind in self.l_prim:
71            for dat in self.all_data_types:
72                tmp_val = []
73                for para in inv_param:
74                    tmp_val.append(state[para][self.true_prim[1][prim_ind]])
75                self.pred_data[prim_ind][dat] = np.array(tmp_val)
76
77        return self.pred_data
class nonlin_onedimmodel:
 80class nonlin_onedimmodel:
 81    """
 82    Class of simple 1D forward model for testing purposes.
 83    """
 84
 85    def __init__(self, input_dict=None):
 86        """
 87        Two inputs here. A dictionary of keys, or parameter directly.
 88
 89        Parameters
 90        ----------
 91        input_dict: dict, optional
 92            contains all information the run the simulator (may come from, e.g., an init file)
 93        """
 94        self.input_dict = input_dict
 95
 96        assert 'reporttype' in self.input_dict, 'Reporttype is missing, please specify this'
 97        assert 'reportpoint' in self.input_dict, 'Reportpoint is missing, please specify this'
 98
 99        self.true_prim = [self.input_dict['reporttype'], self.input_dict['reportpoint']]
100
101        self.true_order = [self.input_dict['reporttype'], self.input_dict['reportpoint']]
102        self.all_data_types = self.input_dict['datatype']
103        self.l_prim = [int(i) for i in range(len(self.true_prim[1]))]
104
105    def setup_fwd_run(self, **kwargs):
106        self.__dict__.update(kwargs)  # parse kwargs input into class attributes
107        assimIndex = [i for i in range(len(self.l_prim))]
108        trueOrder = self.true_order
109
110        self.pred_data = [deepcopy({}) for _ in range(len(assimIndex))]
111        for ind in self.l_prim:
112            for key in self.all_data_types:
113                self.pred_data[ind][key] = np.zeros((1, 1))
114
115        if isinstance(trueOrder[1], list):  # Check if true data prim. ind. is a list
116            self.true_prim = [trueOrder[0], [x for x in trueOrder[1]]]
117        else:  # Float
118            self.true_prim = [trueOrder[0], [trueOrder[1]]]
119
120    def run_fwd_sim(self, state, member_i, del_folder=True):
121        # Fwd. model given by Chen & Oliver, Computat. Geosci., 17(4), p. 689-703, 2013.
122        inv_param = state.keys()
123        for prim_ind in self.l_prim:
124            for dat in self.all_data_types:
125                tmp_val = []
126                for para in inv_param:
127                    tmp_val.append(
128                        (7 / 12) * (state[para] ** 3) - (7 / 2) * (state[para] ** 2) + 8 * state[para])
129                self.pred_data[prim_ind][dat] = np.array(tmp_val)
130
131        return self.pred_data

Class of simple 1D forward model for testing purposes.

nonlin_onedimmodel(input_dict=None)
 85    def __init__(self, input_dict=None):
 86        """
 87        Two inputs here. A dictionary of keys, or parameter directly.
 88
 89        Parameters
 90        ----------
 91        input_dict: dict, optional
 92            contains all information the run the simulator (may come from, e.g., an init file)
 93        """
 94        self.input_dict = input_dict
 95
 96        assert 'reporttype' in self.input_dict, 'Reporttype is missing, please specify this'
 97        assert 'reportpoint' in self.input_dict, 'Reportpoint is missing, please specify this'
 98
 99        self.true_prim = [self.input_dict['reporttype'], self.input_dict['reportpoint']]
100
101        self.true_order = [self.input_dict['reporttype'], self.input_dict['reportpoint']]
102        self.all_data_types = self.input_dict['datatype']
103        self.l_prim = [int(i) for i in range(len(self.true_prim[1]))]

Two inputs here. A dictionary of keys, or parameter directly.

Parameters
  • input_dict (dict, optional): contains all information the run the simulator (may come from, e.g., an init file)
input_dict
true_prim
true_order
all_data_types
l_prim
def setup_fwd_run(self, **kwargs):
105    def setup_fwd_run(self, **kwargs):
106        self.__dict__.update(kwargs)  # parse kwargs input into class attributes
107        assimIndex = [i for i in range(len(self.l_prim))]
108        trueOrder = self.true_order
109
110        self.pred_data = [deepcopy({}) for _ in range(len(assimIndex))]
111        for ind in self.l_prim:
112            for key in self.all_data_types:
113                self.pred_data[ind][key] = np.zeros((1, 1))
114
115        if isinstance(trueOrder[1], list):  # Check if true data prim. ind. is a list
116            self.true_prim = [trueOrder[0], [x for x in trueOrder[1]]]
117        else:  # Float
118            self.true_prim = [trueOrder[0], [trueOrder[1]]]
def run_fwd_sim(self, state, member_i, del_folder=True):
120    def run_fwd_sim(self, state, member_i, del_folder=True):
121        # Fwd. model given by Chen & Oliver, Computat. Geosci., 17(4), p. 689-703, 2013.
122        inv_param = state.keys()
123        for prim_ind in self.l_prim:
124            for dat in self.all_data_types:
125                tmp_val = []
126                for para in inv_param:
127                    tmp_val.append(
128                        (7 / 12) * (state[para] ** 3) - (7 / 2) * (state[para] ** 2) + 8 * state[para])
129                self.pred_data[prim_ind][dat] = np.array(tmp_val)
130
131        return self.pred_data
class sevenmountains:
134class sevenmountains:
135    """
136    The objective function is the elevations of the seven mountains around bergen, to test optimization algorithm
137    """
138
139    def __init__(self, input_dict=None, state=None):
140        """
141        Two inputs here. A dictionary of keys, or parameter directly.
142
143        Parameters
144        ----------
145        input_dict: dict, optional
146            contains all information the run the simulator (may come from, e.g., an init file)
147        state: any, optional
148            Parameter to make predicted data
149
150        Changelog
151        ---------
152        - ST 9/5-18
153        """
154
155        # Inputs
156        self.input_dict = input_dict
157
158        self._load_sevenmountains_data()
159
160        # If input option 1 is selected
161        if self.input_dict is not None:
162            self._extInfoInputDict()
163
164        self.state = state
165
166        # Within
167        self.m_inv = None
168
169    def _load_sevenmountains_data(self):
170        # load mountain coordinates from .mat file
171        with h5py.File('sevenMountains.mat', 'r') as f:
172            longitude = list(f['X'])
173            self.longitude = longitude[0]
174            latitude = list(f['Y'])
175            self.latitude = latitude[0]
176            elevation = list(f['Z'])
177            self.elevation = np.asarray(elevation)
178        # self.elevation = interpolate.interp2d(longitude, latitude, elevation)
179
180    def _extInfoInputDict(self):
181        """
182        Extract the manditory and optional information from the input_dict dictionary.
183
184
185        Parameters
186        ----------
187        input_dict : dict
188            Dictionary containing all information required to run the simulator. (Defined in self)
189
190        Returns
191        -------
192        filename : str
193            Name of the .mako file utilized to generate the ecl input .DATA file.
194
195        Changelog
196        ---------
197        - KF 14/9-2015
198        """
199        # In the ecl framework, all reference to the filename should be uppercase
200        # self.file = self.input_dict['runfile'].upper()
201
202        # SIMOPTIONS - simulator options
203        # TODO: Change this when more options are implemented
204        if 'simoption' in self.input_dict and self.input_dict['simoptions'][0] == 'sim_path':
205            self.options = {'sim_path': self.input_dict['simoptions'][1]}
206        else:
207            self.options = {'sim_path': ''}
208
209        if 'origbounds' in self.input_dict:
210            if isinstance(self.input_dict['origbounds'][0], list):
211                origbounds = np.array(self.input_dict['origbounds'])
212            elif self.input_dict['origbounds'] == 'auto':
213                origbounds = np.array([[np.min(self.longitude), np.max(self.longitude)],
214                                       [np.min(self.latitude), np.max(self.latitude)]])
215            else:
216                origbounds = np.array([self.input_dict['origbounds']])
217            self.orig_lb = origbounds[:, 0]
218            self.orig_ub = origbounds[:, 1]
219
220        if 'obj_const' in self.input_dict:
221            self.obj_scaling = self.input_dict['obj_const'][0][1]
222
223        # if
224        # # load mountain coordinates from .mat file and interpolate
225        # with h5py.File('sevenMountains.mat', 'r') as f:
226        #     longitude = list(f['X'])
227        #     longitude = longitude[0]
228        #     latitude = list(f['Y'])
229        #     latitude = latitude[0]
230        #     elevation = list(f['Z'])
231        #     elevation = asarray(elevation)
232        # self.elevation = interpolate.interp2d(longitude, latitude, elevation)
233
234    def setup_fwd_run(self, state, assim_ind=None, true_ind=None):
235        """
236        Set input parameters from an fwd_sim in the simulation to get predicted data. Parameters can be an ensemble or
237        a single array.
238
239        Parameters
240        ----------
241        state : dict
242            Dictionary of input parameter. It can be either a single 'state' or an ensemble of 'state'.
243
244        Other Parameters
245        ----------------
246        true_ind : list
247            The list of observed data assimilation indices.
248
249        assim_ind : list
250            List with information on assimilation order for ensemble-based methods.
251
252        Changelog
253        ---------
254        - ST 3/6-16
255        """
256
257        # Extract parameter
258        self.m_inv = state['coord']
259
260    def run_fwd_sim(self, en_member=None, folder=os.getcwd(), wait_for_proc=False):
261        """
262        Set up and run a forward simulation in an fwd_sim. The parameters for the forward simulation is set in
263        setup_fwd_run. All the steps to set up and run a forward simulation is done in this object.
264
265        Parameters
266        ----------
267        en_member : int, optional
268            Index of the ensemble member to be run.
269
270        folder : str, optional
271            Folder where the forward simulation is run.
272
273        Changelog
274        ---------
275        - ST 3/6-16
276        """
277        # Set free parameter to fixed
278        if self.m_inv.ndim > 1:  # Ensemble matrix
279            self.state = self.m_inv[:, en_member].copy()
280        else:  # Deterministic fwd_sim
281            self.state = copy(self.m_inv)
282
283        # Run forward model
284        # Use Process to run the scripts needed in the simulation
285        p = Process(target=self.call_sim, args=(folder,))
286        p.start()
287        if wait_for_proc is True:  # Use the join method of Process to wait for simulation to be finished
288            p.join()
289        else:
290            pass
291
292        return p
293
294    def call_sim(self, path=None):
295        """
296        Run the simple 1D forward model
297
298        Parameters
299        ----------
300        path : str, optional
301            Alternative folder where the MARE2DEM input files are located.
302
303        Returns
304        -------
305        d : object
306            Predicted data.
307
308        Changelog
309        ---------
310        - ST 3/6-16
311        """
312        # Save path
313        if path is not None:
314            filename = path
315        else:
316            filename = ''
317
318        func = interpolate.interp2d(self.longitude, self.latitude, self.elevation)
319
320        # Convert to original scale
321        # for i, key in enumerate(self.state):
322        control = self.orig_lb + self.state * (self.orig_ub - self.orig_lb)
323
324        if control.ndim == 1:
325            d = func(control[0], control[1])
326        elif control.ndim == 2:
327            n = control.shape[1]
328            d = []
329            for i in range(n):
330                d[i] = func(control[0][i], control[1][i])
331        else:
332            print('\033[1;31mERROR: Input to objective function has wrong dimension.\033[1;m')
333            sys.exit(1)
334        # # Calc. data
335        # d = -self.m ** 2
336
337        # Save in a numpy zip file
338        np.savez(filename + 'pred_data.npz', d=[d])
339
340    # Create static method since the following function does not use 'self'
341    @staticmethod
342    def get_sim_results(which_resp, ext_data_info=None, member=None):
343        """
344        Get forward simulation results. Simply load the numpy array...
345
346        Parameters
347        ----------
348        which_resp : str
349            Specifies which of the responses is to be outputted (just one data type in this case).
350
351        member : int, optional
352            Ensemble member that is finished.
353
354        Returns
355        -------
356        y : numpy.ndarray
357            Array containing the predicted data (response).
358
359        Changelog
360        ---------
361        - ST 3/6-16
362        """
363
364        # Ensemble runs
365        if member is not None:
366            filename = 'En_' + str(member) + os.sep
367
368        # Single run
369        else:
370            filename = ''
371
372        # Load file and get result
373        time.sleep(0.1)
374        load_file = np.load(filename + 'pred_data.npz')
375        y = np.squeeze(load_file['d'])
376
377        # Return predicted data
378        return y
379
380    # Create static method since the following function does not use 'self'
381    @staticmethod
382    def get_obj_func(obj_func_name, data_info=None, member=None):
383        # Ensemble runs
384        if member is not None:
385            filename = 'En_' + str(member) + os.sep
386
387        # Single run
388        else:
389            filename = ''
390
391        # Load file and get result
392        time.sleep(0.1)
393        load_file = np.load(filename + 'pred_data.npz')
394        y = np.squeeze(load_file['d'])
395
396        # Return predicted data
397        return y
398
399    # Create static method since the following function does not use 'self'
400    @staticmethod
401    def check_sim_end(current_run):
402        """
403        Check if a simulation that has run in the background is finished. For ensemble-based methods,
404        there can possibly be several folders with simulations, and each folder must be checked for finished runs. To
405        check if simulation is done we search for .resp file which is the output in a successful  run.
406
407        Parameters
408        ----------
409        current_run : list
410            List of ensemble members currently running simulation.
411
412        Returns
413        -------
414        member : int
415            Ensemble member that is finished.
416
417        Changelog
418        ---------
419        - ST 9/5-18
420        """
421
422        # Initialize output
423        member = None
424
425        # Search for .resp file
426        if isinstance(current_run, list):
427            for i in range(len(current_run)):  # Check all En_ folders
428                # Search with a specific En_folder
429                for file in os.listdir('En_' + str(current_run[i])):
430                    if file == 'pred_data.npz':  # If there is a output .npz file
431                        member = current_run[i]
432        else:
433            member = current_run
434
435        return member

The objective function is the elevations of the seven mountains around bergen, to test optimization algorithm

sevenmountains(input_dict=None, state=None)
139    def __init__(self, input_dict=None, state=None):
140        """
141        Two inputs here. A dictionary of keys, or parameter directly.
142
143        Parameters
144        ----------
145        input_dict: dict, optional
146            contains all information the run the simulator (may come from, e.g., an init file)
147        state: any, optional
148            Parameter to make predicted data
149
150        Changelog
151        ---------
152        - ST 9/5-18
153        """
154
155        # Inputs
156        self.input_dict = input_dict
157
158        self._load_sevenmountains_data()
159
160        # If input option 1 is selected
161        if self.input_dict is not None:
162            self._extInfoInputDict()
163
164        self.state = state
165
166        # Within
167        self.m_inv = None

Two inputs here. A dictionary of keys, or parameter directly.

Parameters
  • input_dict (dict, optional): contains all information the run the simulator (may come from, e.g., an init file)
  • state (any, optional): Parameter to make predicted data
Changelog
  • ST 9/5-18
input_dict
state
m_inv
def setup_fwd_run(self, state, assim_ind=None, true_ind=None):
234    def setup_fwd_run(self, state, assim_ind=None, true_ind=None):
235        """
236        Set input parameters from an fwd_sim in the simulation to get predicted data. Parameters can be an ensemble or
237        a single array.
238
239        Parameters
240        ----------
241        state : dict
242            Dictionary of input parameter. It can be either a single 'state' or an ensemble of 'state'.
243
244        Other Parameters
245        ----------------
246        true_ind : list
247            The list of observed data assimilation indices.
248
249        assim_ind : list
250            List with information on assimilation order for ensemble-based methods.
251
252        Changelog
253        ---------
254        - ST 3/6-16
255        """
256
257        # Extract parameter
258        self.m_inv = state['coord']

Set input parameters from an fwd_sim in the simulation to get predicted data. Parameters can be an ensemble or a single array.

Parameters
  • state (dict): Dictionary of input parameter. It can be either a single 'state' or an ensemble of 'state'.
Other Parameters
  • true_ind (list): The list of observed data assimilation indices.
  • assim_ind (list): List with information on assimilation order for ensemble-based methods.
Changelog
  • ST 3/6-16
def run_fwd_sim( self, en_member=None, folder='/home/runner/work/PET/PET', wait_for_proc=False):
260    def run_fwd_sim(self, en_member=None, folder=os.getcwd(), wait_for_proc=False):
261        """
262        Set up and run a forward simulation in an fwd_sim. The parameters for the forward simulation is set in
263        setup_fwd_run. All the steps to set up and run a forward simulation is done in this object.
264
265        Parameters
266        ----------
267        en_member : int, optional
268            Index of the ensemble member to be run.
269
270        folder : str, optional
271            Folder where the forward simulation is run.
272
273        Changelog
274        ---------
275        - ST 3/6-16
276        """
277        # Set free parameter to fixed
278        if self.m_inv.ndim > 1:  # Ensemble matrix
279            self.state = self.m_inv[:, en_member].copy()
280        else:  # Deterministic fwd_sim
281            self.state = copy(self.m_inv)
282
283        # Run forward model
284        # Use Process to run the scripts needed in the simulation
285        p = Process(target=self.call_sim, args=(folder,))
286        p.start()
287        if wait_for_proc is True:  # Use the join method of Process to wait for simulation to be finished
288            p.join()
289        else:
290            pass
291
292        return p

Set up and run a forward simulation in an fwd_sim. The parameters for the forward simulation is set in setup_fwd_run. All the steps to set up and run a forward simulation is done in this object.

Parameters
  • en_member (int, optional): Index of the ensemble member to be run.
  • folder (str, optional): Folder where the forward simulation is run.
Changelog
  • ST 3/6-16
def call_sim(self, path=None):
294    def call_sim(self, path=None):
295        """
296        Run the simple 1D forward model
297
298        Parameters
299        ----------
300        path : str, optional
301            Alternative folder where the MARE2DEM input files are located.
302
303        Returns
304        -------
305        d : object
306            Predicted data.
307
308        Changelog
309        ---------
310        - ST 3/6-16
311        """
312        # Save path
313        if path is not None:
314            filename = path
315        else:
316            filename = ''
317
318        func = interpolate.interp2d(self.longitude, self.latitude, self.elevation)
319
320        # Convert to original scale
321        # for i, key in enumerate(self.state):
322        control = self.orig_lb + self.state * (self.orig_ub - self.orig_lb)
323
324        if control.ndim == 1:
325            d = func(control[0], control[1])
326        elif control.ndim == 2:
327            n = control.shape[1]
328            d = []
329            for i in range(n):
330                d[i] = func(control[0][i], control[1][i])
331        else:
332            print('\033[1;31mERROR: Input to objective function has wrong dimension.\033[1;m')
333            sys.exit(1)
334        # # Calc. data
335        # d = -self.m ** 2
336
337        # Save in a numpy zip file
338        np.savez(filename + 'pred_data.npz', d=[d])

Run the simple 1D forward model

Parameters
  • path (str, optional): Alternative folder where the MARE2DEM input files are located.
Returns
  • d (object): Predicted data.
Changelog
  • ST 3/6-16
@staticmethod
def get_sim_results(which_resp, ext_data_info=None, member=None):
341    @staticmethod
342    def get_sim_results(which_resp, ext_data_info=None, member=None):
343        """
344        Get forward simulation results. Simply load the numpy array...
345
346        Parameters
347        ----------
348        which_resp : str
349            Specifies which of the responses is to be outputted (just one data type in this case).
350
351        member : int, optional
352            Ensemble member that is finished.
353
354        Returns
355        -------
356        y : numpy.ndarray
357            Array containing the predicted data (response).
358
359        Changelog
360        ---------
361        - ST 3/6-16
362        """
363
364        # Ensemble runs
365        if member is not None:
366            filename = 'En_' + str(member) + os.sep
367
368        # Single run
369        else:
370            filename = ''
371
372        # Load file and get result
373        time.sleep(0.1)
374        load_file = np.load(filename + 'pred_data.npz')
375        y = np.squeeze(load_file['d'])
376
377        # Return predicted data
378        return y

Get forward simulation results. Simply load the numpy array...

Parameters
  • which_resp (str): Specifies which of the responses is to be outputted (just one data type in this case).
  • member (int, optional): Ensemble member that is finished.
Returns
  • y (numpy.ndarray): Array containing the predicted data (response).
Changelog
  • ST 3/6-16
@staticmethod
def get_obj_func(obj_func_name, data_info=None, member=None):
381    @staticmethod
382    def get_obj_func(obj_func_name, data_info=None, member=None):
383        # Ensemble runs
384        if member is not None:
385            filename = 'En_' + str(member) + os.sep
386
387        # Single run
388        else:
389            filename = ''
390
391        # Load file and get result
392        time.sleep(0.1)
393        load_file = np.load(filename + 'pred_data.npz')
394        y = np.squeeze(load_file['d'])
395
396        # Return predicted data
397        return y
@staticmethod
def check_sim_end(current_run):
400    @staticmethod
401    def check_sim_end(current_run):
402        """
403        Check if a simulation that has run in the background is finished. For ensemble-based methods,
404        there can possibly be several folders with simulations, and each folder must be checked for finished runs. To
405        check if simulation is done we search for .resp file which is the output in a successful  run.
406
407        Parameters
408        ----------
409        current_run : list
410            List of ensemble members currently running simulation.
411
412        Returns
413        -------
414        member : int
415            Ensemble member that is finished.
416
417        Changelog
418        ---------
419        - ST 9/5-18
420        """
421
422        # Initialize output
423        member = None
424
425        # Search for .resp file
426        if isinstance(current_run, list):
427            for i in range(len(current_run)):  # Check all En_ folders
428                # Search with a specific En_folder
429                for file in os.listdir('En_' + str(current_run[i])):
430                    if file == 'pred_data.npz':  # If there is a output .npz file
431                        member = current_run[i]
432        else:
433            member = current_run
434
435        return member

Check if a simulation that has run in the background is finished. For ensemble-based methods, there can possibly be several folders with simulations, and each folder must be checked for finished runs. To check if simulation is done we search for .resp file which is the output in a successful run.

Parameters
  • current_run (list): List of ensemble members currently running simulation.
Returns
  • member (int): Ensemble member that is finished.
Changelog
  • ST 9/5-18
class noSimulation:
438class noSimulation:
439
440    def __init__(self, input_dict):
441        # parse information from the input.
442        # Needs to get datatype, reporttype and reportpoint
443        self.input_dict = input_dict
444        self.true_order = None
445
446    def setup_fwd_run(self, **kwargs):
447        # do whatever initialization you need.
448        # Useful to initialize the self.pred_data variable.
449        # self.pred_data is a list of dictionaries. Where each list element represents
450        # a reportpoint and the dictionary should have the datatypes as keys.
451        # Entries in the dictionary are numpy arrays.
452        self.__dict__.update(kwargs)  # parse kwargs input into class attributes
453
454    def run_fwd_sim(self, state, member):
455        # run simulator. Called from the main function using p_map from p_tqdm package.
456        # Return pred_data if run is successfull, False if run failed.
457        return [state]
noSimulation(input_dict)
440    def __init__(self, input_dict):
441        # parse information from the input.
442        # Needs to get datatype, reporttype and reportpoint
443        self.input_dict = input_dict
444        self.true_order = None
input_dict
true_order
def setup_fwd_run(self, **kwargs):
446    def setup_fwd_run(self, **kwargs):
447        # do whatever initialization you need.
448        # Useful to initialize the self.pred_data variable.
449        # self.pred_data is a list of dictionaries. Where each list element represents
450        # a reportpoint and the dictionary should have the datatypes as keys.
451        # Entries in the dictionary are numpy arrays.
452        self.__dict__.update(kwargs)  # parse kwargs input into class attributes
def run_fwd_sim(self, state, member):
454    def run_fwd_sim(self, state, member):
455        # run simulator. Called from the main function using p_map from p_tqdm package.
456        # Return pred_data if run is successfull, False if run failed.
457        return [state]