Dynamically update schedule from Python

Adds some test cases that show how injection properties in Opm::Schedule
can be dynamically modified from Python.
This commit is contained in:
Håkon Hægland
2022-05-18 14:41:13 +02:00
parent 5e00a0ae59
commit 3c0498e55f
4 changed files with 106 additions and 18 deletions

View File

@@ -3,6 +3,7 @@ import unittest
from contextlib import contextmanager
import datetime as dt
from pathlib import Path
import re
from opm.simulators import BlackOilSimulator
from opm.io.parser import Parser
from opm.io.ecl_state import EclipseState
@@ -36,6 +37,7 @@ class TestBasic(unittest.TestCase):
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)
@@ -55,13 +57,32 @@ class TestBasic(unittest.TestCase):
#schedule.shut_well("PROD", 3)
#prod = schedule.get_well("PROD", 3)
#self.assertEqual(prod.status(), "SHUT")
self.subtest_modify_schedule_dynamically(well_name, report_step)
self.subtest_modify_prod_weltarg_dynamically(well_name, report_step)
self.sim.step()
report_step = self.sim.current_step()
well_name = "INJ"
self.subtest_modify_inj_weltarg_dynamically(well_name, report_step)
self.sim.advance(report_step=last_step)
self.sim.step_cleanup()
def subtest_modify_inj_weltarg_dynamically(self, well_name, report_step):
prop = self.schedule.get_injection_properties(well_name, report_step)
self.assertEqual(prop['surf_inj_rate'], 100000.0) # Mscf/day
self.assertEqual(prop['resv_inj_rate'], 0.0) # rb/day
self.assertEqual(prop['bhp_target'], 9014.0) # psi
self.assertEqual(prop['thp_target'], 0.0)
new_grat_target = prop['surf_inj_rate'] - 100 # stb/day
self.update_inj_grat_target_wconinje(well_name, new_grat_target)
self.sim.step()
prop2 = self.schedule.get_injection_properties(well_name, report_step+1)
self.assertEqual(prop2['surf_inj_rate'], new_grat_target)
new_grat_target += 200
self.update_inj_grat_target_weltarg(well_name, new_grat_target)
self.sim.step()
prop3 = self.schedule.get_injection_properties(well_name, report_step+2)
self.assertEqual(prop3['surf_inj_rate'], new_grat_target)
def subtest_modify_schedule_dynamically(self, well_name, report_step):
def subtest_modify_prod_weltarg_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)
@@ -72,13 +93,43 @@ class TestBasic(unittest.TestCase):
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.update_prod_orat_target_wconprod(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)
self.assertEqual(prop2['oil_rate'], new_oil_target)
new_oil_target += 1000
self.update_prod_orat_target_weltarg(well_name, new_oil_target)
self.sim.step()
prop3 = self.schedule.get_production_properties(well_name, report_step+2)
self.assertEqual(prop3['oil_rate'], new_oil_target)
def update_oil_target_weltarg(self, well_name, oil_target):
# This is an alternative to using WELTARG
def update_inj_grat_target_wconinje(self, well_name, new_surf_flow_rate):
data = self.deck["WCONINJE"]
# assumes data looks like this:
# WCONINJE
# 'INJ' 'GAS' 'OPEN' 'RATE' 100000 1* 9014 /
# /
# The initial rate can also be obtained from data[0][4].get_uda(0).get_double()
data = re.sub(pattern='100000', repl=str(new_surf_flow_rate), string=str(data), count=1)
report_step = self.sim.current_step()
self.schedule.insert_keywords(
data, step=report_step, unit_system=self.unit_system)
# This is an alternative to using WCONINJE to modify injection properties
def update_inj_grat_target_weltarg(self, well_name, net_surf_flow_rate):
data = """
WELTARG
'{}' GRAT {} /
/
""".format(well_name, net_surf_flow_rate)
report_step = self.sim.current_step()
self.schedule.insert_keywords(
data, step=report_step, unit_system=self.unit_system)
# This is an alternative to using WCONPROD to modify production properties
def update_prod_orat_target_weltarg(self, well_name, oil_target):
data = """
WELTARG
'{}' ORAT {} /
@@ -88,7 +139,8 @@ WELTARG
self.schedule.insert_keywords(
data, step=report_step, unit_system=self.unit_system)
def update_oil_target_wconprod(self, well_name, oil_target):
# This is an alternative to using WELTARG to modify production properties
def update_prod_orat_target_wconprod(self, well_name, oil_target):
well_status = "OPEN"
control_mode = "ORAT"
bhp_limit = 1000 # psia