mirror of
https://github.com/OPM/opm-simulators.git
synced 2026-10-25 23:20:12 -05:00
replacing it with a new PhaseUsageInfo and FluidSystem, both of which are using the same implementation of PhaseUsageInfo, and only one set of indices is used. Currently, it is the BlackOilDefaultFluidSystemIndices.
282 lines
10 KiB
C++
282 lines
10 KiB
C++
/*
|
|
Copyright 2016 SINTEF ICT, Applied Mathematics.
|
|
Copyright 2016 - 2017 Statoil ASA.
|
|
Copyright 2017 Dr. Blatt - HPC-Simulation-Software & Services
|
|
Copyright 2016 - 2018 IRIS AS
|
|
|
|
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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include <opm/simulators/wells/BlackoilWellModelRestart.hpp>
|
|
|
|
#include <opm/input/eclipse/Schedule/Group/GuideRateConfig.hpp>
|
|
#include <opm/input/eclipse/Schedule/MSW/WellSegments.hpp>
|
|
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
|
|
|
#include <opm/output/data/Groups.hpp>
|
|
|
|
#include <opm/material/fluidsystems/BlackOilDefaultFluidSystemIndices.hpp>
|
|
|
|
#include <opm/simulators/wells/BlackoilWellModelGeneric.hpp>
|
|
#include <opm/simulators/wells/PerforationData.hpp>
|
|
#include <opm/simulators/wells/SingleWellState.hpp>
|
|
|
|
namespace {
|
|
Opm::data::GuideRateValue::Item
|
|
guideRateRestartItem(const Opm::GuideRateModel::Target target)
|
|
{
|
|
using Item = Opm::data::GuideRateValue::Item;
|
|
using Target = Opm::GuideRateModel::Target;
|
|
|
|
static const auto items = std::unordered_map<Target, Item> {
|
|
{ Target::OIL, Item::Oil },
|
|
{ Target::GAS, Item::Gas },
|
|
{ Target::WAT, Item::Water },
|
|
{ Target::RES, Item::ResV },
|
|
};
|
|
|
|
auto i = items.find(target);
|
|
return (i == items.end()) ? Item::NumItems : i->second;
|
|
}
|
|
|
|
Opm::GuideRate::GuideRateValue
|
|
makeGuideRateValue(const Opm::data::GuideRateValue& restart,
|
|
const Opm::GuideRateModel::Target target)
|
|
{
|
|
const auto item = guideRateRestartItem(target);
|
|
|
|
if (! restart.has(item)) {
|
|
return {};
|
|
}
|
|
|
|
return { 0.0, restart.get(item), target };
|
|
}
|
|
} // Anonymous
|
|
|
|
namespace Opm {
|
|
|
|
template<typename Scalar, typename IndexTraits>
|
|
void BlackoilWellModelRestart<Scalar, IndexTraits>::
|
|
loadRestartConnectionData(const std::vector<data::Rates::opt>& phs,
|
|
const data::Well& rst_well,
|
|
const std::vector<PerforationData<Scalar>>& old_perf_data,
|
|
SingleWellState<Scalar, IndexTraits>& ws) const
|
|
{
|
|
auto& perf_data = ws.perf_data;
|
|
auto perf_pressure = perf_data.pressure.begin();
|
|
auto perf_rates = perf_data.rates.begin();
|
|
auto perf_phase_rates = perf_data.phase_rates.begin();
|
|
|
|
for (const auto& pd : old_perf_data) {
|
|
const auto& rst_connection = rst_well.connections[pd.ecl_index];
|
|
|
|
*perf_pressure = rst_connection.pressure; ++perf_pressure;
|
|
*perf_rates = rst_connection.reservoir_rate; ++perf_rates;
|
|
|
|
for (const auto& phase : phs) {
|
|
*perf_phase_rates = rst_connection.rates.get(phase);
|
|
++perf_phase_rates;
|
|
}
|
|
}
|
|
}
|
|
|
|
template<typename Scalar, typename IndexTraits>
|
|
void BlackoilWellModelRestart<Scalar, IndexTraits>::
|
|
loadRestartSegmentData(const std::string& well_name,
|
|
const std::vector<data::Rates::opt>& phs,
|
|
const data::Well& rst_well,
|
|
SingleWellState<Scalar, IndexTraits>& ws) const
|
|
{
|
|
const auto& segment_set = wellModel_.getWellEcl(well_name).getSegments();
|
|
const auto& rst_segments = rst_well.segments;
|
|
|
|
// \Note: Eventually we need to handle the situations that some segments are shut
|
|
assert(0u + segment_set.size() == rst_segments.size());
|
|
|
|
const auto np = phs.size();
|
|
const auto pres_idx = data::SegmentPressures::Value::Pressure;
|
|
|
|
auto& segments = ws.segments;
|
|
auto& segment_pressure = segments.pressure;
|
|
auto& segment_rates = segments.rates;
|
|
for (const auto& [segNum, rst_segment] : rst_segments) {
|
|
const int segment_index = segment_set.segmentNumberToIndex(segNum);
|
|
|
|
// Recovering segment rates and pressure from the restart values
|
|
segment_pressure[segment_index] = rst_segment.pressures[pres_idx];
|
|
|
|
const auto& rst_segment_rates = rst_segment.rates;
|
|
for (auto p = 0*np; p < np; ++p) {
|
|
segment_rates[segment_index*np + p] = rst_segment_rates.get(phs[p]);
|
|
}
|
|
}
|
|
}
|
|
|
|
template<typename Scalar, typename IndexTraits>
|
|
void BlackoilWellModelRestart<Scalar, IndexTraits>::
|
|
loadRestartWellData(const std::string& well_name,
|
|
const bool handle_ms_well,
|
|
const std::vector<data::Rates::opt>& phs,
|
|
const data::Well& rst_well,
|
|
const std::vector<PerforationData<Scalar>>& old_perf_data,
|
|
SingleWellState<Scalar, IndexTraits>& ws) const
|
|
{
|
|
const auto np = phs.size();
|
|
|
|
ws.bhp = rst_well.bhp;
|
|
ws.thp = rst_well.thp;
|
|
ws.temperature = rst_well.temperature;
|
|
|
|
if (rst_well.current_control.isProducer) {
|
|
ws.production_cmode = rst_well.current_control.prod;
|
|
}
|
|
else {
|
|
ws.injection_cmode = rst_well.current_control.inj;
|
|
}
|
|
|
|
for (auto i = 0*np; i < np; ++i) {
|
|
assert( rst_well.rates.has( phs[ i ] ) );
|
|
ws.surface_rates[i] = rst_well.rates.get(phs[i]);
|
|
}
|
|
|
|
this->loadRestartConnectionData(phs, rst_well, old_perf_data, ws);
|
|
|
|
if (handle_ms_well && !rst_well.segments.empty()) {
|
|
this->loadRestartSegmentData(well_name, phs, rst_well, ws);
|
|
}
|
|
}
|
|
|
|
template<typename Scalar, typename IndexTraits>
|
|
void BlackoilWellModelRestart<Scalar, IndexTraits>::
|
|
loadRestartGroupData(const std::string& group,
|
|
const data::GroupData& value,
|
|
GroupState<Scalar>& grpState) const
|
|
{
|
|
using GPMode = Group::ProductionCMode;
|
|
using GIMode = Group::InjectionCMode;
|
|
|
|
const auto cpc = value.currentControl.currentProdConstraint;
|
|
const auto cgi = value.currentControl.currentGasInjectionConstraint;
|
|
const auto cwi = value.currentControl.currentWaterInjectionConstraint;
|
|
|
|
if (cpc != GPMode::NONE) {
|
|
grpState.production_control(group, cpc);
|
|
}
|
|
|
|
if (cgi != GIMode::NONE) {
|
|
grpState.injection_control(group, Phase::GAS, cgi);
|
|
}
|
|
|
|
if (cwi != GIMode::NONE) {
|
|
grpState.injection_control(group, Phase::WATER, cwi);
|
|
}
|
|
}
|
|
|
|
template<typename Scalar, typename IndexTraits>
|
|
void BlackoilWellModelRestart<Scalar, IndexTraits>::
|
|
loadRestartGuideRates(const int report_step,
|
|
const GuideRateModel::Target target,
|
|
const data::Wells& rst_wells,
|
|
GuideRate& guide_rate) const
|
|
{
|
|
for (const auto& [well_name, rst_well] : rst_wells) {
|
|
if (!wellModel_.hasLocalWell(well_name) ||
|
|
wellModel_.getWellEcl(well_name).isInjector())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
guide_rate.init_grvalue_SI(report_step, well_name,
|
|
makeGuideRateValue(rst_well.guide_rates, target));
|
|
}
|
|
}
|
|
|
|
template<typename Scalar, typename IndexTraits>
|
|
void BlackoilWellModelRestart<Scalar, IndexTraits>::
|
|
loadRestartGuideRates(const int report_step,
|
|
const GuideRateConfig& config,
|
|
const std::map<std::string, data::GroupData>& rst_groups,
|
|
GuideRate& guide_rate) const
|
|
{
|
|
const auto target = config.model().target();
|
|
|
|
for (const auto& [group_name, rst_group] : rst_groups) {
|
|
if (!config.has_production_group(group_name)) {
|
|
continue;
|
|
}
|
|
|
|
const auto& group = config.production_group(group_name);
|
|
if ((group.guide_rate > 0.0) || (group.target != Group::GuideRateProdTarget::FORM)) {
|
|
continue;
|
|
}
|
|
|
|
guide_rate.init_grvalue_SI(report_step, group_name,
|
|
makeGuideRateValue(rst_group.guideRates.production, target));
|
|
}
|
|
}
|
|
|
|
template<typename Scalar, typename IndexTraits>
|
|
void BlackoilWellModelRestart<Scalar, IndexTraits>::
|
|
loadRestartData(const data::Wells& rst_wells,
|
|
const data::GroupAndNetworkValues& grpNwrkValues,
|
|
const bool handle_ms_well,
|
|
WellState<Scalar, IndexTraits>& well_state,
|
|
GroupState<Scalar>& grpState) const
|
|
{
|
|
using rt = data::Rates::opt;
|
|
// const auto& phases = wellModel_.phaseUsage();
|
|
const auto& pu = well_state.phaseUsageInfo();
|
|
const auto np = pu.numActivePhases();
|
|
|
|
std::vector<rt> phs(np);
|
|
if (pu.phaseIsActive(IndexTraits::waterPhaseIdx)) {
|
|
phs.at(pu.canonicalToActivePhaseIdx(IndexTraits::waterPhaseIdx)) = rt::wat;
|
|
}
|
|
|
|
if (pu.phaseIsActive(IndexTraits::oilPhaseIdx)) {
|
|
phs.at(pu.canonicalToActivePhaseIdx(IndexTraits::oilPhaseIdx)) = rt::oil;
|
|
}
|
|
|
|
if (pu.phaseIsActive(IndexTraits::gasPhaseIdx)) {
|
|
phs.at(pu.canonicalToActivePhaseIdx(IndexTraits::gasPhaseIdx)) = rt::gas;
|
|
}
|
|
|
|
for (auto well_index = 0*well_state.size();
|
|
well_index < well_state.size();
|
|
++well_index)
|
|
{
|
|
const auto& well_name = well_state.name(well_index);
|
|
|
|
this->loadRestartWellData(well_name, handle_ms_well && !well_state.is_permanently_inactive_well(well_name), phs,
|
|
rst_wells.at(well_name),
|
|
wellModel_.perfData(well_index),
|
|
well_state.well(well_index));
|
|
}
|
|
|
|
for (const auto& [group, value] : grpNwrkValues.groupData) {
|
|
this->loadRestartGroupData(group, value, grpState);
|
|
}
|
|
}
|
|
|
|
template class BlackoilWellModelRestart<double, BlackOilDefaultFluidSystemIndices>;
|
|
|
|
#if FLOW_INSTANTIATE_FLOAT
|
|
template class BlackoilWellModelRestart<float, BlackOilDefaultFluidSystemIndices>;
|
|
#endif
|
|
|
|
} // namespace Opm
|