From: Markus Blatt <markus@dr-blatt.de>
Date: Wed, 6 Nov 2024 22:57:08 +0100
Subject: Fix Python usage in msim and its tests.

There can only be one embedded Python interpreter in a program,
as Python will never totally cleaned up if it is embedded (using
pybind11).

Unfortunately, test_msim_ACTIONX.cpp created a couple Python
interpreters and with Python 3,12 this resulted in double frees.

This commit fixes this by creating the Python interpreter in a static
shared_ptr and making the tests use that.
---
 msim/include/opm/msim/msim.hpp   | 3 +++
 msim/src/msim.cpp                | 3 ++-
 tests/msim/test_msim_ACTIONX.cpp | 5 ++---
 3 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/msim/include/opm/msim/msim.hpp b/msim/include/opm/msim/msim.hpp
index a21c576..b48bf02 100644
--- a/msim/include/opm/msim/msim.hpp
+++ b/msim/include/opm/msim/msim.hpp
@@ -5,6 +5,7 @@
 #include <opm/input/eclipse/Schedule/Action/State.hpp>
 #include <opm/input/eclipse/Schedule/Schedule.hpp>
 #include <opm/input/eclipse/Schedule/SummaryState.hpp>
+#include <opm/input/eclipse/Python/Python.hpp>
 
 #include <opm/output/data/Solution.hpp>
 #include <opm/output/data/Wells.hpp>
@@ -16,6 +17,7 @@
 #include <functional>
 #include <map>
 #include <string>
+#include <memory>
 
 namespace Opm {
 
@@ -73,6 +75,7 @@ public:
     Schedule schedule;
     Action::State action_state;
     SummaryState st;
+    static std::shared_ptr<Python> python;
 };
 
 } // namespace Opm
diff --git a/msim/src/msim.cpp b/msim/src/msim.cpp
index 9b4064b..8206dcc 100644
--- a/msim/src/msim.cpp
+++ b/msim/src/msim.cpp
@@ -71,6 +71,8 @@ namespace {
 
 namespace Opm {
 
+std::shared_ptr<Python> msim::python = std::make_shared<Python>();
+
 msim::msim(const EclipseState& state_arg, const Schedule& schedule_arg)
     : state   (state_arg)
     , schedule(schedule_arg)
@@ -86,7 +88,6 @@ void msim::run(EclipseIO& io, bool report_only)
     data::Solution sol;
     UDQState udq_state(this->schedule.getUDQConfig(0).params().undefinedValue());
     WellTestState wtest_state;
-    Python python;
 
     io.writeInitial();
     for (size_t report_step = 1; report_step < schedule.size(); report_step++) {
diff --git a/tests/msim/test_msim_ACTIONX.cpp b/tests/msim/test_msim_ACTIONX.cpp
index 6d7beb0..170d15d 100644
--- a/tests/msim/test_msim_ACTIONX.cpp
+++ b/tests/msim/test_msim_ACTIONX.cpp
@@ -63,7 +63,7 @@ struct test_data {
     explicit test_data(const Deck& deck_arg) :
         deck(deck_arg),
         state( this->deck ),
-        python( std::make_shared<Python>() ),
+        python( msim::python ),
         schedule( this->deck, this->state, this->python),
         summary_config( this->deck, this->schedule, this->state.fieldProps(), this->state.aquifer() )
     {
@@ -483,11 +483,10 @@ BOOST_AUTO_TEST_CASE(COMPDAT) {
 
 BOOST_AUTO_TEST_CASE(MSIM_EXIT_TEST_PYACTION) {
     Opm::Parser parser;
-    auto python = std::make_shared<Opm::Python>();
 
     Opm::Deck deck = parser.parseFile("msim/MSIM_PYACTION_EXIT.DATA");
     Opm::EclipseState state(deck);
-    Opm::Schedule schedule(deck, state, python);
+    Opm::Schedule schedule(deck, state, msim::python);
     Opm::SummaryConfig summary_config(deck, schedule, state.fieldProps(), state.aquifer());
 
     {
