diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake
index 5ad1e949..20d9d453 100644
--- a/CMakeLists_files.cmake
+++ b/CMakeLists_files.cmake
@@ -245,6 +245,7 @@ list (APPEND EXAMPLE_SOURCE_FILES
examples/sim_2p_comp_reorder.cpp
examples/sim_2p_incomp.cpp
examples/wells_example.cpp
+ examples/diagnose_relperm.cpp
tutorials/tutorial1.cpp
tutorials/tutorial2.cpp
tutorials/tutorial3.cpp
@@ -367,6 +368,7 @@ list (APPEND PUBLIC_HEADER_FILES
opm/core/props/satfunc/SaturationPropsBasic.hpp
opm/core/props/satfunc/SaturationPropsFromDeck.hpp
opm/core/props/satfunc/SaturationPropsInterface.hpp
+ opm/core/props/satfunc/RelpermDiagnostics.hpp
opm/core/simulator/AdaptiveSimulatorTimer.hpp
opm/core/simulator/AdaptiveTimeStepping.hpp
opm/core/simulator/AdaptiveTimeStepping_impl.hpp
diff --git a/examples/diagnose_relperm.cpp b/examples/diagnose_relperm.cpp
new file mode 100644
index 00000000..7a7a032b
--- /dev/null
+++ b/examples/diagnose_relperm.cpp
@@ -0,0 +1,114 @@
+/*
+ Copyright 2015 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 .
+*/
+
+
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+namespace
+{
+ void warnIfUnusedParams(const Opm::parameter::ParameterGroup& param)
+ {
+ if (param.anyUnused()) {
+ std::cout << "-------------------- Warning: unused parameters: --------------------\n";
+ param.displayUsage();
+ std::cout << "-------------------------------------------------------------------------" << std::endl;
+ }
+ }
+} // anon namespace
+
+
+
+// ----------------- Main program -----------------
+int
+main(int argc, char** argv)
+try
+{
+ using namespace Opm;
+ parameter::ParameterGroup param(argc, argv);
+ // Read saturation tables.
+ EclipseStateConstPtr eclState;
+ ParserPtr parser(new Opm::Parser);
+ Opm::DeckConstPtr deck;
+ //ParseMode parseMode;
+ Opm::ParseMode parseMode({{ ParseMode::PARSE_RANDOM_SLASH , InputError::IGNORE }});
+ std::string deck_filename = param.get("deck_filename");
+ deck = parser->parseFile(deck_filename, parseMode);
+ eclState.reset(new EclipseState(deck, parseMode));
+
+ GridManager gm(deck);
+ const UnstructuredGrid& grid = *gm.c_grid();
+ // Write parameters used for later reference.
+ bool output = param.getDefault("output", true);
+ std::string output_dir;
+ if (output) {
+ output_dir =
+ param.getDefault("output_dir", std::string("output"));
+ boost::filesystem::path fpath(output_dir);
+ try {
+ create_directories(fpath);
+ }
+ catch (...) {
+ OPM_THROW(std::runtime_error, "Creating directories failed: " << fpath);
+ }
+ param.writeParam(output_dir + "/relperm.param");
+ }
+
+ // Issue a warning if any parameters were unused.
+ warnIfUnusedParams(param);
+
+ // Solve eikonal equation.
+ Opm::time::StopWatch timer;
+ timer.start();
+ RelpermDiagnostics diagnostic(eclState);
+ diagnostic.phaseCheck(eclState, deck);
+ diagnostic.satFamilyCheck(eclState);
+ diagnostic.tableCheck(eclState, deck);
+ diagnostic.endPointsCheck(deck, eclState);
+ timer.stop();
+ double tt = timer.secsSinceStart();
+ std::cout << "relperm diagnostics: " << tt << " seconds." << std::endl;
+}
+catch (const std::exception &e) {
+ std::cerr << "Program threw an exception: " << e.what() << "\n";
+ throw;
+}
diff --git a/opm/core/props/satfunc/RelpermDiagnostics.hpp b/opm/core/props/satfunc/RelpermDiagnostics.hpp
new file mode 100644
index 00000000..95e5e4ee
--- /dev/null
+++ b/opm/core/props/satfunc/RelpermDiagnostics.hpp
@@ -0,0 +1,564 @@
+/*
+ Copyright 2015 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_RELPERMDIAGNOSTICS_HEADER_INCLUDED
+#define OPM_RELPERMDIAGNOSTICS_HEADER_INCLUDED
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+namespace Opm {
+
+ enum Status {
+ Pass,
+ Error
+ };
+
+ enum FluidSystem {
+ OilWater,
+ OilGas,
+ WaterGas,
+ BlackOil
+ };
+
+ enum SaturationFunctionFamily {
+ FamilyI,
+ FamilyII,
+ NoFamily
+ };
+
+
+ ///This class is intend to be a relpmer diganostics, to detect
+ ///wrong input of relperm table and endpoints.
+ class RelpermDiagnostics
+ {
+ public:
+ RelpermDiagnostics();
+ RelpermDiagnostics(EclipseStateConstPtr eclstate);
+
+ ///Display all the keywords.
+ Status keywordsDisplay(EclipseStateConstPtr eclState);
+
+ ///Check the phase that used.
+ FluidSystem phaseCheck(EclipseStateConstPtr eclState,
+ DeckConstPtr deck);
+
+
+ ///Check saturation family I and II.
+ Status satFamilyCheck(EclipseStateConstPtr eclState);
+
+ ///Check saturation tables.
+ Status tableCheck(EclipseStateConstPtr eclState,
+ DeckConstPtr deck);
+
+ ///Check endpoints in the saturation tables.
+ Status endPointsCheck(DeckConstPtr deck,
+ EclipseStateConstPtr eclState);
+
+ private:
+ FluidSystem fluidsystem_;
+
+ SaturationFunctionFamily satFamily_;
+ std::vector > unscaledEpsInfo_;
+
+ Status valueRangeCheck_(const std::vector& value,
+ bool isAscending);
+
+ //Status endPointCheck_(const TableContainer&)
+
+ ///For every table, need to deal with case by case.
+ Status swofTableCheck_(const Opm::SwofTable& swofTables);
+ Status sgofTableCheck_(const Opm::SgofTable& sgofTables);
+ Status slgofTableCheck_(const Opm::SlgofTable& slgofTables);
+ Status swfnTableCheck_(const Opm::SwfnTable& swfnTables);
+ Status sgfnTableCheck_(const Opm::SgfnTable& sgfnTables);
+ Status sof3TableCheck_(const Opm::Sof3Table& sof3Tables);
+ Status sof2TableCheck_(const Opm::Sof2Table& sof2Tables);
+ Status sgwfnTableCheck_(const Opm::SgwfnTable& sgwfnTables);
+ };
+
+ RelpermDiagnostics::RelpermDiagnostics()
+ {}
+
+ RelpermDiagnostics::RelpermDiagnostics(Opm::EclipseStateConstPtr eclState)
+ {}
+
+
+ Status RelpermDiagnostics::satFamilyCheck(Opm::EclipseStateConstPtr eclState)
+ {
+ const auto& tableManager = eclState->getTableManager();
+ const TableContainer& swofTables = tableManager->getSwofTables();
+ const TableContainer& slgofTables= tableManager->getSlgofTables();
+ const TableContainer& sgofTables = tableManager->getSgofTables();
+ const TableContainer& swfnTables = tableManager->getSwfnTables();
+ const TableContainer& sgfnTables = tableManager->getSgfnTables();
+ const TableContainer& sof3Tables = tableManager->getSof3Tables();
+ const TableContainer& sof2Tables = tableManager->getSof2Tables();
+ const TableContainer& sgwfnTables= tableManager->getSgwfnTables();
+
+ bool family1 = (!sgofTables.empty() || !slgofTables.empty()) && !swofTables.empty();
+ bool family2 = !swfnTables.empty() && !sgfnTables.empty() && (!sof3Tables.empty() || !sof2Tables.empty()) && !sgwfnTables.empty();
+
+ if (family1 && family2) {
+ throw std::invalid_argument("Saturation families should not be mixed \n"
+ "Use either SGOF and SWOF or SGFN, SWFN and SOF3");
+ }
+
+ if (!family1 && !family2) {
+ throw std::invalid_argument("Saturations function must be specified using either "
+ "family 1 or family 2 keywords \n"
+ "Use either SGOF and SWOF or SGFN, SWFN and SOF3" );
+ }
+
+ if (family1 && !family2) {
+ satFamily_ = SaturationFunctionFamily::FamilyI;
+ std::cout << "Using saturation Family I." << std::endl;
+ }
+ if (!family1 && family2) {
+ satFamily_ = SaturationFunctionFamily::FamilyII;
+ std::cout << "Using saturation Family II." << std::endl;
+ }
+
+ return Opm::Status::Pass;
+ }
+
+
+ FluidSystem RelpermDiagnostics::phaseCheck(EclipseStateConstPtr eclState,
+ DeckConstPtr deck)
+ {
+ bool hasWater = deck->hasKeyword("WATER");
+ bool hasGas = deck->hasKeyword("GAS");
+ bool hasOil = deck->hasKeyword("OIL");
+
+ if (hasWater && hasGas && !hasOil) {
+ std::cout << "This is Water-Gas system." << std::endl;
+ return FluidSystem::WaterGas;
+ }
+ if (hasWater && hasOil && !hasGas) {
+ std::cout << "This is Oil-Water system." << std::endl;
+ return FluidSystem::OilWater;
+ }
+ if (hasOil && hasGas && !hasWater) {
+ std::cout << "This is Oil-Gas system." << std::endl;
+ return FluidSystem::OilGas;
+ }
+ if (hasOil && hasWater && hasGas) {
+ std::cout << "This is Black-oil system." << std::endl;
+ return FluidSystem::BlackOil;
+ }
+ }
+
+ Status RelpermDiagnostics::tableCheck(EclipseStateConstPtr eclState,
+ DeckConstPtr deck)
+ {
+ unsigned numSatRegions = static_cast(deck->getKeyword("TABDIMS")->getRecord(0)->getItem("NTSFUN")->getInt(0));
+ const auto& tableManager = eclState->getTableManager();
+ const TableContainer& swofTables = tableManager->getSwofTables();
+ const TableContainer& slgofTables= tableManager->getSlgofTables();
+ const TableContainer& sgofTables = tableManager->getSgofTables();
+ const TableContainer& swfnTables = tableManager->getSwfnTables();
+ const TableContainer& sgfnTables = tableManager->getSgfnTables();
+ const TableContainer& sof3Tables = tableManager->getSof3Tables();
+ const TableContainer& sof2Tables = tableManager->getSof2Tables();
+ const TableContainer& sgwfnTables= tableManager->getSgwfnTables();
+
+ for (unsigned satnumIdx = 0; satnumIdx < numSatRegions; ++satnumIdx) {
+ if (deck->hasKeyword("SWOF")) {
+ std::cout << "Starting check SWOF tables......" << std::endl;
+ const auto& status = swofTableCheck_(swofTables.getTable(satnumIdx));
+ if (status == Opm::Status::Pass) {
+ std::cout << "End of check, all values are reasonable." << std::endl;
+ }
+ }
+ if (deck->hasKeyword("SGOF")) {
+ std::cout << "Starting check SGOF tables......" << std::endl;
+ const auto& status = sgofTableCheck_(sgofTables.getTable(satnumIdx));
+ if (status == Opm::Status::Pass) {
+ std::cout << "End of check, all values are reasonable." << std::endl;
+ }
+ }
+ if (deck->hasKeyword("SLGOF")) {
+ std::cout << "Starting check SLGOF tables......" << std::endl;
+ const auto& status = slgofTableCheck_(slgofTables.getTable(satnumIdx));
+ if (status == Opm::Status::Pass) {
+ std::cout << "End of check, all values are reasonable." << std::endl;
+ }
+ }
+ if (deck->hasKeyword("SWFN")) {
+ std::cout << "Starting check SWFN tables......" << std::endl;
+ const auto& status = swfnTableCheck_(swfnTables.getTable(satnumIdx));
+ if (status == Opm::Status::Pass) {
+ std::cout << "End of check, all values are reasonable." << std::endl;
+ }
+ }
+ if (deck->hasKeyword("SGFN")) {
+ std::cout << "Starting check SGFN tables......" << std::endl;
+ const auto& status = sgfnTableCheck_(sgfnTables.getTable(satnumIdx));
+ if (status == Opm::Status::Pass) {
+ std::cout << "End of check, all values are reasonable." << std::endl;
+ }
+ }
+ if (deck->hasKeyword("SOF3")) {
+ std::cout << "Starting check SOF3 tables......" << std::endl;
+ const auto& status = sof3TableCheck_(sof3Tables.getTable(satnumIdx));
+ if (status == Opm::Status::Pass) {
+ std::cout << "End of check, all values are reasonable." << std::endl;
+ }
+ }
+ if (deck->hasKeyword("SOF2")) {
+ std::cout << "Starting check SOF2 tables......" << std::endl;
+ const auto& status = sof2TableCheck_(sof2Tables.getTable(satnumIdx));
+ if (status == Opm::Status::Pass) {
+ std::cout << "End of check, all values are reasonable." << std::endl;
+ }
+ }
+ if (deck->hasKeyword("SGWFN")) {
+ std::cout << "Starting check SOF2 tables......" << std::endl;
+ const auto& status = sgwfnTableCheck_(sgwfnTables.getTable(satnumIdx));
+ if (status == Opm::Status::Pass) {
+ std::cout << "End of check, all values are reasonable." << std::endl;
+ }
+ }
+ }
+ return Opm::Status::Pass;
+ }
+
+ Status RelpermDiagnostics::swofTableCheck_(const Opm::SwofTable& swofTables)
+ {
+ const auto& sw = swofTables.getSwColumn();
+ const auto& krw = swofTables.getKrwColumn();
+ const auto& krow = swofTables.getKrowColumn();
+ const auto& pc = swofTables.getPcowColumn();
+
+ ///Check sw column.
+ if (sw.front()< 0 || sw.back() > 1) {
+ OPM_THROW(std::logic_error, "In SWOF table, saturation should be in range [0,1]");
+ }
+ ///TODO check endpoint sw.back() == 1. - Sor.
+ ///Check krw column.
+ if (krw.front() != 0) {
+ OPM_THROW(std::logic_error, "In SWOF table, first value of krw should be 0");
+ }
+ if (krw.front() < 0 || krw.back() > 1) {
+ OPM_THROW(std::logic_error, "In SWOF table, krw should be in range [0,1]");
+ }
+
+ ///Check krow column.
+ if (krow.front() > 1 || krow.back() < 0) {
+ OPM_THROW(std::logic_error, "In SWOF table, krow should be in range [0, 1]");
+ }
+ ///TODO check if run with gas.
+
+ return Opm::Status::Pass;
+ }
+
+
+ Status RelpermDiagnostics::sgofTableCheck_(const Opm::SgofTable& sgofTables)
+ {
+ const auto& sg = sgofTables.getSgColumn();
+ const auto& krg = sgofTables.getKrgColumn();
+ const auto& krog = sgofTables.getKrogColumn();
+ ///Check sw column.
+ if (sg.front()< 0 || sg.back() > 1) {
+ OPM_THROW(std::logic_error, "In SGOF table, saturation should be in range [0,1]");
+ }
+ if (sg.front() != 0) {
+ OPM_THROW(std::logic_error, "In SGOF table, first value in sg column muse be 0");
+ }
+ ///TODO check endpoint sw.back() == 1. - Sor.
+ ///Check krw column.
+ if (krg.front() != 0) {
+ OPM_THROW(std::logic_error, "In SGOF table, first value of krg should be 0");
+ }
+ if (krg.front() < 0 || krg.back() > 1) {
+ OPM_THROW(std::logic_error, "In SGOF table, krg should be in range [0,1]");
+ }
+
+ ///Check krow column.
+ if (krog.front() > 1 || krog.back() < 0) {
+ OPM_THROW(std::logic_error, "In SGOF table, krog should be in range [0, 1]");
+ }
+ ///TODO check if run with water.
+
+ return Opm::Status::Pass;
+
+ }
+
+ Status RelpermDiagnostics::slgofTableCheck_(const Opm::SlgofTable& slgofTables)
+ {
+ const auto& sl = slgofTables.getSlColumn();
+ const auto& krg = slgofTables.getKrgColumn();
+ const auto& krog = slgofTables.getKrogColumn();
+
+ ///Check sl column.
+ ///TODO first value means sl = swco + sor
+ if (sl.front()< 0 || sl.back() > 1) {
+ OPM_THROW(std::logic_error, "In SLGOF table, saturation should be in range [0,1]");
+ }
+ if (sl.back() != 1) {
+ OPM_THROW(std::logic_error, "In SLGOF table, last value in sl column muse be 1");
+ }
+
+ if (krg.front() > 1 || krg.back() < 0) {
+ OPM_THROW(std::logic_error, "In SLGOF table, krg column shoule be in range [0, 1]");
+ }
+ if (krg.back() != 0) {
+ OPM_THROW(std::logic_error, "In SLGOF table, last value in krg column should be 0");
+ }
+
+ if (krog.front() < 0 || krog.back() > 1) {
+ OPM_THROW(std::logic_error, "In SLGOF table, krog column shoule be in range [0, 1]");
+
+ }
+ return Opm::Status::Pass;
+ }
+
+ Status RelpermDiagnostics::swfnTableCheck_(const Opm::SwfnTable& swfnTables)
+ {
+ const auto& sw = swfnTables.getSwColumn();
+ const auto& krw = swfnTables.getKrwColumn();
+
+ ///Check sw column.
+ if (sw.front() < 0 || sw.back() > 1) {
+ OPM_THROW(std::logic_error, "In SWFN table, saturation should be in range [0,1]");
+ }
+
+ ///Check krw column.
+ if (krw.front() < 0 || krw.back() > 1) {
+ OPM_THROW(std::logic_error, "In SWFN table, krw should be in range [0,1]");
+ }
+ if (krw.front() != 0) {
+ OPM_THROW(std::logic_error, "In SWFN table, first value in krw column should be 0");
+ }
+
+ return Opm::Status::Pass;
+ }
+
+
+ Status RelpermDiagnostics::sgfnTableCheck_(const Opm::SgfnTable& sgfnTables)
+ {
+ const auto& sg = sgfnTables.getSgColumn();
+ const auto& krg = sgfnTables.getKrgColumn();
+
+ ///Check sg column.
+ if (sg.front() < 0 || sg.back() > 1) {
+ OPM_THROW(std::logic_error, "In SGFN table, saturation should be in range [0,1]");
+ }
+
+ ///Check krg column.
+ if (krg.front() < 0 || krg.back() > 1) {
+ OPM_THROW(std::logic_error, "In SGFN table, krg should be in range [0,1]");
+ }
+ if (krg.front() != 0) {
+ OPM_THROW(std::logic_error, "In SGFN table, first value in krg column should be 0");
+ }
+
+ return Opm::Status::Pass;
+ }
+
+ Status RelpermDiagnostics::sof3TableCheck_(const Opm::Sof3Table& sof3Tables)
+ {
+ const auto& so = sof3Tables.getSoColumn();
+ const auto& krow = sof3Tables.getKrowColumn();
+ const auto& krog = sof3Tables.getKrogColumn();
+
+ ///Check so column.
+ ///TODO: The max so = 1 - Swco
+ if (so.front() < 0 || so.back() > 1) {
+ OPM_THROW(std::logic_error, "In SOF3 table, saturation should be in range [0,1]");
+ }
+
+ ///Check krow column.
+ if (krow.front() < 0 || krow.back() > 1) {
+ OPM_THROW(std::logic_error, "In SOF3 table, krow should be in range [0,1]");
+ }
+ if (krow.front() != 0) {
+ OPM_THROW(std::logic_error, "In SOF3 table, first value in krow column should be 0");
+ }
+
+ ///Check krog column.
+ if (krog.front() < 0 || krog.back() > 1) {
+ OPM_THROW(std::logic_error, "In SOF3 table, krog should be in range [0,1]");
+ }
+ if (krog.front() != 0) {
+ OPM_THROW(std::logic_error, "In SOF3 table, first value in krog column should be 0");
+ }
+
+ if (krog.back() != krow.back()) {
+ OPM_THROW(std::logic_error, "In SOF3 table, max value in krog and krow should be the same");
+ }
+
+ return Opm::Status::Pass;
+ }
+
+
+ Status RelpermDiagnostics::sof2TableCheck_(const Opm::Sof2Table& sof2Tables)
+ {
+ const auto& so = sof2Tables.getSoColumn();
+ const auto& kro = sof2Tables.getKroColumn();
+
+ ///Check so column.
+ ///TODO: The max so = 1 - Swco
+ if (so.front() < 0 || so.back() > 1) {
+ OPM_THROW(std::logic_error, "In SOF2 table, saturation should be in range [0,1]");
+ }
+
+ ///Check krow column.
+ if (kro.front() < 0 || kro.back() > 1) {
+ OPM_THROW(std::logic_error, "In SOF2 table, krow should be in range [0,1]");
+ }
+ if (kro.front() != 0) {
+ OPM_THROW(std::logic_error, "In SOF2 table, first value in krow column should be 0");
+ }
+
+ return Opm::Status::Pass;
+ }
+
+
+ Status RelpermDiagnostics::sgwfnTableCheck_(const Opm::SgwfnTable& sgwfnTables)
+ {
+ const auto& sg = sgwfnTables.getSgColumn();
+ const auto& krg = sgwfnTables.getKrgColumn();
+ const auto& krgw = sgwfnTables.getKrgwColumn();
+
+ ///Check sg column.
+ if (sg.front() < 0 || sg.back() > 1) {
+ OPM_THROW(std::logic_error, "In SGWFN table, saturation should be in range [0,1]");
+ }
+
+ ///Check krg column.
+ if (krg.front() < 0 || krg.back() > 1) {
+ OPM_THROW(std::logic_error, "In SGWFN table, krg column should be in range [0,1]");
+ }
+ if (krg.front() != 0) {
+ OPM_THROW(std::logic_error, "In SGWFN table, first value in krg column should be 0");
+ }
+
+ ///Check krgw column.
+ ///TODO check saturation sw = 1. - sg
+ if (krgw.front() > 1 || krgw.back() < 0) {
+ OPM_THROW(std::logic_error, "In SGWFN table, krgw column should be in range [0,1]");
+ }
+ if (krgw.back() != 0) {
+ OPM_THROW(std::logic_error, "In SGWFN table, last value in krgw column should be 0");
+ }
+
+ return Opm::Status::Pass;
+ }
+
+
+
+ Status RelpermDiagnostics::valueRangeCheck_(const std::vector& values,
+ bool isAscending)
+ {
+ if (isAscending) {
+ if (values.front() >1 || values.front() <0) {
+ OPM_THROW(std::logic_error, "Values should be in range [0,1]");
+ }
+ } else {
+ if (values.front() <0 || values.front() >1) {
+ OPM_THROW(std::logic_error, "Values should be in range [0,1]");
+ }
+ }
+
+
+ return Opm::Status::Pass;
+ }
+
+
+ Status RelpermDiagnostics::endPointsCheck(DeckConstPtr deck,
+ EclipseStateConstPtr eclState)
+ {
+ // get the number of saturation regions and the number of cells in the deck
+
+ unsigned numSatRegions = static_cast(deck->getKeyword("TABDIMS")->getRecord(0)->getItem("NTSFUN")->getInt(0));
+ unscaledEpsInfo_.resize(numSatRegions);
+
+ bool hasWater = deck->hasKeyword("WATER");
+ bool hasGas = deck->hasKeyword("GAS");
+ bool hasOil = deck->hasKeyword("OIL");
+
+ auto tables = eclState->getTableManager();
+ const TableContainer& swofTables = tables->getSwofTables();
+ const TableContainer& sgofTables = tables->getSgofTables();
+ const TableContainer& slgofTables = tables->getSlgofTables();
+ const TableContainer& sof3Tables = tables->getSof3Tables();
+
+
+ for (unsigned satnumIdx = 0; satnumIdx < numSatRegions; ++satnumIdx) {
+ unscaledEpsInfo_[satnumIdx].extractUnscaled(deck, eclState, satnumIdx);
+ unscaledEpsInfo_[satnumIdx].print();
+ ///Consistency check.
+ std::cout << "End-Points consistency check......" << std::endl;
+ assert(unscaledEpsInfo_[satnumIdx].Sgu < (1. - unscaledEpsInfo_[satnumIdx].Swl));
+ assert(unscaledEpsInfo_[satnumIdx].Sgl < (1. - unscaledEpsInfo_[satnumIdx].Swu));
+
+
+ ///Krow(Sou) == Krog(Sou) for three-phase
+ /// means Krow(Swco) == Krog(Sgco)
+ double krow_value = 1e20;
+ double krog_value = 1e-20;
+ if (hasWater && hasGas && hasOil) {
+ if (satFamily_ == SaturationFunctionFamily::FamilyI) {
+ if (!sgofTables.empty()) {
+ auto sg = sgofTables.getTable(satnumIdx).getSgColumn();
+ auto krog = sgofTables.getTable(satnumIdx).getKrogColumn();
+ krog_value=Opm::linearInterpolation(sg, krog,unscaledEpsInfo_[satnumIdx].Sgl);
+ } else {
+ assert(!slgofTables.empty());
+ auto sl = slgofTables.getTable(satnumIdx).getSlColumn();
+ auto krog = slgofTables.getTable(satnumIdx).getKrogColumn();
+ krog_value=Opm::linearInterpolation(sl, krog, unscaledEpsInfo_[satnumIdx].Sgl);
+ }
+
+ auto sw = swofTables.getTable(satnumIdx).getSwColumn();
+ auto krow = swofTables.getTable(satnumIdx).getKrowColumn();
+ krow_value = Opm::linearInterpolation(sw, krow,unscaledEpsInfo_[satnumIdx].Swl);
+ }
+ if (satFamily_ == SaturationFunctionFamily::FamilyII) {
+ assert(!sof3Table.empty());
+ const double Sou = 1.- unscaledEpsInfo_[satnumIdx].Swl - unscaledEpsInfo_[satnumIdx].Sgl;
+ auto so = sof3Tables.getTable(satnumIdx).getSoColumn();
+ auto krow = sof3Tables.getTable(satnumIdx).getKrowColumn();
+ auto krog = sof3Tables.getTable(satnumIdx).getKrogColumn();
+ krow_value = Opm::linearInterpolation(so, krow, Sou);
+ krog_value = Opm::linearInterpolation(so, krog, Sou);
+ }
+ assert(krow_value == krog_value);
+ }
+ ///Krw(Sw=0)=Krg(Sg=0)=Krow(So=0)=Krog(So=0)=0.
+ ///Mobile fluid requirements
+ assert(((unscaledEpsInfo_[satnumIdx].Sowcr + unscaledEpsInfo_.[satnumIdx].Swcr)-1) < 1e-30);
+ assert(((unscaledEpsInfo_[satnumIdx].Sogcr + unscaledEpsInfo_.[satnumIdx].Sgcr + unscaledEpsInfo_[satnumIdx].Swl) - 1 ) < 1e-30);
+ }
+ std::cout << "End of Check. All values are resonable." << std::endl;
+ return Opm::Status::Pass;
+ }
+
+
+
+} //namespace Opm
+
+#endif // OPM_RELPERMDIAGNOSTICS_HEADER_INCLUDED