mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Merge pull request #1091 from GitPaean/calculating_surface_volume_fraction
[WIP] using surface volume fraction instead of wellVolumeFraction() and wellVolumeFractionScaled() in a few places
This commit is contained in:
commit
eaf9d136bf
@ -310,6 +310,9 @@ enum WellVariablePositions {
|
|||||||
|
|
||||||
EvalWell wellVolumeFractionScaled(const int wellIdx, const int phaseIdx) const;
|
EvalWell wellVolumeFractionScaled(const int wellIdx, const int phaseIdx) const;
|
||||||
|
|
||||||
|
// Q_p / (Q_w + Q_g + Q_o) for three phase cases.
|
||||||
|
EvalWell wellSurfaceVolumeFraction(const int well_index, const int phase) const;
|
||||||
|
|
||||||
bool checkRateEconLimits(const WellEconProductionLimits& econ_production_limits,
|
bool checkRateEconLimits(const WellEconProductionLimits& econ_production_limits,
|
||||||
const WellState& well_state,
|
const WellState& well_state,
|
||||||
const int well_number) const;
|
const int well_number) const;
|
||||||
|
@ -231,7 +231,7 @@ namespace Opm {
|
|||||||
|
|
||||||
// add vol * dF/dt + Q to the well equations;
|
// add vol * dF/dt + Q to the well equations;
|
||||||
for (int p1 = 0; p1 < np; ++p1) {
|
for (int p1 = 0; p1 < np; ++p1) {
|
||||||
EvalWell resWell_loc = (wellVolumeFraction(w, p1) - F0_[w + nw*p1]) * volume / dt;
|
EvalWell resWell_loc = (wellSurfaceVolumeFraction(w, p1) - F0_[w + nw*p1]) * volume / dt;
|
||||||
resWell_loc += getQs(w, p1);
|
resWell_loc += getQs(w, p1);
|
||||||
for (int p2 = 0; p2 < np; ++p2) {
|
for (int p2 = 0; p2 < np; ++p2) {
|
||||||
invDuneD_[w][w][flowPhaseToEbosCompIdx(p1)][flowToEbosPvIdx(p2)] += resWell_loc.derivative(p2+blocksize);
|
invDuneD_[w][w][flowPhaseToEbosCompIdx(p1)][flowToEbosPvIdx(p2)] += resWell_loc.derivative(p2+blocksize);
|
||||||
@ -680,7 +680,7 @@ namespace Opm {
|
|||||||
const int nw = wells().number_of_wells;
|
const int nw = wells().number_of_wells;
|
||||||
for (int phaseIdx = 0; phaseIdx < np; ++phaseIdx) {
|
for (int phaseIdx = 0; phaseIdx < np; ++phaseIdx) {
|
||||||
for (int w = 0; w < nw; ++w) {
|
for (int w = 0; w < nw; ++w) {
|
||||||
F0_[w + nw * phaseIdx] = wellVolumeFraction(w,phaseIdx).value();
|
F0_[w + nw * phaseIdx] = wellSurfaceVolumeFraction(w, phaseIdx).value();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -703,7 +703,7 @@ namespace Opm {
|
|||||||
std::vector<EvalWell> cmix_s(np,0.0);
|
std::vector<EvalWell> cmix_s(np,0.0);
|
||||||
for (int phase = 0; phase < np; ++phase) {
|
for (int phase = 0; phase < np; ++phase) {
|
||||||
//int ebosPhaseIdx = flowPhaseToEbosPhaseIdx(phase);
|
//int ebosPhaseIdx = flowPhaseToEbosPhaseIdx(phase);
|
||||||
cmix_s[phase] = wellVolumeFraction(w,phase);
|
cmix_s[phase] = wellSurfaceVolumeFraction(w, phase);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& fs = intQuants.fluidState();
|
const auto& fs = intQuants.fluidState();
|
||||||
@ -1939,6 +1939,8 @@ namespace Opm {
|
|||||||
const int nw = wells().number_of_wells;
|
const int nw = wells().number_of_wells;
|
||||||
const double target_rate = well_controls_get_current_target(wc);
|
const double target_rate = well_controls_get_current_target(wc);
|
||||||
|
|
||||||
|
// TODO: the formulation for the injectors decides it only work with single phase
|
||||||
|
// surface rate injection control. Improvement will be required.
|
||||||
if (wells().type[wellIdx] == INJECTOR) {
|
if (wells().type[wellIdx] == INJECTOR) {
|
||||||
const double comp_frac = wells().comp_frac[np*wellIdx + phaseIdx];
|
const double comp_frac = wells().comp_frac[np*wellIdx + phaseIdx];
|
||||||
if (comp_frac == 0.0) {
|
if (comp_frac == 0.0) {
|
||||||
@ -1973,21 +1975,29 @@ namespace Opm {
|
|||||||
|
|
||||||
// when it is a single phase rate limit
|
// when it is a single phase rate limit
|
||||||
if (num_phases_under_rate_control == 1) {
|
if (num_phases_under_rate_control == 1) {
|
||||||
if (distr[phaseIdx] == 1.0) {
|
|
||||||
|
// looking for the phase under control
|
||||||
|
int phase_under_control = -1;
|
||||||
|
for (int phase = 0; phase < np; ++phase) {
|
||||||
|
if (distr[phase] > 0.0) {
|
||||||
|
phase_under_control = phase;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(phase_under_control >= 0);
|
||||||
|
|
||||||
|
if (phaseIdx == phase_under_control) {
|
||||||
qs.setValue(target_rate);
|
qs.setValue(target_rate);
|
||||||
return qs;
|
return qs;
|
||||||
}
|
}
|
||||||
|
|
||||||
int currentControlIdx = 0;
|
// TODO: not sure why the single phase under control will have near zero fraction
|
||||||
for (int i = 0; i < np; ++i) {
|
|
||||||
currentControlIdx += wells().comp_frac[np*wellIdx + i] * i;
|
|
||||||
}
|
|
||||||
|
|
||||||
const double eps = 1e-6;
|
const double eps = 1e-6;
|
||||||
if (wellVolumeFractionScaled(wellIdx,currentControlIdx) < eps) {
|
if (wellVolumeFractionScaled(wellIdx, phase_under_control) < eps) {
|
||||||
return qs;
|
return qs;
|
||||||
}
|
}
|
||||||
return (target_rate * wellVolumeFractionScaled(wellIdx,phaseIdx) / wellVolumeFractionScaled(wellIdx,currentControlIdx));
|
return (target_rate * wellVolumeFractionScaled(wellIdx,phaseIdx) / wellVolumeFractionScaled(wellIdx, phase_under_control));
|
||||||
}
|
}
|
||||||
|
|
||||||
// when it is a combined two phase rate limit, such like LRAT
|
// when it is a combined two phase rate limit, such like LRAT
|
||||||
@ -2002,12 +2012,19 @@ namespace Opm {
|
|||||||
return (target_rate * wellVolumeFractionScaled(wellIdx,phaseIdx) / combined_volume_fraction);
|
return (target_rate * wellVolumeFractionScaled(wellIdx,phaseIdx) / combined_volume_fraction);
|
||||||
}
|
}
|
||||||
|
|
||||||
// suppose three phase combined limit is the same with RESV
|
// TODO: three phase surface rate control is not tested yet
|
||||||
// not tested yet.
|
if (num_phases_under_rate_control == 3) {
|
||||||
|
return target_rate * wellSurfaceVolumeFraction(wellIdx, phaseIdx);
|
||||||
|
}
|
||||||
|
} else if (well_controls_get_current_type(wc) == RESERVOIR_RATE) {
|
||||||
|
// ReservoirRate
|
||||||
|
return target_rate * wellVolumeFractionScaled(wellIdx, phaseIdx);
|
||||||
|
} else {
|
||||||
|
OPM_THROW(std::logic_error, "Unknown control type for well " << wells().name[wellIdx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReservoirRate
|
// avoid warning of condition reaches end of non-void function
|
||||||
return target_rate * wellVolumeFractionScaled(wellIdx,phaseIdx);
|
return qs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2062,6 +2079,26 @@ namespace Opm {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<typename FluidSystem, typename BlackoilIndices>
|
||||||
|
typename StandardWellsDense<FluidSystem, BlackoilIndices>::EvalWell
|
||||||
|
StandardWellsDense<FluidSystem, BlackoilIndices>::
|
||||||
|
wellSurfaceVolumeFraction(const int well_index, const int phase) const
|
||||||
|
{
|
||||||
|
EvalWell sum_volume_fraction_scaled = 0.;
|
||||||
|
const int np = wells().number_of_phases;
|
||||||
|
for (int p = 0; p < np; ++p) {
|
||||||
|
sum_volume_fraction_scaled += wellVolumeFractionScaled(well_index, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(sum_volume_fraction_scaled.value() != 0.);
|
||||||
|
|
||||||
|
return wellVolumeFractionScaled(well_index, phase) / sum_volume_fraction_scaled;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<typename FluidSystem, typename BlackoilIndices>
|
template<typename FluidSystem, typename BlackoilIndices>
|
||||||
bool
|
bool
|
||||||
StandardWellsDense<FluidSystem, BlackoilIndices>::
|
StandardWellsDense<FluidSystem, BlackoilIndices>::
|
||||||
|
Loading…
Reference in New Issue
Block a user