diff --git a/python/sunbeam/properties.py b/python/sunbeam/properties.py index a622b4ae8..b450ec0dc 100644 --- a/python/sunbeam/properties.py +++ b/python/sunbeam/properties.py @@ -22,6 +22,13 @@ class EclipseState(object): def cfg(self): return EclipseConfig(self._cfg()) + def faults(self): + """Returns a map from fault names to list of (i,j,k,D) where D ~ 'X+'""" + fs = {} + for fn in self.faultNames(): + fs[fn] = self.faultFaces(fn) + return fs + @delegate(lib.Eclipse3DProperties) class Eclipse3DProperties(object): diff --git a/python/sunbeam/sunbeam.cpp b/python/sunbeam/sunbeam.cpp index 9cca02dd7..d4a93fcbf 100644 --- a/python/sunbeam/sunbeam.cpp +++ b/python/sunbeam/sunbeam.cpp @@ -8,6 +8,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -26,6 +30,42 @@ py::list getNNC( const EclipseState& state ) { l.append( py::make_tuple( x.cell1, x.cell2, x.trans ) ); return l; } +py::list faultNames( const EclipseState& state ) { + py::list l; + const auto& fc = state.getFaults(); + for (size_t i = 0; i < fc.size(); i++) { + const auto& f = fc.getFault(i); + l.append(f.getName()); + } + return l; +} + + const std::string faceDir( FaceDir::DirEnum dir ) { + switch (dir) { + case FaceDir::DirEnum::XPlus: return "X+"; + case FaceDir::DirEnum::XMinus: return "X-"; + case FaceDir::DirEnum::YPlus: return "Y+"; + case FaceDir::DirEnum::YMinus: return "Y-"; + case FaceDir::DirEnum::ZPlus: return "Z+"; + case FaceDir::DirEnum::ZMinus: return "Z-"; + } + return "Unknown direction"; +} +py::list faultFaces( const EclipseState& state, const std::string& name ) { + py::list l; + const auto& gr = state.getInputGrid(); // used for global -> IJK + const auto& fc = state.getFaults(); + const Fault& f = fc.getFault(name); + for (const auto& ff : f) { + // for each fault face + for (size_t g : ff) { + // for global index g in ff + const auto ijk = gr.getIJK(g); + l.append(py::make_tuple(ijk[0], ijk[1], ijk[2], faceDir(ff.getDir()))); + } + } + return l; +} } namespace cfg { @@ -192,6 +232,8 @@ py::class_< EclipseState >( "EclipseState", py::no_init ) .def( "_cfg", &EclipseState::cfg, ref() ) .def( "has_input_nnc", &EclipseState::hasInputNNC ) .def( "input_nnc", state::getNNC ) + .def( "faultNames", state::faultNames ) + .def( "faultFaces", state::faultFaces ) ; py::class_< EclipseGrid >( "EclipseGrid", py::no_init ) diff --git a/tests/state.py b/tests/state.py index 94adbb454..f0f9a3cac 100644 --- a/tests/state.py +++ b/tests/state.py @@ -4,6 +4,50 @@ import sunbeam class TestState(unittest.TestCase): spe3 = None + FAULTS_DECK = """ +RUNSPEC + +DIMENS + 10 10 10 / +GRID +DX +1000*0.25 / +DY +1000*0.25 / +DZ +1000*0.25 / +TOPS +100*0.25 / +FAULTS + 'F1' 1 1 1 4 1 4 'X' / + 'F2' 5 5 1 4 1 4 'X-' / +/ +MULTFLT + 'F1' 0.50 / + 'F2' 0.50 / +/ +EDIT +MULTFLT / + 'F2' 0.25 / +/ +OIL + +GAS + +TITLE +The title + +START +8 MAR 1998 / + +PROPS +REGIONS +SWAT +1000*1 / +SATNUM +1000*2 / +\ +""" def setUp(self): if self.spe3 is None: @@ -51,3 +95,13 @@ class TestState(unittest.TestCase): self.assertFalse(sim.useCPR()) self.assertTrue(sim.hasDISGAS()) self.assertTrue(sim.hasVAPOIL()) + + def test_faults(self): + self.assertEquals([], self.spe3.faultNames()) + self.assertEquals({}, self.spe3.faults()) + faultdeck = sunbeam.parse(self.FAULTS_DECK) + self.assertEqual(['F1', 'F2'], faultdeck.faultNames()) + # 'F2' 5 5 1 4 1 4 'X-' / \n" + f2 = faultdeck.faultFaces('F2') + self.assertTrue((4,0,0,'X-') in f2) + self.assertFalse((3,0,0,'X-') in f2)