Added a get_dt() method

Added a get_dt() to the opm.simulators.BlackOilSimulator Python module.
This will return the size of the previous simulator time step.
This commit is contained in:
Håkon Hægland 2023-09-08 19:40:42 +02:00
parent e2f62644ae
commit ac927d997b
8 changed files with 121 additions and 64 deletions

View File

@ -321,6 +321,12 @@ void handleExtraConvergenceOutput(SimulatorReport& report,
return simtimer_.get(); return simtimer_.get();
} }
/// Get the size of the previous report step
double getPreviousReportStepSize()
{
return simtimer_->stepLengthTaken();
}
private: private:
// called by execute() or executeInitStep() // called by execute() or executeInitStep()
int execute_(int (FlowMainEbos::* runOrInitFunc)(), bool cleanup) int execute_(int (FlowMainEbos::* runOrInitFunc)(), bool cleanup)

View File

@ -43,20 +43,23 @@ public:
std::shared_ptr<Opm::EclipseState> state, std::shared_ptr<Opm::EclipseState> state,
std::shared_ptr<Opm::Schedule> schedule, std::shared_ptr<Opm::Schedule> schedule,
std::shared_ptr<Opm::SummaryConfig> summary_config); std::shared_ptr<Opm::SummaryConfig> summary_config);
void advance(int report_step);
bool checkSimulationFinished(); bool checkSimulationFinished();
int currentStep();
py::array_t<double> getCellVolumes(); py::array_t<double> getCellVolumes();
double getDT();
py::array_t<double> getPorosity(); py::array_t<double> getPorosity();
int run(); int run();
void setPorosity( void setPorosity(
py::array_t<double, py::array::c_style | py::array::forcecast> array); py::array_t<double, py::array::c_style | py::array::forcecast> array);
int step(); int step();
void advance(int report_step);
int currentStep();
int stepInit();
int stepCleanup(); int stepCleanup();
const Opm::FlowMainEbos<TypeTag>& getFlowMainEbos() const; int stepInit();
private: private:
Opm::FlowMainEbos<TypeTag>& getFlowMainEbos() const;
PyMaterialState<TypeTag>& getMaterialState() const;
const std::string deck_filename_; const std::string deck_filename_;
bool has_run_init_ = false; bool has_run_init_ = false;
bool has_run_cleanup_ = false; bool has_run_cleanup_ = false;

View File

@ -54,6 +54,11 @@ if(OPM_ENABLE_PYTHON_TESTS)
COMMAND ${CMAKE_COMMAND} COMMAND ${CMAKE_COMMAND}
-E env PYTHONPATH=${PYTHON_PATH} ${PYTHON_EXECUTABLE} -E env PYTHONPATH=${PYTHON_PATH} ${PYTHON_EXECUTABLE}
-m unittest test/test_schedule.py) -m unittest test/test_schedule.py)
add_test(NAME python_throw
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/python
COMMAND ${CMAKE_COMMAND}
-E env PYTHONPATH=${PYTHON_PATH} ${PYTHON_EXECUTABLE}
-m unittest test/test_throw.py)
endif() endif()
find_file(PYTHON_INSTALL_PY install.py find_file(PYTHON_INSTALL_PY install.py

View File

@ -55,33 +55,46 @@ PyBlackOilSimulator::PyBlackOilSimulator(
{ {
} }
bool PyBlackOilSimulator::checkSimulationFinished() // Public methods alphabetically sorted
// ------------------------------------
void PyBlackOilSimulator::advance(int report_step)
{ {
return this->main_ebos_->getSimTimer()->done(); while (currentStep() < report_step) {
step();
}
} }
const Opm::FlowMainEbos<typename Opm::Pybind::PyBlackOilSimulator::TypeTag>& bool PyBlackOilSimulator::checkSimulationFinished()
PyBlackOilSimulator::getFlowMainEbos() const
{ {
if (this->main_ebos_) { return getFlowMainEbos().getSimTimer()->done();
return *this->main_ebos_; }
}
else { // This returns the report step number that will be executed next time step()
throw std::runtime_error("BlackOilSimulator not initialized: " // is called.
"Cannot get reference to FlowMainEbos object" ); int PyBlackOilSimulator::currentStep()
} {
return getFlowMainEbos().getSimTimer()->currentStepNum();
// NOTE: this->ebos_simulator_->episodeIndex() would also return the current
// report step number, but this number is always delayed by 1 step relative
// to this->main_ebos_->getSimTimer()->currentStepNum()
// See details in runStep() in file SimulatorFullyImplicitBlackoilEbos.hpp
}
py::array_t<double> PyBlackOilSimulator::getCellVolumes() {
std::size_t len;
auto array = getMaterialState().getCellVolumes(&len);
return py::array(len, array.get());
}
double PyBlackOilSimulator::getDT() {
return getFlowMainEbos().getPreviousReportStepSize();
} }
py::array_t<double> PyBlackOilSimulator::getPorosity() py::array_t<double> PyBlackOilSimulator::getPorosity()
{ {
std::size_t len; std::size_t len;
auto array = this->material_state_->getPorosity(&len); auto array = getMaterialState().getPorosity(&len);
return py::array(len, array.get());
}
py::array_t<double> PyBlackOilSimulator::getCellVolumes() {
std::size_t len;
auto array = this->material_state_->getCellVolumes(&len);
return py::array(len, array.get()); return py::array(len, array.get());
} }
@ -96,14 +109,7 @@ void PyBlackOilSimulator::setPorosity( py::array_t<double,
{ {
std::size_t size_ = array.size(); std::size_t size_ = array.size();
const double *poro = array.data(); const double *poro = array.data();
this->material_state_->setPorosity(poro, size_); getMaterialState().setPorosity(poro, size_);
}
void PyBlackOilSimulator::advance(int report_step)
{
while (currentStep() < report_step) {
step();
}
} }
int PyBlackOilSimulator::step() int PyBlackOilSimulator::step()
@ -119,26 +125,14 @@ int PyBlackOilSimulator::step()
} }
//if (this->debug_) //if (this->debug_)
// this->mainEbos_->getSimTimer()->report(std::cout); // this->mainEbos_->getSimTimer()->report(std::cout);
auto result = this->main_ebos_->executeStep(); auto result = getFlowMainEbos().executeStep();
return result; return result;
} }
// This returns the report step number that will be executed next time step()
// is called.
int PyBlackOilSimulator::currentStep()
{
return this->main_ebos_->getSimTimer()->currentStepNum();
// NOTE: this->ebos_simulator_->episodeIndex() would also return the current
// report step number, but this number is always delayed by 1 step relative
// to this->main_ebos_->getSimTimer()->currentStepNum()
// See details in runStep() in file SimulatorFullyImplicitBlackoilEbos.hpp
}
int PyBlackOilSimulator::stepCleanup() int PyBlackOilSimulator::stepCleanup()
{ {
this->has_run_cleanup_ = true; this->has_run_cleanup_ = true;
return this->main_ebos_->executeStepsCleanup(); return getFlowMainEbos().executeStepsCleanup();
} }
int PyBlackOilSimulator::stepInit() int PyBlackOilSimulator::stepInit()
@ -178,6 +172,34 @@ int PyBlackOilSimulator::stepInit()
} }
} }
// Private methods alphabetically sorted
// ------------------------------------
Opm::FlowMainEbos<typename Opm::Pybind::PyBlackOilSimulator::TypeTag>&
PyBlackOilSimulator::getFlowMainEbos() const
{
if (this->main_ebos_) {
return *this->main_ebos_;
}
else {
throw std::runtime_error("BlackOilSimulator not initialized: "
"Cannot get reference to FlowMainEbos object" );
}
}
PyMaterialState<typename Opm::Pybind::PyBlackOilSimulator::TypeTag>&
PyBlackOilSimulator::getMaterialState() const
{
if (this->material_state_) {
return *this->material_state_;
}
else {
throw std::runtime_error("BlackOilSimulator not initialized: "
"Cannot get reference to FlowMainEbos object" );
}
}
// Exported functions
void export_PyBlackOilSimulator(py::module& m) void export_PyBlackOilSimulator(py::module& m)
{ {
py::class_<PyBlackOilSimulator>(m, "BlackOilSimulator") py::class_<PyBlackOilSimulator>(m, "BlackOilSimulator")
@ -189,6 +211,7 @@ void export_PyBlackOilSimulator(py::module& m)
std::shared_ptr<Opm::SummaryConfig> >()) std::shared_ptr<Opm::SummaryConfig> >())
.def("get_cell_volumes", &PyBlackOilSimulator::getCellVolumes, .def("get_cell_volumes", &PyBlackOilSimulator::getCellVolumes,
py::return_value_policy::copy) py::return_value_policy::copy)
.def("get_dt", &PyBlackOilSimulator::getDT)
.def("get_porosity", &PyBlackOilSimulator::getPorosity, .def("get_porosity", &PyBlackOilSimulator::getPorosity,
py::return_value_policy::copy) py::return_value_policy::copy)
.def("run", &PyBlackOilSimulator::run) .def("run", &PyBlackOilSimulator::run)

View File

@ -0,0 +1,12 @@
import os
from contextlib import contextmanager
@contextmanager
def pushd(path):
cwd = os.getcwd()
if not os.path.isdir(path):
os.makedirs(path)
os.chdir(path)
yield
os.chdir(cwd)

View File

@ -3,16 +3,7 @@ import unittest
from contextlib import contextmanager from contextlib import contextmanager
from pathlib import Path from pathlib import Path
from opm.simulators import BlackOilSimulator from opm.simulators import BlackOilSimulator
from .pytest_common import pushd
@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): class TestBasic(unittest.TestCase):
@classmethod @classmethod
@ -63,6 +54,10 @@ class TestBasic(unittest.TestCase):
sim = BlackOilSimulator("SPE1CASE1.DATA") sim = BlackOilSimulator("SPE1CASE1.DATA")
sim.step_init() sim.step_init()
sim.step() sim.step()
dt = sim.get_dt()
# NOTE: The timestep should be 1 month = 31 days
# = 31 * 24 * 60 * 60 seconds = 2678400 seconds
self.assertAlmostEqual(dt, 2678400.0, places=7, msg='value of timestep')
vol = sim.get_cell_volumes() vol = sim.get_cell_volumes()
self.assertEqual(len(vol), 300, 'length of volume vector') self.assertEqual(len(vol), 300, 'length of volume vector')
# NOTE: The volume should be 1000 ft x 1000 ft x 20 ft * 0.3 (porosity) # NOTE: The volume should be 1000 ft x 1000 ft x 20 ft * 0.3 (porosity)

View File

@ -9,16 +9,7 @@ from opm.io.parser import Parser
from opm.io.ecl_state import EclipseState from opm.io.ecl_state import EclipseState
from opm.io.schedule import Schedule from opm.io.schedule import Schedule
from opm.io.summary import SummaryConfig from opm.io.summary import SummaryConfig
from .pytest_common import pushd
@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): class TestBasic(unittest.TestCase):
@classmethod @classmethod

22
python/test/test_throw.py Normal file
View File

@ -0,0 +1,22 @@
import os
import unittest
from pathlib import Path
from opm.simulators import BlackOilSimulator
from .pytest_common import pushd
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/SPE1CASE1a")
def test_all(self):
with pushd(self.data_dir):
sim = BlackOilSimulator("SPE1CASE1.DATA")
# NOTE: The following call should throw an exception since the simulation
# has not been initialized
with self.assertRaises(RuntimeError):
sim.get_dt()