Move getAutoChokeGroupProductionTargetRate() from
WellGroupControls (static method) to GroupStateHelper
(member method). The method has no well dependency and
manually reimplements chain iteration already available
as applyReductionsAndFractions_().
The moved implementation delegates to
applyReductionsAndFractions_() with do_addback=false
and the actual getLocalReductionLevel_() value, replacing
the manual reduction loop.
Make getLocalReductionLevel_() private again (reverting
the visibility change from the previous commit), since
its only external caller was the now-removed static
method in WellGroupControls.
Remove unused FractionCalculator.hpp include from
WellGroupControls.cpp and WellGroupControls.hpp include
from BlackoilWellModelNetwork_impl.hpp and the test file.
Add local_reduction_level gating to the autochoke target
loop in getAutoChokeGroupProductionTargetRate(), preventing
double-counting of reductions at intermediate groups with
group-controlled-wells count of zero.
Remove getGuideRate() from GroupStateHelper: the group path
is dead code (only caller was isAutoChokeGroupUnderperforming_
which now uses guide_rate_ directly), and the well path is
inlined into FractionCalculator::guideRate().
Improve isAutoChokeGroupUnderperforming_() to compute the
control group guide rate as the sum of its FLD children's
guide rates (matching how targets are distributed), and
accumulate efficiency factors from the autochoke group up
to the control group. This makes the formula correct for
the common case where the control group is the immediate
parent with no reductions.
Rename getLocalReductionLevel_ to getLocalReductionLevel
and make it public, as it is now called from
WellGroupControls.cpp.
Update test to verify the corrected target rate and remove
references to the now-fixed double-counting issue.
Add two test cases for getAutoChokeGroupProductionTargetRate():
- TestAutoChokeGroupProductionTargetRate: normal case with
MANI (autochoke, FLD) under intermediate group PLAT that
has a guide rate. Verifies the autochoke reduction loop
produces the same result as applyReductionsAndFractions_()
when both are applicable.
- TestAutoChokeGroupTargetRateDoubleCountingBug: uses a
NETWORK DATA file with NODEPROP (as_choke=YES) and lower
well rates to naturally trigger underperformance detection
(GCW=0). Documents the double-counting bug where missing
local_reduction_level gating causes reductions to be
subtracted at both FIELD and PLAT, producing a clamped-
to-zero target instead of the correct value.
Also adds GROUP_HIGHER_CONSTRAINTS_NETWORK.DATA with
BRANPROP/NODEPROP keywords and parameterizes the test
fixture with mani2_control, data_file, and well rates.
The GCONSUMP efficiency factor calculation was incorrectly applying group
efficiency factors to the groups themselves, rather than following the
the pattern used elsewhere in the code base:
- Groups are NOT affected by their own efficiency factors
- Parent groups apply child efficiency factors when accumulating contributions
Changes:
- Fix GroupState::update_gconsump() to implement correct efficiency pattern
- Add test suite with simple and complex hierarchy scenarios
This commit extends the test_group_higher_constraints test suite with:
1. Extended hierarchy: Added MANI-2 group (with WELL-B) under PLAT to
create realistic group competition scenarios where fractions < 1.0.
The new hierarchy is:
FIELD -> PLAT -> MANI -> WELL-A, WELL-A2
-> MANI-2 -> WELL-B
-> PLAT-2 -> WELL-C
2. New tests for getWellGroupTargetProducer():
- TestWellGroupTargetProducerIndividualControl: WELL-A under ORAT
- TestWellGroupTargetProducerGrupControl: WELL-A under GRUP
- TestWellGroupTargetProducerWithSiblingIndividualControl: WELL-A
under GRUP with sibling WELL-A2 under ORAT (demonstrates case
where reduction != addback)
3. Updated existing tests:
- TestGroupHigherConstraintsWithGuideRate: scale now 0.922 (was 1.39)
- TestGroupHigherConstraintsProdWithoutGuideRate: scale now 0.901
The addback calculation at local_reduction_level was using the
accumulated efficiency factor (from entity to control group) instead
of the partial efficiency factor (from entity to local_reduction_level).
This caused incorrect constraint violations when checking higher-level
group constraints. The fix computes the partial efficiency by multiplying
efficiency factors from local_reduction_level down to the entity.
This test exposes a bug in GroupStateHelper::checkGroupConstraintsProd()
where the addback calculation uses the accumulated efficiency factor
instead of the partial efficiency factor at local_reduction_level.
Test setup:
- Group hierarchy: FIELD -> PLAT (E=0.9) -> MANI (E=0.8) / MANI2 (E=0.7)
- MANI has individual ORAT control, PLAT has guide rate
- WELL-A produces 10000 SM3/day under MANI
The bug causes:
- Addback uses 0.72 (E_MANI * E_PLAT) instead of 0.8 (E_MANI)
- This results in scale = 0.9465 (false constraint violation)
- Correct calculation would give scale = 1.0288 (no violation)
The test currently passes with the buggy expected values. A subsequent
commit will fix the bug and update the test expectations.