mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Move opm/core/props to opm/simulators/utils
The opm/core directory is no longer meaningful, and it contains only components which might collectively be described as simulator utilities.
This commit is contained in:
58
opm/simulators/utils/BlackoilPhases.cpp
Normal file
58
opm/simulators/utils/BlackoilPhases.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright 2021 Equinor 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif // HAVE_CONFIG_H
|
||||
|
||||
#include <opm/simulators/utils/BlackoilPhases.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
Opm::PhaseUsage::PhaseUsage(std::vector<BlackoilPhases::PhaseIndex> phases)
|
||||
{
|
||||
std::sort(phases.begin(), phases.end());
|
||||
this->phase_used.fill(0);
|
||||
this->phase_pos.fill(-1);
|
||||
|
||||
std::size_t current_pos = 0;
|
||||
for (const auto& phase : phases) {
|
||||
this->phase_used[phase] = 1;
|
||||
this->phase_pos[phase] = current_pos;
|
||||
|
||||
current_pos++;
|
||||
}
|
||||
|
||||
this->num_phases = 0;
|
||||
if (this->phase_used[BlackoilPhases::Aqua])
|
||||
this->num_phases++;
|
||||
if (this->phase_used[BlackoilPhases::Liquid])
|
||||
this->num_phases++;
|
||||
if (this->phase_used[BlackoilPhases::Vapour])
|
||||
this->num_phases++;
|
||||
|
||||
this->has_solvent = this->phase_used[BlackoilPhases::Solvent];
|
||||
this->has_polymer = this->phase_used[BlackoilPhases::Polymer];
|
||||
this->has_energy = this->phase_used[BlackoilPhases::Energy];
|
||||
this->has_polymermw = this->phase_used[BlackoilPhases::PolymerMW];
|
||||
this->has_foam = this->phase_used[BlackoilPhases::Foam];
|
||||
this->has_brine = this->phase_used[BlackoilPhases::Brine];
|
||||
this->has_zFraction = this->phase_used[BlackoilPhases::ZFraction];
|
||||
}
|
||||
68
opm/simulators/utils/BlackoilPhases.hpp
Normal file
68
opm/simulators/utils/BlackoilPhases.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
Copyright 2010, 2011, 2012 SINTEF ICT, Applied Mathematics.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OPM_BLACKOILPHASES_HEADER_INCLUDED
|
||||
#define OPM_BLACKOILPHASES_HEADER_INCLUDED
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
|
||||
class BlackoilPhases
|
||||
{
|
||||
public:
|
||||
static const int MaxNumPhases = 3;
|
||||
|
||||
// "Crypto phases" are "phases" (or rather "conservation quantities") in the
|
||||
// sense that they can be active or not and canonical indices can be translated
|
||||
// to and from active ones. That said, they are not considered by num_phases or
|
||||
// MaxNumPhases. The crypto phases which are currently implemented are solvent,
|
||||
// polymer, energy, polymer molecular weight, foam and brine.
|
||||
static const int NumCryptoPhases = 7;
|
||||
|
||||
// enum ComponentIndex { Water = 0, Oil = 1, Gas = 2 };
|
||||
enum PhaseIndex { Aqua = 0, Liquid = 1, Vapour = 2, Solvent = 3, Polymer = 4, Energy = 5, PolymerMW = 6, Foam = 7, Brine = 8, ZFraction = 9 };
|
||||
};
|
||||
|
||||
struct PhaseUsage : public BlackoilPhases
|
||||
{
|
||||
PhaseUsage() = default;
|
||||
explicit PhaseUsage(std::vector<BlackoilPhases::PhaseIndex> phases);
|
||||
|
||||
|
||||
std::array<int, MaxNumPhases + NumCryptoPhases> phase_used;
|
||||
std::array<int, MaxNumPhases + NumCryptoPhases> phase_pos;
|
||||
|
||||
int num_phases;
|
||||
bool has_solvent{};
|
||||
bool has_polymer{};
|
||||
bool has_energy{};
|
||||
// polymer molecular weight
|
||||
bool has_polymermw{};
|
||||
bool has_foam{};
|
||||
bool has_brine{};
|
||||
bool has_zFraction{};
|
||||
|
||||
};
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
#endif // OPM_BLACKOILPHASES_HEADER_INCLUDED
|
||||
154
opm/simulators/utils/phaseUsageFromDeck.cpp
Normal file
154
opm/simulators/utils/phaseUsageFromDeck.cpp
Normal file
@@ -0,0 +1,154 @@
|
||||
|
||||
/*
|
||||
Copyright 2012 SINTEF ICT, Applied Mathematics.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif // HAVE_CONFIG_H
|
||||
|
||||
#include <opm/simulators/utils/phaseUsageFromDeck.hpp>
|
||||
|
||||
#include <opm/common/ErrorMacros.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Deck/Deck.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Runspec.hpp>
|
||||
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
|
||||
PhaseUsage phaseUsage(const Phases& phases)
|
||||
{
|
||||
PhaseUsage pu;
|
||||
pu.phase_used.fill(0);
|
||||
|
||||
// Discover phase usage.
|
||||
pu.phase_used[BlackoilPhases::Aqua] = phases.active(Phase::WATER);
|
||||
pu.phase_used[BlackoilPhases::Liquid] = phases.active(Phase::OIL);
|
||||
pu.phase_used[BlackoilPhases::Vapour] = phases.active(Phase::GAS);
|
||||
|
||||
pu.num_phases = 0;
|
||||
int activePhaseIdx = -1;
|
||||
for (int phaseIdx = 0; phaseIdx < BlackoilPhases::MaxNumPhases; ++phaseIdx) {
|
||||
if (!pu.phase_used[phaseIdx]) {
|
||||
pu.phase_pos[phaseIdx] = -1;
|
||||
}
|
||||
else {
|
||||
pu.phase_pos[phaseIdx] = ++activePhaseIdx;
|
||||
pu.num_phases = activePhaseIdx+1;
|
||||
}
|
||||
}
|
||||
|
||||
// Add solvent info
|
||||
pu.has_solvent = phases.active(Phase::SOLVENT);
|
||||
if (pu.has_solvent) {
|
||||
// this is quite a hack: even though solvent is not considered as in
|
||||
// MaxNumPhases and pu.num_phases because this would break a lot of
|
||||
// assumptions in old code, it is nevertheless an index to be translated
|
||||
// to. solvent and solvent are even larger hacks because not even this can be
|
||||
// done for them.
|
||||
pu.phase_pos[BlackoilPhases::Solvent] = ++activePhaseIdx;
|
||||
}
|
||||
else
|
||||
pu.phase_pos[BlackoilPhases::Solvent] = -1;
|
||||
|
||||
// Add polymer info
|
||||
pu.has_polymer = phases.active(Phase::POLYMER);
|
||||
if (pu.has_polymer) {
|
||||
// this is quite a hack: even though polymer is not considered as in
|
||||
// MaxNumPhases and pu.num_phases because this would break a lot of
|
||||
// assumptions in old code, it is nevertheless an index to be translated
|
||||
// to. polymer and solvent are even larger hacks because not even this can be
|
||||
// done for them.
|
||||
pu.phase_pos[BlackoilPhases::Polymer] = ++activePhaseIdx;
|
||||
}
|
||||
else
|
||||
pu.phase_pos[BlackoilPhases::Polymer] = -1;
|
||||
|
||||
// Add energy info
|
||||
pu.has_energy = phases.active(Phase::ENERGY);
|
||||
if (pu.has_energy) {
|
||||
// this is quite a hack: even though energy is not considered as in
|
||||
// MaxNumPhases and pu.num_phases because this would break a lot of
|
||||
// assumptions in old code, it is nevertheless an index to be translated
|
||||
// to. polymer and solvent are even larger hacks because not even this can be
|
||||
// done for them.
|
||||
pu.phase_pos[BlackoilPhases::Energy] = ++activePhaseIdx;
|
||||
}
|
||||
else
|
||||
pu.phase_pos[BlackoilPhases::Energy] = -1;
|
||||
|
||||
// Add polymer molecular weight related
|
||||
pu.has_polymermw = phases.active(Phase::POLYMW);
|
||||
if (pu.has_polymermw) {
|
||||
if (!pu.has_polymer) {
|
||||
OPM_THROW(std::runtime_error, "pu.has_polymermw is true while pu.has_polymer is false");
|
||||
}
|
||||
pu.phase_pos[BlackoilPhases::PolymerMW] = ++activePhaseIdx;
|
||||
}
|
||||
else
|
||||
pu.phase_pos[BlackoilPhases::PolymerMW] = -1;
|
||||
|
||||
// Add foam info
|
||||
pu.has_foam = phases.active(Phase::FOAM);
|
||||
if (pu.has_foam) {
|
||||
pu.phase_pos[BlackoilPhases::Foam] = ++activePhaseIdx;
|
||||
}
|
||||
else
|
||||
pu.phase_pos[BlackoilPhases::Foam] = -1;
|
||||
|
||||
// Add brine info
|
||||
pu.has_brine = phases.active(Phase::BRINE);
|
||||
if (pu.has_brine) {
|
||||
pu.phase_pos[BlackoilPhases::Brine] = ++activePhaseIdx;
|
||||
}
|
||||
else
|
||||
pu.phase_pos[BlackoilPhases::Brine] = -1;
|
||||
|
||||
// Add zFraction info
|
||||
pu.has_zFraction = phases.active(Phase::ZFRACTION);
|
||||
if (pu.has_zFraction) {
|
||||
pu.phase_pos[BlackoilPhases::ZFraction] = ++activePhaseIdx;
|
||||
}
|
||||
else
|
||||
pu.phase_pos[BlackoilPhases::ZFraction] = -1;
|
||||
|
||||
|
||||
return pu;
|
||||
}
|
||||
|
||||
PhaseUsage phaseUsageFromDeck(const EclipseState& eclipseState)
|
||||
{
|
||||
const auto& phases = eclipseState.runspec().phases();
|
||||
|
||||
return phaseUsage(phases);
|
||||
}
|
||||
|
||||
/// Looks at presence of WATER, OIL and GAS keywords in deck
|
||||
/// to determine active phases.
|
||||
PhaseUsage phaseUsageFromDeck(const Deck& deck)
|
||||
{
|
||||
Runspec runspec( deck );
|
||||
const auto& phases = runspec.phases();
|
||||
|
||||
return phaseUsage(phases);
|
||||
}
|
||||
|
||||
}
|
||||
44
opm/simulators/utils/phaseUsageFromDeck.hpp
Normal file
44
opm/simulators/utils/phaseUsageFromDeck.hpp
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
/*
|
||||
Copyright 2012 SINTEF ICT, Applied Mathematics.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OPM_PHASEUSAGEFROMDECK_HEADER_INCLUDED
|
||||
#define OPM_PHASEUSAGEFROMDECK_HEADER_INCLUDED
|
||||
|
||||
#include <opm/simulators/utils/BlackoilPhases.hpp>
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
class Deck;
|
||||
class EclipseState;
|
||||
class Phases;
|
||||
|
||||
/// Determine the active phases
|
||||
PhaseUsage phaseUsage(const Phases& phases);
|
||||
|
||||
/// Looks at presence of WATER, OIL and GAS keywords in state object
|
||||
/// to determine active phases.
|
||||
PhaseUsage phaseUsageFromDeck(const EclipseState& eclipseState);
|
||||
|
||||
/// Looks at presence of WATER, OIL and GAS keywords in deck
|
||||
/// to determine active phases.
|
||||
PhaseUsage phaseUsageFromDeck(const Deck& deck);
|
||||
}
|
||||
|
||||
#endif // OPM_PHASEUSAGEFROMDECK_HEADER_INCLUDED
|
||||
902
opm/simulators/utils/satfunc/RelpermDiagnostics.cpp
Normal file
902
opm/simulators/utils/satfunc/RelpermDiagnostics.cpp
Normal file
@@ -0,0 +1,902 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif // HAVE_CONFIG_H
|
||||
|
||||
#include <opm/simulators/utils/satfunc/RelpermDiagnostics.hpp>
|
||||
#include <opm/simulators/utils/phaseUsageFromDeck.hpp>
|
||||
|
||||
#include <opm/material/fluidmatrixinteractions/EclEpsGridProperties.hpp>
|
||||
#include <opm/material/fluidmatrixinteractions/EclEpsScalingPoints.hpp>
|
||||
|
||||
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Grid/SatfuncPropertyInitializers.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Runspec.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/SgfnTable.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/SgofTable.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/SgwfnTable.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/SlgofTable.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/Sof2Table.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/Sof3Table.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/SsfnTable.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/SwfnTable.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/SwofTable.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/WsfTable.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/GsfTable.hpp>
|
||||
|
||||
#include <opm/grid/CpGrid.hpp>
|
||||
#include <opm/grid/polyhedralgrid.hh>
|
||||
|
||||
#ifdef HAVE_DUNE_ALUGRID
|
||||
#include <dune/alugrid/grid.hh>
|
||||
#include <dune/alugrid/3d/gridview.hh>
|
||||
#endif // HAVE_DUNE_ALUGRID
|
||||
|
||||
namespace Opm {
|
||||
|
||||
bool RelpermDiagnostics::phaseCheck_(const EclipseState& es)
|
||||
{
|
||||
const auto& phases = es.runspec().phases();
|
||||
bool hasWater = phases.active( Phase::WATER );
|
||||
bool hasGas = phases.active( Phase::GAS );
|
||||
bool hasOil = phases.active( Phase::OIL );
|
||||
bool hasSolvent = phases.active( Phase::SOLVENT );
|
||||
|
||||
if (hasWater && !hasGas && !hasOil && !hasSolvent) {
|
||||
const std::string msg = "System: Single phase Water system. Nothing to check";
|
||||
OpmLog::info(msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hasWater && hasGas && !hasOil && !hasSolvent) {
|
||||
const std::string msg = "System: Single phase Gas system. Nothing to check";
|
||||
OpmLog::info(msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hasWater && !hasGas && hasOil && !hasSolvent) {
|
||||
const std::string msg = "System: Single phase Oil system. Nothing to check";
|
||||
OpmLog::info(msg);
|
||||
return false;
|
||||
}
|
||||
if (hasWater && hasGas && !hasOil && !hasSolvent) {
|
||||
const std::string msg = "System: Water-Gas system.";
|
||||
OpmLog::info(msg);
|
||||
fluidSystem_ = FluidSystem::WaterGas;
|
||||
}
|
||||
if (hasWater && hasOil && !hasGas && !hasSolvent) {
|
||||
const std::string msg = "System: Oil-Water system.";
|
||||
OpmLog::info(msg);
|
||||
fluidSystem_ = FluidSystem::OilWater;
|
||||
}
|
||||
if (hasOil && hasGas && !hasWater && !hasSolvent) {
|
||||
const std::string msg = "System: Oil-Gas system.";
|
||||
OpmLog::info(msg);
|
||||
fluidSystem_ = FluidSystem::OilGas;
|
||||
}
|
||||
if (hasOil && hasWater && hasGas && !hasSolvent) {
|
||||
const std::string msg = "System: Black-oil system.";
|
||||
OpmLog::info(msg);
|
||||
fluidSystem_ = FluidSystem::BlackOil;
|
||||
}
|
||||
if (hasSolvent) {
|
||||
const std::string msg = "System: Solvent model.";
|
||||
OpmLog::info(msg);
|
||||
fluidSystem_ = FluidSystem::Solvent;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void RelpermDiagnostics::satFamilyCheck_(const EclipseState& eclState)
|
||||
{
|
||||
const PhaseUsage pu = phaseUsageFromDeck(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();
|
||||
|
||||
const SwofletTable& swofletTable = tableManager.getSwofletTable();
|
||||
const SgofletTable& sgofletTable = tableManager.getSgofletTable();
|
||||
|
||||
const TableContainer& gsfTables = tableManager.getGsfTables();
|
||||
const TableContainer& wsfTables = tableManager.getWsfTables();
|
||||
|
||||
// Family I test.
|
||||
bool family1 = pu.phase_used[BlackoilPhases::Liquid];
|
||||
if (pu.phase_used[BlackoilPhases::Aqua]) {
|
||||
family1 = family1 && (!swofTables.empty() || !swofletTable.empty());
|
||||
}
|
||||
if (pu.phase_used[BlackoilPhases::Vapour]) {
|
||||
family1 = family1 && ((!sgofTables.empty() || !sgofletTable.empty()) || !slgofTables.empty());
|
||||
}
|
||||
|
||||
// Family II test.
|
||||
bool family2 = true;
|
||||
if (pu.phase_used[BlackoilPhases::Aqua]) {
|
||||
family2 = family2 && (!swfnTables.empty() || !sgwfnTables.empty());
|
||||
}
|
||||
if (pu.phase_used[BlackoilPhases::Liquid]) {
|
||||
family2 = family2 && (!sof3Tables.empty() || !sof2Tables.empty());
|
||||
}
|
||||
if (pu.phase_used[BlackoilPhases::Vapour]) {
|
||||
family2 = family2 && (!sgfnTables.empty() || !sgwfnTables.empty());
|
||||
}
|
||||
|
||||
bool family3 = !gsfTables.empty() && !wsfTables.empty();
|
||||
|
||||
if (family3) {
|
||||
const auto& phases = eclState.runspec().phases();
|
||||
const bool co2store = eclState.runspec().co2Storage();
|
||||
const bool h2store = eclState.runspec().h2Storage();
|
||||
if ( !((co2store || h2store) && phases.active(Phase::GAS) && phases.active(Phase::WATER))) {
|
||||
const std::string msg = "Relative permeability input format: Saturation Family III. \n \
|
||||
Only valid for CO2STORE or H2STORE cases with GAS and WATER.";
|
||||
OpmLog::info(msg);
|
||||
}
|
||||
satFamily_ = SaturationFunctionFamily::FamilyIII;
|
||||
const std::string msg = "Relative permeability input format: Saturation Family III (GSF/WSF).";
|
||||
OpmLog::info(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (family1 && family2) {
|
||||
const std::string msg = "Saturation families should not be mixed.\n Use either SGOF and SWOF or SGFN, SWFN and SOF3";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
if (!family1 && !family2) {
|
||||
const std::string msg = "Saturations function must be specified using either \n \
|
||||
family 1, family 2 or family3 keywords \n \
|
||||
Use either SGOF and SWOF or SGFN, SWFN and SOF3.";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
if (family1 && !family2) {
|
||||
satFamily_ = SaturationFunctionFamily::FamilyI;
|
||||
const std::string msg = "Relative permeability input format: Saturation Family I.";
|
||||
OpmLog::info(msg);
|
||||
}
|
||||
if (!family1 && family2) {
|
||||
satFamily_ = SaturationFunctionFamily::FamilyII;
|
||||
const std::string msg = "Relative permeability input format: Saturation Family II.";
|
||||
OpmLog::info(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void RelpermDiagnostics::tableCheck_(const EclipseState& eclState)
|
||||
{
|
||||
const int numSatRegions = eclState.runspec().tabdims().getNumSatTables();
|
||||
{
|
||||
const std::string msg = "Number of saturation regions: " + std::to_string(numSatRegions) + "\n";
|
||||
OpmLog::info(msg);
|
||||
}
|
||||
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();
|
||||
const TableContainer& sgcwmisTables = tableManager.getSgcwmisTables();
|
||||
const TableContainer& sorwmisTables = tableManager.getSorwmisTables();
|
||||
const TableContainer& ssfnTables = tableManager.getSsfnTables();
|
||||
const TableContainer& miscTables = tableManager.getMiscTables();
|
||||
const TableContainer& msfnTables = tableManager.getMsfnTables();
|
||||
const TableContainer& gsfTables = tableManager.getGsfTables();
|
||||
const TableContainer& wsfTables = tableManager.getWsfTables();
|
||||
|
||||
for (int satnumIdx = 0; satnumIdx < numSatRegions; ++satnumIdx) {
|
||||
if (tableManager.hasTables("SWOF")) {
|
||||
swofTableCheck_(swofTables.getTable<SwofTable>(satnumIdx), satnumIdx+1);
|
||||
}
|
||||
if (tableManager.hasTables("SGOF")) {
|
||||
sgofTableCheck_(sgofTables.getTable<SgofTable>(satnumIdx), satnumIdx+1);
|
||||
}
|
||||
if (tableManager.hasTables("SLGOF")) {
|
||||
slgofTableCheck_(slgofTables.getTable<SlgofTable>(satnumIdx), satnumIdx+1);
|
||||
}
|
||||
if (tableManager.hasTables("SWFN")) {
|
||||
swfnTableCheck_(swfnTables.getTable<SwfnTable>(satnumIdx), satnumIdx+1);
|
||||
}
|
||||
if (tableManager.hasTables("SGFN")) {
|
||||
sgfnTableCheck_(sgfnTables.getTable<SgfnTable>(satnumIdx), satnumIdx+1);
|
||||
}
|
||||
if (tableManager.hasTables("SOF3")) {
|
||||
sof3TableCheck_(sof3Tables.getTable<Sof3Table>(satnumIdx), satnumIdx+1);
|
||||
}
|
||||
if (tableManager.hasTables("SOF2")) {
|
||||
sof2TableCheck_(sof2Tables.getTable<Sof2Table>(satnumIdx), satnumIdx+1);
|
||||
}
|
||||
if (tableManager.hasTables("SGWFN")) {
|
||||
sgwfnTableCheck_(sgwfnTables.getTable<SgwfnTable>(satnumIdx), satnumIdx+1);
|
||||
}
|
||||
if (tableManager.hasTables("SGCWMIS")) {
|
||||
sgcwmisTableCheck_(sgcwmisTables.getTable<SgcwmisTable>(satnumIdx), satnumIdx+1);
|
||||
}
|
||||
if (tableManager.hasTables("SORWMIS")) {
|
||||
sorwmisTableCheck_(sorwmisTables.getTable<SorwmisTable>(satnumIdx), satnumIdx+1);
|
||||
}
|
||||
if (tableManager.hasTables("SSFN")) {
|
||||
ssfnTableCheck_(ssfnTables.getTable<SsfnTable>(satnumIdx), satnumIdx+1);
|
||||
}
|
||||
if (tableManager.hasTables("MSFN")) {
|
||||
msfnTableCheck_(msfnTables.getTable<MsfnTable>(satnumIdx), satnumIdx+1);
|
||||
}
|
||||
if (tableManager.hasTables("GSF")) {
|
||||
gsfTableCheck_(gsfTables.getTable<GsfTable>(satnumIdx), satnumIdx+1);
|
||||
}
|
||||
if (tableManager.hasTables("WSF")) {
|
||||
wsfTableCheck_(wsfTables.getTable<WsfTable>(satnumIdx), satnumIdx+1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (tableManager.hasTables("MISC")) {
|
||||
const int numMiscNumIdx = miscTables.size();
|
||||
const std::string msg = "Number of misc regions: " + std::to_string(numMiscNumIdx) + "\n";
|
||||
OpmLog::info(msg);
|
||||
for (int miscNumIdx = 0; miscNumIdx < numMiscNumIdx; ++miscNumIdx) {
|
||||
miscTableCheck_(miscTables.getTable<MiscTable>(miscNumIdx), miscNumIdx+1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void RelpermDiagnostics::swofTableCheck_(const SwofTable& swofTables,
|
||||
const int satnumIdx)
|
||||
{
|
||||
const auto& sw = swofTables.getSwColumn();
|
||||
const auto& krw = swofTables.getKrwColumn();
|
||||
const auto& krow = swofTables.getKrowColumn();
|
||||
const std::string regionIdx = std::to_string(satnumIdx);
|
||||
//Check sw column.
|
||||
if (sw.front() < 0.0 || sw.back() > 1.0) {
|
||||
const std::string msg = "In SWOF table SATNUM = "+ regionIdx + ", saturation should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
//TODO check endpoint sw.back() == 1. - Sor.
|
||||
//Check krw column.
|
||||
if (krw.front() != 0.0) {
|
||||
const std::string msg = "In SWOF table SATNUM = " + regionIdx + ", first value of krw should be 0.";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
if (krw.front() < 0.0 || krw.back() > 1.0) {
|
||||
const std::string msg = "In SWOF table SATNUM = " + regionIdx + ", krw should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
///Check krow column.
|
||||
if (krow.front() > 1.0 || krow.back() < 0.0) {
|
||||
const std::string msg = "In SWOF table SATNUM = "+ regionIdx + ", krow should be in range [0, 1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
///TODO check if run with gas.
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void RelpermDiagnostics::sgofTableCheck_(const SgofTable& sgofTables,
|
||||
const int satnumIdx)
|
||||
{
|
||||
const auto& sg = sgofTables.getSgColumn();
|
||||
const auto& krg = sgofTables.getKrgColumn();
|
||||
const auto& krog = sgofTables.getKrogColumn();
|
||||
const std::string regionIdx = std::to_string(satnumIdx);
|
||||
//Check sw column.
|
||||
if (sg.front() < 0.0 || sg.back() > 1.0) {
|
||||
const std::string msg = "In SGOF table SATNUM = " + regionIdx + ", saturation should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
if (sg.front() != 0.0) {
|
||||
const std::string msg = "In SGOF table SATNUM = " + regionIdx + ", first value of sg should be 0.";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
//TODO check endpoint sw.back() == 1. - Sor.
|
||||
//Check krw column.
|
||||
if (krg.front() != 0.0) {
|
||||
const std::string msg = "In SGOF table SATNUM = " + regionIdx + ", first value of krg should be 0.";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
if (krg.front() < 0.0 || krg.back() > 1.0) {
|
||||
const std::string msg = "In SGOF table SATNUM = " + regionIdx + ", krg should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
//Check krow column.
|
||||
if (krog.front() > 1.0 || krog.back() < 0.0) {
|
||||
const std::string msg = "In SGOF table SATNUM = " + regionIdx + ", krog should be in range [0, 1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
//TODO check if run with water.
|
||||
}
|
||||
|
||||
void RelpermDiagnostics::slgofTableCheck_(const SlgofTable& slgofTables,
|
||||
const int satnumIdx)
|
||||
{
|
||||
const auto& sl = slgofTables.getSlColumn();
|
||||
const auto& krg = slgofTables.getKrgColumn();
|
||||
const auto& krog = slgofTables.getKrogColumn();
|
||||
const std::string regionIdx = std::to_string(satnumIdx);
|
||||
//Check sl column.
|
||||
//TODO first value means sl = swco + sor
|
||||
if (sl.front() < 0.0 || sl.back() > 1.0) {
|
||||
const std::string msg = "In SLGOF table SATNUM = " + regionIdx + ", saturation should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
if (sl.back() != 1.0) {
|
||||
const std::string msg = "In SLGOF table SATNUM = " + regionIdx + ", last value of sl should be 1.";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
if (krg.front() > 1.0 || krg.back() < 0) {
|
||||
const std::string msg = "In SLGOF table SATNUM = " + regionIdx + ", krg should be in range [0, 1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
if (krg.back() != 0.0) {
|
||||
const std::string msg = "In SLGOF table SATNUM = " + regionIdx + ", last value of krg hould be 0.";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
if (krog.front() < 0.0 || krog.back() > 1.0) {
|
||||
const std::string msg = "In SLGOF table SATNUM = " + regionIdx + ", krog should be in range [0, 1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void RelpermDiagnostics::swfnTableCheck_(const SwfnTable& swfnTables,
|
||||
const int satnumIdx)
|
||||
{
|
||||
const auto& sw = swfnTables.getSwColumn();
|
||||
const auto& krw = swfnTables.getKrwColumn();
|
||||
const std::string regionIdx = std::to_string(satnumIdx);
|
||||
//Check sw column.
|
||||
if (sw.front() < 0.0 || sw.back() > 1.0) {
|
||||
const std::string msg = "In SWFN table SATNUM = " + regionIdx + ", saturation should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
//Check krw column.
|
||||
if (krw.front() < 0.0 || krw.back() > 1.0) {
|
||||
const std::string msg = "In SWFN table SATNUM = " + regionIdx + ", krw should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
if (krw.front() != 0.0) {
|
||||
const std::string msg = "In SWFN table SATNUM = " + regionIdx + ", first value of krw should be 0.";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void RelpermDiagnostics::wsfTableCheck_(const WsfTable& wsfTables,
|
||||
const int satnumIdx)
|
||||
{
|
||||
const auto& sw = wsfTables.getSwColumn();
|
||||
const auto& krw = wsfTables.getKrwColumn();
|
||||
const std::string regionIdx = std::to_string(satnumIdx);
|
||||
//Check sw column.
|
||||
if (sw.front() < 0.0 || sw.back() > 1.0) {
|
||||
const std::string msg = "In WSF table SATNUM = " + regionIdx + ", saturation should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
//Check krw column.
|
||||
if (krw.front() < 0.0 || krw.back() > 1.0) {
|
||||
const std::string msg = "In WSF table SATNUM = " + regionIdx + ", krw should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
if (krw.front() != 0.0) {
|
||||
const std::string msg = "In WSF table SATNUM = " + regionIdx + ", first value of krw should be 0.";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void RelpermDiagnostics::sgfnTableCheck_(const SgfnTable& sgfnTables,
|
||||
const int satnumIdx)
|
||||
{
|
||||
const auto& sg = sgfnTables.getSgColumn();
|
||||
const auto& krg = sgfnTables.getKrgColumn();
|
||||
const std::string regionIdx = std::to_string(satnumIdx);
|
||||
//Check sg column.
|
||||
if (sg.front() < 0.0 || sg.back() > 1.0) {
|
||||
const std::string msg = "In SGFN table SATNUM = " + regionIdx + ", saturation should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
//Check krg column.
|
||||
if (krg.front() < 0.0 || krg.back() > 1.0) {
|
||||
const std::string msg = "In SGFN table SATNUM = " + regionIdx + ", krg should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
if (krg.front() != 0.0) {
|
||||
const std::string msg = "In SGFN table SATNUM = " + regionIdx + ", first value of krg should be 0.";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RelpermDiagnostics::gsfTableCheck_(const GsfTable& gsfTables,
|
||||
const int satnumIdx)
|
||||
{
|
||||
const auto& sg = gsfTables.getSgColumn();
|
||||
const auto& krg = gsfTables.getKrgColumn();
|
||||
const std::string regionIdx = std::to_string(satnumIdx);
|
||||
//Check sg column.
|
||||
if (sg.front() < 0.0 || sg.back() > 1.0) {
|
||||
const std::string msg = "In GSF table SATNUM = " + regionIdx + ", saturation should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
//Check krg column.
|
||||
if (krg.front() < 0.0 || krg.back() > 1.0) {
|
||||
const std::string msg = "In GSF table SATNUM = " + regionIdx + ", krg should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
if (krg.front() != 0.0) {
|
||||
const std::string msg = "In GSF table SATNUM = " + regionIdx + ", first value of krg should be 0.";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RelpermDiagnostics::sof3TableCheck_(const Sof3Table& sof3Tables,
|
||||
const int satnumIdx)
|
||||
{
|
||||
const auto& so = sof3Tables.getSoColumn();
|
||||
const auto& krow = sof3Tables.getKrowColumn();
|
||||
const auto& krog = sof3Tables.getKrogColumn();
|
||||
const std::string regionIdx = std::to_string(satnumIdx);
|
||||
//Check so column.
|
||||
//TODO: The max so = 1 - Swco
|
||||
if (so.front() < 0.0 || so.back() > 1.0) {
|
||||
const std::string msg = "In SOF3 table SATNUM = " + regionIdx + ", saturation should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
//Check krow column.
|
||||
if (krow.front() < 0.0 || krow.back() > 1.0) {
|
||||
const std::string msg = "In SOF3 table SATNUM = " + regionIdx + ", krow should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
if (krow.front() != 0.0) {
|
||||
const std::string msg = "In SOF3 table SATNUM = " + regionIdx + ", first value of krow should be 0.";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
//Check krog column.
|
||||
if (krog.front() < 0.0 || krog.back() > 1.0) {
|
||||
const std::string msg = "In SOF3 table SATNUM = " + regionIdx + ", krog should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
if (krog.front() != 0.0) {
|
||||
const std::string msg = "In SOF3 table SATNUM = " + regionIdx + ", first value of krog should be 0.";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
if (krog.back() != krow.back()) {
|
||||
const std::string msg = "In SOF3 table SATNUM = " + regionIdx + ", max value of krog and krow should be the same.";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void RelpermDiagnostics::sof2TableCheck_(const Sof2Table& sof2Tables,
|
||||
const int satnumIdx)
|
||||
{
|
||||
const auto& so = sof2Tables.getSoColumn();
|
||||
const auto& kro = sof2Tables.getKroColumn();
|
||||
const std::string regionIdx = std::to_string(satnumIdx);
|
||||
//Check so column.
|
||||
//TODO: The max so = 1 - Swco
|
||||
if (so.front() < 0.0 || so.back() > 1.0) {
|
||||
const std::string msg = "In SOF2 table SATNUM = " + regionIdx + ", saturation should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
//Check krow column.
|
||||
if (kro.front() < 0.0 || kro.back() > 1.0) {
|
||||
const std::string msg = "In SOF2 table SATNUM = " + regionIdx + ", krow should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
if (kro.front() != 0.0) {
|
||||
const std::string msg = "In SOF2 table SATNUM = " + regionIdx + ", first value of krow should be 0.";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void RelpermDiagnostics::sgwfnTableCheck_(const SgwfnTable& sgwfnTables,
|
||||
const int satnumIdx)
|
||||
{
|
||||
const auto& sg = sgwfnTables.getSgColumn();
|
||||
const auto& krg = sgwfnTables.getKrgColumn();
|
||||
const auto& krgw = sgwfnTables.getKrgwColumn();
|
||||
const std::string regionIdx = std::to_string(satnumIdx);
|
||||
//Check sg column.
|
||||
if (sg.front() < 0.0 || sg.back() > 1.0) {
|
||||
const std::string msg = "In SGWFN table SATNUM = " + regionIdx + ", saturation should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
//Check krg column.
|
||||
if (krg.front() < 0.0 || krg.back() > 1.0) {
|
||||
const std::string msg = "In SGWFN table SATNUM = " + regionIdx + ", krg should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
if (krg.front() != 0.0) {
|
||||
const std::string msg = "In SGWFN table SATNUM = " + regionIdx + ", first value of krg should be 0.";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
//Check krgw column.
|
||||
//TODO check saturation sw = 1. - sg
|
||||
if (krgw.front() > 1.0 || krgw.back() < 0.0) {
|
||||
const std::string msg = "In SGWFN table SATNUM = " + regionIdx + ", krgw should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
if (krgw.back() != 0.0) {
|
||||
const std::string msg = "In SGWFN table SATNUM = " + regionIdx + ", last value of krgw should be 0.";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void RelpermDiagnostics::sgcwmisTableCheck_(const SgcwmisTable& sgcwmisTables,
|
||||
const int satnumIdx)
|
||||
{
|
||||
const auto& sw = sgcwmisTables.getWaterSaturationColumn();
|
||||
const auto& sgc = sgcwmisTables.getMiscibleResidualGasColumn();
|
||||
const std::string regionIdx = std::to_string(satnumIdx);
|
||||
//Check sw column.
|
||||
if (sw.front() < 0.0 || sw.back() > 1.0) {
|
||||
const std::string msg = "In SGCWMIS table SATNUM = " + regionIdx + ", saturation should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
//Check critical gas column.
|
||||
if (sgc.front() < 0.0 || sgc.back() > 1.0) {
|
||||
const std::string msg = "In SGCWMIS table SATNUM = " + regionIdx + ", critical gas saturation should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void RelpermDiagnostics::sorwmisTableCheck_(const SorwmisTable& sorwmisTables,
|
||||
const int satnumIdx)
|
||||
{
|
||||
const auto& sw = sorwmisTables.getWaterSaturationColumn();
|
||||
const auto& sor = sorwmisTables.getMiscibleResidualOilColumn();
|
||||
const std::string regionIdx = std::to_string(satnumIdx);
|
||||
//Check sw column.
|
||||
if (sw.front() < 0.0 || sw.back() > 1.0) {
|
||||
const std::string msg = "In SORWMIS table SATNUM = " + regionIdx + ", saturation should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
//Check critical oil column.
|
||||
if (sor.front() < 0.0 || sor.back() > 1.0) {
|
||||
const std::string msg = "In SORWMIS table SATNUM = " + regionIdx + ", critical oil saturation should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void RelpermDiagnostics::ssfnTableCheck_(const SsfnTable& ssfnTables,
|
||||
const int satnumIdx)
|
||||
{
|
||||
const auto& frac = ssfnTables.getSolventFractionColumn();
|
||||
const auto& krgm = ssfnTables.getGasRelPermMultiplierColumn();
|
||||
const auto& krsm = ssfnTables.getSolventRelPermMultiplierColumn();
|
||||
const std::string regionIdx = std::to_string(satnumIdx);
|
||||
//Check phase fraction column.
|
||||
if (frac.front() < 0.0 || frac.back() > 1.0) {
|
||||
const std::string msg = "In SSFN table SATNUM = " + regionIdx + ", phase fraction should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
//Check gas relperm multiplier column.
|
||||
if (krgm.front() < 0.0 || krgm.back() > 1.0) {
|
||||
const std::string msg = "In SSFN table SATNUM = " + regionIdx + ", gas relative permeability multiplier should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
//Check solvent relperm multiplier column.
|
||||
if (krsm.front() < 0.0 || krsm.back() > 1.0) {
|
||||
const std::string msg = "In SSFN table SATNUM = " + regionIdx + ", solvent relative permeability multiplier should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void RelpermDiagnostics::miscTableCheck_(const MiscTable& miscTables,
|
||||
const int miscnumIdx)
|
||||
{
|
||||
const auto& frac = miscTables.getSolventFractionColumn();
|
||||
const auto& misc = miscTables.getMiscibilityColumn();
|
||||
|
||||
const std::string regionIdx = std::to_string(miscnumIdx);
|
||||
//Check phase fraction column.
|
||||
if (frac.front() < 0.0 || frac.back() > 1.0) {
|
||||
const std::string msg = "In MISC table MISCNUM = " + regionIdx + ", phase fraction should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
//Check miscibility column.
|
||||
if (misc.front() < 0.0 || misc.back() > 1.0) {
|
||||
const std::string msg = "In MISC table MISCNUM = " + regionIdx + ", miscibility should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void RelpermDiagnostics::msfnTableCheck_(const MsfnTable& msfnTables,
|
||||
const int satnumIdx)
|
||||
{
|
||||
const auto& frac = msfnTables.getGasPhaseFractionColumn();
|
||||
const auto& krgsm = msfnTables.getGasSolventRelpermMultiplierColumn();
|
||||
const auto& krom = msfnTables.getOilRelpermMultiplierColumn();
|
||||
|
||||
const std::string regionIdx = std::to_string(satnumIdx);
|
||||
//Check phase fraction column.
|
||||
if (frac.front() < 0.0 || frac.back() > 1.0) {
|
||||
const std::string msg = "In MSFN table SATNUM = " + regionIdx + ", total gas fraction should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
//Check gas_solvent relperm multiplier column.
|
||||
if (krgsm.front() < 0.0 || krgsm.back() > 1.0) {
|
||||
const std::string msg = "In MSFN table SATNUM = " + regionIdx + ", gas+solvent relative permeability multiplier should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
|
||||
//Check oil relperm multiplier column.
|
||||
if (krom.front() > 1.0 || krom.back() < 0.0) {
|
||||
const std::string msg = "In MSFN table SATNUM = " + regionIdx + ", oil relative permeability multiplier should be in range [0,1].";
|
||||
OpmLog::error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void RelpermDiagnostics::unscaledEndPointsCheck_(const EclipseState& eclState)
|
||||
{
|
||||
// get the number of saturation regions and the number of cells in the deck
|
||||
const auto& runspec = eclState.runspec();
|
||||
const int numSatRegions = runspec.tabdims().getNumSatTables();
|
||||
|
||||
if (numSatRegions < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
unscaledEpsInfo_.resize(numSatRegions);
|
||||
|
||||
const auto& tables = eclState.getTableManager();
|
||||
const auto& phases = runspec.phases();
|
||||
const auto tolcrit = runspec.saturationFunctionControls()
|
||||
.minimumRelpermMobilityThreshold();
|
||||
|
||||
const auto rtep =
|
||||
satfunc::getRawTableEndpoints(tables, phases, tolcrit);
|
||||
|
||||
const auto rfunc =
|
||||
satfunc::getRawFunctionValues(tables, phases, rtep);
|
||||
|
||||
const TableContainer& swofTables = tables.getSwofTables();
|
||||
const SwofletTable& swofletTables = tables.getSwofletTable();
|
||||
const TableContainer& sgofTables = tables.getSgofTables();
|
||||
const SgofletTable& sgofletTables = tables.getSgofletTable();
|
||||
const TableContainer& slgofTables = tables.getSlgofTables();
|
||||
const TableContainer& sof3Tables = tables.getSof3Tables();
|
||||
|
||||
// std::cout << "***************\nEnd-Points In all the Tables\n";
|
||||
for (int satnumIdx = 0; satnumIdx < numSatRegions; ++satnumIdx) {
|
||||
this->unscaledEpsInfo_[satnumIdx]
|
||||
.extractUnscaled(rtep, rfunc, satnumIdx);
|
||||
|
||||
const std::string regionIdx = std::to_string(satnumIdx + 1);
|
||||
///Consistency check.
|
||||
if (unscaledEpsInfo_[satnumIdx].Sgu > (1. - unscaledEpsInfo_[satnumIdx].Swl)) {
|
||||
const std::string msg = "In saturation table SATNUM = " + regionIdx + ", Sgmax should not exceed 1-Swco.";
|
||||
OpmLog::warning(msg);
|
||||
}
|
||||
if (unscaledEpsInfo_[satnumIdx].Sgl > (1. - unscaledEpsInfo_[satnumIdx].Swu)) {
|
||||
const std::string msg = "In saturation table SATNUM = " + regionIdx + ", Sgco should not exceed 1-Swmax.";
|
||||
OpmLog::warning(msg);
|
||||
}
|
||||
|
||||
//Krow(Sou) == Krog(Sou) for three-phase
|
||||
// means Krow(Swco) == Krog(Sgco)
|
||||
double krow_value = 1e20;
|
||||
double krog_value = 1e-20;
|
||||
if (fluidSystem_ == FluidSystem::BlackOil) {
|
||||
if (satFamily_ == SaturationFunctionFamily::FamilyI) {
|
||||
if (!sgofTables.empty()) {
|
||||
const auto& table = sgofTables.getTable<SgofTable>(satnumIdx);
|
||||
krog_value = table.evaluate( "KROG" , unscaledEpsInfo_[satnumIdx].Sgl );
|
||||
} else if (!sgofletTables.empty()) {
|
||||
krog_value = sgofletTables[satnumIdx].krt2_relperm;
|
||||
} else {
|
||||
assert(!slgofTables.empty());
|
||||
const auto& table = slgofTables.getTable<SlgofTable>(satnumIdx);
|
||||
krog_value = table.evaluate( "KROG" , unscaledEpsInfo_[satnumIdx].Sgl );
|
||||
}
|
||||
if (!swofTables.empty()) {
|
||||
const auto& table = swofTables.getTable<SwofTable>(satnumIdx);
|
||||
krow_value = table.evaluate("KROW" , unscaledEpsInfo_[satnumIdx].Swl);
|
||||
} else {
|
||||
assert(!swofletTables.empty());
|
||||
krow_value = swofletTables[satnumIdx].krt2_relperm;
|
||||
}
|
||||
}
|
||||
if (satFamily_ == SaturationFunctionFamily::FamilyII) {
|
||||
assert(!sof3Tables.empty());
|
||||
const auto& table = sof3Tables.getTable<Sof3Table>(satnumIdx);
|
||||
const double Sou = 1.- unscaledEpsInfo_[satnumIdx].Swl - unscaledEpsInfo_[satnumIdx].Sgl;
|
||||
|
||||
krow_value = table.evaluate("KROW" , Sou);
|
||||
krog_value = table.evaluate("KROG" , Sou);
|
||||
}
|
||||
if (krow_value != krog_value) {
|
||||
const std::string msg = "In saturation table SATNUM = " + regionIdx + ", Krow(Somax) should be equal to Krog(Somax).";
|
||||
OpmLog::warning(msg);
|
||||
}
|
||||
}
|
||||
//Krw(Sw=0)=Krg(Sg=0)=Krow(So=0)=Krog(So=0)=0.
|
||||
//Mobile fluid requirements
|
||||
if (((unscaledEpsInfo_[satnumIdx].Sowcr + unscaledEpsInfo_[satnumIdx].Swcr)-1) >= 0) {
|
||||
const std::string msg = "In saturation table SATNUM = " + regionIdx + ", Sowcr + Swcr should be less than 1.";
|
||||
OpmLog::warning(msg);
|
||||
}
|
||||
if (((unscaledEpsInfo_[satnumIdx].Sogcr + unscaledEpsInfo_[satnumIdx].Sgcr + unscaledEpsInfo_[satnumIdx].Swl) - 1 ) > 0) {
|
||||
const std::string msg = "In saturation table SATNUM = " + regionIdx + ", Sogcr + Sgcr + Swco should be less than 1.";
|
||||
OpmLog::warning(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class CartesianIndexMapper>
|
||||
void RelpermDiagnostics::diagnosis(const EclipseState& eclState,
|
||||
const CartesianIndexMapper& cartesianIndexMapper)
|
||||
{
|
||||
OpmLog::info("\n===============Saturation Functions Diagnostics===============\n");
|
||||
bool doDiagnostics = phaseCheck_(eclState);
|
||||
if (!doDiagnostics) // no diagnostics needed for single phase problems
|
||||
return;
|
||||
satFamilyCheck_(eclState);
|
||||
tableCheck_(eclState);
|
||||
unscaledEndPointsCheck_(eclState);
|
||||
scaledEndPointsCheck_(eclState, cartesianIndexMapper);
|
||||
}
|
||||
|
||||
template <class CartesianIndexMapper>
|
||||
void RelpermDiagnostics::scaledEndPointsCheck_(const EclipseState& eclState,
|
||||
const CartesianIndexMapper& cartesianIndexMapper)
|
||||
{
|
||||
// All end points are subject to round-off errors, checks should account for it
|
||||
const float tolerance = 1e-6;
|
||||
const int nc = cartesianIndexMapper.compressedLevelZeroSize();
|
||||
const bool threepoint = eclState.runspec().endpointScaling().threepoint();
|
||||
scaledEpsInfo_.resize(nc);
|
||||
EclEpsGridProperties epsGridProperties(eclState, false);
|
||||
const std::string tag = "Scaled endpoints";
|
||||
for (int c = 0; c < nc; ++c) {
|
||||
const std::string satnumIdx = std::to_string(epsGridProperties.satRegion(c));
|
||||
std::string cellIdx;
|
||||
{
|
||||
std::array<int, 3> ijk;
|
||||
cartesianIndexMapper.cartesianCoordinateLevel(c, ijk, 0);
|
||||
cellIdx = "(" + std::to_string(ijk[0]) + ", " +
|
||||
std::to_string(ijk[1]) + ", " +
|
||||
std::to_string(ijk[2]) + ")";
|
||||
}
|
||||
scaledEpsInfo_[c].extractScaled(eclState, epsGridProperties, c);
|
||||
|
||||
// SGU <= 1.0 - SWL
|
||||
if (scaledEpsInfo_[c].Sgu > (1.0 - scaledEpsInfo_[c].Swl + tolerance)) {
|
||||
const std::string msg = "For scaled endpoints input, cell" + cellIdx + " SATNUM = " + satnumIdx + ", SGU exceed 1.0 - SWL";
|
||||
OpmLog::warning(tag, msg);
|
||||
}
|
||||
|
||||
// SGL <= 1.0 - SWU
|
||||
if (scaledEpsInfo_[c].Sgl > (1.0 - scaledEpsInfo_[c].Swu + tolerance)) {
|
||||
const std::string msg = "For scaled endpoints input, cell" + cellIdx + " SATNUM = " + satnumIdx + ", SGL exceed 1.0 - SWU";
|
||||
OpmLog::warning(tag, msg);
|
||||
}
|
||||
|
||||
if (threepoint && fluidSystem_ == FluidSystem::BlackOil) {
|
||||
// Mobilility check.
|
||||
if ((scaledEpsInfo_[c].Sowcr + scaledEpsInfo_[c].Swcr) >= (1.0 + tolerance)) {
|
||||
const std::string msg = "For scaled endpoints input, cell" + cellIdx + " SATNUM = " + satnumIdx + ", SOWCR + SWCR exceed 1.0";
|
||||
OpmLog::warning(tag, msg);
|
||||
}
|
||||
|
||||
if ((scaledEpsInfo_[c].Sogcr + scaledEpsInfo_[c].Sgcr + scaledEpsInfo_[c].Swl) >= (1.0 + tolerance)) {
|
||||
const std::string msg = "For scaled endpoints input, cell" + cellIdx + " SATNUM = " + satnumIdx + ", SOGCR + SGCR + SWL exceed 1.0";
|
||||
OpmLog::warning(tag, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define INSTANCE_DIAGNOSIS(...) \
|
||||
template void RelpermDiagnostics::diagnosis<Dune::CartesianIndexMapper<__VA_ARGS__>>(const EclipseState&, const Dune::CartesianIndexMapper<__VA_ARGS__>&); \
|
||||
template void RelpermDiagnostics::scaledEndPointsCheck_<Dune::CartesianIndexMapper<__VA_ARGS__>>(const EclipseState&, const Dune::CartesianIndexMapper<__VA_ARGS__>&);
|
||||
|
||||
INSTANCE_DIAGNOSIS(Dune::CpGrid)
|
||||
INSTANCE_DIAGNOSIS(Dune::PolyhedralGrid<3,3>)
|
||||
#if HAVE_DUNE_ALUGRID
|
||||
#if HAVE_MPI
|
||||
INSTANCE_DIAGNOSIS(Dune::ALUGrid<3, 3, Dune::cube, Dune::nonconforming, Dune::ALUGridMPIComm>)
|
||||
#else
|
||||
INSTANCE_DIAGNOSIS(Dune::ALUGrid<3, 3, Dune::cube, Dune::nonconforming, Dune::ALUGridNoComm>)
|
||||
#endif //HAVE_MPI
|
||||
#endif //HAVE_DUNE_ALUGRID
|
||||
} //namespace Opm
|
||||
138
opm/simulators/utils/satfunc/RelpermDiagnostics.hpp
Normal file
138
opm/simulators/utils/satfunc/RelpermDiagnostics.hpp
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OPM_RELPERMDIAGNOSTICS_HEADER_INCLUDED
|
||||
#define OPM_RELPERMDIAGNOSTICS_HEADER_INCLUDED
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
#include <opm/material/fluidmatrixinteractions/EclEpsScalingPoints.hpp>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class EclipseState;
|
||||
class MiscTable;
|
||||
class MsfnTable;
|
||||
class SgcwmisTable;
|
||||
class SgfnTable;
|
||||
class SgofTable;
|
||||
class SgwfnTable;
|
||||
class SlgofTable;
|
||||
class Sof2Table;
|
||||
class Sof3Table;
|
||||
class SorwmisTable;
|
||||
class SsfnTable;
|
||||
class SwfnTable;
|
||||
class SwofTable;
|
||||
class GsfTable;
|
||||
class WsfTable;
|
||||
|
||||
///This class is intend to be a relperm diagnostics, to detect
|
||||
///wrong input of relperm table and endpoints.
|
||||
class RelpermDiagnostics
|
||||
{
|
||||
public:
|
||||
///This function is used to diagnosis relperm in
|
||||
///eclipse data file. Errors and warings will be
|
||||
///output if they're found.
|
||||
///\param[in] eclState eclipse state.
|
||||
///\param[in] grid unstructured grid.
|
||||
template <class CartesianIndexMapper>
|
||||
void diagnosis(const EclipseState& eclState,
|
||||
const CartesianIndexMapper& cartesianIndexMapper);
|
||||
|
||||
private:
|
||||
enum FluidSystem {
|
||||
OilWater,
|
||||
OilGas,
|
||||
WaterGas,
|
||||
BlackOil,
|
||||
Solvent
|
||||
};
|
||||
|
||||
FluidSystem fluidSystem_;
|
||||
|
||||
enum SaturationFunctionFamily {
|
||||
FamilyI,
|
||||
FamilyII,
|
||||
FamilyIII,
|
||||
NoFamily
|
||||
};
|
||||
|
||||
SaturationFunctionFamily satFamily_;
|
||||
|
||||
std::vector<EclEpsScalingPointsInfo<double> > unscaledEpsInfo_;
|
||||
std::vector<EclEpsScalingPointsInfo<double> > scaledEpsInfo_;
|
||||
|
||||
|
||||
///Check the phase that used.
|
||||
/// return false if one-phase system
|
||||
bool phaseCheck_(const EclipseState& es);
|
||||
|
||||
///Check saturation family I and II.
|
||||
void satFamilyCheck_(const EclipseState& eclState);
|
||||
|
||||
///Check saturation tables.
|
||||
void tableCheck_(const EclipseState& eclState);
|
||||
|
||||
///Check endpoints in the saturation tables.
|
||||
void unscaledEndPointsCheck_(const EclipseState& eclState);
|
||||
|
||||
template <class CartesianIndexMapper>
|
||||
void scaledEndPointsCheck_(const EclipseState& eclState,
|
||||
const CartesianIndexMapper& cartesianIndexMapper);
|
||||
|
||||
///For every table, need to deal with case by case.
|
||||
void swofTableCheck_(const SwofTable& swofTables,
|
||||
const int satnumIdx);
|
||||
void sgofTableCheck_(const SgofTable& sgofTables,
|
||||
const int satnumIdx);
|
||||
void slgofTableCheck_(const SlgofTable& slgofTables,
|
||||
const int satnumIdx);
|
||||
void swfnTableCheck_(const SwfnTable& swfnTables,
|
||||
const int satnumIdx);
|
||||
void sgfnTableCheck_(const SgfnTable& sgfnTables,
|
||||
const int satnumIdx);
|
||||
void wsfTableCheck_(const WsfTable& wsfTables,
|
||||
const int satnumIdx);
|
||||
void gsfTableCheck_(const GsfTable& gsfTables,
|
||||
const int satnumIdx);
|
||||
void sof3TableCheck_(const Sof3Table& sof3Tables,
|
||||
const int satnumIdx);
|
||||
void sof2TableCheck_(const Sof2Table& sof2Tables,
|
||||
const int satnumIdx);
|
||||
void sgwfnTableCheck_(const SgwfnTable& sgwfnTables,
|
||||
const int satnumIdx);
|
||||
///Tables for solvent model
|
||||
void sgcwmisTableCheck_(const SgcwmisTable& sgcwmisTables,
|
||||
const int satnumIdx);
|
||||
void sorwmisTableCheck_(const SorwmisTable& sorwmisTables,
|
||||
const int satnumIdx);
|
||||
void ssfnTableCheck_(const SsfnTable& ssfnTables,
|
||||
const int satnumIdx);
|
||||
void miscTableCheck_(const MiscTable& miscTables,
|
||||
const int miscnumIdx);
|
||||
void msfnTableCheck_(const MsfnTable& msfnTables,
|
||||
const int satnumIdx);
|
||||
};
|
||||
|
||||
} //namespace Opm
|
||||
|
||||
#endif // OPM_RELPERMDIAGNOSTICS_HEADER_INCLUDED
|
||||
Reference in New Issue
Block a user