BlackoilWellModelGeneric: template Scalar type

This commit is contained in:
Arne Morten Kvarving 2024-02-17 18:13:46 +01:00
parent 3d381bac91
commit f0e7f8842b
12 changed files with 394 additions and 383 deletions

View File

@ -116,7 +116,7 @@ ActionHandler::ActionHandler(EclipseState& ecl_state,
Schedule& schedule,
Action::State& actionState,
SummaryState& summaryState,
BlackoilWellModelGeneric& wellModel,
BlackoilWellModelGeneric<double>& wellModel,
Parallel::Communication comm)
: ecl_state_(ecl_state)
, schedule_(schedule)

View File

@ -38,7 +38,7 @@ class ActionX;
class State;
}
class BlackoilWellModelGeneric;
template<class Scalar> class BlackoilWellModelGeneric;
class EclipseState;
class Schedule;
struct SimulatorUpdate;
@ -56,7 +56,7 @@ public:
Schedule& schedule,
Action::State& actionState,
SummaryState& summaryState,
BlackoilWellModelGeneric& wellModel,
BlackoilWellModelGeneric<double>& wellModel,
Parallel::Communication comm);
void applyActions(int reportStep,
@ -88,7 +88,7 @@ public:
Schedule& schedule_;
Action::State& actionState_;
SummaryState& summaryState_;
BlackoilWellModelGeneric& wellModel_;
BlackoilWellModelGeneric<double>& wellModel_;
Parallel::Communication comm_;
};

View File

@ -92,7 +92,8 @@ namespace Opm {
/// Class for handling the blackoil well model.
template<typename TypeTag>
class BlackoilWellModel : public BaseAuxiliaryModule<TypeTag>
, public BlackoilWellModelGeneric
, public BlackoilWellModelGeneric<GetPropType<TypeTag,
Properties::Scalar>>
{
public:
// --------- Types ---------
@ -109,10 +110,10 @@ namespace Opm {
using GlobalEqVector = GetPropType<TypeTag, Properties::GlobalEqVector>;
using SparseMatrixAdapter = GetPropType<TypeTag, Properties::SparseMatrixAdapter>;
using GasLiftSingleWell = typename WellInterface<TypeTag>::GasLiftSingleWell;
using GLiftOptWells = typename BlackoilWellModelGeneric::GLiftOptWells;
using GLiftProdWells = typename BlackoilWellModelGeneric::GLiftProdWells;
using GLiftOptWells = typename BlackoilWellModelGeneric<Scalar>::GLiftOptWells;
using GLiftProdWells = typename BlackoilWellModelGeneric<Scalar>::GLiftProdWells;
using GLiftWellStateMap =
typename BlackoilWellModelGeneric::GLiftWellStateMap;
typename BlackoilWellModelGeneric<Scalar>::GLiftWellStateMap;
using GLiftEclWells = typename GasLiftGroupInfo::GLiftEclWells;
using GLiftSyncGroups = typename GasLiftSingleWellGeneric::GLiftSyncGroups;
constexpr static std::size_t pressureVarIndex = GetPropType<TypeTag, Properties::Indices>::pressureSwitchIdx;
@ -234,7 +235,7 @@ namespace Opm {
using WellInterfacePtr = std::shared_ptr<WellInterface<TypeTag> >;
using BlackoilWellModelGeneric::initFromRestartFile;
using BlackoilWellModelGeneric<Scalar>::initFromRestartFile;
void initFromRestartFile(const RestartValue& restartValues)
{
initFromRestartFile(restartValues,
@ -243,7 +244,7 @@ namespace Opm {
param_.use_multisegment_well_);
}
using BlackoilWellModelGeneric::prepareDeserialize;
using BlackoilWellModelGeneric<Scalar>::prepareDeserialize;
void prepareDeserialize(const int report_step)
{
prepareDeserialize(report_step, grid().size(0),

View File

@ -29,7 +29,7 @@
namespace Opm {
class BlackoilWellModelGeneric;
template<class Scalar> class BlackoilWellModelGeneric;
class DeferredLogger;
template<class Scalar> class GroupState;
class SummaryState;
@ -41,7 +41,7 @@ class BlackoilWellModelConstraints
{
public:
//! \brief Constructor initializes reference to the well model.
BlackoilWellModelConstraints(const BlackoilWellModelGeneric& wellModel)
BlackoilWellModelConstraints(const BlackoilWellModelGeneric<Scalar>& wellModel)
: wellModel_(wellModel)
{}
@ -93,7 +93,7 @@ private:
const int reportStepIdx,
DeferredLogger& deferred_logger) const;
const BlackoilWellModelGeneric& wellModel_; //!< Reference to well model
const BlackoilWellModelGeneric<Scalar>& wellModel_; //!< Reference to well model
};
} // namespace Opm

View File

@ -76,7 +76,8 @@
namespace Opm {
BlackoilWellModelGeneric::
template<class Scalar>
BlackoilWellModelGeneric<Scalar>::
BlackoilWellModelGeneric(Schedule& schedule,
const SummaryState& summaryState,
const EclipseState& eclState,
@ -115,22 +116,22 @@ BlackoilWellModelGeneric(Schedule& schedule,
}
}
int
BlackoilWellModelGeneric::
template<class Scalar>
int BlackoilWellModelGeneric<Scalar>::
numLocalWells() const
{
return wells_ecl_.size();
}
int
BlackoilWellModelGeneric::
template<class Scalar>
int BlackoilWellModelGeneric<Scalar>::
numPhases() const
{
return phase_usage_.num_phases;
}
bool
BlackoilWellModelGeneric::
template<class Scalar>
bool BlackoilWellModelGeneric<Scalar>::
hasWell(const std::string& wname) const
{
return std::any_of(this->wells_ecl_.begin(), this->wells_ecl_.end(),
@ -140,22 +141,22 @@ hasWell(const std::string& wname) const
});
}
bool
BlackoilWellModelGeneric::
template<class Scalar>
bool BlackoilWellModelGeneric<Scalar>::
wellsActive() const
{
return wells_active_;
}
bool
BlackoilWellModelGeneric::
template<class Scalar>
bool BlackoilWellModelGeneric<Scalar>::
networkActive() const
{
return network_active_;
}
bool
BlackoilWellModelGeneric::
template<class Scalar>
bool BlackoilWellModelGeneric<Scalar>::
anyMSWellOpenLocal() const
{
for (const auto& well : wells_ecl_) {
@ -166,8 +167,8 @@ anyMSWellOpenLocal() const
return false;
}
const Well&
BlackoilWellModelGeneric::
template<class Scalar>
const Well& BlackoilWellModelGeneric<Scalar>::
getWellEcl(const std::string& well_name) const
{
// finding the iterator of the well in wells_ecl
@ -182,8 +183,8 @@ getWellEcl(const std::string& well_name) const
return *well_ecl;
}
void
BlackoilWellModelGeneric::
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
initFromRestartFile(const RestartValue& restartValues,
WellTestState wtestState,
const std::size_t numCells,
@ -210,7 +211,7 @@ initFromRestartFile(const RestartValue& restartValues,
this->schedule(), handle_ms_well, numCells,
this->well_perf_data_, this->summaryState_);
BlackoilWellModelRestart<double>(*this).
BlackoilWellModelRestart(*this).
loadRestartData(restartValues.wells,
restartValues.grp_nwrk,
handle_ms_well,
@ -218,7 +219,7 @@ initFromRestartFile(const RestartValue& restartValues,
this->groupState());
if (config.has_model()) {
BlackoilWellModelRestart<double>(*this).
BlackoilWellModelRestart(*this).
loadRestartGuideRates(report_step,
config.model().target(),
restartValues.wells,
@ -226,7 +227,7 @@ initFromRestartFile(const RestartValue& restartValues,
}
if (config.has_model()) {
BlackoilWellModelRestart<double>(*this).
BlackoilWellModelRestart(*this).
loadRestartGuideRates(report_step,
config,
restartValues.grp_nwrk.groupData,
@ -240,8 +241,8 @@ initFromRestartFile(const RestartValue& restartValues,
initial_step_ = false;
}
void
BlackoilWellModelGeneric::
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
prepareDeserialize(int report_step, const std::size_t numCells, bool handle_ms_well)
{
// wells_ecl_ should only contain wells on this processor.
@ -263,8 +264,8 @@ prepareDeserialize(int report_step, const std::size_t numCells, bool handle_ms_w
this->updateNupcolWGState();
}
std::vector<Well>
BlackoilWellModelGeneric::
template<class Scalar>
std::vector<Well> BlackoilWellModelGeneric<Scalar>::
getLocalWells(const int timeStepIdx) const
{
auto w = schedule().getWells(timeStepIdx);
@ -272,8 +273,9 @@ getLocalWells(const int timeStepIdx) const
return w;
}
template<class Scalar>
std::vector<std::reference_wrapper<ParallelWellInfo>>
BlackoilWellModelGeneric::
BlackoilWellModelGeneric<Scalar>::
createLocalParallelWellInfo(const std::vector<Well>& wells)
{
std::vector<std::reference_wrapper<ParallelWellInfo>> local_parallel_well_info;
@ -291,8 +293,8 @@ createLocalParallelWellInfo(const std::vector<Well>& wells)
return local_parallel_well_info;
}
void
BlackoilWellModelGeneric::
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
initializeWellProdIndCalculators()
{
this->prod_index_calc_.clear();
@ -302,8 +304,8 @@ initializeWellProdIndCalculators()
}
}
void
BlackoilWellModelGeneric::
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
initializeWellPerfData()
{
well_perf_data_.resize(wells_ecl_.size());
@ -393,8 +395,8 @@ initializeWellPerfData()
}
}
void
BlackoilWellModelGeneric::
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
checkGEconLimits(
const Group& group,
const double simulation_time,
@ -412,7 +414,7 @@ checkGEconLimits(
return;
}
GroupEconomicLimitsChecker<double> checker {
GroupEconomicLimitsChecker<Scalar> checker {
*this, wellTestState(), group, simulation_time, report_step_idx, deferred_logger
};
if (checker.minOilRate() || checker.minGasRate()) {
@ -428,10 +430,10 @@ checkGEconLimits(
}
}
void
BlackoilWellModelGeneric::
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
checkGconsaleLimits(const Group& group,
WellState<double>& well_state,
WellState<Scalar>& well_state,
const int reportStepIdx,
DeferredLogger& deferred_logger)
{
@ -455,25 +457,24 @@ checkGconsaleLimits(const Group& group,
const Group::ProductionCMode& oldProductionControl = this->groupState().production_control(group.name());
int gasPos = phase_usage_.phase_pos[BlackoilPhases::Vapour];
double production_rate = WellGroupHelpers<double>::sumWellSurfaceRates(group,
Scalar production_rate = WellGroupHelpers<Scalar>::sumWellSurfaceRates(group,
schedule(),
well_state,
reportStepIdx,
gasPos,
/*isInjector*/false);
double injection_rate = WellGroupHelpers<double>::sumWellSurfaceRates(group,
Scalar injection_rate = WellGroupHelpers<Scalar>::sumWellSurfaceRates(group,
schedule(),
well_state,
reportStepIdx,
gasPos,
/*isInjector*/true);
// sum over all nodes
injection_rate = comm_.sum(injection_rate);
production_rate = comm_.sum(production_rate);
double sales_rate = production_rate - injection_rate;
double production_target = gconsale.sales_target + injection_rate;
Scalar sales_rate = production_rate - injection_rate;
Scalar production_target = gconsale.sales_target + injection_rate;
// add import rate and subtract consumption rate for group for gas
if (schedule()[reportStepIdx].gconsump().has(group.name())) {
@ -487,7 +488,7 @@ checkGconsaleLimits(const Group& group,
}
if (sales_rate > gconsale.max_sales_rate) {
switch(gconsale.max_proc) {
switch (gconsale.max_proc) {
case GConSale::MaxProcedure::NONE: {
if (oldProductionControl != Group::ProductionCMode::GRAT && oldProductionControl != Group::ProductionCMode::NONE) {
ss = fmt::format("Group sales exceed maximum limit, but the action is NONE for {}. Nothing happens",
@ -559,8 +560,8 @@ checkGconsaleLimits(const Group& group,
deferred_logger.info(ss);
}
bool
BlackoilWellModelGeneric::
template<class Scalar>
bool BlackoilWellModelGeneric<Scalar>::
checkGroupHigherConstraints(const Group& group,
DeferredLogger& deferred_logger,
const int reportStepIdx)
@ -591,16 +592,16 @@ checkGroupHigherConstraints(const Group& group,
->first;
}
std::vector<double> rates(phase_usage_.num_phases, 0.0);
std::vector<Scalar> rates(phase_usage_.num_phases, 0.0);
bool isField = group.name() == "FIELD";
if (!isField && group.isInjectionGroup()) {
// Obtain rates for group.
std::vector<double> resv_coeff_inj(phase_usage_.num_phases, 0.0);
std::vector<Scalar> resv_coeff_inj(phase_usage_.num_phases, 0.0);
calcInjRates(fipnum, pvtreg, resv_coeff_inj);
for (int phasePos = 0; phasePos < phase_usage_.num_phases; ++phasePos) {
const double local_current_rate = WellGroupHelpers<double>::sumWellSurfaceRates(group,
const Scalar local_current_rate = WellGroupHelpers<Scalar>::sumWellSurfaceRates(group,
schedule(),
this->wellState(),
reportStepIdx,
@ -616,7 +617,7 @@ checkGroupHigherConstraints(const Group& group,
if (currentControl != Group::InjectionCMode::FLD && group.injectionGroupControlAvailable(phase)) {
const Group& parentGroup = schedule().getGroup(group.parent(), reportStepIdx);
const auto [is_changed, scaling_factor] =
WellGroupHelpers<double>::checkGroupConstraintsInj(group.name(),
WellGroupHelpers<Scalar>::checkGroupConstraintsInj(group.name(),
group.parent(),
parentGroup,
this->wellState(),
@ -633,11 +634,11 @@ checkGroupHigherConstraints(const Group& group,
deferred_logger);
if (is_changed) {
switched_inj_groups_.insert_or_assign({group.name(), phase}, Group::InjectionCMode2String(Group::InjectionCMode::FLD));
BlackoilWellModelConstraints<double>(*this).
BlackoilWellModelConstraints(*this).
actionOnBrokenConstraints(group, Group::InjectionCMode::FLD,
phase, this->groupState(),
deferred_logger);
WellGroupHelpers<double>::updateWellRatesFromGroupTargetScale(scaling_factor,
WellGroupHelpers<Scalar>::updateWellRatesFromGroupTargetScale(scaling_factor,
group,
schedule(),
reportStepIdx,
@ -653,7 +654,7 @@ checkGroupHigherConstraints(const Group& group,
if (!isField && group.isProductionGroup()) {
// Obtain rates for group.
for (int phasePos = 0; phasePos < phase_usage_.num_phases; ++phasePos) {
const double local_current_rate = WellGroupHelpers<double>::sumWellSurfaceRates(group,
const Scalar local_current_rate = WellGroupHelpers<Scalar>::sumWellSurfaceRates(group,
schedule(),
this->wellState(),
reportStepIdx,
@ -662,14 +663,14 @@ checkGroupHigherConstraints(const Group& group,
// Sum over all processes
rates[phasePos] = -comm_.sum(local_current_rate);
}
std::vector<double> resv_coeff(phase_usage_.num_phases, 0.0);
std::vector<Scalar> resv_coeff(phase_usage_.num_phases, 0.0);
calcRates(fipnum, pvtreg, this->groupState().production_rates(group.name()), resv_coeff);
// Check higher up only if under individual (not FLD) control.
const Group::ProductionCMode& currentControl = this->groupState().production_control(group.name());
if (currentControl != Group::ProductionCMode::FLD && group.productionGroupControlAvailable()) {
const Group& parentGroup = schedule().getGroup(group.parent(), reportStepIdx);
const auto [is_changed, scaling_factor] =
WellGroupHelpers<double>::checkGroupConstraintsProd(group.name(),
WellGroupHelpers<Scalar>::checkGroupConstraintsProd(group.name(),
group.parent(),
parentGroup,
this->wellState(),
@ -686,7 +687,7 @@ checkGroupHigherConstraints(const Group& group,
if (is_changed) {
const auto group_limit_action = group.productionControls(summaryState_).group_limit_action;
std::optional<std::string> worst_offending_well = std::nullopt;
changed = BlackoilWellModelConstraints<double>(*this).
changed = BlackoilWellModelConstraints(*this).
actionOnBrokenConstraints(group, reportStepIdx, group_limit_action,
Group::ProductionCMode::FLD,
this->wellState(),
@ -697,7 +698,7 @@ checkGroupHigherConstraints(const Group& group,
if (changed) {
switched_prod_groups_.insert_or_assign(group.name(),
Group::ProductionCMode2String(Group::ProductionCMode::FLD));
WellGroupHelpers<double>::updateWellRatesFromGroupTargetScale(scaling_factor,
WellGroupHelpers<Scalar>::updateWellRatesFromGroupTargetScale(scaling_factor,
group,
schedule(),
reportStepIdx,
@ -712,8 +713,8 @@ checkGroupHigherConstraints(const Group& group,
return changed;
}
void
BlackoilWellModelGeneric::
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
updateEclWells(const int timeStepIdx,
const SimulatorUpdate& sim_update,
const SummaryState& st)
@ -761,8 +762,8 @@ updateEclWells(const int timeStepIdx,
this->wellStructureChangedDynamically_ = sim_update.well_structure_changed;
}
double
BlackoilWellModelGeneric::
template<class Scalar>
Scalar BlackoilWellModelGeneric<Scalar>::
wellPI(const int well_index) const
{
const auto& pu = this->phase_usage_;
@ -793,8 +794,8 @@ wellPI(const int well_index) const
}
}
double
BlackoilWellModelGeneric::
template<class Scalar>
Scalar BlackoilWellModelGeneric<Scalar>::
wellPI(const std::string& well_name) const
{
auto well_iter = std::find_if(this->wells_ecl_.begin(), this->wells_ecl_.end(),
@ -811,27 +812,27 @@ wellPI(const std::string& well_name) const
return this->wellPI(well_index);
}
bool
BlackoilWellModelGeneric::
template<class Scalar>
bool BlackoilWellModelGeneric<Scalar>::
wasDynamicallyShutThisTimeStep(const int well_index) const
{
return wasDynamicallyShutThisTimeStep(this->wells_ecl_[well_index].name());
}
template<class Scalar>
bool
BlackoilWellModelGeneric::
BlackoilWellModelGeneric<Scalar>::
wasDynamicallyShutThisTimeStep(const std::string& well_name) const
{
return this->closed_this_step_.find(well_name) !=
this->closed_this_step_.end();
}
void
BlackoilWellModelGeneric::
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
updateWsolvent(const Group& group,
const int reportStepIdx,
const WellState<double>& wellState)
const WellState<Scalar>& wellState)
{
for (const std::string& groupName : group.groups()) {
const Group& groupTmp = schedule_.getGroup(groupName, reportStepIdx);
@ -846,13 +847,13 @@ updateWsolvent(const Group& group,
int gasPos = phase_usage_.phase_pos[BlackoilPhases::Vapour];
const auto& controls = group.injectionControls(Phase::GAS, summaryState_);
const Group& groupRein = schedule_.getGroup(controls.reinj_group, reportStepIdx);
double gasProductionRate = WellGroupHelpers<double>::sumWellSurfaceRates(groupRein,
Scalar gasProductionRate = WellGroupHelpers<Scalar>::sumWellSurfaceRates(groupRein,
schedule_,
wellState,
reportStepIdx,
gasPos,
/*isInjector*/false);
double solventProductionRate = WellGroupHelpers<double>::sumSolventRates(groupRein,
Scalar solventProductionRate = WellGroupHelpers<Scalar>::sumSolventRates(groupRein,
schedule_,
wellState,
reportStepIdx,
@ -861,7 +862,7 @@ updateWsolvent(const Group& group,
solventProductionRate = comm_.sum(solventProductionRate);
gasProductionRate = comm_.sum(gasProductionRate);
double wsolvent = 0.0;
Scalar wsolvent = 0.0;
if (std::abs(gasProductionRate) > 1e-6)
wsolvent = solventProductionRate / gasProductionRate;
@ -869,11 +870,11 @@ updateWsolvent(const Group& group,
}
}
void
BlackoilWellModelGeneric::
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
setWsolvent(const Group& group,
const int reportStepIdx,
double wsolvent)
Scalar wsolvent)
{
for (const std::string& groupName : group.groups()) {
const Group& groupTmp = schedule_.getGroup(groupName, reportStepIdx);
@ -889,8 +890,8 @@ setWsolvent(const Group& group,
}
}
void
BlackoilWellModelGeneric::
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
assignShutConnections(data::Wells& wsrpt,
const int reportStepIndex) const
{
@ -934,8 +935,8 @@ assignShutConnections(data::Wells& wsrpt,
}
}
void
BlackoilWellModelGeneric::
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
assignGroupControl(const Group& group,
data::GroupData& gdata) const
{
@ -965,26 +966,27 @@ assignGroupControl(const Group& group,
}
}
void
BlackoilWellModelGeneric::
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
assignGroupValues(const int reportStepIdx,
std::map<std::string, data::GroupData>& gvalues) const
{
const auto groupGuideRates =
BlackoilWellModelGuideRates<double>(*this).calculateAllGroupGuideRates(reportStepIdx);
BlackoilWellModelGuideRates(*this).calculateAllGroupGuideRates(reportStepIdx);
for (const auto& gname : schedule_.groupNames(reportStepIdx)) {
const auto& grup = schedule_.getGroup(gname, reportStepIdx);
auto& gdata = gvalues[gname];
this->assignGroupControl(grup, gdata);
BlackoilWellModelGuideRates<double>(*this).assignGroupGuideRates(grup, groupGuideRates, gdata);
BlackoilWellModelGuideRates(*this).assignGroupGuideRates(grup, groupGuideRates, gdata);
}
}
void
BlackoilWellModelGeneric::
assignNodeValues(std::map<std::string, data::NodeData>& nodevalues, const int reportStepIdx) const
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
assignNodeValues(std::map<std::string, data::NodeData>& nodevalues,
const int reportStepIdx) const
{
nodevalues.clear();
if (reportStepIdx < 0) return;
@ -993,17 +995,21 @@ assignNodeValues(std::map<std::string, data::NodeData>& nodevalues, const int re
nodevalues.emplace(node, data::NodeData{pressure});
// Assign node values of well groups to GPR:WELLNAME
const auto& sched = schedule();
if (!sched.hasGroup(node, reportStepIdx)) continue;
if (!sched.hasGroup(node, reportStepIdx)) {
continue;
}
const auto& group = sched.getGroup(node, reportStepIdx);
for (const std::string& wellname : group.wells()) {
nodevalues.emplace(wellname, data::NodeData{pressure});
nodevalues.emplace(wellname, data::NodeData{pressure});
}
}
const auto& network = schedule()[reportStepIdx].network();
if (!network.active()) return;
if (!network.active()) {
return;
}
auto converged_pressures = WellGroupHelpers<double>::computeNetworkPressures(network,
auto converged_pressures = WellGroupHelpers<Scalar>::computeNetworkPressures(network,
this->wellState(),
this->groupState(),
*(vfp_properties_->getProd()),
@ -1015,30 +1021,33 @@ assignNodeValues(std::map<std::string, data::NodeData>& nodevalues, const int re
it->second.converged_pressure = converged_pressure;
// Assign node values of group to GPR:WELLNAME
const auto& sched = schedule();
if (!sched.hasGroup(node, reportStepIdx)) continue;
if (!sched.hasGroup(node, reportStepIdx)) {
continue;
}
const auto& group = sched.getGroup(node, reportStepIdx);
for (const std::string& wellname : group.wells()) {
auto it2 = nodevalues.find(wellname);
assert(it2 != nodevalues.end());
it2->second.converged_pressure = converged_pressure;
auto it2 = nodevalues.find(wellname);
assert(it2 != nodevalues.end());
it2->second.converged_pressure = converged_pressure;
}
}
}
template<class Scalar>
data::GroupAndNetworkValues
BlackoilWellModelGeneric::
BlackoilWellModelGeneric<Scalar>::
groupAndNetworkData(const int reportStepIdx) const
{
auto grp_nwrk_values = data::GroupAndNetworkValues{};
this->assignGroupValues(reportStepIdx, grp_nwrk_values.groupData);
this->assignNodeValues(grp_nwrk_values.nodeData, reportStepIdx-1); // Schedule state info at previous step
this->assignNodeValues(grp_nwrk_values.nodeData, reportStepIdx - 1); // Schedule state info at previous step
return grp_nwrk_values;
}
void
BlackoilWellModelGeneric::
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
updateAndCommunicateGroupData(const int reportStepIdx,
const int iterationIdx)
{
@ -1057,8 +1066,8 @@ updateAndCommunicateGroupData(const int reportStepIdx,
const auto& well_state_nupcol = this->nupcolWellState();
// the group target reduction rates needs to be update since wells may have switched to/from GRUP control
// The group target reduction does not honor NUPCOL.
std::vector<double> groupTargetReduction(numPhases(), 0.0);
WellGroupHelpers<double>::updateGroupTargetReduction(fieldGroup,
std::vector<Scalar> groupTargetReduction(numPhases(), 0.0);
WellGroupHelpers<Scalar>::updateGroupTargetReduction(fieldGroup,
schedule(),
reportStepIdx,
/*isInjector*/ false,
@ -1067,8 +1076,8 @@ updateAndCommunicateGroupData(const int reportStepIdx,
well_state,
this->groupState(),
groupTargetReduction);
std::vector<double> groupTargetReductionInj(numPhases(), 0.0);
WellGroupHelpers<double>::updateGroupTargetReduction(fieldGroup,
std::vector<Scalar> groupTargetReductionInj(numPhases(), 0.0);
WellGroupHelpers<Scalar>::updateGroupTargetReduction(fieldGroup,
schedule(),
reportStepIdx,
/*isInjector*/ true,
@ -1078,7 +1087,7 @@ updateAndCommunicateGroupData(const int reportStepIdx,
this->groupState(),
groupTargetReductionInj);
WellGroupHelpers<double>::updateREINForGroups(fieldGroup,
WellGroupHelpers<Scalar>::updateREINForGroups(fieldGroup,
schedule(),
reportStepIdx,
phase_usage_,
@ -1086,31 +1095,31 @@ updateAndCommunicateGroupData(const int reportStepIdx,
well_state_nupcol,
this->groupState(),
comm_.rank() == 0);
WellGroupHelpers<double>::updateVREPForGroups(fieldGroup,
WellGroupHelpers<Scalar>::updateVREPForGroups(fieldGroup,
schedule(),
reportStepIdx,
well_state_nupcol,
this->groupState());
WellGroupHelpers<double>::updateReservoirRatesInjectionGroups(fieldGroup,
WellGroupHelpers<Scalar>::updateReservoirRatesInjectionGroups(fieldGroup,
schedule(),
reportStepIdx,
well_state_nupcol,
this->groupState());
WellGroupHelpers<double>::updateSurfaceRatesInjectionGroups(fieldGroup,
WellGroupHelpers<Scalar>::updateSurfaceRatesInjectionGroups(fieldGroup,
schedule(),
reportStepIdx,
well_state_nupcol,
this->groupState());
WellGroupHelpers<double>::updateGroupProductionRates(fieldGroup,
WellGroupHelpers<Scalar>::updateGroupProductionRates(fieldGroup,
schedule(),
reportStepIdx,
well_state_nupcol,
this->groupState());
// We use the rates from the previous time-step to reduce oscillations
WellGroupHelpers<double>::updateWellRates(fieldGroup,
WellGroupHelpers<Scalar>::updateWellRates(fieldGroup,
schedule(),
reportStepIdx,
this->prevWellState(),
@ -1129,15 +1138,15 @@ updateAndCommunicateGroupData(const int reportStepIdx,
this->groupState().communicate_rates(comm_);
}
bool
BlackoilWellModelGeneric::
template<class Scalar>
bool BlackoilWellModelGeneric<Scalar>::
hasTHPConstraints() const
{
return BlackoilWellModelConstraints<double>(*this).hasTHPConstraints();
return BlackoilWellModelConstraints(*this).hasTHPConstraints();
}
void
BlackoilWellModelGeneric::
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
updateNetworkActiveState(const int report_step) {
const auto& network = schedule()[report_step].network();
if (!network.active()) {
@ -1157,8 +1166,8 @@ updateNetworkActiveState(const int report_step) {
this->network_active_ = comm_.max(network_active);
}
bool
BlackoilWellModelGeneric::
template<class Scalar>
bool BlackoilWellModelGeneric<Scalar>::
needPreStepNetworkRebalance(const int report_step) const
{
const auto& network = schedule()[report_step].network();
@ -1176,8 +1185,8 @@ needPreStepNetworkRebalance(const int report_step) const
return network_rebalance_necessary;
}
bool
BlackoilWellModelGeneric::
template<class Scalar>
bool BlackoilWellModelGeneric<Scalar>::
forceShutWellByName(const std::string& wellname,
const double simulation_time)
{
@ -1209,8 +1218,8 @@ forceShutWellByName(const std::string& wellname,
return (well_was_shut == 1);
}
void
BlackoilWellModelGeneric::
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
inferLocalShutWells()
{
this->local_shut_wells_.clear();
@ -1229,8 +1238,8 @@ inferLocalShutWells()
}
}
double
BlackoilWellModelGeneric::
template<class Scalar>
Scalar BlackoilWellModelGeneric<Scalar>::
updateNetworkPressures(const int reportStepIdx)
{
// Get the network and return if inactive (no wells in network at this time)
@ -1241,7 +1250,7 @@ updateNetworkPressures(const int reportStepIdx)
const auto previous_node_pressures = node_pressures_;
node_pressures_ = WellGroupHelpers<double>::computeNetworkPressures(network,
node_pressures_ = WellGroupHelpers<Scalar>::computeNetworkPressures(network,
this->wellState(),
this->groupState(),
*(vfp_properties_->getProd()),
@ -1249,7 +1258,7 @@ updateNetworkPressures(const int reportStepIdx)
reportStepIdx);
// here, the network imbalance is the difference between the previous nodal pressure and the new nodal pressure
double network_imbalance = 0.;
Scalar network_imbalance = 0.;
if (!this->networkActive())
return network_imbalance;
@ -1262,18 +1271,18 @@ updateNetworkPressures(const int reportStepIdx)
continue;
}
const auto pressure = previous_node_pressures.at(name);
const double change = (new_pressure - pressure);
const Scalar change = (new_pressure - pressure);
if (std::abs(change) > network_imbalance) {
network_imbalance = std::abs(change);
}
// we dampen the amount of the nodal pressure can change during one iteration
// due to the fact our nodal pressure calculation is somewhat explicit
// TODO: the following parameters are subject to adjustment for optimization purpose
constexpr double upper_update_bound = 5.0 * unit::barsa;
constexpr Scalar upper_update_bound = 5.0 * unit::barsa;
// relative dampening factor based on update value
constexpr double damping_factor = 0.1;
const double damped_change = std::min(damping_factor * std::abs(change), upper_update_bound);
const double sign = change > 0 ? 1. : -1.;
constexpr Scalar damping_factor = 0.1;
const Scalar damped_change = std::min(damping_factor * std::abs(change), upper_update_bound);
const Scalar sign = change > 0 ? 1. : -1.;
node_pressures_[name] = pressure + sign * damped_change;
}
} else {
@ -1294,9 +1303,9 @@ updateNetworkPressures(const int reportStepIdx)
if (it != node_pressures_.end()) {
// The well belongs to a group with has a network pressure constraint,
// set the dynamic THP constraint of the well accordingly.
const double new_limit = it->second;
const Scalar new_limit = it->second;
well->setDynamicThpLimit(new_limit);
SingleWellState<double>& ws = this->wellState()[well->indexOfWell()];
SingleWellState<Scalar>& ws = this->wellState()[well->indexOfWell()];
const bool thp_is_limit = ws.production_cmode == Well::ProducerCMode::THP;
// TODO: not sure why the thp is NOT updated properly elsewhere
if (thp_is_limit) {
@ -1308,14 +1317,14 @@ updateNetworkPressures(const int reportStepIdx)
return network_imbalance;
}
void
BlackoilWellModelGeneric::
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
calculateEfficiencyFactors(const int reportStepIdx)
{
for (auto& well : well_container_generic_) {
const Well& wellEcl = well->wellEcl();
double well_efficiency_factor = wellEcl.getEfficiencyFactor();
WellGroupHelpers<double>::accumulateGroupEfficiencyFactor(schedule().getGroup(wellEcl.groupName(),
Scalar well_efficiency_factor = wellEcl.getEfficiencyFactor();
WellGroupHelpers<Scalar>::accumulateGroupEfficiencyFactor(schedule().getGroup(wellEcl.groupName(),
reportStepIdx),
schedule(),
reportStepIdx,
@ -1324,8 +1333,9 @@ calculateEfficiencyFactors(const int reportStepIdx)
}
}
template<class Scalar>
WellInterfaceGeneric*
BlackoilWellModelGeneric::
BlackoilWellModelGeneric<Scalar>::
getGenWell(const std::string& well_name)
{
// finding the iterator of the well in wells_ecl
@ -1340,8 +1350,8 @@ getGenWell(const std::string& well_name)
return *well;
}
void
BlackoilWellModelGeneric::
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
setRepRadiusPerfLength()
{
for (const auto& well : well_container_generic_) {
@ -1349,8 +1359,8 @@ setRepRadiusPerfLength()
}
}
void
BlackoilWellModelGeneric::
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
gliftDebug(const std::string& msg,
DeferredLogger& deferred_logger) const
{
@ -1361,9 +1371,8 @@ gliftDebug(const std::string& msg,
}
}
void
BlackoilWellModelGeneric::
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
gliftDebugShowALQ(DeferredLogger& deferred_logger)
{
for (auto& well : this->well_container_generic_) {
@ -1383,8 +1392,8 @@ gliftDebugShowALQ(DeferredLogger& deferred_logger)
// currently has the largest weighted incremental gradient. The
// procedure takes account of any limits on the group production
// rate or lift gas supply applied to any level of group.
void
BlackoilWellModelGeneric::
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
gasLiftOptimizationStage2(DeferredLogger& deferred_logger,
GLiftProdWells& prod_wells,
GLiftOptWells& glift_wells,
@ -1408,8 +1417,8 @@ gasLiftOptimizationStage2(DeferredLogger& deferred_logger,
glift.runOptimize();
}
void
BlackoilWellModelGeneric::
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
updateWellPotentials(const int reportStepIdx,
const bool onlyAfterEvent,
const SummaryConfig& summaryConfig,
@ -1467,11 +1476,10 @@ updateWellPotentials(const int reportStepIdx,
logAndCheckForExceptionsAndThrow(deferred_logger, exc_type,
"computeWellPotentials() failed: " + exc_msg,
terminal_output_, comm_);
}
void
BlackoilWellModelGeneric::
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
runWellPIScaling(const int reportStepIdx,
DeferredLogger& local_deferredLogger)
{
@ -1508,10 +1516,9 @@ runWellPIScaling(const int reportStepIdx,
this->prod_index_calc_[well_index].reInit(well);
};
auto rescaleWellPI =
[this, reportStepIdx](const int well_index,
const double newWellPI) -> void
const Scalar newWellPI) -> void
{
const auto& wname = this->wells_ecl_[well_index].name();
@ -1545,8 +1552,8 @@ runWellPIScaling(const int reportStepIdx,
this->last_run_wellpi_ = reportStepIdx;
}
bool
BlackoilWellModelGeneric::
template<class Scalar>
bool BlackoilWellModelGeneric<Scalar>::
shouldBalanceNetwork(const int reportStepIdx, const int iterationIdx) const
{
// if network is not active, we do not need to balance the network
@ -1570,10 +1577,8 @@ shouldBalanceNetwork(const int reportStepIdx, const int iterationIdx) const
}
}
std::vector<int>
BlackoilWellModelGeneric::
template<class Scalar>
std::vector<int> BlackoilWellModelGeneric<Scalar>::
getCellsForConnections(const Well& well) const
{
std::vector<int> wellCells;
@ -1592,9 +1597,10 @@ getCellsForConnections(const Well& well) const
return wellCells;
}
std::vector<std::string>
BlackoilWellModelGeneric::getWellsForTesting(const int timeStepIdx,
const double simulationTime)
template<class Scalar>
std::vector<std::string> BlackoilWellModelGeneric<Scalar>::
getWellsForTesting(const int timeStepIdx,
const double simulationTime)
{
const auto& wtest_config = schedule()[timeStepIdx].wtest_config();
if (!wtest_config.empty()) { // there is a WTEST request
@ -1603,8 +1609,8 @@ BlackoilWellModelGeneric::getWellsForTesting(const int timeStepIdx,
return {};
}
void
BlackoilWellModelGeneric::
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
assignWellTracerRates(data::Wells& wsrpt,
const WellTracerRates& wellTracerRates) const
{
@ -1618,13 +1624,13 @@ assignWellTracerRates(data::Wells& wsrpt,
continue;
}
std::string tracerName = wTR.first.second;
double rate = wTR.second;
Scalar rate = wTR.second;
xwPos->second.rates.set(data::Rates::opt::tracer, rate, tracerName);
}
}
std::vector<std::vector<int>>
BlackoilWellModelGeneric::
template<class Scalar>
std::vector<std::vector<int>> BlackoilWellModelGeneric<Scalar>::
getMaxWellConnections() const
{
std::vector<std::vector<int>> wells;
@ -1634,7 +1640,7 @@ getMaxWellConnections() const
wells.reserve(schedule_wells.size());
// initialize the additional cell connections introduced by wells.
for ( const auto& well : schedule_wells )
for (const auto& well : schedule_wells)
{
std::vector<int> compressed_well_perforations = this->getCellsForConnections(well);
@ -1647,26 +1653,29 @@ getMaxWellConnections() const
return wells;
}
int BlackoilWellModelGeneric::numLocalWellsEnd() const
template<class Scalar>
int BlackoilWellModelGeneric<Scalar>::numLocalWellsEnd() const
{
auto w = schedule().getWellsatEnd();
w.erase(std::remove_if(w.begin(), w.end(), not_on_process_), w.end());
return w.size();
}
int BlackoilWellModelGeneric::numLocalNonshutWells() const
template<class Scalar>
int BlackoilWellModelGeneric<Scalar>::numLocalNonshutWells() const
{
return well_container_generic_.size();
}
void BlackoilWellModelGeneric::initInjMult() {
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::initInjMult()
{
for (auto& well : this->well_container_generic_) {
if (well->isInjector() && well->wellEcl().getInjMultMode() != Well::InjMultMode::NONE) {
const auto& ws = this->wellState().well(well->indexOfWell());
const auto& perf_data = ws.perf_data;
auto &values = this->prev_inj_multipliers_[well->name()];
auto& values = this->prev_inj_multipliers_[well->name()];
if (values.empty()) {
values.assign(perf_data.size(), 1.0);
}
@ -1675,13 +1684,14 @@ void BlackoilWellModelGeneric::initInjMult() {
}
}
void BlackoilWellModelGeneric::updateFiltrationParticleVolume(const double dt,
const std::size_t water_index)
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
updateFiltrationParticleVolume(const double dt,
const std::size_t water_index)
{
for (auto& well : this->well_container_generic_) {
if (well->isInjector()) {
const double conc = well->wellEcl().evalFilterConc(this->summaryState_);
const Scalar conc = well->wellEcl().evalFilterConc(this->summaryState_);
if (conc > 0.) {
auto fc = this->filter_cake_
.emplace(std::piecewise_construct,
@ -1695,7 +1705,9 @@ void BlackoilWellModelGeneric::updateFiltrationParticleVolume(const double dt,
}
}
void BlackoilWellModelGeneric::updateInjMult(DeferredLogger& deferred_logger)
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
updateInjMult(DeferredLogger& deferred_logger)
{
for (const auto& well : this->well_container_generic_) {
if (well->isInjector() && well->wellEcl().getInjMultMode() != Well::InjMultMode::NONE) {
@ -1704,7 +1716,9 @@ void BlackoilWellModelGeneric::updateInjMult(DeferredLogger& deferred_logger)
}
}
void BlackoilWellModelGeneric::updateInjFCMult(DeferredLogger& deferred_logger)
template<class Scalar>
void BlackoilWellModelGeneric<Scalar>::
updateInjFCMult(DeferredLogger& deferred_logger)
{
for (auto& well : this->well_container_generic_) {
if (well->isInjector()) {
@ -1717,4 +1731,6 @@ void BlackoilWellModelGeneric::updateInjFCMult(DeferredLogger& deferred_logger)
}
}
template class BlackoilWellModelGeneric<double>;
}

View File

@ -46,7 +46,6 @@
#include <memory>
#include <optional>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <vector>
@ -79,6 +78,7 @@ namespace Opm { namespace data {
namespace Opm {
/// Class for handling the blackoil well model.
template<class Scalar>
class BlackoilWellModelGeneric
{
public:
@ -114,14 +114,14 @@ public:
std::vector<Well> getLocalWells(const int timeStepIdx) const;
const Schedule& schedule() const { return schedule_; }
const PhaseUsage& phaseUsage() const { return phase_usage_; }
const GroupState<double>& groupState() const { return this->active_wgstate_.group_state; }
const GroupState<Scalar>& groupState() const { return this->active_wgstate_.group_state; }
std::vector<const WellInterfaceGeneric*> genericWells() const
{ return {well_container_generic_.begin(), well_container_generic_.end()}; }
/*
Immutable version of the currently active wellstate.
*/
const WellState<double>& wellState() const
const WellState<Scalar>& wellState() const
{
return this->active_wgstate_.well_state;
}
@ -129,7 +129,7 @@ public:
/*
Mutable version of the currently active wellstate.
*/
WellState<double>& wellState()
WellState<Scalar>& wellState()
{
return this->active_wgstate_.well_state;
}
@ -138,19 +138,18 @@ public:
Will return the currently active nupcolWellState; must initialize
the internal nupcol wellstate with initNupcolWellState() first.
*/
const WellState<double>& nupcolWellState() const
const WellState<Scalar>& nupcolWellState() const
{
return this->nupcol_wgstate_.well_state;
}
GroupState<double>& groupState() { return this->active_wgstate_.group_state; }
GroupState<Scalar>& groupState() { return this->active_wgstate_.group_state; }
WellTestState& wellTestState() { return this->active_wgstate_.well_test_state; }
const WellTestState& wellTestState() const { return this->active_wgstate_.well_test_state; }
double wellPI(const int well_index) const;
double wellPI(const std::string& well_name) const;
Scalar wellPI(const int well_index) const;
Scalar wellPI(const std::string& well_name) const;
void updateEclWells(const int timeStepIdx,
const SimulatorUpdate& sim_update,
@ -210,7 +209,8 @@ public:
bool shouldBalanceNetwork(const int reportStepIndex,
const int iterationIdx) const;
void updateClosedWellsThisStep(const std::string& well_name) const {
void updateClosedWellsThisStep(const std::string& well_name) const
{
this->closed_this_step_.insert(well_name);
}
bool wasDynamicallyShutThisTimeStep(const std::string& well_name) const;
@ -254,7 +254,6 @@ public:
}
protected:
/*
The dynamic state of the well model is maintained with an instance
of the WellState class. Currently we have
@ -275,7 +274,6 @@ protected:
nupcol_well_state_ and the initNupcolWellState() function.
*/
/*
Will return the last good wellstate. This is typcially used when
initializing a new report step where the Schedule object might
@ -283,25 +281,22 @@ protected:
prevWellState() must have been stored with the commitWellState()
function first.
*/
const WellState<double>& prevWellState() const
const WellState<Scalar>& prevWellState() const
{
return this->last_valid_wgstate_.well_state;
}
const WGState<double>& prevWGState() const
const WGState<Scalar>& prevWGState() const
{
return this->last_valid_wgstate_;
}
/*
Will store a copy of the input argument well_state in the
last_valid_well_state_ member, that state can then be recovered
with a subsequent call to resetWellState().
*/
void commitWGState(WGState<double> wgstate)
void commitWGState(WGState<Scalar> wgstate)
{
this->last_valid_wgstate_ = std::move(wgstate);
}
@ -328,28 +323,29 @@ protected:
/// \brief Create the parallel well information
/// \param localWells The local wells from ECL schedule
std::vector<std::reference_wrapper<ParallelWellInfo>> createLocalParallelWellInfo(const std::vector<Well>& wells);
std::vector<std::reference_wrapper<ParallelWellInfo>>
createLocalParallelWellInfo(const std::vector<Well>& wells);
void initializeWellProdIndCalculators();
void initializeWellPerfData();
bool wasDynamicallyShutThisTimeStep(const int well_index) const;
double updateNetworkPressures(const int reportStepIdx);
Scalar updateNetworkPressures(const int reportStepIdx);
void updateWsolvent(const Group& group,
const int reportStepIdx,
const WellState<double>& wellState);
const WellState<Scalar>& wellState);
void setWsolvent(const Group& group,
const int reportStepIdx,
double wsolvent);
Scalar wsolvent);
virtual void calcRates(const int fipnum,
const int pvtreg,
const std::vector<double>& production_rates,
std::vector<double>& resv_coeff) = 0;
const std::vector<Scalar>& production_rates,
std::vector<Scalar>& resv_coeff) = 0;
virtual void calcInjRates(const int fipnum,
const int pvtreg,
std::vector<double>& resv_coeff) = 0;
const int pvtreg,
std::vector<Scalar>& resv_coeff) = 0;
void assignShutConnections(data::Wells& wsrpt,
const int reportStepIndex) const;
@ -357,12 +353,13 @@ protected:
data::GroupData& gdata) const;
void assignGroupValues(const int reportStepIdx,
std::map<std::string, data::GroupData>& gvalues) const;
void assignNodeValues(std::map<std::string, data::NodeData>& nodevalues, const int reportStepIdx) const;
void assignNodeValues(std::map<std::string, data::NodeData>& nodevalues,
const int reportStepIdx) const;
void calculateEfficiencyFactors(const int reportStepIdx);
void checkGconsaleLimits(const Group& group,
WellState<double>& well_state,
WellState<Scalar>& well_state,
const int reportStepIdx,
DeferredLogger& deferred_logger);
@ -395,7 +392,7 @@ protected:
const int episodeIndex);
virtual void computePotentials(const std::size_t widx,
const WellState<double>& well_state_copy,
const WellState<Scalar>& well_state_copy,
std::string& exc_msg,
ExceptionType::ExcEnum& exc_type,
DeferredLogger& deferred_logger) = 0;
@ -408,11 +405,11 @@ protected:
void initInjMult();
void updateInjMult(DeferredLogger& deferred_logger);
void updateInjFCMult(DeferredLogger& deferred_logger);
void updateFiltrationParticleVolume(const double dt, const std::size_t water_index);
void updateFiltrationParticleVolume(const double dt,
const std::size_t water_index);
// create the well container
virtual void createWellContainer(const int time_step) = 0;
@ -434,7 +431,7 @@ protected:
std::vector<std::string> getWellsForTesting(const int timeStepIdx,
const double simulationTime);
using WellTracerRates = std::map<std::pair<std::string, std::string>, double>;
using WellTracerRates = std::map<std::pair<std::string, std::string>, Scalar>;
void assignWellTracerRates(data::Wells& wsrpt,
const WellTracerRates& wellTracerRates) const;
@ -561,13 +558,13 @@ protected:
GuideRate guideRate_;
std::unique_ptr<VFPProperties> vfp_properties_{};
std::map<std::string, double> node_pressures_; // Storing network pressures for output.
std::map<std::string, Scalar> node_pressures_; // Storing network pressures for output.
// previous injection multiplier, it is used in the injection multiplier calculation for WINJMULT keyword
std::unordered_map<std::string, std::vector<double>> prev_inj_multipliers_;
std::unordered_map<std::string, std::vector<Scalar>> prev_inj_multipliers_;
// Handling for filter cake injection multipliers
std::unordered_map<std::string, WellFilterCake<double>> filter_cake_;
std::unordered_map<std::string, WellFilterCake<Scalar>> filter_cake_;
/*
The various wellState members should be accessed and modified
@ -575,9 +572,9 @@ protected:
commitWellState(), resetWellState(), nupcolWellState() and
updateNupcolWellState().
*/
WGState<double> active_wgstate_;
WGState<double> last_valid_wgstate_;
WGState<double> nupcol_wgstate_;
WGState<Scalar> active_wgstate_;
WGState<Scalar> last_valid_wgstate_;
WGState<Scalar> nupcol_wgstate_;
bool glift_debug = false;
@ -587,11 +584,10 @@ protected:
// Store maps of group name and new group controls for output
std::map<std::string, std::string> switched_prod_groups_;
std::map<std::pair<std::string, Opm::Phase>, std::string> switched_inj_groups_;
std::map<std::pair<std::string, Phase>, std::string> switched_inj_groups_;
// Store map of group name and close offending well for output
std::map<std::string, std::pair<std::string, std::string>> closed_offending_wells_;
private:
WellInterfaceGeneric* getGenWell(const std::string& well_name);
};

View File

@ -30,7 +30,7 @@
namespace Opm {
class BlackoilWellModelGeneric;
template<class Scalar> class BlackoilWellModelGeneric;
namespace data {
struct GroupData;
struct GroupGuideRates;
@ -46,7 +46,7 @@ class BlackoilWellModelGuideRates
{
public:
//! \brief Constructor initializes reference to the well model.
BlackoilWellModelGuideRates(const BlackoilWellModelGeneric& wellModel)
BlackoilWellModelGuideRates(const BlackoilWellModelGeneric<Scalar>& wellModel)
: wellModel_(wellModel)
{}
@ -82,7 +82,7 @@ private:
//! \brief Obtain guide rate values for injection group.
data::GuideRateValue getGuideRateInjectionGroupValues(const Group& group) const;
const BlackoilWellModelGeneric& wellModel_; //!< Reference to well model
const BlackoilWellModelGeneric<Scalar>& wellModel_; //!< Reference to well model
};

View File

@ -30,7 +30,7 @@
namespace Opm {
class BlackoilWellModelGeneric;
template<class Scalar> class BlackoilWellModelGeneric;
namespace data {
struct GroupData;
class GroupAndNetworkValues;
@ -49,7 +49,7 @@ class BlackoilWellModelRestart
{
public:
//! \brief Constructor initializes reference to the well model.
BlackoilWellModelRestart(const BlackoilWellModelGeneric& wellModel)
BlackoilWellModelRestart(const BlackoilWellModelGeneric<Scalar>& wellModel)
: wellModel_(wellModel)
{}
@ -98,7 +98,7 @@ private:
const data::GroupData& value,
GroupState<Scalar>& grpState) const;
const BlackoilWellModelGeneric& wellModel_; //!< Reference to well model
const BlackoilWellModelGeneric<Scalar>& wellModel_; //!< Reference to well model
};

View File

@ -59,15 +59,15 @@ namespace Opm {
template<typename TypeTag>
BlackoilWellModel<TypeTag>::
BlackoilWellModel(Simulator& simulator, const PhaseUsage& phase_usage)
: BlackoilWellModelGeneric(simulator.vanguard().schedule(),
simulator.vanguard().summaryState(),
simulator.vanguard().eclState(),
phase_usage,
simulator.gridView().comm())
: BlackoilWellModelGeneric<Scalar>(simulator.vanguard().schedule(),
simulator.vanguard().summaryState(),
simulator.vanguard().eclState(),
phase_usage,
simulator.gridView().comm())
, simulator_(simulator)
{
terminal_output_ = ((simulator.gridView().comm().rank() == 0) &&
Parameters::get<TypeTag, Properties::EnableTerminalOutput>());
this->terminal_output_ = ((simulator.gridView().comm().rank() == 0) &&
Parameters::get<TypeTag, Properties::EnableTerminalOutput>());
local_num_cells_ = simulator_.gridView().size(0);
@ -146,7 +146,7 @@ namespace Opm {
gravity_ = simulator_.problem().gravity()[2];
initial_step_ = true;
this->initial_step_ = true;
// add the eWoms auxiliary module for the wells to the list
simulator_.model().addAuxiliaryModule(this);
@ -162,9 +162,9 @@ namespace Opm {
{
const uint64_t effective_events_mask = ScheduleEvents::WELL_STATUS_CHANGE
+ ScheduleEvents::NEW_WELL;
const auto& events = schedule()[reportStepIdx].wellgroup_events();
const auto& events = this->schedule()[reportStepIdx].wellgroup_events();
for (auto& wellPtr : this->well_container_) {
const bool well_opened_this_step = report_step_starts_ && events.hasEvent(wellPtr->name(), effective_events_mask);
const bool well_opened_this_step = this->report_step_starts_ && events.hasEvent(wellPtr->name(), effective_events_mask);
wellPtr->init(&this->phase_usage_, this->depth_, this->gravity_,
this->local_num_cells_, this->B_avg_, well_opened_this_step);
}
@ -181,7 +181,7 @@ namespace Opm {
}
// Create cartesian to compressed mapping
const auto& schedule_wells = schedule().getWellsatEnd();
const auto& schedule_wells = this->schedule().getWellsatEnd();
// initialize the additional cell connections introduced by wells.
for (const auto& well : schedule_wells)
@ -419,8 +419,8 @@ namespace Opm {
this->resetWGState();
const int reportStepIdx = simulator_.episodeIndex();
updateAndCommunicateGroupData(reportStepIdx,
simulator_.model().newtonMethod().numIterations());
this->updateAndCommunicateGroupData(reportStepIdx,
simulator_.model().newtonMethod().numIterations());
this->wellState().updateWellsDefaultALQ(this->wells_ecl_, this->summaryState());
this->wellState().gliftTimeStepInit();
@ -436,8 +436,7 @@ namespace Opm {
// Wells are active if they are active wells on at least one process.
const Grid& grid = simulator_.vanguard().grid();
wells_active_ = !this->well_container_.empty();
wells_active_ = grid.comm().max(wells_active_);
this->wells_active_ = grid.comm().max(!this->well_container_.empty());
// do the initialization for all the wells
// TODO: to see whether we can postpone of the intialization of the well containers to
@ -451,29 +450,29 @@ namespace Opm {
}
// calculate the efficiency factors for each well
calculateEfficiencyFactors(reportStepIdx);
this->calculateEfficiencyFactors(reportStepIdx);
if constexpr (has_polymer_)
{
if (PolymerModule::hasPlyshlog() || getPropValue<TypeTag, Properties::EnablePolymerMW>() ) {
setRepRadiusPerfLength();
this->setRepRadiusPerfLength();
}
}
}
OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger, "beginTimeStep() failed: ",
terminal_output_, simulator_.vanguard().grid().comm());
this->terminal_output_, simulator_.vanguard().grid().comm());
for (auto& well : well_container_) {
well->setVFPProperties(vfp_properties_.get());
well->setGuideRate(&guideRate_);
well->setVFPProperties(this->vfp_properties_.get());
well->setGuideRate(&this->guideRate_);
}
this->updateInjFCMult(local_deferredLogger);
// Close completions due to economic reasons
for (auto& well : well_container_) {
well->closeCompletions(wellTestState());
well->closeCompletions(this->wellTestState());
}
// we need the inj_multiplier from the previous time step
@ -501,10 +500,10 @@ namespace Opm {
// calculate the well potentials
try {
updateWellPotentials(reportStepIdx,
/*onlyAfterEvent*/true,
simulator_.vanguard().summaryConfig(),
local_deferredLogger);
this->updateWellPotentials(reportStepIdx,
/*onlyAfterEvent*/true,
simulator_.vanguard().summaryConfig(),
local_deferredLogger);
} catch ( std::runtime_error& e ) {
const std::string msg = "A zero well potential is returned for output purposes. ";
local_deferredLogger.warning("WELL_POTENTIAL_CALCULATION_FAILED", msg);
@ -529,7 +528,7 @@ namespace Opm {
std::string exc_msg;
auto exc_type = ExceptionType::NONE;
// update gpmaint targets
if (schedule_[reportStepIdx].has_gpmaint()) {
if (this->schedule_[reportStepIdx].has_gpmaint()) {
for (auto& calculator : regionalAveragePressureCalculator_) {
calculator.second->template defineState<ElementContext>(simulator_);
}
@ -550,8 +549,8 @@ namespace Opm {
+ ScheduleEvents::WELL_SWITCHED_INJECTOR_PRODUCER
+ ScheduleEvents::NEW_WELL;
const auto& events = schedule()[reportStepIdx].wellgroup_events();
const bool event = report_step_starts_ && events.hasEvent(well->name(), effective_events_mask);
const auto& events = this->schedule()[reportStepIdx].wellgroup_events();
const bool event = this->report_step_starts_ && events.hasEvent(well->name(), effective_events_mask);
const bool dyn_status_change = this->wellState().well(well->name()).status
!= this->prevWellState().well(well->name()).status;
@ -576,7 +575,7 @@ namespace Opm {
}
logAndCheckForExceptionsAndThrow(local_deferredLogger,
exc_type, "beginTimeStep() failed: " + exc_msg, terminal_output_, comm);
exc_type, "beginTimeStep() failed: " + exc_msg, this->terminal_output_, comm);
}
@ -587,13 +586,13 @@ namespace Opm {
DeferredLogger& deferred_logger)
{
for (const std::string& well_name : this->getWellsForTesting(timeStepIdx, simulationTime)) {
const Well& wellEcl = schedule().getWell(well_name, timeStepIdx);
const Well& wellEcl = this->schedule().getWell(well_name, timeStepIdx);
if (wellEcl.getStatus() == Well::Status::SHUT)
continue;
WellInterfacePtr well = createWellForWellTest(well_name, timeStepIdx, deferred_logger);
// some preparation before the well can be used
well->init(&phase_usage_, depth_, gravity_, local_num_cells_, B_avg_, true);
well->init(&this->phase_usage_, depth_, gravity_, local_num_cells_, B_avg_, true);
double well_efficiency_factor = wellEcl.getEfficiencyFactor();
WellGroupHelpers<double>::accumulateGroupEfficiencyFactor(this->schedule().getGroup(wellEcl.groupName(),
@ -603,8 +602,8 @@ namespace Opm {
well_efficiency_factor);
well->setWellEfficiencyFactor(well_efficiency_factor);
well->setVFPProperties(vfp_properties_.get());
well->setGuideRate(&guideRate_);
well->setVFPProperties(this->vfp_properties_.get());
well->setGuideRate(&this->guideRate_);
// initialize rates/previous rates to prevent zero fractions in vfp-interpolation
if (well->isProducer()) {
@ -615,7 +614,8 @@ namespace Opm {
}
try {
well->wellTesting(simulator_, simulationTime, this->wellState(), this->groupState(), wellTestState(), deferred_logger);
well->wellTesting(simulator_, simulationTime, this->wellState(),
this->groupState(), this->wellTestState(), deferred_logger);
} catch (const std::exception& e) {
const std::string msg = fmt::format("Exception during testing of well: {}. The well will not open.\n Exception message: {}", wellEcl.name(), e.what());
deferred_logger.warning("WELL_TESTING_FAILED", msg);
@ -663,7 +663,7 @@ namespace Opm {
this->closed_this_step_.clear();
// time step is finished and we are not any more at the beginning of an report step
report_step_starts_ = false;
this->report_step_starts_ = false;
const int reportStepIdx = simulator_.episodeIndex();
DeferredLogger local_deferredLogger;
@ -690,9 +690,9 @@ namespace Opm {
well->reportWellSwitching(this->wellState().well(well->indexOfWell()), local_deferredLogger);
}
// report group switching
if (terminal_output_) {
if (this->terminal_output_) {
for (const auto& [name, to] : switched_prod_groups_) {
for (const auto& [name, to] : this->switched_prod_groups_) {
const Group::ProductionCMode& oldControl = this->prevWGState().group_state.production_control(name);
std::string from = Group::ProductionCMode2String(oldControl);
if (to != from) {
@ -703,7 +703,7 @@ namespace Opm {
local_deferredLogger.info(msg);
}
}
for (const auto& [key, to] : switched_inj_groups_) {
for (const auto& [key, to] : this->switched_inj_groups_) {
const std::string& name = key.first;
const Opm::Phase& phase = key.second;
@ -724,23 +724,23 @@ namespace Opm {
// calculate the well potentials
try {
updateWellPotentials(reportStepIdx,
/*onlyAfterEvent*/false,
simulator_.vanguard().summaryConfig(),
local_deferredLogger);
this->updateWellPotentials(reportStepIdx,
/*onlyAfterEvent*/false,
simulator_.vanguard().summaryConfig(),
local_deferredLogger);
} catch ( std::runtime_error& e ) {
const std::string msg = "A zero well potential is returned for output purposes. ";
local_deferredLogger.warning("WELL_POTENTIAL_CALCULATION_FAILED", msg);
}
updateWellTestState(simulationTime, wellTestState());
updateWellTestState(simulationTime, this->wellTestState());
// check group sales limits at the end of the timestep
const Group& fieldGroup = schedule_.getGroup("FIELD", reportStepIdx);
checkGEconLimits(
fieldGroup, simulationTime, simulator_.episodeIndex(), local_deferredLogger);
checkGconsaleLimits(fieldGroup, this->wellState(),
simulator_.episodeIndex(), local_deferredLogger);
const Group& fieldGroup = this->schedule_.getGroup("FIELD", reportStepIdx);
this->checkGEconLimits(fieldGroup, simulationTime,
simulator_.episodeIndex(), local_deferredLogger);
this->checkGconsaleLimits(fieldGroup, this->wellState(),
simulator_.episodeIndex(), local_deferredLogger);
this->calculateProductivityIndexValues(local_deferredLogger);
@ -748,7 +748,7 @@ namespace Opm {
const Opm::Parallel::Communication& comm = grid().comm();
DeferredLogger global_deferredLogger = gatherDeferredLogger(local_deferredLogger, comm);
if (terminal_output_) {
if (this->terminal_output_) {
global_deferredLogger.logMessages();
}
@ -822,8 +822,9 @@ namespace Opm {
}
OPM_END_PARALLEL_TRY_CATCH("BlackoilWellModel::initializeWellState() failed: ", simulator_.vanguard().grid().comm());
this->wellState().init(cellPressures, schedule(), wells_ecl_, local_parallel_well_info_, timeStepIdx,
&this->prevWellState(), well_perf_data_,
this->wellState().init(cellPressures, this->schedule(), this->wells_ecl_,
this->local_parallel_well_info_, timeStepIdx,
&this->prevWellState(), this->well_perf_data_,
this->summaryState());
}
@ -838,7 +839,7 @@ namespace Opm {
{
DeferredLogger local_deferredLogger;
const int nw = numLocalWells();
const int nw = this->numLocalWells();
well_container_.clear();
@ -846,7 +847,7 @@ namespace Opm {
well_container_.reserve(nw);
for (int w = 0; w < nw; ++w) {
const Well& well_ecl = wells_ecl_[w];
const Well& well_ecl = this->wells_ecl_[w];
if (!well_ecl.hasConnections()) {
// No connections in this well. Nothing to do.
@ -875,14 +876,14 @@ namespace Opm {
// a timestep without the well in question, after it caused
// repeated timestep cuts. It should therefore not be opened,
// even if it was new or received new targets this report step.
const bool closed_this_step = (wellTestState().lastTestTime(well_name) == simulator_.time());
const bool closed_this_step = (this->wellTestState().lastTestTime(well_name) == simulator_.time());
// TODO: more checking here, to make sure this standard more specific and complete
// maybe there is some WCON keywords will not open the well
auto& events = this->wellState().well(w).events;
if (events.hasEvent(ScheduleEvents::REQUEST_OPEN_WELL)) {
if (!closed_this_step) {
wellTestState().open_well(well_name);
wellTestState().open_completions(well_name);
this->wellTestState().open_well(well_name);
this->wellTestState().open_completions(well_name);
}
events.clearEvent(ScheduleEvents::REQUEST_OPEN_WELL);
}
@ -891,7 +892,7 @@ namespace Opm {
// TODO: should we do this for all kinds of closing reasons?
// something like wellTestState().hasWell(well_name)?
bool wellIsStopped = false;
if (wellTestState().well_is_closed(well_name))
if (this->wellTestState().well_is_closed(well_name))
{
if (well_ecl.getAutomaticShutIn()) {
// shut wells are not added to the well container
@ -913,8 +914,8 @@ namespace Opm {
// shut wells with zero rante constraints and disallowing
if (!well_ecl.getAllowCrossFlow()) {
const bool any_zero_rate_constraint = well_ecl.isProducer()
? well_ecl.productionControls(summaryState_).anyZeroRateConstraint()
: well_ecl.injectionControls(summaryState_).anyZeroRateConstraint();
? well_ecl.productionControls(this->summaryState_).anyZeroRateConstraint()
: well_ecl.injectionControls(this->summaryState_).anyZeroRateConstraint();
if (any_zero_rate_constraint) {
// Treat as shut, do not add to container.
local_deferredLogger.debug(fmt::format(" Well {} gets shut due to having zero rate constraint and disallowing crossflow ", well_ecl.name()) );
@ -939,23 +940,23 @@ namespace Opm {
const Opm::Parallel::Communication& comm = grid().comm();
DeferredLogger global_deferredLogger = gatherDeferredLogger(local_deferredLogger, comm);
if (terminal_output_) {
if (this->terminal_output_) {
global_deferredLogger.logMessages();
}
well_container_generic_.clear();
this->well_container_generic_.clear();
for (auto& w : well_container_)
well_container_generic_.push_back(w.get());
this->well_container_generic_.push_back(w.get());
const auto& network = schedule()[report_step].network();
const auto& network = this->schedule()[report_step].network();
if (network.active() && !this->node_pressures_.empty()) {
for (auto& well: well_container_generic_) {
for (auto& well: this->well_container_generic_) {
// Producers only, since we so far only support the
// "extended" network model (properties defined by
// BRANPROP and NODEPROP) which only applies to producers.
if (well->isProducer()) {
const auto it = node_pressures_.find(well->wellEcl().groupName());
if (it != node_pressures_.end()) {
const auto it = this->node_pressures_.find(well->wellEcl().groupName());
if (it != this->node_pressures_.end()) {
// The well belongs to a group which has a network nodal pressure,
// set the dynamic THP constraint based on the network nodal pressure
const double nodal_pressure = it->second;
@ -1002,7 +1003,7 @@ namespace Opm {
// Cater for case where local part might have no perforations.
const auto pvtreg = perf_data.empty()
? 0 : pvt_region_idx_[perf_data.front().cell_index];
? 0 : this->pvt_region_idx_[perf_data.front().cell_index];
const auto& parallel_well_info = this->local_parallel_well_info_[wellID].get();
const auto global_pvtreg = parallel_well_info.broadcastFirstPerforationValue(pvtreg);
@ -1031,10 +1032,10 @@ namespace Opm {
DeferredLogger& deferred_logger) const
{
// Finding the location of the well in wells_ecl
const int nw_wells_ecl = wells_ecl_.size();
const int nw_wells_ecl = this->wells_ecl_.size();
int index_well_ecl = 0;
for (; index_well_ecl < nw_wells_ecl; ++index_well_ecl) {
if (well_name == wells_ecl_[index_well_ecl].name()) {
if (well_name == this->wells_ecl_[index_well_ecl].name()) {
break;
}
}
@ -1100,22 +1101,22 @@ namespace Opm {
if (this->glift_debug) {
const std::string msg = fmt::format(
"assemble() : iteration {}" , iterationIdx);
gliftDebug(msg, local_deferredLogger);
this->gliftDebug(msg, local_deferredLogger);
}
last_report_ = SimulatorReportSingle();
Dune::Timer perfTimer;
perfTimer.start();
closed_offending_wells_.clear();
this->closed_offending_wells_.clear();
{
const int episodeIdx = simulator_.episodeIndex();
const auto& network = schedule()[episodeIdx].network();
if ( !wellsActive() && !network.active() ) {
const auto& network = this->schedule()[episodeIdx].network();
if (!this->wellsActive() && !network.active()) {
return;
}
}
if (iterationIdx == 0 && wellsActive()) {
if (iterationIdx == 0 && this->wellsActive()) {
// try-catch is needed here as updateWellControls
// contains global communication and has either to
// be reached by all processes or all need to abort
@ -1127,14 +1128,14 @@ namespace Opm {
}
OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger,
"assemble() failed (It=0): ",
terminal_output_, grid().comm());
this->terminal_output_, grid().comm());
}
const bool well_group_control_changed = updateWellControlsAndNetwork(false, dt, local_deferredLogger);
// even when there is no wells active, the network nodal pressure still need to be updated through updateWellControlsAndNetwork()
// but there is no need to assemble the well equations
if ( ! wellsActive() ) {
if ( ! this->wellsActive() ) {
return;
}
@ -1163,7 +1164,7 @@ namespace Opm {
const std::size_t max_iteration = param_.network_max_iterations_;
std::size_t network_update_iteration = 0;
while (do_network_update) {
if (terminal_output_ && (network_update_iteration == iteration_to_relax) ) {
if (this->terminal_output_ && (network_update_iteration == iteration_to_relax) ) {
local_deferredLogger.info(" we begin using relaxed tolerance for network update now after " + std::to_string(iteration_to_relax) + " iterations ");
}
const bool relax_network_balance = network_update_iteration >= iteration_to_relax;
@ -1172,7 +1173,7 @@ namespace Opm {
++network_update_iteration;
if (network_update_iteration >= max_iteration ) {
if (terminal_output_) {
if (this->terminal_output_) {
local_deferredLogger.info("maximum of " + std::to_string(max_iteration) + " iterations has been used, we stop the network update now. "
"The simulation will continue with unconverged network results");
}
@ -1207,11 +1208,11 @@ namespace Opm {
prepareWellsBeforeAssembling(dt, local_deferredLogger);
}
OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger, "updateWellControlsAndNetworkIteration() failed: ",
terminal_output_, grid().comm());
this->terminal_output_, grid().comm());
//update guide rates
const int reportStepIdx = simulator_.episodeIndex();
if (alq_updated || BlackoilWellModelGuideRates<double>(*this).
if (alq_updated || BlackoilWellModelGuideRates(*this).
guideRateUpdateIsNeeded(reportStepIdx)) {
const double simulationTime = simulator_.time();
const auto& comm = simulator_.vanguard().grid().comm();
@ -1250,8 +1251,8 @@ namespace Opm {
{
const int episodeIdx = simulator_.episodeIndex();
const auto& network = schedule()[episodeIdx].network();
if ( !wellsActive() && !network.active() ) {
const auto& network = this->schedule()[episodeIdx].network();
if (!this->wellsActive() && !network.active()) {
return;
}
}
@ -1268,7 +1269,7 @@ namespace Opm {
// TODO: errors here must be caught higher up, as this method is not called in parallel.
// We will log errors on rank 0, but not other ranks for now.
if (terminal_output_) {
if (this->terminal_output_) {
local_deferredLogger.logMessages();
}
@ -1290,9 +1291,9 @@ namespace Opm {
// If all_newton is true we still want to optimize several times pr timestep
// i.e. we also optimize if check simulation_time == last_glift_opt_time_
// that is when the last_glift_opt_time is already updated with the current time step
if ( simulation_time == last_glift_opt_time_ || simulation_time >= (last_glift_opt_time_ + min_wait)) {
if ( simulation_time == this->last_glift_opt_time_ || simulation_time >= (this->last_glift_opt_time_ + min_wait)) {
do_glift_optimization = true;
last_glift_opt_time_ = simulation_time;
this->last_glift_opt_time_ = simulation_time;
}
if (do_glift_optimization) {
@ -1314,7 +1315,7 @@ namespace Opm {
simulator_.vanguard().summaryState(),
simulator_.episodeIndex(),
simulator_.model().newtonMethod().numIterations(),
phase_usage_,
this->phase_usage_,
deferred_logger,
this->wellState(),
this->groupState(),
@ -1322,12 +1323,13 @@ namespace Opm {
this->glift_debug
};
group_info.initialize();
gasLiftOptimizationStage1(
deferred_logger, prod_wells, glift_wells, group_info, state_map);
gasLiftOptimizationStage2(
deferred_logger, prod_wells, glift_wells, group_info, state_map,
simulator_.episodeIndex());
if (this->glift_debug) gliftDebugShowALQ(deferred_logger);
gasLiftOptimizationStage1(deferred_logger, prod_wells, glift_wells,
group_info, state_map);
this->gasLiftOptimizationStage2(deferred_logger, prod_wells, glift_wells,
group_info, state_map, simulator_.episodeIndex());
if (this->glift_debug) {
this->gliftDebugShowALQ(deferred_logger);
}
num_wells_changed = glift_wells.size();
}
num_wells_changed = this->comm_.sum(num_wells_changed);
@ -1527,7 +1529,7 @@ namespace Opm {
deferred_logger);
}
OPM_END_PARALLEL_TRY_CATCH_LOG(deferred_logger, "BlackoilWellModel::assembleWellEqWithoutIteration failed: ",
terminal_output_, grid().comm());
this->terminal_output_, grid().comm());
}
@ -1678,7 +1680,7 @@ namespace Opm {
int wdof = rdofs + i;
jacobian.entry(wdof,wdof) = 1.0;// better scaling ?
}
std::vector<std::vector<int>> wellconnections = getMaxWellConnections();
std::vector<std::vector<int>> wellconnections = this->getMaxWellConnections();
for(int i=0; i < nw; i++){
const auto& perfcells = wellconnections[i];
for(int perfcell : perfcells){
@ -1705,7 +1707,7 @@ namespace Opm {
}
OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger,
"recoverWellSolutionAndUpdateWellState() failed: ",
terminal_output_, simulator_.vanguard().grid().comm());
this->terminal_output_, simulator_.vanguard().grid().comm());
}
@ -1728,7 +1730,7 @@ namespace Opm {
}
// TODO: avoid losing the logging information that could
// be stored in the local_deferredlogger in a parallel case.
if (terminal_output_) {
if (this->terminal_output_) {
local_deferredLogger.logMessages();
}
}
@ -1792,7 +1794,7 @@ namespace Opm {
}
// Log debug messages for NaN or too large residuals.
if (terminal_output_) {
if (this->terminal_output_) {
for (const auto& f : report.wellFailures()) {
if (f.severity() == ConvergenceReport::Severity::NotANumber) {
local_deferredLogger.debug("NaN residual found with phase " + std::to_string(f.phase()) + " for well " + f.wellName());
@ -1841,11 +1843,11 @@ namespace Opm {
report.setWellGroupTargetsViolated(this->lastReport().well_group_control_changed);
}
if (terminal_output_) {
if (this->terminal_output_) {
global_deferredLogger.logMessages();
}
// Log debug messages for NaN or too large residuals.
if (terminal_output_) {
if (this->terminal_output_) {
for (const auto& f : report.wellFailures()) {
if (f.severity() == ConvergenceReport::Severity::NotANumber) {
OpmLog::debug("NaN residual found with phase " + std::to_string(f.phase()) + " for well " + f.wellName());
@ -1882,21 +1884,21 @@ namespace Opm {
updateWellControls(const bool mandatory_network_balance, DeferredLogger& deferred_logger, const bool relax_network_tolerance)
{
const int episodeIdx = simulator_.episodeIndex();
const auto& network = schedule()[episodeIdx].network();
if (!wellsActive() && !network.active()) {
const auto& network = this->schedule()[episodeIdx].network();
if (!this->wellsActive() && !network.active()) {
return {false, false};
}
const int iterationIdx = simulator_.model().newtonMethod().numIterations();
const auto& comm = simulator_.vanguard().grid().comm();
updateAndCommunicateGroupData(episodeIdx, iterationIdx);
this->updateAndCommunicateGroupData(episodeIdx, iterationIdx);
// network related
bool more_network_update = false;
if (shouldBalanceNetwork(episodeIdx, iterationIdx) || mandatory_network_balance) {
const auto local_network_imbalance = updateNetworkPressures(episodeIdx);
if (this->shouldBalanceNetwork(episodeIdx, iterationIdx) || mandatory_network_balance) {
const auto local_network_imbalance = this->updateNetworkPressures(episodeIdx);
const double network_imbalance = comm.max(local_network_imbalance);
const auto& balance = schedule()[episodeIdx].network_balance();
const auto& balance = this->schedule()[episodeIdx].network_balance();
constexpr double relaxtion_factor = 10.0;
const double tolerance = relax_network_tolerance ? relaxtion_factor * balance.pressure_tolerance() : balance.pressure_tolerance();
more_network_update = this->networkActive() && network_imbalance > tolerance;
@ -1904,11 +1906,11 @@ namespace Opm {
bool changed_well_group = false;
// Check group individual constraints.
const int nupcol = schedule()[episodeIdx].nupcol();
const int nupcol = this->schedule()[episodeIdx].nupcol();
// don't switch group control when iterationIdx > nupcol
// to avoid oscilations between group controls
if (iterationIdx <= nupcol) {
const Group& fieldGroup = schedule().getGroup("FIELD", episodeIdx);
const Group& fieldGroup = this->schedule().getGroup("FIELD", episodeIdx);
changed_well_group = updateGroupControls(fieldGroup, deferred_logger, episodeIdx, iterationIdx);
}
// Check wells' group constraints and communicate.
@ -1958,8 +1960,8 @@ namespace Opm {
}
// update wsolvent fraction for REIN wells
const Group& fieldGroup = schedule().getGroup("FIELD", episodeIdx);
updateWsolvent(fieldGroup, episodeIdx, this->nupcolWellState());
const Group& fieldGroup = this->schedule().getGroup("FIELD", episodeIdx);
this->updateWsolvent(fieldGroup, episodeIdx, this->nupcolWellState());
return { changed_well_group, more_network_update };
}
@ -1969,7 +1971,7 @@ namespace Opm {
BlackoilWellModel<TypeTag>::
updateWellControlsDomain(DeferredLogger& deferred_logger, const Domain& domain)
{
if ( !wellsActive() ) return ;
if ( !this->wellsActive() ) return ;
// TODO: decide on and implement an approach to handling of
// group controls, network and similar for domain solves.
@ -2140,18 +2142,19 @@ namespace Opm {
const int iterationIdx,
DeferredLogger& deferred_logger)
{
updateAndCommunicateGroupData(reportStepIdx, iterationIdx);
this->updateAndCommunicateGroupData(reportStepIdx, iterationIdx);
// updateWellStateWithTarget might throw for multisegment wells hence we
// have a parallel try catch here to thrown on all processes.
OPM_BEGIN_PARALLEL_TRY_CATCH()
// if a well or group change control it affects all wells that are under the same group
for (const auto& well : well_container_) {
well->updateWellStateWithTarget(simulator_, this->groupState(), this->wellState(), deferred_logger);
well->updateWellStateWithTarget(simulator_, this->groupState(),
this->wellState(), deferred_logger);
}
OPM_END_PARALLEL_TRY_CATCH("BlackoilWellModel::updateAndCommunicate failed: ",
simulator_.gridView().comm())
updateAndCommunicateGroupData(reportStepIdx, iterationIdx);
this->updateAndCommunicateGroupData(reportStepIdx, iterationIdx);
}
template<typename TypeTag>
@ -2163,14 +2166,14 @@ namespace Opm {
const int iterationIdx)
{
bool changed = false;
bool changed_hc = checkGroupHigherConstraints( group, deferred_logger, reportStepIdx);
bool changed_hc = this->checkGroupHigherConstraints( group, deferred_logger, reportStepIdx);
if (changed_hc) {
changed = true;
updateAndCommunicate(reportStepIdx, iterationIdx, deferred_logger);
}
bool changed_individual =
BlackoilWellModelConstraints<double>(*this).
BlackoilWellModelConstraints(*this).
updateGroupIndividualControl(group,
reportStepIdx,
this->switched_inj_groups_,
@ -2186,7 +2189,7 @@ namespace Opm {
}
// call recursively down the group hierarchy
for (const std::string& groupName : group.groups()) {
bool changed_this = updateGroupControls( schedule().getGroup(groupName, reportStepIdx), deferred_logger, reportStepIdx,iterationIdx);
bool changed_this = updateGroupControls( this->schedule().getGroup(groupName, reportStepIdx), deferred_logger, reportStepIdx,iterationIdx);
changed = changed || changed_this;
}
return changed;
@ -2212,28 +2215,23 @@ namespace Opm {
const Opm::Parallel::Communication comm = grid().comm();
DeferredLogger global_deferredLogger = gatherDeferredLogger(local_deferredLogger, comm);
for (const auto& [group_name, to] : closed_offending_wells_) {
for (const auto& [group_name, to] : this->closed_offending_wells_) {
if (!this->wasDynamicallyShutThisTimeStep(to.second)) {
wellTestState.close_well(
to.second, WellTestConfig::Reason::GROUP, simulationTime);
wellTestState.close_well(to.second, WellTestConfig::Reason::GROUP, simulationTime);
this->updateClosedWellsThisStep(to.second);
std::string msg = fmt::format("Procedure on exceeding {} limit is WELL for group {}. Well {} is {}.",
to.first,
group_name,
to.second,
"shut");
const std::string msg =
fmt::format("Procedure on exceeding {} limit is WELL for group {}. Well {} is {}.",
to.first,
group_name,
to.second,
"shut");
global_deferredLogger.info(msg);
}
}
if (terminal_output_) {
if (this->terminal_output_) {
global_deferredLogger.logMessages();
}
}
@ -2245,7 +2243,7 @@ namespace Opm {
ExceptionType::ExcEnum& exc_type,
DeferredLogger& deferred_logger)
{
const int np = numPhases();
const int np = this->numPhases();
std::vector<double> potentials;
const auto& well = well_container_[widx];
std::string cur_exc_msg;
@ -2445,9 +2443,9 @@ namespace Opm {
const auto& eclProblem = simulator_.problem();
const unsigned numCells = grid.size(/*codim=*/0);
pvt_region_idx_.resize(numCells);
this->pvt_region_idx_.resize(numCells);
for (unsigned cellIdx = 0; cellIdx < numCells; ++cellIdx) {
pvt_region_idx_[cellIdx] =
this->pvt_region_idx_[cellIdx] =
eclProblem.pvtRegionIndex(cellIdx);
}
}
@ -2463,7 +2461,7 @@ namespace Opm {
// in the well equations. As a result, for an oil-water-polymer system, this function will return 2.
// In some way, it makes this function appear to be confusing from its name, and we need
// to revisit/revise this function again when extending the variants of system that flow can simulate.
int numComp = numPhases() < 3? numPhases(): FluidSystem::numComponents;
int numComp = this->numPhases() < 3 ? this->numPhases() : FluidSystem::numComponents;
if constexpr (has_solvent_) {
numComp++;
}
@ -2555,28 +2553,28 @@ namespace Opm {
if (!has_energy_)
return;
int np = numPhases();
int np = this->numPhases();
double cellInternalEnergy;
double cellBinv;
double cellDensity;
double perfPhaseRate;
const int nw = numLocalWells();
const int nw = this->numLocalWells();
for (auto wellID = 0*nw; wellID < nw; ++wellID) {
const Well& well = wells_ecl_[wellID];
const Well& well = this->wells_ecl_[wellID];
if (well.isInjector())
continue;
std::array<double,2> weighted{0.0,0.0};
auto& [weighted_temperature, total_weight] = weighted;
auto& well_info = local_parallel_well_info_[wellID].get();
auto& well_info = this->local_parallel_well_info_[wellID].get();
auto& ws = this->wellState().well(wellID);
auto& perf_data = ws.perf_data;
auto& perf_phase_rate = perf_data.phase_rates;
using int_type = decltype(well_perf_data_[wellID].size());
for (int_type perf = 0, end_perf = well_perf_data_[wellID].size(); perf < end_perf; ++perf) {
const int cell_idx = well_perf_data_[wellID][perf].cell_index;
using int_type = decltype(this->well_perf_data_[wellID].size());
for (int_type perf = 0, end_perf = this->well_perf_data_[wellID].size(); perf < end_perf; ++perf) {
const int cell_idx = this->well_perf_data_[wellID][perf].cell_index;
const auto& intQuants = simulator_.model().intensiveQuantities(cell_idx, /*timeIdx=*/0);
const auto& fs = intQuants.fluidState();
@ -2708,7 +2706,7 @@ namespace Opm {
local_log.debug(os.str());
}
auto global_log = gatherDeferredLogger(local_log, comm);
if (terminal_output_) {
if (this->terminal_output_) {
global_log.logMessages();
}
}

View File

@ -54,7 +54,7 @@ std::string simTimeToString(const std::time_t start_time, const double sim_time)
template<class Scalar>
GroupEconomicLimitsChecker<Scalar>::
GroupEconomicLimitsChecker(const BlackoilWellModelGeneric& well_model,
GroupEconomicLimitsChecker(const BlackoilWellModelGeneric<Scalar>& well_model,
WellTestState& well_test_state,
const Group& group,
const double simulation_time,

View File

@ -31,7 +31,7 @@
namespace Opm
{
class BlackoilWellModelGeneric;
template<class Scalar> class BlackoilWellModelGeneric;
class DeferredLogger;
class Group;
template<class Scalar> class WellState;
@ -41,7 +41,7 @@ template<class Scalar>
class GroupEconomicLimitsChecker
{
public:
GroupEconomicLimitsChecker(const BlackoilWellModelGeneric& well_model,
GroupEconomicLimitsChecker(const BlackoilWellModelGeneric<Scalar>& well_model,
WellTestState& well_test_state,
const Group& group,
const double simulation_time,
@ -73,7 +73,7 @@ private:
bool closeWellsRecursive(const Group& group, int level = 0);
void throwNotImplementedError(const std::string& error) const;
const BlackoilWellModelGeneric& well_model_;
const BlackoilWellModelGeneric<Scalar>& well_model_;
const Group& group_;
const double simulation_time_;
const int report_step_idx_;

View File

@ -259,7 +259,7 @@ BOOST_AUTO_TEST_CASE(EclGenericProblem)
namespace Opm {
class BlackoilWellModelGenericTest : public BlackoilWellModelGeneric
class BlackoilWellModelGenericTest : public BlackoilWellModelGeneric<double>
{
public:
BlackoilWellModelGenericTest(Schedule& schedule,
@ -268,8 +268,8 @@ public:
const PhaseUsage& phase_usage,
const Parallel::Communication& comm,
bool deserialize)
: BlackoilWellModelGeneric(schedule, summaryState,
eclState, phase_usage, comm)
: BlackoilWellModelGeneric<double>(schedule, summaryState,
eclState, phase_usage, comm)
{
if (deserialize) {
active_wgstate_.well_state = WellState<double>(dummy);