def __init__(self, res_config, controls, results): """Will create simulator which can be used to run multiple simulations. The @res_config argument should be a ResConfig object, representing the fully configured state of libres. The @controls argument configures which parameters the simulator should get when actually simulating. The @controls argument should be a dictionary like this: controls = {"cmode": ["Well","Group"], "order" : ["W1", "W2", "W3"]} In this example the simulator will expect two arrays 'cmode' and 'order', consisting of two and three elements respectively. When actually simualating these values will be written to json files looking like: cmode.json = {"Well" : 1.0, "Group" : 2.0} order.json = {"W1" : 1, "W2" : 1.0, "W3": 1.0} When later invoking the start() method the simulator expects to get values for all parameters configured with the @controls argument, otherwise an exception will be raised. Internally in libres code the controls will be implemented as 'ext_param' instances. The @results argument is a list of keys of results which the simulator expects to be generated by the forward model. If argument @results looks like: results = ["CMODE", "order"] The simulator will look for the files 'CMODE_0' and 'order_0' in the simulation folder. If those files are not produced by the simulator an exception will be raised. """ if not isinstance(res_config, ResConfig): raise ValueError( "The first argument must be valid ResConfig instance") self.res_config = res_config self.ert = EnKFMain(self.res_config) self.control_keys = [] self.result_keys = [] ens_config = self.res_config.ensemble_config for key in controls.keys(): ens_config.addNode( EnkfConfigNode.create_ext_param(key, controls[key])) self.control_keys.append(key) for key in results: ens_config.addNode( EnkfConfigNode.create_gen_data(key, "{}_%d".format(key))) self.result_keys.append(key)
def __init__(self, res_config, controls, results, callback=None): """Will create simulator which can be used to run multiple simulations. The @res_config argument should be a ResConfig object, representing the fully configured state of libres. The @controls argument configures which parameters the simulator should get when actually simulating. The @controls argument should be a dictionary like this : controls = { "cmode": ["Well", "Group"], "order": "W" : ["01", "02", "03"] } In this example, the first group of controls "cmode" includes two controls, called "Well" and "Group". The second group of controls "order" has one control "W" with three suffixes. Note that: - Either no variable in a group has suffixes or all the variables in the group have suffixes. - Suffixes must be specified as non-empty collections of strings. - No duplicate groups/controls/suffixes are allowed When actually simulating, these values will be written to json files looking like this: cmode.json = {"Well": 1.0, "Group": 2.0} order.json = { "W": "01": 0.3, "02": 1.0, "03": 4.2 } When later invoking the start() method the simulator expects to get values for all parameters configured with the @controls argument, otherwise an exception will be raised. Internally in libres code the controls will be implemented as 'ext_param' instances. The @results argument is a list of keys of results which the simulator expects to be generated by the forward model. If argument @results looks like: results = ["CMODE", "order"] The simulator will look for the files 'CMODE_0' and 'order_0' in the simulation folder. If those files are not produced by the simulator an exception will be raised. The optional argument callback can be used to provide a callable which will be called as: callback(run_context) When the simulator has started. For the callable passed as callback you are encouraged to use the future proof signature: def callback(*args, **kwargs): .... """ if not isinstance(res_config, ResConfig): raise ValueError( "The first argument must be valid ResConfig instance") self.res_config = res_config self.ert = EnKFMain(self.res_config) self.control_keys = set(controls.keys()) self.result_keys = set(results) self.callback = callback ens_config = self.res_config.ensemble_config for control_name, variables in controls.items(): ens_config.addNode( EnkfConfigNode.create_ext_param(control_name, variables)) for key in results: ens_config.addNode( EnkfConfigNode.create_gen_data(key, "{}_%d".format(key)))
def test_run(self): ens_size = 2 config_file = self.createTestPath( "local/config/simulation_batch/config.ert") with ErtTestContext("simulation_batch", model_config=config_file) as ctx: ert = ctx.getErt() ens_config = ert.ensembleConfig() # Observe that a significant amount of hardcoding # regarding the GEN_DATA and EXT_PARAM nodes is assumed # between this test, the config file and the forward model. # Add control nodes order_control = EnkfConfigNode.create_ext_param( "WELL_ORDER", ["W1", "W2", "W3"]) injection_control = EnkfConfigNode.create_ext_param( "WELL_INJECTION", ["W1", "W4"]) ens_config.addNode(order_control) ens_config.addNode(injection_control) # Add result nodes order_result = EnkfConfigNode.create_gen_data("ORDER", "order_%d") injection_result = EnkfConfigNode.create_gen_data( "INJECTION", "injection_%d") ens_config.addNode(order_result) ens_config.addNode(injection_result) order_node = EnkfNode(order_control) order_node_ext = order_node.as_ext_param() injection_node = EnkfNode(injection_control) injection_node_ext = injection_node.as_ext_param() fs_manager = ert.getEnkfFsManager() sim_fs = fs_manager.getFileSystem("sim_fs") state_map = sim_fs.getStateMap() batch_size = ens_size + 2 for iens in range(batch_size): node_id = NodeId(0, iens) order_node_ext["W1"] = iens order_node_ext["W2"] = iens * 10 order_node_ext["W3"] = iens * 100 order_node.save(sim_fs, node_id) injection_node_ext["W1"] = iens + 1 injection_node_ext["W4"] = 3 * (iens + 1) injection_node.save(sim_fs, node_id) state_map[iens] = RealizationStateEnum.STATE_INITIALIZED mask = BoolVector(default_value=True, initial_size=batch_size) model_config = ert.getModelConfig() runpath_fmt = model_config.getRunpathFormat() jobname_fmt = model_config.getJobnameFormat() subst_list = ert.getDataKW() itr = 0 run_context = ErtRunContext.ensemble_experiment( sim_fs, mask, runpath_fmt, jobname_fmt, subst_list, itr) ert.getEnkfSimulationRunner().createRunPath(run_context) job_queue = ert.get_queue_config().create_job_queue() ert.createRunpath(run_context) num = ert.getEnkfSimulationRunner().runEnsembleExperiment( job_queue, run_context) self.assertEqual(num, batch_size) order_result = EnkfNode(ens_config["ORDER"]) injection_result = EnkfNode(ens_config["INJECTION"]) for iens in range(batch_size): node_id = NodeId(0, iens) order_result.load(sim_fs, node_id) data = order_result.asGenData() order_node.load(sim_fs, node_id) self.assertEqual(order_node_ext["W1"], data[0]) self.assertEqual(order_node_ext["W2"], data[1]) self.assertEqual(order_node_ext["W3"], data[2])