ert 16.0.9__py3-none-any.whl → 19.0.0rc2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- _ert/events.py +19 -2
- _ert/forward_model_runner/client.py +6 -2
- _ert/forward_model_runner/fm_dispatch.py +9 -6
- _ert/forward_model_runner/reporting/event.py +1 -0
- _ert/forward_model_runner/runner.py +1 -2
- _ert/utils.py +12 -0
- ert/__main__.py +58 -38
- ert/analysis/_enif_update.py +8 -4
- ert/analysis/_es_update.py +19 -6
- ert/analysis/_update_commons.py +16 -6
- ert/base_model_context.py +1 -1
- ert/cli/main.py +17 -12
- ert/cli/monitor.py +7 -0
- ert/config/__init__.py +17 -6
- ert/config/_create_observation_dataframes.py +118 -21
- ert/config/_get_num_cpu.py +1 -1
- ert/config/_observations.py +91 -2
- ert/config/_read_summary.py +74 -328
- ert/config/design_matrix.py +62 -23
- ert/config/distribution.py +1 -1
- ert/config/ensemble_config.py +9 -17
- ert/config/ert_config.py +155 -58
- ert/config/everest_control.py +234 -0
- ert/config/{everest_constraints_config.py → everest_response.py} +27 -15
- ert/config/field.py +99 -90
- ert/config/forward_model_step.py +122 -17
- ert/config/gen_data_config.py +5 -10
- ert/config/gen_kw_config.py +11 -41
- ert/config/known_response_types.py +14 -0
- ert/config/parameter_config.py +1 -33
- ert/config/parsing/_option_dict.py +10 -2
- ert/config/parsing/config_errors.py +1 -1
- ert/config/parsing/config_keywords.py +2 -1
- ert/config/parsing/config_schema.py +23 -11
- ert/config/parsing/config_schema_deprecations.py +3 -3
- ert/config/parsing/config_schema_item.py +26 -11
- ert/config/parsing/context_values.py +3 -3
- ert/config/parsing/file_context_token.py +1 -1
- ert/config/parsing/observations_parser.py +6 -2
- ert/config/parsing/queue_system.py +9 -0
- ert/config/parsing/schema_item_type.py +1 -0
- ert/config/queue_config.py +42 -50
- ert/config/response_config.py +0 -8
- ert/config/rft_config.py +275 -0
- ert/config/summary_config.py +3 -8
- ert/config/surface_config.py +73 -26
- ert/config/workflow_fixtures.py +2 -1
- ert/config/workflow_job.py +135 -54
- ert/dark_storage/client/__init__.py +2 -2
- ert/dark_storage/client/_session.py +4 -4
- ert/dark_storage/client/client.py +2 -2
- ert/dark_storage/common.py +12 -3
- ert/dark_storage/compute/misfits.py +11 -7
- ert/dark_storage/endpoints/compute/misfits.py +6 -4
- ert/dark_storage/endpoints/ensembles.py +4 -0
- ert/dark_storage/endpoints/experiment_server.py +30 -24
- ert/dark_storage/endpoints/experiments.py +2 -2
- ert/dark_storage/endpoints/observations.py +8 -6
- ert/dark_storage/endpoints/parameters.py +4 -12
- ert/dark_storage/endpoints/responses.py +24 -5
- ert/dark_storage/json_schema/ensemble.py +3 -0
- ert/dark_storage/json_schema/experiment.py +1 -1
- ert/data/_measured_data.py +6 -5
- ert/ensemble_evaluator/__init__.py +8 -1
- ert/ensemble_evaluator/config.py +2 -1
- ert/ensemble_evaluator/evaluator.py +81 -29
- ert/ensemble_evaluator/event.py +6 -0
- ert/ensemble_evaluator/snapshot.py +3 -1
- ert/ensemble_evaluator/state.py +1 -0
- ert/field_utils/__init__.py +8 -0
- ert/field_utils/field_utils.py +228 -15
- ert/field_utils/grdecl_io.py +1 -1
- ert/field_utils/roff_io.py +1 -1
- ert/gui/__init__.py +5 -2
- ert/gui/ertnotifier.py +1 -1
- ert/gui/ertwidgets/__init__.py +23 -16
- ert/gui/ertwidgets/analysismoduleedit.py +2 -2
- ert/gui/ertwidgets/checklist.py +1 -1
- ert/gui/ertwidgets/closabledialog.py +2 -0
- ert/gui/ertwidgets/copyablelabel.py +2 -0
- ert/gui/ertwidgets/create_experiment_dialog.py +3 -1
- ert/gui/ertwidgets/ensembleselector.py +2 -2
- ert/gui/ertwidgets/listeditbox.py +2 -0
- ert/gui/ertwidgets/models/__init__.py +2 -0
- ert/gui/ertwidgets/models/activerealizationsmodel.py +5 -1
- ert/gui/ertwidgets/models/path_model.py +1 -1
- ert/gui/ertwidgets/models/targetensemblemodel.py +5 -1
- ert/gui/ertwidgets/models/text_model.py +4 -1
- ert/gui/ertwidgets/pathchooser.py +0 -3
- ert/gui/ertwidgets/searchbox.py +17 -4
- ert/gui/ertwidgets/stringbox.py +2 -0
- ert/gui/{suggestor → ertwidgets/suggestor}/_suggestor_message.py +13 -4
- ert/gui/{suggestor → ertwidgets/suggestor}/suggestor.py +63 -30
- ert/gui/main.py +41 -13
- ert/gui/main_window.py +3 -7
- ert/gui/model/fm_step_list.py +3 -0
- ert/gui/model/real_list.py +1 -0
- ert/gui/model/snapshot.py +1 -0
- ert/gui/simulation/combobox_with_description.py +3 -0
- ert/gui/simulation/ensemble_experiment_panel.py +8 -2
- ert/gui/simulation/ensemble_information_filter_panel.py +7 -2
- ert/gui/simulation/ensemble_smoother_panel.py +8 -2
- ert/gui/simulation/evaluate_ensemble_panel.py +17 -7
- ert/gui/simulation/experiment_panel.py +18 -6
- ert/gui/simulation/manual_update_panel.py +35 -10
- ert/gui/simulation/multiple_data_assimilation_panel.py +13 -9
- ert/gui/simulation/run_dialog.py +47 -20
- ert/gui/simulation/single_test_run_panel.py +6 -3
- ert/gui/simulation/view/progress_widget.py +2 -0
- ert/gui/simulation/view/realization.py +5 -1
- ert/gui/simulation/view/update.py +2 -0
- ert/gui/summarypanel.py +20 -1
- ert/gui/tools/event_viewer/panel.py +3 -4
- ert/gui/tools/event_viewer/tool.py +2 -0
- ert/gui/tools/load_results/load_results_panel.py +1 -1
- ert/gui/tools/load_results/load_results_tool.py +2 -0
- ert/gui/tools/manage_experiments/export_dialog.py +136 -0
- ert/gui/tools/manage_experiments/manage_experiments_panel.py +2 -0
- ert/gui/tools/manage_experiments/storage_info_widget.py +121 -16
- ert/gui/tools/manage_experiments/storage_widget.py +4 -3
- ert/gui/tools/plot/customize/color_chooser.py +5 -2
- ert/gui/tools/plot/customize/customize_plot_dialog.py +2 -0
- ert/gui/tools/plot/customize/default_customization_view.py +4 -0
- ert/gui/tools/plot/customize/limits_customization_view.py +3 -0
- ert/gui/tools/plot/customize/statistics_customization_view.py +3 -0
- ert/gui/tools/plot/customize/style_chooser.py +2 -0
- ert/gui/tools/plot/customize/style_customization_view.py +3 -0
- ert/gui/tools/plot/data_type_keys_widget.py +2 -0
- ert/gui/tools/plot/data_type_proxy_model.py +3 -0
- ert/gui/tools/plot/plot_api.py +50 -28
- ert/gui/tools/plot/plot_ensemble_selection_widget.py +17 -10
- ert/gui/tools/plot/plot_widget.py +15 -2
- ert/gui/tools/plot/plot_window.py +41 -19
- ert/gui/tools/plot/plottery/plot_config.py +2 -0
- ert/gui/tools/plot/plottery/plot_context.py +14 -0
- ert/gui/tools/plot/plottery/plots/__init__.py +2 -0
- ert/gui/tools/plot/plottery/plots/cesp.py +3 -1
- ert/gui/tools/plot/plottery/plots/distribution.py +6 -1
- ert/gui/tools/plot/plottery/plots/ensemble.py +13 -5
- ert/gui/tools/plot/plottery/plots/gaussian_kde.py +12 -2
- ert/gui/tools/plot/plottery/plots/histogram.py +3 -1
- ert/gui/tools/plot/plottery/plots/misfits.py +436 -0
- ert/gui/tools/plot/plottery/plots/observations.py +18 -4
- ert/gui/tools/plot/plottery/plots/statistics.py +62 -20
- ert/gui/tools/plot/plottery/plots/std_dev.py +3 -1
- ert/gui/tools/plot/widgets/clearable_line_edit.py +9 -0
- ert/gui/tools/plot/widgets/filter_popup.py +2 -0
- ert/gui/tools/plot/widgets/filterable_kw_list_model.py +3 -0
- ert/gui/tools/plugins/plugin.py +1 -1
- ert/gui/tools/plugins/plugins_tool.py +2 -0
- ert/gui/tools/plugins/process_job_dialog.py +3 -0
- ert/gui/tools/workflows/workflow_dialog.py +2 -0
- ert/gui/tools/workflows/workflows_tool.py +2 -0
- ert/libres_facade.py +5 -7
- ert/logging/__init__.py +4 -1
- ert/mode_definitions.py +2 -0
- ert/plugins/__init__.py +4 -6
- ert/plugins/hook_implementations/workflows/csv_export.py +2 -3
- ert/plugins/hook_implementations/workflows/gen_data_rft_export.py +10 -2
- ert/plugins/hook_specifications/__init__.py +0 -10
- ert/plugins/hook_specifications/jobs.py +0 -9
- ert/plugins/plugin_manager.py +53 -124
- ert/resources/forward_models/run_reservoirsimulator.py +8 -4
- ert/resources/forward_models/template_render.py +10 -10
- ert/resources/shell_scripts/delete_directory.py +2 -2
- ert/run_models/__init__.py +24 -6
- ert/run_models/_create_run_path.py +133 -38
- ert/run_models/ensemble_experiment.py +10 -4
- ert/run_models/ensemble_information_filter.py +8 -1
- ert/run_models/ensemble_smoother.py +9 -3
- ert/run_models/evaluate_ensemble.py +8 -6
- ert/run_models/event.py +7 -3
- ert/run_models/everest_run_model.py +337 -113
- ert/run_models/initial_ensemble_run_model.py +25 -24
- ert/run_models/manual_update.py +6 -3
- ert/run_models/manual_update_enif.py +37 -0
- ert/run_models/model_factory.py +78 -18
- ert/run_models/multiple_data_assimilation.py +22 -11
- ert/run_models/run_model.py +72 -73
- ert/run_models/single_test_run.py +7 -4
- ert/run_models/update_run_model.py +4 -2
- ert/runpaths.py +5 -6
- ert/sample_prior.py +9 -4
- ert/scheduler/__init__.py +10 -5
- ert/scheduler/driver.py +40 -0
- ert/scheduler/event.py +3 -1
- ert/scheduler/job.py +23 -13
- ert/scheduler/lsf_driver.py +15 -5
- ert/scheduler/openpbs_driver.py +10 -4
- ert/scheduler/scheduler.py +5 -0
- ert/scheduler/slurm_driver.py +20 -5
- ert/services/__init__.py +2 -2
- ert/services/_base_service.py +37 -20
- ert/services/_storage_main.py +20 -18
- ert/services/ert_server.py +317 -0
- ert/shared/_doc_utils/__init__.py +4 -2
- ert/shared/_doc_utils/ert_jobs.py +1 -4
- ert/shared/net_utils.py +43 -18
- ert/shared/storage/connection.py +3 -3
- ert/shared/version.py +3 -3
- ert/storage/__init__.py +14 -1
- ert/storage/local_ensemble.py +44 -13
- ert/storage/local_experiment.py +54 -34
- ert/storage/local_storage.py +90 -58
- ert/storage/migration/to10.py +3 -2
- ert/storage/migration/to11.py +9 -10
- ert/storage/migration/to12.py +19 -20
- ert/storage/migration/to13.py +28 -27
- ert/storage/migration/to14.py +3 -3
- ert/storage/migration/to15.py +25 -0
- ert/storage/migration/to16.py +38 -0
- ert/storage/migration/to17.py +42 -0
- ert/storage/migration/to18.py +11 -0
- ert/storage/migration/to19.py +34 -0
- ert/storage/migration/to20.py +23 -0
- ert/storage/migration/to21.py +25 -0
- ert/storage/migration/to6.py +3 -2
- ert/storage/migration/to7.py +12 -13
- ert/storage/migration/to8.py +9 -11
- ert/storage/migration/to9.py +5 -4
- ert/storage/realization_storage_state.py +7 -7
- ert/substitutions.py +12 -28
- ert/validation/active_range.py +7 -7
- ert/validation/ensemble_realizations_argument.py +4 -2
- ert/validation/rangestring.py +16 -16
- ert/workflow_runner.py +6 -3
- {ert-16.0.9.dist-info → ert-19.0.0rc2.dist-info}/METADATA +21 -15
- ert-19.0.0rc2.dist-info/RECORD +524 -0
- {ert-16.0.9.dist-info → ert-19.0.0rc2.dist-info}/WHEEL +1 -1
- everest/api/everest_data_api.py +14 -1
- everest/assets/everest_logo.svg +406 -0
- everest/bin/config_branch_script.py +30 -14
- everest/bin/everconfigdump_script.py +2 -10
- everest/bin/everest_script.py +53 -33
- everest/bin/everlint_script.py +3 -5
- everest/bin/kill_script.py +7 -5
- everest/bin/main.py +11 -24
- everest/bin/monitor_script.py +64 -35
- everest/bin/utils.py +58 -43
- everest/bin/visualization_script.py +23 -13
- everest/config/__init__.py +4 -1
- everest/config/control_config.py +81 -6
- everest/config/control_variable_config.py +4 -3
- everest/config/everest_config.py +102 -79
- everest/config/forward_model_config.py +5 -3
- everest/config/install_data_config.py +7 -5
- everest/config/install_job_config.py +45 -3
- everest/config/install_template_config.py +3 -3
- everest/config/optimization_config.py +19 -6
- everest/config/output_constraint_config.py +8 -2
- everest/config/server_config.py +6 -55
- everest/config/simulator_config.py +62 -17
- everest/config/utils.py +25 -105
- everest/config/validation_utils.py +34 -15
- everest/config_file_loader.py +30 -21
- everest/detached/__init__.py +0 -6
- everest/detached/client.py +7 -52
- everest/detached/everserver.py +19 -45
- everest/everest_storage.py +24 -40
- everest/gui/everest_client.py +2 -3
- everest/gui/main_window.py +2 -2
- everest/optimizer/everest2ropt.py +68 -42
- everest/optimizer/opt_model_transforms.py +15 -20
- everest/optimizer/utils.py +0 -29
- everest/plugins/hook_specs.py +0 -24
- everest/strings.py +1 -6
- everest/util/__init__.py +3 -1
- ert/config/everest_objective_config.py +0 -95
- ert/config/ext_param_config.py +0 -107
- ert/gui/tools/export/__init__.py +0 -3
- ert/gui/tools/export/export_panel.py +0 -83
- ert/gui/tools/export/export_tool.py +0 -67
- ert/gui/tools/export/exporter.py +0 -36
- ert/plugins/hook_specifications/ecl_config.py +0 -29
- ert/services/storage_service.py +0 -127
- ert/summary_key_type.py +0 -234
- ert-16.0.9.dist-info/RECORD +0 -521
- everest/bin/everexport_script.py +0 -53
- everest/config/sampler_config.py +0 -103
- everest/simulator/__init__.py +0 -88
- everest/simulator/everest_to_ert.py +0 -252
- /ert/gui/{suggestor → ertwidgets/suggestor}/__init__.py +0 -0
- /ert/gui/{suggestor → ertwidgets/suggestor}/_colors.py +0 -0
- {ert-16.0.9.dist-info → ert-19.0.0rc2.dist-info}/entry_points.txt +0 -0
- {ert-16.0.9.dist-info → ert-19.0.0rc2.dist-info}/licenses/COPYING +0 -0
- {ert-16.0.9.dist-info → ert-19.0.0rc2.dist-info}/top_level.txt +0 -0
_ert/events.py
CHANGED
|
@@ -41,10 +41,12 @@ class Id:
|
|
|
41
41
|
ENSEMBLE_SUCCEEDED_TYPE = Literal["ensemble.succeeded"]
|
|
42
42
|
ENSEMBLE_CANCELLED_TYPE = Literal["ensemble.cancelled"]
|
|
43
43
|
ENSEMBLE_FAILED_TYPE = Literal["ensemble.failed"]
|
|
44
|
+
ENSEMBLE_WARNING_TYPE = Literal["ensemble.warning"]
|
|
44
45
|
ENSEMBLE_STARTED: Final = "ensemble.started"
|
|
45
46
|
ENSEMBLE_SUCCEEDED: Final = "ensemble.succeeded"
|
|
46
47
|
ENSEMBLE_CANCELLED: Final = "ensemble.cancelled"
|
|
47
48
|
ENSEMBLE_FAILED: Final = "ensemble.failed"
|
|
49
|
+
ENSEMBLE_WARNING: Final = "ensemble.warning"
|
|
48
50
|
ENSEMBLE_TYPES = (
|
|
49
51
|
ENSEMBLE_STARTED_TYPE
|
|
50
52
|
| ENSEMBLE_FAILED_TYPE
|
|
@@ -170,6 +172,15 @@ class EnsembleCancelled(EnsembleBaseEvent):
|
|
|
170
172
|
event_type: Id.ENSEMBLE_CANCELLED_TYPE = Id.ENSEMBLE_CANCELLED
|
|
171
173
|
|
|
172
174
|
|
|
175
|
+
class EnsembleEvaluationWarning(EnsembleBaseEvent):
|
|
176
|
+
"""This event is to indicate that something unexpected happened while
|
|
177
|
+
running the ensemble, and that it might be stuck in an unresponsive state.
|
|
178
|
+
"""
|
|
179
|
+
|
|
180
|
+
event_type: Id.ENSEMBLE_WARNING_TYPE = Id.ENSEMBLE_WARNING
|
|
181
|
+
warning_message: str
|
|
182
|
+
|
|
183
|
+
|
|
173
184
|
class EESnapshot(EnsembleBaseEvent):
|
|
174
185
|
event_type: Id.EE_SNAPSHOT_TYPE = Id.EE_SNAPSHOT
|
|
175
186
|
snapshot: Any
|
|
@@ -200,9 +211,15 @@ RealizationEvent = (
|
|
|
200
211
|
| RealizationResubmit
|
|
201
212
|
)
|
|
202
213
|
|
|
203
|
-
EnsembleEvent =
|
|
214
|
+
EnsembleEvent = (
|
|
215
|
+
EnsembleStarted
|
|
216
|
+
| EnsembleSucceeded
|
|
217
|
+
| EnsembleFailed
|
|
218
|
+
| EnsembleCancelled
|
|
219
|
+
| EnsembleEvaluationWarning
|
|
220
|
+
)
|
|
204
221
|
|
|
205
|
-
EEEvent = EESnapshot | EESnapshotUpdate
|
|
222
|
+
EEEvent = EESnapshot | EESnapshotUpdate | EnsembleEvaluationWarning
|
|
206
223
|
|
|
207
224
|
SnapshotInputEvent = RealizationEvent | EnsembleEvent | FMEvent
|
|
208
225
|
|
|
@@ -2,8 +2,9 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import logging
|
|
5
|
+
import types
|
|
5
6
|
import uuid
|
|
6
|
-
from typing import
|
|
7
|
+
from typing import Self
|
|
7
8
|
|
|
8
9
|
import zmq
|
|
9
10
|
import zmq.asyncio
|
|
@@ -67,7 +68,10 @@ class Client:
|
|
|
67
68
|
return self
|
|
68
69
|
|
|
69
70
|
async def __aexit__(
|
|
70
|
-
self,
|
|
71
|
+
self,
|
|
72
|
+
exc_type: type[BaseException] | None,
|
|
73
|
+
exc_value: BaseException | None,
|
|
74
|
+
exc_traceback: types.TracebackType | None,
|
|
71
75
|
) -> None:
|
|
72
76
|
try:
|
|
73
77
|
await self.send(DISCONNECT_MSG)
|
|
@@ -8,6 +8,7 @@ import sys
|
|
|
8
8
|
import time
|
|
9
9
|
from collections.abc import Generator, Iterable
|
|
10
10
|
from datetime import datetime
|
|
11
|
+
from pathlib import Path
|
|
11
12
|
from typing import TYPE_CHECKING, Any
|
|
12
13
|
|
|
13
14
|
from _ert.forward_model_runner import reporting
|
|
@@ -19,6 +20,7 @@ from _ert.forward_model_runner.reporting.message import (
|
|
|
19
20
|
ProcessTreeStatus,
|
|
20
21
|
)
|
|
21
22
|
from _ert.forward_model_runner.runner import ForwardModelRunner
|
|
23
|
+
from _ert.utils import file_safe_timestamp
|
|
22
24
|
|
|
23
25
|
if TYPE_CHECKING:
|
|
24
26
|
from ert.config.forward_model_step import ForwardModelJSON
|
|
@@ -81,10 +83,10 @@ def _setup_logging(directory: str = "logs") -> None:
|
|
|
81
83
|
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
|
82
84
|
)
|
|
83
85
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
csv_filename = f"memory-profile-{
|
|
86
|
+
timestamp = file_safe_timestamp(datetime.now().isoformat(timespec="minutes"))
|
|
87
|
+
|
|
88
|
+
filename = f"forward-model-runner-log-{timestamp}.txt"
|
|
89
|
+
csv_filename = f"memory-profile-{timestamp}.csv"
|
|
88
90
|
|
|
89
91
|
handler = logging.FileHandler(filename=directory + "/" + filename)
|
|
90
92
|
handler.setFormatter(formatter)
|
|
@@ -107,8 +109,9 @@ def _wait_for_retry() -> None:
|
|
|
107
109
|
|
|
108
110
|
def _read_fm_description_file(retry: bool = True) -> "ForwardModelDescriptionJSON":
|
|
109
111
|
try:
|
|
110
|
-
|
|
111
|
-
|
|
112
|
+
return json.loads(
|
|
113
|
+
Path(FORWARD_MODEL_DESCRIPTION_FILE).read_text(encoding="utf-8")
|
|
114
|
+
)
|
|
112
115
|
except json.JSONDecodeError as e:
|
|
113
116
|
raise OSError(
|
|
114
117
|
"fm_dispatch failed to load JSON-file describing the forward model."
|
|
@@ -40,8 +40,7 @@ class ForwardModelRunner:
|
|
|
40
40
|
def _read_manifest(self) -> dict[str, Manifest] | None:
|
|
41
41
|
if not Path("manifest.json").exists():
|
|
42
42
|
return None
|
|
43
|
-
|
|
44
|
-
data = json.load(f)
|
|
43
|
+
data = json.loads(Path("manifest.json").read_text(encoding="utf-8"))
|
|
45
44
|
return {
|
|
46
45
|
name: {"type": "file", "path": str(Path(file).absolute())}
|
|
47
46
|
for name, file in data.items()
|
_ert/utils.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
def file_safe_timestamp(timestamp: str) -> str:
|
|
2
|
+
"""
|
|
3
|
+
Convert an ISO timestamp string to a file-safe version
|
|
4
|
+
|
|
5
|
+
Keeps the date in the extended format (YYYY-MM-DD) and converts the time
|
|
6
|
+
to the basic format (HHMMSS) by removing colons. This mix is not strictly
|
|
7
|
+
ISO 8601 compliant, but it can still be parsed.
|
|
8
|
+
|
|
9
|
+
Example:
|
|
10
|
+
2025-10-10T14:30:00 -> 2025-10-10T143000
|
|
11
|
+
"""
|
|
12
|
+
return str(timestamp).replace(":", "")
|
ert/__main__.py
CHANGED
|
@@ -12,6 +12,7 @@ import sys
|
|
|
12
12
|
import warnings
|
|
13
13
|
from argparse import ArgumentParser, ArgumentTypeError
|
|
14
14
|
from collections.abc import Sequence
|
|
15
|
+
from pathlib import Path
|
|
15
16
|
from typing import Any
|
|
16
17
|
from uuid import UUID
|
|
17
18
|
|
|
@@ -20,6 +21,7 @@ from opentelemetry.trace import Status, StatusCode
|
|
|
20
21
|
|
|
21
22
|
import ert.shared
|
|
22
23
|
from _ert.threading import set_signal_handler
|
|
24
|
+
from ert.base_model_context import use_runtime_plugins
|
|
23
25
|
from ert.cli.main import ErtCliError, run_cli
|
|
24
26
|
from ert.config import ConfigValidationError, ErtConfig, lint_file
|
|
25
27
|
from ert.logging import LOGGING_CONFIG
|
|
@@ -32,11 +34,12 @@ from ert.mode_definitions import (
|
|
|
32
34
|
WORKFLOW_MODE,
|
|
33
35
|
)
|
|
34
36
|
from ert.namespace import Namespace
|
|
35
|
-
from ert.plugins import
|
|
36
|
-
from ert.run_models.multiple_data_assimilation import
|
|
37
|
-
from ert.services import
|
|
37
|
+
from ert.plugins import ErtRuntimePlugins, get_site_plugins, setup_site_logging
|
|
38
|
+
from ert.run_models.multiple_data_assimilation import MultipleDataAssimilationConfig
|
|
39
|
+
from ert.services import ErtServer, WebvizErt
|
|
40
|
+
from ert.shared.status.utils import get_ert_memory_usage
|
|
38
41
|
from ert.shared.storage.command import add_parser_options as ert_api_add_parser_options
|
|
39
|
-
from ert.storage import ErtStorageException
|
|
42
|
+
from ert.storage import ErtStorageException, ErtStoragePermissionError
|
|
40
43
|
from ert.trace import trace, tracer
|
|
41
44
|
from ert.validation import (
|
|
42
45
|
IntegerArgument,
|
|
@@ -51,9 +54,9 @@ logger = logging.getLogger(__name__)
|
|
|
51
54
|
|
|
52
55
|
|
|
53
56
|
def run_ert_storage(args: Namespace, _: ErtRuntimePlugins | None = None) -> None:
|
|
54
|
-
with
|
|
57
|
+
with ErtServer.start_server(
|
|
55
58
|
verbose=True,
|
|
56
|
-
project=ErtConfig.from_file(args.config).ens_path,
|
|
59
|
+
project=Path(ErtConfig.from_file(args.config).ens_path),
|
|
57
60
|
parent_pid=os.getpid(),
|
|
58
61
|
) as server:
|
|
59
62
|
server.wait()
|
|
@@ -68,8 +71,7 @@ def run_webviz_ert(args: Namespace, _: ErtRuntimePlugins | None = None) -> None:
|
|
|
68
71
|
) from err
|
|
69
72
|
|
|
70
73
|
kwargs: dict[str, Any] = {"verbose": args.verbose}
|
|
71
|
-
|
|
72
|
-
ert_config = ErtConfig.with_plugins(runtime_plugins).from_file(args.config)
|
|
74
|
+
ert_config = ErtConfig.with_plugins(get_site_plugins()).from_file(args.config)
|
|
73
75
|
|
|
74
76
|
os.chdir(ert_config.config_path)
|
|
75
77
|
ens_path = ert_config.ens_path
|
|
@@ -78,18 +80,32 @@ def run_webviz_ert(args: Namespace, _: ErtRuntimePlugins | None = None) -> None:
|
|
|
78
80
|
# only use the base name of the config file path
|
|
79
81
|
kwargs["ert_config"] = os.path.basename(args.config)
|
|
80
82
|
kwargs["project"] = os.path.abspath(ens_path)
|
|
83
|
+
|
|
84
|
+
yellow = "\x1b[33m"
|
|
85
|
+
green = "\x1b[32m"
|
|
86
|
+
bold = "\x1b[1m"
|
|
87
|
+
reset = "\x1b[0m"
|
|
88
|
+
|
|
81
89
|
try:
|
|
82
|
-
with
|
|
90
|
+
with ErtServer.init_service(project=Path(ens_path).absolute()) as storage:
|
|
83
91
|
storage.wait_until_ready()
|
|
84
92
|
print(
|
|
85
|
-
"""
|
|
86
|
-
|
|
93
|
+
f"""
|
|
94
|
+
---------------------------------------------------------------
|
|
95
|
+
|
|
96
|
+
{yellow}{bold}Webviz-ERT is deprecated and will be removed in the near future{reset}
|
|
97
|
+
|
|
98
|
+
{green}{bold}Plotting capabilities provided by Webviz-ERT are now available
|
|
99
|
+
using the ERT plotter{reset}
|
|
100
|
+
|
|
101
|
+
---------------------------------------------------------------
|
|
87
102
|
|
|
88
103
|
Starting up Webviz-ERT. This might take more than a minute.
|
|
89
104
|
|
|
90
|
-
|
|
105
|
+
---------------------------------------------------------------
|
|
91
106
|
"""
|
|
92
107
|
)
|
|
108
|
+
logger.info("Show Webviz-ert deprecation warning")
|
|
93
109
|
webviz_kwargs = {
|
|
94
110
|
"experimental_mode": args.experimental_mode,
|
|
95
111
|
"verbose": args.verbose,
|
|
@@ -500,7 +516,7 @@ def get_ert_parser(parser: ArgumentParser | None = None) -> ArgumentParser:
|
|
|
500
516
|
es_mda_parser.add_argument(
|
|
501
517
|
"--weights",
|
|
502
518
|
type=valid_weights,
|
|
503
|
-
default=
|
|
519
|
+
default=MultipleDataAssimilationConfig.default_weights,
|
|
504
520
|
help="Example custom relative weights: '8,4,2,1'. This means multiple data "
|
|
505
521
|
"assimilation ensemble smoother will half the weight applied to the "
|
|
506
522
|
"observation errors from one iteration to the next across 4 iterations.",
|
|
@@ -565,15 +581,15 @@ def get_ert_parser(parser: ArgumentParser | None = None) -> ArgumentParser:
|
|
|
565
581
|
"--color-always",
|
|
566
582
|
action="store_true",
|
|
567
583
|
help="Force coloring of monitor output, which is automatically"
|
|
568
|
-
|
|
584
|
+
" disabled if the output stream is not a terminal.",
|
|
569
585
|
default=False,
|
|
570
586
|
)
|
|
571
587
|
cli_parser.add_argument(
|
|
572
588
|
"--disable-monitoring",
|
|
573
589
|
action="store_true",
|
|
574
590
|
help="Monitoring will continuously print the status of the realisations"
|
|
575
|
-
|
|
576
|
-
|
|
591
|
+
" classified into Waiting, Pending, Running, Failed, Finished"
|
|
592
|
+
" and Unknown.",
|
|
577
593
|
default=False,
|
|
578
594
|
)
|
|
579
595
|
cli_parser.add_argument(
|
|
@@ -597,7 +613,7 @@ def ert_parser(parser: ArgumentParser | None, args: Sequence[str]) -> Namespace:
|
|
|
597
613
|
def log_process_usage() -> None:
|
|
598
614
|
try:
|
|
599
615
|
usage = resource.getrusage(resource.RUSAGE_SELF)
|
|
600
|
-
max_rss =
|
|
616
|
+
max_rss = get_ert_memory_usage()
|
|
601
617
|
|
|
602
618
|
usage_dict: dict[str, int | float] = {
|
|
603
619
|
"User time": usage.ru_utime,
|
|
@@ -636,25 +652,24 @@ def main() -> None:
|
|
|
636
652
|
|
|
637
653
|
os.environ["ERT_LOG_DIR"] = log_dir
|
|
638
654
|
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
sys.exit(exit_msg)
|
|
655
|
+
config_dict = yaml.safe_load(Path(LOGGING_CONFIG).read_text(encoding="utf-8"))
|
|
656
|
+
for handler_name, handler_config in config_dict["handlers"].items():
|
|
657
|
+
if handler_name == "file":
|
|
658
|
+
handler_config["filename"] = "ert-log.txt"
|
|
659
|
+
if "ert.logging.TimestampedFileHandler" in handler_config.values():
|
|
660
|
+
handler_config["config_filename"] = args.config
|
|
661
|
+
try:
|
|
662
|
+
logging.config.dictConfig(config_dict)
|
|
663
|
+
except ValueError as err:
|
|
664
|
+
if "handler 'file'" in str(err):
|
|
665
|
+
exit_msg = (
|
|
666
|
+
f"Could not configure log handler for files. "
|
|
667
|
+
f"Check if you have write-access to the logs-directory ({log_dir})."
|
|
668
|
+
)
|
|
669
|
+
else:
|
|
670
|
+
exit_msg = str(err)
|
|
671
|
+
os.environ.pop("ERT_LOG_DIR")
|
|
672
|
+
sys.exit(exit_msg)
|
|
658
673
|
|
|
659
674
|
logger = logging.getLogger(__name__)
|
|
660
675
|
if args.verbose:
|
|
@@ -663,9 +678,14 @@ def main() -> None:
|
|
|
663
678
|
handler.setLevel(logging.INFO)
|
|
664
679
|
root_logger.addHandler(handler)
|
|
665
680
|
try:
|
|
666
|
-
|
|
681
|
+
site_plugins = get_site_plugins()
|
|
682
|
+
setup_site_logging(logging.getLogger())
|
|
683
|
+
with use_runtime_plugins(site_plugins):
|
|
667
684
|
logger.info(f"Running ert with {args} in {os.getcwd()}")
|
|
668
|
-
args.func(args,
|
|
685
|
+
args.func(args, site_plugins)
|
|
686
|
+
except ErtStoragePermissionError as err:
|
|
687
|
+
logger.error(str(err))
|
|
688
|
+
sys.exit(str(err))
|
|
669
689
|
except (ErtCliError, ErtStorageException) as err:
|
|
670
690
|
span.set_status(Status(StatusCode.ERROR))
|
|
671
691
|
span.record_exception(err)
|
ert/analysis/_enif_update.py
CHANGED
|
@@ -160,10 +160,14 @@ def analysis_EnIF(
|
|
|
160
160
|
Y=S.T,
|
|
161
161
|
verbose_level=5,
|
|
162
162
|
)
|
|
163
|
-
|
|
163
|
+
updated_parameters = [
|
|
164
|
+
p
|
|
165
|
+
for p, config in source_ensemble.experiment.parameter_configuration.items()
|
|
166
|
+
if config.update
|
|
167
|
+
]
|
|
164
168
|
# Learn the precision matrix block-sparse over parameter groups
|
|
165
169
|
Prec_u = sp.sparse.csc_matrix((0, 0), dtype=float)
|
|
166
|
-
for param_group in
|
|
170
|
+
for param_group in updated_parameters:
|
|
167
171
|
config_node = source_ensemble.experiment.parameter_configuration[param_group]
|
|
168
172
|
X_local = source_ensemble.load_parameters_numpy(param_group, iens_active_index)
|
|
169
173
|
X_local_scaler = StandardScaler()
|
|
@@ -215,7 +219,7 @@ def analysis_EnIF(
|
|
|
215
219
|
|
|
216
220
|
# Iterate over parameters to store the updated ensemble
|
|
217
221
|
parameters_updated = 0
|
|
218
|
-
for param_group in
|
|
222
|
+
for param_group in updated_parameters:
|
|
219
223
|
log_msg = f"Storing data for {param_group}.."
|
|
220
224
|
logger.info(log_msg)
|
|
221
225
|
progress_callback(AnalysisStatusEvent(msg=log_msg))
|
|
@@ -241,7 +245,7 @@ def analysis_EnIF(
|
|
|
241
245
|
)
|
|
242
246
|
_copy_unupdated_parameters(
|
|
243
247
|
list(source_ensemble.experiment.parameter_configuration.keys()),
|
|
244
|
-
|
|
248
|
+
updated_parameters,
|
|
245
249
|
iens_active_index,
|
|
246
250
|
source_ensemble,
|
|
247
251
|
target_ensemble,
|
ert/analysis/_es_update.py
CHANGED
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import functools
|
|
4
4
|
import logging
|
|
5
|
+
import re
|
|
5
6
|
import time
|
|
6
7
|
import warnings
|
|
7
8
|
from collections.abc import Callable, Iterable, Sequence
|
|
@@ -441,6 +442,12 @@ def smoother_update(
|
|
|
441
442
|
with warnings.catch_warnings():
|
|
442
443
|
original_showwarning = warnings.showwarning
|
|
443
444
|
|
|
445
|
+
ILL_CONDITIONED_RE = re.compile(
|
|
446
|
+
r"^LinAlgWarning:.*ill[- ]?conditioned\s+matrix", re.IGNORECASE
|
|
447
|
+
)
|
|
448
|
+
LIMIT_ILL_CONDITIONED_WARNING = 1000
|
|
449
|
+
illconditioned_warn_counter = 0
|
|
450
|
+
|
|
444
451
|
def log_warning(
|
|
445
452
|
message: Warning | str,
|
|
446
453
|
category: type[Warning],
|
|
@@ -449,12 +456,18 @@ def smoother_update(
|
|
|
449
456
|
file: TextIO | None = None,
|
|
450
457
|
line: str | None = None,
|
|
451
458
|
) -> None:
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
)
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
459
|
+
nonlocal illconditioned_warn_counter
|
|
460
|
+
|
|
461
|
+
if ILL_CONDITIONED_RE.search(str(message)):
|
|
462
|
+
illconditioned_warn_counter += 1
|
|
463
|
+
|
|
464
|
+
if illconditioned_warn_counter < LIMIT_ILL_CONDITIONED_WARNING:
|
|
465
|
+
logger.warning(
|
|
466
|
+
f"{category.__name__}: {message} (from {filename}:{lineno})"
|
|
467
|
+
)
|
|
468
|
+
original_showwarning(
|
|
469
|
+
message, category, filename, lineno, file=file, line=line
|
|
470
|
+
)
|
|
458
471
|
|
|
459
472
|
warnings.showwarning = log_warning
|
|
460
473
|
analysis_ES(
|
ert/analysis/_update_commons.py
CHANGED
|
@@ -61,10 +61,19 @@ def _copy_unupdated_parameters(
|
|
|
61
61
|
|
|
62
62
|
# Copy the non-updated parameter groups from source to target
|
|
63
63
|
# for each active realization
|
|
64
|
+
complete_df: pl.DataFrame | None = None
|
|
64
65
|
for parameter_group in not_updated_parameter_groups:
|
|
65
|
-
source_ensemble.
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
data = source_ensemble.load_parameters(parameter_group, iens_active_index)
|
|
67
|
+
if isinstance(data, pl.DataFrame):
|
|
68
|
+
if complete_df is None:
|
|
69
|
+
complete_df = data
|
|
70
|
+
else:
|
|
71
|
+
complete_df = complete_df.join(data, on="realization")
|
|
72
|
+
else:
|
|
73
|
+
target_ensemble.save_parameters(dataset=data)
|
|
74
|
+
|
|
75
|
+
if complete_df is not None:
|
|
76
|
+
target_ensemble.save_parameters(complete_df)
|
|
68
77
|
|
|
69
78
|
|
|
70
79
|
def _expand_wildcards(
|
|
@@ -331,11 +340,12 @@ def _all_parameters(
|
|
|
331
340
|
) -> npt.NDArray[np.float64]:
|
|
332
341
|
"""Return all parameters in assimilation problem"""
|
|
333
342
|
|
|
334
|
-
|
|
335
|
-
|
|
343
|
+
groups_to_update = [
|
|
344
|
+
k for k, v in ensemble.experiment.parameter_configuration.items() if v.update
|
|
345
|
+
]
|
|
336
346
|
param_arrays = [
|
|
337
347
|
ensemble.load_parameters_numpy(param_group, iens_active_index)
|
|
338
|
-
for param_group in
|
|
348
|
+
for param_group in groups_to_update
|
|
339
349
|
]
|
|
340
350
|
|
|
341
351
|
return np.vstack(param_arrays)
|
ert/base_model_context.py
CHANGED
ert/cli/main.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env python
|
|
2
1
|
from __future__ import annotations
|
|
3
2
|
|
|
4
3
|
import contextlib
|
|
@@ -7,9 +6,11 @@ import os
|
|
|
7
6
|
import queue
|
|
8
7
|
import sys
|
|
9
8
|
from collections import Counter
|
|
9
|
+
from pathlib import Path
|
|
10
10
|
from typing import TextIO
|
|
11
11
|
|
|
12
12
|
from _ert.threading import ErtThread
|
|
13
|
+
from ert.base_model_context import use_runtime_plugins
|
|
13
14
|
from ert.cli.monitor import Monitor
|
|
14
15
|
from ert.cli.workflow import execute_workflow
|
|
15
16
|
from ert.config import ErtConfig, QueueSystem
|
|
@@ -23,10 +24,10 @@ from ert.mode_definitions import (
|
|
|
23
24
|
WORKFLOW_MODE,
|
|
24
25
|
)
|
|
25
26
|
from ert.namespace import Namespace
|
|
26
|
-
from ert.plugins import
|
|
27
|
+
from ert.plugins import ErtRuntimePlugins, get_site_plugins
|
|
27
28
|
from ert.run_models.event import StatusEvents
|
|
28
29
|
from ert.run_models.model_factory import create_model
|
|
29
|
-
from ert.storage import open_storage
|
|
30
|
+
from ert.storage import LocalStorage, open_storage
|
|
30
31
|
from ert.storage.local_storage import local_storage_set_ert_config
|
|
31
32
|
|
|
32
33
|
|
|
@@ -45,10 +46,7 @@ def run_cli(args: Namespace, runtime_plugins: ErtRuntimePlugins | None = None) -
|
|
|
45
46
|
if runtime_plugins is not None:
|
|
46
47
|
ert_config = ErtConfig.with_plugins(runtime_plugins).from_file(args.config)
|
|
47
48
|
else:
|
|
48
|
-
|
|
49
|
-
ert_config = ErtConfig.with_plugins(default_runtime_plugins).from_file(
|
|
50
|
-
args.config
|
|
51
|
-
)
|
|
49
|
+
ert_config = ErtConfig.with_plugins(get_site_plugins()).from_file(args.config)
|
|
52
50
|
|
|
53
51
|
local_storage_set_ert_config(ert_config)
|
|
54
52
|
counter_fm_steps = Counter(fms.name for fms in ert_config.forward_model_steps)
|
|
@@ -90,18 +88,25 @@ def run_cli(args: Namespace, runtime_plugins: ErtRuntimePlugins | None = None) -
|
|
|
90
88
|
)
|
|
91
89
|
|
|
92
90
|
if args.mode == WORKFLOW_MODE:
|
|
93
|
-
|
|
91
|
+
path = Path(ert_config.ens_path)
|
|
92
|
+
if LocalStorage.check_migration_needed(path):
|
|
93
|
+
LocalStorage.perform_migration(path)
|
|
94
|
+
with open_storage(path, "w") as storage:
|
|
94
95
|
execute_workflow(ert_config, storage, args.name)
|
|
95
96
|
return
|
|
96
97
|
|
|
97
98
|
status_queue: queue.SimpleQueue[StatusEvents] = queue.SimpleQueue()
|
|
99
|
+
using_local_queuesystem: bool = True
|
|
98
100
|
try:
|
|
99
|
-
with
|
|
101
|
+
with use_runtime_plugins(get_site_plugins()):
|
|
100
102
|
model = create_model(
|
|
101
103
|
ert_config,
|
|
102
104
|
args,
|
|
103
105
|
status_queue,
|
|
104
106
|
)
|
|
107
|
+
using_local_queuesystem = (
|
|
108
|
+
ert_config.queue_config.queue_system == QueueSystem.LOCAL
|
|
109
|
+
)
|
|
105
110
|
except ValueError as e:
|
|
106
111
|
raise ErtCliError(f"{args.mode} was not valid, failed with: {e}") from e
|
|
107
112
|
|
|
@@ -118,17 +123,17 @@ def run_cli(args: Namespace, runtime_plugins: ErtRuntimePlugins | None = None) -
|
|
|
118
123
|
f"and DESIGN_MATRIX ({model.active_realizations.count(True)})"
|
|
119
124
|
)
|
|
120
125
|
|
|
121
|
-
if args.port_range is None and
|
|
126
|
+
if args.port_range is None and using_local_queuesystem:
|
|
122
127
|
# This is within the range for ephemeral ports as defined by
|
|
123
128
|
# most unix flavors https://en.wikipedia.org/wiki/Ephemeral_port
|
|
124
129
|
args.port_range = range(49152, 51819)
|
|
125
130
|
|
|
126
|
-
use_ipc_protocol = model.queue_system == QueueSystem.LOCAL
|
|
127
131
|
evaluator_server_config = EvaluatorServerConfig(
|
|
128
132
|
port_range=None
|
|
129
133
|
if args.port_range is None
|
|
130
134
|
else (min(args.port_range), max(args.port_range) + 1),
|
|
131
|
-
use_ipc_protocol=
|
|
135
|
+
use_ipc_protocol=using_local_queuesystem,
|
|
136
|
+
prioritize_private_ip_address=ert_config.prioritize_private_ip_address,
|
|
132
137
|
)
|
|
133
138
|
|
|
134
139
|
if model.check_if_runpath_exists():
|
ert/cli/monitor.py
CHANGED
|
@@ -9,6 +9,7 @@ from typing import TextIO
|
|
|
9
9
|
import humanize
|
|
10
10
|
from tqdm import tqdm
|
|
11
11
|
|
|
12
|
+
from _ert.events import EnsembleEvaluationWarning
|
|
12
13
|
from ert.ensemble_evaluator import (
|
|
13
14
|
EndEvent,
|
|
14
15
|
EnsembleSnapshot,
|
|
@@ -19,6 +20,7 @@ from ert.ensemble_evaluator import identifiers as ids
|
|
|
19
20
|
from ert.ensemble_evaluator.state import (
|
|
20
21
|
COLOR_FAILED,
|
|
21
22
|
COLOR_FINISHED,
|
|
23
|
+
COLOR_WARNING,
|
|
22
24
|
FORWARD_MODEL_STATE_FAILURE,
|
|
23
25
|
REAL_STATE_TO_COLOR,
|
|
24
26
|
)
|
|
@@ -96,6 +98,11 @@ class Monitor:
|
|
|
96
98
|
| RunModelErrorEvent() as event
|
|
97
99
|
):
|
|
98
100
|
event.write_as_csv(output_path)
|
|
101
|
+
case EnsembleEvaluationWarning(warning_message=msg):
|
|
102
|
+
print(
|
|
103
|
+
self._colorize(msg, color=COLOR_WARNING),
|
|
104
|
+
file=self._out,
|
|
105
|
+
)
|
|
99
106
|
|
|
100
107
|
def _print_step_errors(self) -> None:
|
|
101
108
|
failed_steps: dict[str | None, int] = {}
|