Skip to content

Commit

Permalink
Merge pull request #4017 from lisajulia/fix/pyAction-separate-python-…
Browse files Browse the repository at this point in the history
…bindings-and-opm-embedded

Fix/pyAction: Separate classes for python bindings and opm embedded
  • Loading branch information
blattms committed Apr 30, 2024
2 parents fdb7f01 + d2f45c5 commit 2a34fc4
Show file tree
Hide file tree
Showing 18 changed files with 3,652 additions and 83 deletions.
48 changes: 14 additions & 34 deletions CMakeLists.txt
Expand Up @@ -404,34 +404,15 @@ if (OPM_ENABLE_PYTHON)

target_link_libraries(opmcommon_python PRIVATE
opmcommon)
if(OPM_ENABLE_EMBEDDED_PYTHON)
pybind11_add_module(opm_embedded
${PYTHON_CXX_SOURCE_FILES}
${PROJECT_BINARY_DIR}/python/cxx/builtin_pybind11.cpp)
target_link_libraries(opm_embedded PRIVATE
opmcommon)
endif()
if(TARGET pybind11::pybind11)
target_link_libraries(opmcommon_python PRIVATE
pybind11::pybind11)
if(OPM_ENABLE_EMBEDDED_PYTHON)
target_link_libraries(opm_embedded PRIVATE
pybind11::pybind11)
endif()
else()
target_include_directories(opmcommon_python SYSTEM PRIVATE ${pybind11_INCLUDE_DIRS})
if(OPM_ENABLE_EMBEDDED_PYTHON)
target_include_directories(opm_embedded SYSTEM PRIVATE ${pybind11_INCLUDE_DIRS})
endif()
endif()
set_target_properties(opmcommon_python PROPERTIES
LIBRARY_OUTPUT_DIRECTORY python/opm)
add_dependencies(opmcommon_python copy_python)
if(OPM_ENABLE_EMBEDDED_PYTHON)
set_target_properties(opm_embedded PROPERTIES
LIBRARY_OUTPUT_DIRECTORY python)
add_dependencies(opm_embedded copy_python)
endif()

# Generate versioned setup.py
configure_file(${PROJECT_SOURCE_DIR}/python/setup.py.in
Expand All @@ -443,23 +424,22 @@ if (OPM_ENABLE_PYTHON)
# extra cmake switch, OPM_INSTALL_PYTHON. If you prefer you can still invoke
# setup.py install manually - optionally with the generated script
# setup-install.sh - and completely bypass cmake in the installation phase.
if (OPM_INSTALL_PYTHON)
# If OPM_ENABLE_EMBEDDED_PYTHON is enabled, we also install opmcommon_python,
# to make it available in a Python console.
if (OPM_INSTALL_PYTHON OR OPM_ENABLE_EMBEDDED_PYTHON)
include(PyInstallPrefix)
install(TARGETS opmcommon_python DESTINATION ${DEST_PREFIX}${CMAKE_INSTALL_PREFIX}/${PYTHON_INSTALL_PREFIX}/opm)
install(
CODE "execute_process(
COMMAND ${PYTHON_EXECUTABLE}
python/install.py
${PROJECT_BINARY_DIR}/python/opm
${DEST_PREFIX}${CMAKE_INSTALL_PREFIX}/${PYTHON_INSTALL_PREFIX} 1)")

## Need to install this Python script such that it can be used by opm-simulators when building against an installed
## opm-common
install( PROGRAMS "python/install.py" DESTINATION "${OPM_PYTHON_COMMON_DIR}" )

# Install the convenience library for PYACTION script development
if (OPM_ENABLE_EMBEDDED_PYTHON)
install(TARGETS opm_embedded DESTINATION ${DEST_PREFIX}${CMAKE_INSTALL_PREFIX}/${PYTHON_INSTALL_PREFIX})
if (OPM_INSTALL_PYTHON)
install(
CODE "execute_process(
COMMAND ${PYTHON_EXECUTABLE}
python/install.py
${PROJECT_BINARY_DIR}/python/opm
${DEST_PREFIX}${CMAKE_INSTALL_PREFIX}/${PYTHON_INSTALL_PREFIX} 1)")

## Need to install this Python script such that it can be used by opm-simulators when building against an installed
## opm-common
install( PROGRAMS "python/install.py" DESTINATION "${OPM_PYTHON_COMMON_DIR}" )
endif()
endif()

Expand Down
4 changes: 4 additions & 0 deletions CMakeLists_files.cmake
Expand Up @@ -356,6 +356,8 @@ if(ENABLE_ECL_INPUT)
python/cxx/parsecontext.cpp
python/cxx/parser.cpp
python/cxx/schedule.cpp
python/cxx/schedule_state.cpp
python/cxx/simulation_config.cpp
python/cxx/summary_state.cpp
python/cxx/table_manager.cpp
python/cxx/unit_system.cpp
Expand Down Expand Up @@ -704,13 +706,15 @@ 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_INSERT_INVALID_KEYWORD.DATA
tests/msim/MSIM_PYACTION_NO_RUN_FUNCTION.DATA
tests/msim/MSIM_PYACTION_OPEN_WELL_AT_PAST_REPORT_STEP.DATA
tests/msim/MSIM_PYACTION_OPEN_WELL_AT_TOO_LATE_REPORT_STEP.DATA
tests/msim/retrieve_info.py
tests/msim/action1.py
tests/msim/action2.py
tests/msim/action2_no_run_function.py
Expand Down
2 changes: 1 addition & 1 deletion opm/input/eclipse/Python/PythonInterp.cpp
Expand Up @@ -42,7 +42,7 @@ namespace Opm {
*/

OPM_EMBEDDED_MODULE(opm_embedded, module) {
python::common::export_all_opm_embedded(module);
python::common::export_all(module);
}


Expand Down
13 changes: 12 additions & 1 deletion python/README.md
Expand Up @@ -2,4 +2,15 @@ This folder contains the Python bindings and code required for embedding python

For the Python bindings, see the [Python bindings of opm-simulators](https://github.com/OPM/opm-simulators/blob/master/python/README.md).

For embedding python, see the [documentation](https://opm-project.org/?page_id=1454).
For embedding python, see the [documentation](https://opm-project.org/?page_id=1454).

To enable tooltips for opm_embedded on VSCode (embedded python code):
- Install opm-common
- Copy the file "<opm-common-folder>/python/opm_embedded/__init__.pyi" into the folder at "python.analysis.stubPath" of VS Code and rename it to "opm_embedded.pyi"
You can recreate this stub file by executing "stubgen -m opmcommon_python" in "<opm-common-build-folder>/python/opm", renaming the resuling stub file from "opmcommon_python.pyi" to "opm_embedded.pyi" and adding the lines
```python
current_ecl_state: EclipseState
current_report_step: int
current_schedule: Schedule
current_summary_state: SummaryState
```
2 changes: 1 addition & 1 deletion python/cxx/connection.cpp
Expand Up @@ -26,7 +26,7 @@ void python::common::export_Connection(py::module& module) {
.def_property_readonly("state", &state )
.def_property_readonly( "i", &Connection::getI )
.def_property_readonly( "j", &Connection::getJ )
.def_property_readonly( "j", &Connection::getK )
.def_property_readonly( "k", &Connection::getK )
.def_property_readonly( "pos", &get_pos )
.def_property_readonly( "attached_to_segment", &Connection::attachedToSegment )
.def_property_readonly( "center_depth", &Connection::depth)
Expand Down
9 changes: 0 additions & 9 deletions python/cxx/eclipse_config.cpp
Expand Up @@ -37,14 +37,5 @@ void python::common::export_EclipseConfig(py::module& module)
.def( "getRestartStep" , &InitConfig::getRestartStep );

py::class_< IOConfig >( module, "IOConfig");

py::class_< SimulationConfig >( module, "SimulationConfig")
.def("hasThresholdPressure", &SimulationConfig::useThresholdPressure )
.def("useCPR", &SimulationConfig::useCPR )
.def("useNONNC", &SimulationConfig::useNONNC )
.def("hasDISGAS", &SimulationConfig::hasDISGAS )
.def("hasDISGASW", &SimulationConfig::hasDISGASW )
.def("hasVAPOIL", &SimulationConfig::hasVAPOIL )
.def("hasVAPWAT", &SimulationConfig::hasVAPWAT );
}

27 changes: 10 additions & 17 deletions python/cxx/export.cpp
Expand Up @@ -11,10 +11,12 @@ void python::common::export_all(py::module& module) {
export_Deck(module);
export_DeckKeyword(module);
export_Schedule(module);
export_ScheduleState(module);
export_Well(module);
export_Group(module);
export_Connection(module);
export_EclipseConfig(module);
export_SimulationConfig(module);
export_FieldProperties(module);
export_EclipseState(module);
export_TableManager(module);
Expand All @@ -30,22 +32,13 @@ void python::common::export_all(py::module& 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);
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";
}
pybind11::module submodule = module.def_submodule("embedded");

/*
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
*/
PYBIND11_MODULE(opm_embedded, module) {
python::common::export_all_opm_embedded(module);
}
// These attributes are placeholders, they get set to the actual EclipseState, Schedule and SummaryState in PyRunModule.cpp
// If you change anything here, please recreate and update the python stub file for opm_embedded as described in python/README.md
submodule.attr("current_ecl_state") = std::make_shared<EclipseState>();
submodule.attr("current_summary_state") = std::make_shared<SummaryState>();
submodule.attr("current_schedule") = std::make_shared<Schedule>();
submodule.attr("current_report_step") = 0;
}
3 changes: 2 additions & 1 deletion python/cxx/export.hpp
Expand Up @@ -14,7 +14,6 @@ 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_UnitSystem(py::module& module);
void export_Connection(py::module& module);
void export_Deck(py::module& module);
Expand All @@ -26,7 +25,9 @@ void export_EclipseState(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_ScheduleState(py::module& module);
void export_TableManager(py::module& module);
void export_Well(py::module& module);
void export_Log(py::module& module);
Expand Down
19 changes: 11 additions & 8 deletions python/cxx/log.cpp
Expand Up @@ -38,12 +38,15 @@ void note(const std::string& msg) {

void python::common::export_Log(py::module& module)
{
py::class_<OpmLog>(module, "OpmLog")
.def_static("info", info )
.def_static("warning", warning)
.def_static("error", error)
.def_static("problem", problem)
.def_static("bug", bug)
.def_static("debug", debug)
.def_static("note", note);
py::class_<OpmLog, std::shared_ptr<OpmLog> >( module, "OpmLog", R"(
The Opm::OpmLog class - this is a fully static class which manages a proper
Logger instance.
)")
.def_static("info", info, "Add an info message to the opm log.")
.def_static("warning", warning, "Add a warning message to the opm log.")
.def_static("error", error, "Add an error message to the opm log.")
.def_static("problem", problem, "Add a problem message to the opm log.")
.def_static("bug", bug, "Add a bug message to the opm log.")
.def_static("debug", debug, "Add a debug message to the opm log.")
.def_static("note", note, "Add a note to the opm log.");
}
11 changes: 0 additions & 11 deletions python/cxx/schedule.cpp
Expand Up @@ -139,11 +139,6 @@ namespace {
return sch.hasWell( wellName );
}

const Group& get_group(const ScheduleState& st, const std::string& group_name) {
return st.groups.get(group_name);
}


const ScheduleState& getitem(const Schedule& sch, std::size_t report_step) {
return sch[report_step];
}
Expand Down Expand Up @@ -197,12 +192,6 @@ namespace {

void python::common::export_Schedule(py::module& module) {


py::class_<ScheduleState>(module, "ScheduleState")
.def_property_readonly("nupcol", py::overload_cast<>(&ScheduleState::nupcol, py::const_))
.def("group", &get_group, ref_internal);


// Note: In the below class we use std::shared_ptr as the holder type, see:
//
// https://pybind11.readthedocs.io/en/stable/advanced/smart_ptrs.html
Expand Down
25 changes: 25 additions & 0 deletions python/cxx/schedule_state.cpp
@@ -0,0 +1,25 @@
#include <opm/input/eclipse/Schedule/ScheduleState.hpp>

#include "export.hpp"

namespace {
const Group& get_group(const ScheduleState& st, const std::string& group_name) {
return st.groups.get(group_name);
}
}

/**
* @brief Function to export the ScheduleState class and some methods to Python.
*
* 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 ScheduleState (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_ScheduleState(py::module& module) {

py::class_<ScheduleState>(module, "ScheduleState")
.def_property_readonly("nupcol", py::overload_cast<>(&ScheduleState::nupcol, py::const_))
.def("group", &get_group, ref_internal)
;
}
23 changes: 23 additions & 0 deletions python/cxx/simulation_config.cpp
@@ -0,0 +1,23 @@
#include <opm/input/eclipse/EclipseState/SimulationConfig/SimulationConfig.hpp>

#include "export.hpp"

/**
* @brief Function to export the SimulationConfig class and some methods to Python.
*
* 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 SimulationConfig (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_SimulationConfig(py::module& module)
{
py::class_< SimulationConfig , std::shared_ptr<SimulationConfig>>( module, "SimulationConfig")
.def("hasThresholdPressure", &SimulationConfig::useThresholdPressure )
.def("useCPR", &SimulationConfig::useCPR )
.def("useNONNC", &SimulationConfig::useNONNC )
.def("hasDISGAS", &SimulationConfig::hasDISGAS )
.def("hasDISGASW", &SimulationConfig::hasDISGASW )
.def("hasVAPOIL", &SimulationConfig::hasVAPOIL )
.def("hasVAPWAT", &SimulationConfig::hasVAPWAT );
}
8 changes: 8 additions & 0 deletions python/opm_embedded/__init__.py
@@ -0,0 +1,8 @@
"""
This is the opm_embedded module for embedding python code in PYACTION.
"""

# If you change anything here, please recreate and update the python stub file for opm_embedded as described in python/README.md
from opm.opmcommon_python.embedded import current_ecl_state, current_summary_state, current_schedule, current_report_step
from opm.opmcommon_python import OpmLog
from opm.opmcommon_python import DeckKeyword # Needed for PYINPUT

0 comments on commit 2a34fc4

Please sign in to comment.