diff --git a/opm/simulators/wells/StandardWellEval.cpp b/opm/simulators/wells/StandardWellEval.cpp index 49bbf30ad..76798f0cc 100644 --- a/opm/simulators/wells/StandardWellEval.cpp +++ b/opm/simulators/wells/StandardWellEval.cpp @@ -248,104 +248,10 @@ void StandardWellEval:: updatePrimaryVariables(const WellState& well_state, DeferredLogger& deferred_logger) const { - static constexpr int Gas = WellInterfaceIndices::Gas; - static constexpr int Oil = WellInterfaceIndices::Oil; - static constexpr int Water = WellInterfaceIndices::Water; + if (!baseif_.isOperableAndSolvable() && !baseif_.wellIsStopped()) + return; - if (!baseif_.isOperableAndSolvable() && !baseif_.wellIsStopped()) return; - - const int well_index = baseif_.indexOfWell(); - const int np = baseif_.numPhases(); - const auto& pu = baseif_.phaseUsage(); - const auto& ws = well_state.well(well_index); - // the weighted total well rate - double total_well_rate = 0.0; - for (int p = 0; p < np; ++p) { - total_well_rate += baseif_.scalingFactor(p) * ws.surface_rates[p]; - } - - // Not: for the moment, the first primary variable for the injectors is not G_total. The injection rate - // under surface condition is used here - if (baseif_.isInjector()) { - switch (baseif_.wellEcl().injectorType()) { - case InjectorType::WATER: - primary_variables_.value_[WQTotal] = ws.surface_rates[pu.phase_pos[Water]]; - break; - case InjectorType::GAS: - primary_variables_.value_[WQTotal] = ws.surface_rates[pu.phase_pos[Gas]]; - break; - case InjectorType::OIL: - primary_variables_.value_[WQTotal] = ws.surface_rates[pu.phase_pos[Oil]]; - break; - case InjectorType::MULTI: - // Not supported. - deferred_logger.warning("MULTI_PHASE_INJECTOR_NOT_SUPPORTED", - "Multi phase injectors are not supported, requested for well " + baseif_.name()); - break; - } - } else { - primary_variables_.value_[WQTotal] = total_well_rate; - } - - if (std::abs(total_well_rate) > 0.) { - if constexpr (has_wfrac_variable) { - primary_variables_.value_[WFrac] = baseif_.scalingFactor(pu.phase_pos[Water]) * ws.surface_rates[pu.phase_pos[Water]] / total_well_rate; - } - if constexpr (has_gfrac_variable) { - primary_variables_.value_[GFrac] = baseif_.scalingFactor(pu.phase_pos[Gas]) * (ws.surface_rates[pu.phase_pos[Gas]] - - (Indices::enableSolvent ? ws.sum_solvent_rates() : 0.0) ) / total_well_rate ; - } - if constexpr (Indices::enableSolvent) { - primary_variables_.value_[SFrac] = baseif_.scalingFactor(pu.phase_pos[Gas]) * ws.sum_solvent_rates() / total_well_rate ; - } - } else { // total_well_rate == 0 - if (baseif_.isInjector()) { - // only single phase injection handled - if constexpr (has_wfrac_variable) { - if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) { - auto phase = baseif_.wellEcl().getInjectionProperties().injectorType; - if (phase == InjectorType::WATER) { - primary_variables_.value_[WFrac] = 1.0; - } else { - primary_variables_.value_[WFrac] = 0.0; - } - } - } - if constexpr (has_gfrac_variable) { - if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) { - auto phase = baseif_.wellEcl().getInjectionProperties().injectorType; - if (phase == InjectorType::GAS) { - primary_variables_.value_[GFrac] = (1.0 - baseif_.rsRvInj()); - if constexpr (Indices::enableSolvent) { - primary_variables_.value_[GFrac] = 1.0 - baseif_.rsRvInj() - baseif_.wsolvent(); - primary_variables_.value_[SFrac] = baseif_.wsolvent(); - } - } else { - primary_variables_.value_[GFrac] = 0.0; - } - } - } - - // TODO: it is possible to leave injector as a oil well, - // when F_w and F_g both equals to zero, not sure under what kind of circumstance - // this will happen. - } else if (baseif_.isProducer()) { // producers - // TODO: the following are not addressed for the solvent case yet - if constexpr (has_wfrac_variable) { - primary_variables_.value_[WFrac] = 1.0 / np; - } - - if constexpr (has_gfrac_variable) { - primary_variables_.value_[GFrac] = 1.0 / np; - } - } else { - OPM_DEFLOG_THROW(std::logic_error, "Expected PRODUCER or INJECTOR type of well", deferred_logger); - } - } - - - // BHP - primary_variables_.value_[Bhp] = ws.bhp; + this->primary_variables_.update(well_state, deferred_logger); } template diff --git a/opm/simulators/wells/StandardWellPrimaryVariables.cpp b/opm/simulators/wells/StandardWellPrimaryVariables.cpp index 26f20b934..5bd6a0f6e 100644 --- a/opm/simulators/wells/StandardWellPrimaryVariables.cpp +++ b/opm/simulators/wells/StandardWellPrimaryVariables.cpp @@ -32,7 +32,7 @@ #include #include -#include +#include #include #include @@ -61,6 +61,107 @@ resize(const int numWellEq) numWellEq_ = numWellEq; } +template +void StandardWellPrimaryVariables:: +update(const WellState& well_state, DeferredLogger& deferred_logger) +{ + static constexpr int Water = BlackoilPhases::Aqua; + static constexpr int Oil = BlackoilPhases::Liquid; + static constexpr int Gas = BlackoilPhases::Vapour; + + const int well_index = well_.indexOfWell(); + const int np = well_.numPhases(); + const auto& pu = well_.phaseUsage(); + const auto& ws = well_state.well(well_index); + // the weighted total well rate + double total_well_rate = 0.0; + for (int p = 0; p < np; ++p) { + total_well_rate += well_.scalingFactor(p) * ws.surface_rates[p]; + } + + // Not: for the moment, the first primary variable for the injectors is not G_total. The injection rate + // under surface condition is used here + if (well_.isInjector()) { + switch (well_.wellEcl().injectorType()) { + case InjectorType::WATER: + value_[WQTotal] = ws.surface_rates[pu.phase_pos[Water]]; + break; + case InjectorType::GAS: + value_[WQTotal] = ws.surface_rates[pu.phase_pos[Gas]]; + break; + case InjectorType::OIL: + value_[WQTotal] = ws.surface_rates[pu.phase_pos[Oil]]; + break; + case InjectorType::MULTI: + // Not supported. + deferred_logger.warning("MULTI_PHASE_INJECTOR_NOT_SUPPORTED", + "Multi phase injectors are not supported, requested for well " + well_.name()); + break; + } + } else { + value_[WQTotal] = total_well_rate; + } + + if (std::abs(total_well_rate) > 0.) { + if constexpr (has_wfrac_variable) { + value_[WFrac] = well_.scalingFactor(pu.phase_pos[Water]) * ws.surface_rates[pu.phase_pos[Water]] / total_well_rate; + } + if constexpr (has_gfrac_variable) { + value_[GFrac] = well_.scalingFactor(pu.phase_pos[Gas]) * + (ws.surface_rates[pu.phase_pos[Gas]] - + (Indices::enableSolvent ? ws.sum_solvent_rates() : 0.0) ) / total_well_rate ; + } + if constexpr (Indices::enableSolvent) { + value_[SFrac] = well_.scalingFactor(pu.phase_pos[Gas]) * ws.sum_solvent_rates() / total_well_rate ; + } + } else { // total_well_rate == 0 + if (well_.isInjector()) { + // only single phase injection handled + if constexpr (has_wfrac_variable) { + if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) { + auto phase = well_.wellEcl().getInjectionProperties().injectorType; + if (phase == InjectorType::WATER) { + value_[WFrac] = 1.0; + } else { + value_[WFrac] = 0.0; + } + } + } + if constexpr (has_gfrac_variable) { + if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) { + auto phase = well_.wellEcl().getInjectionProperties().injectorType; + if (phase == InjectorType::GAS) { + value_[GFrac] = (1.0 - well_.rsRvInj()); + if constexpr (Indices::enableSolvent) { + value_[GFrac] = 1.0 - well_.rsRvInj() - well_.wsolvent(); + value_[SFrac] = well_.wsolvent(); + } + } else { + value_[GFrac] = 0.0; + } + } + } + + // TODO: it is possible to leave injector as a oil well, + // when F_w and F_g both equals to zero, not sure under what kind of circumstance + // this will happen. + } else if (well_.isProducer()) { // producers + // TODO: the following are not addressed for the solvent case yet + if constexpr (has_wfrac_variable) { + value_[WFrac] = 1.0 / np; + } + + if constexpr (has_gfrac_variable) { + value_[GFrac] = 1.0 / np; + } + } else { + OPM_DEFLOG_THROW(std::logic_error, "Expected PRODUCER or INJECTOR type of well", deferred_logger); + } + } + + // BHP + value_[Bhp] = ws.bhp; +} template void StandardWellPrimaryVariables:: @@ -81,22 +182,6 @@ updatePolyMW(const BVectorWell& dwells) } } -template -void StandardWellPrimaryVariables:: -copyToWellStatePolyMW(WellState& well_state) const -{ - if (well_.isInjector()) { - auto& ws = well_state.well(well_.indexOfWell()); - auto& perf_data = ws.perf_data; - auto& perf_water_velocity = perf_data.water_velocity; - auto& perf_skin_pressure = perf_data.skin_pressure; - for (int perf = 0; perf < well_.numPerfs(); ++perf) { - perf_water_velocity[perf] = value_[Bhp + 1 + perf]; - perf_skin_pressure[perf] = value_[Bhp + 1 + well_.numPerfs() + perf]; - } - } -} - template void StandardWellPrimaryVariables:: copyToWellState(WellState& well_state, @@ -197,6 +282,22 @@ copyToWellState(WellState& well_state, } } +template +void StandardWellPrimaryVariables:: +copyToWellStatePolyMW(WellState& well_state) const +{ + if (well_.isInjector()) { + auto& ws = well_state.well(well_.indexOfWell()); + auto& perf_data = ws.perf_data; + auto& perf_water_velocity = perf_data.water_velocity; + auto& perf_skin_pressure = perf_data.skin_pressure; + for (int perf = 0; perf < well_.numPerfs(); ++perf) { + perf_water_velocity[perf] = value_[Bhp + 1 + perf]; + perf_skin_pressure[perf] = value_[Bhp + 1 + well_.numPerfs() + perf]; + } + } +} + #define INSTANCE(...) \ template class StandardWellPrimaryVariables,__VA_ARGS__,double>; diff --git a/opm/simulators/wells/StandardWellPrimaryVariables.hpp b/opm/simulators/wells/StandardWellPrimaryVariables.hpp index b8615723b..bfbc9c465 100644 --- a/opm/simulators/wells/StandardWellPrimaryVariables.hpp +++ b/opm/simulators/wells/StandardWellPrimaryVariables.hpp @@ -108,6 +108,9 @@ public: //! \brief Returns number of well equations. int numWellEq() const { return numWellEq_; } + //! \brief Copy values from well state. + void update(const WellState& well_state, DeferredLogger& deferred_logger); + //! \brief Update polymer molecular weight values from solution vector. void updatePolyMW(const BVectorWell& dwells);