2022-10-24 02:36:05 -05:00
/*
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/BlackoilWellModelConstraints.hpp>
2022-08-29 07:25:43 -05:00
# include <opm/common/ErrorMacros.hpp>
2022-10-24 02:36:05 -05:00
# include <opm/input/eclipse/Schedule/Schedule.hpp>
2022-10-24 02:36:05 -05:00
# include <opm/simulators/wells/BlackoilWellModelGeneric.hpp>
2022-10-24 02:36:05 -05:00
# include <opm/simulators/wells/WellGroupHelpers.hpp>
2022-10-24 02:36:05 -05:00
# include <opm/simulators/wells/WellInterfaceGeneric.hpp>
2022-10-31 04:46:50 -05:00
# include <fmt/format.h>
2022-10-24 02:36:05 -05:00
# include <stdexcept>
2022-10-24 02:36:05 -05:00
namespace Opm {
2024-02-17 11:13:46 -06:00
template < class Scalar >
bool BlackoilWellModelConstraints < Scalar > : :
2022-10-24 02:36:05 -05:00
hasTHPConstraints ( ) const
{
int local_result = false ;
for ( const auto & well : wellModel_ . genericWells ( ) ) {
if ( well - > wellHasTHPConstraints ( wellModel_ . summaryState ( ) ) ) {
local_result = true ;
}
}
return wellModel_ . comm ( ) . max ( local_result ) ;
}
2024-02-17 11:13:46 -06:00
template < class Scalar >
std : : pair < Group : : InjectionCMode , Scalar >
BlackoilWellModelConstraints < Scalar > : :
2022-10-24 02:36:05 -05:00
checkGroupInjectionConstraints ( const Group & group ,
const int reportStepIdx ,
const Phase & phase ) const
{
const auto & well_state = wellModel_ . wellState ( ) ;
const auto & pu = wellModel_ . phaseUsage ( ) ;
int phasePos ;
if ( phase = = Phase : : GAS & & pu . phase_used [ BlackoilPhases : : Vapour ] )
phasePos = pu . phase_pos [ BlackoilPhases : : Vapour ] ;
else if ( phase = = Phase : : OIL & & pu . phase_used [ BlackoilPhases : : Liquid ] )
phasePos = pu . phase_pos [ BlackoilPhases : : Liquid ] ;
else if ( phase = = Phase : : WATER & & pu . phase_used [ BlackoilPhases : : Aqua ] )
phasePos = pu . phase_pos [ BlackoilPhases : : Aqua ] ;
else
OPM_THROW ( std : : runtime_error , " Unknown phase " ) ;
auto currentControl = wellModel_ . groupState ( ) . injection_control ( group . name ( ) , phase ) ;
if ( group . has_control ( phase , Group : : InjectionCMode : : RATE ) )
{
if ( currentControl ! = Group : : InjectionCMode : : RATE )
{
2024-02-17 11:13:46 -06:00
Scalar current_rate = 0.0 ;
current_rate + = WellGroupHelpers < Scalar > : : sumWellSurfaceRates ( group ,
2024-02-19 06:47:25 -06:00
wellModel_ . schedule ( ) ,
well_state ,
reportStepIdx ,
phasePos ,
/*isInjector*/ true ) ;
2022-10-24 02:36:05 -05:00
// sum over all nodes
current_rate = wellModel_ . comm ( ) . sum ( current_rate ) ;
const auto & controls = group . injectionControls ( phase , wellModel_ . summaryState ( ) ) ;
2024-02-17 11:13:46 -06:00
Scalar target = controls . surface_max_rate ;
2022-10-24 02:36:05 -05:00
if ( group . has_gpmaint_control ( phase , Group : : InjectionCMode : : RATE ) )
target = wellModel_ . groupState ( ) . gpmaint_target ( group . name ( ) ) ;
if ( target < current_rate ) {
2024-02-17 11:13:46 -06:00
Scalar scale = 1.0 ;
2022-10-24 02:36:05 -05:00
if ( current_rate > 1e-12 )
scale = target / current_rate ;
return std : : make_pair ( Group : : InjectionCMode : : RATE , scale ) ;
}
}
}
if ( group . has_control ( phase , Group : : InjectionCMode : : RESV ) )
{
if ( currentControl ! = Group : : InjectionCMode : : RESV )
{
2024-02-17 11:13:46 -06:00
Scalar current_rate = 0.0 ;
current_rate + = WellGroupHelpers < Scalar > : : sumWellResRates ( group ,
2024-02-19 06:47:25 -06:00
wellModel_ . schedule ( ) ,
well_state ,
reportStepIdx ,
phasePos ,
/*isInjector*/ true ) ;
2022-10-24 02:36:05 -05:00
// sum over all nodes
current_rate = wellModel_ . comm ( ) . sum ( current_rate ) ;
const auto & controls = group . injectionControls ( phase , wellModel_ . summaryState ( ) ) ;
2024-02-17 11:13:46 -06:00
Scalar target = controls . resv_max_rate ;
2022-10-24 02:36:05 -05:00
if ( group . has_gpmaint_control ( phase , Group : : InjectionCMode : : RESV ) )
target = wellModel_ . groupState ( ) . gpmaint_target ( group . name ( ) ) ;
if ( target < current_rate ) {
2024-02-17 11:13:46 -06:00
Scalar scale = 1.0 ;
2022-10-24 02:36:05 -05:00
if ( current_rate > 1e-12 )
scale = target / current_rate ;
return std : : make_pair ( Group : : InjectionCMode : : RESV , scale ) ;
}
}
}
if ( group . has_control ( phase , Group : : InjectionCMode : : REIN ) )
{
if ( currentControl ! = Group : : InjectionCMode : : REIN )
{
2024-02-17 11:13:46 -06:00
Scalar production_Rate = 0.0 ;
2022-10-24 02:36:05 -05:00
const auto & controls = group . injectionControls ( phase , wellModel_ . summaryState ( ) ) ;
const Group & groupRein = wellModel_ . schedule ( ) . getGroup ( controls . reinj_group , reportStepIdx ) ;
2024-02-17 11:13:46 -06:00
production_Rate + = WellGroupHelpers < Scalar > : : sumWellSurfaceRates ( groupRein ,
2024-02-19 06:47:25 -06:00
wellModel_ . schedule ( ) ,
well_state ,
reportStepIdx ,
phasePos ,
/*isInjector*/ false ) ;
2022-10-24 02:36:05 -05:00
// sum over all nodes
production_Rate = wellModel_ . comm ( ) . sum ( production_Rate ) ;
2024-02-17 11:13:46 -06:00
Scalar current_rate = 0.0 ;
current_rate + = WellGroupHelpers < Scalar > : : sumWellSurfaceRates ( group ,
2024-02-19 06:47:25 -06:00
wellModel_ . schedule ( ) ,
well_state ,
reportStepIdx ,
phasePos ,
/*isInjector*/ true ) ;
2022-10-24 02:36:05 -05:00
// sum over all nodes
current_rate = wellModel_ . comm ( ) . sum ( current_rate ) ;
if ( controls . target_reinj_fraction * production_Rate < current_rate ) {
2024-02-17 11:13:46 -06:00
Scalar scale = 1.0 ;
2022-10-24 02:36:05 -05:00
if ( current_rate > 1e-12 )
scale = controls . target_reinj_fraction * production_Rate / current_rate ;
return std : : make_pair ( Group : : InjectionCMode : : REIN , scale ) ;
}
}
}
if ( group . has_control ( phase , Group : : InjectionCMode : : VREP ) )
{
if ( currentControl ! = Group : : InjectionCMode : : VREP )
{
2024-02-17 11:13:46 -06:00
Scalar voidage_rate = 0.0 ;
2022-10-24 02:36:05 -05:00
const auto & controls = group . injectionControls ( phase , wellModel_ . summaryState ( ) ) ;
const Group & groupVoidage = wellModel_ . schedule ( ) . getGroup ( controls . voidage_group , reportStepIdx ) ;
2024-02-17 11:13:46 -06:00
voidage_rate + = WellGroupHelpers < Scalar > : : sumWellResRates ( groupVoidage ,
2024-02-19 06:47:25 -06:00
wellModel_ . schedule ( ) ,
well_state ,
reportStepIdx ,
pu . phase_pos [ BlackoilPhases : : Aqua ] ,
false ) ;
2024-02-17 11:13:46 -06:00
voidage_rate + = WellGroupHelpers < Scalar > : : sumWellResRates ( groupVoidage ,
2024-02-19 06:47:25 -06:00
wellModel_ . schedule ( ) ,
well_state ,
reportStepIdx ,
pu . phase_pos [ BlackoilPhases : : Liquid ] ,
false ) ;
2024-02-17 11:13:46 -06:00
voidage_rate + = WellGroupHelpers < Scalar > : : sumWellResRates ( groupVoidage ,
2024-02-19 06:47:25 -06:00
wellModel_ . schedule ( ) ,
well_state , reportStepIdx ,
pu . phase_pos [ BlackoilPhases : : Vapour ] ,
false ) ;
2022-10-24 02:36:05 -05:00
// sum over all nodes
voidage_rate = wellModel_ . comm ( ) . sum ( voidage_rate ) ;
2024-02-17 11:13:46 -06:00
Scalar total_rate = 0.0 ;
total_rate + = WellGroupHelpers < Scalar > : : sumWellResRates ( group ,
2024-02-19 06:47:25 -06:00
wellModel_ . schedule ( ) ,
well_state ,
reportStepIdx ,
pu . phase_pos [ BlackoilPhases : : Aqua ] ,
true ) ;
2024-02-17 11:13:46 -06:00
total_rate + = WellGroupHelpers < Scalar > : : sumWellResRates ( group ,
2024-02-19 06:47:25 -06:00
wellModel_ . schedule ( ) ,
well_state ,
reportStepIdx ,
pu . phase_pos [ BlackoilPhases : : Liquid ] ,
true ) ;
2024-02-17 11:13:46 -06:00
total_rate + = WellGroupHelpers < Scalar > : : sumWellResRates ( group ,
2024-02-19 06:47:25 -06:00
wellModel_ . schedule ( ) ,
well_state ,
reportStepIdx ,
pu . phase_pos [ BlackoilPhases : : Vapour ] ,
true ) ;
2022-10-24 02:36:05 -05:00
// sum over all nodes
total_rate = wellModel_ . comm ( ) . sum ( total_rate ) ;
if ( controls . target_void_fraction * voidage_rate < total_rate ) {
2024-02-17 11:13:46 -06:00
Scalar scale = 1.0 ;
2022-10-24 02:36:05 -05:00
if ( total_rate > 1e-12 )
scale = controls . target_void_fraction * voidage_rate / total_rate ;
return std : : make_pair ( Group : : InjectionCMode : : VREP , scale ) ;
}
}
}
return std : : make_pair ( Group : : InjectionCMode : : NONE , 1.0 ) ;
}
2024-02-17 11:13:46 -06:00
template < class Scalar >
std : : pair < Group : : ProductionCMode , Scalar >
BlackoilWellModelConstraints < Scalar > : :
2022-10-24 02:36:05 -05:00
checkGroupProductionConstraints ( const Group & group ,
const int reportStepIdx ,
DeferredLogger & deferred_logger ) const
{
const auto & well_state = wellModel_ . wellState ( ) ;
const auto & pu = wellModel_ . phaseUsage ( ) ;
const auto controls = group . productionControls ( wellModel_ . summaryState ( ) ) ;
const Group : : ProductionCMode & currentControl = wellModel_ . groupState ( ) . production_control ( group . name ( ) ) ;
if ( group . has_control ( Group : : ProductionCMode : : ORAT ) )
{
if ( currentControl ! = Group : : ProductionCMode : : ORAT )
{
2024-02-17 11:13:46 -06:00
Scalar current_rate = 0.0 ;
current_rate + = WellGroupHelpers < Scalar > : : sumWellSurfaceRates ( group ,
2024-02-19 06:47:25 -06:00
wellModel_ . schedule ( ) ,
well_state ,
reportStepIdx ,
pu . phase_pos [ BlackoilPhases : : Liquid ] ,
false ) ;
2022-10-24 02:36:05 -05:00
// sum over all nodes
current_rate = wellModel_ . comm ( ) . sum ( current_rate ) ;
if ( controls . oil_target < current_rate ) {
2024-02-17 11:13:46 -06:00
Scalar scale = 1.0 ;
2022-10-24 02:36:05 -05:00
if ( current_rate > 1e-12 )
scale = controls . oil_target / current_rate ;
return std : : make_pair ( Group : : ProductionCMode : : ORAT , scale ) ;
}
}
}
if ( group . has_control ( Group : : ProductionCMode : : WRAT ) )
{
if ( currentControl ! = Group : : ProductionCMode : : WRAT )
{
2024-02-17 11:13:46 -06:00
Scalar current_rate = 0.0 ;
current_rate + = WellGroupHelpers < Scalar > : : sumWellSurfaceRates ( group ,
2024-02-19 06:47:25 -06:00
wellModel_ . schedule ( ) ,
well_state ,
reportStepIdx ,
pu . phase_pos [ BlackoilPhases : : Aqua ] ,
false ) ;
2022-10-24 02:36:05 -05:00
// sum over all nodes
current_rate = wellModel_ . comm ( ) . sum ( current_rate ) ;
if ( controls . water_target < current_rate ) {
2024-02-17 11:13:46 -06:00
Scalar scale = 1.0 ;
2022-10-24 02:36:05 -05:00
if ( current_rate > 1e-12 )
scale = controls . water_target / current_rate ;
return std : : make_pair ( Group : : ProductionCMode : : WRAT , scale ) ;
}
}
}
if ( group . has_control ( Group : : ProductionCMode : : GRAT ) )
{
if ( currentControl ! = Group : : ProductionCMode : : GRAT )
{
2024-02-17 11:13:46 -06:00
Scalar current_rate = 0.0 ;
current_rate + = WellGroupHelpers < Scalar > : : sumWellSurfaceRates ( group ,
2024-02-19 06:47:25 -06:00
wellModel_ . schedule ( ) ,
well_state ,
reportStepIdx ,
pu . phase_pos [ BlackoilPhases : : Vapour ] ,
false ) ;
2022-10-24 02:36:05 -05:00
// sum over all nodes
current_rate = wellModel_ . comm ( ) . sum ( current_rate ) ;
if ( controls . gas_target < current_rate ) {
2024-02-17 11:13:46 -06:00
Scalar scale = 1.0 ;
2022-10-24 02:36:05 -05:00
if ( current_rate > 1e-12 )
scale = controls . gas_target / current_rate ;
return std : : make_pair ( Group : : ProductionCMode : : GRAT , scale ) ;
}
}
}
if ( group . has_control ( Group : : ProductionCMode : : LRAT ) )
{
if ( currentControl ! = Group : : ProductionCMode : : LRAT )
{
2024-02-17 11:13:46 -06:00
Scalar current_rate = 0.0 ;
current_rate + = WellGroupHelpers < Scalar > : : sumWellSurfaceRates ( group ,
2024-02-19 06:47:25 -06:00
wellModel_ . schedule ( ) ,
well_state ,
reportStepIdx ,
pu . phase_pos [ BlackoilPhases : : Liquid ] ,
false ) ;
2024-02-17 11:13:46 -06:00
current_rate + = WellGroupHelpers < Scalar > : : sumWellSurfaceRates ( group ,
2024-02-19 06:47:25 -06:00
wellModel_ . schedule ( ) ,
well_state ,
reportStepIdx ,
pu . phase_pos [ BlackoilPhases : : Aqua ] ,
false ) ;
2022-10-24 02:36:05 -05:00
// sum over all nodes
current_rate = wellModel_ . comm ( ) . sum ( current_rate ) ;
bool skip = false ;
if ( controls . liquid_target = = controls . oil_target ) {
2024-02-17 11:13:46 -06:00
Scalar current_water_rate = WellGroupHelpers < Scalar > : : sumWellSurfaceRates ( group ,
2024-02-19 06:47:25 -06:00
wellModel_ . schedule ( ) ,
well_state ,
reportStepIdx ,
pu . phase_pos [ BlackoilPhases : : Aqua ] ,
false ) ;
2022-10-24 02:36:05 -05:00
current_water_rate = wellModel_ . comm ( ) . sum ( current_water_rate ) ;
if ( std : : abs ( current_water_rate ) < 1e-12 ) {
skip = true ;
deferred_logger . debug ( " LRAT_ORAT_GROUP " , " GROUP " + group . name ( ) + " The LRAT target is equal the ORAT target and the water rate is zero, skip checking LRAT " ) ;
}
}
if ( ! skip & & controls . liquid_target < current_rate ) {
2024-02-17 11:13:46 -06:00
Scalar scale = 1.0 ;
2022-10-24 02:36:05 -05:00
if ( current_rate > 1e-12 )
scale = controls . liquid_target / current_rate ;
return std : : make_pair ( Group : : ProductionCMode : : LRAT , scale ) ;
}
}
}
if ( group . has_control ( Group : : ProductionCMode : : CRAT ) )
{
OPM_DEFLOG_THROW ( std : : runtime_error , " Group " + group . name ( ) + " CRAT control for production groups not implemented " , deferred_logger ) ;
}
if ( group . has_control ( Group : : ProductionCMode : : RESV ) )
{
if ( currentControl ! = Group : : ProductionCMode : : RESV )
{
2024-02-17 11:13:46 -06:00
Scalar current_rate = 0.0 ;
current_rate + = WellGroupHelpers < Scalar > : : sumWellResRates ( group ,
2024-02-19 06:47:25 -06:00
wellModel_ . schedule ( ) ,
well_state ,
reportStepIdx ,
pu . phase_pos [ BlackoilPhases : : Aqua ] ,
false ) ;
2024-02-17 11:13:46 -06:00
current_rate + = WellGroupHelpers < Scalar > : : sumWellResRates ( group ,
2024-02-19 06:47:25 -06:00
wellModel_ . schedule ( ) ,
well_state ,
reportStepIdx ,
pu . phase_pos [ BlackoilPhases : : Liquid ] ,
false ) ;
2024-02-17 11:13:46 -06:00
current_rate + = WellGroupHelpers < Scalar > : : sumWellResRates ( group ,
2024-02-19 06:47:25 -06:00
wellModel_ . schedule ( ) ,
well_state ,
reportStepIdx ,
pu . phase_pos [ BlackoilPhases : : Vapour ] ,
false ) ;
2022-10-24 02:36:05 -05:00
// sum over all nodes
current_rate = wellModel_ . comm ( ) . sum ( current_rate ) ;
2024-02-17 11:13:46 -06:00
Scalar target = controls . resv_target ;
2022-10-24 02:36:05 -05:00
if ( group . has_gpmaint_control ( Group : : ProductionCMode : : RESV ) )
target = wellModel_ . groupState ( ) . gpmaint_target ( group . name ( ) ) ;
if ( target < current_rate ) {
2024-02-17 11:13:46 -06:00
Scalar scale = 1.0 ;
2022-10-24 02:36:05 -05:00
if ( current_rate > 1e-12 )
scale = target / current_rate ;
return std : : make_pair ( Group : : ProductionCMode : : RESV , scale ) ;
}
}
}
if ( group . has_control ( Group : : ProductionCMode : : PRBL ) )
{
OPM_DEFLOG_THROW ( std : : runtime_error , " Group " + group . name ( ) + " PRBL control for production groups not implemented " , deferred_logger ) ;
}
2024-02-17 11:13:46 -06:00
return std : : make_pair ( Group : : ProductionCMode : : NONE , Scalar ( 1.0 ) ) ;
2022-10-24 02:36:05 -05:00
}
2024-02-17 11:13:46 -06:00
template < class Scalar >
bool BlackoilWellModelConstraints < Scalar > : :
2022-10-24 02:36:05 -05:00
checkGroupConstraints ( const Group & group ,
const int reportStepIdx ,
DeferredLogger & deferred_logger ) const
{
if ( group . isInjectionGroup ( ) ) {
const Phase all [ ] = { Phase : : WATER , Phase : : OIL , Phase : : GAS } ;
for ( Phase phase : all ) {
if ( ! group . hasInjectionControl ( phase ) ) {
continue ;
}
const auto & check = this - > checkGroupInjectionConstraints ( group ,
reportStepIdx , phase ) ;
if ( check . first ! = Group : : InjectionCMode : : NONE ) {
return true ;
}
}
}
if ( group . isProductionGroup ( ) ) {
const auto & check = this - > checkGroupProductionConstraints ( group ,
reportStepIdx ,
deferred_logger ) ;
if ( check . first ! = Group : : ProductionCMode : : NONE )
{
return true ;
}
}
// call recursively down the group hierarchy
bool violated = false ;
for ( const std : : string & groupName : group . groups ( ) ) {
const auto & grp = wellModel_ . schedule ( ) . getGroup ( groupName , reportStepIdx ) ;
violated = violated | | this - > checkGroupConstraints ( grp , reportStepIdx , deferred_logger ) ;
}
return violated ;
}
2024-02-17 11:13:46 -06:00
template < class Scalar >
void BlackoilWellModelConstraints < Scalar > : :
2022-10-24 02:36:05 -05:00
actionOnBrokenConstraints ( const Group & group ,
const Group : : InjectionCMode & newControl ,
const Phase & controlPhase ,
2024-02-17 11:13:46 -06:00
GroupState < Scalar > & group_state ,
2022-10-24 02:36:05 -05:00
DeferredLogger & deferred_logger ) const
{
auto oldControl = wellModel_ . groupState ( ) . injection_control ( group . name ( ) , controlPhase ) ;
if ( oldControl ! = newControl ) {
const std : : string from = Group : : InjectionCMode2String ( oldControl ) ;
group_state . injection_control ( group . name ( ) , controlPhase , newControl ) ;
2022-10-31 04:46:50 -05:00
if ( wellModel_ . comm ( ) . rank ( ) = = 0 ) {
auto msg = fmt : : format ( " Switching injection control mode for group {} from {} to {} " ,
group . name ( ) ,
Group : : InjectionCMode2String ( oldControl ) ,
Group : : InjectionCMode2String ( newControl ) ) ;
2022-11-02 02:55:49 -05:00
deferred_logger . debug ( msg ) ;
2022-10-31 04:46:50 -05:00
}
2022-10-24 02:36:05 -05:00
}
}
2024-02-17 11:13:46 -06:00
template < class Scalar >
bool BlackoilWellModelConstraints < Scalar > : :
2022-10-24 02:36:05 -05:00
actionOnBrokenConstraints ( const Group & group ,
2024-02-07 08:11:59 -06:00
const int reportStepIdx ,
2023-07-14 04:20:03 -05:00
const Group : : GroupLimitAction group_limit_action ,
2022-10-24 02:36:05 -05:00
const Group : : ProductionCMode & newControl ,
2024-02-17 11:13:46 -06:00
const WellState < Scalar > & well_state ,
2024-02-07 08:11:59 -06:00
std : : optional < std : : string > & worst_offending_well ,
2024-02-17 11:13:46 -06:00
GroupState < Scalar > & group_state ,
2022-10-24 02:36:05 -05:00
DeferredLogger & deferred_logger ) const
{
2024-02-07 08:11:59 -06:00
bool changed = false ;
2024-04-17 03:34:39 -05:00
const Group : : ProductionCMode oldControl =
wellModel_ . groupState ( ) . production_control ( group . name ( ) ) ;
2022-10-24 02:36:05 -05:00
2022-10-31 04:46:50 -05:00
std : : string ss ;
2024-02-17 11:13:46 -06:00
switch ( group_limit_action . allRates ) {
2022-10-24 02:36:05 -05:00
case Group : : ExceedAction : : NONE : {
2024-06-19 03:47:43 -05:00
if ( oldControl ! = newControl ) {
2024-04-17 03:34:39 -05:00
if ( ( group_limit_action . water = = Group : : ExceedAction : : RATE & &
newControl = = Group : : ProductionCMode : : WRAT ) | |
( group_limit_action . gas = = Group : : ExceedAction : : RATE & &
newControl = = Group : : ProductionCMode : : GRAT ) | |
( group_limit_action . liquid = = Group : : ExceedAction : : RATE & &
newControl = = Group : : ProductionCMode : : LRAT ) ) {
2023-07-12 13:44:10 -05:00
group_state . production_control ( group . name ( ) , newControl ) ;
ss = fmt : : format ( " Switching production control mode for group {} from {} to {} " ,
group . name ( ) ,
Group : : ProductionCMode2String ( oldControl ) ,
Group : : ProductionCMode2String ( newControl ) ) ;
2024-02-07 08:11:59 -06:00
changed = true ;
2023-10-09 04:14:48 -05:00
}
2023-07-12 13:44:10 -05:00
else {
2024-04-17 03:34:39 -05:00
ss = fmt : : format ( " Procedure on exceeding {} limit is NONE for group {}. "
" Nothing is done. " ,
2023-07-13 06:15:54 -05:00
Group : : ProductionCMode2String ( oldControl ) ,
group . name ( ) ) ;
2023-07-12 13:44:10 -05:00
}
2022-10-24 02:36:05 -05:00
}
break ;
}
case Group : : ExceedAction : : CON : {
2024-04-17 03:35:57 -05:00
OPM_DEFLOG_THROW ( std : : runtime_error ,
fmt : : format ( " Group {} GroupProductionExceedLimit CON not implemented " ,
group . name ( ) ) ,
deferred_logger ) ;
2022-10-24 02:36:05 -05:00
break ;
}
case Group : : ExceedAction : : CON_PLUS : {
2024-04-17 03:35:57 -05:00
OPM_DEFLOG_THROW ( std : : runtime_error ,
fmt : : format ( " Group {} GroupProductionExceedLimit CON_PLUS not implemented " ,
group . name ( ) ) ,
deferred_logger ) ;
2022-10-24 02:36:05 -05:00
break ;
}
case Group : : ExceedAction : : WELL : {
2024-04-17 03:34:39 -05:00
std : : tie ( worst_offending_well , std : : ignore ) =
2024-02-17 11:13:46 -06:00
WellGroupHelpers < Scalar > : : worstOffendingWell ( group , wellModel_ . schedule ( ) , reportStepIdx ,
2024-02-19 06:47:25 -06:00
newControl , wellModel_ . phaseUsage ( ) ,
wellModel_ . comm ( ) , well_state , deferred_logger ) ;
2022-10-24 02:36:05 -05:00
break ;
}
case Group : : ExceedAction : : PLUG : {
2024-04-17 03:35:57 -05:00
OPM_DEFLOG_THROW ( std : : runtime_error ,
fmt : : format ( " Group {} GroupProductionExceedLimit PLUG not implemented " ,
group . name ( ) ) ,
deferred_logger ) ;
2022-10-24 02:36:05 -05:00
break ;
}
case Group : : ExceedAction : : RATE : {
if ( oldControl ! = newControl ) {
group_state . production_control ( group . name ( ) , newControl ) ;
2022-10-31 04:46:50 -05:00
ss = fmt : : format ( " Switching production control mode for group {} from {} to {} " ,
group . name ( ) ,
Group : : ProductionCMode2String ( oldControl ) ,
Group : : ProductionCMode2String ( newControl ) ) ;
2022-10-24 02:36:05 -05:00
}
2024-02-07 08:11:59 -06:00
changed = true ;
2022-10-24 02:36:05 -05:00
break ;
}
default :
2024-04-17 03:36:13 -05:00
OPM_THROW ( std : : runtime_error ,
" Invalid procedure for maximum rate limit selected for group " + group . name ( ) ) ;
2022-10-24 02:36:05 -05:00
}
2022-10-31 04:46:50 -05:00
if ( ! ss . empty ( ) & & wellModel_ . comm ( ) . rank ( ) = = 0 )
deferred_logger . debug ( ss ) ;
2024-02-07 08:11:59 -06:00
return changed ;
2022-10-24 02:36:05 -05:00
}
2024-02-17 11:13:46 -06:00
template < class Scalar >
bool BlackoilWellModelConstraints < Scalar > : :
2022-10-24 02:36:05 -05:00
updateGroupIndividualControl ( const Group & group ,
const int reportStepIdx ,
2024-02-17 11:13:46 -06:00
std : : map < std : : pair < std : : string , Phase > , std : : string > & switched_inj ,
2022-10-24 02:36:05 -05:00
std : : map < std : : string , std : : string > & switched_prod ,
2024-02-07 08:11:59 -06:00
std : : map < std : : string , std : : pair < std : : string , std : : string > > & closed_offending_wells ,
2024-02-17 11:13:46 -06:00
GroupState < Scalar > & group_state ,
WellState < Scalar > & well_state ,
2022-10-24 02:36:05 -05:00
DeferredLogger & deferred_logger ) const
{
bool changed = false ;
if ( group . isInjectionGroup ( ) )
{
const Phase all [ ] = { Phase : : WATER , Phase : : OIL , Phase : : GAS } ;
for ( Phase phase : all ) {
if ( ! group . hasInjectionControl ( phase ) ) {
continue ;
}
const auto & changed_this = this - > checkGroupInjectionConstraints ( group ,
reportStepIdx ,
phase ) ;
if ( changed_this . first ! = Group : : InjectionCMode : : NONE )
{
2022-11-02 02:55:49 -05:00
switched_inj . insert_or_assign ( { group . name ( ) , phase } ,
Group : : InjectionCMode2String ( changed_this . first ) ) ;
2022-10-24 02:36:05 -05:00
this - > actionOnBrokenConstraints ( group , changed_this . first , phase ,
group_state , deferred_logger ) ;
2024-02-17 11:13:46 -06:00
WellGroupHelpers < Scalar > : : updateWellRatesFromGroupTargetScale ( changed_this . second ,
2024-02-19 06:47:25 -06:00
group ,
wellModel_ . schedule ( ) ,
reportStepIdx ,
/* isInjector */ false ,
wellModel_ . groupState ( ) ,
well_state ) ;
2022-10-24 02:36:05 -05:00
changed = true ;
}
}
}
if ( group . isProductionGroup ( ) ) {
const auto & changed_this = this - > checkGroupProductionConstraints ( group ,
reportStepIdx ,
deferred_logger ) ;
const auto controls = group . productionControls ( wellModel_ . summaryState ( ) ) ;
2024-02-07 08:11:59 -06:00
2022-10-24 02:36:05 -05:00
if ( changed_this . first ! = Group : : ProductionCMode : : NONE )
{
2024-02-07 08:11:59 -06:00
std : : optional < std : : string > worst_offending_well = std : : nullopt ;
changed = this - > actionOnBrokenConstraints ( group , reportStepIdx ,
2023-07-14 04:20:03 -05:00
controls . group_limit_action ,
2024-02-07 08:11:59 -06:00
changed_this . first , well_state ,
worst_offending_well ,
2022-10-24 02:36:05 -05:00
group_state , deferred_logger ) ;
2024-02-07 08:11:59 -06:00
if ( changed ) {
switched_prod . insert_or_assign ( group . name ( ) ,
Group : : ProductionCMode2String ( changed_this . first ) ) ;
2024-02-17 11:13:46 -06:00
WellGroupHelpers < Scalar > : : updateWellRatesFromGroupTargetScale ( changed_this . second ,
2024-02-19 06:47:25 -06:00
group ,
wellModel_ . schedule ( ) ,
reportStepIdx ,
/* isInjector */ false ,
wellModel_ . groupState ( ) ,
well_state ) ;
2024-02-07 08:11:59 -06:00
} else if ( worst_offending_well ) {
closed_offending_wells . insert_or_assign ( group . name ( ) ,
std : : make_pair ( Group : : ProductionCMode2String ( changed_this . first ) , * worst_offending_well ) ) ;
}
2022-10-24 02:36:05 -05:00
}
}
return changed ;
}
2024-02-17 11:13:46 -06:00
template class BlackoilWellModelConstraints < double > ;
2022-10-24 02:36:05 -05:00
}