/*
Copyright 2017 SINTEF Digital, Mathematics and Cybernetics.
Copyright 2017 Statoil ASA.
Copyright 2018 IRIS
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see .
*/
#include
#include
#include
#include
#include
namespace Opm
{
bool WellTest::checkMaxRatioLimitWell(const SingleWellState& ws,
const double max_ratio_limit,
const RatioFunc& ratioFunc) const
{
const int np = well_.numPhases();
std::vector well_rates(np, 0.0);
for (int p = 0; p < np; ++p) {
well_rates[p] = ws.surface_rates[p];
}
const double well_ratio = ratioFunc(well_rates, well_.phaseUsage());
return (well_ratio > max_ratio_limit);
}
void WellTest::checkMaxRatioLimitCompletions(const SingleWellState& ws,
const double max_ratio_limit,
const RatioFunc& ratioFunc,
RatioLimitCheckReport& report) const
{
int worst_offending_completion = RatioLimitCheckReport::INVALIDCOMPLETION;
// the maximum water cut value of the completions
// it is used to identify the most offending completion
double max_ratio_completion = 0;
const int np = well_.numPhases();
const auto& perf_data = ws.perf_data;
const auto& perf_phase_rates = perf_data.phase_rates;
// look for the worst_offending_completion
for (const auto& completion : well_.getCompletions()) {
std::vector completion_rates(np, 0.0);
// looping through the connections associated with the completion
const std::vector& conns = completion.second;
for (const int c : conns) {
for (int p = 0; p < np; ++p) {
const double connection_rate = perf_phase_rates[c * np + p];
completion_rates[p] += connection_rate;
}
} // end of for (const int c : conns)
well_.parallelWellInfo().communication().sum(completion_rates.data(), completion_rates.size());
const double ratio_completion = ratioFunc(completion_rates, well_.phaseUsage());
if (ratio_completion > max_ratio_completion) {
worst_offending_completion = completion.first;
max_ratio_completion = ratio_completion;
}
} // end of for (const auto& completion : completions_)
const double violation_extent = max_ratio_completion / max_ratio_limit;
if (violation_extent > report.violation_extent) {
report.worst_offending_completion = worst_offending_completion;
report.violation_extent = violation_extent;
}
}
void WellTest::checkMaxGORLimit(const WellEconProductionLimits& econ_production_limits,
const SingleWellState& ws,
RatioLimitCheckReport& report) const
{
static constexpr int Oil = BlackoilPhases::Liquid;
static constexpr int Gas = BlackoilPhases::Vapour;
// function to calculate gor based on rates
auto gor = [](const std::vector& rates,
const PhaseUsage& pu) {
const double oil_rate = -rates[pu.phase_pos[Oil]];
const double gas_rate = -rates[pu.phase_pos[Gas]];
if (gas_rate <= 0.)
return 0.;
else if (oil_rate <= 0.)
return 1.e100; // big value to mark it as violated
else
return (gas_rate / oil_rate);
};
const double max_gor_limit = econ_production_limits.maxGasOilRatio();
assert(max_gor_limit > 0.);
const bool gor_limit_violated = this->checkMaxRatioLimitWell(ws, max_gor_limit, gor);
if (gor_limit_violated) {
report.ratio_limit_violated = true;
this->checkMaxRatioLimitCompletions(ws, max_gor_limit, gor, report);
}
}
void WellTest::checkMaxWGRLimit(const WellEconProductionLimits& econ_production_limits,
const SingleWellState& ws,
RatioLimitCheckReport& report) const
{
static constexpr int Gas = BlackoilPhases::Vapour;
static constexpr int Water = BlackoilPhases::Aqua;
// function to calculate wgr based on rates
auto wgr = [](const std::vector& rates,
const PhaseUsage& pu) {
const double water_rate = -rates[pu.phase_pos[Water]];
const double gas_rate = -rates[pu.phase_pos[Gas]];
if (water_rate <= 0.)
return 0.;
else if (gas_rate <= 0.)
return 1.e100; // big value to mark it as violated
else
return (water_rate / gas_rate);
};
const double max_wgr_limit = econ_production_limits.maxWaterGasRatio();
assert(max_wgr_limit > 0.);
const bool wgr_limit_violated = this->checkMaxRatioLimitWell(ws, max_wgr_limit, wgr);
if (wgr_limit_violated) {
report.ratio_limit_violated = true;
this->checkMaxRatioLimitCompletions(ws, max_wgr_limit, wgr, report);
}
}
} // namespace Opm