From 9cd1395757090962b205caaecefbba9a3a68f3dc Mon Sep 17 00:00:00 2001 From: Panasun Date: Thu, 1 Oct 2026 14:08:30 +0200 Subject: [PATCH 01/12] Change the example code from file_name input to 4 args input --- .../sphinx_docs/docs/parallel-in-python.rst | 56 ++++++++++--------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/python/sphinx_docs/docs/parallel-in-python.rst b/python/sphinx_docs/docs/parallel-in-python.rst index b2a6d73..87baf65 100644 --- a/python/sphinx_docs/docs/parallel-in-python.rst +++ b/python/sphinx_docs/docs/parallel-in-python.rst @@ -37,44 +37,44 @@ An example script for a parallel run .. code-block:: python - from opm.simulators import BlackOilSimulator + from mpi4py import MPI # noqa: E402 -- owns MPI_Init; must come before OPM + from opm.simulators import BlackOilSimulator # noqa: E402 + from opm.io.parser import Parser # noqa: E402 + from opm.io.ecl_state import EclipseState # noqa: E402 + from opm.io.schedule import Schedule # noqa: E402 + from opm.io.summary import SummaryConfig # noqa: E402 - # mpi4py owns MPI_Init/MPI_Finalize; importing it initializes MPI for the - # whole process, including the simulator underneath. - from mpi4py import MPI + CASE = "SPE1CASE1.DATA" - COMM = MPI.COMM_WORLD - RANK = COMM.Get_rank() + COMM = MPI.COMM_WORLD + RANK = COMM.Get_rank() - CASE = "SPE1CASE1.DATA" + def main(): + deck = Parser().parse(CASE) + state = EclipseState(deck) # needed to build the Schedule only + schedule = Schedule(deck, state) + summary_config = SummaryConfig(deck, state, schedule) - def main(): - sim = BlackOilSimulator(filename=CASE) + # The one change from the documented example: None instead of `state`. + sim = BlackOilSimulator(deck, None, schedule, summary_config) + sim.setup_mpi(init=False, finalize=False) - # init=False: MPI is already initialized by mpi4py. - # finalize=False: keep MPI alive until the script exits. - sim.setup_mpi(init=False, finalize=False) + sim.step_init() - sim.step_init() + poro = sim.get_porosity() + sim.set_porosity(poro * 0.95) - sim.step() + sim.step() - # The grid is distributed, so each rank sees only its own cells - # (owned + overlap). - poro = sim.get_porosity() - sim.set_porosity(poro * 0.95) + sim.step_cleanup() - sim.step() + if RANK == 0: + print("done -- results written to SPE1CASE1.PRT", flush=True) - sim.step_cleanup() + if __name__ == "__main__": + main() - if RANK == 0: - print("done -- results written to SPE1CASE1.PRT", flush=True) - - - if __name__ == "__main__": - main() Run it with: @@ -134,3 +134,7 @@ Constructing the simulator ``BlackOilSimulator(deck, state, schedule, summary_config)`` — cannot run on more than one rank. It aborts with ``Parallel simulator setup is incorrect as it does not use ParallelEclipseState``. + + +To Reviewer +----------- From 8a19bcddf30f57d7d872218393d7688be1e111af Mon Sep 17 00:00:00 2001 From: Panasun Date: Thu, 1 Oct 2026 14:14:49 +0200 Subject: [PATCH 02/12] I decide to remove the TO REVIEWER section and I will write it in PR instead --- python/sphinx_docs/docs/parallel-in-python.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/python/sphinx_docs/docs/parallel-in-python.rst b/python/sphinx_docs/docs/parallel-in-python.rst index 87baf65..9f3d35f 100644 --- a/python/sphinx_docs/docs/parallel-in-python.rst +++ b/python/sphinx_docs/docs/parallel-in-python.rst @@ -134,7 +134,3 @@ Constructing the simulator ``BlackOilSimulator(deck, state, schedule, summary_config)`` — cannot run on more than one rank. It aborts with ``Parallel simulator setup is incorrect as it does not use ParallelEclipseState``. - - -To Reviewer ------------ From aee5e9231247f0d646cacf5e3723a0e0f08ce10d Mon Sep 17 00:00:00 2001 From: panasun1994 <102752624+panasun1994@users.noreply.github.com> Date: Fri, 9 Oct 2026 09:42:47 +0200 Subject: [PATCH 03/12] Update python/sphinx_docs/docs/parallel-in-python.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Håkon Hægland --- python/sphinx_docs/docs/parallel-in-python.rst | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/python/sphinx_docs/docs/parallel-in-python.rst b/python/sphinx_docs/docs/parallel-in-python.rst index 9f3d35f..5012226 100644 --- a/python/sphinx_docs/docs/parallel-in-python.rst +++ b/python/sphinx_docs/docs/parallel-in-python.rst @@ -37,12 +37,14 @@ An example script for a parallel run .. code-block:: python - from mpi4py import MPI # noqa: E402 -- owns MPI_Init; must come before OPM - from opm.simulators import BlackOilSimulator # noqa: E402 - from opm.io.parser import Parser # noqa: E402 - from opm.io.ecl_state import EclipseState # noqa: E402 - from opm.io.schedule import Schedule # noqa: E402 - from opm.io.summary import SummaryConfig # noqa: E402 + # Importing mpi4py initializes MPI for the whole process, + # including the simulator underneath. + from mpi4py import MPI + from opm.simulators import BlackOilSimulator + from opm.io.parser import Parser + from opm.io.ecl_state import EclipseState + from opm.io.schedule import Schedule + from opm.io.summary import SummaryConfig CASE = "SPE1CASE1.DATA" From 2cf489d0a9c4e1bccee392d5d7cebe2f06d71df0 Mon Sep 17 00:00:00 2001 From: panasun1994 <102752624+panasun1994@users.noreply.github.com> Date: Fri, 9 Oct 2026 09:43:27 +0200 Subject: [PATCH 04/12] Update python/sphinx_docs/docs/parallel-in-python.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Håkon Hægland --- python/sphinx_docs/docs/parallel-in-python.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/sphinx_docs/docs/parallel-in-python.rst b/python/sphinx_docs/docs/parallel-in-python.rst index 5012226..6b979c7 100644 --- a/python/sphinx_docs/docs/parallel-in-python.rst +++ b/python/sphinx_docs/docs/parallel-in-python.rst @@ -58,7 +58,9 @@ An example script for a parallel run schedule = Schedule(deck, state) summary_config = SummaryConfig(deck, state, schedule) - # The one change from the documented example: None instead of `state`. + # Compared with the serial example in "Run OPM Flow from Python", the only + # change is None in place of `state`: in parallel the simulator must build + # the EclipseState itself (see "Constructing the simulator" below). sim = BlackOilSimulator(deck, None, schedule, summary_config) sim.setup_mpi(init=False, finalize=False) From 0d94188239cd09d525817ff09e6b0d08f87332c3 Mon Sep 17 00:00:00 2001 From: panasun1994 <102752624+panasun1994@users.noreply.github.com> Date: Fri, 9 Oct 2026 09:44:45 +0200 Subject: [PATCH 05/12] Update python/sphinx_docs/docs/parallel-in-python.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Håkon Hægland --- python/sphinx_docs/docs/parallel-in-python.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/python/sphinx_docs/docs/parallel-in-python.rst b/python/sphinx_docs/docs/parallel-in-python.rst index 6b979c7..d18dc12 100644 --- a/python/sphinx_docs/docs/parallel-in-python.rst +++ b/python/sphinx_docs/docs/parallel-in-python.rst @@ -35,6 +35,15 @@ Running in parallel needs the following in addition: An example script for a parallel run ------------------------------------ +The example builds the simulator from objects parsed in Python, instead of from +the file name, so that the script can change well controls during the run +through the ``Schedule`` object it passes in, for example with +``schedule.shut_well("PROD", step)``. With the filename constructor the +simulator builds its own ``Schedule``, which the script cannot reach. Passing +``None`` for the ``EclipseState`` is what makes this work in parallel (see +"Constructing the simulator" below). This is a workaround until the simulator +offers a supported way to reach its own ``Schedule``. + .. code-block:: python # Importing mpi4py initializes MPI for the whole process, From c3618e3622d46523923b126b5232cc9c6f83925a Mon Sep 17 00:00:00 2001 From: panasun1994 <102752624+panasun1994@users.noreply.github.com> Date: Fri, 9 Oct 2026 09:45:48 +0200 Subject: [PATCH 06/12] Update python/sphinx_docs/docs/parallel-in-python.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Håkon Hægland --- python/sphinx_docs/docs/parallel-in-python.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/sphinx_docs/docs/parallel-in-python.rst b/python/sphinx_docs/docs/parallel-in-python.rst index d18dc12..29edcd5 100644 --- a/python/sphinx_docs/docs/parallel-in-python.rst +++ b/python/sphinx_docs/docs/parallel-in-python.rst @@ -71,6 +71,8 @@ offers a supported way to reach its own ``Schedule``. # change is None in place of `state`: in parallel the simulator must build # the EclipseState itself (see "Constructing the simulator" below). sim = BlackOilSimulator(deck, None, schedule, summary_config) + # init=False: MPI is already initialized by mpi4py. + # finalize=False: keep MPI alive until the script exits. sim.setup_mpi(init=False, finalize=False) sim.step_init() From 0c3908a57171abf74a4c0e09ed824dcf89a41298 Mon Sep 17 00:00:00 2001 From: panasun1994 <102752624+panasun1994@users.noreply.github.com> Date: Fri, 9 Oct 2026 09:46:37 +0200 Subject: [PATCH 07/12] Update python/sphinx_docs/docs/parallel-in-python.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Håkon Hægland --- python/sphinx_docs/docs/parallel-in-python.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/sphinx_docs/docs/parallel-in-python.rst b/python/sphinx_docs/docs/parallel-in-python.rst index 29edcd5..2d05641 100644 --- a/python/sphinx_docs/docs/parallel-in-python.rst +++ b/python/sphinx_docs/docs/parallel-in-python.rst @@ -77,6 +77,8 @@ offers a supported way to reach its own ``Schedule``. sim.step_init() + # The grid is distributed, so each rank sees only its own cells + # (owned + overlap). poro = sim.get_porosity() sim.set_porosity(poro * 0.95) From 9fd911eee5e93047a7d58956844b90074b833173 Mon Sep 17 00:00:00 2001 From: panasun1994 <102752624+panasun1994@users.noreply.github.com> Date: Fri, 9 Oct 2026 09:46:56 +0200 Subject: [PATCH 08/12] Update python/sphinx_docs/docs/parallel-in-python.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Håkon Hægland --- python/sphinx_docs/docs/parallel-in-python.rst | 7 ------- 1 file changed, 7 deletions(-) diff --git a/python/sphinx_docs/docs/parallel-in-python.rst b/python/sphinx_docs/docs/parallel-in-python.rst index 2d05641..618dffd 100644 --- a/python/sphinx_docs/docs/parallel-in-python.rst +++ b/python/sphinx_docs/docs/parallel-in-python.rst @@ -86,13 +86,6 @@ offers a supported way to reach its own ``Schedule``. sim.step_cleanup() - if RANK == 0: - print("done -- results written to SPE1CASE1.PRT", flush=True) - - if __name__ == "__main__": - main() - - Run it with: From 0ea27860df3f90fc2b7dff842a5a071cd9fafeae Mon Sep 17 00:00:00 2001 From: panasun1994 <102752624+panasun1994@users.noreply.github.com> Date: Fri, 9 Oct 2026 10:39:23 +0200 Subject: [PATCH 09/12] Update python/sphinx_docs/docs/parallel-in-python.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Håkon Hægland --- python/sphinx_docs/docs/parallel-in-python.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/python/sphinx_docs/docs/parallel-in-python.rst b/python/sphinx_docs/docs/parallel-in-python.rst index 618dffd..3ffe5a9 100644 --- a/python/sphinx_docs/docs/parallel-in-python.rst +++ b/python/sphinx_docs/docs/parallel-in-python.rst @@ -86,6 +86,13 @@ offers a supported way to reach its own ``Schedule``. sim.step_cleanup() + if RANK == 0: + print("done -- results written to SPE1CASE1.PRT", flush=True) + + + if __name__ == "__main__": + main() + Run it with: From 463fe0cfe17e14565b26656a011a3aa4005e4501 Mon Sep 17 00:00:00 2001 From: panasun1994 <102752624+panasun1994@users.noreply.github.com> Date: Fri, 9 Oct 2026 10:39:41 +0200 Subject: [PATCH 10/12] Update python/sphinx_docs/docs/parallel-in-python.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Håkon Hægland --- python/sphinx_docs/docs/parallel-in-python.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/sphinx_docs/docs/parallel-in-python.rst b/python/sphinx_docs/docs/parallel-in-python.rst index 3ffe5a9..23c7ac9 100644 --- a/python/sphinx_docs/docs/parallel-in-python.rst +++ b/python/sphinx_docs/docs/parallel-in-python.rst @@ -42,7 +42,9 @@ through the ``Schedule`` object it passes in, for example with simulator builds its own ``Schedule``, which the script cannot reach. Passing ``None`` for the ``EclipseState`` is what makes this work in parallel (see "Constructing the simulator" below). This is a workaround until the simulator -offers a supported way to reach its own ``Schedule``. +offers a supported way to reach its own ``Schedule``. In a parallel run, make +every such change on every rank: each rank holds its own ``Schedule``, and a +change made only under ``if RANK == 0:`` is silently ignored. .. code-block:: python From 5879a3dbd7e351031623e07f737f0ebb3eb5752a Mon Sep 17 00:00:00 2001 From: Panasun Date: Fri, 9 Oct 2026 11:26:54 +0200 Subject: [PATCH 11/12] Address review, adding the shut_well example and expected result --- .../sphinx_docs/docs/parallel-in-python.rst | 40 ++++++++++++++++--- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/python/sphinx_docs/docs/parallel-in-python.rst b/python/sphinx_docs/docs/parallel-in-python.rst index 23c7ac9..6175f91 100644 --- a/python/sphinx_docs/docs/parallel-in-python.rst +++ b/python/sphinx_docs/docs/parallel-in-python.rst @@ -79,12 +79,18 @@ change made only under ``if RANK == 0:`` is silently ignored. sim.step_init() + # Change well controls through the Schedule passed to the constructor. + # Every rank must make the same call: a change made only under + # `if RANK == 0:` is silently ignored. + schedule.shut_well("PROD", 3) + # The grid is distributed, so each rank sees only its own cells # (owned + overlap). poro = sim.get_porosity() sim.set_porosity(poro * 0.95) - sim.step() + while not sim.check_simulation_finished(): + sim.step() sim.step_cleanup() @@ -108,6 +114,24 @@ and confirm the rank count in the print file: grep "Number of MPI processes" SPE1CASE1.PRT +To check that the well was shut, read the oil rate of ``PROD`` back from the +summary file once the run has finished: + +.. code-block:: python + + from opm.io.ecl import ESmry + + smry = ESmry("SPE1CASE1.SMSPEC") + print("TIME (days):", [round(float(t), 1) for t in smry["TIME"]]) + print("WOPR:PROD: ", [round(v) for v in smry["WOPR:PROD"]]) + +The rate is 20000 until day 3 and 0 from then on: + +.. code-block:: text + + TIME (days): [1.0, 1.6, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0] + WOPR:PROD: [20000, 20000, 20000, 20000, 0, 0, 0, 0, 0, 0, 0] + Good to know ------------ @@ -143,13 +167,17 @@ Constructing the simulator .. warning:: - In parallel, only the **filename constructor** works: + In parallel, the ``EclipseState`` argument of the four-argument + constructor must be ``None``: .. code-block:: python - sim = BlackOilSimulator(filename="SPE1CASE1.DATA") + sim = BlackOilSimulator(deck, None, schedule, summary_config) - The four-argument form documented for serial runs — - ``BlackOilSimulator(deck, state, schedule, summary_config)`` — cannot run on - more than one rank. It aborts with + Passing an ``EclipseState`` object fails on more than one rank with ``Parallel simulator setup is incorrect as it does not use ParallelEclipseState``. + With ``None``, the simulator builds the parallel state itself from the + DATA file. The filename constructor, ``BlackOilSimulator(filename=...)``, + also works in parallel, but then the script has no access to the + ``Schedule`` the simulator uses, so well controls cannot be changed from + Python. From ce5173cb66fb47101b407fc712e63dc66d85a85d Mon Sep 17 00:00:00 2001 From: Panasun Manorost <102752624+panasun1994@users.noreply.github.com> Date: Fri, 9 Oct 2026 16:35:53 +0200 Subject: [PATCH 12/12] Update python/sphinx_docs/docs/parallel-in-python.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Håkon Hægland --- python/sphinx_docs/docs/parallel-in-python.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/python/sphinx_docs/docs/parallel-in-python.rst b/python/sphinx_docs/docs/parallel-in-python.rst index 6175f91..7477790 100644 --- a/python/sphinx_docs/docs/parallel-in-python.rst +++ b/python/sphinx_docs/docs/parallel-in-python.rst @@ -125,7 +125,12 @@ summary file once the run has finished: print("TIME (days):", [round(float(t), 1) for t in smry["TIME"]]) print("WOPR:PROD: ", [round(v) for v in smry["WOPR:PROD"]]) -The rate is 20000 until day 3 and 0 from then on: +The output depends on the deck. With the ten-year ``SPE1CASE1.DATA`` from +opm-tests, the lists are long, and the rate is 20000 until day 90 and 0 from +then on. With the ten-day version used by the opm-simulators Python tests +(`python/test_data/SPE1CASE1a +`_), +the rate is 20000 until day 3 and 0 from then on: .. code-block:: text