added some config classes, refactored out files
This commit is contained in:
@@ -6,6 +6,9 @@ target_link_libraries( sunbeam ${Boost_LIBRARIES} ${opm-parser_LIBRARIES} )
|
||||
|
||||
set(PYTHON_SOURCES
|
||||
__init__.py
|
||||
sunbeam.py)
|
||||
sunbeam.py
|
||||
config.py
|
||||
properties.py
|
||||
schedule.py)
|
||||
|
||||
add_python_package(sunbeam sunbeam "${PYTHON_SOURCES}")
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from .sunbeam import parse
|
||||
from .sunbeam import Well
|
||||
from .schedule import Well
|
||||
from .libsunbeam import action
|
||||
from .properties import parse
|
||||
from .config import EclipseConfig
|
||||
|
||||
__version__ = '0.0.1'
|
||||
__license__ = 'GNU General Public License version 3'
|
||||
|
||||
13
python/sunbeam/config.py
Normal file
13
python/sunbeam/config.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from os.path import isfile
|
||||
import libsunbeam as lib
|
||||
from .sunbeam import delegate
|
||||
|
||||
@delegate(lib.SummaryConfig)
|
||||
class SummaryConfig(object):
|
||||
def __repr__(self):
|
||||
return 'SummaryConfig()'
|
||||
|
||||
@delegate(lib.EclipseConfig)
|
||||
class EclipseConfig(object):
|
||||
def __repr__(self):
|
||||
return 'EclipseConfig()'
|
||||
77
python/sunbeam/properties.py
Normal file
77
python/sunbeam/properties.py
Normal file
@@ -0,0 +1,77 @@
|
||||
from os.path import isfile
|
||||
import libsunbeam as lib
|
||||
from .sunbeam import delegate
|
||||
from .schedule import Schedule
|
||||
from .config import EclipseConfig
|
||||
|
||||
@delegate(lib.EclipseState)
|
||||
class EclipseState(object):
|
||||
def __repr__(self):
|
||||
return 'EclipseState(title = "%s")' % self.title
|
||||
|
||||
@property
|
||||
def schedule(self):
|
||||
return Schedule(self._schedule())
|
||||
|
||||
def props(self):
|
||||
return Eclipse3DProperties(self._props())
|
||||
|
||||
def grid(self):
|
||||
return EclipseGrid(self._grid())
|
||||
|
||||
def cfg(self):
|
||||
return EclipseConfig(self._cfg())
|
||||
|
||||
|
||||
@delegate(lib.Eclipse3DProperties)
|
||||
class Eclipse3DProperties(object):
|
||||
|
||||
def __repr__(self):
|
||||
return 'Eclipse3DProperties()'
|
||||
|
||||
|
||||
@delegate(lib.EclipseGrid)
|
||||
class EclipseGrid(object):
|
||||
|
||||
def getNX(self):
|
||||
return self._getXYZ()[0]
|
||||
def getNY(self):
|
||||
return self._getXYZ()[1]
|
||||
def getNZ(self):
|
||||
return self._getXYZ()[2]
|
||||
|
||||
def __repr__(self):
|
||||
x,y,z = self._getXYZ()
|
||||
g = self.cartesianSize()
|
||||
na = self.nactive()
|
||||
cnt = '(%d, %d, %d)' % (x,y,z)
|
||||
if na != g:
|
||||
cnt += ', active = %s' % na
|
||||
return 'EclipseGrid(%s)' % cnt
|
||||
|
||||
def _parse_context(actions):
|
||||
ctx = lib.ParseContext()
|
||||
|
||||
if actions is None:
|
||||
return ctx
|
||||
|
||||
# this might be a single tuple, in which case we unpack it and repack it
|
||||
# into a list. If it's not a tuple we assume it's an iterable and just
|
||||
# carry on
|
||||
try:
|
||||
key, action = actions
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
actions = [(key, action)]
|
||||
|
||||
for key, action in actions:
|
||||
ctx.update(key, action)
|
||||
|
||||
return ctx
|
||||
|
||||
def parse(deck, actions = None):
|
||||
"""deck may be a deck string, or a file path"""
|
||||
if isfile(deck):
|
||||
return EclipseState(lib.parse(deck, _parse_context(actions)))
|
||||
return EclipseState(lib.parseData(deck, _parse_context(actions)))
|
||||
79
python/sunbeam/schedule.py
Normal file
79
python/sunbeam/schedule.py
Normal file
@@ -0,0 +1,79 @@
|
||||
import libsunbeam as lib
|
||||
from .sunbeam import delegate
|
||||
|
||||
@delegate(lib.Schedule)
|
||||
class Schedule(object):
|
||||
|
||||
def __repr__(self):
|
||||
lt = len(self.timesteps)
|
||||
lw = len(self.wells)
|
||||
return 'Schedule(timesteps: %d, wells: %d)' % (lt, lw)
|
||||
|
||||
@property
|
||||
def wells(self):
|
||||
return map(Well, self._wells)
|
||||
|
||||
def group(self, name):
|
||||
return Group(self._group(name), self)
|
||||
|
||||
@property
|
||||
def groups(self):
|
||||
def mk(x): return Group(x, self)
|
||||
def not_field(x): return x.name != 'FIELD'
|
||||
return map(mk, filter(not_field, self._groups))
|
||||
|
||||
|
||||
@delegate(lib.Well)
|
||||
class Well(object):
|
||||
|
||||
def pos(self, timestep = None):
|
||||
if timestep is None:
|
||||
return self.I(), self.J(), self.ref()
|
||||
return self.I(timestep), self.J(timestep), self.ref(timestep)
|
||||
|
||||
def __repr__(self):
|
||||
return 'Well(name = "%s")' % self.name
|
||||
|
||||
@staticmethod
|
||||
def defined(timestep):
|
||||
def fn(well): return well.isdefined(timestep)
|
||||
return fn
|
||||
|
||||
@staticmethod
|
||||
def injector(timestep):
|
||||
def fn(well): return well.isinjector(timestep)
|
||||
return fn
|
||||
|
||||
@staticmethod
|
||||
def producer(timestep):
|
||||
def fn(well): return well.isproducer(timestep)
|
||||
return fn
|
||||
|
||||
# using the names flowing and closed for functions that test if a well is
|
||||
# opened or closed at some point, because we might want to use the more
|
||||
# imperative words 'open' and 'close' (or 'shut') for *changing* the status
|
||||
# later
|
||||
@staticmethod
|
||||
def flowing(timestep):
|
||||
def fn(well): return well.status(timestep) == 'OPEN'
|
||||
return fn
|
||||
|
||||
@staticmethod
|
||||
def closed(timestep):
|
||||
def fn(well): return well.status(timestep) == 'SHUT'
|
||||
return fn
|
||||
|
||||
@staticmethod
|
||||
def auto(timestep):
|
||||
def fn(well): return well.status(timestep) == 'AUTO'
|
||||
return fn
|
||||
|
||||
@delegate(lib.Group)
|
||||
class Group(object):
|
||||
def __init__(self, _, schedule):
|
||||
self._schedule = schedule
|
||||
|
||||
def wells(self, timestep):
|
||||
names = self._wellnames(timestep)
|
||||
wells = { well.name: well for well in self._schedule.wells }
|
||||
return map(wells.__getitem__, filter(wells.__contains__, names))
|
||||
@@ -2,6 +2,11 @@
|
||||
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseConfig.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/SimulationConfig/SimulationConfig.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/InitConfig/InitConfig.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/IOConfig/RestartConfig.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Well.hpp>
|
||||
@@ -23,6 +28,9 @@ py::list getNNC( const EclipseState& state ) {
|
||||
}
|
||||
}
|
||||
|
||||
namespace cfg {
|
||||
}
|
||||
|
||||
namespace grid {
|
||||
py::tuple getXYZ( const EclipseGrid& grid ) {
|
||||
return py::make_tuple( grid.getNX(),
|
||||
@@ -172,11 +180,16 @@ py::register_exception_translator< key_error >( &key_error::translate );
|
||||
py::def( "parse", parse );
|
||||
py::def( "parseData", parseData );
|
||||
|
||||
|
||||
/*
|
||||
* state, grid, properties
|
||||
*/
|
||||
py::class_< EclipseState >( "EclipseState", py::no_init )
|
||||
.add_property( "title", &EclipseState::getTitle )
|
||||
.def( "_schedule", &EclipseState::getSchedule, ref() )
|
||||
.def( "_props", &EclipseState::get3DProperties, ref() )
|
||||
.def( "_grid", &EclipseState::getInputGrid, ref() )
|
||||
.def( "_cfg", &EclipseState::cfg, ref() )
|
||||
.def( "has_input_nnc", &EclipseState::hasInputNNC )
|
||||
.def( "input_nnc", state::getNNC )
|
||||
;
|
||||
@@ -195,6 +208,45 @@ py::class_< Eclipse3DProperties >( "Eclipse3DProperties", py::no_init )
|
||||
.def( "__getitem__", props::getitem )
|
||||
;
|
||||
|
||||
/*
|
||||
* config
|
||||
*/
|
||||
py::class_< EclipseConfig >( "EclipseConfig", py::no_init )
|
||||
.def( "summary", &EclipseConfig::summary, ref())
|
||||
.def( "init", &EclipseConfig::init, ref())
|
||||
.def( "restart", &EclipseConfig::restart, ref())
|
||||
.def( "simulation", &EclipseConfig::simulation, ref())
|
||||
;
|
||||
|
||||
py::class_< SummaryConfig >( "SummaryConfig", py::no_init )
|
||||
.def( "__contains__", &SummaryConfig::hasKeyword )
|
||||
;
|
||||
|
||||
py::class_< InitConfig >( "InitConfig", py::no_init )
|
||||
.def( "hasEquil", &InitConfig::hasEquil )
|
||||
.def( "restartRequested", &InitConfig::restartRequested )
|
||||
.def( "getRestartStep" , &InitConfig::getRestartStep )
|
||||
;
|
||||
|
||||
py::class_< RestartConfig >( "RestartConfig", py::no_init )
|
||||
.def( "getKeyword", &RestartConfig::getKeyword )
|
||||
.def( "getFirstRestartStep", &RestartConfig::getFirstRestartStep )
|
||||
.def( "getWriteRestartFile", &RestartConfig::getWriteRestartFile )
|
||||
;
|
||||
|
||||
py::class_< SimulationConfig >( "SimulationConfig", py::no_init )
|
||||
.def("hasThresholdPressure", &SimulationConfig::hasThresholdPressure )
|
||||
.def("useCPR", &SimulationConfig::useCPR )
|
||||
.def("hasDISGAS", &SimulationConfig::hasDISGAS )
|
||||
.def("hasVAPOIL", &SimulationConfig::hasVAPOIL )
|
||||
;
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* schedule, well, completion, group
|
||||
*/
|
||||
py::class_< Well >( "Well", py::no_init )
|
||||
.add_property( "name", mkcopy( &Well::name ) )
|
||||
.add_property( "preferred_phase", &well::preferred_phase )
|
||||
@@ -242,6 +294,11 @@ py::class_< Schedule >( "Schedule", py::no_init )
|
||||
.def( "_group", &Schedule::getGroup, ref() )
|
||||
;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* misc
|
||||
*/
|
||||
py::class_< ParseContext >( "ParseContext" )
|
||||
.def( "update", ctx_update )
|
||||
;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
from os.path import isfile
|
||||
import libsunbeam as lib
|
||||
|
||||
class _delegate(object):
|
||||
@@ -40,148 +39,3 @@ def delegate(delegate_cls, to = '_sun'):
|
||||
return cls
|
||||
|
||||
return inner
|
||||
|
||||
@delegate(lib.Schedule)
|
||||
class Schedule(object):
|
||||
|
||||
def __repr__(self):
|
||||
lt = len(self.timesteps)
|
||||
lw = len(self.wells)
|
||||
return 'Schedule(timesteps: %d, wells: %d)' % (lt, lw)
|
||||
|
||||
@property
|
||||
def wells(self):
|
||||
return map(Well, self._wells)
|
||||
|
||||
def group(self, name):
|
||||
return Group(self._group(name), self)
|
||||
|
||||
@property
|
||||
def groups(self):
|
||||
def mk(x): return Group(x, self)
|
||||
def not_field(x): return x.name != 'FIELD'
|
||||
return map(mk, filter(not_field, self._groups))
|
||||
|
||||
@delegate(lib.Eclipse3DProperties)
|
||||
class Eclipse3DProperties(object):
|
||||
|
||||
def __repr__(self):
|
||||
return 'Eclipse3DProperties()'
|
||||
|
||||
@delegate(lib.EclipseGrid)
|
||||
class EclipseGrid(object):
|
||||
|
||||
def getNX(self):
|
||||
return self._getXYZ()[0]
|
||||
def getNY(self):
|
||||
return self._getXYZ()[1]
|
||||
def getNZ(self):
|
||||
return self._getXYZ()[2]
|
||||
|
||||
def __repr__(self):
|
||||
x,y,z = self._getXYZ()
|
||||
g = self.cartesianSize()
|
||||
na = self.nactive()
|
||||
cnt = '(%d, %d, %d)' % (x,y,z)
|
||||
if na != g:
|
||||
cnt += ', active = %s' % na
|
||||
return 'EclipseGrid(%s)' % cnt
|
||||
|
||||
|
||||
@delegate(lib.EclipseState)
|
||||
class EclipseState(object):
|
||||
def __repr__(self):
|
||||
return 'EclipseState(title = "%s")' % self.title
|
||||
|
||||
@property
|
||||
def schedule(self):
|
||||
return Schedule(self._schedule())
|
||||
|
||||
def props(self):
|
||||
return Eclipse3DProperties(self._props())
|
||||
|
||||
def grid(self):
|
||||
return EclipseGrid(self._grid())
|
||||
|
||||
@delegate(lib.Well)
|
||||
class Well(object):
|
||||
|
||||
def pos(self, timestep = None):
|
||||
if timestep is None:
|
||||
return self.I(), self.J(), self.ref()
|
||||
return self.I(timestep), self.J(timestep), self.ref(timestep)
|
||||
|
||||
def __repr__(self):
|
||||
return 'Well(name = "%s")' % self.name
|
||||
|
||||
@staticmethod
|
||||
def defined(timestep):
|
||||
def fn(well): return well.isdefined(timestep)
|
||||
return fn
|
||||
|
||||
@staticmethod
|
||||
def injector(timestep):
|
||||
def fn(well): return well.isinjector(timestep)
|
||||
return fn
|
||||
|
||||
@staticmethod
|
||||
def producer(timestep):
|
||||
def fn(well): return well.isproducer(timestep)
|
||||
return fn
|
||||
|
||||
# using the names flowing and closed for functions that test if a well is
|
||||
# opened or closed at some point, because we might want to use the more
|
||||
# imperative words 'open' and 'close' (or 'shut') for *changing* the status
|
||||
# later
|
||||
@staticmethod
|
||||
def flowing(timestep):
|
||||
def fn(well): return well.status(timestep) == 'OPEN'
|
||||
return fn
|
||||
|
||||
@staticmethod
|
||||
def closed(timestep):
|
||||
def fn(well): return well.status(timestep) == 'SHUT'
|
||||
return fn
|
||||
|
||||
@staticmethod
|
||||
def auto(timestep):
|
||||
def fn(well): return well.status(timestep) == 'AUTO'
|
||||
return fn
|
||||
|
||||
@delegate(lib.Group)
|
||||
class Group(object):
|
||||
def __init__(self, _, schedule):
|
||||
self._schedule = schedule
|
||||
|
||||
def wells(self, timestep):
|
||||
names = self._wellnames(timestep)
|
||||
wells = { well.name: well for well in self._schedule.wells }
|
||||
return map(wells.__getitem__, filter(wells.__contains__, names))
|
||||
|
||||
|
||||
def _parse_context(actions):
|
||||
ctx = lib.ParseContext()
|
||||
|
||||
if actions is None:
|
||||
return ctx
|
||||
|
||||
# this might be a single tuple, in which case we unpack it and repack it
|
||||
# into a list. If it's not a tuple we assume it's an iterable and just
|
||||
# carry on
|
||||
try:
|
||||
key, action = actions
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
actions = [(key, action)]
|
||||
|
||||
for key, action in actions:
|
||||
ctx.update(key, action)
|
||||
|
||||
return ctx
|
||||
|
||||
def parse(deck, actions = None):
|
||||
"""deck may be a deck string, or a file path"""
|
||||
if isfile(deck):
|
||||
return EclipseState(lib.parse(deck, _parse_context(actions)))
|
||||
return EclipseState(lib.parseData(deck, _parse_context(actions)))
|
||||
|
||||
Reference in New Issue
Block a user