Alternative solvent extension for the black oil model.

This commit is contained in:
Ove Sævareid
2020-10-10 16:20:25 +02:00
parent 09a4a04c22
commit 0f7e66e151
24 changed files with 435 additions and 11 deletions

71
ebos/ebos_extbo.cc Normal file
View File

@@ -0,0 +1,71 @@
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*
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 2 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/>.
Consult the COPYING file in the top-level source directory of this
module for the precise wording of the license and the list of
copyright holders.
*/
/*!
* \file
*
* \brief A general-purpose simulator for ECL decks using the black-oil model.
*/
#include "config.h"
#include "ebos.hh"
#include "startEbos.hh"
namespace Opm::Properties {
namespace TTag {
struct EbosExtboTypeTag {
using InheritsFrom = std::tuple<EbosTypeTag>;
};
}
// enable the polymer extension of the black oil model
template<class TypeTag>
struct EnableExtbo<TypeTag, TTag::EbosExtboTypeTag> {
static constexpr bool value = true;
};
} // namespace Opm::Properties
namespace Opm {
void ebosExtboSetDeck(std::unique_ptr<Opm::Deck> deck,
std::unique_ptr<Opm::ParseContext> parseContext,
std::unique_ptr<Opm::ErrorGuard> errorGuard,
double externalSetupTime)
{
using ProblemTypeTag = Properties::TTag::EbosExtboTypeTag;
using Vanguard = GetPropType<ProblemTypeTag, Properties::Vanguard>;
Vanguard::setExternalSetupTime(externalSetupTime);
Vanguard::setExternalParseContext(std::move(parseContext));
Vanguard::setExternalErrorGuard(std::move(errorGuard));
Vanguard::setExternalDeck(std::move(deck));
}
int ebosExtboMain(int argc, char **argv)
{
using ProblemTypeTag = Properties::TTag::EbosExtboTypeTag;
return Opm::startEbos<ProblemTypeTag>(argc, argv);
}
}

44
ebos/ebos_extbo.hh Normal file
View File

@@ -0,0 +1,44 @@
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*
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 2 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/>.
Consult the COPYING file in the top-level source directory of this
module for the precise wording of the license and the list of
copyright holders.
*/
/*!
* \file
*
* \brief The function prototypes required to start the solvent variant of ebos
*/
#ifndef EBOS_EXTBO_HH
#define EBOS_EXTBO_HH
#include <opm/parser/eclipse/Deck/Deck.hpp>
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
#include <opm/parser/eclipse/Parser/ErrorGuard.hpp>
namespace Opm {
void ebosExtboSetDeck(Opm::Deck* deck,
Opm::ParseContext* parseContext,
Opm::ErrorGuard* errorGuard,
double externalSetupTime);
int ebosExtboMain(int argc, char** argv);
}
#endif

37
ebos/ebos_extbo_main.cc Normal file
View File

@@ -0,0 +1,37 @@
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*
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 2 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/>.
Consult the COPYING file in the top-level source directory of this
module for the precise wording of the license and the list of
copyright holders.
*/
/*!
* \file
*
* \brief The main function for the stand alone solvent variant of ebos.
*
* This only calls the ebosExtboMain() function.
*/
#include "config.h"
#include "ebos_extbo.hh"
int main(int argc, char** argv)
{
return Opm::ebosExtboMain(argc, argv);
}

View File

@@ -111,6 +111,7 @@ class EclTransExtensiveQuantities
enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
enum { numPhases = FluidSystem::numPhases };
enum { enableSolvent = getPropValue<TypeTag, Properties::EnableSolvent>() };
enum { enableExtbo = getPropValue<TypeTag, Properties::EnableExtbo>() };
enum { enableEnergy = getPropValue<TypeTag, Properties::EnableEnergy>() };
typedef Opm::MathToolbox<Evaluation> Toolbox;
@@ -271,7 +272,10 @@ protected:
const Evaluation& pressureInterior = intQuantsIn.fluidState().pressure(phaseIdx);
Evaluation pressureExterior = Toolbox::value(intQuantsEx.fluidState().pressure(phaseIdx));
pressureExterior += rhoAvg*(distZ*g);
if (enableExtbo) //z-dependency ...
pressureExterior += Toolbox::value(rhoAvg)*(distZ*g);
else
pressureExterior += rhoAvg*(distZ*g);
pressureDifference_[phaseIdx] = pressureExterior - pressureInterior;

View File

@@ -396,6 +396,14 @@ public:
cFoam_.resize(bufferSize, 0.0);
if (getPropValue<TypeTag, Properties::EnableBrine>())
cSalt_.resize(bufferSize, 0.0);
if (getPropValue<TypeTag, Properties::EnableExtbo>()) {
extboX_.resize(bufferSize, 0.0);
extboY_.resize(bufferSize, 0.0);
extboZ_.resize(bufferSize, 0.0);
mFracOil_.resize(bufferSize, 0.0);
mFracGas_.resize(bufferSize, 0.0);
mFracCo2_.resize(bufferSize, 0.0);
}
if (simulator_.problem().vapparsActive())
soMax_.resize(bufferSize, 0.0);
@@ -657,6 +665,36 @@ public:
cSalt_[globalDofIdx] = fs.saltConcentration().value();
}
if (extboX_.size() > 0) {
extboX_[globalDofIdx] = intQuants.xvalue().value();
}
if (extboY_.size() > 0) {
extboY_[globalDofIdx] = intQuants.yvalue().value();
}
if (extboZ_.size() > 0) {
extboZ_[globalDofIdx] = intQuants.zFraction().value();
}
if (mFracCo2_.size() > 0) {
const Scalar stdVolOil = Opm::getValue(fs.saturation(oilPhaseIdx))*Opm::getValue(fs.invB(oilPhaseIdx))
+ Opm::getValue(fs.saturation(gasPhaseIdx))*Opm::getValue(fs.invB(gasPhaseIdx))*Opm::getValue(fs.Rv());
const Scalar stdVolGas = Opm::getValue(fs.saturation(gasPhaseIdx))*Opm::getValue(fs.invB(gasPhaseIdx))*(1.0-intQuants.yvalue().value())
+ Opm::getValue(fs.saturation(oilPhaseIdx))*Opm::getValue(fs.invB(oilPhaseIdx))*Opm::getValue(fs.Rs())*(1.0-intQuants.xvalue().value());
const Scalar stdVolCo2 = Opm::getValue(fs.saturation(gasPhaseIdx))*Opm::getValue(fs.invB(gasPhaseIdx))*intQuants.yvalue().value()
+ Opm::getValue(fs.saturation(oilPhaseIdx))*Opm::getValue(fs.invB(oilPhaseIdx))*Opm::getValue(fs.Rs())*intQuants.xvalue().value();
const Scalar rhoO= 836.19;
const Scalar rhoG= 1.2984;
const Scalar rhoCO2=1.8727048125;
const Scalar stdMassTotal= 1.0e-10 + stdVolOil*rhoO + stdVolGas*rhoG + stdVolCo2*rhoCO2;
mFracOil_[globalDofIdx] = stdVolOil*rhoO/stdMassTotal;
mFracGas_[globalDofIdx] = stdVolGas*rhoG/stdMassTotal;
mFracCo2_[globalDofIdx] = stdVolCo2*rhoCO2/stdMassTotal;
}
if (bubblePointPressure_.size() > 0) {
try {
bubblePointPressure_[globalDofIdx] = Opm::getValue(FluidSystem::bubblePointPressure(fs, intQuants.pvtRegionIndex()));
@@ -1045,6 +1083,24 @@ public:
if (sSol_.size() > 0)
sol.insert ("SSOLVENT", Opm::UnitSystem::measure::identity, std::move(sSol_), Opm::data::TargetType::RESTART_SOLUTION);
if (extboX_.size() > 0)
sol.insert ("SS_X", Opm::UnitSystem::measure::identity, std::move(extboX_), Opm::data::TargetType::RESTART_AUXILIARY);
if (extboY_.size() > 0)
sol.insert ("SS_Y", Opm::UnitSystem::measure::identity, std::move(extboY_), Opm::data::TargetType::RESTART_AUXILIARY);
if (extboZ_.size() > 0)
sol.insert ("SS_Z", Opm::UnitSystem::measure::identity, std::move(extboZ_), Opm::data::TargetType::RESTART_AUXILIARY);
if (mFracOil_.size() > 0)
sol.insert ("STD_OIL", Opm::UnitSystem::measure::identity, std::move(mFracOil_), Opm::data::TargetType::RESTART_AUXILIARY);
if (mFracGas_.size() > 0)
sol.insert ("STD_GAS", Opm::UnitSystem::measure::identity, std::move(mFracGas_), Opm::data::TargetType::RESTART_AUXILIARY);
if (mFracCo2_.size() > 0)
sol.insert ("STD_CO2", Opm::UnitSystem::measure::identity, std::move(mFracCo2_), Opm::data::TargetType::RESTART_AUXILIARY);
if (cPolymer_.size() > 0)
sol.insert ("POLYMER", Opm::UnitSystem::measure::identity, std::move(cPolymer_), Opm::data::TargetType::RESTART_SOLUTION);
@@ -2290,6 +2346,12 @@ private:
ScalarBuffer viscosity_[numPhases];
ScalarBuffer relativePermeability_[numPhases];
ScalarBuffer sSol_;
ScalarBuffer extboX_;
ScalarBuffer extboY_;
ScalarBuffer extboZ_;
ScalarBuffer mFracOil_;
ScalarBuffer mFracGas_;
ScalarBuffer mFracCo2_;
ScalarBuffer cPolymer_;
ScalarBuffer cFoam_;
ScalarBuffer cSalt_;

View File

@@ -534,6 +534,10 @@ template<class TypeTag>
struct EnableFoam<TypeTag, TTag::EclBaseProblem> {
static constexpr bool value = false;
};
template<class TypeTag>
struct EnableExtbo<TypeTag, TTag::EclBaseProblem> {
static constexpr bool value = false;
};
// disable thermal flux boundaries by default
template<class TypeTag>
@@ -613,6 +617,7 @@ class EclProblem : public GetPropType<TypeTag, Properties::BaseProblem>
enum { enableBrine = getPropValue<TypeTag, Properties::EnableBrine>() };
enum { enablePolymerMolarWeight = getPropValue<TypeTag, Properties::EnablePolymerMW>() };
enum { enableFoam = getPropValue<TypeTag, Properties::EnableFoam>() };
enum { enableExtbo = getPropValue<TypeTag, Properties::EnableExtbo>() };
enum { enableTemperature = getPropValue<TypeTag, Properties::EnableTemperature>() };
enum { enableEnergy = getPropValue<TypeTag, Properties::EnableEnergy>() };
enum { enableThermalFluxBoundaries = getPropValue<TypeTag, Properties::EnableThermalFluxBoundaries>() };
@@ -647,6 +652,7 @@ class EclProblem : public GetPropType<TypeTag, Properties::BaseProblem>
typedef BlackOilPolymerModule<TypeTag> PolymerModule;
typedef BlackOilFoamModule<TypeTag> FoamModule;
typedef BlackOilBrineModule<TypeTag> BrineModule;
typedef BlackOilExtboModule<TypeTag> ExtboModule;
typedef typename EclEquilInitializer<TypeTag>::ScalarFluidState InitialFluidState;
@@ -812,6 +818,7 @@ public:
PolymerModule::initFromState(vanguard.eclState());
FoamModule::initFromState(vanguard.eclState());
BrineModule::initFromState(vanguard.eclState());
ExtboModule::initFromState(vanguard.eclState());
// create the ECL writer
eclWriter_.reset(new EclWriterType(simulator));
@@ -2176,6 +2183,11 @@ private:
else if (!enablePolymer && deck.hasKeyword("POLYMER"))
throw std::runtime_error("The deck enables the polymer option, but the simulator is compiled without it.");
if (enableExtbo && !deck.hasKeyword("PVTSOL"))
throw std::runtime_error("The simulator requires the extendedBO option to be enabled, but the deck does not.");
else if (!enableExtbo && deck.hasKeyword("PVTSOL"))
throw std::runtime_error("The deck enables the extendedBO option, but the simulator is compiled without it.");
if (deck.hasKeyword("TEMP") && deck.hasKeyword("THERMAL"))
throw std::runtime_error("The deck enables both, the TEMP and the THERMAL options, but they are mutually exclusive.");