mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
blackoil: implement the immiscible solvent extension
Conceptually this is IMO pretty questionable, since it adds a second "gas phase" that does not mix with "ordinary" gas. I suppose the reason why this extension was conceived by E100 is that if all you have is hammer, everything looks like a nail... Functionality-wise, this patch is still not fully complete because miscibility of the solvent "phase" is not yet implemented. As far as I can see, the API changes required by miscibility are quite limited, though.
This commit is contained in:
parent
cddf643b5a
commit
bcdc4e5e38
@ -32,6 +32,7 @@
|
||||
#define EWOMS_ECL_FLUX_MODULE_HH
|
||||
|
||||
#include <ewoms/disc/common/fvbaseproperties.hh>
|
||||
#include <ewoms/models/blackoil/blackoilproperties.hh>
|
||||
#include <ewoms/common/signum.hh>
|
||||
|
||||
#include <opm/common/Valgrind.hpp>
|
||||
@ -102,6 +103,8 @@ protected:
|
||||
template <class TypeTag>
|
||||
class EclTransExtensiveQuantities
|
||||
{
|
||||
typedef typename GET_PROP_TYPE(TypeTag, ExtensiveQuantities) Implementation;
|
||||
|
||||
typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, ElementContext) ElementContext;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
|
||||
@ -110,7 +113,9 @@ class EclTransExtensiveQuantities
|
||||
typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
|
||||
|
||||
enum { dimWorld = GridView::dimensionworld };
|
||||
enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) };
|
||||
enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
|
||||
enum { numPhases = FluidSystem::numPhases };
|
||||
enum { enableSolvent = GET_PROP_VALUE(TypeTag, EnableSolvent) };
|
||||
|
||||
typedef Opm::MathToolbox<Evaluation> Toolbox;
|
||||
typedef Dune::FieldVector<Scalar, dimWorld> DimVector;
|
||||
@ -201,6 +206,9 @@ protected:
|
||||
return dnIdx_[phaseIdx];
|
||||
}
|
||||
|
||||
void updateSolvent(const ElementContext& elemCtx, unsigned scvfIdx, unsigned timeIdx)
|
||||
{ asImp_().updateVolumeFluxTrans(elemCtx, scvfIdx, timeIdx); }
|
||||
|
||||
/*!
|
||||
* \brief Update the required gradients for interior faces
|
||||
*/
|
||||
@ -347,6 +355,13 @@ protected:
|
||||
void calculateFluxes_(const ElementContext& elemCtx OPM_UNUSED, unsigned scvfIdx OPM_UNUSED, unsigned timeIdx OPM_UNUSED)
|
||||
{ }
|
||||
|
||||
private:
|
||||
Implementation& asImp_()
|
||||
{ return *static_cast<Implementation*>(this); }
|
||||
|
||||
const Implementation& asImp_() const
|
||||
{ return *static_cast<const Implementation*>(this); }
|
||||
|
||||
// the volumetric flux of all phases [m^3/s]
|
||||
Evaluation volumeFlux_[numPhases];
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#ifndef EWOMS_ECL_PEACEMAN_WELL_HH
|
||||
#define EWOMS_ECL_PEACEMAN_WELL_HH
|
||||
|
||||
#include <ewoms/models/blackoil/blackoilproperties.hh>
|
||||
#include <ewoms/aux/baseauxiliarymodule.hh>
|
||||
#include <ewoms/common/propertysystem.hh>
|
||||
#include <ewoms/common/alignedallocator.hh>
|
||||
@ -46,17 +47,6 @@
|
||||
#include <map>
|
||||
|
||||
namespace Ewoms {
|
||||
namespace Properties {
|
||||
NEW_PROP_TAG(Scalar);
|
||||
NEW_PROP_TAG(Discretization);
|
||||
NEW_PROP_TAG(FluidSystem);
|
||||
NEW_PROP_TAG(Simulator);
|
||||
NEW_PROP_TAG(ElementContext);
|
||||
NEW_PROP_TAG(RateVector);
|
||||
NEW_PROP_TAG(GridView);
|
||||
NEW_PROP_TAG(NumPhases);
|
||||
NEW_PROP_TAG(NumComponents);
|
||||
}
|
||||
|
||||
template <class TypeTag>
|
||||
class EcfvDiscretization;
|
||||
@ -124,6 +114,7 @@ class EclPeacemanWell : public BaseAuxiliaryModule<TypeTag>
|
||||
static const unsigned gasCompIdx = FluidSystem::gasCompIdx;
|
||||
|
||||
static const unsigned numModelEq = GET_PROP_VALUE(TypeTag, NumEq);
|
||||
static const unsigned conti0EqIdx = GET_PROP_TYPE(TypeTag, Indices)::conti0EqIdx;
|
||||
|
||||
typedef Opm::CompositionalFluidState<Scalar, FluidSystem, /*storeEnthalpy=*/false> FluidState;
|
||||
typedef Dune::FieldMatrix<Scalar, dimWorld, dimWorld> DimMatrix;
|
||||
@ -446,10 +437,9 @@ public:
|
||||
|
||||
// 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
|
||||
// rate for each component as its first conservation equations, but we
|
||||
// require the black-oil model for now anyway, so this should not be too much
|
||||
// of a problem...
|
||||
assert(numModelEq == numComponents);
|
||||
// rate for each component as its first conservation equation, but we require
|
||||
// the black-oil model for now anyway, so this should not be too much of a
|
||||
// problem...
|
||||
Opm::Valgrind::CheckDefined(q);
|
||||
auto& matrixEntry = matrix[gridDofIdx][wellGlobalDofIdx];
|
||||
matrixEntry = 0.0;
|
||||
@ -1127,8 +1117,8 @@ public:
|
||||
continue;
|
||||
|
||||
modelRate.setVolumetricRate(intQuants.fluidState(), phaseIdx, volumetricRates[phaseIdx]);
|
||||
for (unsigned eqIdx = 0; eqIdx < q.size(); ++eqIdx)
|
||||
q[eqIdx] += modelRate[eqIdx];
|
||||
for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx)
|
||||
q[conti0EqIdx + compIdx] += modelRate[conti0EqIdx + compIdx];
|
||||
}
|
||||
|
||||
Opm::Valgrind::CheckDefined(q);
|
||||
|
@ -248,6 +248,7 @@ class EclProblem : public GET_PROP_TYPE(TypeTag, BaseProblem)
|
||||
enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
|
||||
enum { numPhases = FluidSystem::numPhases };
|
||||
enum { numComponents = FluidSystem::numComponents };
|
||||
enum { enableSolvent = GET_PROP_VALUE(TypeTag, EnableSolvent) };
|
||||
enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
|
||||
enum { oilPhaseIdx = FluidSystem::oilPhaseIdx };
|
||||
enum { waterPhaseIdx = FluidSystem::waterPhaseIdx };
|
||||
@ -267,6 +268,7 @@ class EclProblem : public GET_PROP_TYPE(TypeTag, BaseProblem)
|
||||
typedef typename GET_PROP_TYPE(TypeTag, MaterialLawParams) MaterialLawParams;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Evaluation) Evaluation;
|
||||
|
||||
typedef BlackOilSolventModule<TypeTag> SolventModule;
|
||||
typedef Opm::CompositionalFluidState<Scalar, FluidSystem> ScalarFluidState;
|
||||
typedef Opm::MathToolbox<Evaluation> Toolbox;
|
||||
typedef Ewoms::EclSummaryWriter<TypeTag> EclSummaryWriter;
|
||||
@ -315,6 +317,10 @@ public:
|
||||
{
|
||||
// add the output module for the Ecl binary output
|
||||
simulator.model().addOutputModule(new Ewoms::EclOutputBlackOilModule<TypeTag>(simulator));
|
||||
|
||||
// Tell the solvent module to initialize its internal data structures
|
||||
const auto& gridManager = simulator.gridManager();
|
||||
SolventModule::initFromDeck(gridManager.deck(), gridManager.eclState());
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -754,6 +760,24 @@ public:
|
||||
return pvtnum_[elemIdx];
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the index of the relevant region for thermodynmic properties
|
||||
*/
|
||||
template <class Context>
|
||||
unsigned satnumRegionIndex(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
|
||||
{ return satnumRegionIndex(context.globalSpaceIndex(spaceIdx, timeIdx)); }
|
||||
|
||||
/*!
|
||||
* \brief Returns the index the relevant saturation function region given a cell index
|
||||
*/
|
||||
unsigned satnumRegionIndex(unsigned elemIdx) const
|
||||
{
|
||||
if (satnum_.empty())
|
||||
return 0;
|
||||
|
||||
return satnum_[elemIdx];
|
||||
}
|
||||
|
||||
/*!
|
||||
* \copydoc FvBaseProblem::name
|
||||
*/
|
||||
@ -803,6 +827,9 @@ public:
|
||||
}
|
||||
else
|
||||
values.assignNaive(initialFluidStates_[globalDofIdx]);
|
||||
|
||||
//if (enableSolvent)
|
||||
// values[Indices::solventSaturationIdx] = whatever;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -1004,8 +1031,9 @@ private:
|
||||
const auto& deck = gridManager.deck();
|
||||
const auto& eclState = gridManager.eclState();
|
||||
|
||||
// the PVT region number
|
||||
// the PVT and saturation region numbers
|
||||
updatePvtnum_();
|
||||
updateSatnum_();
|
||||
|
||||
////////////////////////////////
|
||||
// porosity
|
||||
@ -1357,6 +1385,25 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void updateSatnum_()
|
||||
{
|
||||
const auto& eclState = this->simulator().gridManager().eclState();
|
||||
const auto& eclProps = eclState.get3DProperties();
|
||||
|
||||
if (!eclProps.hasDeckIntGridProperty("SATNUM"))
|
||||
return;
|
||||
|
||||
const auto& satnumData = eclProps.getIntGridProperty("SATNUM").getData();
|
||||
const auto& gridManager = this->simulator().gridManager();
|
||||
|
||||
unsigned numElems = gridManager.gridView().size(/*codim=*/0);
|
||||
satnum_.resize(numElems);
|
||||
for (unsigned elemIdx = 0; elemIdx < numElems; ++elemIdx) {
|
||||
unsigned cartElemIdx = gridManager.cartesianIndex(elemIdx);
|
||||
satnum_[elemIdx] = satnumData[cartElemIdx] - 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct PffDofData_
|
||||
{
|
||||
Scalar transmissibility;
|
||||
@ -1401,6 +1448,7 @@ private:
|
||||
EclThresholdPressure<TypeTag> thresholdPressures_;
|
||||
|
||||
std::vector<unsigned short> pvtnum_;
|
||||
std::vector<unsigned short> satnum_;
|
||||
std::vector<unsigned short> rockTableIdx_;
|
||||
std::vector<RockParams> rockParams_;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user