Skip to content

Commit

Permalink
Use the documentation from opm-common and opm-embedded on the generat…
Browse files Browse the repository at this point in the history
…ed website
  • Loading branch information
lisajulia committed Jun 17, 2024
1 parent 5ae5cdc commit 69c9c34
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 43 deletions.
4 changes: 4 additions & 0 deletions docs/docs/common.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
OPM Common Python Documentation
===============================

.. opm_common_docstrings::
5 changes: 3 additions & 2 deletions docs/docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Configuration file for the Sphinx documentation builder.

project = "opm"
project = "OPM Python Documentation"
copyright = "2024 Equinor ASA"
author = "Håkon Hægland"

Expand Down Expand Up @@ -37,7 +37,8 @@ def extract_opm_python_release():
# Our sphinx extension that will use the docstrings.json file to generate documentation
extensions = ["opm_python_docs.sphinx_ext_docstrings"]
# Path to docstrings.json
opm_python_docstrings_path = os.path.abspath('../docstrings.json')
opm_simulators_docstrings_path = os.path.abspath('../docstrings_simulators.json')
opm_common_docstrings_path = os.path.abspath('../docstrings_common.json')

templates_path = ["_templates"]
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
Expand Down
52 changes: 52 additions & 0 deletions docs/docs/embedded.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
OPM Embedded Python Documentation
=================================

The PYACTION keyword is a flow specific keyword which allows for executing embedded Python
code in the SCHEDULE section. The embedded Python code will then be executed at the end of each successful timestep.

The PYACTION keyword is inspired
by the ACTIONX keyword, but instead of a .DATA formatted condition you
are allowed to implement the condition with a general Python script. The
ACTIONX keywords are very clearly separated in a condition part and an
action part in the form of a list of keywords which are effectively injected in
the SCHEDULE section when the condition evaluates to true.
This is not so for PYACTION where there is one Python script in which both
conditions can be evaluated and changes applied.

In order to enable the PYACTION keyword:

1. OPM flow must be compiled with the cmake switches -DOPM ENABLE EMBEDDED PYTHON=ON and -DOPM ENABLE PYTHON=ON, the default is to build with these switches set to OFF.

2. The keyword PYACTION must be added to the SCHEDULE section:

.. code-block:: python
<PYACTION\_NAME> <SINGLE/UNLIMITED> /
<pythonscript> /
3. You need to provide the Python script.


To interact with the simulator in the embedded Python code, you can access four variables from the simulator:

.. code-block:: python
# Python module opm_embedded
import opm_embedded
# The current EclipseState
ecl_state = opm_embedded.current_ecl_state
# The current Schedule
schedule = opm_embedded.current_schedule
# The current SummaryState
summary_state = opm_embedded.current_summary_state
# The current report step
report_step = opm_embedded.current_report_step
- current_ecl_state: An instance of the `EclipseState <common.html#opm.io.ecl_state.EclipseState>`_ class - this is a representation of all static properties in the model, ranging from porosity to relperm tables. The content of the ecl state is immutable - you are not allowed to change the static properties at runtime.

- current_schedule: An instance of the `Schedule <common.html#opm.io.schedule.Schedule>`_ class - this is a representation of all the content from the SCHEDULE section, notably all well and group information and the timestepping.

- current_report_step: This is an integer for the report step we are currently working on. Observe that the PYACTION is called for every simulator timestep, i.e. it will typically be called multiple times with the same value for the report step argument.

- current_summary_state: An instance of the `SummaryState <common.html#opm.io.sim.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.
10 changes: 6 additions & 4 deletions docs/docs/index.rst
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
Welcome to the Python documentation for opm-simulators!
=======================================================
Welcome to the Python documentation for OPM Flow!
=================================================

.. toctree::
:maxdepth: 1
:caption: Contents:

introduction
python

common
simulators
embedded

Indices and tables
==================

Expand Down
2 changes: 1 addition & 1 deletion docs/docs/introduction.rst
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Introduction
============

Documentation for the ``opm.simulators`` Python module.
Documentation for the OPM Python interfaces.
4 changes: 0 additions & 4 deletions docs/docs/python.rst

This file was deleted.

5 changes: 5 additions & 0 deletions docs/docs/simulators.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
OPM Simulators Python Documentation
===================================

.. opm_simulators_docstrings::

78 changes: 46 additions & 32 deletions docs/src/opm_python_docs/sphinx_ext_docstrings.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,57 @@
from sphinx.util.docutils import SphinxDirective
from docutils import nodes

class PybindDocstringsDirective(SphinxDirective):
def readDocStrings(directive, docstrings_path):
print(docstrings_path)
with open(docstrings_path, 'r') as file:
docstrings = json.load(file)
result = []
for name, item in docstrings.items():
# Create a ViewList instance for the function signature and docstring
rst = ViewList()

# Check if signature exists and prepend it to the docstring
signature = item.get('signature', '')
item_type = item.get('type', 'method')
signature_line = f".. py:{item_type}:: {signature}" if signature else f".. py:{item_type}:: {name}()"
rst.append(signature_line, source="")
rst.append("", source="")

# Add the docstring text if it exists
docstring = item.get('doc', '')
if docstring:
for line in docstring.split('\n'):
rst.append(f" {line}", source="")

# Create a node that will be populated by nested_parse_with_titles
node = nodes.section()
node.document = directive.state.document
# Parse the rst content
nested_parse_with_titles(directive.state, rst, node)

result.extend(node.children)
return result

class SimulatorsDirective(SphinxDirective):
required_arguments = 0
optional_arguments = 0
final_argument_whitespace = False
option_spec = {}

def run(self):
return readDocStrings(self, self.state.document.settings.env.app.config.opm_simulators_docstrings_path)

class CommonDirective(SphinxDirective):
required_arguments = 0
optional_arguments = 0
final_argument_whitespace = False
option_spec = {}

def run(self):
env = self.state.document.settings.env
docstrings_path = env.app.config.opm_python_docstrings_path
with open(docstrings_path, 'r') as file:
docstrings = json.load(file)
result = []
for func_name, doc_info in docstrings.items():
signature = doc_info.get('signature', '')
docstring = doc_info.get('doc', '')

# Create a ViewList instance for the function signature and docstring
rst = ViewList()

# Check if signature exists and prepend it to the docstring
signature_line = f".. py:function:: {signature}" if signature else f".. py:function:: {func_name}()"
rst.append(signature_line, source="")
rst.append("", source="")
# Add the docstring text if it exists
if docstring:
for line in docstring.split('\n'):
rst.append(f" {line}", source="")

# Create a node that will be populated by nested_parse_with_titles
node = nodes.section()
node.document = self.state.document
# Parse the rst content
nested_parse_with_titles(self.state, rst, node)

result.extend(node.children)
return result
return readDocStrings(self, self.state.document.settings.env.app.config.opm_common_docstrings_path)

def setup(app):
app.add_config_value('opm_python_docstrings_path', None, 'env')
app.add_directive("opm_python_docstrings", PybindDocstringsDirective)
app.add_config_value('opm_simulators_docstrings_path', None, 'env')
app.add_config_value('opm_common_docstrings_path', None, 'env')
app.add_directive("opm_simulators_docstrings", SimulatorsDirective)
app.add_directive("opm_common_docstrings", CommonDirective)

0 comments on commit 69c9c34

Please sign in to comment.