Skip to content

Commit

Permalink
Only export things to opm_embedded module that are needed
Browse files Browse the repository at this point in the history
There are three modules that contain classes exported to Python:
- opmcommon_python: all classes
- opm_embedded, as embedded Python module: all classes needed for PYACTION and PYINPUT
- opm_embedded, as the shared library: all classes needed for PYACTION

Changes:
- Now each of the three modules contains only the classes that are needed.
- In the embedded python code, one could acutally initialize a new ScheduleState, EclipseState and SummaryState, I have removed this constructor from the embedded python code.
  • Loading branch information
lisajulia committed Apr 17, 2024
1 parent 2964ed8 commit ccc241b
Show file tree
Hide file tree
Showing 10 changed files with 889 additions and 76 deletions.
2 changes: 2 additions & 0 deletions CMakeLists_files.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -705,10 +705,12 @@ if(ENABLE_ECL_OUTPUT)
tests/ACTIONX_M1.X0010
tests/wclose.py
tests/msim/MSIM_PYACTION.DATA
tests/msim/MSIM_PYACTION_RETRIEVE_INFO.DATA
tests/msim/MSIM_PYACTION_CHANGING_SCHEDULE.DATA
tests/msim/MSIM_PYACTION_CHANGING_SCHEDULE_ACTIONX_CALLBACK.DATA
tests/msim/MSIM_PYACTION_INSERT_KEYWORD.DATA
tests/msim/MSIM_PYACTION_NO_RUN_FUNCTION.DATA
tests/msim/retrieve_info.py
tests/msim/action1.py
tests/msim/action2.py
tests/msim/action2_no_run_function.py
Expand Down
67 changes: 45 additions & 22 deletions python/cxx/eclipse_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,33 +92,56 @@ namespace {
return state.fieldProps();
}

/**
* @brief Function to export methods that are available for both embedded Python code and Python bindings for the Python class c.
*
* @param c Reference to the python class.
*/
void add_shared_EclipseState_methods(py::class_< EclipseState, std::shared_ptr<EclipseState> >& c) {
c.def_property_readonly( "title", &EclipseState::getTitle )
.def( "tables", &EclipseState::getTableManager, ref_internal)
.def( "field_props", &get_field_props, ref_internal)
.def( "grid", &EclipseState::getInputGrid, ref_internal)
.def( "has_input_nnc", &EclipseState::hasInputNNC)
.def( "input_nnc", &getNNC)
.def( "faultNames", &faultNames)
.def( "faultFaces", &faultFaces)
.def( "jfunc", &jfunc)
.def( "simulation", &EclipseState::getSimulationConfig, ref_internal)
;
}
}

void python::common::export_EclipseState(py::module& module) {
/**
* @brief Function to export the EclipseState class and some methods to the opm_embedded python module.
*
* In the below class we use std::shared_ptr as the holder type, see https://pybind11.readthedocs.io/en/stable/advanced/smart_ptrs.html
* this makes it possible to share the EclipseState (which is created only once per simulation) in the opm_embedded module.
*
* @param module Reference to the python module.
*/
void python::common::export_EclipseState_embedded(py::module& module) {
auto c = py::class_< EclipseState, std::shared_ptr<EclipseState> >( module, "EclipseState", R"pbdoc(
The Opm::EclipseState class - this is a representation of all static properties in the model,
ranging from porosity to relperm tables. The content of the EclipseState is immutable and may not
be changed at runtime.)pbdoc");

add_shared_EclipseState_methods(c);
}

// Note: In the below class we std::shared_ptr as the holder type, see:
//
// https://pybind11.readthedocs.io/en/stable/advanced/smart_ptrs.html
//
// this makes it possible to share the returned object with e.g. and
// opm.simulators.BlackOilSimulator Python object
//
py::class_< EclipseState, std::shared_ptr<EclipseState> >( module, "EclipseState", R"pbdoc(
The Opm::EclipseState class - this is a representation of all static properties in the model,
ranging from porosity to relperm tables. The content of the EclipseState is immutable and may not
be changed at runtime.)pbdoc")
/**
* @brief Function to export the EclipseState class and some methods to the opmcommon_python module, for the Python bindings.
*
* In the below class we use std::shared_ptr as the holder type, see https://pybind11.readthedocs.io/en/stable/advanced/smart_ptrs.html
* this makes it possible to share the EclipseState (which is created only once per simulation) with e.g. the opm.simulators.BlackOilSimulator Python object.
*
* @param module Reference to the python module.
*/
void python::common::export_EclipseState(py::module& module) {
auto c = py::class_< EclipseState, std::shared_ptr<EclipseState> >( module, "EclipseState")
.def(py::init<const Deck&>())
.def_property_readonly( "title", &EclipseState::getTitle )
.def( "field_props", &get_field_props, ref_internal)
.def( "grid", &EclipseState::getInputGrid, ref_internal)
.def( "config", &EclipseState::cfg, ref_internal)
.def( "tables", &EclipseState::getTableManager, ref_internal)
.def( "has_input_nnc", &EclipseState::hasInputNNC )
.def( "simulation", &EclipseState::getSimulationConfig, ref_internal)
.def( "input_nnc", &getNNC )
.def( "faultNames", &faultNames )
.def( "faultFaces", &faultFaces )
.def( "jfunc", &jfunc )
;

add_shared_EclipseState_methods(c);
}
48 changes: 42 additions & 6 deletions python/cxx/export.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
#include <opm/input/eclipse/Schedule/Schedule.hpp>
#include <opm/input/eclipse/Schedule/SummaryState.hpp>
#include <opm/common/OpmLog/OpmLog.hpp>

void python::common::export_all(py::module& module) {
export_ParseContext(module);
Expand All @@ -29,25 +30,60 @@ void python::common::export_all(py::module& module) {
export_ParserKeywords(module);
}


PYBIND11_MODULE(opmcommon_python, module) {
python::common::export_all(module);
}

void python::common::export_all_opm_embedded(py::module& module) {
python::common::export_all(module);
/**
* @brief Function to export several classes to the opm_embedded module that is created as a shared library.
*
* @param module Reference to the python module.
*/
void python::common::export_all_opm_embedded_for_sl(py::module& module) {
export_Schedule_embedded(module);
export_EclipseState_embedded(module);
export_SummaryState_embedded(module);

export_Connection(module);
export_FieldProperties(module);
export_EclipseGrid(module);
export_Group(module);
export_Log(module);
export_ScheduleState(module);
export_SimulationConfig(module);
export_TableManager(module);
export_Well(module);

module.attr("current_ecl_state") = std::make_shared<EclipseState>();
module.attr("current_summary_state") = std::make_shared<SummaryState>();
module.attr("current_schedule") = std::make_shared<Schedule>();
module.attr("current_report_step") = 0;
module.doc() = R"pbdoc(This is the opm_embedded module for embedding python code in PYACTION.)pbdoc";
}

/**
* @brief Function to export several classes to the opm_embedded module.
*
* @param module Reference to the python module.
*/
void python::common::export_all_opm_embedded(py::module& module) {
// The additional classes are needed for the PYINPUT keyword
export_ParseContext(module);
export_Parser(module);
export_Deck(module);
export_DeckKeyword(module);
export_UnitSystem(module);
export_ParserKeywords(module);

python::common::export_all_opm_embedded_for_sl(module);
}


/*
PYBIND11_MODULE create a Python of all the Python/C++ classes which are
generated in the python::common::export_all_opm_embedded() function in the wrapping code.
The same module is created as an embedded python module in PythonInterp.cpp
generated in the python::common::export_all_opm_embedded_for_sl() function in the wrapping code.
The same module (with export_all_opm_embedded) is created as an embedded python module in PythonInterp.cpp
*/
PYBIND11_MODULE(opm_embedded, module) {
python::common::export_all_opm_embedded(module);
python::common::export_all_opm_embedded_for_sl(module);
}
4 changes: 4 additions & 0 deletions python/cxx/export.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const py::return_value_policy move = py::return_value_policy::move;
namespace python::common {
void export_all(py::module& module);
void export_all_opm_embedded(py::module& module);
void export_all_opm_embedded_for_sl(py::module& module);
void export_UnitSystem(py::module& module);
void export_Connection(py::module& module);
void export_Deck(py::module& module);
Expand All @@ -23,18 +24,21 @@ void export_FieldProperties(py::module& module);
void export_EclipseConfig(py::module& module);
void export_EclipseGrid(py::module& module);
void export_EclipseState(py::module& module);
void export_EclipseState_embedded(py::module& module);
void export_Group(py::module& module);
void export_ParseContext(py::module& module);
void export_Parser(py::module& module);
void export_SimulationConfig(py::module& module);
void export_Schedule(py::module& module);
void export_Schedule_embedded(py::module& module);
void export_ScheduleState(py::module& module);
void export_TableManager(py::module& module);
void export_Well(py::module& module);
void export_Log(py::module& module);
void export_IO(py::module& module);
void export_EModel(py::module& module);
void export_SummaryState(py::module& module);
void export_SummaryState_embedded(py::module& module);

// The export_ParserKeywords() function is implemented in the source file
// ${BUILD}/builtin_pybind11.cpp which is generated by the build system.
Expand Down
75 changes: 53 additions & 22 deletions python/cxx/schedule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,60 @@ namespace {
}
sch.applyKeywords(keywords, report_step);
}

/**
* @brief Function to export methods that are available for both embedded Python code and Python bindings for the Python class c.
*
* @param c Reference to the python class.
*/
void add_shared_Schedule_methods(py::class_< Schedule, std::shared_ptr<Schedule> >& c) {
c.def_property_readonly("start", &get_start_time)
.def_property_readonly("end", &get_end_time)
.def_property_readonly("timesteps", &get_timesteps)
.def("__len__", &Schedule::size)
.def("shut_well", &Schedule::shut_well)
.def("open_well", &Schedule::open_well)
.def("stop_well", &Schedule::stop_well)
.def("get_injection_properties", &get_injection_properties, py::arg("well_name"), py::arg("report_step"))
.def("get_production_properties", &get_production_properties, py::arg("well_name"), py::arg("report_step"))
.def("well_names", py::overload_cast<const std::string&>(&Schedule::wellNames, py::const_))
.def("insert_keywords", py::overload_cast<Schedule&, py::list&, std::size_t>(&insert_keywords), py::arg("keywords"), py::arg("step"))
.def("insert_keywords", py::overload_cast<Schedule&, const std::string&, std::size_t>(&insert_keywords), py::arg("data"), py::arg("step"))
.def("insert_keywords", py::overload_cast<Schedule&, const std::string&>(&insert_keywords),py::arg("data"))
.def("__contains__", &has_well )
.def("_groups", &get_groups )
.def( "get_well", &get_well)
.def("__getitem__", &getitem)
.def( "get_wells", &Schedule::getWells)
;
}
}

/**
* @brief Function to export the Schedule class and some methods to the opm_embedded python module.
*
* In the below class we use std::shared_ptr as the holder type, see https://pybind11.readthedocs.io/en/stable/advanced/smart_ptrs.html
* this makes it possible to share the Schedule (which is created only once per simulation) in the opm_embedded module.
*
* @param module Reference to the python module.
*/
void python::common::export_Schedule_embedded(py::module& module) {
auto c = py::class_< Schedule, std::shared_ptr<Schedule> >( module, "Schedule", R"pbdoc(
The Opm::Schedule class - this is a representation of all the content from
the SCHEDULE section, notably all well and group information and the timestepping.
)pbdoc");

add_shared_Schedule_methods(c);
}

/**
* @brief Function to export the Schedule class and some methods to the opmcommon_python module, for the Python bindings.
*
* In the below class we use std::shared_ptr as the holder type, see https://pybind11.readthedocs.io/en/stable/advanced/smart_ptrs.html
* this makes it possible to share the Schedule (which is created only once per simulation) with e.g. the opm.simulators.BlackOilSimulator Python object.
*
* @param module Reference to the python module.
*/
void python::common::export_Schedule(py::module& module) {

// Note: In the below class we use std::shared_ptr as the holder type, see:
Expand All @@ -199,29 +249,10 @@ void python::common::export_Schedule(py::module& module) {
// this makes it possible to share the returned object with e.g. and
// opm.simulators.BlackOilSimulator Python object
//
py::class_< Schedule, std::shared_ptr<Schedule> >( module, "Schedule", R"pbdoc(
The Opm::Schedule class - this is a representation of all the content from
the SCHEDULE section, notably all well and group information and the timestepping.
)pbdoc")
auto c = py::class_< Schedule, std::shared_ptr<Schedule> >( module, "Schedule")
.def(py::init<const Deck&, const EclipseState& >())
.def("_groups", &get_groups )
.def_property_readonly( "start", &get_start_time )
.def_property_readonly( "end", &get_end_time )
.def_property_readonly( "timesteps", &get_timesteps )
.def("__len__", &Schedule::size)
.def("__getitem__", &getitem)
.def( "shut_well", &Schedule::shut_well)
.def( "open_well", &Schedule::open_well)
.def( "stop_well", &Schedule::stop_well)
.def( "get_wells", &Schedule::getWells)
.def( "get_injection_properties", &get_injection_properties, py::arg("well_name"), py::arg("report_step"))
.def( "get_production_properties", &get_production_properties, py::arg("well_name"), py::arg("report_step"))
.def("well_names", py::overload_cast<const std::string&>(&Schedule::wellNames, py::const_))
.def( "get_well", &get_well)
.def( "insert_keywords", py::overload_cast<Schedule&, py::list&, std::size_t>(&insert_keywords), py::arg("keywords"), py::arg("step"))
.def( "insert_keywords", py::overload_cast<Schedule&, const std::string&, std::size_t, const UnitSystem&>(&insert_keywords), py::arg("data"), py::arg("step"), py::arg("unit_system"))
.def( "insert_keywords", py::overload_cast<Schedule&, const std::string&, std::size_t>(&insert_keywords), py::arg("data"), py::arg("step"))
.def( "insert_keywords", py::overload_cast<Schedule&, const std::string&>(&insert_keywords),py::arg("data"))
.def( "__contains__", &has_well );
;

add_shared_Schedule_methods(c);
}
69 changes: 51 additions & 18 deletions python/cxx/summary_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,27 +37,60 @@ std::vector<std::string> wells(const SummaryState * st) {
}




/**
* @brief Function to export methods that are available for both embedded Python code and Python bindings for the Python class c.
*
* @param c Reference to the python class.
*/
void add_shared_SummaryState_methods(py::class_< SummaryState, std::shared_ptr<SummaryState> >& c) {
c.def("update", &SummaryState::update)
.def("update_well_var", &SummaryState::update_well_var)
.def("update_group_var", &SummaryState::update_group_var)
.def("well_var", py::overload_cast<const std::string&, const std::string&>(&SummaryState::get_well_var, py::const_))
.def("group_var", py::overload_cast<const std::string&, const std::string&>(&SummaryState::get_group_var, py::const_))
.def("elapsed", &SummaryState::get_elapsed)
.def_property_readonly("groups", groups)
.def_property_readonly("wells", wells)
.def("__contains__", &SummaryState::has)
.def("has_well_var", py::overload_cast<const std::string&, const std::string&>(&SummaryState::has_well_var, py::const_))
.def("has_group_var", py::overload_cast<const std::string&, const std::string&>(&SummaryState::has_group_var, py::const_))
.def("__setitem__", &SummaryState::set)
.def("__getitem__", py::overload_cast<const std::string&>(&SummaryState::get, py::const_))
;
}

}
/**
* @brief Function to export the SummaryState class and some methods to the opm_embedded python module.
*
* In the below class we use std::shared_ptr as the holder type, see https://pybind11.readthedocs.io/en/stable/advanced/smart_ptrs.html
* this makes it possible to share the SummaryState (which is created only once per simulation) in the opm_embedded module.
*
* @param module Reference to the python module.
*/
void python::common::export_SummaryState_embedded(py::module& module) {
auto c = py::class_<SummaryState, std::shared_ptr<SummaryState>>(module, "SummaryState", R"pbdoc(
The Opm::SummaryState class - this is where the current summary results of the simulator are stored.
The SummaryState class has methods to get hold of well, group and general variables.
)pbdoc");

void python::common::export_SummaryState(py::module& module) {
add_shared_SummaryState_methods(c);
}

py::class_<SummaryState, std::shared_ptr<SummaryState>>(module, "SummaryState", R"pbdoc(
The Opm::SummaryState class - this is where the current summary results of the simulator are stored.
The SummaryState class has methods to get hold of well, group and general variables.
)pbdoc")
/**
* @brief Function to export the SummaryState class and some methods to the opmcommon_python module, for the Python bindings.
*
* In the below class we use std::shared_ptr as the holder type, see https://pybind11.readthedocs.io/en/stable/advanced/smart_ptrs.html
* this makes it possible to share the SummaryState (which is created only once per simulation) with e.g. the opm.simulators.BlackOilSimulator Python object.
*
* @param module Reference to the python module.
*/
void python::common::export_SummaryState(py::module& module) {
auto c = py::class_<SummaryState, std::shared_ptr<SummaryState>>(module, "SummaryState")
.def(py::init<std::time_t>())
.def("update", &SummaryState::update)
.def("update_well_var", &SummaryState::update_well_var)
.def("update_group_var", &SummaryState::update_group_var)
.def("well_var", py::overload_cast<const std::string&, const std::string&>(&SummaryState::get_well_var, py::const_))
.def("group_var", py::overload_cast<const std::string&, const std::string&>(&SummaryState::get_group_var, py::const_))
.def("elapsed", &SummaryState::get_elapsed)
.def_property_readonly("groups", groups)
.def_property_readonly("wells", wells)
.def("__contains__", &SummaryState::has)
.def("has_well_var", py::overload_cast<const std::string&, const std::string&>(&SummaryState::has_well_var, py::const_))
.def("has_group_var", py::overload_cast<const std::string&, const std::string&>(&SummaryState::has_group_var, py::const_))
.def("__setitem__", &SummaryState::set)
.def("__getitem__", py::overload_cast<const std::string&>(&SummaryState::get, py::const_));
;

add_shared_SummaryState_methods(c);
}

0 comments on commit ccc241b

Please sign in to comment.