make ebos AD aware

This commit is contained in:
Andreas Lauser 2015-05-21 16:18:45 +02:00
parent eba7e06bed
commit 2428ff41ae
6 changed files with 154 additions and 105 deletions

View File

@ -35,9 +35,8 @@
namespace Ewoms {
namespace Properties {
NEW_PROP_TAG(MaterialLaw);
}}
}
namespace Ewoms {
template <class TypeTag>
class EclTransIntensiveQuantities;
@ -96,13 +95,16 @@ class EclTransExtensiveQuantities
{
typedef typename GET_PROP_TYPE(TypeTag, ElementContext) ElementContext;
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
typedef typename GET_PROP_TYPE(TypeTag, Evaluation) Evaluation;
typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
enum { dimWorld = GridView::dimensionworld };
enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) };
typedef Opm::MathToolbox<Evaluation> Toolbox;
typedef Dune::FieldVector<Scalar, dimWorld> DimVector;
typedef Dune::FieldVector<Evaluation, dimWorld> EvalDimVector;
typedef Dune::FieldMatrix<Scalar, dimWorld, dimWorld> DimMatrix;
public:
@ -127,7 +129,7 @@ public:
*
* \param phaseIdx The index of the fluid phase
*/
const DimVector& potentialGrad(int phaseIdx) const
const EvalDimVector& potentialGrad(int phaseIdx) const
{
OPM_THROW(Opm::NotAvailable,
"The ECL transmissibility module does not provide explicit potential gradients");
@ -139,7 +141,7 @@ public:
*
* \param phaseIdx The index of the fluid phase
*/
const DimVector& filterVelocity(int phaseIdx) const
const EvalDimVector& filterVelocity(int phaseIdx) const
{
OPM_THROW(Opm::NotAvailable,
"The ECL transmissibility module does not provide explicit filter velocities");
@ -154,8 +156,8 @@ public:
*
* \param phaseIdx The index of the fluid phase
*/
Scalar volumeFlux(int phaseIdx) const
{ return - pressureDifferential_[phaseIdx]*mobility_[phaseIdx] * trans_/faceArea_; }
const Evaluation& volumeFlux(int phaseIdx) const
{ return volumeFlux_[phaseIdx]; }
protected:
/*!
@ -168,7 +170,7 @@ protected:
int upstreamIndex_(int phaseIdx) const
{
assert(0 <= phaseIdx && phaseIdx < numPhases);
return (pressureDifferential_[phaseIdx] >= 0)?exteriorDofIdx_:interiorDofIdx_;
return (Toolbox::value(pressureDifferential_[phaseIdx]) >= 0)?exteriorDofIdx_:interiorDofIdx_;
}
/*!
@ -181,7 +183,7 @@ protected:
int downstreamIndex_(int phaseIdx) const
{
assert(0 <= phaseIdx && phaseIdx < numPhases);
return (pressureDifferential_[phaseIdx] >= 0)?interiorDofIdx_:exteriorDofIdx_;
return (Toolbox::value(pressureDifferential_[phaseIdx]) >= 0)?interiorDofIdx_:exteriorDofIdx_;
}
/*!
@ -219,20 +221,30 @@ protected:
Scalar distZEx = zEx - zFace;
for (int phaseIdx=0; phaseIdx < numPhases; phaseIdx++) {
// calculate the hydrostatic pressures at the face's integration point
Scalar rhoIn = intQuantsIn.fluidState().density(phaseIdx);
Scalar rhoEx = intQuantsEx.fluidState().density(phaseIdx);
// do the gravity correction at the face's integration point
const Evaluation& rhoIn = intQuantsIn.fluidState().density(phaseIdx);
Scalar rhoEx = Toolbox::value(intQuantsEx.fluidState().density(phaseIdx));
Scalar pressureInterior = intQuantsIn.fluidState().pressure(phaseIdx);
Scalar pressureExterior = intQuantsEx.fluidState().pressure(phaseIdx);
Evaluation pressureInterior = intQuantsIn.fluidState().pressure(phaseIdx);
Scalar pressureExterior = Toolbox::value(intQuantsEx.fluidState().pressure(phaseIdx));
pressureInterior += - rhoIn*(g*distZIn);
pressureExterior += - rhoEx*(g*distZEx);
pressureDifferential_[phaseIdx] = pressureExterior - pressureInterior;
const auto& up = elemCtx.intensiveQuantities(upstreamIndex_(phaseIdx), timeIdx);
mobility_[phaseIdx] = up.mobility(phaseIdx);
// this is slightly hacky because in the automatic differentiation case, it
// only works for the element centered finite volume method. for ebos this
// does not matter, though.
int upstreamIdx = upstreamIndex_(phaseIdx);
const auto& up = elemCtx.intensiveQuantities(upstreamIdx, timeIdx);
if (upstreamIdx == interiorDofIdx_)
volumeFlux_[phaseIdx] =
pressureDifferential_[phaseIdx]*up.mobility(phaseIdx) * (- trans_/faceArea_);
else
volumeFlux_[phaseIdx] =
pressureDifferential_[phaseIdx]*(Toolbox::value(up.mobility(phaseIdx)) * (- trans_/faceArea_));
}
}
@ -252,12 +264,12 @@ protected:
// the area of the face between the DOFs [m^2]
Scalar faceArea_;
// the mobility of all phases [1 / (Pa s)]
Scalar mobility_[numPhases];
// the volumetric flux of all phases [m^3/s]
Evaluation volumeFlux_[numPhases];
// the difference in effective pressure between the two degrees of
// freedom [Pa]
Scalar pressureDifferential_[numPhases];
Evaluation pressureDifferential_[numPhases];
};
} // namespace Ewoms

View File

@ -24,6 +24,7 @@
#define EWOMS_ECL_OUTPUT_BLACK_OIL_MODULE_HH
#include "eclwriter.hh"
#include "ecldeckunits.hh"
#include <ewoms/io/baseoutputmodule.hh>
@ -54,9 +55,7 @@ SET_BOOL_PROP(EclOutputBlackOil, EclOutputWriteGasDissolutionFactor, true);
SET_BOOL_PROP(EclOutputBlackOil, EclOutputWriteGasFormationVolumeFactor, true);
SET_BOOL_PROP(EclOutputBlackOil, EclOutputWriteOilFormationVolumeFactor, true);
SET_BOOL_PROP(EclOutputBlackOil, EclOutputWriteOilSaturationPressure, true);
}} // namespace Ewoms, Properties
namespace Ewoms {
} // namespace Properties
// forward declaration
template <class TypeTag>
@ -76,6 +75,7 @@ class EclOutputBlackOilModule : public BaseOutputModule<TypeTag>
typedef typename GET_PROP_TYPE(TypeTag, Simulator) Simulator;
typedef typename GET_PROP_TYPE(TypeTag, Discretization) Discretization;
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
typedef typename GET_PROP_TYPE(TypeTag, Evaluation) Evaluation;
typedef typename GET_PROP_TYPE(TypeTag, ElementContext) ElementContext;
typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
@ -156,6 +156,8 @@ public:
*/
void processElement(const ElementContext &elemCtx)
{
typedef Opm::MathToolbox<Evaluation> Toolbox;
if (!std::is_same<Discretization, Ewoms::EcfvDiscretization<TypeTag> >::value)
return;
@ -163,20 +165,20 @@ public:
const auto &fs = elemCtx.intensiveQuantities(dofIdx, /*timeIdx=*/0).fluidState();
int globalDofIdx = elemCtx.globalSpaceIndex(dofIdx, /*timeIdx=*/0);
int regionIdx = elemCtx.primaryVars(dofIdx, /*timeIdx=*/0).pvtRegionIndex();
Scalar po = fs.pressure(oilPhaseIdx);
Scalar To = fs.temperature(oilPhaseIdx);
Scalar XoG = fs.massFraction(oilPhaseIdx, gasCompIdx);
Scalar XgO = fs.massFraction(gasPhaseIdx, oilCompIdx);
Scalar po = Toolbox::value(fs.pressure(oilPhaseIdx));
Scalar To = Toolbox::value(fs.temperature(oilPhaseIdx));
Scalar XoG = Toolbox::value(fs.massFraction(oilPhaseIdx, gasCompIdx));
Scalar XgO = Toolbox::value(fs.massFraction(gasPhaseIdx, oilCompIdx));
if (saturationsOutput_()) {
for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
saturation_[phaseIdx][globalDofIdx] = fs.saturation(phaseIdx);
saturation_[phaseIdx][globalDofIdx] = Toolbox::value(fs.saturation(phaseIdx));
Valgrind::CheckDefined(saturation_[phaseIdx][globalDofIdx]);
}
}
if (pressuresOutput_()) {
for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
pressure_[phaseIdx][globalDofIdx] = fs.pressure(phaseIdx) / 1e5;
pressure_[phaseIdx][globalDofIdx] = Toolbox::value(fs.pressure(phaseIdx));
Valgrind::CheckDefined(pressure_[phaseIdx][globalDofIdx]);
}
}

View File

@ -46,9 +46,8 @@ NEW_PROP_TAG(RateVector);
NEW_PROP_TAG(GridView);
NEW_PROP_TAG(NumPhases);
NEW_PROP_TAG(NumComponents);
}}
}
namespace Ewoms {
template <class TypeTag>
class EcfvDiscretization;
@ -83,6 +82,7 @@ class EclPeacemanWell : public BaseAuxiliaryModule<TypeTag>
typedef typename GET_PROP_TYPE(TypeTag, GlobalEqVector) GlobalEqVector;
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
typedef typename GET_PROP_TYPE(TypeTag, Evaluation) Evaluation;
typedef typename GET_PROP_TYPE(TypeTag, Discretization) Discretization;
typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
typedef typename GET_PROP_TYPE(TypeTag, Simulator) Simulator;
@ -91,6 +91,7 @@ class EclPeacemanWell : public BaseAuxiliaryModule<TypeTag>
typedef typename GET_PROP_TYPE(TypeTag, RateVector) RateVector;
typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
typedef Opm::MathToolbox<Evaluation> Toolbox;
typedef typename GridView::template Codim<0>::EntityPointer ElementPointer;
// the dimension of the simulator's world
@ -179,19 +180,19 @@ class EclPeacemanWell : public BaseAuxiliaryModule<TypeTag>
//////////////
// the phase pressures inside a DOF
std::array<Scalar, numPhases> pressure;
std::array<Evaluation, numPhases> pressure;
// the phase densities at the DOF
std::array<Scalar, numPhases> density;
std::array<Evaluation, numPhases> density;
// the phase mobilities of the DOF
std::array<Scalar, numPhases> mobility;
std::array<Evaluation, numPhases> mobility;
// the composition of the oil phase at the DOF
std::array<Scalar, numComponents> oilMassFraction;
std::array<Evaluation, numComponents> oilMassFraction;
// the composition of the gas phase at the DOF
std::array<Scalar, numComponents> gasMassFraction;
std::array<Evaluation, numComponents> gasMassFraction;
std::shared_ptr<ElementPointer> elementPtr;
int localDofIdx;
@ -323,7 +324,7 @@ public:
for (int priVarIdx = 0; priVarIdx < numModelEq; ++priVarIdx) {
// calculate the derivative of the well equation w.r.t. the current
// primary variable using forward differences
Scalar eps = 1e-6*std::max(1.0, priVars[priVarIdx]);
Scalar eps = 1e-6*std::max<Scalar>(1.0, priVars[priVarIdx]);
priVars[priVarIdx] += eps;
elemCtx.updateIntensiveQuantities(priVars, dofVars.localDofIdx, /*timeIdx=*/0);
@ -351,7 +352,7 @@ public:
const auto& fluidState = elemCtx.intensiveQuantities(dofVars.localDofIdx, /*timeIdx=*/0).fluidState();
// first, we need the source term of the grid for the slightly disturbed well.
Scalar eps = std::max(1e5, actualBottomHolePressure_)*1e-8;
Scalar eps = std::max<Scalar>(1e5, actualBottomHolePressure_)*1e-8;
computeVolumetricDofRates_(resvRates, actualBottomHolePressure_ + eps, dofVariables_[gridDofIdx]);
for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
modelRate.setVolumetricRate(fluidState, phaseIdx, resvRates[phaseIdx]);
@ -366,7 +367,8 @@ public:
}
// and finally, we divide by the epsilon to get the derivative
q /= eps;
for (int eqIdx = 0; eqIdx < numModelEq; ++eqIdx)
q[eqIdx] /= eps;
// now we put this derivative into the right place in the Jacobian
// matrix. This is a bit hacky because it assumes that the model uses a mass
@ -378,13 +380,13 @@ public:
auto &matrixEntry = matrix[gridDofIdx][wellGlobalDofIdx];
matrixEntry = 0.0;
for (int eqIdx = 0; eqIdx < numModelEq; ++ eqIdx)
matrixEntry[eqIdx][0] = - q[eqIdx]/dofVars.totalVolume;
matrixEntry[eqIdx][0] = - Toolbox::value(q[eqIdx])/dofVars.totalVolume;
//
/////////////
}
// effect of changing the well's bottom hole pressure on the well equation
Scalar eps = std::min(1e7, std::max(1e6, targetBottomHolePressure_))*1e-8;
Scalar eps = std::min<Scalar>(1e7, std::max<Scalar>(1e6, targetBottomHolePressure_))*1e-8;
Scalar wellResidStar = wellResidual_(actualBottomHolePressure_ + eps);
diagBlock[0][0] = (wellResidStar - wellResid)/eps;
}
@ -937,7 +939,7 @@ public:
int wellGlobalDof = AuxModule::localToGlobalDof(/*localDofIdx=*/0);
// retrieve the bottom hole pressure from the global system of equations
actualBottomHolePressure_ = dofVariables_.begin()->second.pressure[0];
actualBottomHolePressure_ = Toolbox::value(dofVariables_.begin()->second.pressure[0]);
actualBottomHolePressure_ = computeRateEquivalentBhp_();
sol[wellGlobalDof][0] = actualBottomHolePressure_;
@ -1017,7 +1019,7 @@ public:
tmp.update(context.intensiveQuantities(dofIdx, timeIdx));
std::array<Scalar, numPhases> volumetricRates;
std::array<Evaluation, numPhases> volumetricRates;
computeVolumetricDofRates_(volumetricRates, actualBottomHolePressure_, tmp);
// convert to mass rates
@ -1027,6 +1029,7 @@ public:
modelRate.setVolumetricRate(intQuants.fluidState(), phaseIdx, volumetricRates[phaseIdx]);
q += modelRate;
}
Valgrind::CheckDefined(q);
}
@ -1061,10 +1064,13 @@ protected:
dofVars.connectionTransmissibilityFactor = exposureFactor*Kh/(std::log(r0 / rWell) + S);
}
void computeVolumetricDofRates_(std::array<Scalar, numPhases> &volRates,
template <class Eval>
void computeVolumetricDofRates_(std::array<Eval, numPhases> &volRates,
Scalar bottomHolePressure,
const DofVariables& dofVars) const
{
typedef Opm::MathToolbox<Evaluation> Toolbox;
for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
volRates[phaseIdx] = 0.0;
@ -1082,14 +1088,14 @@ protected:
// well model due to Peaceman; see Chen et al., p. 449
// phase pressure in grid cell
Scalar p = dofVars.pressure[phaseIdx];
const Eval& p = Toolbox::template toLhs<Eval>(dofVars.pressure[phaseIdx]);
// density and mobility of fluid phase
Scalar rho = dofVars.density[phaseIdx];
Scalar lambda;
const Eval& rho = Toolbox::template toLhs<Eval>(dofVars.density[phaseIdx]);
Eval lambda;
if (wellType_ == Producer) {
//assert(p < pbh);
lambda = dofVars.mobility[phaseIdx];
lambda = Toolbox::template toLhs<Eval>(dofVars.mobility[phaseIdx]);
}
else if (wellType_ == Injector) {
//assert(p > pbh);
@ -1102,7 +1108,7 @@ protected:
// 1/viscosity...
lambda = 0.0;
for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
lambda += dofVars.mobility[phaseIdx];
lambda += Toolbox::template toLhs<Eval>(dofVars.mobility[phaseIdx]);
}
else
OPM_THROW(std::logic_error,
@ -1117,7 +1123,7 @@ protected:
Valgrind::CheckDefined(refDepth_);
// pressure in the borehole ("hole pressure") at the given location
Scalar ph = pbh + rho*g*(depth - refDepth_);
Eval ph = pbh + rho*g*(depth - refDepth_);
// volumetric reservoir rate for the phase
volRates[phaseIdx] = Twj*lambda*(ph - p);
@ -1167,34 +1173,34 @@ protected:
surfaceRates[oilPhaseIdx] =
// oil in gas phase
reservoirRate[gasPhaseIdx]
* dofVars.density[gasPhaseIdx]
* dofVars.gasMassFraction[oilCompIdx]
* Toolbox::value(dofVars.density[gasPhaseIdx])
* Toolbox::value(dofVars.gasMassFraction[oilCompIdx])
/ rhoOilSurface
+
// oil in oil phase
reservoirRate[oilPhaseIdx]
* dofVars.density[oilPhaseIdx]
* dofVars.oilMassFraction[oilCompIdx]
* Toolbox::value(dofVars.density[oilPhaseIdx])
* Toolbox::value(dofVars.oilMassFraction[oilCompIdx])
/ rhoOilSurface;
// gas
surfaceRates[gasPhaseIdx] =
// gas in gas phase
reservoirRate[gasPhaseIdx]
* dofVars.density[gasPhaseIdx]
* dofVars.gasMassFraction[gasCompIdx]
* Toolbox::value(dofVars.density[gasPhaseIdx])
* Toolbox::value(dofVars.gasMassFraction[gasCompIdx])
/ rhoGasSurface
+
// gas in oil phase
reservoirRate[oilPhaseIdx]
* dofVars.density[oilPhaseIdx]
* dofVars.oilMassFraction[gasCompIdx]
* Toolbox::value(dofVars.density[oilPhaseIdx])
* Toolbox::value(dofVars.oilMassFraction[gasCompIdx])
/ rhoGasSurface;
// water
surfaceRates[waterPhaseIdx] =
reservoirRate[waterPhaseIdx]
* dofVars.density[waterPhaseIdx]
* Toolbox::value(dofVars.density[waterPhaseIdx])
/ rhoWaterSurface;
}
@ -1389,17 +1395,17 @@ protected:
if (wellType_ == Injector) {
// for injectors the computed rates are positive and the target BHP is the
// maximum allowed pressure ...
result = std::min(maxSurfaceRate - surfaceRate, result);
result = std::min(maxResvRate - resvRate, result);
result = std::min(1e-7*(targetBottomHolePressure_ - bhp), result);
result = std::min<Scalar>(maxSurfaceRate - surfaceRate, result);
result = std::min<Scalar>(maxResvRate - resvRate, result);
result = std::min<Scalar>(1e-7*(targetBottomHolePressure_ - bhp), result);
}
else {
assert(wellType_ == Producer);
// ... for producers the rates are negative and the bottom hole pressure is
// is the minimum
result = std::min(maxSurfaceRate + surfaceRate, result);
result = std::min(maxResvRate + resvRate, result);
result = std::min(1e-7*(bhp - targetBottomHolePressure_), result);
result = std::min<Scalar>(maxSurfaceRate + surfaceRate, result);
result = std::min<Scalar>(maxResvRate + resvRate, result);
result = std::min<Scalar>(1e-7*(bhp - targetBottomHolePressure_), result);
}
const Scalar scalingFactor = 1e-3;

View File

@ -24,6 +24,8 @@
#ifndef EWOMS_ECL_PROBLEM_HH
#define EWOMS_ECL_PROBLEM_HH
#include <opm/material/localad/Evaluation.hpp>
#include "eclgridmanager.hh"
#include "eclwellmanager.hh"
#include "eclwriter.hh"
@ -93,19 +95,23 @@ SET_PROP(EclBaseProblem, MaterialLaw)
private:
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
typedef typename GET_PROP_TYPE(TypeTag, Evaluation) Evaluation;
typedef Opm::TwoPhaseMaterialTraits<Scalar,
/*wettingPhaseIdx=*/FluidSystem::waterPhaseIdx,
/*nonWettingPhaseIdx=*/FluidSystem::oilPhaseIdx> OilWaterTraits;
/*nonWettingPhaseIdx=*/FluidSystem::oilPhaseIdx,
Evaluation> OilWaterTraits;
typedef Opm::TwoPhaseMaterialTraits<Scalar,
/*wettingPhaseIdx=*/FluidSystem::oilPhaseIdx,
/*nonWettingPhaseIdx=*/FluidSystem::gasPhaseIdx> GasOilTraits;
/*nonWettingPhaseIdx=*/FluidSystem::gasPhaseIdx,
Evaluation> GasOilTraits;
typedef Opm::ThreePhaseMaterialTraits<Scalar,
/*wettingPhaseIdx=*/FluidSystem::waterPhaseIdx,
/*nonWettingPhaseIdx=*/FluidSystem::oilPhaseIdx,
/*gasPhaseIdx=*/FluidSystem::gasPhaseIdx> Traits;
/*gasPhaseIdx=*/FluidSystem::gasPhaseIdx,
Evaluation> Traits;
typedef typename Opm::PiecewiseLinearTwoPhaseMaterial<OilWaterTraits> OilWaterLaw;
typedef typename Opm::PiecewiseLinearTwoPhaseMaterial<GasOilTraits> GasOilLaw;
@ -173,9 +179,8 @@ SET_STRING_PROP(EclBaseProblem, GridFile, "data/ecl.DATA");
// between writing restart files
SET_INT_PROP(EclBaseProblem, RestartWritingInterval, 0xffffff); // disable
}} // namespace Properties, Opm
} // namespace Properties
namespace Ewoms {
/*!
* \ingroup EclBlackOilSimulator
*
@ -196,6 +201,7 @@ class EclProblem : public GET_PROP_TYPE(TypeTag, BaseProblem)
enum { dimWorld = GridView::dimensionworld };
// copy some indices for convenience
enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
enum { numPhases = FluidSystem::numPhases };
enum { numComponents = FluidSystem::numComponents };
enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
@ -209,12 +215,13 @@ class EclProblem : public GET_PROP_TYPE(TypeTag, BaseProblem)
typedef typename GET_PROP_TYPE(TypeTag, RateVector) RateVector;
typedef typename GET_PROP_TYPE(TypeTag, BoundaryRateVector) BoundaryRateVector;
typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
typedef typename GET_PROP_TYPE(TypeTag, BlackOilFluidState) BlackOilFluidState;
typedef typename GET_PROP_TYPE(TypeTag, Simulator) Simulator;
typedef typename GET_PROP_TYPE(TypeTag, MaterialLawParams) MaterialLawParams;
typedef typename GET_PROP_TYPE(TypeTag, Evaluation) Evaluation;
typedef Opm::CompositionalFluidState<Scalar, FluidSystem> ScalarFluidState;
typedef Opm::MathToolbox<Evaluation> Toolbox;
typedef Ewoms::EclSummaryWriter<TypeTag> EclSummaryWriter;
typedef Dune::FieldMatrix<Scalar, dimWorld, dimWorld> DimMatrix;
struct RockParams {
@ -663,13 +670,18 @@ public:
int spaceIdx,
int timeIdx) const
{
rate = 0;
rate = Toolbox::createConstant(0);
for (int eqIdx = 0; eqIdx < numEq; ++ eqIdx)
rate[eqIdx] = Toolbox::createConstant(0.0);
wellManager_.computeTotalRatesForDof(rate, context, spaceIdx, timeIdx);
// convert the source term from the total mass rate of the
// cell to the one per unit of volume as used by the model.
int globalDofIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
rate /= this->model().dofTotalVolume(globalDofIdx);
for (int eqIdx = 0; eqIdx < numEq; ++ eqIdx)
rate[eqIdx] /= this->model().dofTotalVolume(globalDofIdx);
}
//! \}
@ -901,29 +913,29 @@ private:
regionIdx);
}
typedef std::shared_ptr<const Opm::GasPvtInterface<Scalar> > GasPvtSharedPtr;
typedef std::shared_ptr<const Opm::GasPvtInterface<Scalar, Evaluation> > GasPvtSharedPtr;
GasPvtSharedPtr gasPvt(createGasPvt_(deck, eclState));
FluidSystem::setGasPvt(gasPvt);
typedef std::shared_ptr<const Opm::OilPvtInterface<Scalar> > OilPvtSharedPtr;
typedef std::shared_ptr<const Opm::OilPvtInterface<Scalar, Evaluation> > OilPvtSharedPtr;
OilPvtSharedPtr oilPvt(createOilPvt_(deck, eclState));
FluidSystem::setOilPvt(oilPvt);
typedef std::shared_ptr<const Opm::WaterPvtInterface<Scalar> > WaterPvtSharedPtr;
typedef std::shared_ptr<const Opm::WaterPvtInterface<Scalar, Evaluation> > WaterPvtSharedPtr;
WaterPvtSharedPtr waterPvt(createWaterPvt_(deck, eclState));
FluidSystem::setWaterPvt(waterPvt);
FluidSystem::initEnd();
}
Opm::OilPvtInterface<Scalar>* createOilPvt_(Opm::DeckConstPtr deck,
Opm::EclipseStateConstPtr eclState)
Opm::OilPvtInterface<Scalar, Evaluation>* createOilPvt_(Opm::DeckConstPtr deck,
Opm::EclipseStateConstPtr eclState)
{
Opm::DeckKeywordConstPtr densityKeyword = deck->getKeyword("DENSITY");
int numPvtRegions = densityKeyword->size();
if (deck->hasKeyword("PVTO")) {
Opm::LiveOilPvt<Scalar> *oilPvt = new Opm::LiveOilPvt<Scalar>;
Opm::LiveOilPvt<Scalar, Evaluation> *oilPvt = new Opm::LiveOilPvt<Scalar, Evaluation>;
oilPvt->setNumRegions(numPvtRegions);
for (int regionIdx = 0; regionIdx < numPvtRegions; ++regionIdx)
@ -933,7 +945,7 @@ private:
return oilPvt;
}
else if (deck->hasKeyword("PVDO")) {
Opm::DeadOilPvt<Scalar> *oilPvt = new Opm::DeadOilPvt<Scalar>;
Opm::DeadOilPvt<Scalar, Evaluation> *oilPvt = new Opm::DeadOilPvt<Scalar, Evaluation>;
oilPvt->setNumRegions(numPvtRegions);
for (int regionIdx = 0; regionIdx < numPvtRegions; ++regionIdx)
@ -943,8 +955,8 @@ private:
return oilPvt;
}
else if (deck->hasKeyword("PVCDO")) {
Opm::ConstantCompressibilityOilPvt<Scalar> *oilPvt =
new Opm::ConstantCompressibilityOilPvt<Scalar>;
Opm::ConstantCompressibilityOilPvt<Scalar, Evaluation> *oilPvt =
new Opm::ConstantCompressibilityOilPvt<Scalar, Evaluation>;
oilPvt->setNumRegions(numPvtRegions);
for (int regionIdx = 0; regionIdx < numPvtRegions; ++regionIdx)
@ -959,14 +971,14 @@ private:
OPM_THROW(std::logic_error, "Not implemented: Oil PVT of this deck!");
}
Opm::GasPvtInterface<Scalar>* createGasPvt_(Opm::DeckConstPtr deck,
Opm::EclipseStateConstPtr eclState)
Opm::GasPvtInterface<Scalar, Evaluation>* createGasPvt_(Opm::DeckConstPtr deck,
Opm::EclipseStateConstPtr eclState)
{
Opm::DeckKeywordConstPtr densityKeyword = deck->getKeyword("DENSITY");
int numPvtRegions = densityKeyword->size();
if (deck->hasKeyword("PVTG")) {
Opm::WetGasPvt<Scalar> *gasPvt = new Opm::WetGasPvt<Scalar>;
Opm::WetGasPvt<Scalar, Evaluation> *gasPvt = new Opm::WetGasPvt<Scalar, Evaluation>;
gasPvt->setNumRegions(numPvtRegions);
for (int regionIdx = 0; regionIdx < numPvtRegions; ++regionIdx)
@ -976,7 +988,7 @@ private:
return gasPvt;
}
else if (deck->hasKeyword("PVDG")) {
Opm::DryGasPvt<Scalar> *gasPvt = new Opm::DryGasPvt<Scalar>;
Opm::DryGasPvt<Scalar, Evaluation> *gasPvt = new Opm::DryGasPvt<Scalar, Evaluation>;
gasPvt->setNumRegions(numPvtRegions);
for (int regionIdx = 0; regionIdx < numPvtRegions; ++regionIdx)
@ -988,15 +1000,15 @@ private:
OPM_THROW(std::logic_error, "Not implemented: Gas PVT of this deck!");
}
Opm::WaterPvtInterface<Scalar>* createWaterPvt_(Opm::DeckConstPtr deck,
Opm::EclipseStateConstPtr eclState)
Opm::WaterPvtInterface<Scalar, Evaluation>* createWaterPvt_(Opm::DeckConstPtr deck,
Opm::EclipseStateConstPtr eclState)
{
Opm::DeckKeywordConstPtr densityKeyword = deck->getKeyword("DENSITY");
int numPvtRegions = densityKeyword->size();
if (deck->hasKeyword("PVTW")) {
Opm::ConstantCompressibilityWaterPvt<Scalar> *waterPvt =
new Opm::ConstantCompressibilityWaterPvt<Scalar>;
Opm::ConstantCompressibilityWaterPvt<Scalar, Evaluation> *waterPvt =
new Opm::ConstantCompressibilityWaterPvt<Scalar, Evaluation>;
waterPvt->setNumRegions(numPvtRegions);
for (int regionIdx = 0; regionIdx < numPvtRegions; ++regionIdx)
@ -1082,7 +1094,6 @@ private:
Scalar temperature = tempiData[cartesianDofIdx];
if (!std::isfinite(temperature) || temperature <= 0)
temperature = FluidSystem::surfaceTemperature;
dofFluidState.setTemperature(temperature);
//////
@ -1107,6 +1118,8 @@ private:
Scalar pc[numPhases];
const auto& matParams = materialLawParams_(dofIdx);
MaterialLaw::capillaryPressures(pc, matParams, dofFluidState);
Valgrind::CheckDefined(oilPressure);
Valgrind::CheckDefined(pc);
for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
dofFluidState.setPressure(phaseIdx, oilPressure + (pc[phaseIdx] - pc[oilPhaseIdx]));
Scalar gasPressure = dofFluidState.pressure(gasPhaseIdx);
@ -1134,7 +1147,9 @@ private:
// note that we use the gas pressure here. this is because the primary
// varibles and the intensive quantities of the black oil model also do
// this...
Scalar RsSat = FluidSystem::gasDissolutionFactor(temperature, gasPressure, /*regionIdx=*/0);
Scalar RsSat = FluidSystem::gasDissolutionFactor(temperature,
gasPressure,
/*regionIdx=*/0);
Scalar RsReal = (*rsData)[cartesianDofIdx];
if (RsReal > RsSat) {
@ -1172,7 +1187,9 @@ private:
//
// first, retrieve the relevant black-gas parameters from
// the fluid system.
Scalar RvSat = FluidSystem::oilVaporizationFactor(temperature, gasPressure, /*regionIdx=*/0);
Scalar RvSat = FluidSystem::oilVaporizationFactor(temperature,
gasPressure,
/*regionIdx=*/0);
Scalar RvReal = (*rvData)[cartesianDofIdx];
if (RvReal > RvSat) {
@ -1225,7 +1242,7 @@ private:
std::vector<unsigned short> rockTableIdx_;
std::vector<RockParams> rockParams_;
std::vector<BlackOilFluidState> initialFluidStates_;
std::vector<ScalarFluidState> initialFluidStates_;
EclWellManager<TypeTag> wellManager_;

View File

@ -284,7 +284,13 @@ private:
assert(dimIdx < dimWorld);
halfTrans = perm[dimIdx][dimIdx];
halfTrans *= is.geometry().volume();
halfTrans *= std::abs<Scalar>(is.centerUnitOuterNormal()*distance);
const auto &normal = is.centerUnitOuterNormal();
Scalar val = 0;
for (unsigned i = 0; i < normal.size(); ++i)
val += is.centerUnitOuterNormal()[i]*distance[i];
halfTrans *= std::abs<Scalar>(val);
halfTrans /= distance*distance;
}
@ -301,13 +307,14 @@ private:
return x;
}
template <class MultScalar>
void applyMultipliers_(Scalar &trans, int faceIdx, int elemIdx,
const std::vector<Scalar>& multx,
const std::vector<Scalar>& multxMinus,
const std::vector<Scalar>& multy,
const std::vector<Scalar>& multyMinus,
const std::vector<Scalar>& multz,
const std::vector<Scalar>& multzMinus) const
const std::vector<MultScalar>& multx,
const std::vector<MultScalar>& multxMinus,
const std::vector<MultScalar>& multy,
const std::vector<MultScalar>& multyMinus,
const std::vector<MultScalar>& multz,
const std::vector<MultScalar>& multzMinus) const
{
// apply multiplyer for the transmissibility of the face. (the
// face index is the index of the reference-element face which
@ -336,8 +343,9 @@ private:
}
}
template <class NtgScalar>
void applyNtg_(Scalar &trans, int faceIdx, int elemIdx,
const std::vector<Scalar>& ntg) const
const std::vector<NtgScalar>& ntg) const
{
// apply multiplyer for the transmissibility of the face. (the
// face index is the index of the reference-element face which

View File

@ -44,9 +44,8 @@
namespace Ewoms {
namespace Properties {
NEW_PROP_TAG(Grid);
}}
}
namespace Ewoms {
/*!
* \ingroup EclBlackOilSimulator
*
@ -60,10 +59,12 @@ class EclWellManager
typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
typedef typename GET_PROP_TYPE(TypeTag, Grid) Grid;
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
typedef typename GET_PROP_TYPE(TypeTag, Evaluation) Evaluation;
typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
typedef typename GET_PROP_TYPE(TypeTag, ElementContext) ElementContext;
typedef typename GET_PROP_TYPE(TypeTag, RateVector) RateVector;
enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
enum { numPhases = FluidSystem::numPhases };
typedef typename GridView::template Codim<0>::Entity Element;
@ -72,6 +73,8 @@ class EclWellManager
typedef std::map<int, std::pair<const Opm::Completion*, std::shared_ptr<Well> > > WellCompletionsMap;
typedef Dune::FieldVector<Evaluation, numEq> EvalEqVector;
public:
EclWellManager(Simulator &simulator)
: simulator_(simulator)
@ -478,12 +481,13 @@ public:
* freedom.
*/
template <class Context>
void computeTotalRatesForDof(RateVector &q,
void computeTotalRatesForDof(EvalEqVector &q,
const Context &context,
int dofIdx,
int timeIdx) const
{
q = 0.0;
for (int eqIdx = 0; eqIdx < numEq; ++ eqIdx)
q[eqIdx] = 0.0;
RateVector wellRate;