Skip to content

Commit

Permalink
Remove IES
Browse files Browse the repository at this point in the history
  • Loading branch information
sondreso committed Jan 22, 2025
1 parent 2839ae7 commit b7f37e7
Show file tree
Hide file tree
Showing 20 changed files with 36 additions and 980 deletions.
9 changes: 0 additions & 9 deletions docs/ert/reference/running_ert.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,6 @@ Ensemble Smoother
:prog: ert
:path: ensemble_smoother

Iterative Ensemble Smoother
~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. argparse::
:module: ert.__main__
:func: get_ert_parser
:prog: ert
:path: iterative_ensemble_smoother

ES MDA
~~~~~~

Expand Down
5 changes: 0 additions & 5 deletions docs/ert/theory/ensemble_based_methods.rst
Original file line number Diff line number Diff line change
Expand Up @@ -384,11 +384,6 @@ In plain English, the ES MDA consists of several consecutive smoother updates wi
error bars. The ES MDA with one iteration is identical to the Ensemble smoother.


Iterative ensemble smoother - Ensemble subspace version
-------------------------------------------------------

The algorithm implemented is described in the article `Efficient Implementation of an Iterative Ensemble Smoother for Data Assimilation and Reservoir History Matching <https://www.frontiersin.org/articles/10.3389/fams.2019.00047/full>`_.

Kalman posterior properties
---------------------------

Expand Down
69 changes: 0 additions & 69 deletions src/ert/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
ENSEMBLE_EXPERIMENT_MODE,
ENSEMBLE_SMOOTHER_MODE,
ES_MDA_MODE,
ITERATIVE_ENSEMBLE_SMOOTHER_MODE,
TEST_RUN_MODE,
WORKFLOW_MODE,
)
Expand Down Expand Up @@ -421,73 +420,6 @@ def get_ert_parser(parser: ArgumentParser | None = None) -> ArgumentParser:
help="Name of the experiment",
)

# iterative_ensemble_smoother_parser
iterative_ensemble_smoother_description = (
"Run experiments in cli while performing updates"
" on the parameters using the iterative ensemble smoother algorithm."
)
iterative_ensemble_smoother_parser = subparsers.add_parser(
ITERATIVE_ENSEMBLE_SMOOTHER_MODE,
description=iterative_ensemble_smoother_description,
help=iterative_ensemble_smoother_description,
)
iterative_ensemble_smoother_parser.add_argument(
"--current-case",
type=valid_name,
default="default",
action=DeprecatedAction,
alternative_option="--current-ensemble",
dest="current_ensemble",
help="Deprecated: This argument is deprecated and will be "
"removed in future versions. Use --current-ensemble instead.",
)
iterative_ensemble_smoother_parser.add_argument(
"--current-ensemble",
type=valid_name,
default="default",
help="Name of the ensemble where the results for the experiment "
"using the prior parameters will be stored.",
)
iterative_ensemble_smoother_parser.add_argument(
"--target-case",
type=valid_name_format,
default="iter-%d",
action=DeprecatedAction,
dest="target_ensemble",
alternative_option="--target--ensemble",
help="Deprecated: This argument is deprecated and will be "
"removed in future versions. Use --target-ensemble instead.",
)
iterative_ensemble_smoother_parser.add_argument(
"--target-ensemble",
type=valid_name_format,
default="iter-%d",
help="The iterative ensemble smoother creates multiple ensembles for the different "
"iterations. The ensemble names will follow the specified format. "
"For example, 'Target ensemble format: iter_%%d' will generate "
"ensembles with the names iter_0, iter_1, iter_2, iter_3, ....",
)
iterative_ensemble_smoother_parser.add_argument(
"--realizations",
type=valid_realizations,
help="These are the realizations that will be used to perform experiments."
"For example, if 'Number of realizations:50 and active realizations are 0-9', "
"then only realizations 0,1,2,3,...,9 will be used to perform experiments "
"while realizations 10,11, 12,...,49 will be excluded.",
)
iterative_ensemble_smoother_parser.add_argument(
"--num-iterations",
type=valid_num_iterations,
required=False,
help="The number of iterations to run.",
)
iterative_ensemble_smoother_parser.add_argument(
"--experiment-name",
type=str,
default="ies",
help="Name of the experiment",
)

# es_mda_parser
es_mda_description = f"Run '{ES_MDA_MODE}' in cli"
es_mda_parser = subparsers.add_parser(
Expand Down Expand Up @@ -574,7 +506,6 @@ def get_ert_parser(parser: ArgumentParser | None = None) -> ArgumentParser:
test_run_parser,
ensemble_experiment_parser,
ensemble_smoother_parser,
iterative_ensemble_smoother_parser,
es_mda_parser,
workflow_parser,
]:
Expand Down
2 changes: 0 additions & 2 deletions src/ert/analysis/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from ._es_update import (
ErtAnalysisError,
iterative_smoother_update,
smoother_update,
)
from .event import (
Expand All @@ -26,6 +25,5 @@
"ObservationAndResponseSnapshot",
"ObservationStatus",
"SmootherSnapshot",
"iterative_smoother_update",
"smoother_update",
]
189 changes: 1 addition & 188 deletions src/ert/analysis/_es_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from ert.config import GenKwConfig

from ..config.analysis_config import ObservationGroups, UpdateSettings
from ..config.analysis_module import BaseSettings, ESSettings, IESSettings
from ..config.analysis_module import BaseSettings, ESSettings
from . import misfit_preprocessor
from .event import (
AnalysisCompleteEvent,
Expand Down Expand Up @@ -629,123 +629,6 @@ def correlation_callback(
)


def analysis_IES(
parameters: Iterable[str],
observations: Iterable[str],
rng: np.random.Generator,
analysis_config: IESSettings,
alpha: float,
std_cutoff: float,
smoother_snapshot: SmootherSnapshot,
ens_mask: npt.NDArray[np.bool_],
source_ensemble: Ensemble,
target_ensemble: Ensemble,
sies_smoother: ies.SIES | None,
progress_callback: Callable[[AnalysisEvent], None],
auto_scale_observations: list[ObservationGroups],
sies_step_length: Callable[[int], float],
initial_mask: npt.NDArray[np.bool_],
) -> ies.SIES:
iens_active_index = np.flatnonzero(ens_mask)
# Pick out realizations that were among the initials that are still living
# Example: initial_mask=[1,1,1,0,1], ens_mask=[0,1,1,0,1]
# Then the result is [0,1,1,1]
# This is needed for the SIES library
masking_of_initial_parameters = ens_mask[initial_mask]

progress_callback(AnalysisStatusEvent(msg="Loading observations and responses.."))

(
S,
(
observation_values,
observation_errors,
update_snapshot,
),
) = _load_observations_and_responses(
source_ensemble,
alpha,
std_cutoff,
1.0,
iens_active_index,
observations,
auto_scale_observations,
progress_callback,
)

smoother_snapshot.update_step_snapshots = update_snapshot
if len(observation_values) == 0:
msg = "No active observations for update step"
progress_callback(
AnalysisErrorEvent(
error_msg=msg,
data=DataSection(
header=smoother_snapshot.header,
data=smoother_snapshot.csv,
extra=smoother_snapshot.extra,
),
)
)
raise ErtAnalysisError(msg)

# if the algorithm object is not passed, initialize it
if sies_smoother is None:
# The sies smoother must be initialized with the full parameter ensemble
# Get relevant active realizations
parameter_ensemble_active = _all_parameters(source_ensemble, iens_active_index)
sies_smoother = ies.SIES(
parameters=parameter_ensemble_active,
covariance=observation_errors**2,
observations=observation_values,
seed=rng,
inversion=analysis_config.inversion,
truncation=analysis_config.enkf_truncation,
)

# Keep track of iterations to calculate step-lengths
sies_smoother.iteration = 1

# Calculate step-lengths to scale SIES iteration
step_length = sies_step_length(sies_smoother.iteration)

# Propose a transition matrix using only active realizations
proposed_W = sies_smoother.propose_W_masked(
S, ensemble_mask=masking_of_initial_parameters, step_length=step_length
)

# Store transition matrix for later use on sies object
sies_smoother.W[:, masking_of_initial_parameters] = proposed_W

for param_group in parameters:
param_ensemble_array = _load_param_ensemble_array(
source_ensemble, param_group, iens_active_index
)
param_ensemble_array += (
param_ensemble_array @ sies_smoother.W / np.sqrt(len(iens_active_index) - 1)
)

progress_callback(AnalysisStatusEvent(msg=f"Storing data for {param_group}.."))
_save_param_ensemble_array_to_disk(
target_ensemble, param_ensemble_array, param_group, iens_active_index
)

_copy_unupdated_parameters(
list(source_ensemble.experiment.parameter_configuration.keys()),
parameters,
iens_active_index,
source_ensemble,
target_ensemble,
)

assert sies_smoother is not None, "sies_smoother should be initialized"

# Increment the iteration number
sies_smoother.iteration += 1

# Return the sies smoother so it may be iterated over
return sies_smoother


def _create_smoother_snapshot(
prior_name: str,
posterior_name: str,
Expand Down Expand Up @@ -827,73 +710,3 @@ def smoother_update(
)
)
return smoother_snapshot


def iterative_smoother_update(
prior_storage: Ensemble,
posterior_storage: Ensemble,
sies_smoother: ies.SIES | None,
parameters: Iterable[str],
observations: Iterable[str],
update_settings: UpdateSettings,
analysis_config: IESSettings,
sies_step_length: Callable[[int], float],
initial_mask: npt.NDArray[np.bool_],
rng: np.random.Generator | None = None,
progress_callback: Callable[[AnalysisEvent], None] | None = None,
global_scaling: float = 1.0,
) -> tuple[SmootherSnapshot, ies.SIES]:
if not progress_callback:
progress_callback = noop_progress_callback
if rng is None:
rng = np.random.default_rng()

ens_mask = prior_storage.get_realization_mask_with_responses()

smoother_snapshot = _create_smoother_snapshot(
prior_storage.name,
posterior_storage.name,
update_settings,
global_scaling,
)

try:
sies_smoother = analysis_IES(
parameters=parameters,
observations=observations,
rng=rng,
analysis_config=analysis_config,
alpha=update_settings.alpha,
std_cutoff=update_settings.std_cutoff,
smoother_snapshot=smoother_snapshot,
ens_mask=ens_mask,
source_ensemble=prior_storage,
target_ensemble=posterior_storage,
sies_smoother=sies_smoother,
progress_callback=progress_callback,
auto_scale_observations=update_settings.auto_scale_observations,
sies_step_length=sies_step_length,
initial_mask=initial_mask,
)
except Exception as e:
progress_callback(
AnalysisErrorEvent(
error_msg=str(e),
data=DataSection(
header=smoother_snapshot.header,
data=smoother_snapshot.csv,
extra=smoother_snapshot.extra,
),
)
)
raise e
progress_callback(
AnalysisCompleteEvent(
data=DataSection(
header=smoother_snapshot.header,
data=smoother_snapshot.csv,
extra=smoother_snapshot.extra,
)
)
)
return smoother_snapshot, sies_smoother
2 changes: 0 additions & 2 deletions src/ert/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
ENSEMBLE_EXPERIMENT_MODE,
ENSEMBLE_SMOOTHER_MODE,
ES_MDA_MODE,
ITERATIVE_ENSEMBLE_SMOOTHER_MODE,
TEST_RUN_MODE,
WORKFLOW_MODE,
)
Expand Down Expand Up @@ -68,7 +67,6 @@ def run_cli(args: Namespace, plugin_manager: ErtPluginManager | None = None) ->
if args.mode in {
ENSEMBLE_SMOOTHER_MODE,
ES_MDA_MODE,
ITERATIVE_ENSEMBLE_SMOOTHER_MODE,
}:
if not ert_config.ensemble_config.parameter_configs:
raise ErtCliError(
Expand Down
1 change: 0 additions & 1 deletion src/ert/config/parsing/analysis_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@


class AnalysisMode(StrEnum):
ITERATED_ENSEMBLE_SMOOTHER = "IES_ENKF"
ENSEMBLE_SMOOTHER = "STD_ENKF"
7 changes: 0 additions & 7 deletions src/ert/gui/simulation/experiment_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
from .ensemble_smoother_panel import EnsembleSmootherPanel
from .evaluate_ensemble_panel import EvaluateEnsemblePanel
from .experiment_config_panel import ExperimentConfigPanel
from .iterated_ensemble_smoother_panel import IteratedEnsembleSmootherPanel
from .manual_update_panel import ManualUpdatePanel
from .multiple_data_assimilation_panel import MultipleDataAssimilationPanel
from .run_dialog import RunDialog
Expand Down Expand Up @@ -168,12 +167,6 @@ def __init__(
EnsembleSmootherPanel(analysis_config, run_path, notifier, ensemble_size),
experiment_type_valid,
)
self.addExperimentConfigPanel(
IteratedEnsembleSmootherPanel(
analysis_config, run_path, notifier, ensemble_size
),
experiment_type_valid,
)
self.addExperimentConfigPanel(
ManualUpdatePanel(ensemble_size, run_path, notifier, analysis_config),
experiment_type_valid,
Expand Down
Loading

0 comments on commit b7f37e7

Please sign in to comment.