Example #1
0
    def test_parser_deckItems(self):

        parser = Parser()

        error_recovery = [("PARSE_RANDOM_SLASH", opm.io.action.ignore),
                          ("PARSE_EXTRA_RECORDS", opm.io.action.ignore)]

        context = ParseContext(error_recovery)

        self.deck_spe1case1 = parser.parse(test_path("data/SPE1CASE1.DATA"),
                                           context)

        dkw_compdate = self.deck_spe1case1["COMPDAT"]

        self.assertTrue(dkw_compdate[0][0].is_string())
        self.assertFalse(dkw_compdate[0][1].is_string())

        self.assertTrue(dkw_compdate[0][1].is_int())
        self.assertFalse(dkw_compdate[0][1].is_double())

        self.assertTrue(dkw_compdate[0][8].is_double())

        self.assertTrue(dkw_compdate[0][0].value == "PROD")

        conI = dkw_compdate[0][1].value
        conJ = dkw_compdate[0][2].value
        conK = dkw_compdate[0][3].value

        self.assertEqual(dkw_compdate[0][5].value, "OPEN")

        self.assertTrue((conI, conJ, conK) == (10, 10, 3))

        self.assertFalse(dkw_compdate[0][7].valid)
        self.assertTrue(dkw_compdate[0][7].defaulted)

        self.assertEqual(dkw_compdate[0][6].value, 0)

        self.assertEqual(dkw_compdate[0][8].value, 0.5)

        dkw_wconprod = self.deck_spe1case1["WCONPROD"]

        welln = dkw_wconprod[0][0].value
        self.assertEqual(dkw_wconprod[0][2].value, "ORAT")
        self.assertEqual(dkw_wconprod[0][3].value, "WUOPRL")
        self.assertEqual(dkw_wconprod[0][5].value, 1.5e5)

        dkw_permx = self.deck_spe1case1["PERMX"]
        permx = dkw_permx.get_raw_array()
        self.assertEqual(len(permx), 300)
        self.assertTrue(isinstance(permx, np.ndarray))
        self.assertEqual(permx.dtype, "float64")

        dkw_eqlnum = self.deck_spe1case1["EQLNUM"]
        eqlnum = dkw_eqlnum.get_int_array()

        self.assertEqual(len(eqlnum), 300)
        self.assertTrue(isinstance(eqlnum, np.ndarray))
        self.assertEqual(eqlnum.dtype, "int32")
Example #2
0
    def setUpClass(cls):
        parser = Parser()
        cls.deck_cpa  = parser.parse(test_path('data/CORNERPOINT_ACTNUM.DATA'))
        cls.cp_state = EclipseState(cls.deck_cpa)

        cls.deck_spe3 = parser.parse(test_path('spe3/SPE3CASE1.DATA'))
        cls.state    = EclipseState(cls.deck_spe3)
        cls.schedule  = Schedule(cls.deck_spe3, cls.state)
        cls.summary_config = SummaryConfig(cls.deck_spe3, cls.state, cls.schedule)
Example #3
0
    def test_throw_on_invalid_recovery(self):
        recoveries = [("PARSE_RANDOM_SLASH", 3.14)]

        with self.assertRaises(TypeError):
            parse_context = ParseContext(recoveries)
            deck = Parser().parse(self.spe3fn, parse_context)

        with self.assertRaises(TypeError):
            parse_context = ParseContext("PARSE_RANDOM_SLASH")
            deck = Parser().parse(self.spe3fn, parse_context)
Example #4
0
 def test_faults(self):
     self.assertEquals([], self.state.faultNames())
     parser = Parser()
     faultdeck = parser.parse_string(self.FAULTS_DECK)
     faultstate = EclipseState(faultdeck)
     self.assertEqual(['F1', 'F2'], faultstate.faultNames())
     # 'F2'  5  5  1  4   1  4  'X-' / \n"
     f2 = faultstate.faultFaces('F2')
     self.assertTrue((4, 0, 0, 'X-') in f2)
     self.assertFalse((3, 0, 0, 'X-') in f2)
Example #5
0
    def test_dynamic_parser2(self):
        parser = Parser(add_default=False)
        builtin = Builtin()
        kw_list = [
            "START", "RUNSPEC", "FIELD", "REGIONS", "DIMENS", "GRID", "DX",
            "DY", "DZ", "TOPS", "OPERNUM", "FIPNUM"
        ]
        for kw in kw_list:
            parser.add_keyword(builtin[kw])

        deck = parser.parse_string(self.REGIONDATA)
Example #6
0
    def test_jfunc(self):
        # jf["FLAG"]         = WATER; # set in deck
        # jf["DIRECTION"]    = XY;    # default
        # jf["ALPHA_FACTOR"] = 0.5    # default
        # jf["BETA_FACTOR"]  = 0.5    # default
        # jf["OIL_WATER"]    = 21.0   # set in deck
        # jf["GAS_OIL"]      = -1.0   # N/A

        parser = Parser()
        deck = parser.parse(test_path('data/JFUNC.DATA'))
        js = EclipseState(deck)
        self.assertEqual('JFUNC TEST', js.title)
        jf = js.jfunc()
        print(jf)
        self.assertEqual(jf['FLAG'], 'WATER')
        self.assertEqual(jf['DIRECTION'], 'XY')
        self.assertFalse('GAS_OIL' in jf)
        self.assertTrue('OIL_WATER' in jf)
        self.assertEqual(jf['OIL_WATER'], 21.0)
        self.assertEqual(jf["ALPHA_FACTOR"], 0.5)  # default
        self.assertEqual(jf["BETA_FACTOR"], 0.5)  # default

        jfunc_gas = """
DIMENS
 10 10 10 /
ENDSCALE
/
GRID
DX
1000*0.25 /
DY
1000*0.25 /
DZ
1000*0.25 /
TOPS
100*0.25 /
PORO
  1000*0.15 /
JFUNC
  GAS * 13.0 0.6 0.7 Z /
PROPS\nREGIONS
"""
        deck2 = parser.parse_string(jfunc_gas)
        js_gas = EclipseState(deck2)
        jf = js_gas.jfunc()
        self.assertEqual(jf['FLAG'], 'GAS')
        self.assertEqual(jf['DIRECTION'], 'Z')
        self.assertTrue('GAS_OIL' in jf)
        self.assertFalse('OIL_WATER' in jf)
        self.assertEqual(jf['GAS_OIL'], 13.0)
        self.assertEqual(jf["ALPHA_FACTOR"], 0.6)  # default
        self.assertEqual(jf["BETA_FACTOR"], 0.7)  # default
Example #7
0
    def test_parse_ignore_keyword(self):
        deck_string = """
FIPNUM
  100*1 100*2 /

KEYWORD
  1 2 3 /
        """

        parse_context = ParseContext()
        parser = Parser()
        parse_context.ignore_keyword("KEYWORD")
        deck = parser.parse_string(deck_string, parse_context)
        self.assertEqual(len(deck), 1)
Example #8
0
    def test_parser_extension(self):
        error_recovery = [("PARSE_RANDOM_SLASH", opm.io.action.ignore)]

        parse_context = ParseContext(error_recovery)
        parser = Parser()
        for kw in self.KEYWORDS:
            parser.add_keyword(json.dumps(kw))

        deck = parser.parse_string(self.DECK_ADDITIONAL_KEYWORDS,
                                   parse_context)

        self.assertIn('TESTKEY0', deck)
        self.assertIn('TESTKEY1', deck)
        self.assertIn('TESTKEY2', deck)
Example #9
0
 def setUpClass(cls):
     deck = Parser().parse(test_path('spe3/SPE3CASE1.DATA'))
     print("Creating state")
     cls.state = EclipseState(deck)
     print("State OK")
     cls.sch = Schedule(deck, cls.state)
     cls.timesteps = cls.sch.timesteps
Example #10
0
 def test_well_names(self):
     deck = Parser().parse(test_path('spe3/SPE3CASE1.DATA'))
     state = EclipseState(deck)
     sch = Schedule(deck, state)
     wnames = sch.well_names("*")
     self.assertTrue("PROD" in wnames)
     self.assertTrue("INJ" in wnames)
     self.assertEqual(len(wnames), 2)
Example #11
0
    def test_parse_with_multiple_recoveries(self):
        recoveries = [("PARSE_RANDOM_SLASH", opm.io.action.ignore),
                      ("FOO", opm.io.action.warn),
                      ("PARSE_RANDOM_TEXT", opm.io.action.throw)]

        parse_context = ParseContext(recoveries)
        deck = Parser().parse(self.spe3fn, parse_context)
        state = EclipseState(deck)
Example #12
0
    def test_parse_norne(self):
         parse_context = ParseContext( [('PARSE_RANDOM_SLASH', opm.io.action.ignore)] )
         deck = Parser().parse(self.norne_fname, parse_context)
         es = EclipseState( deck )

         self.assertEqual(46, es.grid().nx)
         self.assertEqual(112, es.grid().ny)
         self.assertEqual(22, es.grid().nz)
Example #13
0
    def test_raw_string_output(self):
        deck_string = """
UDQ
   DEFINE WUOPR2   WOPR '*' * WOPR '*' /
   DEFINE WUGASRA  3 - WGLIR '*' /
/
        """

        parse_context = ParseContext( )
        parser = Parser()
        parse_context.ignore_keyword("KEYWORD")
        deck = parser.parse_string( deck_string )
        udq = deck[0]
        s = ""
        for rec in udq:
            for item in rec:
                s += item.get_str(0)
Example #14
0
    def test_deck_kw_vector(self):
        parser = Parser()
        deck = parser.parse_string(self.REGIONDATA)
        active_unit_system = deck.active_unit_system()
        default_unit_system = deck.default_unit_system()
        self.assertEqual(active_unit_system.name, "Field")

        int_array = np.array([0, 1, 2, 3])
        hbnum_kw = DeckKeyword( parser["HBNUM"], int_array)
        assert( np.array_equal(hbnum_kw.get_int_array(), int_array) )

        raw_array = np.array([1.1, 2.2, 3.3])
        zcorn_kw = DeckKeyword( parser["ZCORN"], raw_array, active_unit_system, default_unit_system)
        assert( np.array_equal(zcorn_kw.get_raw_array(), raw_array) )
        si_array = zcorn_kw.get_SI_array()
        self.assertAlmostEqual( si_array[0], 1.1 * unit_foot )
        self.assertAlmostEqual( si_array[2], 3.3 * unit_foot )
Example #15
0
def parse(fname):
    s = dt.now()
    ps = ParseContext([('PARSE_RANDOM_SLASH', opm.io.action.ignore)])
    deck = Parser().parse(fname, ps)
    es = EclipseState(deck)
    e = dt.now()
    print('Parsing took %s sec' % (e - s).seconds)
    return es
Example #16
0
    def test_deck_kw_records_uda(self):
        parser = Parser()
        deck = parser.parse_string(self.REGIONDATA)
        active_unit_system = deck.active_unit_system()
        default_unit_system = deck.default_unit_system()
        oil_target = 30000  # stb/day
        well_name = "PROD"
        well_status = "OPEN"
        control_mode = "ORAT"
        bhp_limit = 1000  # psia

        wconprod = DeckKeyword(parser["WCONPROD"], [[
            well_name, well_status, control_mode, oil_target, "4*", bhp_limit
        ]], active_unit_system, default_unit_system)

        self.assertEqual(len(wconprod), 1)
        record = wconprod[0]
        self.assertEqual(record[0].name(), "WELL")
        self.assertTrue(record[0].is_string())
        self.assertEqual(record[0].get_str(0), "PROD")
        self.assertEqual(record[1].name(), "STATUS")
        self.assertTrue(record[1].is_string())
        self.assertEqual(record[1].get_str(0), "OPEN")
        self.assertEqual(record[2].name(), "CMODE")
        self.assertTrue(record[2].is_string())
        self.assertEqual(record[2].get_str(0), "ORAT")
        self.assertEqual(record[3].name(), "ORAT")
        self.assertTrue(record[3].is_uda())
        self.assertEqual(record[3].value, 30000)
        self.assertEqual(record[4].name(), "WRAT")
        self.assertTrue(record[4].is_uda())
        self.assertEqual(record[4].value, 0)
        self.assertEqual(record[5].name(), "GRAT")
        self.assertTrue(record[5].is_uda())
        self.assertEqual(record[5].value, 0)
        self.assertEqual(record[6].name(), "LRAT")
        self.assertTrue(record[6].is_uda())
        self.assertEqual(record[6].value, 0)
        self.assertEqual(record[7].name(), "RESV")
        self.assertTrue(record[7].is_uda())
        self.assertEqual(record[7].value, 0)
        self.assertEqual(record[8].name(), "BHP")
        self.assertTrue(record[8].is_uda())
        self.assertEqual(record[8].value, 1000)
Example #17
0
    def test_no_leading_DATES(self):
        tv = TimeVector(datetime.date(1997, 11, 6),
                        base_file=test_path("data/schedule/part1.sch"))
        s = str(tv)
        d = Parser().parse_string(s)
        kw0 = d[0]
        self.assertEqual(kw0.name, "WELSPECS")

        tv2 = TimeVector(datetime.date(2000, 1, 1))
        self.assertEqual("", str(tv2))
Example #18
0
    def test_getitem(self):
        deck = Parser().parse(test_path('spe3/SPE3CASE1.DATA'))
        state = EclipseState(deck)
        sch = Schedule(deck, state)
        self.assertEqual(len(sch), 176)
        with self.assertRaises(IndexError):
            a = sch[200]

        st100 = sch[100]
        nupcol = st100.nupcol
Example #19
0
    def test_open_shut(self):
        deck = Parser().parse(test_path('spe3/SPE3CASE1.DATA'))
        state = EclipseState(deck)
        sch = Schedule(deck, state)
        prod = sch.get_well("PROD", 1)
        self.assertEqual(prod.status(), "OPEN")

        sch.shut_well("PROD", 10)
        prod = sch.get_well("PROD", 10)
        self.assertEqual(prod.status(), "SHUT")
Example #20
0
    def test_parser_section_deckItems(self):

        all_spe1case1 = [
            "RUNSPEC", "TITLE", "DIMENS", "EQLDIMS", "TABDIMS", "REGDIMS",
            "OIL", "GAS", "WATER", "DISGAS", "FIELD", "START", "WELLDIMS",
            "UNIFOUT", "UDQDIMS", "UDADIMS", "GRID", "INIT", "NOECHO", "DX",
            "DY", "DZ", "TOPS", "PORO", "PERMX", "PERMY", "PERMZ", "ECHO",
            "PROPS", "PVTW", "ROCK", "SWOF", "SGOF", "DENSITY", "PVDG", "PVTO",
            "REGIONS", "EQLNUM", "FIPNUM", "SOLUTION", "EQUIL", "RSVD",
            "SUMMARY", "FOPR", "WGOR", "FGOR", "BPR", "BGSAT", "WBHP", "WGIR",
            "WGIT", "WGPR", "WGPT", "WOIR", "WOIT", "WOPR", "WOPT", "WWIR",
            "WWIT", "WWPR", "WWPT", "WUOPRL", "SCHEDULE", "UDQ", "RPTSCHED",
            "RPTRST", "DRSDT", "WELSPECS", "COMPDAT", "WCONPROD", "WCONINJE",
            "TSTEP"
        ]

        # notice that RUNSPEC keywords will always be parsed since these properties from these keyword
        # are needed to parse following sections.

        props_spe1case1 = [
            "RUNSPEC", "TITLE", "DIMENS", "EQLDIMS", "TABDIMS", "REGDIMS",
            "OIL", "GAS", "WATER", "DISGAS", "FIELD", "START", "WELLDIMS",
            "UNIFOUT", "UDQDIMS", "UDADIMS", "GRID", "PVTW", "ROCK", "SWOF",
            "SGOF", "DENSITY", "PVDG", "PVTO"
        ]

        parser = Parser()

        error_recovery = [("PARSE_RANDOM_SLASH", opm.io.action.ignore),
                          ("PARSE_EXTRA_RECORDS", opm.io.action.ignore)]

        context = ParseContext(error_recovery)

        deck1 = parser.parse(test_path("data/SPE1CASE1.DATA"), context)

        self.assertEqual(len(deck1), len(all_spe1case1))

        test_1 = [dkw.name for dkw in deck1]

        for test, ref in zip(test_1, all_spe1case1):
            self.assertEqual(test, ref)

        section_list = [eclSectionType.PROPS]

        deck2 = parser.parse(test_path("data/SPE1CASE1.DATA"), context,
                             section_list)

        self.assertEqual(len(deck2), len(props_spe1case1))

        test_2 = [dkw.name for dkw in deck2]

        for test, ref in zip(test_2, props_spe1case1):
            self.assertEqual(test, ref)

        # props section keyword located in include file for this deck (SPE1CASE1B.DATA)
        # not possible to parse individual sections

        with self.assertRaises(RuntimeError):
            parser.parse(test_path("data/SPE1CASE1B.DATA"), context,
                         section_list)
Example #21
0
 def test_injection_properties(self):
     deck = Parser().parse(test_path('spe3/SPE3CASE1.DATA'))
     state = EclipseState(deck)
     sch = Schedule(deck, state)
     report_step = 4
     well_name = 'INJ'
     prop = sch.get_injection_properties(well_name, report_step)
     self.assertEqual(prop['surf_inj_rate'], 4700.0)  # Mscf/day
     self.assertEqual(prop['resv_inj_rate'], 0.0)  # rb/day
     self.assertEqual(prop['bhp_target'], 4000.0)  # psi
     self.assertEqual(prop['thp_target'], 0.0)
     with self.assertRaises(IndexError):
         prop = sch.get_injection_properties("UNDEF", report_step)
     with self.assertRaises(KeyError):
         prop = sch.get_injection_properties("PROD", report_step)
Example #22
0
def main():
    deck = Parser().parse('../tests/spe3/SPE3CASE1.DATA')
    es = EclipseState(deck)
    sc = Schedule(deck, es)
    wp = sc.get_wells(0)[0] # producer
    wi = sc.get_wells(0)[1] # injector
    print('state:     %s' % es)
    print('schedule:  %s' % sc)
    print('prod well: %s' % wp)
    print('inj  well: %s' % wi)
    for i in range(len(sc.timesteps)):
        if not sc.get_wells(i)[0].isproducer() or sc.get_wells(i)[0].isinjector():
            print('wp is not producer in step %s' % sc.timesteps[i])
        if not sc.get_wells(i)[1].isinjector() or sc.get_wells(i)[1].isproducer():
            print('wi is not injector in step %s' % sc.timesteps[i])
Example #23
0
 def test_production_properties(self):
     deck = Parser().parse(test_path('spe3/SPE3CASE1.DATA'))
     state = EclipseState(deck)
     sch = Schedule(deck, state)
     report_step = 4
     well_name = 'PROD'
     prop = sch.get_production_properties(well_name, report_step)
     self.assertEqual(prop['alq_value'], 0.0)
     self.assertEqual(prop['bhp_target'], 500.0)
     self.assertEqual(prop['gas_rate'], 6200.0)
     self.assertEqual(prop['liquid_rate'], 0.0)
     self.assertEqual(prop['oil_rate'], 0.0)
     self.assertEqual(prop['resv_rate'], 0.0)
     self.assertEqual(prop['thp_target'], 0.0)
     self.assertEqual(prop['water_rate'], 0.0)
Example #24
0
    def test_create(self):
        parser = Parser()
        deck = parser.parse(self.spe3fn)

        context = ParseContext()
        deck = parser.parse(self.spe3fn, context)

        with open(self.spe3fn) as f:
            string = f.read()
        deck = parser.parse_string(string)
        deck = parser.parse_string(string, context)
Example #25
0
    def test_create(self):
        parser = Parser()
        deck = parser.parse(self.spe3fn)
        active_unit_system = deck.active_unit_system()
        default_unit_system = deck.default_unit_system()
        self.assertEqual(active_unit_system.name, "Field")

        context = ParseContext()
        deck = parser.parse(self.spe3fn, context)

        with open(self.spe3fn) as f:
            string = f.read()
        deck = parser.parse_string(string)
        deck = parser.parse_string(string, context)
Example #26
0
    def load(self, filename, date=None):
        """Will parse a Schedule file and add the keywords to the current TimeVector.

        You can call the load() method repeatedly, the different timesteps will
        be ordered chronologically. If a timestep is already present the
        keywords will be appended.

        The optional date argument can be used to insert schedule file
        fragments which do not have any DATES / TSTEP keywords. Assuming you
        have a base file 'base.sch' and a small fragment 'well.sch' with the
        WELSPECS and COMPDAT keywords to create one well, then the new well can
        be added 1.st of April 2017 as this:

            tv = TimeVector( start )
            tv.load("base.sch")
            tv.load("well.sch", date = datetime.datetime(2017, 4, 1))

        """
        deck = Parser().parse(filename)
        self._add_deck(deck, date)
Example #27
0
 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.assertEqual(prod.status(), "OPEN")
         #schedule.shut_well("PROD", 3)
         #prod = schedule.get_well("PROD", 3)
         #self.assertEqual(prod.status(), "SHUT")
         sim.step()
         sim.step()
Example #28
0
 def load_string(self, deck_string, date=None):
     """
     Like load() - but load from a string literal instead of file.
     """
     deck = Parser().parse_string(deck_string)
     self._add_deck(deck, date)
Example #29
0
    def __init__(self, start_date, base_string=None, base_file=None):
        """The TimeVector class is a simple vector class with DATES/TSTEP blocks.

         The TimeVector class is a basic building block for tools designed to
         update schedule files. A schedule file consists of a list of keywords
         related to the dynamic properties of the field, like opening and
         closing wells, specifiying rates and so on. The temporal advancement of
         the simulator is controlled by DATES and TSTEP keywords. A typical
         schedule section can look like this:

         --- Step 1 -----------------------

         WELSPECS
            'C1'   'G1'   10 10 10 'OIL' /
         /

         COMPDAT
            'C1' 15 20 10 16 'OPEN' /
            'C1' 15 21 16 16 'OPEN' /
         /

         WCONHIST
            'C1' 'OPEN'  'ORAT' 1000 /
         /

         --- Step 2 ----------------------

         DATES
            10  'MAY' 2016 /
         /

         WCONHIST
            'C1'  'OPEN'  'ORAT' 2000 /
         /

        --- Step 3 ----------------------

         TSTEP
             10 /

         WELSPECS
            'W2'  'G1'  5 5 5 'OIL' /
         /

         COMPDAT
            'W2' 10 10 7 10 'OPEN' /
         /

         WCONHIST
            'C1' 'OPEN' 'ORAT' 3000 /
            'W2' 'OPEN' 'ORAT' 1500 /
         /

         --- Step 4 ----------------------

         DATES
            30 'MAY' 2016 /
         /

         As indicated above the DATES and TSTEP keywords act as delimiters in
         the schedule file. In the TimeVector class the fundamental unit is
         TimeStep instance which consists of a list of keywords, and a
         terminating DATES or TSTEP keyword, the example above would correspond
         to a TimeVector with three TimeStep instances.

         Basic usage example:

            #!/usr/bin/env python
            from opm.tools import TimeVector

            # Create vector and load history.
            tv = TimeVector( start )
            tv.load("history.sch")


            # Load predictions from another file
            tv.load("prediction.sch")


            # Insert the definition of one particular well at
            # a specifed date.
            tv.load("extra_wll.sch", date = datetime.datetime(2018,10,1))


            # Check if we have a certain timestep:
            if datetime.datetime(2017,1,1) in tv:
                print("We have it!")
            else:
                print("No such date")


            # Dump the updated schedule content to a file:
            with open("schedule","w") as f:
                 f.write(str(tv))


        """
        if base_string and base_file:
            raise ValueError(
                "Can only supply one of base_string and base_file arguments")

        self.start_date = datetime.datetime(start_date.year, start_date.month,
                                            start_date.day)
        self.time_steps_dict = {}
        self.time_steps_list = []

        ts = TimeStep.create_first(self.start_date)

        self._add_dates_block(ts)
        start_dt = datetime.datetime(start_date.year, start_date.month,
                                     start_date.day)
        if base_file:
            deck = Parser().parse(base_file)
            self._add_deck(deck, start_dt)

        if base_string:
            deck = Parser().parse_string(base_string)
            self._add_deck(deck, start_dt)
Example #30
0
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/SPE1CASE1b")

    def test_all(self):
        with pushd(self.data_dir):
            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")
            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_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)
        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_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'], 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)

    # 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 {} /
/
        """.format(well_name, oil_target)
        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 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
        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)