Merge branch 'master' of https://github.com/OPM/opm-simulators into fix_cpr_oil_gas

This commit is contained in:
hnil 2019-04-01 12:57:18 +02:00
commit 30368ca7c5
8 changed files with 119 additions and 85 deletions

View File

@ -33,7 +33,7 @@
#include <array> #include <array>
#include <memory> #include <memory>
#include <except> #include <exception>
#include <vector> #include <vector>
#include <cassert> #include <cassert>

View File

@ -25,6 +25,9 @@
* *
* \brief The common settings for all ebos variants. * \brief The common settings for all ebos variants.
*/ */
#ifndef EBOS_HH
#define EBOS_HH
#include "eclproblem.hh" #include "eclproblem.hh"
#include <opm/autodiff/BlackoilWellModel.hpp> #include <opm/autodiff/BlackoilWellModel.hpp>
@ -133,3 +136,5 @@ public:
using ParentType::EclProblem; using ParentType::EclProblem;
}; };
} }
#endif // EBOS_HH

View File

@ -363,7 +363,7 @@ protected:
{ {
const auto& problem = elemCtx.problem(); const auto& problem = elemCtx.problem();
bool enableBoundaryMassFlux = problem.hasFreeBoundaryConditions(); bool enableBoundaryMassFlux = problem.nonTrivialBoundaryConditions();
if (!enableBoundaryMassFlux) if (!enableBoundaryMassFlux)
return; return;

View File

@ -140,6 +140,10 @@ NEW_PROP_TAG(EnableDebuggingChecks);
// thermal gradient specified via the TEMPVD keyword // thermal gradient specified via the TEMPVD keyword
NEW_PROP_TAG(EnableThermalFluxBoundaries); NEW_PROP_TAG(EnableThermalFluxBoundaries);
// Specify whether API tracking should be enabled (replaces PVT regions).
// TODO: This is not yet implemented
NEW_PROP_TAG(EnableApiTracking);
// The class which deals with ECL aquifers // The class which deals with ECL aquifers
NEW_PROP_TAG(EclAquiferModel); NEW_PROP_TAG(EclAquiferModel);
@ -229,6 +233,9 @@ SET_BOOL_PROP(EclBaseProblem, EnableGravity, true);
// only write the solutions for the report steps to disk // only write the solutions for the report steps to disk
SET_BOOL_PROP(EclBaseProblem, EnableWriteAllSolutions, false); SET_BOOL_PROP(EclBaseProblem, EnableWriteAllSolutions, false);
// disable API tracking
SET_BOOL_PROP(EclBaseProblem, EnableApiTracking, false);
// The default for the end time of the simulation [s] // The default for the end time of the simulation [s]
// //
// By default, stop it after the universe will probably have stopped // By default, stop it after the universe will probably have stopped
@ -390,6 +397,7 @@ class EclProblem : public GET_PROP_TYPE(TypeTag, BaseProblem)
enum { enableTemperature = GET_PROP_VALUE(TypeTag, EnableTemperature) }; enum { enableTemperature = GET_PROP_VALUE(TypeTag, EnableTemperature) };
enum { enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy) }; enum { enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy) };
enum { enableThermalFluxBoundaries = GET_PROP_VALUE(TypeTag, EnableThermalFluxBoundaries) }; enum { enableThermalFluxBoundaries = GET_PROP_VALUE(TypeTag, EnableThermalFluxBoundaries) };
enum { enableApiTracking = GET_PROP_VALUE(TypeTag, EnableApiTracking) };
enum { gasPhaseIdx = FluidSystem::gasPhaseIdx }; enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
enum { oilPhaseIdx = FluidSystem::oilPhaseIdx }; enum { oilPhaseIdx = FluidSystem::oilPhaseIdx };
enum { waterPhaseIdx = FluidSystem::waterPhaseIdx }; enum { waterPhaseIdx = FluidSystem::waterPhaseIdx };
@ -1325,12 +1333,10 @@ public:
template <class Context> template <class Context>
Scalar temperature(const Context& context, unsigned spaceIdx, unsigned timeIdx) const Scalar temperature(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
{ {
// use the temporally constant temperature, i.e. use the initial temperature of // use the initial temperature of the DOF if temperature is not a primary
// the DOF // variable
unsigned globalDofIdx = context.globalSpaceIndex(spaceIdx, timeIdx); unsigned globalDofIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
if (!initialFluidStates_.empty()) return initialFluidStates_[globalDofIdx].temperature(/*phaseIdx=*/0);
return initialFluidStates_[globalDofIdx].temperature(/*phaseIdx=*/0);
return initialTemperature_[globalDofIdx];
} }
/*! /*!
@ -1357,7 +1363,7 @@ public:
values.setThermalFlow(context, spaceIdx, timeIdx, initialFluidStates_[globalDofIdx]); values.setThermalFlow(context, spaceIdx, timeIdx, initialFluidStates_[globalDofIdx]);
} }
if (hasFreeBoundaryConditions()) { if (nonTrivialBoundaryConditions()) {
unsigned indexInInside = context.intersection(spaceIdx).indexInInside(); unsigned indexInInside = context.intersection(spaceIdx).indexInInside();
unsigned interiorDofIdx = context.interiorScvIndex(spaceIdx, timeIdx); unsigned interiorDofIdx = context.interiorScvIndex(spaceIdx, timeIdx);
unsigned globalDofIdx = context.globalSpaceIndex(interiorDofIdx, timeIdx); unsigned globalDofIdx = context.globalSpaceIndex(interiorDofIdx, timeIdx);
@ -1612,8 +1618,8 @@ public:
return (oilVaporizationControl.getType() == Opm::OilVaporizationEnum::VAPPARS); return (oilVaporizationControl.getType() == Opm::OilVaporizationEnum::VAPPARS);
} }
bool hasFreeBoundaryConditions() const bool nonTrivialBoundaryConditions() const
{ return hasFreeBoundaryConditions_; } { return nonTrivialBoundaryConditions_; }
/*! /*!
* \brief Propose the size of the next time step to the simulator. * \brief Propose the size of the next time step to the simulator.
@ -1686,6 +1692,11 @@ private:
{ {
const auto& deck = this->simulator().vanguard().deck(); const auto& deck = this->simulator().vanguard().deck();
if (enableApiTracking)
throw std::logic_error("API tracking is not yet implemented but requested at compile time.");
if (!enableApiTracking && deck.hasKeyword("API"))
throw std::logic_error("The simulator is build with API tracking disabled, but API tracking is requested by the deck.");
if (enableSolvent && !deck.hasKeyword("SOLVENT")) if (enableSolvent && !deck.hasKeyword("SOLVENT"))
throw std::runtime_error("The simulator requires the solvent option to be enabled, but the deck does not."); throw std::runtime_error("The simulator requires the solvent option to be enabled, but the deck does not.");
else if (!enableSolvent && deck.hasKeyword("SOLVENT")) else if (!enableSolvent && deck.hasKeyword("SOLVENT"))
@ -2538,18 +2549,11 @@ private:
void readBoundaryConditions_() void readBoundaryConditions_()
{ {
hasFreeBoundaryConditions_ = false; nonTrivialBoundaryConditions_ = false;
readBoundaryConditionKeyword_("FREEBCX", freebcX_);
readBoundaryConditionKeyword_("FREEBCX-", freebcXMinus_);
readBoundaryConditionKeyword_("FREEBCY", freebcY_);
readBoundaryConditionKeyword_("FREEBCY-", freebcYMinus_);
readBoundaryConditionKeyword_("FREEBCZ", freebcZ_);
readBoundaryConditionKeyword_("FREEBCZ-", freebcZMinus_);
const auto& vanguard = this->simulator().vanguard(); const auto& vanguard = this->simulator().vanguard();
if (vanguard.deck().hasKeyword("BCRATE")) { if (vanguard.deck().hasKeyword("BC")) {
hasFreeBoundaryConditions_ = true; nonTrivialBoundaryConditions_ = true;
size_t numCartDof = vanguard.cartesianSize(); size_t numCartDof = vanguard.cartesianSize();
unsigned numElems = vanguard.gridView().size(/*codim=*/0); unsigned numElems = vanguard.gridView().size(/*codim=*/0);
std::vector<int> cartesianToCompressedElemIdx(numCartDof); std::vector<int> cartesianToCompressedElemIdx(numCartDof);
@ -2563,14 +2567,21 @@ private:
massratebcY_.resize(numElems, 0.0); massratebcY_.resize(numElems, 0.0);
massratebcZMinus_.resize(numElems, 0.0); massratebcZMinus_.resize(numElems, 0.0);
massratebcZ_.resize(numElems, 0.0); massratebcZ_.resize(numElems, 0.0);
freebcX_.resize(numElems, false);
freebcXMinus_.resize(numElems, false);
freebcY_.resize(numElems, false);
freebcYMinus_.resize(numElems, false);
freebcZ_.resize(numElems, false);
freebcZMinus_.resize(numElems, false);
const auto& ratebcs = vanguard.deck().getKeywordList("BCRATE"); const auto& bcs = vanguard.deck().getKeywordList("BC");
for (size_t listIdx = 0; listIdx < ratebcs.size(); ++listIdx) { for (size_t listIdx = 0; listIdx < bcs.size(); ++listIdx) {
const auto& ratebc = *ratebcs[listIdx]; const auto& bc = *bcs[listIdx];
for (size_t record = 0; record < ratebc.size(); ++record) { for (size_t record = 0; record < bc.size(); ++record) {
std::string compName = ratebc.getRecord(record).getItem("COMPONENT").getTrimmedString(0); std::string type = bc.getRecord(record).getItem("TYPE").getTrimmedString(0);
std::string compName = bc.getRecord(record).getItem("COMPONENT").getTrimmedString(0);
int compIdx = -999; int compIdx = -999;
if (compName == "OIL") if (compName == "OIL")
@ -2582,77 +2593,95 @@ private:
else if (compName == "SOLVENT") else if (compName == "SOLVENT")
{ {
if (!enableSolvent) if (!enableSolvent)
throw std::logic_error("solvent is disabled and you're trying to add solvent to BCRATE"); throw std::logic_error("solvent is disabled and you're trying to add solvent to BC");
compIdx = Indices::solventSaturationIdx; compIdx = Indices::solventSaturationIdx;
} }
else if (compName == "POLYMER") else if (compName == "POLYMER")
{ {
if (!enablePolymer) if (!enablePolymer)
throw std::logic_error("polymer is disabled and you're trying to add polymer to BCRATE"); throw std::logic_error("polymer is disabled and you're trying to add polymer to BC");
compIdx = Indices::polymerConcentrationIdx; compIdx = Indices::polymerConcentrationIdx;
} }
else if (compName == "NONE")
{
if ( type == "RATE")
throw std::logic_error("you need to specify the component when RATE type is set in BC");
}
else else
throw std::logic_error("invalid component name for BCRATE"); throw std::logic_error("invalid component name for BC");
assert(compIdx >= 0);
std::string direction = ratebc.getRecord(record).getItem("DIRECTION").getTrimmedString(0); int i1 = bc.getRecord(record).getItem("I1").template get< int >(0) - 1;
std::vector<RateVector>* data = 0; int i2 = bc.getRecord(record).getItem("I2").template get< int >(0) - 1;
if (direction == "X-") int j1 = bc.getRecord(record).getItem("J1").template get< int >(0) - 1;
data = &massratebcXMinus_; int j2 = bc.getRecord(record).getItem("J2").template get< int >(0) - 1;
else if (direction == "X") int k1 = bc.getRecord(record).getItem("K1").template get< int >(0) - 1;
data = &massratebcX_; int k2 = bc.getRecord(record).getItem("K2").template get< int >(0) - 1;
else if (direction == "Y-") std::string direction = bc.getRecord(record).getItem("DIRECTION").getTrimmedString(0);
data = &massratebcYMinus_;
else if (direction == "Y")
data = &massratebcY_;
else if (direction == "Z-")
data = &massratebcZMinus_;
else if (direction == "Z")
data = &massratebcZ_;
else
throw std::logic_error("invalid direction for BCRATE");
int i1 = ratebc.getRecord(record).getItem("I1").template get< int >(0) - 1; if (type == "RATE") {
int i2 = ratebc.getRecord(record).getItem("I2").template get< int >(0) - 1; assert(compIdx >= 0);
int j1 = ratebc.getRecord(record).getItem("J1").template get< int >(0) - 1; std::vector<RateVector>* data = 0;
int j2 = ratebc.getRecord(record).getItem("J2").template get< int >(0) - 1; if (direction == "X-")
int k1 = ratebc.getRecord(record).getItem("K1").template get< int >(0) - 1; data = &massratebcXMinus_;
int k2 = ratebc.getRecord(record).getItem("K2").template get< int >(0) - 1; else if (direction == "X")
const Evaluation rate = ratebc.getRecord(record).getItem("RATE").getSIDouble(0); data = &massratebcX_;
for (int i = i1; i <= i2; ++i) { else if (direction == "Y-")
for (int j = j1; j <= j2; ++j) { data = &massratebcYMinus_;
for (int k = k1; k <= k2; ++k) { else if (direction == "Y")
std::array<int, 3> tmp = {i,j,k}; data = &massratebcY_;
size_t elemIdx = cartesianToCompressedElemIdx[vanguard.cartesianIndex(tmp)]; else if (direction == "Z-")
(*data)[elemIdx][compIdx] = rate; data = &massratebcZMinus_;
else if (direction == "Z")
data = &massratebcZ_;
else
throw std::logic_error("invalid direction for BC");
const Evaluation rate = bc.getRecord(record).getItem("RATE").getSIDouble(0);
for (int i = i1; i <= i2; ++i) {
for (int j = j1; j <= j2; ++j) {
for (int k = k1; k <= k2; ++k) {
std::array<int, 3> tmp = {i,j,k};
size_t elemIdx = cartesianToCompressedElemIdx[vanguard.cartesianIndex(tmp)];
(*data)[elemIdx][compIdx] = rate;
}
} }
} }
} else if (type == "FREE") {
std::vector<bool>* data = 0;
if (direction == "X-")
data = &freebcXMinus_;
else if (direction == "X")
data = &freebcX_;
else if (direction == "Y-")
data = &freebcYMinus_;
else if (direction == "Y")
data = &freebcY_;
else if (direction == "Z-")
data = &freebcZMinus_;
else if (direction == "Z")
data = &freebcZ_;
else
throw std::logic_error("invalid direction for BC");
for (int i = i1; i <= i2; ++i) {
for (int j = j1; j <= j2; ++j) {
for (int k = k1; k <= k2; ++k) {
std::array<int, 3> tmp = {i,j,k};
size_t elemIdx = cartesianToCompressedElemIdx[vanguard.cartesianIndex(tmp)];
(*data)[elemIdx] = true;
}
}
}
} else {
throw std::logic_error("invalid type for BC. Use FREE or RATE");
} }
} }
} }
} }
} }
void readBoundaryConditionKeyword_(const std::string& name, std::vector<bool>& compressedData)
{
const auto& eclProps = this->simulator().vanguard().eclState().get3DProperties();
const auto& vanguard = this->simulator().vanguard();
unsigned numElems = vanguard.gridView().size(/*codim=*/0);
compressedData.resize(numElems, false);
if (eclProps.hasDeckDoubleGridProperty(name)) {
const std::vector<double>& data = eclProps.getDoubleGridProperty(name).getData();
for (unsigned elemIdx = 0; elemIdx < numElems; ++elemIdx) {
unsigned cartElemIdx = vanguard.cartesianIndex(elemIdx);
compressedData[elemIdx] = (data[cartElemIdx] > 0);
}
hasFreeBoundaryConditions_ = true;
}
}
// this method applies the runtime constraints specified via the deck and/or command // this method applies the runtime constraints specified via the deck and/or command
// line parameters for the size of the next time step size. // line parameters for the size of the next time step size.
Scalar limitNextTimeStepSize_(Scalar dtNext) const Scalar limitNextTimeStepSize_(Scalar dtNext) const
@ -2719,7 +2748,6 @@ private:
std::vector<Scalar> maxPolymerAdsorption_; std::vector<Scalar> maxPolymerAdsorption_;
std::vector<InitialFluidState> initialFluidStates_; std::vector<InitialFluidState> initialFluidStates_;
std::vector<Scalar> initialTemperature_;
std::vector<Scalar> polymerConcentration_; std::vector<Scalar> polymerConcentration_;
// polymer molecular weight // polymer molecular weight
@ -2744,7 +2772,7 @@ private:
PffGridVector<GridView, Stencil, PffDofData_, DofMapper> pffDofData_; PffGridVector<GridView, Stencil, PffDofData_, DofMapper> pffDofData_;
TracerModel tracerModel_; TracerModel tracerModel_;
bool hasFreeBoundaryConditions_; bool nonTrivialBoundaryConditions_;
std::vector<bool> freebcX_; std::vector<bool> freebcX_;
std::vector<bool> freebcXMinus_; std::vector<bool> freebcXMinus_;
std::vector<bool> freebcY_; std::vector<bool> freebcY_;

View File

@ -30,10 +30,14 @@
#include "tracervdtable.hh" #include "tracervdtable.hh"
#include <ewoms/models/blackoil/blackoilmodel.hh>
#include <dune/istl/operators.hh> #include <dune/istl/operators.hh>
#include <dune/istl/solvers.hh> #include <dune/istl/solvers.hh>
#include <dune/istl/preconditioners.hh> #include <dune/istl/preconditioners.hh>
#include <dune/common/version.hh>
#include <string> #include <string>
#include <vector> #include <vector>
#include <iostream> #include <iostream>

View File

@ -31,6 +31,7 @@
#include "collecttoiorank.hh" #include "collecttoiorank.hh"
#include "ecloutputblackoilmodule.hh" #include "ecloutputblackoilmodule.hh"
#include <ewoms/models/blackoil/blackoilmodel.hh>
#include <ewoms/disc/ecfv/ecfvdiscretization.hh> #include <ewoms/disc/ecfv/ecfvdiscretization.hh>
#include <ewoms/io/baseoutputwriter.hh> #include <ewoms/io/baseoutputwriter.hh>
#include <ewoms/parallel/tasklets.hh> #include <ewoms/parallel/tasklets.hh>

View File

@ -494,7 +494,9 @@ protected:
// TODO: Revise when linear solvers interface opm-core is done // TODO: Revise when linear solvers interface opm-core is done
// Construct linear solver. // Construct linear solver.
// GMRes solver // GMRes solver
int verbosity = ( isIORank_ ) ? parameters_.linear_solver_verbosity_ : 0; int verbosity = 0;
if (simulator_.gridView().comm().rank() == 0)
verbosity = parameters_.linear_solver_verbosity_;
if ( parameters_.newton_use_gmres_ ) { if ( parameters_.newton_use_gmres_ ) {
Dune::RestartedGMResSolver<Vector> linsolve(opA, sp, precond, Dune::RestartedGMResSolver<Vector> linsolve(opA, sp, precond,
@ -838,7 +840,6 @@ protected:
mutable int iterations_; mutable int iterations_;
mutable bool converged_; mutable bool converged_;
boost::any parallelInformation_; boost::any parallelInformation_;
bool isIORank_;
std::unique_ptr<Matrix> matrix_; std::unique_ptr<Matrix> matrix_;
Vector *rhs_; Vector *rhs_;

View File

@ -94,8 +94,6 @@ namespace MissingFeatures {
"CONNECTION", "CONNECTION",
"CPR", "CPR",
"DATE", "DATE",
"ECHO",
"EDITNNC",
"ENDACTIO", "ENDACTIO",
"ENDFIN" "ENDFIN"
"ENDNUM", "ENDNUM",
@ -131,7 +129,6 @@ namespace MissingFeatures {
"NETBALAN", "NETBALAN",
"NEXTSTEP", "NEXTSTEP",
"NOCASC", "NOCASC",
"NOECHO",
"NOGGF", "NOGGF",
"NOINSPEC", "NOINSPEC",
"NOMONITO", "NOMONITO",
@ -170,7 +167,6 @@ namespace MissingFeatures {
"RPTPROS", "RPTPROS",
"PRTRST", "PRTRST",
"RPTRUNSP", "RPTRUNSP",
"RPTSCHED",
"RPTSMRY", "RPTSMRY",
"RPTSOL", "RPTSOL",
"RSCONST", "RSCONST",
@ -205,7 +201,6 @@ namespace MissingFeatures {
"WPAVE", "WPAVE",
"WPITAB", "WPITAB",
"WTEMP", "WTEMP",
"WTEST",
"WTRACER", "WTRACER",
"ZIPPY2" }; "ZIPPY2" };
std::multimap<std::string, PartiallySupported<std::string> > string_options; std::multimap<std::string, PartiallySupported<std::string> > string_options;