From 172725aef8ed8ea439c29ea5beacd670ddc82a3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A5l=20Gr=C3=B8n=C3=A5s=20Drange?= Date: Fri, 28 Oct 2016 13:57:00 +0200 Subject: [PATCH] Added JFUNC in TableManager and getJFuncColumn() * Fully internalized JFUNC * Added JFunc.cpp, throw on wrong FLAG/DIR in JFUNC kw * added tests for JFUNC in TableManagerTests * added protected member m_jfunc to SimpleTable * Added getJFuncColumn to accompany getPcowColumn * Throws if pressure or jfunc is accessed inappropriately * ... meaning if getPcowColumn is called when JFUNC is in deck, or * getJFuncColumn is called when JFUNC is not in deck * added tests for throwing and for getJFuncColumn * SimpleTable.getColumn("PCOW/PCOG") throws if JFUNC * In the event that one tries to get "PCOW" or "PCOG" via getColumn * ... this will throw if JFUNC is present in the deck. * Added tests. --- opm/parser/eclipse/CMakeLists.txt | 2 + .../eclipse/EclipseState/Tables/JFunc.cpp | 92 ++++++++++ .../eclipse/EclipseState/Tables/JFunc.hpp | 55 ++++++ .../eclipse/EclipseState/Tables/SgfnTable.hpp | 4 +- .../eclipse/EclipseState/Tables/SgofTable.hpp | 4 +- .../EclipseState/Tables/SimpleTable.cpp | 31 +++- .../EclipseState/Tables/SimpleTable.hpp | 6 +- .../EclipseState/Tables/SlgofTable.hpp | 4 +- .../eclipse/EclipseState/Tables/SwfnTable.hpp | 9 +- .../eclipse/EclipseState/Tables/SwofTable.hpp | 5 +- .../EclipseState/Tables/TableManager.cpp | 29 +++- .../EclipseState/Tables/TableManager.hpp | 50 ++++++ .../eclipse/EclipseState/Tables/Tables.cpp | 51 +++++- .../Tables/tests/TableContainerTests.cpp | 2 +- .../Tables/tests/TableManagerTests.cpp | 163 +++++++++++++++++- .../eclipse/IntegrationTests/ParseSGOF.cpp | 2 +- .../eclipse/IntegrationTests/ParseSLGOF.cpp | 2 +- .../eclipse/IntegrationTests/ParseSWOF.cpp | 2 +- 18 files changed, 476 insertions(+), 37 deletions(-) create mode 100644 opm/parser/eclipse/EclipseState/Tables/JFunc.cpp create mode 100644 opm/parser/eclipse/EclipseState/Tables/JFunc.hpp diff --git a/opm/parser/eclipse/CMakeLists.txt b/opm/parser/eclipse/CMakeLists.txt index 534f67bfa..a1fd2f76d 100644 --- a/opm/parser/eclipse/CMakeLists.txt +++ b/opm/parser/eclipse/CMakeLists.txt @@ -103,6 +103,7 @@ EclipseState/Schedule/GroupTree.cpp EclipseState/Schedule/Tuning.cpp EclipseState/Schedule/Events.cpp # +EclipseState/Tables/JFunc.cpp EclipseState/Tables/SimpleTable.cpp EclipseState/Tables/VFPProdTable.cpp EclipseState/Tables/VFPInjTable.cpp @@ -227,6 +228,7 @@ EclipseState/IOConfig/RestartConfig.hpp EclipseState/IOConfig/IOConfig.hpp # EclipseState/Tables/FlatTable.hpp +EclipseState/Tables/JFunc.hpp EclipseState/Tables/Tabdims.hpp EclipseState/Tables/Eqldims.hpp EclipseState/Tables/Regdims.hpp diff --git a/opm/parser/eclipse/EclipseState/Tables/JFunc.cpp b/opm/parser/eclipse/EclipseState/Tables/JFunc.cpp new file mode 100644 index 000000000..99b30bdc5 --- /dev/null +++ b/opm/parser/eclipse/EclipseState/Tables/JFunc.cpp @@ -0,0 +1,92 @@ +/* + Copyright 2016 Statoil ASA. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . + */ + +#include +#include +#include + +namespace Opm { + + JFunc::JFunc(const Deck& deck) : + m_exists(deck.hasKeyword("JFUNC")) + { + if (!m_exists) + return; + const auto& kw = *deck.getKeywordList()[0]; + const auto& rec = kw.getRecord(0); + const auto& kw_flag = rec.getItem("FLAG").get(0); + if (kw_flag == "BOTH") + flag = Flag::BOTH; + else if (kw_flag == "WATER") + flag = Flag::WATER; + else if (kw_flag == "GAS") + flag = Flag::GAS; + else + throw std::invalid_argument("Illegal JFUNC FLAG, must be BOTH, WATER, or GAS. Was \"" + kw_flag + "\"."); + + if (flag != Flag::WATER) + goSurfaceTension = rec.getItem("GO_SURFACE_TENSION").get(0); + + if (flag != Flag::GAS) + owSurfaceTension = rec.getItem("OW_SURFACE_TENSION").get(0); + + alphaFactor = rec.getItem("ALPHA_FACTOR").get(0); + betaFactor = rec.getItem("BETA_FACTOR").get(0); + + const auto kw_dir = rec.getItem("DIRECTION").get(0); + if (kw_dir == "XY") + direction = Direction::XY; + else if (kw_dir == "X") + direction = Direction::X; + else if (kw_dir == "Y") + direction = Direction::Y; + else if (kw_dir == "Z") + direction = Direction::Z; + else + throw std::invalid_argument("Illegal JFUNC DIRECTION, must be XY, X, Y, or Z. Was \"" + kw_dir + "\"."); + } + + double JFunc::getAlphaFactor() const { + return alphaFactor; + } + + double JFunc::getBetaFactor() const { + return betaFactor; + } + + double JFunc::getgoSurfaceTension() const { + if (flag == JFunc::Flag::WATER) + throw std::invalid_argument("Cannot get gas-oil with WATER JFUNC"); + return goSurfaceTension; + } + + double JFunc::getowSurfaceTension() const { + if (flag == JFunc::Flag::GAS) + throw std::invalid_argument("Cannot get oil-water with GAS JFUNC"); + return owSurfaceTension; + } + + const JFunc::Flag& JFunc::getJFuncFlag() const { + return flag; + } + + const JFunc::Direction& JFunc::getDirection() const { + return direction; + } +} // Opm:: diff --git a/opm/parser/eclipse/EclipseState/Tables/JFunc.hpp b/opm/parser/eclipse/EclipseState/Tables/JFunc.hpp new file mode 100644 index 000000000..8ccb8a289 --- /dev/null +++ b/opm/parser/eclipse/EclipseState/Tables/JFunc.hpp @@ -0,0 +1,55 @@ +/* + Copyright 2016 Statoil ASA. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . + */ + +#ifndef OPM_JFUNC_HPP_ +#define OPM_JFUNC_HPP_ + +#include + + +namespace Opm { + +class JFunc +{ +public: + + enum class Flag { BOTH, WATER, GAS }; + enum class Direction { XY, X, Y, Z }; + + JFunc(const Deck& deck); + double getAlphaFactor() const; + double getBetaFactor() const; + double getgoSurfaceTension() const; + double getowSurfaceTension() const; + const Flag& getJFuncFlag() const; + const Direction& getDirection() const; + operator bool() const { return m_exists; } + +private: + Flag flag; // JFUNC flag: WATER, GAS, or BOTH. Default BOTH + double owSurfaceTension; // oil-wat surface tension. Required if flag is BOTH or WATER + double goSurfaceTension; // gas-oil surface tension. Required if flag is BOTH or GAS + double alphaFactor; // alternative porosity term. Default 0.5 + double betaFactor; // alternative permeability term. Default 0.5 + Direction direction; // XY, X, Y, Z. Default XY + const bool m_exists; // will be true if JFunc is specified in the deck +}; +} // Opm:: + +#endif /* OPM_JFUNC_HPP_ */ diff --git a/opm/parser/eclipse/EclipseState/Tables/SgfnTable.hpp b/opm/parser/eclipse/EclipseState/Tables/SgfnTable.hpp index 4080c5267..bf46a0204 100644 --- a/opm/parser/eclipse/EclipseState/Tables/SgfnTable.hpp +++ b/opm/parser/eclipse/EclipseState/Tables/SgfnTable.hpp @@ -28,11 +28,13 @@ namespace Opm { class SgfnTable : public SimpleTable { public: - SgfnTable( const DeckItem& item ); + SgfnTable( const DeckItem& item, const bool jfunc ); const TableColumn& getSgColumn() const; const TableColumn& getKrgColumn() const; const TableColumn& getPcogColumn() const; + + const TableColumn& getJFuncColumn() const; }; } diff --git a/opm/parser/eclipse/EclipseState/Tables/SgofTable.hpp b/opm/parser/eclipse/EclipseState/Tables/SgofTable.hpp index 3335d5c72..a9a49e151 100644 --- a/opm/parser/eclipse/EclipseState/Tables/SgofTable.hpp +++ b/opm/parser/eclipse/EclipseState/Tables/SgofTable.hpp @@ -27,7 +27,7 @@ namespace Opm { class SgofTable : public SimpleTable { public: - SgofTable( const DeckItem& item ); + SgofTable( const DeckItem& item, const bool jfunc ); const TableColumn& getSgColumn() const; const TableColumn& getKrgColumn() const; @@ -38,6 +38,8 @@ namespace Opm { // is inconsistent, but it is the one used in the Eclipse // manual...) const TableColumn& getPcogColumn() const; + + const TableColumn& getJFuncColumn() const; }; } diff --git a/opm/parser/eclipse/EclipseState/Tables/SimpleTable.cpp b/opm/parser/eclipse/EclipseState/Tables/SimpleTable.cpp index e570d6617..e26affdb1 100644 --- a/opm/parser/eclipse/EclipseState/Tables/SimpleTable.cpp +++ b/opm/parser/eclipse/EclipseState/Tables/SimpleTable.cpp @@ -26,15 +26,17 @@ namespace Opm { SimpleTable::SimpleTable( TableSchema schema, const DeckItem& deckItem) : - m_schema( std::move( schema ) ) { - + m_schema( std::move( schema ) ), + m_jfunc (false) + { init( deckItem ); } SimpleTable::SimpleTable( TableSchema schema ) : - m_schema( std::move( schema ) ) { - + m_schema( std::move( schema ) ), + m_jfunc (false) + { addColumns(); } @@ -84,6 +86,9 @@ namespace Opm { size_t deckItemIdx = rowIdx*numColumns() + colIdx; if (deckItem.defaultApplied(deckItemIdx)) column.addDefault( ); + else if (m_jfunc) { + column.addValue( deckItem.getData()[deckItemIdx] ); + } else column.addValue( deckItem.getSIDouble(deckItemIdx) ); } @@ -101,6 +106,11 @@ namespace Opm { } const TableColumn& SimpleTable::getColumn( const std::string& name) const { + if (!this->m_jfunc) + return m_columns.get( name ); + + if (name == "PCOW" || name == "PCOG") + assertJFuncPressure(false); // this will throw since m_jfunc=true return m_columns.get( name ); } @@ -110,6 +120,11 @@ namespace Opm { TableColumn& SimpleTable::getColumn( const std::string& name) { + if (!this->m_jfunc) + return m_columns.get( name ); + + if (name == "PCOW" || name == "PCOG") + assertJFuncPressure(false); // this will throw since m_jfunc=true return m_columns.get( name ); } @@ -131,4 +146,12 @@ namespace Opm { return valueColumn.eval( index ); } + void SimpleTable::assertJFuncPressure(const bool jf) const { + if (jf == m_jfunc) + return; + if (m_jfunc) + throw std::invalid_argument("Cannot get pressure column with JFUNC in deck"); + else + throw std::invalid_argument("Cannot get JFUNC column when JFUNC not in deck"); + } } diff --git a/opm/parser/eclipse/EclipseState/Tables/SimpleTable.hpp b/opm/parser/eclipse/EclipseState/Tables/SimpleTable.hpp index 17f86ee3a..3a1bac6eb 100644 --- a/opm/parser/eclipse/EclipseState/Tables/SimpleTable.hpp +++ b/opm/parser/eclipse/EclipseState/Tables/SimpleTable.hpp @@ -39,7 +39,7 @@ namespace Opm { SimpleTable(TableSchema, const DeckItem& deckItem); explicit SimpleTable( TableSchema ); void addColumns(); - void init(const DeckItem& deckItem); + void init(const DeckItem& deckItem ); size_t numColumns() const; size_t numRows() const; void addRow( const std::vector& row); @@ -60,11 +60,15 @@ namespace Opm { */ double evaluate(const std::string& columnName, double xPos) const; + /// throws std::invalid_argument if jf != m_jfunc + void assertJFuncPressure(const bool jf) const; + protected: std::map m_columnNames; std::vector > m_valueDefaulted; TableSchema m_schema; OrderedMap m_columns; + bool m_jfunc = false; }; } diff --git a/opm/parser/eclipse/EclipseState/Tables/SlgofTable.hpp b/opm/parser/eclipse/EclipseState/Tables/SlgofTable.hpp index 33040ab34..17bdba33c 100644 --- a/opm/parser/eclipse/EclipseState/Tables/SlgofTable.hpp +++ b/opm/parser/eclipse/EclipseState/Tables/SlgofTable.hpp @@ -28,7 +28,7 @@ namespace Opm { class SlgofTable : public SimpleTable { public: - SlgofTable( const DeckItem& item ); + SlgofTable( const DeckItem& item, const bool jfunc ); const TableColumn& getSlColumn() const; const TableColumn& getKrgColumn() const; const TableColumn& getKrogColumn() const; @@ -38,6 +38,8 @@ namespace Opm { // is inconsistent, but it is the one used in the Eclipse // manual...) const TableColumn& getPcogColumn() const; + + const TableColumn& getJFuncColumn() const; }; } diff --git a/opm/parser/eclipse/EclipseState/Tables/SwfnTable.hpp b/opm/parser/eclipse/EclipseState/Tables/SwfnTable.hpp index 0889c2072..ddebd87b6 100644 --- a/opm/parser/eclipse/EclipseState/Tables/SwfnTable.hpp +++ b/opm/parser/eclipse/EclipseState/Tables/SwfnTable.hpp @@ -25,14 +25,17 @@ namespace Opm { class SwfnTable : public SimpleTable { public: - SwfnTable( const DeckItem& item ); + SwfnTable( const DeckItem& item, const bool jfunc ); const TableColumn& getSwColumn() const; const TableColumn& getKrwColumn() const; - // this column is p_o - p_w (non-wetting phase pressure minus - // wetting phase pressure for a given water saturation) + /// this column is p_o - p_w (non-wetting phase pressure minus + /// wetting phase pressure for a given water saturation) const TableColumn& getPcowColumn() const; + + /// use this function if JFUNC is set in the deck + const TableColumn& getJFuncColumn() const; }; } diff --git a/opm/parser/eclipse/EclipseState/Tables/SwofTable.hpp b/opm/parser/eclipse/EclipseState/Tables/SwofTable.hpp index b962d6c4c..d68122a43 100644 --- a/opm/parser/eclipse/EclipseState/Tables/SwofTable.hpp +++ b/opm/parser/eclipse/EclipseState/Tables/SwofTable.hpp @@ -27,7 +27,7 @@ namespace Opm { class SwofTable : public SimpleTable { public: - SwofTable( const DeckItem& item ); + SwofTable( const DeckItem& item, const bool jfunc ); const TableColumn& getSwColumn() const; const TableColumn& getKrwColumn() const; const TableColumn& getKrowColumn() const; @@ -35,6 +35,9 @@ namespace Opm { // this column is p_o - p_w (non-wetting phase pressure minus // wetting phase pressure for a given water saturation) const TableColumn& getPcowColumn() const; + + /// use this function if JFUNC is set in the deck + const TableColumn& getJFuncColumn() const; }; } diff --git a/opm/parser/eclipse/EclipseState/Tables/TableManager.cpp b/opm/parser/eclipse/EclipseState/Tables/TableManager.cpp index ec3483101..0d6b9a45e 100644 --- a/opm/parser/eclipse/EclipseState/Tables/TableManager.cpp +++ b/opm/parser/eclipse/EclipseState/Tables/TableManager.cpp @@ -67,6 +67,8 @@ #include #include +#include + #include #include #include @@ -78,7 +80,8 @@ namespace Opm { m_tabdims( Tabdims(deck)), hasImptvd (deck.hasKeyword("IMPTVD")), hasEnptvd (deck.hasKeyword("ENPTVD")), - hasEqlnum (deck.hasKeyword("EQLNUM")) + hasEqlnum (deck.hasKeyword("EQLNUM")), + m_jfunc( deck ) { initDims( deck ); initSimpleTables( deck ); @@ -233,18 +236,21 @@ namespace Opm { addTables( "ROCKTAB", numRocktabTables); } - initSimpleTableContainer(deck, "SWOF" , m_tabdims.getNumSatTables()); + initSimpleTableContainer(deck, "SGWFN", m_tabdims.getNumSatTables()); - initSimpleTableContainer(deck, "SGOF" , m_tabdims.getNumSatTables()); - initSimpleTableContainer(deck, "SLGOF" , m_tabdims.getNumSatTables()); initSimpleTableContainer(deck, "SOF2" , m_tabdims.getNumSatTables()); initSimpleTableContainer(deck, "SOF3" , m_tabdims.getNumSatTables()); - initSimpleTableContainer(deck, "SWFN" , m_tabdims.getNumSatTables()); - initSimpleTableContainer(deck, "SGFN" , m_tabdims.getNumSatTables()); + { + initSimpleTableContainerWithJFunc(deck, "SWOF", m_tabdims.getNumSatTables()); + initSimpleTableContainerWithJFunc(deck, "SGOF", m_tabdims.getNumSatTables()); + initSimpleTableContainerWithJFunc(deck, "SWFN", m_tabdims.getNumSatTables()); + initSimpleTableContainerWithJFunc(deck, "SGFN", m_tabdims.getNumSatTables()); + initSimpleTableContainerWithJFunc(deck, "SLGOF", m_tabdims.getNumSatTables()); + + } initSimpleTableContainer(deck, "SSFN" , m_tabdims.getNumSatTables()); initSimpleTableContainer(deck, "MSFN" , m_tabdims.getNumSatTables()); - initSimpleTableContainer(deck, "RSVD" , m_eqldims->getNumEquilRegions()); initSimpleTableContainer(deck, "RVVD" , m_eqldims->getNumEquilRegions()); { @@ -670,6 +676,12 @@ namespace Opm { return getTables("TLPMIXPA"); } + const JFunc& TableManager::getJFunc() const { + if (!useJFunc()) + throw std::invalid_argument("Cannot get JFUNC table when JFUNC not in deck"); + return m_jfunc; + } + const std::map& TableManager::getVFPProdTables() const { return m_vfpprodTables; } @@ -690,6 +702,9 @@ namespace Opm { return hasEqlnum; } + bool TableManager::useJFunc() const { + return m_jfunc; + } const MessageContainer& TableManager::getMessageContainer() const { return m_messages; diff --git a/opm/parser/eclipse/EclipseState/Tables/TableManager.hpp b/opm/parser/eclipse/EclipseState/Tables/TableManager.hpp index 2c4987da0..8a4c55749 100644 --- a/opm/parser/eclipse/EclipseState/Tables/TableManager.hpp +++ b/opm/parser/eclipse/EclipseState/Tables/TableManager.hpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -99,6 +100,8 @@ namespace Opm { const TableContainer& getMsfnTables() const; const TableContainer& getTlpmixpaTables() const; + const JFunc& getJFunc() const; + const std::vector& getPvtgTables() const; const std::vector& getPvtoTables() const; const PvtwTable& getPvtwTable() const; @@ -116,6 +119,9 @@ namespace Opm { /// deck has keyword "EQLNUM" --- Equilibriation region numbers bool useEqlnum() const; + /// deck has keyword "JFUNC" --- Use Leverett's J Function for capillary pressure + bool useJFunc() const; + const MessageContainer& getMessageContainer() const; MessageContainer& getMessageContainer(); @@ -142,6 +148,39 @@ namespace Opm { void initPlyrockTables(const Deck& deck); void initPlyshlogTables(const Deck& deck); + + + + /** + * JFUNC + */ + template + void initSimpleTableContainerWithJFunc(const Deck& deck, + const std::string& keywordName, + const std::string& tableName, + size_t numTables) { + if (!deck.hasKeyword(keywordName)) + return; // the table is not featured by the deck... + + auto& container = forceGetTables(tableName , numTables); + + if (deck.count(keywordName) > 1) { + complainAboutAmbiguousKeyword(deck, keywordName); + return; + } + + const auto& tableKeyword = deck.getKeyword(keywordName); + for (size_t tableIdx = 0; tableIdx < tableKeyword.size(); ++tableIdx) { + const auto& dataItem = tableKeyword.getRecord( tableIdx ).getItem( 0 ); + if (dataItem.size() > 0) { + std::shared_ptr table = std::make_shared( dataItem, useJFunc() ); + container.addTable( tableIdx , table ); + } + } + } + + + template void initSimpleTableContainer(const Deck& deck, const std::string& keywordName, @@ -175,6 +214,15 @@ namespace Opm { } + template + void initSimpleTableContainerWithJFunc(const Deck& deck, + const std::string& keywordName, + size_t numTables) { + initSimpleTableContainerWithJFunc(deck , keywordName , keywordName , numTables); + } + + + template void initSimpleTable(const Deck& deck, const std::string& keywordName, @@ -244,6 +292,8 @@ namespace Opm { const bool hasEnptvd;// if deck has keyword ENPTVD const bool hasEqlnum;// if deck has keyword EQLNUM + const JFunc m_jfunc; + MessageContainer m_messages; }; } diff --git a/opm/parser/eclipse/EclipseState/Tables/Tables.cpp b/opm/parser/eclipse/EclipseState/Tables/Tables.cpp index 7b60f01a7..87c1a215e 100644 --- a/opm/parser/eclipse/EclipseState/Tables/Tables.cpp +++ b/opm/parser/eclipse/EclipseState/Tables/Tables.cpp @@ -100,13 +100,14 @@ PvtoTable::PvtoTable( const DeckKeyword& keyword, size_t tableIdx) : PvtxTable::init(keyword , tableIdx); } -SwofTable::SwofTable( const DeckItem& item ) { +SwofTable::SwofTable( const DeckItem& item , const bool jfunc) { m_schema.addColumn( ColumnSchema( "SW" , Table::STRICTLY_INCREASING , Table::DEFAULT_NONE) ); m_schema.addColumn( ColumnSchema( "KRW" , Table::RANDOM , Table::DEFAULT_LINEAR) ); m_schema.addColumn( ColumnSchema( "KROW" , Table::RANDOM , Table::DEFAULT_LINEAR) ); m_schema.addColumn( ColumnSchema( "PCOW" , Table::RANDOM , Table::DEFAULT_LINEAR) ); + m_jfunc = jfunc; SimpleTable::init( item ); } @@ -123,6 +124,12 @@ const TableColumn& SwofTable::getKrowColumn() const { } const TableColumn& SwofTable::getPcowColumn() const { + SimpleTable::assertJFuncPressure(false); + return SimpleTable::getColumn(3); +} + +const TableColumn& SwofTable::getJFuncColumn() const { + SimpleTable::assertJFuncPressure(true); return SimpleTable::getColumn(3); } @@ -152,12 +159,13 @@ const TableColumn& SgwfnTable::getPcgwColumn() const { return SimpleTable::getColumn(3); } -SgofTable::SgofTable( const DeckItem& item ) { +SgofTable::SgofTable( const DeckItem& item , const bool jfunc) { m_schema.addColumn( ColumnSchema("SG" , Table::STRICTLY_INCREASING , Table::DEFAULT_NONE)); m_schema.addColumn( ColumnSchema("KRG" , Table::RANDOM , Table::DEFAULT_LINEAR )); m_schema.addColumn( ColumnSchema("KROG" , Table::RANDOM , Table::DEFAULT_LINEAR )); m_schema.addColumn( ColumnSchema("PCOG" , Table::RANDOM , Table::DEFAULT_LINEAR )); + m_jfunc = jfunc; SimpleTable::init( item ); } @@ -174,16 +182,22 @@ const TableColumn& SgofTable::getKrogColumn() const { } const TableColumn& SgofTable::getPcogColumn() const { + SimpleTable::assertJFuncPressure(false); return SimpleTable::getColumn(3); - } -SlgofTable::SlgofTable( const DeckItem& item ) { +const TableColumn& SgofTable::getJFuncColumn() const { + SimpleTable::assertJFuncPressure(true); + return SimpleTable::getColumn(3); +} + +SlgofTable::SlgofTable( const DeckItem& item, const bool jfunc ) { m_schema.addColumn( ColumnSchema("SL" , Table::STRICTLY_INCREASING , Table::DEFAULT_NONE )); m_schema.addColumn( ColumnSchema("KRG" , Table::DECREASING , Table::DEFAULT_LINEAR )); m_schema.addColumn( ColumnSchema("KROG" , Table::INCREASING , Table::DEFAULT_LINEAR )); m_schema.addColumn( ColumnSchema("PCOG" , Table::DECREASING , Table::DEFAULT_LINEAR )); + m_jfunc = jfunc; SimpleTable::init( item ); if (getSlColumn().back() != 1.0) { @@ -204,6 +218,12 @@ const TableColumn& SlgofTable::getKrogColumn() const { } const TableColumn& SlgofTable::getPcogColumn() const { + SimpleTable::assertJFuncPressure(false); + return SimpleTable::getColumn(3); +} + +const TableColumn& SlgofTable::getJFuncColumn() const { + SimpleTable::assertJFuncPressure(true); return SimpleTable::getColumn(3); } @@ -286,12 +306,13 @@ const TableColumn& PvdoTable::getViscosityColumn() const { return SimpleTable::getColumn(2); } -SwfnTable::SwfnTable( const DeckItem& item ) { +SwfnTable::SwfnTable( const DeckItem& item, const bool jfunc ) { m_schema.addColumn( ColumnSchema("SW" , Table::STRICTLY_INCREASING , Table::DEFAULT_NONE )); m_schema.addColumn( ColumnSchema("KRW" , Table::INCREASING , Table::DEFAULT_LINEAR )); m_schema.addColumn( ColumnSchema("PCOW" , Table::DECREASING , Table::DEFAULT_LINEAR )); - SimpleTable::init(item); + m_jfunc = jfunc; + SimpleTable::init( item ); } const TableColumn& SwfnTable::getSwColumn() const { @@ -303,15 +324,23 @@ const TableColumn& SwfnTable::getKrwColumn() const { } const TableColumn& SwfnTable::getPcowColumn() const { + SimpleTable::assertJFuncPressure(false); return SimpleTable::getColumn(2); } -SgfnTable::SgfnTable( const DeckItem& item ) { +const TableColumn& SwfnTable::getJFuncColumn() const { + SimpleTable::assertJFuncPressure(true); + return SimpleTable::getColumn(2); +} + + +SgfnTable::SgfnTable( const DeckItem& item, const bool jfunc ) { m_schema.addColumn( ColumnSchema("SG" , Table::STRICTLY_INCREASING , Table::DEFAULT_NONE ) ); m_schema.addColumn( ColumnSchema("KRG" , Table::INCREASING , Table::DEFAULT_LINEAR)); m_schema.addColumn( ColumnSchema("PCOG" , Table::INCREASING , Table::DEFAULT_LINEAR)); - SimpleTable::init(item); + m_jfunc = jfunc; + SimpleTable::init( item ); } @@ -324,6 +353,12 @@ const TableColumn& SgfnTable::getKrgColumn() const { } const TableColumn& SgfnTable::getPcogColumn() const { + SimpleTable::assertJFuncPressure(false); + return SimpleTable::getColumn(2); +} + +const TableColumn& SgfnTable::getJFuncColumn() const { + SimpleTable::assertJFuncPressure(true); return SimpleTable::getColumn(2); } diff --git a/opm/parser/eclipse/EclipseState/Tables/tests/TableContainerTests.cpp b/opm/parser/eclipse/EclipseState/Tables/tests/TableContainerTests.cpp index 69223607b..1040c3cb4 100644 --- a/opm/parser/eclipse/EclipseState/Tables/tests/TableContainerTests.cpp +++ b/opm/parser/eclipse/EclipseState/Tables/tests/TableContainerTests.cpp @@ -54,7 +54,7 @@ BOOST_AUTO_TEST_CASE( CreateContainer ) { BOOST_CHECK_EQUAL( 0 , container.size() ); BOOST_CHECK_EQUAL( false , container.hasTable( 1 )); - std::shared_ptr table = std::make_shared( deck.getKeyword("SWOF").getRecord(0).getItem(0) ); + std::shared_ptr table = std::make_shared( deck.getKeyword("SWOF").getRecord(0).getItem(0), false ); BOOST_CHECK_THROW( container.addTable( 10 , table ), std::invalid_argument ); container.addTable( 6 , table ); BOOST_CHECK_EQUAL( 1 , container.size() ); diff --git a/opm/parser/eclipse/EclipseState/Tables/tests/TableManagerTests.cpp b/opm/parser/eclipse/EclipseState/Tables/tests/TableManagerTests.cpp index 2c98956ed..0341c0746 100644 --- a/opm/parser/eclipse/EclipseState/Tables/tests/TableManagerTests.cpp +++ b/opm/parser/eclipse/EclipseState/Tables/tests/TableManagerTests.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -40,6 +41,8 @@ #include #include +#include + #include #include @@ -90,12 +93,83 @@ Opm::Deck createSingleRecordDeckWithVd() { return parser.parseString(deckData, Opm::ParseContext()); } +Opm::Deck createSingleRecordDeckWithJFunc() { + const char *deckData = + "RUNSPEC\n" + "ENDSCALE\n" + "2* 1 2 /\n" + "PROPS\n" + "JFUNC\n" + " WATER 22.0 /\n" + "TABDIMS\n" + " 2 /\n" + "\n" + "SWFN\n" + "0.22 .0 7.0 \n" + "0.3 .0 4.0 \n" + "0.5 .24 2.5 \n" + "0.8 .65 1.0 \n" + "0.9 .83 .5 \n" + "1.0 1.00 .0 /\n" + "/\n" + "IMPTVD\n" + "3000.0 6*0.1 0.31 1*0.1\n" + "9000.0 6*0.1 0.32 1*0.1/\n" + "ENPTVD\n" + "3000.0 0.20 0.20 1.0 0.0 0.04 1.0 0.18 0.22\n" + "9000.0 0.22 0.22 1.0 0.0 0.04 1.0 0.18 0.22 /"; + + Opm::Parser parser; + return parser.parseString(deckData, Opm::ParseContext()); +} + +Opm::Deck createSingleRecordDeckWithJFuncBoth() { + const char *deckData = + "RUNSPEC\nENDSCALE\n2* 1 2 /\nPROPS\n" + "JFUNC\n * 55.0 88.0 /\n" // ASTERISK MEANS DEFAULT VALUE + "TABDIMS\n 2 /\n"; + Opm::Parser parser; + return parser.parseString(deckData, Opm::ParseContext()); +} + +Opm::Deck createSingleRecordDeckWithFullJFunc() { + const char *deckData = + "RUNSPEC\nENDSCALE\n2* 1 2 /\nPROPS\n" + "JFUNC\n WATER 2.7182 3.1416 0.6 0.7 Z /\n" + "TABDIMS\n 2 /\n"; + Opm::Parser parser; + return parser.parseString(deckData, Opm::ParseContext()); +} + +Opm::Deck createSingleRecordDeckWithJFuncBrokenFlag() { + const char *deckData = + "RUNSPEC\nENDSCALE\n2* 1 2 /\nPROPS\n" + "JFUNC\n GARBAGE 55.0 88.0 /\n" + "TABDIMS\n 2 /\n"; + Opm::Parser parser; + return parser.parseString(deckData, Opm::ParseContext()); +} + +Opm::Deck createSingleRecordDeckWithJFuncBrokenDirection() { + const char *deckData = + "RUNSPEC\nENDSCALE\n2* 1 2 /\nPROPS\n" + "JFUNC\n * * * * * XZ /\n" + "TABDIMS\n 2 /\n"; + Opm::Parser parser; + return parser.parseString(deckData, Opm::ParseContext()); +} + + +/// used in BOOST_CHECK_CLOSE +static float epsilon() { + return 0.00001; +} } BOOST_AUTO_TEST_CASE( CreateTables ) { auto deck = createSingleRecordDeck(); Opm::TableManager tables(deck); - auto tabdims = tables.getTabdims(); + auto& tabdims = tables.getTabdims(); BOOST_CHECK_EQUAL( tabdims.getNumSatTables() , 2 ); BOOST_CHECK( !tables.useImptvd() ); BOOST_CHECK( !tables.useEnptvd() ); @@ -104,13 +178,51 @@ BOOST_AUTO_TEST_CASE( CreateTables ) { BOOST_AUTO_TEST_CASE( CreateTablesWithVd ) { auto deck = createSingleRecordDeckWithVd(); Opm::TableManager tables(deck); - auto tabdims = tables.getTabdims(); + auto& tabdims = tables.getTabdims(); BOOST_CHECK_EQUAL( tabdims.getNumSatTables() , 2 ); BOOST_CHECK( tables.useImptvd() ); BOOST_CHECK( tables.useEnptvd() ); } +BOOST_AUTO_TEST_CASE( CreateTablesWithJFunc ) { + auto deck = createSingleRecordDeckWithJFunc(); + Opm::TableManager tables(deck); + const Opm::Tabdims& tabdims = tables.getTabdims(); + BOOST_CHECK_EQUAL(tabdims.getNumSatTables(), 2); + BOOST_CHECK(tables.useImptvd()); + BOOST_CHECK(tables.useEnptvd()); + const auto& swfnTab = tables.getSwfnTables(); + + const float swfnDataVerbatim[] = + {0.22, 0.00, 7.00, 0.30, 0.00, 4.00, 0.50, 0.24, 2.50, + 0.80, 0.65, 1.00, 0.90, 0.83, 0.50, 1.00, 1.00, 0.00}; + + + for (size_t tab = 0; tab < swfnTab.size(); tab++) { + const auto& t = swfnTab.getTable(tab); + + BOOST_CHECK_THROW( t.getColumn("PCOW"), std::invalid_argument ); + + for (size_t c_idx = 0; c_idx < t.numColumns(); c_idx++) { + const auto& col = t.getColumn(c_idx); + for (size_t i = 0; i < col.size(); i++) { + int idx = c_idx + i*3; + BOOST_CHECK_CLOSE( col[i], swfnDataVerbatim[idx], epsilon()); + } + } + } + + const auto& tt = swfnTab.getTable(0); + BOOST_CHECK_THROW(tt.getPcowColumn(), std::invalid_argument); + + const auto& col = tt.getJFuncColumn(); + for (size_t i = 0; i < col.size(); i++) { + BOOST_CHECK_CLOSE(col[i], swfnDataVerbatim[i*3 + 2], epsilon()); + } + + BOOST_CHECK(tables.useJFunc()); +} /*****************************************************************/ @@ -130,8 +242,8 @@ BOOST_AUTO_TEST_CASE(SwofTable_Tests) { Opm::Parser parser; auto deck = parser.parseString(deckData, Opm::ParseContext()); - Opm::SwofTable swof1Table(deck.getKeyword("SWOF").getRecord(0).getItem(0)); - Opm::SwofTable swof2Table(deck.getKeyword("SWOF").getRecord(1).getItem(0)); + Opm::SwofTable swof1Table(deck.getKeyword("SWOF").getRecord(0).getItem(0), false); + Opm::SwofTable swof2Table(deck.getKeyword("SWOF").getRecord(1).getItem(0), false); BOOST_CHECK_EQUAL(swof1Table.numRows(), 2); BOOST_CHECK_EQUAL(swof2Table.numRows(), 3); @@ -216,8 +328,8 @@ BOOST_AUTO_TEST_CASE(SgofTable_Tests) { Opm::Parser parser; auto deck = parser.parseString(deckData, Opm::ParseContext()); - Opm::SgofTable sgof1Table(deck.getKeyword("SGOF").getRecord(0).getItem(0)); - Opm::SgofTable sgof2Table(deck.getKeyword("SGOF").getRecord(1).getItem(0)); + Opm::SgofTable sgof1Table(deck.getKeyword("SGOF").getRecord(0).getItem(0), false); + Opm::SgofTable sgof2Table(deck.getKeyword("SGOF").getRecord(1).getItem(0), false); BOOST_CHECK_EQUAL(sgof1Table.numRows(), 2); BOOST_CHECK_EQUAL(sgof2Table.numRows(), 3); @@ -565,9 +677,48 @@ VFPPROD \n\ } } +BOOST_AUTO_TEST_CASE(JFuncTestThrowingOnBrokenData) { + auto deck = createSingleRecordDeckWithJFuncBrokenFlag(); + BOOST_CHECK_THROW(Opm::TableManager tm (deck), std::invalid_argument); + auto deck2 = createSingleRecordDeckWithJFuncBrokenDirection(); + BOOST_CHECK_THROW(Opm::TableManager tm2 (deck2), std::invalid_argument); +} +BOOST_AUTO_TEST_CASE(JFuncTestThrowingGalore) { + auto deck = createSingleRecordDeckWithVd(); + Opm::TableManager tables(deck); + auto tabdims = tables.getTabdims(); + BOOST_CHECK(!tables.useJFunc()); + BOOST_CHECK_THROW(tables.getJFunc(), std::invalid_argument); +} +BOOST_AUTO_TEST_CASE(JFuncTest) { + const auto deck = createSingleRecordDeckWithJFuncBoth(); + Opm::TableManager tables(deck); + BOOST_CHECK(tables.useJFunc()); + + const Opm::JFunc& jt = tables.getJFunc(); + BOOST_CHECK(jt.getJFuncFlag() == Opm::JFunc::Flag::BOTH); + BOOST_CHECK_CLOSE(jt.getowSurfaceTension(), 55.0, epsilon()); + BOOST_CHECK_CLOSE(jt.getgoSurfaceTension(), 88.0, epsilon()); + BOOST_CHECK_CLOSE(jt.getAlphaFactor(), 0.5, epsilon()); // default + BOOST_CHECK_CLOSE(jt.getBetaFactor(), 0.5, epsilon()); // default + BOOST_CHECK(jt.getDirection() == Opm::JFunc::Direction::XY); // default + + // full specification = WATER 2.7182 3.1416 0.6 0.7 Z + const auto deck2 = createSingleRecordDeckWithFullJFunc(); + Opm::TableManager tables2(deck2); + BOOST_CHECK(tables2.useJFunc()); + + const auto& jt2 = tables2.getJFunc(); + BOOST_CHECK(jt2.getJFuncFlag() == Opm::JFunc::Flag::WATER); + BOOST_CHECK_CLOSE(jt2.getowSurfaceTension(), 2.7182, epsilon()); + BOOST_CHECK_THROW(jt2.getgoSurfaceTension(), std::invalid_argument); + BOOST_CHECK_CLOSE(jt2.getAlphaFactor(), 0.6, epsilon()); // default + BOOST_CHECK_CLOSE(jt2.getBetaFactor(), 0.7, epsilon()); // default + BOOST_CHECK(jt2.getDirection() == Opm::JFunc::Direction::Z); // default +} diff --git a/opm/parser/eclipse/IntegrationTests/ParseSGOF.cpp b/opm/parser/eclipse/IntegrationTests/ParseSGOF.cpp index f64b84086..f765e5ba0 100644 --- a/opm/parser/eclipse/IntegrationTests/ParseSGOF.cpp +++ b/opm/parser/eclipse/IntegrationTests/ParseSGOF.cpp @@ -61,7 +61,7 @@ BOOST_AUTO_TEST_CASE( parse_SGOF_OK ) { const auto& item0 = record0.getItem(0); BOOST_CHECK_EQUAL(10U * 4, item0.size()); - Opm::SgofTable sgofTable(deck.getKeyword("SGOF").getRecord(0).getItem(0)); + Opm::SgofTable sgofTable(deck.getKeyword("SGOF").getRecord(0).getItem(0), false); BOOST_CHECK_EQUAL(10U, sgofTable.getSgColumn().size()); BOOST_CHECK_EQUAL(0.1, sgofTable.getSgColumn()[0]); BOOST_CHECK_EQUAL(0.0, sgofTable.getKrgColumn()[0]); diff --git a/opm/parser/eclipse/IntegrationTests/ParseSLGOF.cpp b/opm/parser/eclipse/IntegrationTests/ParseSLGOF.cpp index 6684e6908..71f3073ee 100644 --- a/opm/parser/eclipse/IntegrationTests/ParseSLGOF.cpp +++ b/opm/parser/eclipse/IntegrationTests/ParseSLGOF.cpp @@ -61,7 +61,7 @@ BOOST_AUTO_TEST_CASE( parse_SLGOF_OK ) { BOOST_CHECK_EQUAL(1U , record0.size()); BOOST_CHECK_EQUAL(10U * 4, item0.size()); - Opm::SlgofTable slgofTable( deck.getKeyword("SLGOF").getRecord(0).getItem(0) ); + Opm::SlgofTable slgofTable( deck.getKeyword("SLGOF").getRecord(0).getItem(0), false ); BOOST_CHECK_EQUAL(10U, slgofTable.getSlColumn().size()); BOOST_CHECK_EQUAL(0.1, slgofTable.getSlColumn()[0]); BOOST_CHECK_EQUAL(1.0, slgofTable.getSlColumn()[9]); diff --git a/opm/parser/eclipse/IntegrationTests/ParseSWOF.cpp b/opm/parser/eclipse/IntegrationTests/ParseSWOF.cpp index accb30076..cbca31836 100644 --- a/opm/parser/eclipse/IntegrationTests/ParseSWOF.cpp +++ b/opm/parser/eclipse/IntegrationTests/ParseSWOF.cpp @@ -63,7 +63,7 @@ BOOST_AUTO_TEST_CASE( parse_SWOF_OK ) { BOOST_CHECK_EQUAL(1U , record0.size()); BOOST_CHECK_EQUAL(10U * 4, item0.size()); - Opm::SwofTable swofTable(deck.getKeyword("SWOF").getRecord(0).getItem(0)); + Opm::SwofTable swofTable(deck.getKeyword("SWOF").getRecord(0).getItem(0), false); BOOST_CHECK_EQUAL(10U, swofTable.getSwColumn().size()); BOOST_CHECK_CLOSE(0.1, swofTable.getSwColumn()[0], 1e-8); BOOST_CHECK_CLOSE(1.0, swofTable.getSwColumn().back(), 1e-8);