Merge pull request #2051 from atgeirr/enable-onephase-revised-rebased

Enable onephase
This commit is contained in:
Atgeirr Flø Rasmussen 2019-10-11 21:02:46 +02:00 committed by GitHub
commit 4ddb8e8d56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 699 additions and 209 deletions

View File

@ -19,6 +19,7 @@ cmake_minimum_required (VERSION 2.8)
option(SIBLING_SEARCH "Search for other modules in sibling directories?" ON) option(SIBLING_SEARCH "Search for other modules in sibling directories?" ON)
set( USE_OPENMP_DEFAULT OFF ) # Use of OpenMP is considered experimental set( USE_OPENMP_DEFAULT OFF ) # Use of OpenMP is considered experimental
option(BUILD_FLOW "Build the production oriented flow simulator?" ON) option(BUILD_FLOW "Build the production oriented flow simulator?" ON)
option(BUILD_FLOW_VARIANTS "Build the variants for flow by default?" OFF)
option(BUILD_EBOS "Build the research oriented ebos simulator?" ON) option(BUILD_EBOS "Build the research oriented ebos simulator?" ON)
option(BUILD_EBOS_EXTENSIONS "Build the variants for various extensions of ebos by default?" OFF) option(BUILD_EBOS_EXTENSIONS "Build the variants for various extensions of ebos by default?" OFF)
option(BUILD_EBOS_DEBUG_EXTENSIONS "Build the ebos variants which are purely for debugging by default?" OFF) option(BUILD_EBOS_DEBUG_EXTENSIONS "Build the ebos variants which are purely for debugging by default?" OFF)
@ -155,15 +156,36 @@ opm_add_test(flow
flow/flow_ebos_oilwater_polymer.cpp flow/flow_ebos_oilwater_polymer.cpp
flow/flow_ebos_oilwater_polymer_injectivity.cpp) flow/flow_ebos_oilwater_polymer_injectivity.cpp)
if (NOT BUILD_FLOW_VARIANTS)
set(FLOW_VARIANTS_DEFAULT_ENABLE_IF "FALSE")
else()
set(FLOW_VARIANTS_DEFAULT_ENABLE_IF "TRUE")
endif()
# Variant versions of Flow.
opm_add_test(flow_blackoil_dunecpr opm_add_test(flow_blackoil_dunecpr
ONLY_COMPILE ONLY_COMPILE
DEFAULT_ENABLE_IF ${FLOW_DEFAULT_ENABLE_IF} DEFAULT_ENABLE_IF ${FLOW_VARIANTS_DEFAULT_ENABLE_IF}
SOURCES flow/flow_blackoil_dunecpr.cpp SOURCES flow/flow_blackoil_dunecpr.cpp
EXE_NAME flow_blackoil_dunecpr EXE_NAME flow_blackoil_dunecpr
DEPENDS "opmsimulators" DEPENDS "opmsimulators"
LIBRARIES "opmsimulators") LIBRARIES "opmsimulators")
opm_add_test(flow_onephase
ONLY_COMPILE
DEFAULT_ENABLE_IF ${FLOW_VARIANTS_DEFAULT_ENABLE_IF}
SOURCES flow/flow_onephase.cpp
EXE_NAME flow_onephase
DEPENDS "opmsimulators"
LIBRARIES "opmsimulators")
opm_add_test(flow_onephase_energy
ONLY_COMPILE
DEFAULT_ENABLE_IF ${FLOW_VARIANTS_DEFAULT_ENABLE_IF}
SOURCES flow/flow_onephase_energy.cpp
EXE_NAME flow_onephase_energy
DEPENDS "opmsimulators"
LIBRARIES "opmsimulators")
if (BUILD_FLOW) if (BUILD_FLOW)
install(TARGETS flow DESTINATION bin) install(TARGETS flow DESTINATION bin)

View File

@ -395,7 +395,16 @@ public:
} }
if (oilPressure_.size() > 0) { if (oilPressure_.size() > 0) {
oilPressure_[globalDofIdx] = Opm::getValue(fs.pressure(oilPhaseIdx)); if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
oilPressure_[globalDofIdx] = Opm::getValue(fs.pressure(oilPhaseIdx));
}else{
// put pressure in oil pressure for output
if (FluidSystem::phaseIsActive(waterPhaseIdx)) {
oilPressure_[globalDofIdx] = Opm::getValue(fs.pressure(waterPhaseIdx));
} else {
oilPressure_[globalDofIdx] = Opm::getValue(fs.pressure(gasPhaseIdx));
}
}
Opm::Valgrind::CheckDefined(oilPressure_[globalDofIdx]); Opm::Valgrind::CheckDefined(oilPressure_[globalDofIdx]);
} }

View File

@ -665,17 +665,20 @@ public:
minTimeStepSize_ = tuning.getTSMINZ(0); minTimeStepSize_ = tuning.getTSMINZ(0);
} }
initFluidSystem_();
// deal with DRSDT // deal with DRSDT
unsigned ntpvt = eclState.runspec().tabdims().getNumPVTTables(); unsigned ntpvt = eclState.runspec().tabdims().getNumPVTTables();
maxDRs_.resize(ntpvt, 1e30);
dRsDtOnlyFreeGas_.resize(ntpvt, false);
size_t numDof = this->model().numGridDof(); size_t numDof = this->model().numGridDof();
lastRs_.resize(numDof, 0.0); if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
maxDRv_.resize(ntpvt, 1e30); maxDRs_.resize(ntpvt, 1e30);
lastRv_.resize(numDof, 0.0); dRsDtOnlyFreeGas_.resize(ntpvt, false);
maxOilSaturation_.resize(numDof, 0.0); lastRs_.resize(numDof, 0.0);
maxDRv_.resize(ntpvt, 1e30);
lastRv_.resize(numDof, 0.0);
maxOilSaturation_.resize(numDof, 0.0);
}
initFluidSystem_();
updateElementDepths_(); updateElementDepths_();
readRockParameters_(); readRockParameters_();
readMaterialParameters_(); readMaterialParameters_();

View File

@ -43,7 +43,7 @@ SET_PROP(EclFlowProblemSimple, FluidState)
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
typedef typename GET_PROP_TYPE(TypeTag, Evaluation) Evaluation; typedef typename GET_PROP_TYPE(TypeTag, Evaluation) Evaluation;
static const bool compositionSwitchEnabled = Indices::gasEnabled; static const bool compositionSwitchEnabled = Indices::gasEnabled;
public: public:
//typedef Opm::BlackOilFluidSystemSimple<Scalar> type; //typedef Opm::BlackOilFluidSystemSimple<Scalar> type;
typedef Opm::BlackOilFluidState<Evaluation, FluidSystem, enableTemperature, enableEnergy, compositionSwitchEnabled, Indices::numPhases > type; typedef Opm::BlackOilFluidState<Evaluation, FluidSystem, enableTemperature, enableEnergy, compositionSwitchEnabled, Indices::numPhases > type;
@ -89,7 +89,7 @@ namespace Opm {
#endif #endif
SET_BOOL_PROP(EclFlowProblemSimple, EnableStorageCache, true); SET_BOOL_PROP(EclFlowProblemSimple, EnableStorageCache, true);
SET_BOOL_PROP(EclFlowProblemSimple, EnableIntensiveQuantityCache, true); SET_BOOL_PROP(EclFlowProblemSimple, EnableIntensiveQuantityCache, true);
//SET_INT_PROP(EclFlowProblemSimple, NumWellAdjoint, 1); //SET_INT_PROP(EclFlowProblemSimple, NumWellAdjoint, 1);
//SET_BOOL_PROP(EclFlowProblem, EnableStorageCache, true); //SET_BOOL_PROP(EclFlowProblem, EnableStorageCache, true);
//SET_BOOL_PROP(EclFlowProblem, EnableIntensiveQuantityCache, true); //SET_BOOL_PROP(EclFlowProblem, EnableIntensiveQuantityCache, true);
@ -98,8 +98,6 @@ namespace Opm {
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
typedef TTAG(EclFlowProblemSimple) TypeTag; typedef TTAG(EclFlowProblemSimple) TypeTag;
bool outputCout = true; return mainFlow<TypeTag>(argc, argv);
bool outputFiles = true;
return mainFlow<TypeTag>(argc, argv, outputCout, outputFiles);
} }

91
flow/flow_onephase.cpp Normal file
View File

@ -0,0 +1,91 @@
/*
Copyright 2013, 2014, 2015 SINTEF ICT, Applied Mathematics.
Copyright 2014 Dr. Blatt - HPC-Simulation-Software & Services
Copyright 2015, 2017 IRIS AS
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/>.
*/
#include "config.h"
#include "flow/flow_tag.hpp"
#include <opm/models/blackoil/blackoilonephaseindices.hh>
BEGIN_PROPERTIES
NEW_TYPE_TAG(EclFlowProblemSimple, INHERITS_FROM(EclFlowProblem));
NEW_PROP_TAG(FluidState);
NEW_PROP_TAG(FluidSystem);
//! The indices required by the model
SET_PROP(EclFlowProblemSimple, Indices)
{
private:
// it is unfortunately not possible to simply use 'TypeTag' here because this leads
// to cyclic definitions of some properties. if this happens the compiler error
// messages unfortunately are *really* confusing and not really helpful.
typedef TTAG(EclFlowProblem) BaseTypeTag;
typedef typename GET_PROP_TYPE(BaseTypeTag, FluidSystem) FluidSystem;
public:
typedef Ewoms::BlackOilOnePhaseIndices<GET_PROP_VALUE(TypeTag, EnableSolvent),
GET_PROP_VALUE(TypeTag, EnablePolymer),
GET_PROP_VALUE(TypeTag, EnableEnergy),
GET_PROP_VALUE(TypeTag, EnableFoam),
/*PVOffset=*/0,
/*enebledCompIdx=*/FluidSystem::waterCompIdx>
type;
};
SET_PROP(EclFlowProblemSimple, FluidState)
{
private:
typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
enum { enableTemperature = GET_PROP_VALUE(TypeTag, EnableTemperature) };
enum { enableSolvent = GET_PROP_VALUE(TypeTag, EnableSolvent) };
enum { enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy) };
enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) };
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
typedef typename GET_PROP_TYPE(TypeTag, Evaluation) Evaluation;
static const bool compositionSwitchEnabled = Indices::gasEnabled;
public:
// typedef Opm::BlackOilFluidSystemSimple<Scalar> type;
typedef Opm::BlackOilFluidState<Evaluation,
FluidSystem,
enableTemperature,
enableEnergy,
compositionSwitchEnabled,
Indices::numPhases>
type;
};
// SET_PROP(EclFlowProblemSimple, FluidSystem)
// {
// private:
// //typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
// typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
// typedef typename GET_PROP_TYPE(TypeTag, Evaluation) Evaluation;
// typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
// public:
// typedef Opm::BlackOilFluidSystem<Scalar,Indices> type;
// };
END_PROPERTIES
int
main(int argc, char** argv)
{
typedef TTAG(EclFlowProblemSimple) TypeTag;
return mainFlow<TypeTag>(argc, argv);
}

View File

@ -0,0 +1,93 @@
/*
Copyright 2013, 2014, 2015 SINTEF ICT, Applied Mathematics.
Copyright 2014 Dr. Blatt - HPC-Simulation-Software & Services
Copyright 2015, 2017 IRIS AS
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/>.
*/
#include "config.h"
#include "flow/flow_tag.hpp"
#include <opm/models/blackoil/blackoilonephaseindices.hh>
BEGIN_PROPERTIES
NEW_TYPE_TAG(EclFlowProblemSimple, INHERITS_FROM(EclFlowProblem));
SET_BOOL_PROP(EclFlowProblemSimple, EnableEnergy, true);
NEW_PROP_TAG(FluidState);
NEW_PROP_TAG(FluidSystem);
//! The indices required by the model
SET_PROP(EclFlowProblemSimple, Indices)
{
private:
// it is unfortunately not possible to simply use 'TypeTag' here because this leads
// to cyclic definitions of some properties. if this happens the compiler error
// messages unfortunately are *really* confusing and not really helpful.
typedef TTAG(EclFlowProblem) BaseTypeTag;
typedef typename GET_PROP_TYPE(BaseTypeTag, FluidSystem) FluidSystem;
public:
typedef Ewoms::BlackOilOnePhaseIndices<GET_PROP_VALUE(TypeTag, EnableSolvent),
GET_PROP_VALUE(TypeTag, EnablePolymer),
GET_PROP_VALUE(TypeTag, EnableEnergy),
GET_PROP_VALUE(TypeTag, EnableFoam),
/*PVOffset=*/0,
/*enebledCompIdx=*/FluidSystem::waterCompIdx>
type;
};
SET_PROP(EclFlowProblemSimple, FluidState)
{
private:
typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
enum { enableTemperature = GET_PROP_VALUE(TypeTag, EnableTemperature) };
enum { enableSolvent = GET_PROP_VALUE(TypeTag, EnableSolvent) };
enum { enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy) };
enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) };
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
typedef typename GET_PROP_TYPE(TypeTag, Evaluation) Evaluation;
static const bool compositionSwitchEnabled = Indices::gasEnabled;
public:
// typedef Opm::BlackOilFluidSystemSimple<Scalar> type;
typedef Opm::BlackOilFluidState<Evaluation,
FluidSystem,
enableTemperature,
enableEnergy,
compositionSwitchEnabled,
Indices::numPhases>
type;
};
// SET_PROP(EclFlowProblemSimple, FluidSystem)
// {
// private:
// //typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
// typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
// typedef typename GET_PROP_TYPE(TypeTag, Evaluation) Evaluation;
// typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
// public:
// typedef Opm::BlackOilFluidSystem<Scalar,Indices> type;
// };
END_PROPERTIES
int
main(int argc, char** argv)
{
typedef TTAG(EclFlowProblemSimple) TypeTag;
return mainFlow<TypeTag>(argc, argv);
}

View File

@ -29,13 +29,18 @@
#include <opm/common/utility/parameters/ParameterGroup.hpp> #include <opm/common/utility/parameters/ParameterGroup.hpp>
#include <opm/material/common/ResetLocale.hpp> #include <opm/material/common/ResetLocale.hpp>
#include <opm/common/OpmLog/OpmLog.hpp>
#include <opm/common/OpmLog/EclipsePRTLog.hpp>
#include <opm/common/OpmLog/LogUtil.hpp>
#include <opm/parser/eclipse/Deck/Deck.hpp> #include <opm/parser/eclipse/Deck/Deck.hpp>
#include <opm/parser/eclipse/Parser/Parser.hpp> #include <opm/parser/eclipse/Parser/Parser.hpp>
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp> #include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
#include <opm/parser/eclipse/EclipseState/checkDeck.hpp> #include <opm/parser/eclipse/EclipseState/checkDeck.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/ArrayDimChecker.hpp>
//#include <opm/material/fluidsystems/BlackOilFluidSystemSimple.hpp> //#include <opm/material/fluidsystems/BlackOilFluidSystemSimple.hpp>
//#include <opm/material/fluidsystems/BlackOilFluidSystemSimple.hpp> //#include <opm/material/fluidsystems/BlackOilFluidSystemSimple.hpp>
#include <opm/models/blackoil/blackoilintensivequantities.hh> #include <opm/models/blackoil/blackoilintensivequantities.hh>
#include <opm/material/fluidstates/BlackOilFluidState.hpp> #include <opm/material/fluidstates/BlackOilFluidState.hpp>
//#include <opm/material/fluidstates/BlackOilFluidStateSimple.hpp> //#include <opm/material/fluidstates/BlackOilFluidStateSimple.hpp>
@ -66,7 +71,7 @@ namespace Opm {
Vanguard::setExternalDeck(&deck); Vanguard::setExternalDeck(&deck);
Vanguard::setExternalEclState(&eclState); Vanguard::setExternalEclState(&eclState);
} }
// ----------------- Main program ----------------- // ----------------- Main program -----------------
template <class TypeTag> template <class TypeTag>
int flowEbosMain(int argc, char** argv, bool outputCout, bool outputFiles) int flowEbosMain(int argc, char** argv, bool outputCout, bool outputFiles)
@ -74,7 +79,7 @@ namespace Opm {
// we always want to use the default locale, and thus spare us the trouble // we always want to use the default locale, and thus spare us the trouble
// with incorrect locale settings. // with incorrect locale settings.
Opm::resetLocale(); Opm::resetLocale();
#if HAVE_DUNE_FEM #if HAVE_DUNE_FEM
Dune::Fem::MPIManager::initialize(argc, argv); Dune::Fem::MPIManager::initialize(argc, argv);
#else #else
@ -118,13 +123,162 @@ namespace detail
throw std::invalid_argument( "Cannot find input case " + casename ); throw std::invalid_argument( "Cannot find input case " + casename );
} }
// This function is an extreme special case, if the program has been invoked
// *exactly* as:
//
// flow --version
//
// the call is intercepted by this function which will print "flow $version"
// on stdout and exit(0).
void handleVersionCmdLine(int argc, char** argv) {
for ( int i = 1; i < argc; ++i )
{
if (std::strcmp(argv[i], "--version") == 0) {
std::cout << "flow " << Opm::moduleVersionName() << std::endl;
std::exit(EXIT_SUCCESS);
}
}
}
}
enum class FileOutputMode {
//! \brief No output to files.
OUTPUT_NONE = 0,
//! \brief Output only to log files, no eclipse output.
OUTPUT_LOG_ONLY = 1,
//! \brief Output to all files.
OUTPUT_ALL = 3
};
void ensureOutputDirExists(const std::string& cmdline_output_dir)
{
if (!boost::filesystem::is_directory(cmdline_output_dir)) {
try {
boost::filesystem::create_directories(cmdline_output_dir);
}
catch (...) {
throw std::runtime_error("Creation of output directory '" + cmdline_output_dir + "' failed\n");
}
}
}
// Setup the OpmLog backends
FileOutputMode setupLogging(int mpi_rank_, const std::string& deck_filename, const std::string& cmdline_output_dir, const std::string& cmdline_output, bool output_cout_, const std::string& stdout_log_id) {
if (!cmdline_output_dir.empty()) {
ensureOutputDirExists(cmdline_output_dir);
}
// create logFile
using boost::filesystem::path;
path fpath(deck_filename);
std::string baseName;
std::ostringstream debugFileStream;
std::ostringstream logFileStream;
// Strip extension "." or ".DATA"
std::string extension = boost::to_upper_copy(fpath.extension().string());
if (extension == ".DATA" || extension == ".") {
baseName = boost::to_upper_copy(fpath.stem().string());
} else {
baseName = boost::to_upper_copy(fpath.filename().string());
}
std::string output_dir = cmdline_output_dir;
if (output_dir.empty()) {
output_dir = absolute(path(baseName).parent_path()).string();
}
logFileStream << output_dir << "/" << baseName;
debugFileStream << output_dir << "/" << baseName;
if (mpi_rank_ != 0) {
// Added rank to log file for non-zero ranks.
// This prevents message loss.
debugFileStream << "." << mpi_rank_;
// If the following file appears then there is a bug.
logFileStream << "." << mpi_rank_;
}
logFileStream << ".PRT";
debugFileStream << ".DBG";
FileOutputMode output;
{
static std::map<std::string, FileOutputMode> stringToOutputMode =
{ {"none", FileOutputMode::OUTPUT_NONE },
{"false", FileOutputMode::OUTPUT_LOG_ONLY },
{"log", FileOutputMode::OUTPUT_LOG_ONLY },
{"all" , FileOutputMode::OUTPUT_ALL },
{"true" , FileOutputMode::OUTPUT_ALL }};
auto outputModeIt = stringToOutputMode.find(cmdline_output);
if (outputModeIt != stringToOutputMode.end()) {
output = outputModeIt->second;
}
else {
output = FileOutputMode::OUTPUT_ALL;
std::cerr << "Value " << cmdline_output <<
" is not a recognized output mode. Using \"all\" instead."
<< std::endl;
}
}
if (output > FileOutputMode::OUTPUT_NONE) {
std::shared_ptr<Opm::EclipsePRTLog> prtLog = std::make_shared<Opm::EclipsePRTLog>(logFileStream.str(), Opm::Log::NoDebugMessageTypes, false, output_cout_);
Opm::OpmLog::addBackend("ECLIPSEPRTLOG", prtLog);
prtLog->setMessageLimiter(std::make_shared<Opm::MessageLimiter>());
prtLog->setMessageFormatter(std::make_shared<Opm::SimpleMessageFormatter>(false));
}
if (output >= FileOutputMode::OUTPUT_LOG_ONLY) {
std::string debugFile = debugFileStream.str();
std::shared_ptr<Opm::StreamLog> debugLog = std::make_shared<Opm::EclipsePRTLog>(debugFileStream.str(), Opm::Log::DefaultMessageTypes, false, output_cout_);
Opm::OpmLog::addBackend("DEBUGLOG", debugLog);
}
std::shared_ptr<Opm::StreamLog> streamLog = std::make_shared<Opm::StreamLog>(std::cout, Opm::Log::StdoutMessageTypes);
Opm::OpmLog::addBackend(stdout_log_id, streamLog);
streamLog->setMessageFormatter(std::make_shared<Opm::SimpleMessageFormatter>(true));
return output;
}
void setupMessageLimiter(const Opm::MessageLimits msgLimits, const std::string& stdout_log_id) {
std::shared_ptr<Opm::StreamLog> stream_log = Opm::OpmLog::getBackend<Opm::StreamLog>(stdout_log_id);
const std::map<int64_t, int> limits = {{Opm::Log::MessageType::Note,
msgLimits.getCommentPrintLimit(0)},
{Opm::Log::MessageType::Info,
msgLimits.getMessagePrintLimit(0)},
{Opm::Log::MessageType::Warning,
msgLimits.getWarningPrintLimit(0)},
{Opm::Log::MessageType::Error,
msgLimits.getErrorPrintLimit(0)},
{Opm::Log::MessageType::Problem,
msgLimits.getProblemPrintLimit(0)},
{Opm::Log::MessageType::Bug,
msgLimits.getBugPrintLimit(0)}};
stream_log->setMessageLimiter(std::make_shared<Opm::MessageLimiter>(10, limits));
} }
// ----------------- Main program ----------------- // ----------------- Main program -----------------
template<class TypeTag> template<class TypeTag>
int mainFlow(int argc, char** argv, bool outputCout, bool outputFiles) int mainFlow(int argc, char** argv)
{ {
Dune::Timer externalSetupTimer;
externalSetupTimer.start();
detail::handleVersionCmdLine(argc, argv);
// MPI setup. // MPI setup.
#if HAVE_DUNE_FEM #if HAVE_DUNE_FEM
Dune::Fem::MPIManager::initialize(argc, argv); Dune::Fem::MPIManager::initialize(argc, argv);
@ -151,15 +305,21 @@ int mainFlow(int argc, char** argv, bool outputCout, bool outputFiles)
typedef TTAG(FlowEarlyBird) PreTypeTag; typedef TTAG(FlowEarlyBird) PreTypeTag;
typedef GET_PROP_TYPE(PreTypeTag, Problem) PreProblem; typedef GET_PROP_TYPE(PreTypeTag, Problem) PreProblem;
PreProblem::setBriefDescription("Simple Flow, an advanced reservoir simulator for ECL-decks provided by the Open Porous Media project."); PreProblem::setBriefDescription("Flow, an advanced reservoir simulator for ECL-decks provided by the Open Porous Media project.");
int status = Opm::FlowMainEbos<PreTypeTag>::setupParameters_(argc, argv); int status = Opm::FlowMainEbos<PreTypeTag>::setupParameters_(argc, argv);
if (status != 0) if (status != 0) {
// if setupParameters_ returns a value smaller than 0, there was no error, but // if setupParameters_ returns a value smaller than 0, there was no error, but
// the program should abort. This is the case e.g. for the --help and the // the program should abort. This is the case e.g. for the --help and the
// --print-properties parameters. // --print-properties parameters.
#if HAVE_MPI
MPI_Finalize();
#endif
return (status >= 0)?status:0; return (status >= 0)?status:0;
}
FileOutputMode outputMode = FileOutputMode::OUTPUT_NONE;
bool outputCout = false;
if (mpiRank == 0) if (mpiRank == 0)
outputCout = EWOMS_GET_PARAM(PreTypeTag, bool, EnableTerminalOutput); outputCout = EWOMS_GET_PARAM(PreTypeTag, bool, EnableTerminalOutput);
@ -176,38 +336,67 @@ int mainFlow(int argc, char** argv, bool outputCout, bool outputFiles)
// Create Deck and EclipseState. // Create Deck and EclipseState.
try { try {
Opm::Parser parser; if (outputCout) {
typedef std::pair<std::string, Opm::InputError::Action> ParseModePair; std::cout << "Reading deck file '" << deckFilename << "'\n";
typedef std::vector<ParseModePair> ParseModePairs; std::cout.flush();
ParseModePairs tmp; }
tmp.push_back(ParseModePair(Opm::ParseContext::PARSE_RANDOM_SLASH, Opm::InputError::IGNORE)); std::shared_ptr<Opm::Deck> deck;
tmp.push_back(ParseModePair(Opm::ParseContext::PARSE_MISSING_DIMS_KEYWORD, Opm::InputError::WARN)); std::shared_ptr<Opm::EclipseState> eclipseState;
tmp.push_back(ParseModePair(Opm::ParseContext::SUMMARY_UNKNOWN_WELL, Opm::InputError::WARN)); std::shared_ptr<Opm::Schedule> schedule;
tmp.push_back(ParseModePair(Opm::ParseContext::SUMMARY_UNKNOWN_GROUP, Opm::InputError::WARN)); std::shared_ptr<Opm::SummaryConfig> summaryConfig;
Opm::ParseContext parseContext(tmp); {
Opm::ErrorGuard errorGuard; Opm::Parser parser;
Opm::ParseContext parseContext;
Opm::ErrorGuard errorGuard;
outputMode = setupLogging(mpiRank,
deckFilename,
EWOMS_GET_PARAM(PreTypeTag, std::string, OutputDir),
EWOMS_GET_PARAM(PreTypeTag, std::string, OutputMode),
outputCout, "STDOUT_LOGGER");
std::shared_ptr<Opm::Deck> deck = std::make_shared< Opm::Deck >( parser.parseFile(deckFilename , parseContext, errorGuard) ); if (EWOMS_GET_PARAM(PreTypeTag, bool, EclStrictParsing))
if ( outputCout ) { parseContext.update( Opm::InputError::DELAYED_EXIT1);
Opm::checkDeck(*deck, parser, parseContext, errorGuard); else {
Opm::MissingFeatures::checkKeywords(*deck); parseContext.update(Opm::ParseContext::PARSE_RANDOM_SLASH, Opm::InputError::IGNORE);
} parseContext.update(Opm::ParseContext::PARSE_MISSING_DIMS_KEYWORD, Opm::InputError::WARN);
//Opm::Runspec runspec( *deck ); parseContext.update(Opm::ParseContext::SUMMARY_UNKNOWN_WELL, Opm::InputError::WARN);
//const auto& phases = runspec.phases(); parseContext.update(Opm::ParseContext::SUMMARY_UNKNOWN_GROUP, Opm::InputError::WARN);
}
std::shared_ptr<Opm::EclipseState> eclipseState = std::make_shared< Opm::EclipseState > ( *deck, parseContext, errorGuard ); Opm::FlowMainEbos<PreTypeTag>::printPRTHeader(outputCout);
Opm::flowEbosSetDeck<TypeTag>(*deck, *eclipseState);
return Opm::flowEbosMain<TypeTag>(argc, argv, outputCout, outputFiles); deck.reset( new Opm::Deck( parser.parseFile(deckFilename , parseContext, errorGuard)));
Opm::MissingFeatures::checkKeywords(*deck, parseContext, errorGuard);
if ( outputCout )
Opm::checkDeck(*deck, parser, parseContext, errorGuard);
eclipseState.reset( new Opm::EclipseState(*deck, parseContext, errorGuard ));
schedule.reset(new Opm::Schedule(*deck, *eclipseState, parseContext, errorGuard));
summaryConfig.reset( new Opm::SummaryConfig(*deck, *schedule, eclipseState->getTableManager(), parseContext, errorGuard));
setupMessageLimiter(schedule->getMessageLimits(), "STDOUT_LOGGER");
Opm::checkConsistentArrayDimensions(*eclipseState, *schedule, parseContext, errorGuard);
if (errorGuard) {
errorGuard.dump();
errorGuard.clear();
throw std::runtime_error("Unrecoverable errors were encountered while loading input.");
}
}
bool outputFiles = (outputMode != FileOutputMode::OUTPUT_NONE);
Opm::flowEbosSetDeck<TypeTag>(*deck, *eclipseState);
return Opm::flowEbosMain<TypeTag>(argc, argv, outputCout, outputFiles);
} }
catch (const std::invalid_argument& e) catch (const std::invalid_argument& e)
{ {
if (outputCout) { if (outputCout) {
std::cerr << "Failed to create valid EclipseState object." << std::endl; std::cerr << "Failed to create valid EclipseState object." << std::endl;
std::cerr << "Exception caught: " << e.what() << std::endl; std::cerr << "Exception caught: " << e.what() << std::endl;
} }
throw; throw;
} }
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
#endif #endif

View File

@ -54,14 +54,9 @@ namespace Opm
} }
} }
// Only 2 or 3 phase systems handled.
if (pu.num_phases < 2 || pu.num_phases > 3) {
OPM_THROW(std::runtime_error, "Cannot handle cases with " << pu.num_phases << " phases.");
}
// We need oil systems, since we do not support the keywords needed for // We need oil systems, since we do not support the keywords needed for
// water-gas systems. // water-gas systems.
if (!pu.phase_used[BlackoilPhases::Liquid]) { if (!pu.phase_used[BlackoilPhases::Liquid] && !(pu.num_phases == 1)) {
OPM_THROW(std::runtime_error, "Cannot handle cases with no OIL, i.e. water-gas systems."); OPM_THROW(std::runtime_error, "Cannot handle cases with no OIL, i.e. water-gas systems.");
} }

View File

@ -422,28 +422,35 @@ namespace Opm {
Scalar saturationsOld[FluidSystem::numPhases] = { 0.0 }; Scalar saturationsOld[FluidSystem::numPhases] = { 0.0 };
Scalar oilSaturationOld = 1.0; Scalar oilSaturationOld = 1.0;
if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
saturationsOld[FluidSystem::waterPhaseIdx] = priVarsOld[Indices::waterSaturationIdx];
oilSaturationOld -= saturationsOld[FluidSystem::waterPhaseIdx];
}
if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx) && priVarsOld.primaryVarsMeaning() == PrimaryVariables::Sw_po_Sg) {
saturationsOld[FluidSystem::gasPhaseIdx] = priVarsOld[Indices::compositionSwitchIdx];
oilSaturationOld -= saturationsOld[FluidSystem::gasPhaseIdx];
}
if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
saturationsOld[FluidSystem::oilPhaseIdx] = oilSaturationOld;
}
// NB fix me! adding pressures changes to satutation changes does not make sense
Scalar tmp = pressureNew - pressureOld; Scalar tmp = pressureNew - pressureOld;
resultDelta += tmp*tmp; resultDelta += tmp*tmp;
resultDenom += pressureNew*pressureNew; resultDenom += pressureNew*pressureNew;
for (unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++ phaseIdx) { if (FluidSystem::numActivePhases() > 1) {
const Scalar tmpSat = saturationsNew[phaseIdx] - saturationsOld[phaseIdx]; if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
resultDelta += tmpSat * tmpSat; saturationsOld[FluidSystem::waterPhaseIdx] = priVarsOld[Indices::waterSaturationIdx];
resultDenom += saturationsNew[phaseIdx]*saturationsNew[phaseIdx]; oilSaturationOld -= saturationsOld[FluidSystem::waterPhaseIdx];
}
if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx) &&
priVarsOld.primaryVarsMeaning() == PrimaryVariables::Sw_po_Sg)
{
saturationsOld[FluidSystem::gasPhaseIdx] = priVarsOld[Indices::compositionSwitchIdx];
oilSaturationOld -= saturationsOld[FluidSystem::gasPhaseIdx];
}
if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
saturationsOld[FluidSystem::oilPhaseIdx] = oilSaturationOld;
}
for (unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++ phaseIdx) {
Scalar tmpSat = saturationsNew[phaseIdx] - saturationsOld[phaseIdx];
resultDelta += tmpSat*tmpSat;
resultDenom += saturationsNew[phaseIdx]*saturationsNew[phaseIdx];
assert(std::isfinite(resultDelta));
assert(std::isfinite(resultDenom));
}
} }
} }

View File

@ -432,9 +432,11 @@ namespace Opm
return; return;
} }
// Run relperm diagnostics // Run relperm diagnostics if we have more than one phase.
RelpermDiagnostics diagnostic; if (FluidSystem::numActivePhases() > 1) {
diagnostic.diagnosis(eclState(), deck(), this->grid()); RelpermDiagnostics diagnostic;
diagnostic.diagnosis(eclState(), deck(), this->grid());
}
} }
// Run the simulator. // Run the simulator.

View File

@ -60,6 +60,7 @@ AdaptiveSimulatorTimer& AdaptiveSimulatorTimer::operator++ ()
{ {
++current_step_; ++current_step_;
current_time_ += dt_; current_time_ += dt_;
assert(dt_ > 0);
// store used time step sizes // store used time step sizes
steps_.push_back( dt_ ); steps_.push_back( dt_ );
return *this; return *this;
@ -71,7 +72,7 @@ AdaptiveSimulatorTimer& AdaptiveSimulatorTimer::operator++ ()
double remaining = (total_time_ - current_time_); double remaining = (total_time_ - current_time_);
// apply max time step if it was set // apply max time step if it was set
dt_ = std::min( dt_estimate, max_time_step_ ); dt_ = std::min( dt_estimate, max_time_step_ );
assert(dt_ > 0);
if( remaining > 0 ) { if( remaining > 0 ) {
// set new time step (depending on remaining time) // set new time step (depending on remaining time)
@ -81,6 +82,7 @@ AdaptiveSimulatorTimer& AdaptiveSimulatorTimer::operator++ ()
if( dt_ > max_time_step_ ) { if( dt_ > max_time_step_ ) {
dt_ = 0.5 * remaining; dt_ = 0.5 * remaining;
} }
assert(dt_ > 0);
return; return;
} }
@ -89,6 +91,7 @@ AdaptiveSimulatorTimer& AdaptiveSimulatorTimer::operator++ ()
if( 1.5 * dt_ > remaining ) { if( 1.5 * dt_ > remaining ) {
dt_ = 0.5 * remaining; dt_ = 0.5 * remaining;
assert(dt_ > 0);
return; return;
} }
} }
@ -102,6 +105,7 @@ AdaptiveSimulatorTimer& AdaptiveSimulatorTimer::operator++ ()
double AdaptiveSimulatorTimer::currentStepLength () const double AdaptiveSimulatorTimer::currentStepLength () const
{ {
assert(dt_ > 0);
return dt_; return dt_;
} }

View File

@ -293,9 +293,10 @@ namespace Opm {
double dtEstimate = timeStepControl_->computeTimeStepSize(dt, iterations, relativeChange, double dtEstimate = timeStepControl_->computeTimeStepSize(dt, iterations, relativeChange,
substepTimer.simulationTimeElapsed()); substepTimer.simulationTimeElapsed());
assert(dtEstimate > 0);
// limit the growth of the timestep size by the growth factor // limit the growth of the timestep size by the growth factor
dtEstimate = std::min(dtEstimate, double(maxGrowth_ * dt)); dtEstimate = std::min(dtEstimate, double(maxGrowth_ * dt));
assert(dtEstimate > 0);
// further restrict time step size growth after convergence problems // further restrict time step size growth after convergence problems
if (restarts > 0) { if (restarts > 0) {
dtEstimate = std::min(growthFactor_ * dt, dtEstimate); dtEstimate = std::min(growthFactor_ * dt, dtEstimate);
@ -309,7 +310,7 @@ namespace Opm {
const double maxPredictionTHPTimestep = 16.0 * unit::day; const double maxPredictionTHPTimestep = 16.0 * unit::day;
dtEstimate = std::min(dtEstimate, maxPredictionTHPTimestep); dtEstimate = std::min(dtEstimate, maxPredictionTHPTimestep);
} }
assert(dtEstimate > 0);
if (timestepVerbose_) { if (timestepVerbose_) {
std::ostringstream ss; std::ostringstream ss;
substepReport.reportStep(ss); substepReport.reportStep(ss);

View File

@ -128,12 +128,16 @@ namespace Opm
{ {
// shift errors // shift errors
for( int i=0; i<2; ++i ) { for( int i=0; i<2; ++i ) {
errors_[ i ] = errors_[i+1]; errors_[ i ] = errors_[i+1];
} }
// store new error // store new error
const double error = relChange.relativeChange(); const double error = relChange.relativeChange();
errors_[ 2 ] = error; errors_[ 2 ] = error;
for( int i=0; i<2; ++i ) {
assert(std::isfinite(errors_[i]));
assert(errors_[i]>0);
}
if( error > tol_ ) if( error > tol_ )
{ {

View File

@ -251,9 +251,19 @@ namespace Opm {
const unsigned cellIdx = elemCtx.globalSpaceIndex(/*spaceIdx=*/0, /*timeIdx=*/0); const unsigned cellIdx = elemCtx.globalSpaceIndex(/*spaceIdx=*/0, /*timeIdx=*/0);
const auto& intQuants = elemCtx.intensiveQuantities(/*spaceIdx=*/0, /*timeIdx=*/0); const auto& intQuants = elemCtx.intensiveQuantities(/*spaceIdx=*/0, /*timeIdx=*/0);
const auto& fs = intQuants.fluidState(); const auto& fs = intQuants.fluidState();
// copy of get perfpressure in Standard well
const double p = fs.pressure(FluidSystem::oilPhaseIdx).value(); // exept for value
cellPressures[cellIdx] = p; double perf_pressure = 0.0;
if (Indices::oilEnabled) {
perf_pressure = fs.pressure(FluidSystem::oilPhaseIdx).value();
} else {
if (Indices::waterEnabled) {
perf_pressure = fs.pressure(FluidSystem::waterPhaseIdx).value();
} else {
perf_pressure = fs.pressure(FluidSystem::gasPhaseIdx).value();
}
}
cellPressures[cellIdx] = perf_pressure;
} }
well_state_.init(wells(), cellPressures, schedule(), wells_ecl_, timeStepIdx, &previous_well_state_, phase_usage_); well_state_.init(wells(), cellPressures, schedule(), wells_ecl_, timeStepIdx, &previous_well_state_, phase_usage_);
@ -1525,8 +1535,8 @@ namespace Opm {
int int
BlackoilWellModel<TypeTag>::numComponents() const BlackoilWellModel<TypeTag>::numComponents() const
{ {
if (numPhases() == 2) { if (numWells() > 0 && numPhases() < 3) {
return 2; return numPhases();
} }
int numComp = FluidSystem::numComponents; int numComp = FluidSystem::numComponents;
if (has_solvent_) { if (has_solvent_) {

View File

@ -493,11 +493,13 @@ namespace Opm {
// sum p, rs, rv, and T. // sum p, rs, rv, and T.
double hydrocarbonPV = pv_cell*hydrocarbon; double hydrocarbonPV = pv_cell*hydrocarbon;
pv += hydrocarbonPV; if (hydrocarbonPV > 0) {
p += fs.pressure(FluidSystem::oilPhaseIdx).value()*hydrocarbonPV; pv += hydrocarbonPV;
rs += fs.Rs().value()*hydrocarbonPV; p += fs.pressure(FluidSystem::oilPhaseIdx).value()*hydrocarbonPV;
rv += fs.Rv().value()*hydrocarbonPV; rs += fs.Rs().value()*hydrocarbonPV;
T += fs.temperature(FluidSystem::oilPhaseIdx).value()*hydrocarbonPV; rv += fs.Rv().value()*hydrocarbonPV;
T += fs.temperature(FluidSystem::oilPhaseIdx).value()*hydrocarbonPV;
}
} }
for (const auto& reg : rmap_.activeRegions()) { for (const auto& reg : rmap_.activeRegions()) {
@ -521,7 +523,7 @@ namespace Opm {
} }
} }
/** /**
* Region identifier. * Region identifier.
* *
* Integral type. * Integral type.

View File

@ -59,6 +59,7 @@ namespace Opm
using typename Base::Indices; using typename Base::Indices;
using typename Base::RateConverterType; using typename Base::RateConverterType;
using typename Base::SparseMatrixAdapter; using typename Base::SparseMatrixAdapter;
using typename Base::FluidState;
using Base::numEq; using Base::numEq;
@ -293,6 +294,8 @@ namespace Opm
EvalWell extendEval(const Eval& in) const; EvalWell extendEval(const Eval& in) const;
Eval getPerfCellPressure(const FluidState& fs) const;
// xw = inv(D)*(rw - C*x) // xw = inv(D)*(rw - C*x)
void recoverSolutionWell(const BVector& x, BVectorWell& xw) const; void recoverSolutionWell(const BVector& x, BVectorWell& xw) const;

View File

@ -238,6 +238,10 @@ namespace Opm
StandardWell<TypeTag>:: StandardWell<TypeTag>::
wellVolumeFraction(const unsigned compIdx) const wellVolumeFraction(const unsigned compIdx) const
{ {
if (FluidSystem::numActivePhases() == 1) {
return EvalWell(numWellEq_ + numEq, 1.0);
}
if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx) && compIdx == Indices::canonicalToActiveComponentIndex(FluidSystem::waterCompIdx)) { if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx) && compIdx == Indices::canonicalToActiveComponentIndex(FluidSystem::waterCompIdx)) {
return primary_variables_evaluation_[WFrac]; return primary_variables_evaluation_[WFrac];
} }
@ -305,6 +309,24 @@ namespace Opm
template<typename TypeTag>
typename StandardWell<TypeTag>::Eval
StandardWell<TypeTag>::getPerfCellPressure(const typename StandardWell<TypeTag>::FluidState& fs) const
{
Eval pressure;
if (Indices::oilEnabled) {
pressure = fs.pressure(FluidSystem::oilPhaseIdx);
} else {
if (Indices::waterEnabled) {
pressure = fs.pressure(FluidSystem::waterPhaseIdx);
} else {
pressure = fs.pressure(FluidSystem::gasPhaseIdx);
}
}
return pressure;
}
template<typename TypeTag> template<typename TypeTag>
void void
StandardWell<TypeTag>:: StandardWell<TypeTag>::
@ -321,7 +343,7 @@ namespace Opm
{ {
const auto& fs = intQuants.fluidState(); const auto& fs = intQuants.fluidState();
const EvalWell pressure = extendEval(fs.pressure(FluidSystem::oilPhaseIdx)); const EvalWell pressure = extendEval(getPerfCellPressure(fs));
const EvalWell rs = extendEval(fs.Rs()); const EvalWell rs = extendEval(fs.Rs());
const EvalWell rv = extendEval(fs.Rv()); const EvalWell rv = extendEval(fs.Rv());
std::vector<EvalWell> b_perfcells_dense(num_components_, EvalWell{numWellEq_ + numEq, 0.0}); std::vector<EvalWell> b_perfcells_dense(num_components_, EvalWell{numWellEq_ + numEq, 0.0});
@ -669,7 +691,9 @@ namespace Opm
|| (pu.phase_pos[Gas] == p && summaryConfig.hasSummaryKey("WPIG:" + name()))) { || (pu.phase_pos[Gas] == p && summaryConfig.hasSummaryKey("WPIG:" + name()))) {
const unsigned int compIdx = flowPhaseToEbosCompIdx(p); const unsigned int compIdx = flowPhaseToEbosCompIdx(p);
const double drawdown = well_state.perfPress()[first_perf_ + perf] - intQuants.fluidState().pressure(FluidSystem::oilPhaseIdx).value(); const auto& fs = intQuants.fluidState();
Eval perf_pressure = getPerfCellPressure(fs);
const double drawdown = well_state.perfPress()[first_perf_ + perf] - perf_pressure.value();
const bool new_well = schedule.hasWellEvent(name(), ScheduleEvents::NEW_WELL, current_step_); const bool new_well = schedule.hasWellEvent(name(), ScheduleEvents::NEW_WELL, current_step_);
double productivity_index = cq_s[compIdx].value() / drawdown; double productivity_index = cq_s[compIdx].value() / drawdown;
scaleProductivityIndex(perf, productivity_index, new_well, deferred_logger); scaleProductivityIndex(perf, productivity_index, new_well, deferred_logger);
@ -679,12 +703,15 @@ namespace Opm
} }
// add vol * dF/dt + Q to the well equations; // add vol * dF/dt + Q to the well equations;
for (int componentIdx = 0; componentIdx < numWellConservationEq; ++componentIdx) { for (int componentIdx = 0; componentIdx < numWellConservationEq; ++componentIdx) {
// TODO: following the development in MSW, we need to convert the volume of the wellbore to be surface volume // TODO: following the development in MSW, we need to convert the volume of the wellbore to be surface volume
// since all the rates are under surface condition // since all the rates are under surface condition
EvalWell resWell_loc = (wellSurfaceVolumeFraction(componentIdx) - F0_[componentIdx]) * volume / dt; EvalWell resWell_loc(numWellEq_ + numEq, 0.0);
if (FluidSystem::numActivePhases() > 1) {
assert(dt > 0);
resWell_loc += (wellSurfaceVolumeFraction(componentIdx) - F0_[componentIdx]) * volume / dt;
}
resWell_loc -= getQs(componentIdx) * well_efficiency_factor_; resWell_loc -= getQs(componentIdx) * well_efficiency_factor_;
for (int pvIdx = 0; pvIdx < numWellEq_; ++pvIdx) { for (int pvIdx = 0; pvIdx < numWellEq_; ++pvIdx) {
invDuneD_[0][0][componentIdx][pvIdx] += resWell_loc.derivative(pvIdx+numEq); invDuneD_[0][0][componentIdx][pvIdx] += resWell_loc.derivative(pvIdx+numEq);
@ -919,29 +946,30 @@ namespace Opm
const double relaxation_factor_fractions = (well_type_ == PRODUCER) ? const double relaxation_factor_fractions = (well_type_ == PRODUCER) ?
relaxationFactorFractionsProducer(old_primary_variables, dwells) relaxationFactorFractionsProducer(old_primary_variables, dwells)
: 1.0; : 1.0;
if (FluidSystem::numActivePhases() > 1) {
// update the second and third well variable (The flux fractions)
if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
const int sign2 = dwells[0][WFrac] > 0 ? 1: -1;
const double dx2_limited = sign2 * std::min(std::abs(dwells[0][WFrac] * relaxation_factor_fractions), dFLimit);
// primary_variables_[WFrac] = old_primary_variables[WFrac] - dx2_limited;
primary_variables_[WFrac] = old_primary_variables[WFrac] - dx2_limited;
}
// update the second and third well variable (The flux fractions) if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) { const int sign3 = dwells[0][GFrac] > 0 ? 1: -1;
const int sign2 = dwells[0][WFrac] > 0 ? 1: -1; const double dx3_limited = sign3 * std::min(std::abs(dwells[0][GFrac] * relaxation_factor_fractions), dFLimit);
const double dx2_limited = sign2 * std::min(std::abs(dwells[0][WFrac] * relaxation_factor_fractions), dFLimit); primary_variables_[GFrac] = old_primary_variables[GFrac] - dx3_limited;
// primary_variables_[WFrac] = old_primary_variables[WFrac] - dx2_limited; }
primary_variables_[WFrac] = old_primary_variables[WFrac] - dx2_limited;
if (has_solvent) {
const int sign4 = dwells[0][SFrac] > 0 ? 1: -1;
const double dx4_limited = sign4 * std::min(std::abs(dwells[0][SFrac]) * relaxation_factor_fractions, dFLimit);
primary_variables_[SFrac] = old_primary_variables[SFrac] - dx4_limited;
}
processFractions();
} }
if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
const int sign3 = dwells[0][GFrac] > 0 ? 1: -1;
const double dx3_limited = sign3 * std::min(std::abs(dwells[0][GFrac] * relaxation_factor_fractions), dFLimit);
primary_variables_[GFrac] = old_primary_variables[GFrac] - dx3_limited;
}
if (has_solvent) {
const int sign4 = dwells[0][SFrac] > 0 ? 1: -1;
const double dx4_limited = sign4 * std::min(std::abs(dwells[0][SFrac]) * relaxation_factor_fractions, dFLimit);
primary_variables_[SFrac] = old_primary_variables[SFrac] - dx4_limited;
}
processFractions();
// updating the total rates Q_t // updating the total rates Q_t
const double relaxation_factor_rate = relaxationFactorRate(old_primary_variables, dwells); const double relaxation_factor_rate = relaxationFactorRate(old_primary_variables, dwells);
primary_variables_[WQTotal] = old_primary_variables[WQTotal] - dwells[0][WQTotal] * relaxation_factor_rate; primary_variables_[WQTotal] = old_primary_variables[WQTotal] - dwells[0][WQTotal] * relaxation_factor_rate;
@ -956,6 +984,10 @@ namespace Opm
} }
updateExtraPrimaryVariables(dwells); updateExtraPrimaryVariables(dwells);
for (double v : primary_variables_) {
assert(Opm::isfinite(v));
}
} }
@ -1073,49 +1105,53 @@ namespace Opm
updateWellStateFromPrimaryVariables(WellState& well_state, Opm::DeferredLogger& deferred_logger) const updateWellStateFromPrimaryVariables(WellState& well_state, Opm::DeferredLogger& deferred_logger) const
{ {
const PhaseUsage& pu = phaseUsage(); const PhaseUsage& pu = phaseUsage();
assert( FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx) );
const int oil_pos = pu.phase_pos[Oil];
std::vector<double> F(number_of_phases_, 0.0); std::vector<double> F(number_of_phases_, 0.0);
F[oil_pos] = 1.0; if (FluidSystem::numActivePhases() == 1) {
F[0] = 1.0;
} else {
assert( FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx) );
const int oil_pos = pu.phase_pos[Oil];
F[oil_pos] = 1.0;
if ( FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx) ) { if ( FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx) ) {
const int water_pos = pu.phase_pos[Water]; const int water_pos = pu.phase_pos[Water];
F[water_pos] = primary_variables_[WFrac]; F[water_pos] = primary_variables_[WFrac];
F[oil_pos] -= F[water_pos]; F[oil_pos] -= F[water_pos];
}
if ( FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx) ) {
const int gas_pos = pu.phase_pos[Gas];
F[gas_pos] = primary_variables_[GFrac];
F[oil_pos] -= F[gas_pos];
}
double F_solvent = 0.0;
if (has_solvent) {
F_solvent = primary_variables_[SFrac];
F[oil_pos] -= F_solvent;
}
// convert the fractions to be Q_p / G_total to calculate the phase rates
for (int p = 0; p < number_of_phases_; ++p) {
const double scal = scalingFactor(p);
// for injection wells, there should only one non-zero scaling factor
if (scal > 0) {
F[p] /= scal ;
} else {
// this should only happens to injection wells
F[p] = 0.;
} }
}
// F_solvent is added to F_gas. This means that well_rate[Gas] also contains solvent. if ( FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx) ) {
// More testing is needed to make sure this is correct for well groups and THP. const int gas_pos = pu.phase_pos[Gas];
if (has_solvent){ F[gas_pos] = primary_variables_[GFrac];
F_solvent /= scalingFactor(contiSolventEqIdx); F[oil_pos] -= F[gas_pos];
F[pu.phase_pos[Gas]] += F_solvent; }
}
double F_solvent = 0.0;
if (has_solvent) {
F_solvent = primary_variables_[SFrac];
F[oil_pos] -= F_solvent;
}
// convert the fractions to be Q_p / G_total to calculate the phase rates
for (int p = 0; p < number_of_phases_; ++p) {
const double scal = scalingFactor(p);
// for injection wells, there should only one non-zero scaling factor
if (scal > 0) {
F[p] /= scal ;
} else {
// this should only happens to injection wells
F[p] = 0.;
}
}
// F_solvent is added to F_gas. This means that well_rate[Gas] also contains solvent.
// More testing is needed to make sure this is correct for well groups and THP.
if (has_solvent){
F_solvent /= scalingFactor(contiSolventEqIdx);
F[pu.phase_pos[Gas]] += F_solvent;
}
}
well_state.bhp()[index_of_well_] = primary_variables_[Bhp]; well_state.bhp()[index_of_well_] = primary_variables_[Bhp];
// calculate the phase rates based on the primary variables // calculate the phase rates based on the primary variables
@ -1292,6 +1328,10 @@ namespace Opm
break; break;
} // end of switch } // end of switch
for (double v : primary_variables_) {
assert(Opm::isfinite(v));
}
} }
@ -1324,7 +1364,8 @@ namespace Opm
const auto& int_quantities = *(ebos_simulator.model().cachedIntensiveQuantities(cell_idx, /*timeIdx=*/ 0)); const auto& int_quantities = *(ebos_simulator.model().cachedIntensiveQuantities(cell_idx, /*timeIdx=*/ 0));
const auto& fs = int_quantities.fluidState(); const auto& fs = int_quantities.fluidState();
// the pressure of the reservoir grid block the well connection is in // the pressure of the reservoir grid block the well connection is in
const double p_r = fs.pressure(FluidSystem::oilPhaseIdx).value(); Eval perf_pressure = getPerfCellPressure(fs);
double p_r = perf_pressure.value();
// calculating the b for the connection // calculating the b for the connection
std::vector<double> b_perf(num_components_); std::vector<double> b_perf(num_components_);
@ -1550,8 +1591,9 @@ namespace Opm
const int cell_idx = well_cells_[perf]; const int cell_idx = well_cells_[perf];
const auto& intQuants = *(ebos_simulator.model().cachedIntensiveQuantities(cell_idx, /*timeIdx=*/0)); const auto& intQuants = *(ebos_simulator.model().cachedIntensiveQuantities(cell_idx, /*timeIdx=*/0));
const auto& fs = intQuants.fluidState(); const auto& fs = intQuants.fluidState();
Eval perf_pressure = getPerfCellPressure(fs);
const double pressure = perf_pressure.value();
const double pressure = (fs.pressure(FluidSystem::oilPhaseIdx)).value();
const double bhp = getBhp().value(); const double bhp = getBhp().value();
// Pressure drawdown (also used to determine direction of flow) // Pressure drawdown (also used to determine direction of flow)
@ -1755,6 +1797,7 @@ namespace Opm
// TODO: to check why should be perf - 1 // TODO: to check why should be perf - 1
const double p_above = perf == 0 ? well_state.bhp()[w] : well_state.perfPress()[first_perf_ + perf - 1]; const double p_above = perf == 0 ? well_state.bhp()[w] : well_state.perfPress()[first_perf_ + perf - 1];
const double p_avg = (well_state.perfPress()[first_perf_ + perf] + p_above)/2; const double p_avg = (well_state.perfPress()[first_perf_ + perf] + p_above)/2;
// strange choice
const double temperature = fs.temperature(FluidSystem::oilPhaseIdx).value(); const double temperature = fs.temperature(FluidSystem::oilPhaseIdx).value();
if (waterPresent) { if (waterPresent) {
@ -2518,57 +2561,57 @@ namespace Opm
} }
} }
if (std::abs(total_well_rate) > 0.) { if (FluidSystem::numActivePhases() > 1) {
const auto pu = phaseUsage(); if (std::abs(total_well_rate) > 0.) {
if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) { const auto pu = phaseUsage();
primary_variables_[WFrac] = scalingFactor(pu.phase_pos[Water]) * well_state.wellRates()[np*well_index + pu.phase_pos[Water]] / total_well_rate;
}
if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
primary_variables_[GFrac] = scalingFactor(pu.phase_pos[Gas]) * (well_state.wellRates()[np*well_index + pu.phase_pos[Gas]] - well_state.solventWellRate(well_index)) / total_well_rate ;
}
if (has_solvent) {
primary_variables_[SFrac] = scalingFactor(pu.phase_pos[Gas]) * well_state.solventWellRate(well_index) / total_well_rate ;
}
} else { // total_well_rate == 0
if (well_type_ == INJECTOR) {
auto phase = well_ecl_.getInjectionProperties().injectorType;
// only single phase injection handled
if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) { if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
if (phase == Well2::InjectorType::WATER) { primary_variables_[WFrac] = scalingFactor(pu.phase_pos[Water]) * well_state.wellRates()[np*well_index + pu.phase_pos[Water]] / total_well_rate;
primary_variables_[WFrac] = 1.0;
} else {
primary_variables_[WFrac] = 0.0;
}
} }
if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) { if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
if (phase == Well2::InjectorType::GAS) { primary_variables_[GFrac] = scalingFactor(pu.phase_pos[Gas]) * (well_state.wellRates()[np*well_index + pu.phase_pos[Gas]] - well_state.solventWellRate(well_index)) / total_well_rate ;
primary_variables_[GFrac] = 1.0 - wsolvent(); }
if (has_solvent) { if (has_solvent) {
primary_variables_[SFrac] = wsolvent(); primary_variables_[SFrac] = scalingFactor(pu.phase_pos[Gas]) * well_state.solventWellRate(well_index) / total_well_rate ;
}
} else { // total_well_rate == 0
if (well_type_ == INJECTOR) {
auto phase = well_ecl_.getInjectionProperties().injectorType;
// only single phase injection handled
if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
if (phase == Well2::InjectorType::WATER) {
primary_variables_[WFrac] = 1.0;
} else {
primary_variables_[WFrac] = 0.0;
}
}
if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
if (phase == Well2::InjectorType::GAS) {
primary_variables_[GFrac] = 1.0 - wsolvent();
if (has_solvent) {
primary_variables_[SFrac] = wsolvent();
}
} else {
primary_variables_[GFrac] = 0.0;
} }
} else {
primary_variables_[GFrac] = 0.0;
} }
}
// TODO: it is possible to leave injector as a oil well, // TODO: it is possible to leave injector as a oil well,
// when F_w and F_g both equals to zero, not sure under what kind of circumstance // when F_w and F_g both equals to zero, not sure under what kind of circumstance
// this will happen. // this will happen.
} else if (well_type_ == PRODUCER) { // producers } else if (well_type_ == PRODUCER) { // producers
// TODO: the following are not addressed for the solvent case yet // TODO: the following are not addressed for the solvent case yet
if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) { if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
primary_variables_[WFrac] = 1.0 / np; primary_variables_[WFrac] = 1.0 / np;
}
if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
primary_variables_[GFrac] = 1.0 / np;
}
} else {
OPM_DEFLOG_THROW(std::logic_error, "Expected PRODUCER or INJECTOR type of well", deferred_logger);
} }
if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
primary_variables_[GFrac] = 1.0 / np;
}
} else {
OPM_DEFLOG_THROW(std::logic_error, "Expected PRODUCER or INJECTOR type of well", deferred_logger);
} }
} }
// BHP // BHP
primary_variables_[Bhp] = well_state.bhp()[index_of_well_]; primary_variables_[Bhp] = well_state.bhp()[index_of_well_];
@ -2579,6 +2622,10 @@ namespace Opm
primary_variables_[Bhp + 1 + number_of_perforations_ + perf] = well_state.perfSkinPressure()[first_perf_ + perf]; primary_variables_[Bhp + 1 + number_of_perforations_ + perf] = well_state.perfSkinPressure()[first_perf_ + perf];
} }
} }
for (double v : primary_variables_) {
assert(Opm::isfinite(v));
}
} }
@ -2824,28 +2871,31 @@ namespace Opm
// 0.95 is a experimental value, which remains to be optimized // 0.95 is a experimental value, which remains to be optimized
double relaxation_factor = 1.0; double relaxation_factor = 1.0;
if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) { if (FluidSystem::numActivePhases() > 1) {
const double relaxation_factor_w = relaxationFactorFraction(primary_variables[WFrac], dwells[0][WFrac]); if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
relaxation_factor = std::min(relaxation_factor, relaxation_factor_w); const double relaxation_factor_w = relaxationFactorFraction(primary_variables[WFrac], dwells[0][WFrac]);
} relaxation_factor = std::min(relaxation_factor, relaxation_factor_w);
}
if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) { if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
const double relaxation_factor_g = relaxationFactorFraction(primary_variables[GFrac], dwells[0][GFrac]); const double relaxation_factor_g = relaxationFactorFraction(primary_variables[GFrac], dwells[0][GFrac]);
relaxation_factor = std::min(relaxation_factor, relaxation_factor_g); relaxation_factor = std::min(relaxation_factor, relaxation_factor_g);
} }
if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx) && FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) { if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)
// We need to make sure the even with the relaxation_factor, the sum of F_w and F_g is below one, so there will && FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
// not be negative oil fraction later // We need to make sure the even with the relaxation_factor, the sum of F_w and F_g is below one, so
const double original_sum = primary_variables[WFrac] + primary_variables[GFrac]; // there will not be negative oil fraction later
const double relaxed_update = (dwells[0][WFrac] + dwells[0][GFrac]) * relaxation_factor; const double original_sum = primary_variables[WFrac] + primary_variables[GFrac];
const double possible_updated_sum = original_sum - relaxed_update; const double relaxed_update = (dwells[0][WFrac] + dwells[0][GFrac]) * relaxation_factor;
const double possible_updated_sum = original_sum - relaxed_update;
if (possible_updated_sum > 1.0) { if (possible_updated_sum > 1.0) {
assert(relaxed_update != 0.); assert(relaxed_update != 0.);
const double further_relaxation_factor = std::abs((1. - original_sum) / relaxed_update) * 0.95; const double further_relaxation_factor = std::abs((1. - original_sum) / relaxed_update) * 0.95;
relaxation_factor *= further_relaxation_factor; relaxation_factor *= further_relaxation_factor;
}
} }
} }

View File

@ -94,6 +94,7 @@ namespace Opm
static const bool has_solvent = GET_PROP_VALUE(TypeTag, EnableSolvent); static const bool has_solvent = GET_PROP_VALUE(TypeTag, EnableSolvent);
static const bool has_polymer = GET_PROP_VALUE(TypeTag, EnablePolymer); static const bool has_polymer = GET_PROP_VALUE(TypeTag, EnablePolymer);
static const bool has_energy = GET_PROP_VALUE(TypeTag, EnableEnergy); static const bool has_energy = GET_PROP_VALUE(TypeTag, EnableEnergy);
static const bool has_temperature = GET_PROP_VALUE(TypeTag, EnableTemperature);
// flag for polymer molecular weight related // flag for polymer molecular weight related
static const bool has_polymermw = GET_PROP_VALUE(TypeTag, EnablePolymerMW); static const bool has_polymermw = GET_PROP_VALUE(TypeTag, EnablePolymerMW);
static const bool has_foam = GET_PROP_VALUE(TypeTag, EnableFoam); static const bool has_foam = GET_PROP_VALUE(TypeTag, EnableFoam);
@ -106,7 +107,13 @@ namespace Opm
// For the conversion between the surface volume rate and reservoir voidage rate // For the conversion between the surface volume rate and reservoir voidage rate
using RateConverterType = RateConverter:: using RateConverterType = RateConverter::
SurfaceToReservoirVoidage<FluidSystem, std::vector<int> >; SurfaceToReservoirVoidage<FluidSystem, std::vector<int> >;
static const bool compositionSwitchEnabled = Indices::gasEnabled;
using FluidState = Opm::BlackOilFluidState<Eval,
FluidSystem,
has_temperature,
has_energy,
compositionSwitchEnabled,
Indices::numPhases >;
/// Constructor /// Constructor
WellInterface(const Well2& well, const int time_step, const Wells* wells, WellInterface(const Well2& well, const int time_step, const Wells* wells,
const ModelParameters& param, const ModelParameters& param,