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);