MultisegmentWell: move updatePrimaryVariables to MultisegmentWellPrimaryVariables

This commit is contained in:
Arne Morten Kvarving 2022-12-19 09:52:48 +01:00
parent e1fccd47dc
commit 5212e9c100
5 changed files with 95 additions and 88 deletions

View File

@ -290,91 +290,6 @@ updatePrimaryVariablesNewton(const BVectorWell& dwells,
}
}
template<typename FluidSystem, typename Indices, typename Scalar>
void
MultisegmentWellEval<FluidSystem,Indices,Scalar>::
updatePrimaryVariables(const WellState& well_state)
{
static constexpr int Water = BlackoilPhases::Aqua;
static constexpr int Gas = BlackoilPhases::Vapour;
// TODO: to test using rate conversion coefficients to see if it will be better than
// this default one
if (!baseif_.isOperableAndSolvable() && !baseif_.wellIsStopped()) return;
const Well& well = baseif_.wellEcl();
// the index of the top segment in the WellState
const auto& ws = well_state.well(baseif_.indexOfWell());
const auto& segments = ws.segments;
// maybe a throw for parallel running?
assert(int(segments.size()) == this->numberOfSegments());
const auto& segment_rates = segments.rates;
const auto& segment_pressure = segments.pressure;
const PhaseUsage& pu = baseif_.phaseUsage();
for (int seg = 0; seg < this->numberOfSegments(); ++seg) {
// calculate the total rate for each segment
double total_seg_rate = 0.0;
// the segment pressure
primary_variables_.value_[seg][SPres] = segment_pressure[seg];
// TODO: under what kind of circustances, the following will be wrong?
// the definition of g makes the gas phase is always the last phase
for (int p = 0; p < baseif_.numPhases(); p++) {
total_seg_rate += baseif_.scalingFactor(p) * segment_rates[baseif_.numPhases() * seg + p];
}
if (seg == 0) {
if (baseif_.isInjector()) {
total_seg_rate = std::max(total_seg_rate, 0.);
} else {
total_seg_rate = std::min(total_seg_rate, 0.);
}
}
primary_variables_.value_[seg][WQTotal] = total_seg_rate;
if (std::abs(total_seg_rate) > 0.) {
if (has_wfrac_variable) {
const int water_pos = pu.phase_pos[Water];
primary_variables_.value_[seg][WFrac] = baseif_.scalingFactor(water_pos) * segment_rates[baseif_.numPhases() * seg + water_pos] / total_seg_rate;
}
if (has_gfrac_variable) {
const int gas_pos = pu.phase_pos[Gas];
primary_variables_.value_[seg][GFrac] = baseif_.scalingFactor(gas_pos) * segment_rates[baseif_.numPhases() * seg + gas_pos] / total_seg_rate;
}
} else { // total_seg_rate == 0
if (baseif_.isInjector()) {
// only single phase injection handled
auto phase = well.getInjectionProperties().injectorType;
if (has_wfrac_variable) {
if (phase == InjectorType::WATER) {
primary_variables_.value_[seg][WFrac] = 1.0;
} else {
primary_variables_.value_[seg][WFrac] = 0.0;
}
}
if (has_gfrac_variable) {
if (phase == InjectorType::GAS) {
primary_variables_.value_[seg][GFrac] = 1.0;
} else {
primary_variables_.value_[seg][GFrac] = 0.0;
}
}
} else if (baseif_.isProducer()) { // producers
if (has_wfrac_variable) {
primary_variables_.value_[seg][WFrac] = 1.0 / baseif_.numPhases();
}
if (has_gfrac_variable) {
primary_variables_.value_[seg][GFrac] = 1.0 / baseif_.numPhases();
}
}
}
}
}
template<typename FluidSystem, typename Indices, typename Scalar>
typename MultisegmentWellEval<FluidSystem,Indices,Scalar>::EvalWell
MultisegmentWellEval<FluidSystem,Indices,Scalar>::

View File

@ -134,8 +134,6 @@ protected:
// handling the overshooting and undershooting of the fractions
void processFractions(const int seg);
void updatePrimaryVariables(const WellState& well_state);
void updateUpwindingSegments();
// updating the well_state based on well solution dwells

View File

@ -29,6 +29,11 @@
#include <opm/models/blackoil/blackoilonephaseindices.hh>
#include <opm/models/blackoil/blackoiltwophaseindices.hh>
#include <opm/simulators/wells/WellInterfaceIndices.hpp>
#include <opm/simulators/wells/WellState.hpp>
#include <algorithm>
namespace Opm {
template<class FluidSystem, class Indices, class Scalar>
@ -52,6 +57,91 @@ init()
}
}
template<class FluidSystem, class Indices, class Scalar>
void MultisegmentWellPrimaryVariables<FluidSystem,Indices,Scalar>::
update(const WellState& well_state)
{
static constexpr int Water = BlackoilPhases::Aqua;
static constexpr int Gas = BlackoilPhases::Vapour;
// TODO: to test using rate conversion coefficients to see if it will be better than
// this default one
if (!well_.isOperableAndSolvable() && !well_.wellIsStopped())
return;
const Well& well = well_.wellEcl();
// the index of the top segment in the WellState
const auto& ws = well_state.well(well_.indexOfWell());
const auto& segments = ws.segments;
// maybe a throw for parallel running?
assert(segments.size() == value_.size());
const auto& segment_rates = segments.rates;
const auto& segment_pressure = segments.pressure;
const PhaseUsage& pu = well_.phaseUsage();
for (size_t seg = 0; seg < value_.size(); ++seg) {
// calculate the total rate for each segment
double total_seg_rate = 0.0;
// the segment pressure
value_[seg][SPres] = segment_pressure[seg];
// TODO: under what kind of circustances, the following will be wrong?
// the definition of g makes the gas phase is always the last phase
for (int p = 0; p < well_.numPhases(); p++) {
total_seg_rate += well_.scalingFactor(p) * segment_rates[well_.numPhases() * seg + p];
}
if (seg == 0) {
if (well_.isInjector()) {
total_seg_rate = std::max(total_seg_rate, 0.);
} else {
total_seg_rate = std::min(total_seg_rate, 0.);
}
}
value_[seg][WQTotal] = total_seg_rate;
if (std::abs(total_seg_rate) > 0.) {
if (has_wfrac_variable) {
const int water_pos = pu.phase_pos[Water];
value_[seg][WFrac] = well_.scalingFactor(water_pos) * segment_rates[well_.numPhases() * seg + water_pos] / total_seg_rate;
}
if (has_gfrac_variable) {
const int gas_pos = pu.phase_pos[Gas];
value_[seg][GFrac] = well_.scalingFactor(gas_pos) * segment_rates[well_.numPhases() * seg + gas_pos] / total_seg_rate;
}
} else { // total_seg_rate == 0
if (well_.isInjector()) {
// only single phase injection handled
auto phase = well.getInjectionProperties().injectorType;
if (has_wfrac_variable) {
if (phase == InjectorType::WATER) {
value_[seg][WFrac] = 1.0;
} else {
value_[seg][WFrac] = 0.0;
}
}
if (has_gfrac_variable) {
if (phase == InjectorType::GAS) {
value_[seg][GFrac] = 1.0;
} else {
value_[seg][GFrac] = 0.0;
}
}
} else if (well_.isProducer()) { // producers
if (has_wfrac_variable) {
value_[seg][WFrac] = 1.0 / well_.numPhases();
}
if (has_gfrac_variable) {
value_[seg][GFrac] = 1.0 / well_.numPhases();
}
}
}
}
}
#define INSTANCE(...) \
template class MultisegmentWellPrimaryVariables<BlackOilFluidSystem<double,BlackOilDefaultIndexTraits>,__VA_ARGS__,double>;

View File

@ -31,6 +31,7 @@ namespace Opm
{
template<class FluidSystem, class Indices, class Scalar> class WellInterfaceIndices;
class WellState;
template<class FluidSystem, class Indices, class Scalar>
class MultisegmentWellPrimaryVariables
@ -79,6 +80,9 @@ public:
//! \brief Initialize evaluations from values.
void init();
//! \brief Copy values from well state.
void update(const WellState& well_state);
// the values for the primary varibles
// based on different solutioin strategies, the wells can have different primary variables
std::vector<std::array<double, numWellEq> > value_;

View File

@ -142,7 +142,7 @@ namespace Opm
MultisegmentWell<TypeTag>::
updatePrimaryVariables(const WellState& well_state, DeferredLogger& /* deferred_logger */)
{
this->MSWEval::updatePrimaryVariables(well_state);
this->primary_variables_.update(well_state);
}