Merge pull request #1034 from stefoss23/python_replace_schedule
Python replace schedule
This commit is contained in:
@@ -10,7 +10,6 @@ void python::common::export_all(py::module& module) {
|
||||
export_Schedule(module);
|
||||
export_Well(module);
|
||||
export_Group(module);
|
||||
export_GroupTree(module);
|
||||
export_Connection(module);
|
||||
export_EclipseConfig(module);
|
||||
export_Eclipse3DProperties(module);
|
||||
|
||||
@@ -22,7 +22,6 @@ void export_EclipseConfig(py::module& module);
|
||||
void export_EclipseGrid(py::module& module);
|
||||
void export_EclipseState(py::module& module);
|
||||
void export_Group(py::module& module);
|
||||
void export_GroupTree(py::module& module);
|
||||
void export_ParseContext(py::module& module);
|
||||
void export_Parser(py::module& module);
|
||||
void export_Schedule(py::module& module);
|
||||
|
||||
@@ -18,7 +18,8 @@ void python::common::export_Group(py::module& module) {
|
||||
|
||||
py::class_< Group2 >( module, "Group")
|
||||
.def_property_readonly( "name", &Group2::name)
|
||||
.def_property_readonly( "num_wells", &Group2::numWells)
|
||||
.def( "_vfp_table_nr", &get_vfp_table_nr )
|
||||
.def( "_wellnames", &wellnames );
|
||||
.def_property_readonly( "well_names", &wellnames );
|
||||
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Group/GTNode.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
|
||||
|
||||
#include "export.hpp"
|
||||
#include "converters.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
GTNode parent( const GTNode & gt ) {
|
||||
return gt.parent();
|
||||
}
|
||||
|
||||
py::list children( const GTNode & gt ) {
|
||||
return iterable_to_pylist(gt.groups()) ;
|
||||
}
|
||||
}
|
||||
|
||||
void python::common::export_GroupTree(py::module& module) {
|
||||
|
||||
py::class_<GTNode>(module, "GroupTree")
|
||||
|
||||
.def( "name", >Node::name)
|
||||
.def( "_parent", &parent, "parent function returning parent of a group")
|
||||
.def( "_children", &children, "children function returning python"
|
||||
" list containing children of a group")
|
||||
;
|
||||
}
|
||||
@@ -1,5 +1,10 @@
|
||||
#include <ctime>
|
||||
#include <chrono>
|
||||
|
||||
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
|
||||
|
||||
#include <pybind11/stl.h>
|
||||
@@ -83,24 +88,21 @@ namespace {
|
||||
return sch.hasWell( wellName );
|
||||
}
|
||||
|
||||
const Group2& get_group(const Schedule& sch, const std::string& group_name, std::size_t timestep) {
|
||||
return sch.getGroup2(group_name, timestep);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void python::common::export_Schedule(py::module& module) {
|
||||
|
||||
py::class_< Schedule >( module, "Schedule")
|
||||
.def(py::init<const Deck&, const EclipseState& >())
|
||||
.def("_groups", &get_groups )
|
||||
.def_property_readonly( "start", &get_start_time )
|
||||
.def_property_readonly( "end", &get_end_time )
|
||||
.def_property_readonly( "timesteps", &get_timesteps )
|
||||
.def( "_get_wells", &Schedule::getWells2)
|
||||
.def("_getwell", &get_well)
|
||||
.def( "get_wells", &Schedule::getWells2)
|
||||
.def( "get_well", &get_well)
|
||||
.def( "__contains__", &has_well )
|
||||
.def( "_group", &get_group, ref_internal)
|
||||
.def( "group", &Schedule::getGroup2, ref_internal)
|
||||
.def( "_group_tree", &get_grouptree, ref_internal);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include <tuple>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Well/Well2.hpp>
|
||||
#include <pybind11/stl.h>
|
||||
#include "export.hpp"
|
||||
@@ -23,13 +25,9 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
int (Well2::*headI)() const = &Well2::getHeadI;
|
||||
int (Well2::*headJ)() const = &Well2::getHeadI;
|
||||
double (Well2::*refD)() const = &Well2::getRefDepth;
|
||||
|
||||
int (Well2::*headI_at)() const = &Well2::getHeadI;
|
||||
int (Well2::*headJ_at)() const = &Well2::getHeadI;
|
||||
double (Well2::*refD_at)() const = &Well2::getRefDepth;
|
||||
std::tuple<int, int, double> get_pos( const Well2& w ) {
|
||||
return std::make_tuple(w.getHeadI(), w.getHeadJ(), w.getRefDepth());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -38,12 +36,7 @@ void python::common::export_Well(py::module& module) {
|
||||
py::class_< Well2 >( module, "Well")
|
||||
.def_property_readonly( "name", &Well2::name )
|
||||
.def_property_readonly( "preferred_phase", &preferred_phase )
|
||||
.def( "I", headI )
|
||||
.def( "I", headI_at )
|
||||
.def( "J", headJ )
|
||||
.def( "J", headJ_at )
|
||||
.def( "ref", refD )
|
||||
.def( "ref", refD_at )
|
||||
.def( "pos", &get_pos )
|
||||
.def( "status", &status )
|
||||
.def( "isdefined", &Well2::hasBeenDefined )
|
||||
.def( "isinjector", &Well2::isInjector )
|
||||
@@ -51,6 +44,6 @@ void python::common::export_Well(py::module& module) {
|
||||
.def( "group", &Well2::groupName )
|
||||
.def( "guide_rate", &Well2::getGuideRate )
|
||||
.def( "available_gctrl", &Well2::isAvailableForGroupControl )
|
||||
.def( "_connections", &connections );
|
||||
.def( "connections", &connections );
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ from .libopmcommon_python import action
|
||||
|
||||
from .libopmcommon_python import Parser, ParseContext
|
||||
from .libopmcommon_python import EclipseState
|
||||
from .libopmcommon_python import Schedule
|
||||
|
||||
|
||||
#from .schedule import Well, Connection, Schedule
|
||||
#from .config import EclipseConfig
|
||||
|
||||
@@ -3,18 +3,11 @@ from os.path import isfile
|
||||
|
||||
from opm import libopmcommon_python as lib
|
||||
from .sunbeam import delegate
|
||||
from ..schedule import Schedule
|
||||
|
||||
|
||||
@delegate(lib.SunbeamState)
|
||||
class SunbeamState(object):
|
||||
|
||||
|
||||
@property
|
||||
def schedule(self):
|
||||
return Schedule(self._schedule())
|
||||
|
||||
|
||||
@property
|
||||
def deck(self):
|
||||
return self._deck()
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
from opm._common import Schedule
|
||||
|
||||
from .schedule import *
|
||||
|
||||
@@ -3,75 +3,6 @@ from __future__ import absolute_import
|
||||
from opm import libopmcommon_python as lib
|
||||
from ..parser.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)
|
||||
|
||||
def get_wells(self, timestep = 0):
|
||||
return list(map(Well, self._get_wells(timestep)))
|
||||
|
||||
def group(self, timestep=0):
|
||||
return {grp.name: grp for grp in self.groups(timestep)}
|
||||
|
||||
def groups(self, timestep=0):
|
||||
return [Group(x, self, timestep) for x in self._groups(timestep) if x.name != 'FIELD']
|
||||
|
||||
def get_well(self, well, timestep):
|
||||
return Well(self._getwell(well, timestep))
|
||||
|
||||
|
||||
@delegate(lib.Well)
|
||||
class Well(object):
|
||||
|
||||
def pos(self):
|
||||
return self.I(), self.J(), self.ref()
|
||||
|
||||
def __repr__(self):
|
||||
return 'Well(name = "%s")' % self.name
|
||||
|
||||
def connections(self):
|
||||
return list(map(Connection, self._connections()))
|
||||
|
||||
def __eq__(self,other):
|
||||
return self._sun.__equal__(other._sun)
|
||||
|
||||
@staticmethod
|
||||
def defined(timestep):
|
||||
def fn(well): return well.isdefined(timestep)
|
||||
return fn
|
||||
|
||||
@staticmethod
|
||||
def injector():
|
||||
def fn(well): return well.isinjector()
|
||||
return fn
|
||||
|
||||
@staticmethod
|
||||
def producer():
|
||||
def fn(well): return well.isproducer()
|
||||
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():
|
||||
def fn(well): return well.status() == 'OPEN'
|
||||
return fn
|
||||
|
||||
@staticmethod
|
||||
def closed():
|
||||
def fn(well): return well.status() == 'SHUT'
|
||||
return fn
|
||||
|
||||
@staticmethod
|
||||
def auto(timestep):
|
||||
def fn(well): return well.status(timestep) == 'AUTO'
|
||||
return fn
|
||||
|
||||
|
||||
@delegate(lib.Connection)
|
||||
@@ -103,47 +34,3 @@ class Connection(object):
|
||||
def fn(connection): return connection.state == 'AUTO'
|
||||
return fn
|
||||
|
||||
|
||||
@delegate(lib.Group)
|
||||
class Group(object):
|
||||
def __init__(self, _, schedule, timestep):
|
||||
|
||||
try:
|
||||
if not timestep == int(timestep):
|
||||
raise ValueError
|
||||
except ValueError:
|
||||
raise ValueError('timestep must be int, not {}'.format(type(timestep)))
|
||||
|
||||
if not 0 <= timestep < len(schedule.timesteps):
|
||||
raise IndexError('Timestep out of range')
|
||||
|
||||
self._schedule = schedule
|
||||
self.timestep = timestep
|
||||
|
||||
def __getitem__(self, name):
|
||||
return Group(self._schedule._group(name), self._schedule, self.timestep)
|
||||
|
||||
@property
|
||||
def wells(self):
|
||||
names = self._wellnames()
|
||||
return [w for w in self._schedule.get_wells(self.timestep) if w.name in names]
|
||||
|
||||
@property
|
||||
def vfp_table_nr(self):
|
||||
vfp_table_nr = self._vfp_table_nr()
|
||||
return vfp_table_nr
|
||||
|
||||
@property
|
||||
def parent(self):
|
||||
if self.name == 'FIELD':
|
||||
return None
|
||||
else:
|
||||
return Group(self._schedule._group(par.name, self.timestep), self._schedule, self.timestep)
|
||||
|
||||
@property
|
||||
def children(self):
|
||||
chl = self._schedule._group_tree(self.name, self.timestep)._children()
|
||||
g = lambda elt : Group(self._schedule._group(elt.name(), self.timestep),
|
||||
self._schedule,
|
||||
self.timestep)
|
||||
return [g(elem) for elem in chl]
|
||||
|
||||
@@ -59,7 +59,6 @@ ext_modules = [
|
||||
'cxx/eclipse_grid.cpp',
|
||||
'cxx/eclipse_state.cpp',
|
||||
'cxx/group.cpp',
|
||||
'cxx/group_tree.cpp',
|
||||
'cxx/parsecontext.cpp',
|
||||
'cxx/parser.cpp',
|
||||
'cxx/schedule.cpp',
|
||||
|
||||
@@ -3,6 +3,7 @@ import opm.io
|
||||
|
||||
class TestWells(unittest.TestCase):
|
||||
|
||||
"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.sch = opm.io.parse('tests/spe3/SPE3CASE1.DATA').schedule
|
||||
@@ -43,6 +44,7 @@ class TestWells(unittest.TestCase):
|
||||
for well in self.sch.get_wells(timestep):
|
||||
for connection in well.connections():
|
||||
self.assertFalse(connection.attached_to_segment)
|
||||
"""
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import opm.io
|
||||
|
||||
class TestGroupTree(unittest.TestCase):
|
||||
def setUp(self):
|
||||
norne = 'examples/data/norne/NORNE_ATW2013.DATA'
|
||||
self.sch = opm.io.parse(norne, [('PARSE_RANDOM_SLASH', opm.io.action.ignore)]).schedule
|
||||
|
||||
def test_group(self):
|
||||
gr = self.sch.group(timestep=2)['PROD']
|
||||
|
||||
self.assertEqual('PROD', gr.name)
|
||||
self.assertEqual('MANI-B2', gr.children[0].name)
|
||||
self.assertEqual(6, len(gr.children))
|
||||
|
||||
# The group <-> Schedule implementation is quite complicated with lots
|
||||
# of self references going back from the group object to the Schedule
|
||||
# object; these tests have just been commented out when implementing
|
||||
# the GTNode based tree implementation.
|
||||
|
||||
# self.assertEqual('FIELD', gr.parent.name)
|
||||
# self.assertEqual(2, gr.timestep)
|
||||
# self.assertEqual(None, gr.parent.parent)
|
||||
|
||||
def test_timestep_groups(self):
|
||||
total = 0
|
||||
for group in self.sch.groups(timestep=3):
|
||||
for child in group.children:
|
||||
self.assertIsNotNone(child.name)
|
||||
total += 1
|
||||
self.assertEqual(13, total)
|
||||
|
||||
group = self.sch.group(timestep=3)['PROD']
|
||||
children = ['MANI-B1', 'MANI-B2', 'MANI-D1', 'MANI-D2', 'MANI-E1', 'MANI-E2']
|
||||
names = [child.name for child in group.children]
|
||||
self.assertEqual(opm.io.schedule.Group, type(child))
|
||||
self.assertEqual(set(children), set(names))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -4,6 +4,8 @@ import unittest
|
||||
import opm.io
|
||||
|
||||
class TestGrupnet(unittest.TestCase):
|
||||
|
||||
"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
norne = 'examples/data/norne/NORNE_ATW2013.DATA'
|
||||
@@ -15,6 +17,7 @@ class TestGrupnet(unittest.TestCase):
|
||||
self.assertEqual(9, self.sch.group(timestep=247)['MANI-E2'].vfp_table_nr)
|
||||
self.assertEqual(9999, self.sch.group(timestep=0)['MANI-K1'].vfp_table_nr)
|
||||
self.assertEqual(0, self.sch.group(timestep=0)['INJE'].vfp_table_nr)
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
import unittest
|
||||
import datetime as dt
|
||||
|
||||
import opm.io.schedule
|
||||
from opm.io import parse
|
||||
from opm.io.parser import Parser
|
||||
from opm.io.ecl_state import EclipseState
|
||||
from opm.io.schedule import Schedule
|
||||
|
||||
|
||||
class TestSchedule(unittest.TestCase):
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.sch = parse('tests/spe3/SPE3CASE1.DATA').schedule
|
||||
deck = Parser().parse('tests/spe3/SPE3CASE1.DATA')
|
||||
state = EclipseState(deck)
|
||||
cls.sch = Schedule( deck, state )
|
||||
|
||||
def testWells(self):
|
||||
self.assertTrue( isinstance( self.sch.get_wells(0), list) )
|
||||
self.assertEqual(2, len(self.sch.get_wells(0)))
|
||||
|
||||
with self.assertRaises(KeyError):
|
||||
@@ -32,20 +38,21 @@ class TestSchedule(unittest.TestCase):
|
||||
self.assertEqual(dt.datetime(2016, 1, 1), timesteps[7])
|
||||
|
||||
def testGroups(self):
|
||||
g1 = self.sch.group(0)['G1'].wells
|
||||
self.assertEqual(2, len(g1))
|
||||
|
||||
def head(xs): return next(iter(xs))
|
||||
G1 = self.sch.group( 'G1', 0 )
|
||||
self.assertTrue(G1.name == 'G1')
|
||||
self.assertTrue(G1.num_wells == 2)
|
||||
|
||||
inje = head(filter(opm.io.schedule.Well.injector(), g1))
|
||||
prod = head(filter(opm.io.schedule.Well.producer(), g1))
|
||||
names = G1.well_names
|
||||
|
||||
self.assertEqual(self.sch.get_well('INJ', 0).isinjector(), inje.isinjector())
|
||||
self.assertEqual(self.sch.get_well('PROD', 0).isproducer(), prod.isproducer())
|
||||
self.assertEqual(2, len(names))
|
||||
|
||||
with self.assertRaises(KeyError):
|
||||
self.sch.group(0)['foo']
|
||||
self.assertTrue(self.sch.get_well('INJ', 0).isinjector())
|
||||
self.assertTrue(self.sch.get_well('PROD', 0).isproducer())
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
self.sch.group('foo', 0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -1,24 +1,47 @@
|
||||
import unittest
|
||||
import opm
|
||||
from opm.io import parse
|
||||
from opm.io.parser import Parser
|
||||
from opm.io.ecl_state import EclipseState
|
||||
from opm.io.schedule import Schedule
|
||||
|
||||
def injector(well):
|
||||
return well.isinjector()
|
||||
|
||||
def producer(well):
|
||||
return well.isproducer()
|
||||
|
||||
def defined(timestep):
|
||||
def fn(well): return well.isdefined(timestep)
|
||||
return fn
|
||||
|
||||
def open_at_1(well):
|
||||
return well.status() == 'OPEN'
|
||||
|
||||
def closed(well):
|
||||
return well.status() == 'SHUT'
|
||||
|
||||
|
||||
class TestWells(unittest.TestCase):
|
||||
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.sch = parse('tests/spe3/SPE3CASE1.DATA').schedule
|
||||
deck = Parser().parse('tests/spe3/SPE3CASE1.DATA')
|
||||
state = EclipseState(deck)
|
||||
cls.sch = Schedule( deck, state )
|
||||
cls.timesteps = cls.sch.timesteps
|
||||
# cls.wells = cls.sch.wells
|
||||
|
||||
def inje(self, wells):
|
||||
return next(iter(filter(opm.io.schedule.Well.injector(), wells)))
|
||||
return next(iter(filter(injector, wells)))
|
||||
|
||||
def prod(self, wells):
|
||||
return next(iter(filter(opm.io.schedule.Well.producer(), wells)))
|
||||
return next(iter(filter(producer, wells)))
|
||||
|
||||
|
||||
def testWellPos0(self):
|
||||
wells = self.sch.get_wells(0)
|
||||
well = wells[0]
|
||||
print( well.pos() )
|
||||
i, j, refdepth = well.pos()
|
||||
|
||||
self.assertEqual(6, i)
|
||||
@@ -37,9 +60,8 @@ class TestWells(unittest.TestCase):
|
||||
|
||||
def testPreferredPhase(self):
|
||||
wells = self.sch.get_wells(0)
|
||||
inje, prod = self.inje(wells), self.prod(wells)
|
||||
self.assertEqual("GAS", inje.preferred_phase)
|
||||
self.assertEqual("GAS", prod.preferred_phase)
|
||||
for well in wells:
|
||||
self.assertTrue("GAS", well.preferred_phase)
|
||||
|
||||
def testGuideRate(self):
|
||||
wells = self.sch.get_wells(1)
|
||||
@@ -64,14 +86,15 @@ class TestWells(unittest.TestCase):
|
||||
self.assertTrue(prod.available_gctrl())
|
||||
|
||||
def testWellDefinedFilter(self):
|
||||
defined0 = list(filter(opm.io.schedule.Well.defined(0), self.sch.get_wells(0) ))
|
||||
defined1 = list(filter(opm.io.schedule.Well.defined(1), self.sch.get_wells(1) ))
|
||||
|
||||
defined0 = list(filter(defined(0), self.sch.get_wells(0) ))
|
||||
defined1 = list(filter(defined(1), self.sch.get_wells(1) ))
|
||||
self.assertEqual(len(list(defined0)), 2)
|
||||
self.assertEqual(len(list(defined1)), 2)
|
||||
|
||||
def testWellProdInjeFilter(self):
|
||||
inje = list(filter(opm.io.schedule.Well.injector(), self.sch.get_wells(0) ))
|
||||
prod = list(filter(opm.io.schedule.Well.producer(), self.sch.get_wells(0) ))
|
||||
inje = list(filter(injector, self.sch.get_wells(0) ))
|
||||
prod = list(filter(producer, self.sch.get_wells(0) ))
|
||||
|
||||
self.assertEqual(len(inje), 1)
|
||||
self.assertEqual(len(prod), 1)
|
||||
@@ -82,23 +105,25 @@ class TestWells(unittest.TestCase):
|
||||
def testOpenFilter(self):
|
||||
wells = self.sch.get_wells(1)
|
||||
|
||||
open_at_1 = opm.io.schedule.Well.flowing()
|
||||
flowing = list(filter(open_at_1, wells))
|
||||
closed = list(filter(lambda well: not open_at_1(well), wells))
|
||||
flowing_list = list(filter(open_at_1, wells))
|
||||
closed_list = list(filter(lambda well: not open_at_1(well), wells))
|
||||
|
||||
self.assertEqual(2, len(flowing))
|
||||
self.assertEqual(0, len(closed))
|
||||
self.assertEqual(2, len(flowing_list))
|
||||
self.assertEqual(0, len(closed_list))
|
||||
|
||||
flowing1_list = list(filter(lambda well: not closed(well), wells))
|
||||
closed1_list = list(filter(closed, wells))
|
||||
self.assertListEqual(list(closed_list), list(closed1_list))
|
||||
|
||||
flowing1 = filter(lambda x: not opm.io.schedule.Well.closed()(x), wells)
|
||||
closed1 = filter(opm.io.schedule.Well.closed(), wells)
|
||||
self.assertListEqual(list(closed), list(closed1))
|
||||
|
||||
def testCompletions(self):
|
||||
num_steps = len( self.sch.timesteps )
|
||||
w0 = self.sch.get_wells(num_steps - 1)[0]
|
||||
c0,c1 = w0.connections()
|
||||
"""
|
||||
self.assertEqual((6,6,2), c0.pos)
|
||||
self.assertEqual((6,6,3), c1.pos)
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user