diff --git a/ebos/eclgenericvanguard.cc b/ebos/eclgenericvanguard.cc index c86fa62c7..ef4031693 100644 --- a/ebos/eclgenericvanguard.cc +++ b/ebos/eclgenericvanguard.cc @@ -55,11 +55,11 @@ namespace Opm { double EclGenericVanguard::externalSetupTime_ = 0.0; std::unique_ptr EclGenericVanguard::externalParseContext_; std::unique_ptr EclGenericVanguard::externalErrorGuard_; -std::unique_ptr EclGenericVanguard::externalDeck_; +std::shared_ptr EclGenericVanguard::externalDeck_; bool EclGenericVanguard::externalDeckSet_ = false; -std::unique_ptr EclGenericVanguard::externalEclState_; -std::unique_ptr EclGenericVanguard::externalEclSchedule_; -std::unique_ptr EclGenericVanguard::externalEclSummaryConfig_; +std::shared_ptr EclGenericVanguard::externalEclState_; +std::shared_ptr EclGenericVanguard::externalEclSchedule_; +std::shared_ptr EclGenericVanguard::externalEclSummaryConfig_; std::unique_ptr EclGenericVanguard::externalUDQState_; std::unique_ptr EclGenericVanguard::externalActionState_; std::unique_ptr EclGenericVanguard::comm_; @@ -81,22 +81,45 @@ void EclGenericVanguard::setExternalErrorGuard(std::unique_ptr error externalErrorGuard_ = std::move(errorGuard); } +void EclGenericVanguard::setExternalSchedule(std::shared_ptr& schedule) +{ + externalEclSchedule_ = schedule; +} + void EclGenericVanguard::setExternalSchedule(std::unique_ptr schedule) { externalEclSchedule_ = std::move(schedule); } -void EclGenericVanguard::setExternalSummaryConfig(std::unique_ptr summaryConfig) +void EclGenericVanguard::setExternalSummaryConfig( + std::shared_ptr& summaryConfig) +{ + externalEclSummaryConfig_ = summaryConfig; +} + +void EclGenericVanguard::setExternalSummaryConfig( + std::unique_ptr summaryConfig) { externalEclSummaryConfig_ = std::move(summaryConfig); } +void EclGenericVanguard::setExternalDeck(std::shared_ptr& deck) +{ + externalDeck_ = deck; + externalDeckSet_ = true; +} + void EclGenericVanguard::setExternalDeck(std::unique_ptr deck) { externalDeck_ = std::move(deck); externalDeckSet_ = true; } +void EclGenericVanguard::setExternalEclState(std::shared_ptr& eclState) +{ + externalEclState_ = eclState; +} + void EclGenericVanguard::setExternalEclState(std::unique_ptr eclState) { externalEclState_ = std::move(eclState); diff --git a/ebos/eclgenericvanguard.hh b/ebos/eclgenericvanguard.hh index 9fc79a368..04a7b341d 100644 --- a/ebos/eclgenericvanguard.hh +++ b/ebos/eclgenericvanguard.hh @@ -128,12 +128,14 @@ public: * management of these two objects, i.e., they are not allowed to be deleted as long * as the simulator vanguard object is alive. */ + static void setExternalDeck(std::shared_ptr& deck); static void setExternalDeck(std::unique_ptr deck); /*! * \brief Set the Opm::EclipseState object which ought to be used when the simulator * vanguard is instantiated. */ + static void setExternalEclState(std::shared_ptr& eclState); static void setExternalEclState(std::unique_ptr eclState); /*! @@ -142,6 +144,7 @@ public: * The lifetime of this object is not managed by the vanguard, i.e., the object must * stay valid until after the vanguard gets destroyed. */ + static void setExternalSchedule(std::shared_ptr& schedule); static void setExternalSchedule(std::unique_ptr schedule); /*! @@ -150,6 +153,7 @@ public: * The lifetime of this object is not managed by the vanguard, i.e., the object must * stay valid until after the vanguard gets destroyed. */ + static void setExternalSummaryConfig(std::shared_ptr& summaryConfig); static void setExternalSummaryConfig(std::unique_ptr summaryConfig); static void setExternalUDQState(std::unique_ptr udqState); @@ -296,11 +300,14 @@ protected: static double externalSetupTime_; static std::unique_ptr externalParseContext_; static std::unique_ptr externalErrorGuard_; - static std::unique_ptr externalDeck_; + + // These variables may be owned by both Python and the simulator + static std::shared_ptr externalDeck_; + static std::shared_ptr externalEclState_; + static std::shared_ptr externalEclSchedule_; + static std::shared_ptr externalEclSummaryConfig_; + static bool externalDeckSet_; - static std::unique_ptr externalEclState_; - static std::unique_ptr externalEclSchedule_; - static std::unique_ptr externalEclSummaryConfig_; static std::unique_ptr externalUDQState_; static std::unique_ptr externalActionState_; static std::unique_ptr comm_; @@ -326,11 +333,12 @@ protected: // parser objects. std::unique_ptr parseContext_; std::unique_ptr errorGuard_; - std::unique_ptr deck_; - std::unique_ptr eclState_; - std::unique_ptr eclSchedule_; - std::unique_ptr eclSummaryConfig_; std::shared_ptr python; + // These variables may be owned by both Python and the simulator + std::shared_ptr deck_; + std::shared_ptr eclState_; + std::shared_ptr eclSchedule_; + std::shared_ptr eclSummaryConfig_; /*! \brief Information about wells in parallel * diff --git a/flow/flow_ebos_blackoil.cpp b/flow/flow_ebos_blackoil.cpp index b90da267d..ad1216292 100644 --- a/flow/flow_ebos_blackoil.cpp +++ b/flow/flow_ebos_blackoil.cpp @@ -30,21 +30,21 @@ namespace Opm { -void flowEbosBlackoilSetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, +void flowEbosBlackoilSetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, std::unique_ptr udqState, - std::unique_ptr summaryConfig) + std::shared_ptr& summaryConfig) { using TypeTag = Properties::TTag::EclFlowProblem; using Vanguard = GetPropType; Vanguard::setExternalSetupTime(setupTime); - Vanguard::setExternalDeck(std::move(deck)); - Vanguard::setExternalEclState(std::move(eclState)); - Vanguard::setExternalSchedule(std::move(schedule)); + Vanguard::setExternalDeck(deck); + Vanguard::setExternalEclState(eclState); + Vanguard::setExternalSchedule(schedule); Vanguard::setExternalUDQState(std::move(udqState)); - Vanguard::setExternalSummaryConfig(std::move(summaryConfig)); + Vanguard::setExternalSummaryConfig(summaryConfig); } std::unique_ptr> diff --git a/flow/flow_ebos_blackoil.hpp b/flow/flow_ebos_blackoil.hpp index 9331ec415..cdf9c8782 100644 --- a/flow/flow_ebos_blackoil.hpp +++ b/flow/flow_ebos_blackoil.hpp @@ -29,11 +29,11 @@ class SummaryConfig; class UDQState; namespace Properties { namespace TTag { struct EclFlowProblem; } } -void flowEbosBlackoilSetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, +void flowEbosBlackoilSetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, std::unique_ptr udqState, - std::unique_ptr summaryConfig); + std::shared_ptr& summaryConfig); int flowEbosBlackoilMain(int argc, char** argv, bool outputCout, bool outputFiles); diff --git a/flow/flow_ebos_brine.cpp b/flow/flow_ebos_brine.cpp index 9ffc85b47..6df9f86f7 100644 --- a/flow/flow_ebos_brine.cpp +++ b/flow/flow_ebos_brine.cpp @@ -43,19 +43,19 @@ struct EnableBrine { }} namespace Opm { -void flowEbosBrineSetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, - std::unique_ptr summaryConfig) +void flowEbosBrineSetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, + std::shared_ptr& summaryConfig) { using TypeTag = Properties::TTag::EclFlowBrineProblem; using Vanguard = GetPropType; Vanguard::setExternalSetupTime(setupTime); - Vanguard::setExternalDeck(std::move(deck)); - Vanguard::setExternalEclState(std::move(eclState)); - Vanguard::setExternalSchedule(std::move(schedule)); - Vanguard::setExternalSummaryConfig(std::move(summaryConfig)); + Vanguard::setExternalDeck(deck); + Vanguard::setExternalEclState(eclState); + Vanguard::setExternalSchedule(schedule); + Vanguard::setExternalSummaryConfig(summaryConfig); } diff --git a/flow/flow_ebos_brine.hpp b/flow/flow_ebos_brine.hpp index a117ba341..4dd2c1f4c 100644 --- a/flow/flow_ebos_brine.hpp +++ b/flow/flow_ebos_brine.hpp @@ -26,10 +26,10 @@ class EclipseState; class Schedule; class SummaryConfig; -void flowEbosBrineSetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, - std::unique_ptr summaryConfig); +void flowEbosBrineSetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, + std::shared_ptr& summaryConfig); int flowEbosBrineMain(int argc, char** argv, bool outputCout, bool outputFiles); } diff --git a/flow/flow_ebos_energy.cpp b/flow/flow_ebos_energy.cpp index 13f41eda5..ec88c161e 100644 --- a/flow/flow_ebos_energy.cpp +++ b/flow/flow_ebos_energy.cpp @@ -43,19 +43,19 @@ struct EnableEnergy { }} namespace Opm { -void flowEbosEnergySetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, - std::unique_ptr summaryConfig) +void flowEbosEnergySetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, + std::shared_ptr& summaryConfig) { using TypeTag = Properties::TTag::EclFlowEnergyProblem; using Vanguard = GetPropType; Vanguard::setExternalSetupTime(setupTime); - Vanguard::setExternalDeck(std::move(deck)); - Vanguard::setExternalEclState(std::move(eclState)); - Vanguard::setExternalSchedule(std::move(schedule)); - Vanguard::setExternalSummaryConfig(std::move(summaryConfig)); + Vanguard::setExternalDeck(deck); + Vanguard::setExternalEclState(eclState); + Vanguard::setExternalSchedule(schedule); + Vanguard::setExternalSummaryConfig(summaryConfig); } // ----------------- Main program ----------------- diff --git a/flow/flow_ebos_energy.hpp b/flow/flow_ebos_energy.hpp index bbd05f20b..c916f202c 100644 --- a/flow/flow_ebos_energy.hpp +++ b/flow/flow_ebos_energy.hpp @@ -26,10 +26,10 @@ class EclipseState; class Schedule; class SummaryConfig; -void flowEbosEnergySetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, - std::unique_ptr summaryConfig); +void flowEbosEnergySetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, + std::shared_ptr& summaryConfig); int flowEbosEnergyMain(int argc, char** argv, bool outputCout, bool outputFiles); } diff --git a/flow/flow_ebos_extbo.cpp b/flow/flow_ebos_extbo.cpp index a759c6929..f1330f948 100644 --- a/flow/flow_ebos_extbo.cpp +++ b/flow/flow_ebos_extbo.cpp @@ -43,19 +43,19 @@ struct EnableExtbo { }} namespace Opm { -void flowEbosExtboSetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, - std::unique_ptr summaryConfig) +void flowEbosExtboSetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, + std::shared_ptr& summaryConfig) { using TypeTag = Properties::TTag::EclFlowExtboProblem; using Vanguard = GetPropType; Vanguard::setExternalSetupTime(setupTime); - Vanguard::setExternalDeck(std::move(deck)); - Vanguard::setExternalEclState(std::move(eclState)); - Vanguard::setExternalSchedule(std::move(schedule)); - Vanguard::setExternalSummaryConfig(std::move(summaryConfig)); + Vanguard::setExternalDeck(deck); + Vanguard::setExternalEclState(eclState); + Vanguard::setExternalSchedule(schedule); + Vanguard::setExternalSummaryConfig(summaryConfig); } // ----------------- Main program ----------------- diff --git a/flow/flow_ebos_extbo.hpp b/flow/flow_ebos_extbo.hpp index a36189285..508d742c5 100644 --- a/flow/flow_ebos_extbo.hpp +++ b/flow/flow_ebos_extbo.hpp @@ -26,10 +26,10 @@ class EclipseState; class Schedule; class SummaryConfig; -void flowEbosExtboSetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, - std::unique_ptr summaryConfig); +void flowEbosExtboSetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, + std::shared_ptr& summaryConfig); int flowEbosExtboMain(int argc, char** argv, bool outputCout, bool outputFiles); } diff --git a/flow/flow_ebos_foam.cpp b/flow/flow_ebos_foam.cpp index 6d40ca6da..ba4209731 100644 --- a/flow/flow_ebos_foam.cpp +++ b/flow/flow_ebos_foam.cpp @@ -43,19 +43,19 @@ struct EnableFoam { }} namespace Opm { -void flowEbosFoamSetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, - std::unique_ptr summaryConfig) +void flowEbosFoamSetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, + std::shared_ptr& summaryConfig) { using TypeTag = Properties::TTag::EclFlowFoamProblem; using Vanguard = GetPropType; Vanguard::setExternalSetupTime(setupTime); - Vanguard::setExternalDeck(std::move(deck)); - Vanguard::setExternalEclState(std::move(eclState)); - Vanguard::setExternalSchedule(std::move(schedule)); - Vanguard::setExternalSummaryConfig(std::move(summaryConfig)); + Vanguard::setExternalDeck(deck); + Vanguard::setExternalEclState(eclState); + Vanguard::setExternalSchedule(schedule); + Vanguard::setExternalSummaryConfig(summaryConfig); } diff --git a/flow/flow_ebos_foam.hpp b/flow/flow_ebos_foam.hpp index 33b036b59..453d1bfc9 100644 --- a/flow/flow_ebos_foam.hpp +++ b/flow/flow_ebos_foam.hpp @@ -26,10 +26,10 @@ class EclipseState; class Schedule; class SummaryConfig; -void flowEbosFoamSetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, - std::unique_ptr summaryConfig); +void flowEbosFoamSetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, + std::shared_ptr& summaryConfig); int flowEbosFoamMain(int argc, char** argv, bool outputCout, bool outputFiles); } diff --git a/flow/flow_ebos_gasoil.cpp b/flow/flow_ebos_gasoil.cpp index 69f4e9c37..d649d1960 100644 --- a/flow/flow_ebos_gasoil.cpp +++ b/flow/flow_ebos_gasoil.cpp @@ -63,19 +63,19 @@ public: }} namespace Opm { -void flowEbosGasOilSetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, - std::unique_ptr summaryConfig) +void flowEbosGasOilSetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, + std::shared_ptr& summaryConfig) { using TypeTag = Properties::TTag::EclFlowGasOilProblem; using Vanguard = GetPropType; Vanguard::setExternalSetupTime(setupTime); - Vanguard::setExternalDeck(std::move(deck)); - Vanguard::setExternalEclState(std::move(eclState)); - Vanguard::setExternalSchedule(std::move(schedule)); - Vanguard::setExternalSummaryConfig(std::move(summaryConfig)); + Vanguard::setExternalDeck(deck); + Vanguard::setExternalEclState(eclState); + Vanguard::setExternalSchedule(schedule); + Vanguard::setExternalSummaryConfig(summaryConfig); } diff --git a/flow/flow_ebos_gasoil.hpp b/flow/flow_ebos_gasoil.hpp index a30b94f0b..f05fcda59 100644 --- a/flow/flow_ebos_gasoil.hpp +++ b/flow/flow_ebos_gasoil.hpp @@ -26,10 +26,10 @@ class EclipseState; class Schedule; class SummaryConfig; -void flowEbosGasOilSetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, - std::unique_ptr summaryConfig); +void flowEbosGasOilSetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, + std::shared_ptr& summaryConfig); int flowEbosGasOilMain(int argc, char** argv, bool outputCout, bool outputFiles); } diff --git a/flow/flow_ebos_gaswater.cpp b/flow/flow_ebos_gaswater.cpp index c76500db8..4a3c61982 100644 --- a/flow/flow_ebos_gaswater.cpp +++ b/flow/flow_ebos_gaswater.cpp @@ -66,19 +66,19 @@ public: }} namespace Opm { -void flowEbosGasWaterSetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, - std::unique_ptr summaryConfig) +void flowEbosGasWaterSetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, + std::shared_ptr& summaryConfig) { using TypeTag = Properties::TTag::EclFlowGasWaterProblem; using Vanguard = GetPropType; Vanguard::setExternalSetupTime(setupTime); - Vanguard::setExternalDeck(std::move(deck)); - Vanguard::setExternalEclState(std::move(eclState)); - Vanguard::setExternalSchedule(std::move(schedule)); - Vanguard::setExternalSummaryConfig(std::move(summaryConfig)); + Vanguard::setExternalDeck(deck); + Vanguard::setExternalEclState(eclState); + Vanguard::setExternalSchedule(schedule); + Vanguard::setExternalSummaryConfig(summaryConfig); } diff --git a/flow/flow_ebos_gaswater.hpp b/flow/flow_ebos_gaswater.hpp index 1db517a1e..22960c487 100644 --- a/flow/flow_ebos_gaswater.hpp +++ b/flow/flow_ebos_gaswater.hpp @@ -26,10 +26,10 @@ class EclipseState; class Schedule; class SummaryConfig; -void flowEbosGasWaterSetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, - std::unique_ptr summaryConfig); +void flowEbosGasWaterSetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, + std::shared_ptr& summaryConfig); int flowEbosGasWaterMain(int argc, char** argv, bool outputCout, bool outputFiles); } diff --git a/flow/flow_ebos_oilwater.cpp b/flow/flow_ebos_oilwater.cpp index 557601a43..f7cfcde30 100644 --- a/flow/flow_ebos_oilwater.cpp +++ b/flow/flow_ebos_oilwater.cpp @@ -63,19 +63,19 @@ public: }} namespace Opm { -void flowEbosOilWaterSetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, - std::unique_ptr summaryConfig) +void flowEbosOilWaterSetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, + std::shared_ptr& summaryConfig) { using TypeTag = Properties::TTag::EclFlowOilWaterProblem; using Vanguard = GetPropType; Vanguard::setExternalSetupTime(setupTime); - Vanguard::setExternalDeck(std::move(deck)); - Vanguard::setExternalEclState(std::move(eclState)); - Vanguard::setExternalSchedule(std::move(schedule)); - Vanguard::setExternalSummaryConfig(std::move(summaryConfig)); + Vanguard::setExternalDeck(deck); + Vanguard::setExternalEclState(eclState); + Vanguard::setExternalSchedule(schedule); + Vanguard::setExternalSummaryConfig(summaryConfig); } // ----------------- Main program ----------------- diff --git a/flow/flow_ebos_oilwater.hpp b/flow/flow_ebos_oilwater.hpp index ea4c940b2..b81176377 100644 --- a/flow/flow_ebos_oilwater.hpp +++ b/flow/flow_ebos_oilwater.hpp @@ -26,10 +26,10 @@ class EclipseState; class Schedule; class SummaryConfig; -void flowEbosOilWaterSetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, - std::unique_ptr summaryConfig); +void flowEbosOilWaterSetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, + std::shared_ptr& summaryConfig); int flowEbosOilWaterMain(int argc, char** argv, bool outputCout, bool outputFiles); } diff --git a/flow/flow_ebos_oilwater_brine.cpp b/flow/flow_ebos_oilwater_brine.cpp index 759a0f610..da21c804b 100644 --- a/flow/flow_ebos_oilwater_brine.cpp +++ b/flow/flow_ebos_oilwater_brine.cpp @@ -66,19 +66,19 @@ public: }} namespace Opm { -void flowEbosOilWaterBrineSetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, - std::unique_ptr summaryConfig) +void flowEbosOilWaterBrineSetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, + std::shared_ptr& summaryConfig) { using TypeTag = Properties::TTag::EclFlowOilWaterBrineProblem; using Vanguard = GetPropType; Vanguard::setExternalSetupTime(setupTime); - Vanguard::setExternalDeck(std::move(deck)); - Vanguard::setExternalEclState(std::move(eclState)); - Vanguard::setExternalSchedule(std::move(schedule)); - Vanguard::setExternalSummaryConfig(std::move(summaryConfig)); + Vanguard::setExternalDeck(deck); + Vanguard::setExternalEclState(eclState); + Vanguard::setExternalSchedule(schedule); + Vanguard::setExternalSummaryConfig(summaryConfig); } // ----------------- Main program ----------------- diff --git a/flow/flow_ebos_oilwater_brine.hpp b/flow/flow_ebos_oilwater_brine.hpp index 7a6c919af..56f358cbf 100644 --- a/flow/flow_ebos_oilwater_brine.hpp +++ b/flow/flow_ebos_oilwater_brine.hpp @@ -26,10 +26,10 @@ class EclipseState; class Schedule; class SummaryConfig; -void flowEbosOilWaterBrineSetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, - std::unique_ptr summaryConfig); +void flowEbosOilWaterBrineSetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, + std::shared_ptr& summaryConfig); int flowEbosOilWaterBrineMain(int argc, char** argv, bool outputCout, bool outputFiles); } diff --git a/flow/flow_ebos_oilwater_polymer.cpp b/flow/flow_ebos_oilwater_polymer.cpp index e25508776..e2d07bc20 100644 --- a/flow/flow_ebos_oilwater_polymer.cpp +++ b/flow/flow_ebos_oilwater_polymer.cpp @@ -66,19 +66,19 @@ public: }} namespace Opm { -void flowEbosOilWaterPolymerSetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, - std::unique_ptr summaryConfig) +void flowEbosOilWaterPolymerSetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, + std::shared_ptr& summaryConfig) { using TypeTag = Properties::TTag::EclFlowOilWaterPolymerProblem; using Vanguard = GetPropType; Vanguard::setExternalSetupTime(setupTime); - Vanguard::setExternalDeck(std::move(deck)); - Vanguard::setExternalEclState(std::move(eclState)); - Vanguard::setExternalSchedule(std::move(schedule)); - Vanguard::setExternalSummaryConfig(std::move(summaryConfig)); + Vanguard::setExternalDeck(deck); + Vanguard::setExternalEclState(eclState); + Vanguard::setExternalSchedule(schedule); + Vanguard::setExternalSummaryConfig(summaryConfig); } // ----------------- Main program ----------------- diff --git a/flow/flow_ebos_oilwater_polymer.hpp b/flow/flow_ebos_oilwater_polymer.hpp index d82dc4df3..778ab27c7 100644 --- a/flow/flow_ebos_oilwater_polymer.hpp +++ b/flow/flow_ebos_oilwater_polymer.hpp @@ -26,10 +26,10 @@ class EclipseState; class Schedule; class SummaryConfig; -void flowEbosOilWaterPolymerSetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, - std::unique_ptr summaryConfig); +void flowEbosOilWaterPolymerSetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, + std::shared_ptr& summaryConfig); int flowEbosOilWaterPolymerMain(int argc, char** argv, bool outputCout, bool outputFiles); } diff --git a/flow/flow_ebos_polymer.cpp b/flow/flow_ebos_polymer.cpp index ef4eab9b7..c03c7f873 100644 --- a/flow/flow_ebos_polymer.cpp +++ b/flow/flow_ebos_polymer.cpp @@ -43,19 +43,19 @@ struct EnablePolymer { }} namespace Opm { -void flowEbosPolymerSetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, - std::unique_ptr summaryConfig) +void flowEbosPolymerSetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, + std::shared_ptr& summaryConfig) { using TypeTag = Properties::TTag::EclFlowPolymerProblem; using Vanguard = GetPropType; Vanguard::setExternalSetupTime(setupTime); - Vanguard::setExternalDeck(std::move(deck)); - Vanguard::setExternalEclState(std::move(eclState)); - Vanguard::setExternalSchedule(std::move(schedule)); - Vanguard::setExternalSummaryConfig(std::move(summaryConfig)); + Vanguard::setExternalDeck(deck); + Vanguard::setExternalEclState(eclState); + Vanguard::setExternalSchedule(schedule); + Vanguard::setExternalSummaryConfig(summaryConfig); } // ----------------- Main program ----------------- diff --git a/flow/flow_ebos_polymer.hpp b/flow/flow_ebos_polymer.hpp index a007c6569..9709edb28 100644 --- a/flow/flow_ebos_polymer.hpp +++ b/flow/flow_ebos_polymer.hpp @@ -26,10 +26,10 @@ class EclipseState; class Schedule; class SummaryConfig; -void flowEbosPolymerSetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, - std::unique_ptr summaryConfig); +void flowEbosPolymerSetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, + std::shared_ptr& summaryConfig); int flowEbosPolymerMain(int argc, char** argv, bool outputCout, bool outputFiles); } diff --git a/flow/flow_ebos_solvent.cpp b/flow/flow_ebos_solvent.cpp index 329d3a87b..7f4ebd5bf 100644 --- a/flow/flow_ebos_solvent.cpp +++ b/flow/flow_ebos_solvent.cpp @@ -43,19 +43,19 @@ struct EnableSolvent { }} namespace Opm { -void flowEbosSolventSetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, - std::unique_ptr summaryConfig) +void flowEbosSolventSetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, + std::shared_ptr& summaryConfig) { using TypeTag = Properties::TTag::EclFlowSolventProblem; using Vanguard = GetPropType; Vanguard::setExternalSetupTime(setupTime); - Vanguard::setExternalDeck(std::move(deck)); - Vanguard::setExternalEclState(std::move(eclState)); - Vanguard::setExternalSchedule(std::move(schedule)); - Vanguard::setExternalSummaryConfig(std::move(summaryConfig)); + Vanguard::setExternalDeck(deck); + Vanguard::setExternalEclState(eclState); + Vanguard::setExternalSchedule(schedule); + Vanguard::setExternalSummaryConfig(summaryConfig); } diff --git a/flow/flow_ebos_solvent.hpp b/flow/flow_ebos_solvent.hpp index 9662e774e..7290d49de 100644 --- a/flow/flow_ebos_solvent.hpp +++ b/flow/flow_ebos_solvent.hpp @@ -26,10 +26,10 @@ class EclipseState; class Schedule; class SummaryConfig; -void flowEbosSolventSetDeck(double setupTime, std::unique_ptr deck, - std::unique_ptr eclState, - std::unique_ptr schedule, - std::unique_ptr summaryConfig); +void flowEbosSolventSetDeck(double setupTime, std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, + std::shared_ptr& summaryConfig); int flowEbosSolventMain(int argc, char** argv, bool outoutCout, bool outputFiles); } diff --git a/opm/simulators/flow/Main.hpp b/opm/simulators/flow/Main.hpp index 01ab24fd0..cea6a1df5 100644 --- a/opm/simulators/flow/Main.hpp +++ b/opm/simulators/flow/Main.hpp @@ -82,13 +82,16 @@ struct FlowEarlyBird { namespace Opm { template - void flowEbosSetDeck(std::unique_ptr deck, std::unique_ptr eclState, std::unique_ptr schedule, std::unique_ptr summaryConfig) + void flowEbosSetDeck(std::shared_ptr& deck, + std::shared_ptr& eclState, + std::shared_ptr& schedule, + std::shared_ptr summaryConfig) { using Vanguard = GetPropType; - Vanguard::setExternalDeck(std::move(deck)); - Vanguard::setExternalEclState(std::move(eclState)); - Vanguard::setExternalSchedule(std::move(schedule)); - Vanguard::setExternalSummaryConfig(std::move(summaryConfig)); + Vanguard::setExternalDeck(deck); + Vanguard::setExternalEclState(eclState); + Vanguard::setExternalSchedule(schedule); + Vanguard::setExternalSummaryConfig(summaryConfig); } // ----------------- Main program ----------------- @@ -123,31 +126,27 @@ namespace Opm public: Main(int argc, char** argv) : argc_(argc), argv_(argv) { initMPI(); } + // This constructor can be called from Python Main(const std::string &filename) { - deckFilename_.assign(filename); - flowProgName_.assign("flow"); - argc_ = 2; - saveArgs_[0] = const_cast(flowProgName_.c_str()); - saveArgs_[1] = const_cast(deckFilename_.c_str()); - argv_ = saveArgs_; + setArgvArgc_(filename); initMPI(); } - Main(int argc, - char** argv, - std::unique_ptr deck, - std::unique_ptr eclipseState, - std::unique_ptr schedule, - std::unique_ptr summaryConfig) - : argc_(argc) - , argv_(argv) - , deck_(std::move(deck)) - , eclipseState_(std::move(eclipseState)) - , schedule_(std::move(schedule)) - , summaryConfig_(std::move(summaryConfig)) + // This constructor can be called from Python when Python has already + // parsed a deck + Main( + std::shared_ptr& deck, + std::shared_ptr& eclipseState, + std::shared_ptr& schedule, + std::shared_ptr& summaryConfig) + : deck_{deck} + , eclipseState_{eclipseState} + , schedule_{schedule} + , summaryConfig_{summaryConfig} { - initMPI(); + setArgvArgc_(deck->getDataFile()); + initMPI(); } ~Main() @@ -159,6 +158,16 @@ namespace Opm #endif } + void setArgvArgc_(const std::string& filename) + { + deckFilename_.assign(filename); + flowProgName_.assign("flow"); + argc_ = 2; + saveArgs_[0] = const_cast(flowProgName_.c_str()); + saveArgs_[1] = const_cast(deckFilename_.c_str()); + argv_ = saveArgs_; + } + void initMPI() { #if HAVE_DUNE_FEM @@ -202,11 +211,11 @@ namespace Opm // case. E.g. check that number of phases == 3 flowEbosBlackoilSetDeck( setupTime_, - std::move(deck_), - std::move(eclipseState_), - std::move(schedule_), + deck_, + eclipseState_, + schedule_, std::move(udqState_), - std::move(summaryConfig_)); + summaryConfig_); return flowEbosBlackoilMainInit( argc_, argv_, outputCout_, outputFiles_); } else { @@ -230,18 +239,20 @@ namespace Opm else if( phases.size() == 2 ) { // oil-gas if (phases.active( Phase::OIL ) && phases.active( Phase::GAS )) { - flowEbosGasOilSetDeck(setupTime_, std::move(deck_), std::move(eclipseState_), - std::move(schedule_), std::move(summaryConfig_)); + flowEbosGasOilSetDeck( + setupTime_, deck_, eclipseState_, schedule_, summaryConfig_); return flowEbosGasOilMain(argc_, argv_, outputCout_, outputFiles_); } // oil-water else if ( phases.active( Phase::OIL ) && phases.active( Phase::WATER ) ) { - flowEbosOilWaterSetDeck(setupTime_, std::move(deck_), std::move(eclipseState_), std::move(schedule_), std::move(summaryConfig_)); + flowEbosOilWaterSetDeck( + setupTime_, deck_, eclipseState_, schedule_, summaryConfig_); return flowEbosOilWaterMain(argc_, argv_, outputCout_, outputFiles_); } // gas-water else if ( phases.active( Phase::GAS ) && phases.active( Phase::WATER ) ) { - flowEbosGasWaterSetDeck(setupTime_, std::move(deck_), std::move(eclipseState_), std::move(schedule_), std::move(summaryConfig_)); + flowEbosGasWaterSetDeck( + setupTime_, deck_, eclipseState_, schedule_, summaryConfig_); return flowEbosGasWaterMain(argc_, argv_, outputCout_, outputFiles_); } else { @@ -268,25 +279,19 @@ namespace Opm } if ( phases.size() == 3 ) { // oil water polymer case - flowEbosOilWaterPolymerSetDeck(setupTime_, std::move(deck_), - std::move(eclipseState_), - std::move(schedule_), - std::move(summaryConfig_)); + flowEbosOilWaterPolymerSetDeck( + setupTime_, deck_, eclipseState_, schedule_, summaryConfig_); return flowEbosOilWaterPolymerMain(argc_, argv_, outputCout_, outputFiles_); } else { - flowEbosPolymerSetDeck(setupTime_, std::move(deck_), - std::move(eclipseState_), - std::move(schedule_), - std::move(summaryConfig_)); + flowEbosPolymerSetDeck( + setupTime_, deck_, eclipseState_, schedule_, summaryConfig_); return flowEbosPolymerMain(argc_, argv_, outputCout_, outputFiles_); } } // Foam case else if ( phases.active( Phase::FOAM ) ) { - flowEbosFoamSetDeck(setupTime_, std::move(deck_), - std::move(eclipseState_), - std::move(schedule_), - std::move(summaryConfig_)); + flowEbosFoamSetDeck( + setupTime_, deck_, eclipseState_, schedule_, summaryConfig_); return flowEbosFoamMain(argc_, argv_, outputCout_, outputFiles_); } // Brine case @@ -298,51 +303,43 @@ namespace Opm return EXIT_FAILURE; } if ( phases.size() == 3 ) { // oil water brine case - flowEbosOilWaterBrineSetDeck(setupTime_, std::move(deck_), - std::move(eclipseState_), - std::move(schedule_), - std::move(summaryConfig_)); + flowEbosOilWaterBrineSetDeck( + setupTime_, deck_, eclipseState_, schedule_, summaryConfig_); return flowEbosOilWaterBrineMain(argc_, argv_, outputCout_, outputFiles_); } else { - flowEbosBrineSetDeck(setupTime_, std::move(deck_), - std::move(eclipseState_), - std::move(schedule_), - std::move(summaryConfig_)); + flowEbosBrineSetDeck( + setupTime_, deck_, eclipseState_, schedule_, summaryConfig_); return flowEbosBrineMain(argc_, argv_, outputCout_, outputFiles_); } } // Solvent case else if ( phases.active( Phase::SOLVENT ) ) { - flowEbosSolventSetDeck(setupTime_, std::move(deck_), - std::move(eclipseState_), - std::move(schedule_), - std::move(summaryConfig_)); + flowEbosSolventSetDeck( + setupTime_, deck_, eclipseState_, schedule_, summaryConfig_); return flowEbosSolventMain(argc_, argv_, outputCout_, outputFiles_); } // Extended BO case else if ( phases.active( Phase::ZFRACTION ) ) { - flowEbosExtboSetDeck(setupTime_, std::move(deck_), - std::move(eclipseState_), - std::move(schedule_), - std::move(summaryConfig_)); + flowEbosExtboSetDeck( + setupTime_, deck_, eclipseState_, schedule_, summaryConfig_); return flowEbosExtboMain(argc_, argv_, outputCout_, outputFiles_); } // Energy case else if (eclipseState_->getSimulationConfig().isThermal()) { - flowEbosEnergySetDeck(setupTime_, std::move(deck_), - std::move(eclipseState_), - std::move(schedule_), - std::move(summaryConfig_)); + flowEbosEnergySetDeck( + setupTime_, deck_, eclipseState_, schedule_, summaryConfig_); return flowEbosEnergyMain(argc_, argv_, outputCout_, outputFiles_); } #endif // FLOW_BLACKOIL_ONLY // Blackoil case else if( phases.size() == 3 ) { - flowEbosBlackoilSetDeck(setupTime_, std::move(deck_), - std::move(eclipseState_), - std::move(schedule_), - std::move(udqState_), - std::move(summaryConfig_)); + flowEbosBlackoilSetDeck( + setupTime_, + deck_, + eclipseState_, + schedule_, + std::move(udqState_), + summaryConfig_); return flowEbosBlackoilMain(argc_, argv_, outputCout_, outputFiles_); } else { @@ -355,10 +352,8 @@ namespace Opm template int dispatchStatic_() { - flowEbosSetDeck(std::move(deck_), - std::move(eclipseState_), - std::move(schedule_), - std::move(summaryConfig_)); + flowEbosSetDeck( + deck_, eclipseState_, schedule_, summaryConfig_); return flowEbosMain(argc_, argv_, outputCout_, outputFiles_); } @@ -549,12 +544,14 @@ namespace Opm std::string deckFilename_; std::string flowProgName_; char *saveArgs_[2]; - std::unique_ptr deck_; - std::unique_ptr eclipseState_; - std::unique_ptr schedule_; std::unique_ptr udqState_; std::unique_ptr actionState_; - std::unique_ptr summaryConfig_; + + // These variables may be owned by both Python and the simulator + std::shared_ptr deck_; + std::shared_ptr eclipseState_; + std::shared_ptr schedule_; + std::shared_ptr summaryConfig_; }; } // namespace Opm diff --git a/opm/simulators/flow/python/PyBlackOilSimulator.hpp b/opm/simulators/flow/python/PyBlackOilSimulator.hpp new file mode 100644 index 000000000..0c7ffd6bc --- /dev/null +++ b/opm/simulators/flow/python/PyBlackOilSimulator.hpp @@ -0,0 +1,76 @@ +/* + Copyright 2020 Equinor ASA. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . +*/ + +#ifndef OPM_PY_BLACKOIL_SIMULATOR_HEADER_INCLUDED +#define OPM_PY_BLACKOIL_SIMULATOR_HEADER_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Opm::Pybind { +class PyBlackOilSimulator +{ + using TypeTag = Opm::Properties::TTag::EclFlowProblem; +private: + using Simulator = Opm::GetPropType; + +public: + PyBlackOilSimulator( const std::string& deckFilename); + PyBlackOilSimulator( + std::shared_ptr& deck, + std::shared_ptr& state, + std::shared_ptr& schedule, + std::shared_ptr& summary_config); + py::array_t getPorosity(); + int run(); + void setPorosity( + py::array_t array); + int step(); + int stepInit(); + int stepCleanup(); + const Opm::FlowMainEbos& getFlowMainEbos() const; + +private: + const std::string deckFilename_; + bool hasRunInit_ = false; + bool hasRunCleanup_ = false; + + // This *must* be declared before other pointers + // to simulator objects. This in order to deinitialize + // MPI at the correct time (ie after the other objects). + std::unique_ptr main_; + + std::unique_ptr> mainEbos_; + Simulator *ebosSimulator_; + std::unique_ptr> materialState_; + std::shared_ptr deck_; + std::shared_ptr eclipse_state_; + std::shared_ptr schedule_; + std::shared_ptr summary_config_; +}; + +} // namespace Opm::Pybind +#endif // OPM_PY_BLACKOIL_SIMULATOR_HEADER_INCLUDED diff --git a/opm/simulators/flow/python/Pybind11Exporter.hpp b/opm/simulators/flow/python/Pybind11Exporter.hpp new file mode 100644 index 000000000..1feedd305 --- /dev/null +++ b/opm/simulators/flow/python/Pybind11Exporter.hpp @@ -0,0 +1,15 @@ +#ifndef OPM_PYBIND11_EXPORTER_HEADER_INCLUDED +#define OPM_PYBIND11_EXPORTER_HEADER_INCLUDED + +#include +#include +//#include + +namespace py = pybind11; + +namespace Opm::Pybind { + void export_all(py::module& m); + void export_PyBlackOilSimulator(py::module& m); +} + +#endif //OPM_PYBIND11_EXPORTER_HEADER_INCLUDED diff --git a/opm/simulators/utils/readDeck.cpp b/opm/simulators/utils/readDeck.cpp index 476936f25..958c0e31b 100644 --- a/opm/simulators/utils/readDeck.cpp +++ b/opm/simulators/utils/readDeck.cpp @@ -191,8 +191,8 @@ void setupMessageLimiter(const Opm::MessageLimits msgLimits, const std::string& } -void readDeck(int rank, std::string& deckFilename, std::unique_ptr& deck, std::unique_ptr& eclipseState, - std::unique_ptr& schedule, std::unique_ptr& udqState, std::unique_ptr& actionState, std::unique_ptr& summaryConfig, +void readDeck(int rank, std::string& deckFilename, std::shared_ptr& deck, std::shared_ptr& eclipseState, + std::shared_ptr& schedule, std::unique_ptr& udqState, std::unique_ptr& actionState, std::shared_ptr& summaryConfig, std::unique_ptr errorGuard, std::shared_ptr& python, std::unique_ptr parseContext, bool initFromRestart, bool checkDeck, const std::optional& outputInterval) { diff --git a/opm/simulators/utils/readDeck.hpp b/opm/simulators/utils/readDeck.hpp index be200431a..2e0acbe06 100644 --- a/opm/simulators/utils/readDeck.hpp +++ b/opm/simulators/utils/readDeck.hpp @@ -57,8 +57,8 @@ FileOutputMode setupLogging(int mpi_rank_, const std::string& deck_filename, con /// \brief Reads the deck and creates all necessary objects if needed /// /// If pointers already contains objects then they are used otherwise they are created and can be used outside later. -void readDeck(int rank, std::string& deckFilename, std::unique_ptr& deck, std::unique_ptr& eclipseState, - std::unique_ptr& schedule, std::unique_ptr& udqState, std::unique_ptr& actionState, std::unique_ptr& summaryConfig, +void readDeck(int rank, std::string& deckFilename, std::shared_ptr& deck, std::shared_ptr& eclipseState, + std::shared_ptr& schedule, std::unique_ptr& udqState, std::unique_ptr& actionState, std::shared_ptr& summaryConfig, std::unique_ptr errorGuard, std::shared_ptr& python, std::unique_ptr parseContext, bool initFromRestart, bool checkDeck, const std::optional& outputInterval); } // end namespace Opm diff --git a/python/simulators/CMakeLists.txt b/python/simulators/CMakeLists.txt index 40237a4e6..7a3545d05 100644 --- a/python/simulators/CMakeLists.txt +++ b/python/simulators/CMakeLists.txt @@ -1,11 +1,18 @@ # NOTE: we assume that add_subdirectory( pybind11 ) is called from the -# parent folder's CMakeLists.txt before this CMakeLists.txt is loaded. -# Therefore, pybind11's CMakeLists.txt has already run -# find_package(PYTHON) to define variables like -# ${PYTHON_EXECUTABLE} +# parent folder's CMakeLists.txt before this CMakeLists.txt is loaded. +# Therefore, pybind11's CMakeLists.txt has already run +# find_package(PYTHON) to define variables like ${PYTHON_EXECUTABLE} # - -pybind11_add_module(simulators simulators.cpp ${PYBIND11_SYSTEM}) +# NOTE: The variable ${PYBIND11_SYSTEM} is set in python/CMakeLists.txt +# to the value "SYSTEM" or unset, depending on the current version of Pybind11. +# The value is then forwarded to target_include_directories(), see +# +# https://cmake.org/cmake/help/latest/command/target_include_directories.html +# https://pybind11.readthedocs.io/en/stable/compiling.html +# +pybind11_add_module(simulators ${PYBIND11_SYSTEM} + PyBlackOilSimulator.cpp + Pybind11Exporter.cpp) set_target_properties( simulators PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/python/opm2 ) @@ -30,9 +37,19 @@ if(OPM_ENABLE_PYTHON_TESTS) if(Python3_EXECUTABLE AND NOT PYTHON_EXECUTABLE) set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE}) endif() - add_test(NAME python_tests + set(PYTHON_PATH ${PROJECT_BINARY_DIR}/python:${opm-common_DIR}/python:$ENV{PYTHONPATH}) + # NOTE: See comment in test_basic.py for the reason why we are + # splitting the python tests into multiple add_test() tests instead + # of having a single "python -m unittest" test call that will run all + # the tests in the "test" sub directory. + add_test(NAME python_basic WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/python COMMAND ${CMAKE_COMMAND} - -E env PYTHONPATH=${PROJECT_BINARY_DIR}/python:$ENV{PYTHONPATH} - ${PYTHON_EXECUTABLE} -m unittest ) + -E env PYTHONPATH=${PYTHON_PATH} ${PYTHON_EXECUTABLE} + -m unittest test/test_basic.py) + add_test(NAME python_schedule + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/python + COMMAND ${CMAKE_COMMAND} + -E env PYTHONPATH=${PYTHON_PATH} ${PYTHON_EXECUTABLE} + -m unittest test/test_schedule.py) endif() diff --git a/python/simulators/PyBlackOilSimulator.cpp b/python/simulators/PyBlackOilSimulator.cpp new file mode 100644 index 000000000..e44b6ca51 --- /dev/null +++ b/python/simulators/PyBlackOilSimulator.cpp @@ -0,0 +1,162 @@ +/* + Copyright 2020 Equinor ASA. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . +*/ + +#include "config.h" +#include +#include +#include +#include +#define FLOW_BLACKOIL_ONLY +#include +#include +// NOTE: EXIT_SUCCESS, EXIT_FAILURE is defined in cstdlib +#include +#include +#include +#include + +namespace py = pybind11; + +namespace Opm::Pybind { +PyBlackOilSimulator::PyBlackOilSimulator( const std::string &deckFilename) + : deckFilename_{deckFilename} +{ +} + +PyBlackOilSimulator::PyBlackOilSimulator( + std::shared_ptr& deck, + std::shared_ptr& state, + std::shared_ptr& schedule, + std::shared_ptr& summary_config +) + : deck_{deck} + , eclipse_state_{state} + , schedule_{schedule} + , summary_config_{summary_config} +{ +} + +const Opm::FlowMainEbos& + PyBlackOilSimulator::getFlowMainEbos() const +{ + if (this->mainEbos_) { + return *(this->mainEbos_.get()); + } + else { + throw std::runtime_error("BlackOilSimulator not initialized: " + "Cannot get reference to FlowMainEbos object" ); + } +} + +py::array_t PyBlackOilSimulator::getPorosity() +{ + std::size_t len; + auto array = materialState_->getPorosity(&len); + return py::array(len, array.get()); +} + +int PyBlackOilSimulator::run() +{ + auto mainObject = Opm::Main( deckFilename_ ); + return mainObject.runDynamic(); +} + +void PyBlackOilSimulator::setPorosity( py::array_t array) +{ + std::size_t size_ = array.size(); + const double *poro = array.data(); + materialState_->setPorosity(poro, size_); +} + +int PyBlackOilSimulator::step() +{ + if (!hasRunInit_) { + throw std::logic_error("step() called before step_init()"); + } + if (hasRunCleanup_) { + throw std::logic_error("step() called after step_cleanup()"); + } + return mainEbos_->executeStep(); +} + +int PyBlackOilSimulator::stepCleanup() +{ + hasRunCleanup_ = true; + return mainEbos_->executeStepsCleanup(); +} + +int PyBlackOilSimulator::stepInit() +{ + + if (hasRunInit_) { + // Running step_init() multiple times is not implemented yet, + if (hasRunCleanup_) { + throw std::logic_error("step_init() called again"); + } + else { + return EXIT_SUCCESS; + } + } + if (this->deck_) { + main_ = std::make_unique( + this->deck_, + this->eclipse_state_, + this->schedule_, + this->summary_config_ + ); + } + else { + main_ = std::make_unique( deckFilename_ ); + } + int exitCode = EXIT_SUCCESS; + mainEbos_ = main_->initFlowEbosBlackoil(exitCode); + if (mainEbos_) { + int result = mainEbos_->executeInitStep(); + hasRunInit_ = true; + ebosSimulator_ = mainEbos_->getSimulatorPtr(); + materialState_ = std::make_unique>( + ebosSimulator_); + return result; + } + else { + return exitCode; + } +} + +void export_PyBlackOilSimulator(py::module& m) +{ + py::class_(m, "BlackOilSimulator") + .def(py::init< const std::string& >()) + .def(py::init< + std::shared_ptr&, + std::shared_ptr&, + std::shared_ptr&, + std::shared_ptr& >()) + .def("get_porosity", &PyBlackOilSimulator::getPorosity, + py::return_value_policy::copy) + .def("run", &PyBlackOilSimulator::run) + .def("set_porosity", &PyBlackOilSimulator::setPorosity) + .def("step", &PyBlackOilSimulator::step) + .def("step_init", &PyBlackOilSimulator::stepInit) + .def("step_cleanup", &PyBlackOilSimulator::stepCleanup); +} + +} // namespace Opm::Pybind + diff --git a/python/simulators/Pybind11Exporter.cpp b/python/simulators/Pybind11Exporter.cpp new file mode 100644 index 000000000..6f0db977b --- /dev/null +++ b/python/simulators/Pybind11Exporter.cpp @@ -0,0 +1,11 @@ +#include +#include + +void Opm::Pybind::export_all(py::module& m) { + export_PyBlackOilSimulator(m); +} + +PYBIND11_MODULE(simulators, m) +{ + Opm::Pybind::export_all(m); +} diff --git a/python/test/test_basic.py b/python/test/test_basic.py index 933377b76..d769f0456 100755 --- a/python/test/test_basic.py +++ b/python/test/test_basic.py @@ -55,7 +55,7 @@ class TestBasic(unittest.TestCase): # However, as noted above this is not currently possible. # test_dir = Path(os.path.dirname(__file__)) - cls.data_dir = test_dir.parent.joinpath("test_data/SPE1CASE1") + cls.data_dir = test_dir.parent.joinpath("test_data/SPE1CASE1a") def test_all(self): diff --git a/python/test/test_schedule.py b/python/test/test_schedule.py new file mode 100755 index 000000000..99aa1c262 --- /dev/null +++ b/python/test/test_schedule.py @@ -0,0 +1,52 @@ +import os +import unittest +from contextlib import contextmanager +import datetime as dt +from pathlib import Path +from opm2.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 + +@contextmanager +def pushd(path): + cwd = os.getcwd() + if not os.path.isdir(path): + os.makedirs(path) + os.chdir(path) + yield + os.chdir(cwd) + + +class TestBasic(unittest.TestCase): + @classmethod + def setUpClass(cls): + # NOTE: See comment in test_basic.py for the reason why we are + # only using a single test_all() function instead of splitting + # it up in multiple test functions + test_dir = Path(os.path.dirname(__file__)) + cls.data_dir = test_dir.parent.joinpath("test_data/SPE1CASE1b") + + + def test_all(self): + with pushd(self.data_dir): + deck = Parser().parse('SPE1CASE1.DATA') + state = EclipseState(deck) + schedule = Schedule( deck, state ) + summary_config = SummaryConfig(deck, state, schedule) + self.assertTrue('PROD' in schedule) + self.assertTrue('INJ' in schedule) + self.assertEqual(dt.datetime(2015, 1, 1), schedule.start) + self.assertEqual(dt.datetime(2016, 1, 1), schedule.end) + sim = BlackOilSimulator( deck, state, schedule, summary_config ) + sim.step_init() + sim.step() + prod = schedule.get_well("PROD", 2) + self.assertEqual(prod.status(), "OPEN") + #schedule.shut_well("PROD", 3) + #prod = schedule.get_well("PROD", 3) + #self.assertEqual(prod.status(), "SHUT") + sim.step() + sim.step() + diff --git a/python/test_data/SPE1CASE1/SPE1CASE1.DATA b/python/test_data/SPE1CASE1a/SPE1CASE1.DATA similarity index 100% rename from python/test_data/SPE1CASE1/SPE1CASE1.DATA rename to python/test_data/SPE1CASE1a/SPE1CASE1.DATA diff --git a/python/test_data/SPE1CASE1b/SPE1CASE1.DATA b/python/test_data/SPE1CASE1b/SPE1CASE1.DATA new file mode 100644 index 000000000..19b65bd6c --- /dev/null +++ b/python/test_data/SPE1CASE1b/SPE1CASE1.DATA @@ -0,0 +1,439 @@ +-- This reservoir simulation deck is made available under the Open Database +-- License: http://opendatacommons.org/licenses/odbl/1.0/. Any rights in +-- individual contents of the database are licensed under the Database Contents +-- License: http://opendatacommons.org/licenses/dbcl/1.0/ + +-- Copyright (C) 2015 Statoil + +-- This simulation is based on the data given in +-- 'Comparison of Solutions to a Three-Dimensional +-- Black-Oil Reservoir Simulation Problem' by Aziz S. Odeh, +-- Journal of Petroleum Technology, January 1981 + +-- NOTE: This deck is currently not supported by the OPM +-- simulator flow due to lack of support for DRSDT. + +--------------------------------------------------------------------------- +------------------------ SPE1 - CASE 1 ------------------------------------ +--------------------------------------------------------------------------- + +RUNSPEC +-- ------------------------------------------------------------------------- + +TITLE + SPE1 - CASE 1 + +DIMENS + 10 10 3 / + +-- The number of equilibration regions is inferred from the EQLDIMS +-- keyword. +EQLDIMS +/ + +-- The number of PVTW tables is inferred from the TABDIMS keyword; +-- when no data is included in the keyword the default values are used. +TABDIMS +/ + +OIL +GAS +WATER +DISGAS +-- As seen from figure 4 in Odeh, GOR is increasing with time, +-- which means that dissolved gas is present + +FIELD + +START + 1 'JAN' 2015 / + +WELLDIMS +-- Item 1: maximum number of wells in the model +-- - there are two wells in the problem; injector and producer +-- Item 2: maximum number of grid blocks connected to any one well +-- - must be one as the wells are located at specific grid blocks +-- Item 3: maximum number of groups in the model +-- - we are dealing with only one 'group' +-- Item 4: maximum number of wells in any one group +-- - there must be two wells in a group as there are two wells in total + 2 1 1 2 / + +UNIFOUT + +GRID + +-- The INIT keyword is used to request an .INIT file. The .INIT file +-- is written before the simulation actually starts, and contains grid +-- properties and saturation tables as inferred from the input +-- deck. There are no other keywords which can be used to configure +-- exactly what is written to the .INIT file. +INIT + + +-- ------------------------------------------------------------------------- +NOECHO + +DX +-- There are in total 300 cells with length 1000ft in x-direction + 300*1000 / +DY +-- There are in total 300 cells with length 1000ft in y-direction + 300*1000 / +DZ +-- The layers are 20, 30 and 50 ft thick, in each layer there are 100 cells + 100*20 100*30 100*50 / + +TOPS +-- The depth of the top of each grid block + 100*8325 / + +PORO +-- Constant porosity of 0.3 throughout all 300 grid cells + 300*0.3 / + +PERMX +-- The layers have perm. 500mD, 50mD and 200mD, respectively. + 100*500 100*50 100*200 / + +PERMY +-- Equal to PERMX + 100*500 100*50 100*200 / + +PERMZ +-- Cannot find perm. in z-direction in Odeh's paper +-- For the time being, we will assume PERMZ equal to PERMX and PERMY: + 100*500 100*50 100*200 / +ECHO + +PROPS +-- ------------------------------------------------------------------------- + +PVTW +-- Item 1: pressure reference (psia) +-- Item 2: water FVF (rb per bbl or rb per stb) +-- Item 3: water compressibility (psi^{-1}) +-- Item 4: water viscosity (cp) +-- Item 5: water 'viscosibility' (psi^{-1}) + +-- Using values from Norne: +-- In METRIC units: +-- 277.0 1.038 4.67E-5 0.318 0.0 / +-- In FIELD units: + 4017.55 1.038 3.22E-6 0.318 0.0 / + +ROCK +-- Item 1: reference pressure (psia) +-- Item 2: rock compressibility (psi^{-1}) + +-- Using values from table 1 in Odeh: + 14.7 3E-6 / + +SWOF +-- Column 1: water saturation +-- - this has been set to (almost) equally spaced values from 0.12 to 1 +-- Column 2: water relative permeability +-- - generated from the Corey-type approx. formula +-- the coeffisient is set to 10e-5, S_{orw}=0 and S_{wi}=0.12 +-- Column 3: oil relative permeability when only oil and water are present +-- - we will use the same values as in column 3 in SGOF. +-- This is not really correct, but since only the first +-- two values are of importance, this does not really matter +-- Column 4: water-oil capillary pressure (psi) + +0.12 0 1 0 +0.18 4.64876033057851E-008 1 0 +0.24 0.000000186 0.997 0 +0.3 4.18388429752066E-007 0.98 0 +0.36 7.43801652892562E-007 0.7 0 +0.42 1.16219008264463E-006 0.35 0 +0.48 1.67355371900826E-006 0.2 0 +0.54 2.27789256198347E-006 0.09 0 +0.6 2.97520661157025E-006 0.021 0 +0.66 3.7654958677686E-006 0.01 0 +0.72 4.64876033057851E-006 0.001 0 +0.78 0.000005625 0.0001 0 +0.84 6.69421487603306E-006 0 0 +0.91 8.05914256198347E-006 0 0 +1 0.00001 0 0 / + + +SGOF +-- Column 1: gas saturation +-- Column 2: gas relative permeability +-- Column 3: oil relative permeability when oil, gas and connate water are present +-- Column 4: oil-gas capillary pressure (psi) +-- - stated to be zero in Odeh's paper + +-- Values in column 1-3 are taken from table 3 in Odeh's paper: +0 0 1 0 +0.001 0 1 0 +0.02 0 0.997 0 +0.05 0.005 0.980 0 +0.12 0.025 0.700 0 +0.2 0.075 0.350 0 +0.25 0.125 0.200 0 +0.3 0.190 0.090 0 +0.4 0.410 0.021 0 +0.45 0.60 0.010 0 +0.5 0.72 0.001 0 +0.6 0.87 0.0001 0 +0.7 0.94 0.000 0 +0.85 0.98 0.000 0 +0.88 0.984 0.000 0 / +--1.00 1.0 0.000 0 / +-- Warning from Eclipse: first sat. value in SWOF + last sat. value in SGOF +-- must not be greater than 1, but Eclipse still runs +-- Flow needs the sum to be excactly 1 so I added a row with gas sat. = 0.88 +-- The corresponding krg value was estimated by assuming linear rel. between +-- gas sat. and krw. between gas sat. 0.85 and 1.00 (the last two values given) + +DENSITY +-- Density (lb per ft³) at surface cond. of +-- oil, water and gas, respectively (in that order) + +-- Using values from Norne: +-- In METRIC units: +-- 859.5 1033.0 0.854 / +-- In FIELD units: + 53.66 64.49 0.0533 / + +PVDG +-- Column 1: gas phase pressure (psia) +-- Column 2: gas formation volume factor (rb per Mscf) +-- - in Odeh's paper the units are said to be given in rb per bbl, +-- but this is assumed to be a mistake: FVF-values in Odeh's paper +-- are given in rb per scf, not rb per bbl. This will be in +-- agreement with conventions +-- Column 3: gas viscosity (cP) + +-- Using values from lower right table in Odeh's table 2: +14.700 166.666 0.008000 +264.70 12.0930 0.009600 +514.70 6.27400 0.011200 +1014.7 3.19700 0.014000 +2014.7 1.61400 0.018900 +2514.7 1.29400 0.020800 +3014.7 1.08000 0.022800 +4014.7 0.81100 0.026800 +5014.7 0.64900 0.030900 +9014.7 0.38600 0.047000 / + +PVTO +-- Column 1: dissolved gas-oil ratio (Mscf per stb) +-- Column 2: bubble point pressure (psia) +-- Column 3: oil FVF for saturated oil (rb per stb) +-- Column 4: oil viscosity for saturated oil (cP) + +-- Use values from top left table in Odeh's table 2: +0.0010 14.7 1.0620 1.0400 / +0.0905 264.7 1.1500 0.9750 / +0.1800 514.7 1.2070 0.9100 / +0.3710 1014.7 1.2950 0.8300 / +0.6360 2014.7 1.4350 0.6950 / +0.7750 2514.7 1.5000 0.6410 / +0.9300 3014.7 1.5650 0.5940 / +1.2700 4014.7 1.6950 0.5100 + 9014.7 1.5790 0.7400 / +1.6180 5014.7 1.8270 0.4490 + 9014.7 1.7370 0.6310 / +-- It is required to enter data for undersaturated oil for the highest GOR +-- (i.e. the last row) in the PVTO table. +-- In order to fulfill this requirement, values for oil FVF and viscosity +-- at 9014.7psia and GOR=1.618 for undersaturated oil have been approximated: +-- It has been assumed that there is a linear relation between the GOR +-- and the FVF when keeping the pressure constant at 9014.7psia. +-- From Odeh we know that (at 9014.7psia) the FVF is 2.357 at GOR=2.984 +-- for saturated oil and that the FVF is 1.579 at GOR=1.27 for undersaturated oil, +-- so it is possible to use the assumption described above. +-- An equivalent approximation for the viscosity has been used. +/ + +SOLUTION +-- ------------------------------------------------------------------------- + +EQUIL +-- Item 1: datum depth (ft) +-- Item 2: pressure at datum depth (psia) +-- - Odeh's table 1 says that initial reservoir pressure is +-- 4800 psi at 8400ft, which explains choice of item 1 and 2 +-- Item 3: depth of water-oil contact (ft) +-- - chosen to be directly under the reservoir +-- Item 4: oil-water capillary pressure at the water oil contact (psi) +-- - given to be 0 in Odeh's paper +-- Item 5: depth of gas-oil contact (ft) +-- - chosen to be directly above the reservoir +-- Item 6: gas-oil capillary pressure at gas-oil contact (psi) +-- - given to be 0 in Odeh's paper +-- Item 7: RSVD-table +-- Item 8: RVVD-table +-- Item 9: Set to 0 as this is the only value supported by OPM + +-- Item #: 1 2 3 4 5 6 7 8 9 + 8400 4800 8450 0 8300 0 1 0 0 / + +RSVD +-- Dissolved GOR is initially constant with depth through the reservoir. +-- The reason is that the initial reservoir pressure given is higher +---than the bubble point presssure of 4014.7psia, meaning that there is no +-- free gas initially present. +8300 1.270 +8450 1.270 / + +SUMMARY +-- ------------------------------------------------------------------------- + +-- 1a) Oil rate vs time +FOPR +-- Field Oil Production Rate + +-- 1b) GOR vs time +WGOR +-- Well Gas-Oil Ratio + 'PROD' +/ +-- Using FGOR instead of WGOR:PROD results in the same graph +FGOR + +-- 2a) Pressures of the cell where the injector and producer are located +BPR +1 1 1 / +10 10 3 / +/ + +-- 2b) Gas saturation at grid points given in Odeh's paper +BGSAT +1 1 1 / +1 1 2 / +1 1 3 / +10 1 1 / +10 1 2 / +10 1 3 / +10 10 1 / +10 10 2 / +10 10 3 / +/ + +-- In order to compare Eclipse with Flow: +WBHP + 'INJ' + 'PROD' +/ +WGIR + 'INJ' + 'PROD' +/ +WGIT + 'INJ' + 'PROD' +/ +WGPR + 'INJ' + 'PROD' +/ +WGPT + 'INJ' + 'PROD' +/ +WOIR + 'INJ' + 'PROD' +/ +WOIT + 'INJ' + 'PROD' +/ +WOPR + 'INJ' + 'PROD' +/ +WOPT + 'INJ' + 'PROD' +/ +WWIR + 'INJ' + 'PROD' +/ +WWIT + 'INJ' + 'PROD' +/ +WWPR + 'INJ' + 'PROD' +/ +WWPT + 'INJ' + 'PROD' +/ +SCHEDULE +-- ------------------------------------------------------------------------- +RPTSCHED + 'PRES' 'SGAS' 'RS' 'WELLS' / + +RPTRST + 'BASIC=1' / + + +-- If no resolution (i.e. case 1), the two following lines must be added: +DRSDT + 0 / +-- if DRSDT is set to 0, GOR cannot rise and free gas does not +-- dissolve in undersaturated oil -> constant bubble point pressure + +WELSPECS +-- WELNAME GRPNAME III JJJ DEPTH PREFERRED_PHASE + 'PROD' 'G1' 10 10 8400 'OIL' / + 'INJ' 'G1' 1 1 8335 'GAS' / +/ +-- Coordinates in item 3-4 are retrieved from Odeh's figure 1 and 2 +-- Note that the depth at the midpoint of the well grid blocks +-- has been used as reference depth for bottom hole pressure in item 5 + +COMPDAT +-- WELNAME III JJJ KUP KLOW OPEN/SHUT SATTAB TRANS DIAM + 'PROD' 10 10 3 3 'OPEN' 1* 1* 0.5 / + 'INJ' 1 1 1 1 'OPEN' 1* 1* 0.5 / +/ +-- Coordinates in item 2-5 are retreived from Odeh's figure 1 and 2 +-- Item 9 is the well bore internal diameter, +-- the radius is given to be 0.25ft in Odeh's paper + + +WCONPROD +-- WELLNAME OPEN/SHUT CTRLMODE OILRATE_UPLIM BHP_LOWLIM + 'PROD' 'OPEN' 'ORAT' 20000 4* 1000 / +/ + +-- It is stated in Odeh's paper that the maximum oil prod. rate +-- is 20 000stb per day which explains the choice of value in item 4. +-- The items > 4 are defaulted with the exception of item 9, +-- the BHP lower limit, which is given to be 1000psia in Odeh's paper + +WCONINJE +-- WELLNAME INJECTORTYP OPEN/SHUT CTRLMODE SURFTGTRATE 6 BHPUPLIMIT + 'INJ' 'GAS' 'OPEN' 'RATE' 100000 1* 9014 / +/ + +-- Stated in Odeh that gas inj. rate (item 5) is 100MMscf per day +-- BHP upper limit (item 7) should not be exceeding the highest +-- pressure in the PVT table=9014.7psia (default is 100 000psia) + +TSTEP +--Advance the simulater once a month for TEN years: +31 28 31 30 31 30 31 31 30 31 30 31 / +--31 28 31 30 31 30 31 31 30 31 30 31 +--31 28 31 30 31 30 31 31 30 31 30 31 +--31 28 31 30 31 30 31 31 30 31 30 31 +--31 28 31 30 31 30 31 31 30 31 30 31 +--31 28 31 30 31 30 31 31 30 31 30 31 +--31 28 31 30 31 30 31 31 30 31 30 31 +--31 28 31 30 31 30 31 31 30 31 30 31 +--31 28 31 30 31 30 31 31 30 31 30 31 +--31 28 31 30 31 30 31 31 30 31 30 31 / + +--Advance the simulator once a year for TEN years: +--10*365 / + +END