Ejemplo n.º 1
0
def test_post_update_data(client):
    data = pd.DataFrame(np.random.rand(4, 2), index=[2, 4, 6, 8])

    builder = ErtConfigBuilder()
    builder.add_general_observation("OBS", "RES", data)
    ert = builder.build()

    # Post two ensembles
    parent_ensemble_id = extraction.post_ensemble_data(ert,
                                                       builder.ensemble_size)
    update_id = extraction.post_update_data(ert, parent_ensemble_id, "boruvka")
    child_ensemble_id = extraction.post_ensemble_data(ert,
                                                      builder.ensemble_size,
                                                      update_id)

    # Experiment should have two ensembles
    experiment_id = client.fetch_experiment()
    ensembles = client.get(f"/experiments/{experiment_id}/ensembles").json()
    assert len(ensembles) == 2

    # Parent ensemble should have a child
    assert ensembles[0]["child_ensemble_ids"] == [child_ensemble_id]
    assert ensembles[0]["parent_ensemble_id"] is None

    # Child ensemble should have a parent
    assert ensembles[1]["child_ensemble_ids"] == []
    assert ensembles[1]["parent_ensemble_id"] == parent_ensemble_id
Ejemplo n.º 2
0
def test_observation_transformation(client):
    data = pd.DataFrame([[1, 0.1], [2, 0.2], [3, 0.3], [4, 0.4]],
                        index=[0, 1, 2, 3])

    builder = ErtConfigBuilder()
    builder.ensemble_size = 5
    builder.add_general_observation("OBS", "RES", data)
    builder.job_script = dedent("""\
    #!/usr/bin/python3
    import re
    from pathlib import Path

    # Obtain realization index by looking at the name of current directory
    real = int(re.match("^realization([0-9]+)$", Path.cwd().name)[1])

    outlier   = 1000 + real  # Large number, ERT disables
    active_a  = 1 + real
    active_b  = 2 + real
    small_var = 3  # Small variation between responses, ERT disables

    output = [outlier, active_a, active_b, small_var]
    with open("poly_0.out", "w") as f:
        f.write("\\n".join(str(x) for x in output))
    """)
    ert = builder.build()

    # Post first ensemble
    parent_ensemble_id = extraction.post_ensemble_data(ert,
                                                       builder.ensemble_size)

    # Create runpath and run ERT
    run_context = _create_runpath(ert)
    _evaluate_ensemble(ert, run_context)
    _run_update(ert, run_context)

    # Post second ensemble
    update_id = extraction.post_update_data(ert, parent_ensemble_id, "boruvka")
    child_ensemble_id = extraction.post_ensemble_data(ert,
                                                      builder.ensemble_size,
                                                      update_id)

    # Ensemble should have 1 observation with transformation
    observations = client.get(
        f"/ensembles/{child_ensemble_id}/observations").json()
    assert len(observations) == 1

    # Validate data
    obs = observations[0]
    assert obs["name"] == "OBS"
    assert obs["values"] == data[0].tolist()
    assert obs["errors"] == data[1].tolist()

    trans = obs["transformation"]
    assert trans["name"] == "OBS"
    assert trans["active"] == [False, True, True, False]
    assert trans["scale"] == [1.0] * 4
    assert trans["observation_id"] == obs["id"]
Ejemplo n.º 3
0
def test_parameters(client):
    priors = _make_priors()

    # Add priors to ERT config
    builder = ErtConfigBuilder()
    builder.ensemble_size = 10
    for name, conf, _ in priors:
        builder.add_prior(name, conf)
    ert = builder.build()

    # Start ERT
    _create_runpath(ert)

    # Post initial ensemble
    extraction.post_ensemble_data(ert, -1)

    # Get ensemble_id
    experiment_id = client.fetch_experiment()
    ensembles = client.get(f"/experiments/{experiment_id}/ensembles").json()
    ensemble_id = ensembles[0]["id"]

    # Compare parameters (+ 2 due to the two log10_ coeffs)
    parameters = client.get(f"/ensembles/{ensemble_id}/parameters").json()
    parameter_names = [entry["name"] for entry in parameters]
    assert len(parameters) == len(parameter_names)
    assert len(parameters) == len(priors) + 2
    for name, _, prior in priors:
        assert f"COEFFS:{name}" in parameter_names
        if prior["function"] in ("lognormal", "loguniform"):
            assert f"LOG10_COEFFS:{name}" in parameter_names

    # Compare records (+ 2 due to the two log10_ coeffs)
    records = client.get(f"/ensembles/{ensemble_id}/records").json()
    assert len(records) == len(priors) + 2
    for name, _, prior in priors:
        assert f"COEFFS:{name}" in records
        if prior["function"] in ("lognormal", "loguniform"):
            assert f"LOG10_COEFFS:{name}" in records

    parameters_df = _get_parameters()
    assert len(parameters_df) == builder.ensemble_size
    for col in parameters_df:
        record_data = client.get(
            f"/ensembles/{ensemble_id}/records/COEFFS:{col}",
            headers={
                "accept": "application/x-parquet"
            },
        ).content
        stream = io.BytesIO(record_data)
        df = pd.read_parquet(stream)

        # ERT produces a low-quality version
        assert_almost_equal(parameters_df[col].values,
                            df.values.flatten(),
                            decimal=4)
Ejemplo n.º 4
0
def test_empty_ensemble(client):
    ert = ErtConfigBuilder().build()
    extraction.post_ensemble_data(ert, -1)

    id = client.fetch_experiment()

    # Name is "default"
    for ens in client.get(f"/experiments/{id}/ensembles").json():
        assert (client.get(f"/ensembles/{ens['id']}/userdata").json()["name"]
                == "default")

    # No priors exist
    assert client.get(f"/experiments/{id}").json()["priors"] == {}
Ejemplo n.º 5
0
def test_empty_ensemble_with_name(client):
    name = _rand_name()

    # Create case with given name
    ert = ErtConfigBuilder().build()
    ert.select_or_create_new_case(name)

    # Post initial ensemble
    extraction.post_ensemble_data(ert, -1)

    # Compare results
    id = client.fetch_experiment()
    for ens in client.get(f"/experiments/{id}/ensembles").json():
        assert client.get(f"/ensembles/{ens['id']}/userdata").json()["name"] == name
Ejemplo n.º 6
0
    def _runAndPostProcess(self, run_context, arguments, update_id=None):
        phase_msg = "Running iteration %d of %d simulation iterations..." % (
            run_context.get_iter(),
            self.phaseCount() - 1,
        )
        self.setPhase(run_context.get_iter(), phase_msg, indeterminate=False)

        self.setPhaseName("Pre processing...", indeterminate=True)
        self.ert().getEnkfSimulationRunner().createRunPath(run_context)
        EnkfSimulationRunner.runWorkflows(HookRuntime.PRE_SIMULATION,
                                          ert=ERT.ert)
        # create ensemble
        ensemble_id = post_ensemble_data(update_id=update_id)
        self.setPhaseName("Running forecast...", indeterminate=False)
        if FeatureToggling.is_enabled("ensemble-evaluator"):
            ee_config = arguments["ee_config"]
            num_successful_realizations = self.run_ensemble_evaluator(
                run_context, ee_config)
        else:
            self._job_queue = self._queue_config.create_job_queue()
            num_successful_realizations = (
                self.ert().getEnkfSimulationRunner().runSimpleStep(
                    self._job_queue, run_context))

        self.checkHaveSufficientRealizations(num_successful_realizations)

        self.setPhaseName("Post processing...", indeterminate=True)
        EnkfSimulationRunner.runWorkflows(HookRuntime.POST_SIMULATION,
                                          ert=ERT.ert)
        post_ensemble_results(ensemble_id)
        return ensemble_id
Ejemplo n.º 7
0
 def _post_ensemble_data(self, update_id: Optional[str] = None) -> str:
     self.setPhaseName("Uploading data...")
     ensemble_id = post_ensemble_data(ert=ERT.enkf_facade,
                                      ensemble_size=self._ensemble_size,
                                      update_id=update_id)
     self.setPhaseName("Uploading done")
     return ensemble_id
Ejemplo n.º 8
0
 def _post_ensemble_data(self, update_id: Optional[str] = None) -> str:
     self.setPhaseName("Uploading data...")
     ensemble_id = post_ensemble_data(
         ert=self.facade,
         ensemble_size=self._ensemble_size,
         update_id=update_id,
         active_realizations=self._active_realizations,
     )
     self.setPhaseName("Uploading done")
     return ensemble_id
Ejemplo n.º 9
0
def test_priors(client):
    priors = _make_priors()

    # Add priors to ERT config
    builder = ErtConfigBuilder()
    for name, conf, _ in priors:
        builder.add_prior(name, conf)
    ert = builder.build()

    # Start ERT
    _create_runpath(ert)

    # Post initial ensemble
    extraction.post_ensemble_data(ert, -1)

    # Compare results
    id = client.fetch_experiment()
    actual_priors = client.get(f"/experiments/{id}").json()["priors"]
    assert len(priors) == len(actual_priors)
    for name, _, resp in priors:
        assert actual_priors[f"COEFFS:{name}"] == resp
Ejemplo n.º 10
0
def test_observations(client):
    data = pd.DataFrame([[1, 0.1], [2, 0.2], [3, 0.3], [4, 0.4]], index=[2, 4, 6, 8])

    builder = ErtConfigBuilder()
    builder.add_general_observation("OBS", "RES", data)
    ert = builder.build()

    # Post ensemble
    extraction.post_ensemble_data(ert, builder.ensemble_size)

    # Experiment should have 1 observation
    experiment_id = client.fetch_experiment()
    observations = client.get(f"/experiments/{experiment_id}/observations").json()
    assert len(observations) == 1

    # Validate data
    obs = observations[0]
    assert obs["name"] == "OBS"
    assert obs["values"] == data[0].tolist()
    assert obs["errors"] == data[1].tolist()
    assert obs["x_axis"] == data.index.astype(str).tolist()
    assert obs["transformation"] is None
Ejemplo n.º 11
0
def test_post_ensemble_results(client):
    data = pd.DataFrame([[1, 0.1], [2, 0.2], [3, 0.3], [4, 0.4]],
                        index=[2, 4, 6, 8])
    response_name = "RES"

    # Add priors to ERT config
    builder = ErtConfigBuilder()
    builder.ensemble_size = 2
    builder.add_general_observation("OBS", response_name, data)

    data = [0.0, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9]
    df = pd.DataFrame(data)

    # Create job
    script = dedent(f"""\
    #!/usr/bin/python3

    if __name__ == "__main__":
        output = {str(data)}
        with open("poly_0.out", "w") as f:
            f.write("\\n".join(map(str, output)))
    """)
    builder.job_script = script

    ert = builder.build()

    # Create runpath and run ERT
    run_context = _create_runpath(ert)
    _evaluate_ensemble(ert, run_context)

    # Post initial ensemble
    ensemble_id = extraction.post_ensemble_data(ert, builder.ensemble_size)

    # Post ensemble results
    extraction.post_ensemble_results(ert, ensemble_id)

    # Retrieve response data
    data = client.get(
        f"/ensembles/{ensemble_id}/responses/{response_name}/data")
    stream = io.BytesIO(data.content)
    response_df = pd.read_csv(stream,
                              index_col=0,
                              float_precision="round_trip")
    for realization in range(0, builder.ensemble_size):
        assert_array_equal(response_df.loc[realization].values,
                           df.values.flatten())
Ejemplo n.º 12
0
    def _simulateAndPostProcess(self,
                                run_context,
                                arguments,
                                update_id: int = None):
        iteration = run_context.get_iter()

        phase_string = "Running simulation for iteration: %d" % iteration
        self.setPhaseName(phase_string, indeterminate=True)
        self.ert().getEnkfSimulationRunner().createRunPath(run_context)

        phase_string = "Pre processing for iteration: %d" % iteration
        self.setPhaseName(phase_string)
        EnkfSimulationRunner.runWorkflows(HookRuntime.PRE_SIMULATION,
                                          ert=ERT.ert)

        # Push ensemble, parameters, observations to new storage
        new_ensemble_id = post_ensemble_data(update_id=update_id,
                                             ensemble_size=self._ensemble_size)

        phase_string = "Running forecast for iteration: %d" % iteration
        self.setPhaseName(phase_string, indeterminate=False)

        if FeatureToggling.is_enabled("ensemble-evaluator"):
            ee_config = arguments["ee_config"]
            num_successful_realizations = self.run_ensemble_evaluator(
                run_context, ee_config)
        else:
            self._job_queue = self._queue_config.create_job_queue()
            num_successful_realizations = (
                self.ert().getEnkfSimulationRunner().runSimpleStep(
                    self._job_queue, run_context))

        # Push simulation results to storage
        post_ensemble_results(new_ensemble_id)

        num_successful_realizations += arguments.get(
            "prev_successful_realizations", 0)
        self.checkHaveSufficientRealizations(num_successful_realizations)

        phase_string = "Post processing for iteration: %d" % iteration
        self.setPhaseName(phase_string, indeterminate=True)
        EnkfSimulationRunner.runWorkflows(HookRuntime.POST_SIMULATION,
                                          ert=ERT.ert)

        return num_successful_realizations, new_ensemble_id
Ejemplo n.º 13
0
    def runSimulations__(self, arguments, run_msg):

        run_context = self.create_context(arguments)

        self.setPhase(0, "Running simulations...", indeterminate=False)

        self.setPhaseName("Pre processing...", indeterminate=True)
        self.ert().getEnkfSimulationRunner().createRunPath(run_context)

        # Push ensemble, parameters, observations to new storage
        ensemble_id = post_ensemble_data(ensemble_size=self._ensemble_size)
        EnkfSimulationRunner.runWorkflows(HookRuntime.PRE_SIMULATION, ERT.ert)

        self.setPhaseName(run_msg, indeterminate=False)

        if FeatureToggling.is_enabled("ensemble-evaluator"):
            ee_config = arguments["ee_config"]
            num_successful_realizations = self.run_ensemble_evaluator(
                run_context, ee_config
            )
        else:
            self._job_queue = self._queue_config.create_job_queue()
            num_successful_realizations = (
                self.ert()
                .getEnkfSimulationRunner()
                .runEnsembleExperiment(self._job_queue, run_context)
            )

        num_successful_realizations += arguments.get("prev_successful_realizations", 0)
        self.checkHaveSufficientRealizations(num_successful_realizations)

        self.setPhaseName("Post processing...", indeterminate=True)
        EnkfSimulationRunner.runWorkflows(HookRuntime.POST_SIMULATION, ERT.ert)
        self.setPhase(1, "Simulations completed.")  # done...

        # Push simulation results to storage
        post_ensemble_results(ensemble_id)

        return run_context
Ejemplo n.º 14
0
    def runSimulations(self, arguments):
        prior_context = self.create_context(arguments)

        self.checkMinimumActiveRealizations(prior_context)
        self.setPhase(0, "Running simulations...", indeterminate=False)

        # self.setAnalysisModule(arguments["analysis_module"])

        self.setPhaseName("Pre processing...", indeterminate=True)
        self.ert().getEnkfSimulationRunner().createRunPath(prior_context)

        # Push ensemble, parameters, observations to new storage
        ensemble_id = post_ensemble_data()

        EnkfSimulationRunner.runWorkflows(HookRuntime.PRE_SIMULATION,
                                          ert=ERT.ert)

        self.setPhaseName("Running forecast...", indeterminate=False)

        if FeatureToggling.is_enabled("ensemble-evaluator"):
            ee_config = arguments["ee_config"]
            num_successful_realizations = self.run_ensemble_evaluator(
                prior_context, ee_config)
        else:
            self._job_queue = self._queue_config.create_job_queue()
            num_successful_realizations = self.ert().getEnkfSimulationRunner(
            ).runSimpleStep(self._job_queue, prior_context)

        self.checkHaveSufficientRealizations(num_successful_realizations)

        self.setPhaseName("Post processing...", indeterminate=True)
        EnkfSimulationRunner.runWorkflows(HookRuntime.POST_SIMULATION,
                                          ert=ERT.ert)

        self.setPhaseName("Analyzing...")
        EnkfSimulationRunner.runWorkflows(HookRuntime.PRE_FIRST_UPDATE,
                                          ert=ERT.ert)
        EnkfSimulationRunner.runWorkflows(HookRuntime.PRE_UPDATE, ert=ERT.ert)
        es_update = self.ert().getESUpdate()
        success = es_update.smootherUpdate(prior_context)
        if not success:
            raise ErtRunError("Analysis of simulation failed!")
        EnkfSimulationRunner.runWorkflows(HookRuntime.POST_UPDATE, ert=ERT.ert)

        # Push simulation results to storage
        post_ensemble_results(ensemble_id)

        self.setPhase(1, "Running simulations...")
        self.ert().getEnkfFsManager().switchFileSystem(
            prior_context.get_target_fs())

        self.setPhaseName("Pre processing...")

        rerun_context = self.create_context(arguments,
                                            prior_context=prior_context)

        self.ert().getEnkfSimulationRunner().createRunPath(rerun_context)

        # Push ensemble, parameters, observations to new storage
        analysis_module_name = self.ert().analysisConfig().activeModuleName()
        ensemble_id = post_ensemble_data((ensemble_id, analysis_module_name))

        EnkfSimulationRunner.runWorkflows(HookRuntime.PRE_SIMULATION,
                                          ert=ERT.ert)

        self.setPhaseName("Running forecast...", indeterminate=False)

        if FeatureToggling.is_enabled("ensemble-evaluator"):
            ee_config = arguments["ee_config"]
            num_successful_realizations = self.run_ensemble_evaluator(
                rerun_context, ee_config)
        else:
            self._job_queue = self._queue_config.create_job_queue()
            num_successful_realizations = self.ert().getEnkfSimulationRunner(
            ).runSimpleStep(self._job_queue, rerun_context)

        self.checkHaveSufficientRealizations(num_successful_realizations)

        self.setPhaseName("Post processing...", indeterminate=True)
        EnkfSimulationRunner.runWorkflows(HookRuntime.POST_SIMULATION,
                                          ert=ERT.ert)

        self.setPhase(2, "Simulations completed.")

        # Push simulation results to storage
        post_ensemble_results(ensemble_id)

        return prior_context
Ejemplo n.º 15
0
    def runSimulations(self, arguments):
        phase_count = ERT.enkf_facade.get_number_of_iterations() + 1
        self.setPhaseCount(phase_count)

        analysis_module = self.setAnalysisModule(arguments["analysis_module"])
        target_case_format = arguments["target_case"]
        run_context = self.create_context(arguments, 0)

        self.ert().analysisConfig().getAnalysisIterConfig().setCaseFormat(
            target_case_format)

        self._runAndPostProcess(run_context, arguments)

        analysis_config = self.ert().analysisConfig()
        analysis_iter_config = analysis_config.getAnalysisIterConfig()
        num_retries_per_iteration = analysis_iter_config.getNumRetries()
        num_retries = 0
        current_iter = 0

        previous_ensemble_id = None
        while current_iter < ERT.enkf_facade.get_number_of_iterations(
        ) and num_retries < num_retries_per_iteration:
            pre_analysis_iter_num = analysis_module.getInt("ITER")
            # We run the PRE_FIRST_UPDATE hook here because the current_iter is explicitly available, versus
            # in the run_context inside analyzeStep
            if current_iter == 0:
                EnkfSimulationRunner.runWorkflows(HookRuntime.PRE_FIRST_UPDATE,
                                                  ert=ERT.ert)
            self.analyzeStep(run_context)
            current_iter = analysis_module.getInt("ITER")

            analysis_success = current_iter > pre_analysis_iter_num
            if analysis_success:
                # Push ensemble, parameters, observations to new storage
                analysis_module_name = self.ert().analysisConfig(
                ).activeModuleName()
                previous_ensemble_id = post_ensemble_data((
                    previous_ensemble_id, analysis_module_name
                ) if previous_ensemble_id is not None else None)
                post_ensemble_results(previous_ensemble_id)
                run_context = self.create_context(arguments,
                                                  current_iter,
                                                  prior_context=run_context)
                self._runAndPostProcess(run_context, arguments)
                num_retries = 0
            else:
                run_context = self.create_context(arguments,
                                                  current_iter,
                                                  prior_context=run_context,
                                                  rerun=True)
                self._runAndPostProcess(run_context, arguments)
                num_retries += 1

        analysis_module_name = self.ert().analysisConfig().activeModuleName()
        previous_ensemble_id = post_ensemble_data((
            previous_ensemble_id, analysis_module_name
        ) if previous_ensemble_id is not None else None)
        post_ensemble_results(previous_ensemble_id)

        if current_iter == (phase_count - 1):
            self.setPhase(phase_count, "Simulations completed.")
        else:
            raise ErtRunError(
                "Iterated Ensemble Smoother stopped: maximum number of iteration retries (%d retries) reached for iteration %d"
                % (num_retries_per_iteration, current_iter))

        return run_context