Support for mechanical dispersion

This commit is contained in:
David Landa Marban 2023-10-25 19:46:55 +02:00
parent 960663e7b8
commit bc03821d57
11 changed files with 127 additions and 8 deletions

View File

@ -189,7 +189,9 @@ public:
getPropValue<TypeTag, getPropValue<TypeTag,
Properties::EnableEnergy>(), Properties::EnableEnergy>(),
getPropValue<TypeTag, getPropValue<TypeTag,
Properties::EnableDiffusion>()); Properties::EnableDiffusion>(),
getPropValue<TypeTag,
Properties::EnableDispersion>());
// Re-ordering for ALUGrid // Re-ordering for ALUGrid
globalTrans_->update(false, [&](unsigned int i) { return gridEquilIdxToGridIdx(i);}); globalTrans_->update(false, [&](unsigned int i) { return gridEquilIdxToGridIdx(i);});
} }

View File

@ -281,7 +281,8 @@ protected:
this->grid(), this->grid(),
this->cellCentroids(), this->cellCentroids(),
getPropValue<TypeTag, Properties::EnableEnergy>(), getPropValue<TypeTag, Properties::EnableEnergy>(),
getPropValue<TypeTag, Properties::EnableDiffusion>())); getPropValue<TypeTag, Properties::EnableDiffusion>(),
getPropValue<TypeTag, Properties::EnableDispersion>()));
globalTrans_->update(false); globalTrans_->update(false);
} }

View File

@ -145,6 +145,7 @@ class EclProblem : public GetPropType<TypeTag, Properties::BaseProblem>
enum { enableTemperature = getPropValue<TypeTag, Properties::EnableTemperature>() }; enum { enableTemperature = getPropValue<TypeTag, Properties::EnableTemperature>() };
enum { enableEnergy = getPropValue<TypeTag, Properties::EnableEnergy>() }; enum { enableEnergy = getPropValue<TypeTag, Properties::EnableEnergy>() };
enum { enableDiffusion = getPropValue<TypeTag, Properties::EnableDiffusion>() }; enum { enableDiffusion = getPropValue<TypeTag, Properties::EnableDiffusion>() };
enum { enableDispersion = getPropValue<TypeTag, Properties::EnableDispersion>() };
enum { enableThermalFluxBoundaries = getPropValue<TypeTag, Properties::EnableThermalFluxBoundaries>() }; enum { enableThermalFluxBoundaries = getPropValue<TypeTag, Properties::EnableThermalFluxBoundaries>() };
enum { enableApiTracking = getPropValue<TypeTag, Properties::EnableApiTracking>() }; enum { enableApiTracking = getPropValue<TypeTag, Properties::EnableApiTracking>() };
enum { enableMICP = getPropValue<TypeTag, Properties::EnableMICP>() }; enum { enableMICP = getPropValue<TypeTag, Properties::EnableMICP>() };
@ -278,7 +279,8 @@ public:
simulator.vanguard().grid(), simulator.vanguard().grid(),
simulator.vanguard().cellCentroids(), simulator.vanguard().cellCentroids(),
enableEnergy, enableEnergy,
enableDiffusion) enableDiffusion,
enableDispersion)
, thresholdPressures_(simulator) , thresholdPressures_(simulator)
, wellModel_(simulator) , wellModel_(simulator)
, aquiferModel_(simulator) , aquiferModel_(simulator)
@ -824,6 +826,13 @@ public:
return transmissibilities_.diffusivity(globalCellIn, globalCellOut); return transmissibilities_.diffusivity(globalCellIn, globalCellOut);
} }
/*!
* give the dispersivity for a face i.e. pair.
*/
Scalar dispersivity(const unsigned globalCellIn, const unsigned globalCellOut) const{
return transmissibilities_.dispersivity(globalCellIn, globalCellOut);
}
/*! /*!
* \brief Direct access to a boundary transmissibility. * \brief Direct access to a boundary transmissibility.
*/ */
@ -2448,6 +2457,7 @@ private:
ConditionalStorage<enableEnergy, Scalar> thermalHalfTransIn; ConditionalStorage<enableEnergy, Scalar> thermalHalfTransIn;
ConditionalStorage<enableEnergy, Scalar> thermalHalfTransOut; ConditionalStorage<enableEnergy, Scalar> thermalHalfTransOut;
ConditionalStorage<enableDiffusion, Scalar> diffusivity; ConditionalStorage<enableDiffusion, Scalar> diffusivity;
ConditionalStorage<enableDispersion, Scalar> dispersivity;
Scalar transmissibility; Scalar transmissibility;
}; };
@ -2473,6 +2483,8 @@ private:
} }
if constexpr (enableDiffusion) if constexpr (enableDiffusion)
*dofData.diffusivity = transmissibilities_.diffusivity(globalCenterElemIdx, globalElemIdx); *dofData.diffusivity = transmissibilities_.diffusivity(globalCenterElemIdx, globalElemIdx);
if (enableDispersion)
dofData.dispersivity = transmissibilities_.dispersivity(globalCenterElemIdx, globalElemIdx);
} }
}; };

View File

@ -269,6 +269,12 @@ struct EnableDiffusion<TypeTag, TTag::EclBaseProblem> {
static constexpr bool value = true; static constexpr bool value = true;
}; };
// Enable dispersion
template<class TypeTag>
struct EnableDispersion<TypeTag, TTag::EclBaseProblem> {
static constexpr bool value = false;
};
// only write the solutions for the report steps to disk // only write the solutions for the report steps to disk
template<class TypeTag> template<class TypeTag>
struct EnableWriteAllSolutions<TypeTag, TTag::EclBaseProblem> { struct EnableWriteAllSolutions<TypeTag, TTag::EclBaseProblem> {

View File

@ -66,7 +66,8 @@ public:
const Grid& grid, const Grid& grid,
std::function<std::array<double,dimWorld>(int)> centroids, std::function<std::array<double,dimWorld>(int)> centroids,
bool enableEnergy, bool enableEnergy,
bool enableDiffusivity); bool enableDiffusivity,
bool enableDispersivity);
/*! /*!
* \brief Return the permeability for an element. * \brief Return the permeability for an element.
@ -107,6 +108,11 @@ public:
*/ */
Scalar diffusivity(unsigned elemIdx1, unsigned elemIdx2) const; Scalar diffusivity(unsigned elemIdx1, unsigned elemIdx2) const;
/*!
* \brief Return the dispersivity for the intersection between two elements.
*/
Scalar dispersivity(unsigned elemIdx1, unsigned elemIdx2) const;
/*! /*!
* \brief Actually compute the transmissibility over a face as a pre-compute step. * \brief Actually compute the transmissibility over a face as a pre-compute step.
* *
@ -230,6 +236,8 @@ protected:
void extractPorosity_(); void extractPorosity_();
void extractDispersion_();
void computeHalfTrans_(Scalar& halfTrans, void computeHalfTrans_(Scalar& halfTrans,
const DimVector& areaNormal, const DimVector& areaNormal,
int faceIdx, // in the reference element that contains the intersection int faceIdx, // in the reference element that contains the intersection
@ -258,6 +266,7 @@ protected:
std::vector<DimMatrix> permeability_; std::vector<DimMatrix> permeability_;
std::vector<Scalar> porosity_; std::vector<Scalar> porosity_;
std::vector<Scalar> dispersion_;
std::unordered_map<std::uint64_t, Scalar> trans_; std::unordered_map<std::uint64_t, Scalar> trans_;
const EclipseState& eclState_; const EclipseState& eclState_;
const GridView& gridView_; const GridView& gridView_;
@ -269,8 +278,10 @@ protected:
std::map<std::pair<unsigned, unsigned>, Scalar> thermalHalfTransBoundary_; std::map<std::pair<unsigned, unsigned>, Scalar> thermalHalfTransBoundary_;
bool enableEnergy_; bool enableEnergy_;
bool enableDiffusivity_; bool enableDiffusivity_;
bool enableDispersivity_;
std::unordered_map<std::uint64_t, Scalar> thermalHalfTrans_; //NB this is based on direction map size is ca 2*trans_ (diffusivity_) std::unordered_map<std::uint64_t, Scalar> thermalHalfTrans_; //NB this is based on direction map size is ca 2*trans_ (diffusivity_)
std::unordered_map<std::uint64_t, Scalar> diffusivity_; std::unordered_map<std::uint64_t, Scalar> diffusivity_;
std::unordered_map<std::uint64_t, Scalar> dispersivity_;
const LookUpData<Grid,GridView> lookUpData_; const LookUpData<Grid,GridView> lookUpData_;
const LookUpCartesianData<Grid,GridView> lookUpCartesianData_; const LookUpCartesianData<Grid,GridView> lookUpCartesianData_;

View File

@ -93,7 +93,8 @@ EclTransmissibility(const EclipseState& eclState,
const Grid& grid, const Grid& grid,
std::function<std::array<double,dimWorld>(int)> centroids, std::function<std::array<double,dimWorld>(int)> centroids,
bool enableEnergy, bool enableEnergy,
bool enableDiffusivity) bool enableDiffusivity,
bool enableDispersivity)
: eclState_(eclState) : eclState_(eclState)
, gridView_(gridView) , gridView_(gridView)
, cartMapper_(cartMapper) , cartMapper_(cartMapper)
@ -101,6 +102,7 @@ EclTransmissibility(const EclipseState& eclState,
, centroids_(centroids) , centroids_(centroids)
, enableEnergy_(enableEnergy) , enableEnergy_(enableEnergy)
, enableDiffusivity_(enableDiffusivity) , enableDiffusivity_(enableDiffusivity)
, enableDispersivity_(enableDispersivity)
, lookUpData_(gridView) , lookUpData_(gridView)
, lookUpCartesianData_(gridView, cartMapper) , lookUpCartesianData_(gridView, cartMapper)
{ {
@ -147,6 +149,17 @@ diffusivity(unsigned elemIdx1, unsigned elemIdx2) const
} }
template<class Grid, class GridView, class ElementMapper, class CartesianIndexMapper, class Scalar>
Scalar EclTransmissibility<Grid,GridView,ElementMapper,CartesianIndexMapper,Scalar>::
dispersivity(unsigned elemIdx1, unsigned elemIdx2) const
{
if (dispersivity_.empty())
return 0.0;
return dispersivity_.at(isId(elemIdx1, elemIdx2));
}
template<class Grid, class GridView, class ElementMapper, class CartesianIndexMapper, class Scalar> template<class Grid, class GridView, class ElementMapper, class CartesianIndexMapper, class Scalar>
void EclTransmissibility<Grid,GridView,ElementMapper,CartesianIndexMapper,Scalar>:: void EclTransmissibility<Grid,GridView,ElementMapper,CartesianIndexMapper,Scalar>::
update(bool global, const std::function<unsigned int(unsigned int)>& map, const bool applyNncMultregT) update(bool global, const std::function<unsigned int(unsigned int)>& map, const bool applyNncMultregT)
@ -159,7 +172,8 @@ update(bool global, const std::function<unsigned int(unsigned int)>& map, const
unsigned numElements = elemMapper.size(); unsigned numElements = elemMapper.size();
// get the ntg values, the ntg values are modified for the cells merged with minpv // get the ntg values, the ntg values are modified for the cells merged with minpv
const std::vector<double>& ntg = this->lookUpData_.assignFieldPropsDoubleOnLeaf(eclState_.fieldProps(), "NTG", numElements); const std::vector<double>& ntg = this->lookUpData_.assignFieldPropsDoubleOnLeaf(eclState_.fieldProps(), "NTG", numElements);
const bool updateDiffusivity = eclState_.getSimulationConfig().isDiffusive() && enableDiffusivity_; const bool updateDiffusivity = eclState_.getSimulationConfig().isDiffusive();
const bool updateDispersivity = eclState_.getSimulationConfig().rock_config().dispersion();
if (map) if (map)
extractPermeability_(map); extractPermeability_(map);
@ -209,6 +223,13 @@ update(bool global, const std::function<unsigned int(unsigned int)>& map, const
extractPorosity_(); extractPorosity_();
} }
// if dispersion is enabled, let's do the same for the "dispersivity"
if (updateDispersivity) {
dispersivity_.clear();
dispersivity_.reserve(numElements*3*1.05);
extractDispersion_();
}
// The MULTZ needs special case if the option is ALL // The MULTZ needs special case if the option is ALL
// Then the smallest multiplier is applied. // Then the smallest multiplier is applied.
// Default is to apply the top and bottom multiplier // Default is to apply the top and bottom multiplier
@ -314,6 +335,9 @@ update(bool global, const std::function<unsigned int(unsigned int)>& map, const
if (updateDiffusivity) { if (updateDiffusivity) {
diffusivity_[isId(elemIdx, outsideElemIdx)] = 0.0; diffusivity_[isId(elemIdx, outsideElemIdx)] = 0.0;
} }
if (updateDispersivity) {
dispersivity_[isId(elemIdx, outsideElemIdx)] = 0.0;
}
continue; continue;
} }
@ -485,6 +509,42 @@ update(bool global, const std::function<unsigned int(unsigned int)>& map, const
diffusivity_[isId(elemIdx, outsideElemIdx)] = diffusivity; diffusivity_[isId(elemIdx, outsideElemIdx)] = diffusivity;
} }
// update the "dispersivity half transmissibility" for the intersection
if (updateDispersivity) {
Scalar halfDispersivity1;
Scalar halfDispersivity2;
computeHalfDiffusivity_(halfDispersivity1,
faceAreaNormal,
distanceVector_(faceCenterInside,
intersection.indexInInside(),
elemIdx,
axisCentroids),
dispersion_[elemIdx]);
computeHalfDiffusivity_(halfDispersivity2,
faceAreaNormal,
distanceVector_(faceCenterOutside,
intersection.indexInOutside(),
outsideElemIdx,
axisCentroids),
dispersion_[outsideElemIdx]);
applyNtg_(halfDispersivity1, insideFaceIdx, elemIdx, ntg);
applyNtg_(halfDispersivity2, outsideFaceIdx, outsideElemIdx, ntg);
//TODO Add support for multipliers
Scalar dispersivity;
if (std::abs(halfDispersivity1) < 1e-30 || std::abs(halfDispersivity2) < 1e-30)
// avoid division by zero
dispersivity = 0.0;
else
dispersivity = 1.0 / (1.0/halfDispersivity1 + 1.0/halfDispersivity2);
dispersivity_[isId(elemIdx, outsideElemIdx)] = dispersivity;
}
} }
} }
@ -615,6 +675,18 @@ extractPorosity_()
"(The PORO keywords are missing)"); "(The PORO keywords are missing)");
} }
template<class Grid, class GridView, class ElementMapper, class CartesianIndexMapper, class Scalar>
void EclTransmissibility<Grid,GridView,ElementMapper,CartesianIndexMapper,Scalar>::
extractDispersion_()
{
if (!enableDispersivity_) {
throw std::runtime_error("Dispersion disabled at compile time, but the deck "
"contains the DISPERC keyword.");
}
const auto& fp = eclState_.fieldProps();
dispersion_ = fp.get_double("DISPERC");
}
template<class Grid, class GridView, class ElementMapper, class CartesianIndexMapper, class Scalar> template<class Grid, class GridView, class ElementMapper, class CartesianIndexMapper, class Scalar>
void EclTransmissibility<Grid,GridView,ElementMapper,CartesianIndexMapper,Scalar>:: void EclTransmissibility<Grid,GridView,ElementMapper,CartesianIndexMapper,Scalar>::
removeSmallNonCartesianTransmissibilities_() removeSmallNonCartesianTransmissibilities_()

View File

@ -70,6 +70,9 @@ struct LocalResidual<TypeTag, TTag::EclFlowGasOilEnergyProblem> { using type = B
template<class TypeTag> template<class TypeTag>
struct EnableDiffusion<TypeTag, TTag::EclFlowGasOilEnergyProblem> { static constexpr bool value = true; }; struct EnableDiffusion<TypeTag, TTag::EclFlowGasOilEnergyProblem> { static constexpr bool value = true; };
template<class TypeTag>
struct EnableDispersion<TypeTag, TTag::EclFlowGasOilEnergyProblem> { static constexpr bool value = true; };
}} }}
namespace Opm { namespace Opm {

View File

@ -41,10 +41,12 @@ struct Linearizer<TypeTag, TTag::EclFlowGasOilDiffuseProblem> { using type = Tpf
template<class TypeTag> template<class TypeTag>
struct LocalResidual<TypeTag, TTag::EclFlowGasOilDiffuseProblem> { using type = BlackOilLocalResidualTPFA<TypeTag>; }; struct LocalResidual<TypeTag, TTag::EclFlowGasOilDiffuseProblem> { using type = BlackOilLocalResidualTPFA<TypeTag>; };
template<class TypeTag> template<class TypeTag>
struct EnableDiffusion<TypeTag, TTag::EclFlowGasOilDiffuseProblem> { static constexpr bool value = true; }; struct EnableDiffusion<TypeTag, TTag::EclFlowGasOilDiffuseProblem> { static constexpr bool value = true; };
template<class TypeTag>
struct EnableDispersion<TypeTag, TTag::EclFlowGasOilDiffuseProblem> { static constexpr bool value = true; };
//! The indices required by the model //! The indices required by the model
template<class TypeTag> template<class TypeTag>
struct Indices<TypeTag, TTag::EclFlowGasOilDiffuseProblem> struct Indices<TypeTag, TTag::EclFlowGasOilDiffuseProblem>

View File

@ -48,6 +48,9 @@ struct LocalResidual<TypeTag, TTag::EclFlowGasWaterDissolutionDiffuseProblem> {
template<class TypeTag> template<class TypeTag>
struct EnableDiffusion<TypeTag, TTag::EclFlowGasWaterDissolutionDiffuseProblem> { static constexpr bool value = true; }; struct EnableDiffusion<TypeTag, TTag::EclFlowGasWaterDissolutionDiffuseProblem> { static constexpr bool value = true; };
template<class TypeTag>
struct EnableDispersion<TypeTag, TTag::EclFlowGasWaterDissolutionDiffuseProblem> { static constexpr bool value = true; };
template<class TypeTag> template<class TypeTag>
struct EnableDisgasInWater<TypeTag, TTag::EclFlowGasWaterDissolutionDiffuseProblem> { struct EnableDisgasInWater<TypeTag, TTag::EclFlowGasWaterDissolutionDiffuseProblem> {
static constexpr bool value = true; static constexpr bool value = true;

View File

@ -46,7 +46,10 @@ template<class TypeTag>
struct LocalResidual<TypeTag, TTag::EclFlowGasWaterEnergyProblem> { using type = BlackOilLocalResidualTPFA<TypeTag>; }; struct LocalResidual<TypeTag, TTag::EclFlowGasWaterEnergyProblem> { using type = BlackOilLocalResidualTPFA<TypeTag>; };
template<class TypeTag> template<class TypeTag>
struct EnableDiffusion<TypeTag, TTag::EclFlowGasWaterEnergyProblem> { static constexpr bool value = false; }; struct EnableDiffusion<TypeTag, TTag::EclFlowGasWaterEnergyProblem> { static constexpr bool value = true; };
template<class TypeTag>
struct EnableDispersion<TypeTag, TTag::EclFlowGasWaterEnergyProblem> { static constexpr bool value = true; };
template<class TypeTag> template<class TypeTag>
struct EnableEnergy<TypeTag, TTag::EclFlowGasWaterEnergyProblem> { struct EnableEnergy<TypeTag, TTag::EclFlowGasWaterEnergyProblem> {

View File

@ -133,6 +133,10 @@ template<class TypeTag>
struct EnableMICP<TypeTag, TTag::EclFlowProblem> { struct EnableMICP<TypeTag, TTag::EclFlowProblem> {
static constexpr bool value = false; static constexpr bool value = false;
}; };
template<class TypeTag>
struct EnableDispersion<TypeTag, TTag::EclFlowProblem> {
static constexpr bool value = false;
};
template<class TypeTag> template<class TypeTag>
struct EclWellModel<TypeTag, TTag::EclFlowProblem> { struct EclWellModel<TypeTag, TTag::EclFlowProblem> {