mirror of
https://github.com/OPM/opm-simulators.git
synced 2024-12-27 09:40:59 -06:00
Merge pull request #3910 from hakonhagland/python_rates2
Dynamically update Opm::Schedule from Python
This commit is contained in:
commit
cce9e2d0b3
@ -387,6 +387,10 @@ namespace Opm
|
||||
return ebosSimulator_.get();
|
||||
}
|
||||
|
||||
SimulatorTimer* getSimTimer() {
|
||||
return simtimer_.get();
|
||||
}
|
||||
|
||||
private:
|
||||
// called by execute() or executeInitStep()
|
||||
int execute_(int (FlowMainEbos::* runOrInitFunc)(), bool cleanup)
|
||||
|
@ -44,11 +44,14 @@ public:
|
||||
std::shared_ptr<Opm::EclipseState> state,
|
||||
std::shared_ptr<Opm::Schedule> schedule,
|
||||
std::shared_ptr<Opm::SummaryConfig> summary_config);
|
||||
bool checkSimulationFinished();
|
||||
py::array_t<double> getPorosity();
|
||||
int run();
|
||||
void setPorosity(
|
||||
py::array_t<double, py::array::c_style | py::array::forcecast> array);
|
||||
int step();
|
||||
void advance(int report_step);
|
||||
int currentStep();
|
||||
int stepInit();
|
||||
int stepCleanup();
|
||||
const Opm::FlowMainEbos<TypeTag>& getFlowMainEbos() const;
|
||||
@ -57,7 +60,7 @@ private:
|
||||
const std::string deckFilename_;
|
||||
bool hasRunInit_ = false;
|
||||
bool hasRunCleanup_ = false;
|
||||
|
||||
bool debug_ = 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).
|
||||
|
@ -14,7 +14,8 @@ pybind11_add_module(simulators ${PYBIND11_SYSTEM}
|
||||
PyBlackOilSimulator.cpp
|
||||
Pybind11Exporter.cpp)
|
||||
|
||||
set_target_properties( simulators PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/python/opm2 )
|
||||
set(PYTHON_OPM_SIMULATORS_PACKAGE_PATH ${PROJECT_BINARY_DIR}/python/opm2/simulators)
|
||||
set_target_properties( simulators PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PYTHON_OPM_SIMULATORS_PACKAGE_PATH} )
|
||||
|
||||
target_sources(simulators
|
||||
PRIVATE
|
||||
@ -46,6 +47,9 @@ file( COPY ${PROJECT_SOURCE_DIR}/python/test
|
||||
DESTINATION ${PROJECT_BINARY_DIR}/python)
|
||||
file( COPY ${PROJECT_SOURCE_DIR}/python/test_data
|
||||
DESTINATION ${PROJECT_BINARY_DIR}/python)
|
||||
file( MAKE_DIRECTORY ${PYTHON_OPM_SIMULATORS_PACKAGE_PATH} )
|
||||
file( COPY ${PROJECT_SOURCE_DIR}/python/simulators/__init__.py
|
||||
DESTINATION ${PYTHON_OPM_SIMULATORS_PACKAGE_PATH})
|
||||
|
||||
if(OPM_ENABLE_PYTHON_TESTS)
|
||||
if(Python3_EXECUTABLE AND NOT PYTHON_EXECUTABLE)
|
||||
|
@ -52,6 +52,11 @@ PyBlackOilSimulator::PyBlackOilSimulator(
|
||||
{
|
||||
}
|
||||
|
||||
bool PyBlackOilSimulator::checkSimulationFinished()
|
||||
{
|
||||
return this->mainEbos_->getSimTimer()->done();
|
||||
}
|
||||
|
||||
const Opm::FlowMainEbos<typename Opm::Pybind::PyBlackOilSimulator::TypeTag>&
|
||||
PyBlackOilSimulator::getFlowMainEbos() const
|
||||
{
|
||||
@ -85,6 +90,13 @@ void PyBlackOilSimulator::setPorosity( py::array_t<double,
|
||||
materialState_->setPorosity(poro, size_);
|
||||
}
|
||||
|
||||
void PyBlackOilSimulator::advance(int report_step)
|
||||
{
|
||||
while (currentStep() < report_step) {
|
||||
step();
|
||||
}
|
||||
}
|
||||
|
||||
int PyBlackOilSimulator::step()
|
||||
{
|
||||
if (!hasRunInit_) {
|
||||
@ -93,9 +105,27 @@ int PyBlackOilSimulator::step()
|
||||
if (hasRunCleanup_) {
|
||||
throw std::logic_error("step() called after step_cleanup()");
|
||||
}
|
||||
return mainEbos_->executeStep();
|
||||
if(checkSimulationFinished()) {
|
||||
throw std::logic_error("step() called, but simulation is done");
|
||||
}
|
||||
//if (this->debug_)
|
||||
// this->mainEbos_->getSimTimer()->report(std::cout);
|
||||
auto result = mainEbos_->executeStep();
|
||||
return result;
|
||||
}
|
||||
|
||||
// This returns the report step number that will be executed next time step()
|
||||
// is called.
|
||||
int PyBlackOilSimulator::currentStep()
|
||||
{
|
||||
return this->mainEbos_->getSimTimer()->currentStepNum();
|
||||
// NOTE: this->ebosSimulator_->episodeIndex() would also return the current
|
||||
// report step number, but this number is always delayed by 1 step relative
|
||||
// to this->mainEbos_->getSimTimer()->currentStepNum()
|
||||
// See details in runStep() in file SimulatorFullyImplicitBlackoilEbos.hpp
|
||||
}
|
||||
|
||||
|
||||
int PyBlackOilSimulator::stepCleanup()
|
||||
{
|
||||
hasRunCleanup_ = true;
|
||||
@ -153,7 +183,9 @@ void export_PyBlackOilSimulator(py::module& m)
|
||||
py::return_value_policy::copy)
|
||||
.def("run", &PyBlackOilSimulator::run)
|
||||
.def("set_porosity", &PyBlackOilSimulator::setPorosity)
|
||||
.def("current_step", &PyBlackOilSimulator::currentStep)
|
||||
.def("step", &PyBlackOilSimulator::step)
|
||||
.def("advance", &PyBlackOilSimulator::advance, py::arg("report_step"))
|
||||
.def("step_init", &PyBlackOilSimulator::stepInit)
|
||||
.def("step_cleanup", &PyBlackOilSimulator::stepCleanup);
|
||||
}
|
||||
|
12
python/simulators/__init__.py
Normal file
12
python/simulators/__init__.py
Normal file
@ -0,0 +1,12 @@
|
||||
# Instead of having the pybind11 extension module, e.g.
|
||||
# simulators.cpython-310-x86_64-linux-gnu.so located
|
||||
# directly in the opm2 directory, we create a package (sub
|
||||
# directory) with the same name and place it there.
|
||||
# In this way we can do (if needed in the future)
|
||||
#
|
||||
# from opm.simulators import BlackOilSimulator, FoamSimulator, PurePythonUtils, ...
|
||||
#
|
||||
# where FoamSimulator and PurePythonUtils does not currently exists,
|
||||
# but could be possible future extensions..
|
||||
#
|
||||
from .simulators import BlackOilSimulator
|
@ -2,7 +2,7 @@ import os
|
||||
import unittest
|
||||
from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
from opm2.simulators import BlackOilSimulator
|
||||
from opm.simulators import BlackOilSimulator
|
||||
|
||||
@contextmanager
|
||||
def pushd(path):
|
||||
|
@ -3,7 +3,7 @@ import unittest
|
||||
from contextlib import contextmanager
|
||||
import datetime as dt
|
||||
from pathlib import Path
|
||||
from opm2.simulators import BlackOilSimulator
|
||||
from opm.simulators import BlackOilSimulator
|
||||
from opm.io.parser import Parser
|
||||
from opm.io.ecl_state import EclipseState
|
||||
from opm.io.schedule import Schedule
|
||||
@ -31,22 +31,72 @@ class TestBasic(unittest.TestCase):
|
||||
|
||||
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.deck = Parser().parse('SPE1CASE1.DATA')
|
||||
state = EclipseState(self.deck)
|
||||
self.schedule = Schedule( self.deck, state )
|
||||
summary_config = SummaryConfig(self.deck, state, self.schedule)
|
||||
self.unit_system = self.deck.active_unit_system()
|
||||
self.assertTrue('PROD' in self.schedule)
|
||||
self.assertTrue('INJ' in self.schedule)
|
||||
self.assertEqual(dt.datetime(2015, 1, 1), self.schedule.start)
|
||||
self.assertEqual(dt.datetime(2016, 1, 1), self.schedule.end)
|
||||
self.sim = BlackOilSimulator(
|
||||
self.deck, state, self.schedule, summary_config )
|
||||
tsteps = self.schedule.timesteps
|
||||
self.assertEqual(dt.datetime(2015, 1, 1), tsteps[0])
|
||||
last_step = len(tsteps) - 1
|
||||
self.assertEqual(dt.datetime(2016, 1, 1), tsteps[last_step])
|
||||
self.sim.step_init()
|
||||
report_step = 4
|
||||
self.sim.advance(report_step=report_step)
|
||||
well_name = "PROD"
|
||||
prod = self.schedule.get_well(well_name, 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()
|
||||
self.subtest_modify_schedule_dynamically(well_name, report_step)
|
||||
self.sim.step()
|
||||
self.sim.advance(report_step=last_step)
|
||||
self.sim.step_cleanup()
|
||||
|
||||
|
||||
def subtest_modify_schedule_dynamically(self, well_name, report_step):
|
||||
prop = self.schedule.get_production_properties(well_name, report_step)
|
||||
self.assertEqual(prop['alq_value'], 0.0)
|
||||
self.assertEqual(prop['bhp_target'], 1000.0)
|
||||
self.assertEqual(prop['gas_rate'], 0.0)
|
||||
self.assertEqual(prop['liquid_rate'], 0.0)
|
||||
self.assertEqual(prop['oil_rate'], 20000.0)
|
||||
self.assertEqual(prop['resv_rate'], 0.0)
|
||||
self.assertEqual(prop['thp_target'], 0.0)
|
||||
self.assertEqual(prop['water_rate'], 0.0)
|
||||
new_oil_target = prop['oil_rate'] + 10000 # stb/day
|
||||
#self.update_oil_target_wconprod(well_name, new_oil_target)
|
||||
self.update_oil_target_weltarg(well_name, new_oil_target)
|
||||
self.sim.step()
|
||||
prop2 = self.schedule.get_production_properties(well_name, report_step+1)
|
||||
self.assertEqual(prop2['oil_rate'], 30000.0)
|
||||
|
||||
def update_oil_target_weltarg(self, well_name, oil_target):
|
||||
data = """
|
||||
WELTARG
|
||||
'{}' ORAT {} /
|
||||
/
|
||||
""".format(well_name, oil_target)
|
||||
report_step = self.sim.current_step()
|
||||
self.schedule.insert_keywords(
|
||||
data, step=report_step, unit_system=self.unit_system)
|
||||
|
||||
def update_oil_target_wconprod(self, well_name, oil_target):
|
||||
well_status = "OPEN"
|
||||
control_mode = "ORAT"
|
||||
bhp_limit = 1000 # psia
|
||||
data = """
|
||||
WCONPROD
|
||||
'{}' '{}' '{}' {} 4* {} /
|
||||
/
|
||||
""".format(well_name, well_status, control_mode, oil_target, bhp_limit)
|
||||
report_step = self.sim.current_step()
|
||||
self.schedule.insert_keywords(
|
||||
data, step=report_step, unit_system=self.unit_system)
|
||||
|
Loading…
Reference in New Issue
Block a user