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)
set( USE_OPENMP_DEFAULT OFF ) # Use of OpenMP is considered experimental
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_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)
@ -155,15 +156,36 @@ opm_add_test(flow
flow/flow_ebos_oilwater_polymer.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
ONLY_COMPILE
DEFAULT_ENABLE_IF ${FLOW_DEFAULT_ENABLE_IF}
DEFAULT_ENABLE_IF ${FLOW_VARIANTS_DEFAULT_ENABLE_IF}
SOURCES flow/flow_blackoil_dunecpr.cpp
EXE_NAME flow_blackoil_dunecpr
DEPENDS "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)
install(TARGETS flow DESTINATION bin)

View File

@ -395,7 +395,16 @@ public:
}
if (oilPressure_.size() > 0) {
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]);
}

View File

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

View File

@ -99,7 +99,5 @@ namespace Opm {
int main(int argc, char** argv)
{
typedef TTAG(EclFlowProblemSimple) TypeTag;
bool outputCout = true;
bool outputFiles = true;
return mainFlow<TypeTag>(argc, argv, outputCout, outputFiles);
return mainFlow<TypeTag>(argc, argv);
}

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,10 +29,15 @@
#include <opm/common/utility/parameters/ParameterGroup.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/Parser/Parser.hpp>
#include <opm/parser/eclipse/EclipseState/EclipseState.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>
@ -118,13 +123,162 @@ namespace detail
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 -----------------
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.
#if HAVE_DUNE_FEM
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 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);
if (status != 0)
if (status != 0) {
// 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
// --print-properties parameters.
#if HAVE_MPI
MPI_Finalize();
#endif
return (status >= 0)?status:0;
}
FileOutputMode outputMode = FileOutputMode::OUTPUT_NONE;
bool outputCout = false;
if (mpiRank == 0)
outputCout = EWOMS_GET_PARAM(PreTypeTag, bool, EnableTerminalOutput);
@ -176,26 +336,55 @@ int mainFlow(int argc, char** argv, bool outputCout, bool outputFiles)
// Create Deck and EclipseState.
try {
Opm::Parser parser;
typedef std::pair<std::string, Opm::InputError::Action> ParseModePair;
typedef std::vector<ParseModePair> ParseModePairs;
ParseModePairs tmp;
tmp.push_back(ParseModePair(Opm::ParseContext::PARSE_RANDOM_SLASH, Opm::InputError::IGNORE));
tmp.push_back(ParseModePair(Opm::ParseContext::PARSE_MISSING_DIMS_KEYWORD, Opm::InputError::WARN));
tmp.push_back(ParseModePair(Opm::ParseContext::SUMMARY_UNKNOWN_WELL, Opm::InputError::WARN));
tmp.push_back(ParseModePair(Opm::ParseContext::SUMMARY_UNKNOWN_GROUP, Opm::InputError::WARN));
Opm::ParseContext parseContext(tmp);
Opm::ErrorGuard errorGuard;
std::shared_ptr<Opm::Deck> deck = std::make_shared< Opm::Deck >( parser.parseFile(deckFilename , parseContext, errorGuard) );
if (outputCout) {
Opm::checkDeck(*deck, parser, parseContext, errorGuard);
Opm::MissingFeatures::checkKeywords(*deck);
std::cout << "Reading deck file '" << deckFilename << "'\n";
std::cout.flush();
}
//Opm::Runspec runspec( *deck );
//const auto& phases = runspec.phases();
std::shared_ptr<Opm::Deck> deck;
std::shared_ptr<Opm::EclipseState> eclipseState;
std::shared_ptr<Opm::Schedule> schedule;
std::shared_ptr<Opm::SummaryConfig> summaryConfig;
{
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::EclipseState> eclipseState = std::make_shared< Opm::EclipseState > ( *deck, parseContext, errorGuard );
if (EWOMS_GET_PARAM(PreTypeTag, bool, EclStrictParsing))
parseContext.update( Opm::InputError::DELAYED_EXIT1);
else {
parseContext.update(Opm::ParseContext::PARSE_RANDOM_SLASH, Opm::InputError::IGNORE);
parseContext.update(Opm::ParseContext::PARSE_MISSING_DIMS_KEYWORD, Opm::InputError::WARN);
parseContext.update(Opm::ParseContext::SUMMARY_UNKNOWN_WELL, Opm::InputError::WARN);
parseContext.update(Opm::ParseContext::SUMMARY_UNKNOWN_GROUP, Opm::InputError::WARN);
}
Opm::FlowMainEbos<PreTypeTag>::printPRTHeader(outputCout);
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);
}

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
// 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.");
}

View File

@ -422,12 +422,21 @@ namespace Opm {
Scalar saturationsOld[FluidSystem::numPhases] = { 0.0 };
Scalar oilSaturationOld = 1.0;
// NB fix me! adding pressures changes to satutation changes does not make sense
Scalar tmp = pressureNew - pressureOld;
resultDelta += tmp*tmp;
resultDenom += pressureNew*pressureNew;
if (FluidSystem::numActivePhases() > 1) {
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) {
if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx) &&
priVarsOld.primaryVarsMeaning() == PrimaryVariables::Sw_po_Sg)
{
saturationsOld[FluidSystem::gasPhaseIdx] = priVarsOld[Indices::compositionSwitchIdx];
oilSaturationOld -= saturationsOld[FluidSystem::gasPhaseIdx];
}
@ -435,15 +444,13 @@ namespace Opm {
if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
saturationsOld[FluidSystem::oilPhaseIdx] = oilSaturationOld;
}
Scalar tmp = pressureNew - pressureOld;
resultDelta += tmp*tmp;
resultDenom += pressureNew*pressureNew;
for (unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++ phaseIdx) {
const Scalar tmpSat = saturationsNew[phaseIdx] - saturationsOld[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,10 +432,12 @@ namespace Opm
return;
}
// Run relperm diagnostics
// Run relperm diagnostics if we have more than one phase.
if (FluidSystem::numActivePhases() > 1) {
RelpermDiagnostics diagnostic;
diagnostic.diagnosis(eclState(), deck(), this->grid());
}
}
// Run the simulator.
void runSimulator(bool output_cout)

View File

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

View File

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

View File

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

View File

@ -251,9 +251,19 @@ namespace Opm {
const unsigned cellIdx = elemCtx.globalSpaceIndex(/*spaceIdx=*/0, /*timeIdx=*/0);
const auto& intQuants = elemCtx.intensiveQuantities(/*spaceIdx=*/0, /*timeIdx=*/0);
const auto& fs = intQuants.fluidState();
const double p = fs.pressure(FluidSystem::oilPhaseIdx).value();
cellPressures[cellIdx] = p;
// copy of get perfpressure in Standard well
// exept for value
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_);
@ -1525,8 +1535,8 @@ namespace Opm {
int
BlackoilWellModel<TypeTag>::numComponents() const
{
if (numPhases() == 2) {
return 2;
if (numWells() > 0 && numPhases() < 3) {
return numPhases();
}
int numComp = FluidSystem::numComponents;
if (has_solvent_) {

View File

@ -493,12 +493,14 @@ namespace Opm {
// sum p, rs, rv, and T.
double hydrocarbonPV = pv_cell*hydrocarbon;
if (hydrocarbonPV > 0) {
pv += hydrocarbonPV;
p += fs.pressure(FluidSystem::oilPhaseIdx).value()*hydrocarbonPV;
rs += fs.Rs().value()*hydrocarbonPV;
rv += fs.Rv().value()*hydrocarbonPV;
T += fs.temperature(FluidSystem::oilPhaseIdx).value()*hydrocarbonPV;
}
}
for (const auto& reg : rmap_.activeRegions()) {
auto& ra = attr_.attributes(reg);

View File

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

View File

@ -238,6 +238,10 @@ namespace Opm
StandardWell<TypeTag>::
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)) {
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>
void
StandardWell<TypeTag>::
@ -321,7 +343,7 @@ namespace Opm
{
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 rv = extendEval(fs.Rv());
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()))) {
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_);
double productivity_index = cq_s[compIdx].value() / drawdown;
scaleProductivityIndex(perf, productivity_index, new_well, deferred_logger);
@ -679,12 +703,15 @@ namespace Opm
}
// add vol * dF/dt + Q to the well equations;
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
// 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_;
for (int pvIdx = 0; pvIdx < numWellEq_; ++pvIdx) {
invDuneD_[0][0][componentIdx][pvIdx] += resWell_loc.derivative(pvIdx+numEq);
@ -919,7 +946,7 @@ namespace Opm
const double relaxation_factor_fractions = (well_type_ == PRODUCER) ?
relaxationFactorFractionsProducer(old_primary_variables, dwells)
: 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;
@ -941,6 +968,7 @@ namespace Opm
}
processFractions();
}
// updating the total rates Q_t
const double relaxation_factor_rate = relaxationFactorRate(old_primary_variables, dwells);
@ -956,6 +984,10 @@ namespace Opm
}
updateExtraPrimaryVariables(dwells);
for (double v : primary_variables_) {
assert(Opm::isfinite(v));
}
}
@ -1073,10 +1105,13 @@ namespace Opm
updateWellStateFromPrimaryVariables(WellState& well_state, Opm::DeferredLogger& deferred_logger) const
{
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);
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) ) {
@ -1116,6 +1151,7 @@ namespace Opm
F[pu.phase_pos[Gas]] += F_solvent;
}
}
well_state.bhp()[index_of_well_] = primary_variables_[Bhp];
// calculate the phase rates based on the primary variables
@ -1292,6 +1328,10 @@ namespace Opm
break;
} // 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& fs = int_quantities.fluidState();
// 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
std::vector<double> b_perf(num_components_);
@ -1550,8 +1591,9 @@ namespace Opm
const int cell_idx = well_cells_[perf];
const auto& intQuants = *(ebos_simulator.model().cachedIntensiveQuantities(cell_idx, /*timeIdx=*/0));
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();
// Pressure drawdown (also used to determine direction of flow)
@ -1755,6 +1797,7 @@ namespace Opm
// 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_avg = (well_state.perfPress()[first_perf_ + perf] + p_above)/2;
// strange choice
const double temperature = fs.temperature(FluidSystem::oilPhaseIdx).value();
if (waterPresent) {
@ -2518,6 +2561,7 @@ namespace Opm
}
}
if (FluidSystem::numActivePhases() > 1) {
if (std::abs(total_well_rate) > 0.) {
const auto pu = phaseUsage();
if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
@ -2540,7 +2584,6 @@ namespace Opm
primary_variables_[WFrac] = 0.0;
}
}
if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
if (phase == Well2::InjectorType::GAS) {
primary_variables_[GFrac] = 1.0 - wsolvent();
@ -2567,7 +2610,7 @@ namespace Opm
OPM_DEFLOG_THROW(std::logic_error, "Expected PRODUCER or INJECTOR type of well", deferred_logger);
}
}
}
// BHP
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];
}
}
for (double v : primary_variables_) {
assert(Opm::isfinite(v));
}
}
@ -2824,6 +2871,7 @@ namespace Opm
// 0.95 is a experimental value, which remains to be optimized
double relaxation_factor = 1.0;
if (FluidSystem::numActivePhases() > 1) {
if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
const double relaxation_factor_w = relaxationFactorFraction(primary_variables[WFrac], dwells[0][WFrac]);
relaxation_factor = std::min(relaxation_factor, relaxation_factor_w);
@ -2834,9 +2882,10 @@ namespace Opm
relaxation_factor = std::min(relaxation_factor, relaxation_factor_g);
}
if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx) && FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
// 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
// not be negative oil fraction later
if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)
&& FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
// 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 not be negative oil fraction later
const double original_sum = primary_variables[WFrac] + primary_variables[GFrac];
const double relaxed_update = (dwells[0][WFrac] + dwells[0][GFrac]) * relaxation_factor;
const double possible_updated_sum = original_sum - relaxed_update;
@ -2848,6 +2897,7 @@ namespace Opm
relaxation_factor *= further_relaxation_factor;
}
}
}
assert(relaxation_factor >= 0.0 && relaxation_factor <= 1.0);

View File

@ -94,6 +94,7 @@ namespace Opm
static const bool has_solvent = GET_PROP_VALUE(TypeTag, EnableSolvent);
static const bool has_polymer = GET_PROP_VALUE(TypeTag, EnablePolymer);
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
static const bool has_polymermw = GET_PROP_VALUE(TypeTag, EnablePolymerMW);
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
using RateConverterType = RateConverter::
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
WellInterface(const Well2& well, const int time_step, const Wells* wells,
const ModelParameters& param,