mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Merge pull request #4630 from akva2/unify_mobility
changed: unify getMobility(Eval|Scalar)
This commit is contained in:
commit
809f6d19ef
@ -235,14 +235,11 @@ namespace Opm
|
|||||||
DeferredLogger& deferred_logger);
|
DeferredLogger& deferred_logger);
|
||||||
|
|
||||||
// get the mobility for specific perforation
|
// get the mobility for specific perforation
|
||||||
void getMobilityEval(const Simulator& ebosSimulator,
|
template<class Value>
|
||||||
const int perf,
|
void getMobility(const Simulator& ebosSimulator,
|
||||||
std::vector<EvalWell>& mob) const;
|
const int perf,
|
||||||
|
std::vector<Value>& mob,
|
||||||
// get the mobility for specific perforation
|
DeferredLogger& deferred_logger) const;
|
||||||
void getMobilityScalar(const Simulator& ebosSimulator,
|
|
||||||
const int perf,
|
|
||||||
std::vector<Scalar>& mob) const;
|
|
||||||
|
|
||||||
void computeWellRatesAtBhpLimit(const Simulator& ebosSimulator,
|
void computeWellRatesAtBhpLimit(const Simulator& ebosSimulator,
|
||||||
std::vector<double>& well_flux,
|
std::vector<double>& well_flux,
|
||||||
|
@ -389,7 +389,7 @@ namespace Opm
|
|||||||
const auto& intQuants = ebosSimulator.model().intensiveQuantities(cell_idx, /*timeIdx=*/ 0);
|
const auto& intQuants = ebosSimulator.model().intensiveQuantities(cell_idx, /*timeIdx=*/ 0);
|
||||||
// flux for each perforation
|
// flux for each perforation
|
||||||
std::vector<Scalar> mob(this->num_components_, 0.);
|
std::vector<Scalar> mob(this->num_components_, 0.);
|
||||||
getMobilityScalar(ebosSimulator, perf, mob);
|
getMobility(ebosSimulator, perf, mob, deferred_logger);
|
||||||
double trans_mult = ebosSimulator.problem().template rockCompTransMultiplier<double>(intQuants, cell_idx);
|
double trans_mult = ebosSimulator.problem().template rockCompTransMultiplier<double>(intQuants, cell_idx);
|
||||||
const double Tw = this->well_index_[perf] * trans_mult;
|
const double Tw = this->well_index_[perf] * trans_mult;
|
||||||
|
|
||||||
@ -716,7 +716,7 @@ namespace Opm
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Scalar> mob(this->num_components_, 0.0);
|
std::vector<Scalar> mob(this->num_components_, 0.0);
|
||||||
getMobilityScalar(ebosSimulator, static_cast<int>(subsetPerfID), mob);
|
getMobility(ebosSimulator, static_cast<int>(subsetPerfID), mob, deferred_logger);
|
||||||
|
|
||||||
const auto& fs = fluidState(subsetPerfID);
|
const auto& fs = fluidState(subsetPerfID);
|
||||||
setToZero(connPI);
|
setToZero(connPI);
|
||||||
@ -1066,115 +1066,27 @@ namespace Opm
|
|||||||
deferred_logger);
|
deferred_logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename TypeTag>
|
template <typename TypeTag>
|
||||||
|
template<class Value>
|
||||||
void
|
void
|
||||||
MultisegmentWell<TypeTag>::
|
MultisegmentWell<TypeTag>::
|
||||||
getMobilityEval(const Simulator& ebosSimulator,
|
getMobility(const Simulator& ebosSimulator,
|
||||||
const int perf,
|
const int perf,
|
||||||
std::vector<EvalWell>& mob) const
|
std::vector<Value>& mob,
|
||||||
|
DeferredLogger& deferred_logger) const
|
||||||
{
|
{
|
||||||
// TODO: most of this function, if not the whole function, can be moved to the base class
|
auto obtain = [this](const Eval& value)
|
||||||
const int cell_idx = this->well_cells_[perf];
|
{
|
||||||
assert (int(mob.size()) == this->num_components_);
|
if constexpr (std::is_same_v<Value, Scalar>) {
|
||||||
const auto& intQuants = ebosSimulator.model().intensiveQuantities(cell_idx, /*timeIdx=*/0);
|
return getValue(value);
|
||||||
const auto& materialLawManager = ebosSimulator.problem().materialLawManager();
|
} else {
|
||||||
|
return this->extendEval(value);
|
||||||
// either use mobility of the perforation cell or calcualte its own
|
}
|
||||||
// based on passing the saturation table index
|
};
|
||||||
const int satid = this->saturation_table_number_[perf] - 1;
|
WellInterface<TypeTag>::getMobility(ebosSimulator, perf, mob, obtain, deferred_logger);
|
||||||
const int satid_elem = materialLawManager->satnumRegionIdx(cell_idx);
|
|
||||||
if( satid == satid_elem ) { // the same saturation number is used. i.e. just use the mobilty from the cell
|
|
||||||
|
|
||||||
for (unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) {
|
|
||||||
if (!FluidSystem::phaseIsActive(phaseIdx)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned activeCompIdx = Indices::canonicalToActiveComponentIndex(FluidSystem::solventComponentIndex(phaseIdx));
|
|
||||||
mob[activeCompIdx] = this->extendEval(intQuants.mobility(phaseIdx));
|
|
||||||
}
|
|
||||||
// if (has_solvent) {
|
|
||||||
// mob[contiSolventEqIdx] = extendEval(intQuants.solventMobility());
|
|
||||||
// }
|
|
||||||
} else {
|
|
||||||
|
|
||||||
const auto& paramsCell = materialLawManager->connectionMaterialLawParams(satid, cell_idx);
|
|
||||||
std::array<Eval,3> relativePerms = { 0.0, 0.0, 0.0 };
|
|
||||||
MaterialLaw::relativePermeabilities(relativePerms, paramsCell, intQuants.fluidState());
|
|
||||||
|
|
||||||
// reset the satnumvalue back to original
|
|
||||||
materialLawManager->connectionMaterialLawParams(satid_elem, cell_idx);
|
|
||||||
|
|
||||||
// compute the mobility
|
|
||||||
for (unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) {
|
|
||||||
if (!FluidSystem::phaseIsActive(phaseIdx)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned activeCompIdx = Indices::canonicalToActiveComponentIndex(FluidSystem::solventComponentIndex(phaseIdx));
|
|
||||||
mob[activeCompIdx] = this->extendEval(relativePerms[phaseIdx] / intQuants.fluidState().viscosity(phaseIdx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename TypeTag>
|
|
||||||
void
|
|
||||||
MultisegmentWell<TypeTag>::
|
|
||||||
getMobilityScalar(const Simulator& ebosSimulator,
|
|
||||||
const int perf,
|
|
||||||
std::vector<Scalar>& mob) const
|
|
||||||
{
|
|
||||||
// TODO: most of this function, if not the whole function, can be moved to the base class
|
|
||||||
const int cell_idx = this->well_cells_[perf];
|
|
||||||
assert (int(mob.size()) == this->num_components_);
|
|
||||||
const auto& intQuants = ebosSimulator.model().intensiveQuantities(cell_idx, /*timeIdx=*/0);
|
|
||||||
const auto& materialLawManager = ebosSimulator.problem().materialLawManager();
|
|
||||||
|
|
||||||
// either use mobility of the perforation cell or calcualte its own
|
|
||||||
// based on passing the saturation table index
|
|
||||||
const int satid = this->saturation_table_number_[perf] - 1;
|
|
||||||
const int satid_elem = materialLawManager->satnumRegionIdx(cell_idx);
|
|
||||||
if( satid == satid_elem ) { // the same saturation number is used. i.e. just use the mobilty from the cell
|
|
||||||
|
|
||||||
for (unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) {
|
|
||||||
if (!FluidSystem::phaseIsActive(phaseIdx)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned activeCompIdx = Indices::canonicalToActiveComponentIndex(FluidSystem::solventComponentIndex(phaseIdx));
|
|
||||||
mob[activeCompIdx] = getValue(intQuants.mobility(phaseIdx));
|
|
||||||
}
|
|
||||||
// if (has_solvent) {
|
|
||||||
// mob[contiSolventEqIdx] = extendEval(intQuants.solventMobility());
|
|
||||||
// }
|
|
||||||
} else {
|
|
||||||
|
|
||||||
const auto& paramsCell = materialLawManager->connectionMaterialLawParams(satid, cell_idx);
|
|
||||||
std::array<Scalar,3> relativePerms = { 0.0, 0.0, 0.0 };
|
|
||||||
MaterialLaw::relativePermeabilities(relativePerms, paramsCell, intQuants.fluidState());
|
|
||||||
|
|
||||||
// reset the satnumvalue back to original
|
|
||||||
materialLawManager->connectionMaterialLawParams(satid_elem, cell_idx);
|
|
||||||
|
|
||||||
// compute the mobility
|
|
||||||
for (unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) {
|
|
||||||
if (!FluidSystem::phaseIsActive(phaseIdx)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned activeCompIdx = Indices::canonicalToActiveComponentIndex(FluidSystem::solventComponentIndex(phaseIdx));
|
|
||||||
mob[activeCompIdx] = relativePerms[phaseIdx] / getValue(intQuants.fluidState().viscosity(phaseIdx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<typename TypeTag>
|
template<typename TypeTag>
|
||||||
double
|
double
|
||||||
@ -1270,7 +1182,7 @@ namespace Opm
|
|||||||
std::vector<Scalar> mob(this->num_components_, 0.0);
|
std::vector<Scalar> mob(this->num_components_, 0.0);
|
||||||
|
|
||||||
// TODO: maybe we should store the mobility somewhere, so that we only need to calculate it one per iteration
|
// TODO: maybe we should store the mobility somewhere, so that we only need to calculate it one per iteration
|
||||||
getMobilityScalar(ebos_simulator, perf, mob);
|
getMobility(ebos_simulator, perf, mob, deferred_logger);
|
||||||
|
|
||||||
const int cell_idx = this->well_cells_[perf];
|
const int cell_idx = this->well_cells_[perf];
|
||||||
const auto& int_quantities = ebos_simulator.model().intensiveQuantities(cell_idx, /*timeIdx=*/ 0);
|
const auto& int_quantities = ebos_simulator.model().intensiveQuantities(cell_idx, /*timeIdx=*/ 0);
|
||||||
@ -1628,7 +1540,7 @@ namespace Opm
|
|||||||
const int cell_idx = this->well_cells_[perf];
|
const int cell_idx = this->well_cells_[perf];
|
||||||
const auto& int_quants = ebosSimulator.model().intensiveQuantities(cell_idx, /*timeIdx=*/ 0);
|
const auto& int_quants = ebosSimulator.model().intensiveQuantities(cell_idx, /*timeIdx=*/ 0);
|
||||||
std::vector<EvalWell> mob(this->num_components_, 0.0);
|
std::vector<EvalWell> mob(this->num_components_, 0.0);
|
||||||
getMobilityEval(ebosSimulator, perf, mob);
|
getMobility(ebosSimulator, perf, mob, deferred_logger);
|
||||||
const double trans_mult = ebosSimulator.problem().template rockCompTransMultiplier<double>(int_quants, cell_idx);
|
const double trans_mult = ebosSimulator.problem().template rockCompTransMultiplier<double>(int_quants, cell_idx);
|
||||||
const double Tw = this->well_index_[perf] * trans_mult;
|
const double Tw = this->well_index_[perf] * trans_mult;
|
||||||
std::vector<EvalWell> cq_s(this->num_components_, 0.0);
|
std::vector<EvalWell> cq_s(this->num_components_, 0.0);
|
||||||
@ -1940,7 +1852,7 @@ namespace Opm
|
|||||||
const int cell_idx = this->well_cells_[perf];
|
const int cell_idx = this->well_cells_[perf];
|
||||||
const auto& int_quants = ebosSimulator.model().intensiveQuantities(cell_idx, /*timeIdx=*/ 0);
|
const auto& int_quants = ebosSimulator.model().intensiveQuantities(cell_idx, /*timeIdx=*/ 0);
|
||||||
std::vector<Scalar> mob(this->num_components_, 0.0);
|
std::vector<Scalar> mob(this->num_components_, 0.0);
|
||||||
getMobilityScalar(ebosSimulator, perf, mob);
|
getMobility(ebosSimulator, perf, mob, deferred_logger);
|
||||||
const double trans_mult = ebosSimulator.problem().template rockCompTransMultiplier<double>(int_quants, cell_idx);
|
const double trans_mult = ebosSimulator.problem().template rockCompTransMultiplier<double>(int_quants, cell_idx);
|
||||||
const double Tw = this->well_index_[perf] * trans_mult;
|
const double Tw = this->well_index_[perf] * trans_mult;
|
||||||
std::vector<Scalar> cq_s(this->num_components_, 0.0);
|
std::vector<Scalar> cq_s(this->num_components_, 0.0);
|
||||||
|
@ -333,17 +333,11 @@ namespace Opm
|
|||||||
virtual double getRefDensity() const override;
|
virtual double getRefDensity() const override;
|
||||||
|
|
||||||
// get the mobility for specific perforation
|
// get the mobility for specific perforation
|
||||||
void getMobilityEval(const Simulator& ebosSimulator,
|
template<class Value>
|
||||||
const int perf,
|
void getMobility(const Simulator& ebosSimulator,
|
||||||
std::vector<EvalWell>& mob,
|
const int perf,
|
||||||
DeferredLogger& deferred_logger) const;
|
std::vector<Value>& mob,
|
||||||
|
DeferredLogger& deferred_logger) const;
|
||||||
// get the mobility for specific perforation
|
|
||||||
void getMobilityScalar(const Simulator& ebosSimulator,
|
|
||||||
const int perf,
|
|
||||||
std::vector<Scalar>& mob,
|
|
||||||
DeferredLogger& deferred_logger) const;
|
|
||||||
|
|
||||||
|
|
||||||
void updateWaterMobilityWithPolymer(const Simulator& ebos_simulator,
|
void updateWaterMobilityWithPolymer(const Simulator& ebos_simulator,
|
||||||
const int perf,
|
const int perf,
|
||||||
|
@ -618,7 +618,7 @@ namespace Opm
|
|||||||
const int cell_idx = this->well_cells_[perf];
|
const int cell_idx = this->well_cells_[perf];
|
||||||
const auto& intQuants = ebosSimulator.model().intensiveQuantities(cell_idx, /*timeIdx=*/ 0);
|
const auto& intQuants = ebosSimulator.model().intensiveQuantities(cell_idx, /*timeIdx=*/ 0);
|
||||||
std::vector<EvalWell> mob(this->num_components_, {this->primary_variables_.numWellEq() + Indices::numEq, 0.});
|
std::vector<EvalWell> mob(this->num_components_, {this->primary_variables_.numWellEq() + Indices::numEq, 0.});
|
||||||
getMobilityEval(ebosSimulator, perf, mob, deferred_logger);
|
getMobility(ebosSimulator, perf, mob, deferred_logger);
|
||||||
|
|
||||||
PerforationRates perf_rates;
|
PerforationRates perf_rates;
|
||||||
double trans_mult = ebosSimulator.problem().template rockCompTransMultiplier<double>(intQuants, cell_idx);
|
double trans_mult = ebosSimulator.problem().template rockCompTransMultiplier<double>(intQuants, cell_idx);
|
||||||
@ -820,61 +820,25 @@ namespace Opm
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<typename TypeTag>
|
template<typename TypeTag>
|
||||||
|
template<class Value>
|
||||||
void
|
void
|
||||||
StandardWell<TypeTag>::
|
StandardWell<TypeTag>::
|
||||||
getMobilityEval(const Simulator& ebosSimulator,
|
getMobility(const Simulator& ebosSimulator,
|
||||||
const int perf,
|
const int perf,
|
||||||
std::vector<EvalWell>& mob,
|
std::vector<Value>& mob,
|
||||||
DeferredLogger& deferred_logger) const
|
DeferredLogger& deferred_logger) const
|
||||||
{
|
{
|
||||||
const int cell_idx = this->well_cells_[perf];
|
auto obtain = [this](const Eval& value)
|
||||||
assert (int(mob.size()) == this->num_components_);
|
{
|
||||||
const auto& intQuants = ebosSimulator.model().intensiveQuantities(cell_idx, /*timeIdx=*/0);
|
if constexpr (std::is_same_v<Value, Scalar>) {
|
||||||
const auto& materialLawManager = ebosSimulator.problem().materialLawManager();
|
return getValue(value);
|
||||||
|
} else {
|
||||||
// either use mobility of the perforation cell or calcualte its own
|
return this->extendEval(value);
|
||||||
// based on passing the saturation table index
|
}
|
||||||
const int satid = this->saturation_table_number_[perf] - 1;
|
};
|
||||||
const int satid_elem = materialLawManager->satnumRegionIdx(cell_idx);
|
WellInterface<TypeTag>::getMobility(ebosSimulator, perf, mob,
|
||||||
if( satid == satid_elem ) { // the same saturation number is used. i.e. just use the mobilty from the cell
|
obtain, deferred_logger);
|
||||||
|
|
||||||
for (unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) {
|
|
||||||
if (!FluidSystem::phaseIsActive(phaseIdx)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned activeCompIdx = Indices::canonicalToActiveComponentIndex(FluidSystem::solventComponentIndex(phaseIdx));
|
|
||||||
mob[activeCompIdx] = this->extendEval(intQuants.mobility(phaseIdx));
|
|
||||||
}
|
|
||||||
if (has_solvent) {
|
|
||||||
mob[Indices::contiSolventEqIdx] = this->extendEval(intQuants.solventMobility());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
const auto& paramsCell = materialLawManager->connectionMaterialLawParams(satid, cell_idx);
|
|
||||||
std::array<Eval,3> relativePerms = { 0.0, 0.0, 0.0 };
|
|
||||||
MaterialLaw::relativePermeabilities(relativePerms, paramsCell, intQuants.fluidState());
|
|
||||||
|
|
||||||
// reset the satnumvalue back to original
|
|
||||||
materialLawManager->connectionMaterialLawParams(satid_elem, cell_idx);
|
|
||||||
|
|
||||||
// compute the mobility
|
|
||||||
for (unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) {
|
|
||||||
if (!FluidSystem::phaseIsActive(phaseIdx)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned activeCompIdx = Indices::canonicalToActiveComponentIndex(FluidSystem::solventComponentIndex(phaseIdx));
|
|
||||||
mob[activeCompIdx] = this->extendEval(relativePerms[phaseIdx] / intQuants.fluidState().viscosity(phaseIdx));
|
|
||||||
}
|
|
||||||
|
|
||||||
// this may not work if viscosity and relperms has been modified?
|
|
||||||
if constexpr (has_solvent) {
|
|
||||||
OPM_DEFLOG_THROW(std::runtime_error, "individual mobility for wells does not work in combination with solvent", deferred_logger);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// modify the water mobility if polymer is present
|
// modify the water mobility if polymer is present
|
||||||
if constexpr (has_polymer) {
|
if constexpr (has_polymer) {
|
||||||
@ -885,81 +849,16 @@ namespace Opm
|
|||||||
// for the cases related to polymer molecular weight, we assume fully mixing
|
// for the cases related to polymer molecular weight, we assume fully mixing
|
||||||
// as a result, the polymer and water share the same viscosity
|
// as a result, the polymer and water share the same viscosity
|
||||||
if constexpr (!Base::has_polymermw) {
|
if constexpr (!Base::has_polymermw) {
|
||||||
updateWaterMobilityWithPolymer(ebosSimulator, perf, mob, deferred_logger);
|
if constexpr (std::is_same_v<Value, Scalar>) {
|
||||||
}
|
std::vector<EvalWell> mob_eval(this->num_components_, {this->primary_variables_.numWellEq() + Indices::numEq, 0.});
|
||||||
}
|
for (size_t i = 0; i < mob.size(); ++i)
|
||||||
}
|
mob_eval[i].setValue(mob[i]);
|
||||||
|
updateWaterMobilityWithPolymer(ebosSimulator, perf, mob_eval, deferred_logger);
|
||||||
template<typename TypeTag>
|
for (size_t i = 0; i < mob.size(); ++i) {
|
||||||
void
|
mob[i] = getValue(mob_eval[i]);
|
||||||
StandardWell<TypeTag>::
|
}
|
||||||
getMobilityScalar(const Simulator& ebosSimulator,
|
} else {
|
||||||
const int perf,
|
updateWaterMobilityWithPolymer(ebosSimulator, perf, mob, deferred_logger);
|
||||||
std::vector<Scalar>& mob,
|
|
||||||
DeferredLogger& deferred_logger) const
|
|
||||||
{
|
|
||||||
const int cell_idx = this->well_cells_[perf];
|
|
||||||
assert (int(mob.size()) == this->num_components_);
|
|
||||||
const auto& intQuants = ebosSimulator.model().intensiveQuantities(cell_idx, /*timeIdx=*/0);
|
|
||||||
const auto& materialLawManager = ebosSimulator.problem().materialLawManager();
|
|
||||||
|
|
||||||
// either use mobility of the perforation cell or calcualte its own
|
|
||||||
// based on passing the saturation table index
|
|
||||||
const int satid = this->saturation_table_number_[perf] - 1;
|
|
||||||
const int satid_elem = materialLawManager->satnumRegionIdx(cell_idx);
|
|
||||||
if( satid == satid_elem ) { // the same saturation number is used. i.e. just use the mobilty from the cell
|
|
||||||
|
|
||||||
for (unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) {
|
|
||||||
if (!FluidSystem::phaseIsActive(phaseIdx)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned activeCompIdx = Indices::canonicalToActiveComponentIndex(FluidSystem::solventComponentIndex(phaseIdx));
|
|
||||||
mob[activeCompIdx] = getValue(intQuants.mobility(phaseIdx));
|
|
||||||
}
|
|
||||||
if (has_solvent) {
|
|
||||||
mob[Indices::contiSolventEqIdx] = getValue(intQuants.solventMobility());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
const auto& paramsCell = materialLawManager->connectionMaterialLawParams(satid, cell_idx);
|
|
||||||
std::array<Eval,3> relativePerms = { 0.0, 0.0, 0.0 };
|
|
||||||
MaterialLaw::relativePermeabilities(relativePerms, paramsCell, intQuants.fluidState());
|
|
||||||
|
|
||||||
// reset the satnumvalue back to original
|
|
||||||
materialLawManager->connectionMaterialLawParams(satid_elem, cell_idx);
|
|
||||||
|
|
||||||
// compute the mobility
|
|
||||||
for (unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) {
|
|
||||||
if (!FluidSystem::phaseIsActive(phaseIdx)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned activeCompIdx = Indices::canonicalToActiveComponentIndex(FluidSystem::solventComponentIndex(phaseIdx));
|
|
||||||
mob[activeCompIdx] = getValue(relativePerms[phaseIdx]) / getValue(intQuants.fluidState().viscosity(phaseIdx));
|
|
||||||
}
|
|
||||||
|
|
||||||
// this may not work if viscosity and relperms has been modified?
|
|
||||||
if constexpr (has_solvent) {
|
|
||||||
OPM_DEFLOG_THROW(std::runtime_error, "individual mobility for wells does not work in combination with solvent", deferred_logger);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// modify the water mobility if polymer is present
|
|
||||||
if constexpr (has_polymer) {
|
|
||||||
if (!FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
|
|
||||||
OPM_DEFLOG_THROW(std::runtime_error, "Water is required when polymer is active", deferred_logger);
|
|
||||||
}
|
|
||||||
|
|
||||||
// for the cases related to polymer molecular weight, we assume fully mixing
|
|
||||||
// as a result, the polymer and water share the same viscosity
|
|
||||||
if constexpr (!Base::has_polymermw) {
|
|
||||||
std::vector<EvalWell> mob_eval(this->num_components_, {this->primary_variables_.numWellEq() + Indices::numEq, 0.});
|
|
||||||
for (size_t i = 0; i < mob.size(); ++i)
|
|
||||||
mob_eval[i].setValue(mob[i]);
|
|
||||||
updateWaterMobilityWithPolymer(ebosSimulator, perf, mob_eval, deferred_logger);
|
|
||||||
for (size_t i = 0; i < mob.size(); ++i) {
|
|
||||||
mob[i] = getValue(mob_eval[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1043,7 +942,7 @@ namespace Opm
|
|||||||
|
|
||||||
for (int perf = 0; perf < this->number_of_perforations_; ++perf) {
|
for (int perf = 0; perf < this->number_of_perforations_; ++perf) {
|
||||||
std::vector<Scalar> mob(this->num_components_, 0.0);
|
std::vector<Scalar> mob(this->num_components_, 0.0);
|
||||||
getMobilityScalar(ebos_simulator, perf, mob, deferred_logger);
|
getMobility(ebos_simulator, perf, mob, deferred_logger);
|
||||||
|
|
||||||
const int cell_idx = this->well_cells_[perf];
|
const int cell_idx = this->well_cells_[perf];
|
||||||
const auto& int_quantities = ebos_simulator.model().intensiveQuantities(cell_idx, /*timeIdx=*/ 0);
|
const auto& int_quantities = ebos_simulator.model().intensiveQuantities(cell_idx, /*timeIdx=*/ 0);
|
||||||
@ -1450,7 +1349,7 @@ namespace Opm
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::vector<EvalWell> mob(this->num_components_, {this->primary_variables_.numWellEq() + Indices::numEq, 0.0});
|
std::vector<EvalWell> mob(this->num_components_, {this->primary_variables_.numWellEq() + Indices::numEq, 0.0});
|
||||||
getMobilityEval(ebosSimulator, static_cast<int>(subsetPerfID), mob, deferred_logger);
|
getMobility(ebosSimulator, static_cast<int>(subsetPerfID), mob, deferred_logger);
|
||||||
|
|
||||||
const auto& fs = fluidState(subsetPerfID);
|
const auto& fs = fluidState(subsetPerfID);
|
||||||
setToZero(connPI);
|
setToZero(connPI);
|
||||||
@ -1652,7 +1551,7 @@ namespace Opm
|
|||||||
const auto& intQuants = ebosSimulator.model().intensiveQuantities(cell_idx, /*timeIdx=*/ 0);
|
const auto& intQuants = ebosSimulator.model().intensiveQuantities(cell_idx, /*timeIdx=*/ 0);
|
||||||
// flux for each perforation
|
// flux for each perforation
|
||||||
std::vector<Scalar> mob(this->num_components_, 0.);
|
std::vector<Scalar> mob(this->num_components_, 0.);
|
||||||
getMobilityScalar(ebosSimulator, perf, mob, deferred_logger);
|
getMobility(ebosSimulator, perf, mob, deferred_logger);
|
||||||
double trans_mult = ebosSimulator.problem().template rockCompTransMultiplier<double>(intQuants, cell_idx);
|
double trans_mult = ebosSimulator.problem().template rockCompTransMultiplier<double>(intQuants, cell_idx);
|
||||||
const double Tw = this->well_index_[perf] * trans_mult;
|
const double Tw = this->well_index_[perf] * trans_mult;
|
||||||
|
|
||||||
@ -2509,7 +2408,7 @@ namespace Opm
|
|||||||
const int cell_idx = this->well_cells_[perf];
|
const int cell_idx = this->well_cells_[perf];
|
||||||
const auto& intQuants = ebosSimulator.model().intensiveQuantities(cell_idx, /*timeIdx=*/ 0);
|
const auto& intQuants = ebosSimulator.model().intensiveQuantities(cell_idx, /*timeIdx=*/ 0);
|
||||||
std::vector<Scalar> mob(this->num_components_, 0.);
|
std::vector<Scalar> mob(this->num_components_, 0.);
|
||||||
getMobilityScalar(ebosSimulator, perf, mob, deferred_logger);
|
getMobility(ebosSimulator, perf, mob, deferred_logger);
|
||||||
std::vector<Scalar> cq_s(this->num_components_, 0.);
|
std::vector<Scalar> cq_s(this->num_components_, 0.);
|
||||||
double trans_mult = ebosSimulator.problem().template rockCompTransMultiplier<double>(intQuants, cell_idx);
|
double trans_mult = ebosSimulator.problem().template rockCompTransMultiplier<double>(intQuants, cell_idx);
|
||||||
const double Tw = this->well_index_[perf] * trans_mult;
|
const double Tw = this->well_index_[perf] * trans_mult;
|
||||||
|
@ -329,14 +329,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// simulation parameters
|
// simulation parameters
|
||||||
const ModelParameters& param_;
|
const ModelParameters& param_;
|
||||||
|
|
||||||
std::vector<RateVector> connectionRates_;
|
std::vector<RateVector> connectionRates_;
|
||||||
|
|
||||||
std::vector< Scalar > B_avg_;
|
std::vector< Scalar > B_avg_;
|
||||||
|
|
||||||
bool changed_to_stopped_this_step_ = false;
|
bool changed_to_stopped_this_step_ = false;
|
||||||
|
|
||||||
double wpolymer() const;
|
double wpolymer() const;
|
||||||
@ -394,6 +390,15 @@ protected:
|
|||||||
|
|
||||||
Eval getPerfCellPressure(const FluidState& fs) const;
|
Eval getPerfCellPressure(const FluidState& fs) const;
|
||||||
|
|
||||||
|
// get the mobility for specific perforation
|
||||||
|
template<class Value, class Callback>
|
||||||
|
void getMobility(const Simulator& ebosSimulator,
|
||||||
|
const int perf,
|
||||||
|
std::vector<Value>& mob,
|
||||||
|
Callback& extendEval,
|
||||||
|
[[maybe_unused]] DeferredLogger& deferred_logger) const;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1203,4 +1203,68 @@ namespace Opm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename TypeTag>
|
||||||
|
template<class Value, class Callback>
|
||||||
|
void
|
||||||
|
WellInterface<TypeTag>::
|
||||||
|
getMobility(const Simulator& ebosSimulator,
|
||||||
|
const int perf,
|
||||||
|
std::vector<Value>& mob,
|
||||||
|
Callback& extendEval,
|
||||||
|
[[maybe_unused]] DeferredLogger& deferred_logger) const
|
||||||
|
{
|
||||||
|
auto relpermArray = []()
|
||||||
|
{
|
||||||
|
if constexpr (std::is_same_v<Value, Scalar>) {
|
||||||
|
return std::array<Scalar,3>{};
|
||||||
|
} else {
|
||||||
|
return std::array<Eval,3>{};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const int cell_idx = this->well_cells_[perf];
|
||||||
|
assert (int(mob.size()) == this->num_components_);
|
||||||
|
const auto& intQuants = ebosSimulator.model().intensiveQuantities(cell_idx, /*timeIdx=*/0);
|
||||||
|
const auto& materialLawManager = ebosSimulator.problem().materialLawManager();
|
||||||
|
|
||||||
|
// either use mobility of the perforation cell or calculate its own
|
||||||
|
// based on passing the saturation table index
|
||||||
|
const int satid = this->saturation_table_number_[perf] - 1;
|
||||||
|
const int satid_elem = materialLawManager->satnumRegionIdx(cell_idx);
|
||||||
|
if (satid == satid_elem) { // the same saturation number is used. i.e. just use the mobilty from the cell
|
||||||
|
for (unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) {
|
||||||
|
if (!FluidSystem::phaseIsActive(phaseIdx)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned activeCompIdx = Indices::canonicalToActiveComponentIndex(FluidSystem::solventComponentIndex(phaseIdx));
|
||||||
|
mob[activeCompIdx] = extendEval(intQuants.mobility(phaseIdx));
|
||||||
|
}
|
||||||
|
if constexpr (has_solvent) {
|
||||||
|
mob[Indices::contiSolventEqIdx] = extendEval(intQuants.solventMobility());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const auto& paramsCell = materialLawManager->connectionMaterialLawParams(satid, cell_idx);
|
||||||
|
auto relativePerms = relpermArray();
|
||||||
|
MaterialLaw::relativePermeabilities(relativePerms, paramsCell, intQuants.fluidState());
|
||||||
|
|
||||||
|
// reset the satnumvalue back to original
|
||||||
|
materialLawManager->connectionMaterialLawParams(satid_elem, cell_idx);
|
||||||
|
|
||||||
|
// compute the mobility
|
||||||
|
for (unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) {
|
||||||
|
if (!FluidSystem::phaseIsActive(phaseIdx)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned activeCompIdx = Indices::canonicalToActiveComponentIndex(FluidSystem::solventComponentIndex(phaseIdx));
|
||||||
|
mob[activeCompIdx] = extendEval(relativePerms[phaseIdx] / intQuants.fluidState().viscosity(phaseIdx));
|
||||||
|
}
|
||||||
|
|
||||||
|
// this may not work if viscosity and relperms has been modified?
|
||||||
|
if constexpr (has_solvent) {
|
||||||
|
OPM_DEFLOG_THROW(std::runtime_error, "individual mobility for wells does not work in combination with solvent", deferred_logger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Opm
|
} // namespace Opm
|
||||||
|
Loading…
Reference in New Issue
Block a user