Rename python/python folder to python/opm
This makes bdist_wheel find and add the library binary files.
This commit is contained in:
0
python/opm/__init__.py
Normal file
0
python/opm/__init__.py
Normal file
33
python/opm/_common.py
Normal file
33
python/opm/_common.py
Normal file
@@ -0,0 +1,33 @@
|
||||
# This is the entry point were all the pybind11/C++ symbols are imported into
|
||||
# Python. Before actually being used the symbols are typically imported one
|
||||
# more time to a more suitable location; e.g the Parser() class is imported in
|
||||
# the opm/io/parser/__init__.py file as:
|
||||
#
|
||||
# from opm._common import Parser
|
||||
#
|
||||
# So that end user code can import it as:
|
||||
#
|
||||
# from opm.io.parser import Parser
|
||||
from __future__ import absolute_import
|
||||
from .libopmcommon_python import action
|
||||
|
||||
from .libopmcommon_python import Parser, ParseContext
|
||||
from .libopmcommon_python import DeckKeyword
|
||||
from .libopmcommon_python import DeckItem
|
||||
|
||||
from .libopmcommon_python import EclipseState
|
||||
from .libopmcommon_python import FieldProperties
|
||||
from .libopmcommon_python import Schedule
|
||||
from .libopmcommon_python import OpmLog
|
||||
from .libopmcommon_python import SummaryConfig
|
||||
from .libopmcommon_python import EclFile, eclArrType
|
||||
from .libopmcommon_python import ERst
|
||||
from .libopmcommon_python import ESmry
|
||||
from .libopmcommon_python import EGrid
|
||||
from .libopmcommon_python import ERft
|
||||
from .libopmcommon_python import EclOutput
|
||||
from .libopmcommon_python import SummaryState
|
||||
|
||||
#from .schedule import Well, Connection, Schedule
|
||||
#from .config import EclipseConfig
|
||||
#from .parser import parse, parse_string
|
||||
2
python/opm/io/__init__.py
Normal file
2
python/opm/io/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from .parser import *
|
||||
from .log import *
|
||||
40
python/opm/io/deck/__init__.py
Normal file
40
python/opm/io/deck/__init__.py
Normal file
@@ -0,0 +1,40 @@
|
||||
from opm._common import DeckKeyword
|
||||
from opm._common import DeckItem
|
||||
|
||||
|
||||
# in prinsiple it should be possible to use the has_value(int) function
|
||||
# on not only the first element. However, in 99% of the use cases it is the
|
||||
# first element which is of interesst. Hence for python bindings this is
|
||||
# hardcoded to the first element
|
||||
|
||||
@property
|
||||
def defaulted_deckitem(self):
|
||||
return self.__defaulted(0)
|
||||
|
||||
|
||||
@property
|
||||
def has_value_deckitem(self):
|
||||
return self.__has_value(0)
|
||||
|
||||
|
||||
@property
|
||||
def get_item_deckitem(self):
|
||||
|
||||
if self.is_int():
|
||||
return self.get_int(0)
|
||||
elif self.is_string():
|
||||
return self.get_str(0)
|
||||
elif self.is_double():
|
||||
return self.get_raw(0)
|
||||
elif self.is_uda():
|
||||
if self.__is_numberic():
|
||||
return self.__uda_double()
|
||||
else:
|
||||
return self.__uda_str()
|
||||
else:
|
||||
raise ValueError("Deck Item, unknown type")
|
||||
|
||||
|
||||
setattr(DeckItem, "defaulted", defaulted_deckitem)
|
||||
setattr(DeckItem, "valid", has_value_deckitem)
|
||||
setattr(DeckItem, "value", get_item_deckitem)
|
||||
221
python/opm/io/ecl/__init__.py
Normal file
221
python/opm/io/ecl/__init__.py
Normal file
@@ -0,0 +1,221 @@
|
||||
from opm._common import eclArrType
|
||||
from opm._common import EclFile
|
||||
from opm._common import ERst
|
||||
from opm._common import ESmry
|
||||
from opm._common import EGrid
|
||||
from opm._common import ERft
|
||||
from opm._common import EclOutput
|
||||
|
||||
import sys
|
||||
import datetime
|
||||
import numpy as np
|
||||
import datetime
|
||||
|
||||
# When extracting the strings from CHAR keywords we get a character array, in
|
||||
# Python this becomes a list of bytes. This desperate monkey-patching is to
|
||||
# ensure the EclFile class returns normal Python strings in the case of CHAR
|
||||
# arrays. The return value is normal Python list of strings.
|
||||
|
||||
@property
|
||||
def eclfile_get_list_of_arrays(self):
|
||||
|
||||
if sys.version_info.major == 2:
|
||||
rawData = self.__get_list_of_arrays()
|
||||
return [ ( x[0].encode("utf-8"), x[1], x[2] ) for x in rawData ]
|
||||
else:
|
||||
return self.__get_list_of_arrays()
|
||||
|
||||
|
||||
def getitem_eclfile(self, arg):
|
||||
|
||||
if isinstance(arg, tuple):
|
||||
data, array_type = self.__get_data(str(arg[0]), int(arg[1]))
|
||||
else:
|
||||
data, array_type = self.__get_data(arg)
|
||||
|
||||
if array_type == eclArrType.CHAR:
|
||||
return [ x.decode("utf-8") for x in data ]
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def erst_get_list_of_arrays(self, arg):
|
||||
|
||||
if sys.version_info.major==2:
|
||||
rawData = self.__get_list_of_arrays(arg)
|
||||
return [ ( x[0].encode("utf-8"), x[1], x[2] ) for x in rawData ]
|
||||
else:
|
||||
return self.__get_list_of_arrays(arg)
|
||||
|
||||
|
||||
def getitem_erst(self, arg):
|
||||
|
||||
if not isinstance(arg, tuple):
|
||||
raise ValueError("expecting tuple argument, (index, rstep), (name, rstep) or (name, rstep, occurrence) ")
|
||||
|
||||
if len(arg) == 2:
|
||||
if isinstance(arg[0], int):
|
||||
data, array_type = self.__get_data(arg[0], int(arg[1]))
|
||||
else:
|
||||
data, array_type = self.__get_data(str(arg[0]), int(arg[1]), 0) # default first occurrence
|
||||
elif len(arg) == 3:
|
||||
data, array_type = self.__get_data(str(arg[0]), int(arg[1]), int(arg[2]))
|
||||
else:
|
||||
raise ValueError("expecting tuple argument with 2 or 3 argumens: (index, rstep), (name, rstep) or (name, rstep, occurrence) ")
|
||||
|
||||
if array_type == eclArrType.CHAR:
|
||||
return [ x.decode("utf-8") for x in data ]
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def contains_erst(self, arg):
|
||||
|
||||
if isinstance(arg, tuple):
|
||||
if len(arg) == 2:
|
||||
return self.__contains((arg[0], arg[1]))
|
||||
else:
|
||||
raise ValueError("expecting tuple (array name , report step number) or \
|
||||
or report step number")
|
||||
|
||||
elif isinstance(arg, int):
|
||||
return self.__has_report_step(arg)
|
||||
|
||||
else:
|
||||
raise ValueError("expecting tuple (array name , report step number) or \
|
||||
or report step number")
|
||||
|
||||
@property
|
||||
def esmry_end_date(self):
|
||||
|
||||
start = self.start_date
|
||||
time = self.__get_all("TIME")
|
||||
|
||||
return start + datetime.timedelta(days = float(time[-1]))
|
||||
|
||||
|
||||
def getitem_esmry(self, arg):
|
||||
|
||||
if isinstance(arg, tuple):
|
||||
if arg[1] == True:
|
||||
return self.__get_at_rstep(arg[0])
|
||||
else:
|
||||
return self.__get_all(arg[0])
|
||||
else:
|
||||
return self.__get_all(arg)
|
||||
|
||||
|
||||
def contains_erft(self, arg):
|
||||
|
||||
if isinstance(arg, tuple):
|
||||
if len(arg) == 4:
|
||||
return self.__has_rft(arg[0], arg[1], arg[2], arg[3])
|
||||
elif len(arg) == 5:
|
||||
return self.__has_array(arg[0], arg[1], (arg[2], arg[3], arg[4]))
|
||||
elif len(arg) == 2:
|
||||
return self.__has_array(arg[0], arg[1])
|
||||
else:
|
||||
raise ValueError("expecting tuple (wellname, year, month, day) or \
|
||||
(arrayName, wellname, year, month, day) or (arrayName, report_index)")
|
||||
else:
|
||||
raise ValueError("expecting tuple (wellname, year, month, day) or \
|
||||
(arrayName, wellname, year, month, day) or (arrayName, report_index)")
|
||||
|
||||
@property
|
||||
def erft_list_of_rfts(self):
|
||||
|
||||
if sys.version_info.major==2:
|
||||
data = self.__get_list_of_rfts()
|
||||
return [ ( x[0].encode("utf-8"), x[1], x[2] ) for x in data ]
|
||||
else:
|
||||
return self.__get_list_of_rfts()
|
||||
|
||||
|
||||
def erft_list_of_arrays(self, arg1, arg2 = None):
|
||||
|
||||
if not arg2:
|
||||
data = self.__get_list_of_arrays(int(arg1))
|
||||
else:
|
||||
data = self.__get_list_of_arrays(str(arg1), int(arg2[0]), int(arg2[1]), int(arg2[2]))
|
||||
|
||||
if sys.version_info.major==2:
|
||||
return [ ( x[0].encode("utf-8"), x[1], x[2] ) for x in data ]
|
||||
else:
|
||||
return data
|
||||
|
||||
|
||||
def getitem_erft(self, arg):
|
||||
|
||||
if isinstance(arg, tuple):
|
||||
if len(arg) == 2:
|
||||
data, array_type = self.__get_data(arg[0], arg[1])
|
||||
elif len(arg) == 5:
|
||||
data, array_type = self.__get_data(arg[0], arg[1], arg[2], arg[3], arg[4])
|
||||
else:
|
||||
raise ValueError("ERft.__getitem__, expecting tuple (name, index) or (name, well, y, m, d)")
|
||||
else:
|
||||
raise ValueError("ERft.__getitem__, expecting tuple (name, index) or (name, well, y, m, d)")
|
||||
|
||||
if array_type == eclArrType.CHAR:
|
||||
return np.array([ x.decode("utf-8") for x in data ])
|
||||
else:
|
||||
return data
|
||||
|
||||
|
||||
'''
|
||||
EclOutput supports writing of numpy arrays. Data types
|
||||
(CHAR, LOGI, REAL, DOUB and INTE) is derived from the numpy dtype property
|
||||
EclOutput partly supports writing of python lists
|
||||
(CHAR, LOGI, INTE)
|
||||
'''
|
||||
|
||||
def ecloutput_write(self, name, array):
|
||||
|
||||
if isinstance(array, list):
|
||||
if all(isinstance(element, str) for element in array):
|
||||
array = np.array(array)
|
||||
elif all(isinstance(element, bool) for element in array):
|
||||
array = np.array(array)
|
||||
elif all(isinstance(element, int) for element in array):
|
||||
array = np.array(array, dtype = "int32")
|
||||
elif sys.version_info.major == 2 and all(isinstance(element, unicode) for element in array):
|
||||
array = np.array(array)
|
||||
else:
|
||||
raise ValueError("!!array {} is python list, type {}, not supported".format(name, type(array[0])))
|
||||
|
||||
if not isinstance(array, np.ndarray):
|
||||
raise ValueError("EclOutput - write function works only for numpy arrays")
|
||||
|
||||
if array.dtype == "float32":
|
||||
self.__write_real_array(name, array)
|
||||
elif array.dtype == "int32":
|
||||
self.__write_inte_array(name, array)
|
||||
elif array.dtype == "int64":
|
||||
print ("!Warning, writing numpy dtype=int64 to 32 bit integer format")
|
||||
self.__write_inte_array(name, array)
|
||||
elif array.dtype == "float64":
|
||||
self.__write_doub_array(name, array)
|
||||
elif array.dtype == "bool":
|
||||
self.__write_logi_array(name, array)
|
||||
elif array.dtype.kind in {'U', 'S'}:
|
||||
self.__write_char_array(name, array)
|
||||
else:
|
||||
raise ValueError("unknown array type for array {}".format(name))
|
||||
|
||||
|
||||
setattr(EclFile, "__getitem__", getitem_eclfile)
|
||||
setattr(EclFile, "arrays", eclfile_get_list_of_arrays)
|
||||
|
||||
setattr(ERst, "__contains__", contains_erst)
|
||||
setattr(ERst, "arrays", erst_get_list_of_arrays)
|
||||
setattr(ERst, "__getitem__", getitem_erst)
|
||||
|
||||
setattr(ESmry, "end_date", esmry_end_date)
|
||||
setattr(ESmry, "__getitem__", getitem_esmry)
|
||||
|
||||
setattr(ERft, "__contains__", contains_erft)
|
||||
setattr(ERft, "list_of_rfts", erft_list_of_rfts)
|
||||
setattr(ERft, "arrays", erft_list_of_arrays)
|
||||
setattr(ERft, "__getitem__",getitem_erft)
|
||||
|
||||
setattr(EclOutput, "write", ecloutput_write)
|
||||
1
python/opm/io/ecl_state/__init__.py
Normal file
1
python/opm/io/ecl_state/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from opm._common import EclipseState
|
||||
1
python/opm/io/log.py
Normal file
1
python/opm/io/log.py
Normal file
@@ -0,0 +1 @@
|
||||
from opm._common import OpmLog
|
||||
3
python/opm/io/parser/__init__.py
Normal file
3
python/opm/io/parser/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from opm._common import action
|
||||
from opm._common import Parser
|
||||
from opm._common import ParseContext
|
||||
1
python/opm/io/schedule/__init__.py
Normal file
1
python/opm/io/schedule/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from opm._common import Schedule
|
||||
1
python/opm/io/sim/__init__.py
Normal file
1
python/opm/io/sim/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from opm._common import SummaryState
|
||||
1
python/opm/io/summary/__init__.py
Normal file
1
python/opm/io/summary/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from opm._common import SummaryConfig
|
||||
1
python/opm/tools/__init__.py
Normal file
1
python/opm/tools/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .time_vector import TimeVector, TimeStep
|
||||
364
python/opm/tools/time_vector.py
Normal file
364
python/opm/tools/time_vector.py
Normal file
@@ -0,0 +1,364 @@
|
||||
import datetime
|
||||
from operator import attrgetter
|
||||
try:
|
||||
from StringIO import StringIO
|
||||
except ImportError:
|
||||
from io import StringIO
|
||||
|
||||
from opm.io.parser import Parser
|
||||
|
||||
# This is from the TimeMap.cpp implementation in opm
|
||||
ecl_month = {"JAN" : 1,
|
||||
"FEB" : 2,
|
||||
"MAR" : 3,
|
||||
"APR" : 4,
|
||||
"MAI" : 5,
|
||||
"MAY" : 5,
|
||||
"JUN" : 6,
|
||||
"JLY" : 7,
|
||||
"JUL" : 7,
|
||||
"AUG" : 8,
|
||||
"SEP" : 9,
|
||||
"OCT" : 10,
|
||||
"OKT" : 10,
|
||||
"NOV" : 11,
|
||||
"DEC" : 12,
|
||||
"DES" : 12}
|
||||
|
||||
inv_ecl_month = {1 : "JAN",
|
||||
2 : "FEB",
|
||||
3 : "MAR",
|
||||
4 : "APR",
|
||||
5 : "MAY",
|
||||
6 : "JUN",
|
||||
7 : "JUL",
|
||||
8 : "AUG",
|
||||
9 : "SEP",
|
||||
10: "OCT",
|
||||
11 : "NOV",
|
||||
12 : "DEC"}
|
||||
|
||||
def _make_datetime(dates_record):
|
||||
day = dates_record[0].get_int(0)
|
||||
month = dates_record[1].get_str(0)
|
||||
year = dates_record[2].get_int(0)
|
||||
|
||||
return datetime.datetime(year, ecl_month[month], day)
|
||||
|
||||
class TimeStep(object):
|
||||
|
||||
def __init__(self, dt, keywords):
|
||||
"""The TimeStep class consist of a list of keywords and a corresponding date.
|
||||
|
||||
Observe that the date value corresponds to a DATES / TSTEP keyword
|
||||
following *after* the keywords; i.e. if the TimeStep instance contains
|
||||
a WCONHIST keyword the settings in that keyword should apply *until*
|
||||
the date specified is reached. See the documentation of the TimeVector
|
||||
class for more details of the relationship between TimeVector and
|
||||
TimeStep.
|
||||
|
||||
"""
|
||||
self.dt = dt
|
||||
self.keywords = keywords
|
||||
self.tstep = None
|
||||
self.is_start = False
|
||||
|
||||
|
||||
@classmethod
|
||||
def create_first(cls, dt):
|
||||
ts = cls(dt, [])
|
||||
ts.is_start = True
|
||||
return ts
|
||||
|
||||
def add_keyword(self, kw):
|
||||
self.keywords.append(kw)
|
||||
|
||||
|
||||
|
||||
def __len__(self):
|
||||
return len(self.keywords)
|
||||
|
||||
def __contains__(self, arg):
|
||||
for kw in self.keywords:
|
||||
if arg == kw.name:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def __str__(self):
|
||||
string = StringIO()
|
||||
|
||||
if not self.is_start:
|
||||
day = self.dt.day
|
||||
month = self.dt.month
|
||||
year = self.dt.year
|
||||
string.write("DATES\n {day} '{month}' {year}/\n/\n\n".format( day=day, month = inv_ecl_month[month], year=year))
|
||||
|
||||
for kw in self.keywords:
|
||||
string.write(str(kw))
|
||||
string.write("\n")
|
||||
|
||||
return string.getvalue()
|
||||
|
||||
|
||||
class TimeVector(object):
|
||||
|
||||
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)
|
||||
|
||||
|
||||
def __len__(self):
|
||||
"""
|
||||
The number of timesteps in the vector.
|
||||
"""
|
||||
return len(self.time_steps_dict)
|
||||
|
||||
def __contains__(self, dt):
|
||||
"""
|
||||
Will return true if the vector contains a timestep at date dt.
|
||||
"""
|
||||
if isinstance(dt, datetime.date):
|
||||
dt = datetime.datetime(dt.year, dt.month, dt.day)
|
||||
return dt in self.time_steps_dict
|
||||
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""Will look up a timestep in the vector.
|
||||
|
||||
The index argument can either be an integer or a datetime instance.
|
||||
|
||||
"""
|
||||
if isinstance(index,int):
|
||||
return self.time_steps_list[index]
|
||||
else:
|
||||
if isinstance(index,datetime.date):
|
||||
index = datetime.datetime(index.year, index.month, index.day)
|
||||
return self.time_steps_dict[index]
|
||||
|
||||
|
||||
def _add_dates_block(self, ts):
|
||||
self.time_steps_dict[ts.dt] = ts
|
||||
self.time_steps_list.append(ts)
|
||||
|
||||
def delete(self, dt):
|
||||
del self.time_steps_dict[dt]
|
||||
for (index,ts) in enumerate(self.time_steps_list):
|
||||
if ts.dt == dt:
|
||||
del self.time_steps_list[index]
|
||||
break
|
||||
|
||||
|
||||
def add_keywords(self, dt, keywords):
|
||||
if dt < self.start_date:
|
||||
raise ValueError("Invalid datetime argument: {}".format(dt))
|
||||
|
||||
if dt in self.time_steps_dict:
|
||||
ts = self[dt]
|
||||
for kw in keywords:
|
||||
ts.add_keyword(kw)
|
||||
else:
|
||||
ts = TimeStep(dt, keywords)
|
||||
self._add_dates_block(ts)
|
||||
self.time_steps_list.sort( key = attrgetter("dt"))
|
||||
|
||||
|
||||
def _add_deck(self, deck, start_date):
|
||||
first_kw = deck[0]
|
||||
if start_date is None:
|
||||
if first_kw.name != "DATES":
|
||||
raise ValueError("When loading you must *either* specify date - or file must start with DATES keyword")
|
||||
dt = _make_datetime(first_kw[len(first_kw) - 1])
|
||||
else:
|
||||
if first_kw.name == "DATES":
|
||||
raise ValueError("When loading you must *either* specify date - or file must start with DATES keyword")
|
||||
dt = start_date
|
||||
|
||||
keywords = []
|
||||
for kw in deck:
|
||||
|
||||
if kw.name == "DATES":
|
||||
self.add_keywords(dt, keywords)
|
||||
|
||||
for index in range(len(kw)-1):
|
||||
dt = _make_datetime(kw[index])
|
||||
self.add_keywords(dt, [])
|
||||
|
||||
dt = _make_datetime(kw[len(kw)-1])
|
||||
|
||||
keywords = []
|
||||
continue
|
||||
|
||||
#if kw.name == "TSTEP":
|
||||
#raise ValueError("Must block the ranges with active TSTEP - getting a DATES in there is ERROR")
|
||||
|
||||
keywords.append(kw)
|
||||
|
||||
self.add_keywords(dt, keywords)
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
def __str__(self):
|
||||
"""Will return a string representation of the vector.
|
||||
|
||||
The output from this method should be valid Schedule input which can be
|
||||
passed to a simulator.
|
||||
|
||||
"""
|
||||
|
||||
string = StringIO()
|
||||
for ts in self:
|
||||
string.write(str(ts))
|
||||
|
||||
return string.getvalue()
|
||||
|
||||
|
||||
|
||||
|
||||
@property
|
||||
def dates(self):
|
||||
"""
|
||||
Will return a list of all the dates in the vector.
|
||||
"""
|
||||
return [ x.dt for x in self.time_steps_list ]
|
||||
Reference in New Issue
Block a user