mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Merge pull request #2851 from osae/extboSimulators
Alternative solvent extension for the black oil model.
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
# include <flow/flow_ebos_oilwater.hpp>
|
||||
# include <flow/flow_ebos_solvent.hpp>
|
||||
# include <flow/flow_ebos_polymer.hpp>
|
||||
# include <flow/flow_ebos_extbo.hpp>
|
||||
# include <flow/flow_ebos_foam.hpp>
|
||||
# include <flow/flow_ebos_brine.hpp>
|
||||
# include <flow/flow_ebos_oilwater_brine.hpp>
|
||||
@@ -292,6 +293,14 @@ namespace Opm
|
||||
std::move(summaryConfig_));
|
||||
return Opm::flowEbosSolventMain(argc_, argv_, outputCout_, outputFiles_);
|
||||
}
|
||||
// Extended BO case
|
||||
else if ( phases.active( Opm::Phase::ZFRACTION ) ) {
|
||||
Opm::flowEbosExtboSetDeck(setupTime_, std::move(deck_),
|
||||
std::move(eclipseState_),
|
||||
std::move(schedule_),
|
||||
std::move(summaryConfig_));
|
||||
return Opm::flowEbosExtboMain(argc_, argv_, outputCout_, outputFiles_);
|
||||
}
|
||||
// Energy case
|
||||
else if (eclipseState_->getSimulationConfig().isThermal()) {
|
||||
Opm::flowEbosEnergySetDeck(setupTime_, std::move(deck_),
|
||||
|
||||
@@ -296,6 +296,7 @@ namespace Opm {
|
||||
const ModelParameters param_;
|
||||
bool terminal_output_;
|
||||
bool has_solvent_;
|
||||
bool has_zFraction_;
|
||||
bool has_polymer_;
|
||||
std::vector<int> pvt_region_idx_;
|
||||
PhaseUsage phase_usage_;
|
||||
|
||||
@@ -33,6 +33,7 @@ namespace Opm {
|
||||
BlackoilWellModel(Simulator& ebosSimulator)
|
||||
: ebosSimulator_(ebosSimulator)
|
||||
, has_solvent_(getPropValue<TypeTag, Properties::EnableSolvent>())
|
||||
, has_zFraction_(getPropValue<TypeTag, Properties::EnableExtbo>())
|
||||
, has_polymer_(getPropValue<TypeTag, Properties::EnablePolymer>())
|
||||
{
|
||||
terminal_output_ = false;
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
#include <opm/models/blackoil/blackoilpolymermodules.hh>
|
||||
#include <opm/models/blackoil/blackoilsolventmodules.hh>
|
||||
#include <opm/models/blackoil/blackoilextbomodules.hh>
|
||||
#include <opm/models/blackoil/blackoilfoammodules.hh>
|
||||
#include <opm/models/blackoil/blackoilbrinemodules.hh>
|
||||
|
||||
@@ -74,6 +75,7 @@ namespace Opm
|
||||
using Base::numEq;
|
||||
|
||||
using Base::has_solvent;
|
||||
using Base::has_zFraction;
|
||||
using Base::has_polymer;
|
||||
using Base::has_foam;
|
||||
using Base::has_brine;
|
||||
@@ -89,9 +91,10 @@ namespace Opm
|
||||
static const int numEnergyEq = Indices::numEnergy;
|
||||
static const int numFoamEq = Indices::numFoam;
|
||||
static const int numBrineEq = Indices::numBrine;
|
||||
static const int numExtbos = Indices::numExtbos;
|
||||
|
||||
// number of the conservation equations
|
||||
static const int numWellConservationEq = numEq - numPolymerEq - numEnergyEq - numFoamEq - numBrineEq;
|
||||
static const int numWellConservationEq = numEq - numPolymerEq - numEnergyEq - numFoamEq - numBrineEq - numExtbos;
|
||||
// number of the well control equations
|
||||
static const int numWellControlEq = 1;
|
||||
// number of the well equations that will always be used
|
||||
@@ -147,6 +150,7 @@ namespace Opm
|
||||
typedef DenseAd::DynamicEvaluation<Scalar, numStaticWellEq + numEq + 1> EvalWell;
|
||||
|
||||
using Base::contiSolventEqIdx;
|
||||
using Base::contiZfracEqIdx;
|
||||
using Base::contiPolymerEqIdx;
|
||||
using Base::contiFoamEqIdx;
|
||||
using Base::contiBrineEqIdx;
|
||||
@@ -523,6 +527,7 @@ namespace Opm
|
||||
std::vector<RateVector>& connectionRates,
|
||||
std::vector<EvalWell>& cq_s,
|
||||
EvalWell& water_flux_s,
|
||||
EvalWell& cq_s_zfrac_effective,
|
||||
Opm::DeferredLogger& deferred_logger) const;
|
||||
|
||||
// check whether the well is operable under the current reservoir condition
|
||||
|
||||
@@ -388,6 +388,12 @@ namespace Opm
|
||||
b_perfcells_dense[contiSolventEqIdx] = extendEval(intQuants.solventInverseFormationVolumeFactor());
|
||||
}
|
||||
|
||||
if (has_zFraction && this->isInjector()) {
|
||||
const unsigned gasCompIdx = Indices::canonicalToActiveComponentIndex(FluidSystem::gasCompIdx);
|
||||
b_perfcells_dense[gasCompIdx] *= (1.0 - wsolvent());
|
||||
b_perfcells_dense[gasCompIdx] += wsolvent()*intQuants.zPureInvFormationVolumeFactor().value();
|
||||
}
|
||||
|
||||
// Pressure drawdown (also used to determine direction of flow)
|
||||
const EvalWell well_pressure = bhp + perf_pressure_diffs_[perf];
|
||||
EvalWell drawdown = pressure - well_pressure;
|
||||
@@ -605,7 +611,8 @@ namespace Opm
|
||||
// Calculate perforation quantities.
|
||||
std::vector<EvalWell> cq_s(num_components_, {numWellEq_ + numEq, 0.0});
|
||||
EvalWell water_flux_s{numWellEq_ + numEq, 0.0};
|
||||
calculateSinglePerf(ebosSimulator, perf, well_state, connectionRates, cq_s, water_flux_s, deferred_logger);
|
||||
EvalWell cq_s_zfrac_effective{numWellEq_ + numEq, 0.0};
|
||||
calculateSinglePerf(ebosSimulator, perf, well_state, connectionRates, cq_s, water_flux_s, cq_s_zfrac_effective, deferred_logger);
|
||||
|
||||
// Equation assembly for this perforation.
|
||||
if (has_polymer && this->has_polymermw && this->isInjector()) {
|
||||
@@ -639,6 +646,12 @@ namespace Opm
|
||||
well_state.perfPhaseRates()[(first_perf_ + perf) * np + ebosCompIdxToFlowCompIdx(componentIdx)] = cq_s[componentIdx].value();
|
||||
}
|
||||
}
|
||||
|
||||
if (has_zFraction) {
|
||||
for (int pvIdx = 0; pvIdx < numWellEq_; ++pvIdx) {
|
||||
duneC_[0][cell_idx][pvIdx][contiZfracEqIdx] -= cq_s_zfrac_effective.derivative(pvIdx+numEq);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Update the connection
|
||||
connectionRates_ = connectionRates;
|
||||
@@ -686,6 +699,7 @@ namespace Opm
|
||||
std::vector<RateVector>& connectionRates,
|
||||
std::vector<EvalWell>& cq_s,
|
||||
EvalWell& water_flux_s,
|
||||
EvalWell& cq_s_zfrac_effective,
|
||||
Opm::DeferredLogger& deferred_logger) const
|
||||
{
|
||||
const bool allow_cf = getAllowCrossFlow() || openCrossFlowAvoidSingularity(ebosSimulator);
|
||||
@@ -812,6 +826,22 @@ namespace Opm
|
||||
connectionRates[perf][contiFoamEqIdx] = Base::restrictEval(cq_s_foam);
|
||||
}
|
||||
|
||||
if (has_zFraction) {
|
||||
// TODO: the application of well efficiency factor has not been tested with an example yet
|
||||
const unsigned gasCompIdx = Indices::canonicalToActiveComponentIndex(FluidSystem::gasCompIdx);
|
||||
cq_s_zfrac_effective = cq_s[gasCompIdx];
|
||||
if (this->isInjector()) {
|
||||
cq_s_zfrac_effective *= wsolvent();
|
||||
} else if (cq_s_zfrac_effective.value() != 0.0) {
|
||||
const double dis_gas_frac = perf_dis_gas_rate / cq_s_zfrac_effective.value();
|
||||
cq_s_zfrac_effective *= extendEval(dis_gas_frac*intQuants.xVolume() + (1.0-dis_gas_frac)*intQuants.yVolume());
|
||||
}
|
||||
well_state.perfRateSolvent()[first_perf_ + perf] = cq_s_zfrac_effective.value();
|
||||
|
||||
cq_s_zfrac_effective *= well_efficiency_factor_;
|
||||
connectionRates[perf][contiZfracEqIdx] = Base::restrictEval(cq_s_zfrac_effective);
|
||||
}
|
||||
|
||||
if (has_brine) {
|
||||
// TODO: the application of well efficiency factor has not been tested with an example yet
|
||||
const unsigned waterCompIdx = Indices::canonicalToActiveComponentIndex(FluidSystem::waterCompIdx);
|
||||
@@ -1978,7 +2008,7 @@ namespace Opm
|
||||
const double oilrate = std::abs(well_state.wellRates()[oilpos_well]); //in order to handle negative rates in producers
|
||||
rvmax_perf[perf] = FluidSystem::gasPvt().saturatedOilVaporizationFactor(fs.pvtRegionIndex(), temperature, p_avg);
|
||||
if (oilrate > 0) {
|
||||
const double gasrate = std::abs(well_state.wellRates()[gaspos_well]) - well_state.solventWellRate(w);
|
||||
const double gasrate = std::abs(well_state.wellRates()[gaspos_well]) - (has_solvent ? well_state.solventWellRate(w) : 0.0);
|
||||
double rv = 0.0;
|
||||
if (gasrate > 0) {
|
||||
rv = oilrate / gasrate;
|
||||
@@ -2003,7 +2033,7 @@ namespace Opm
|
||||
if (gasPresent) {
|
||||
rsmax_perf[perf] = FluidSystem::oilPvt().saturatedGasDissolutionFactor(fs.pvtRegionIndex(), temperature, p_avg);
|
||||
const int gaspos_well = pu.phase_pos[Gas] + w * pu.num_phases;
|
||||
const double gasrate = std::abs(well_state.wellRates()[gaspos_well]) - well_state.solventWellRate(w);
|
||||
const double gasrate = std::abs(well_state.wellRates()[gaspos_well]) - (has_solvent ? well_state.solventWellRate(w) : 0.0);
|
||||
if (gasrate > 0) {
|
||||
const double oilrate = std::abs(well_state.wellRates()[oilpos_well]);
|
||||
double rs = 0.0;
|
||||
@@ -2224,7 +2254,7 @@ namespace Opm
|
||||
{
|
||||
// the following implementation assume that the polymer is always after the w-o-g phases
|
||||
// For the polymer, energy and foam cases, there is one more mass balance equations of reservoir than wells
|
||||
assert((int(B_avg.size()) == num_components_) || has_polymer || has_energy || has_foam || has_brine);
|
||||
assert((int(B_avg.size()) == num_components_) || has_polymer || has_energy || has_foam || has_brine || has_zFraction);
|
||||
|
||||
const double tol_wells = param_.tolerance_wells_;
|
||||
const double maxResidualAllowed = param_.max_residual_allowed_;
|
||||
@@ -2900,7 +2930,8 @@ namespace Opm
|
||||
primary_variables_[WFrac] = scalingFactor(pu.phase_pos[Water]) * well_state.wellRates()[np*well_index + pu.phase_pos[Water]] / total_well_rate;
|
||||
}
|
||||
if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
|
||||
primary_variables_[GFrac] = scalingFactor(pu.phase_pos[Gas]) * (well_state.wellRates()[np*well_index + pu.phase_pos[Gas]] - well_state.solventWellRate(well_index)) / total_well_rate ;
|
||||
primary_variables_[GFrac] = scalingFactor(pu.phase_pos[Gas]) * (well_state.wellRates()[np*well_index + pu.phase_pos[Gas]]
|
||||
- (has_solvent ? well_state.solventWellRate(well_index) : 0.0) ) / total_well_rate ;
|
||||
}
|
||||
if (has_solvent) {
|
||||
primary_variables_[SFrac] = scalingFactor(pu.phase_pos[Gas]) * well_state.solventWellRate(well_index) / total_well_rate ;
|
||||
@@ -2919,8 +2950,9 @@ namespace Opm
|
||||
|
||||
if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
|
||||
if (phase == InjectorType::GAS) {
|
||||
primary_variables_[GFrac] = 1.0 - wsolvent();
|
||||
primary_variables_[GFrac] = 1.0;
|
||||
if (has_solvent) {
|
||||
primary_variables_[GFrac] = 1.0 - wsolvent();
|
||||
primary_variables_[SFrac] = wsolvent();
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -92,6 +92,7 @@ namespace Opm
|
||||
typedef DenseAd::Evaluation<double, /*size=*/numEq> Eval;
|
||||
|
||||
static const bool has_solvent = getPropValue<TypeTag, Properties::EnableSolvent>();
|
||||
static const bool has_zFraction = getPropValue<TypeTag, Properties::EnableExtbo>();
|
||||
static const bool has_polymer = getPropValue<TypeTag, Properties::EnablePolymer>();
|
||||
static const bool has_energy = getPropValue<TypeTag, Properties::EnableEnergy>();
|
||||
static const bool has_temperature = getPropValue<TypeTag, Properties::EnableTemperature>();
|
||||
@@ -100,6 +101,7 @@ namespace Opm
|
||||
static const bool has_foam = getPropValue<TypeTag, Properties::EnableFoam>();
|
||||
static const bool has_brine = getPropValue<TypeTag, Properties::EnableBrine>();
|
||||
static const int contiSolventEqIdx = Indices::contiSolventEqIdx;
|
||||
static const int contiZfracEqIdx = Indices::contiZfracEqIdx;
|
||||
static const int contiPolymerEqIdx = Indices::contiPolymerEqIdx;
|
||||
// index for the polymer molecular weight continuity equation
|
||||
static const int contiPolymerMWEqIdx = Indices::contiPolymerMWEqIdx;
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace Opm
|
||||
|
||||
wsolvent_ = 0.0;
|
||||
|
||||
if (has_solvent && well.isInjector()) {
|
||||
if ((has_solvent || has_zFraction) && well.isInjector()) {
|
||||
auto injectorType = well_ecl_.injectorType();
|
||||
if (injectorType == InjectorType::GAS) {
|
||||
wsolvent_ = well_ecl_.getSolventFraction();
|
||||
|
||||
@@ -163,7 +163,6 @@ namespace Opm
|
||||
|
||||
perfRateBrine_.clear();
|
||||
perfRateBrine_.resize(nperf, 0.0);
|
||||
|
||||
// intialize wells that have been there before
|
||||
// order may change so the mapping is based on the well name
|
||||
if (prevState && !prevState->wellMap().empty()) {
|
||||
@@ -576,7 +575,7 @@ namespace Opm
|
||||
well.rates.set( rt::well_potential_gas, this->well_potentials_[well_rate_index + pu.phase_pos[Gas]] );
|
||||
}
|
||||
|
||||
if ( pu.has_solvent ) {
|
||||
if ( pu.has_solvent || pu.has_zFraction) {
|
||||
well.rates.set( rt::solvent, solventWellRate(w) );
|
||||
}
|
||||
|
||||
@@ -621,7 +620,7 @@ namespace Opm
|
||||
if ( pu.has_brine ) {
|
||||
comp.rates.set( rt::brine, this->perfRateBrine()[wt.second[1] + local_comp_index]);
|
||||
}
|
||||
if ( pu.has_solvent ) {
|
||||
if ( pu.has_solvent || pu.has_zFraction) {
|
||||
comp.rates.set( rt::solvent, this->perfRateSolvent()[wt.second[1] + local_comp_index]);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user