mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
make ebos AD aware
This commit is contained in:
parent
eba7e06bed
commit
2428ff41ae
@ -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
|
||||
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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_;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user