In multi-rank MPI runs, some log messages were written by all ranks instead
of only rank 0, causing "logging fallout" files (e.g., CASE.1.DBG, CASE.2.DBG).
Changes:
- Add rank check before calling logPressures() in FlowThresholdPressure
- Make TimeStepControl verbose flag rank-aware in createController()
This ensures only rank 0 produces log output for these code paths.
In history mode reservoir coupling, no GRUPSLAV keyword is defined because
rate allocation is not needed (wells use WCONHIST with imposed rates).
This caused assertion failures when the well model attempted to exchange
slave group data with numSlaveGroups == 0.
Changes:
- Skip receiving slave group production/injection data when numSlaveGroups == 0
- Skip sending slave group data when numSlaveGroups == 0
Eliminate complicated variant handling in initForInjector_() and
initForProducer_(). The code previously required knowledge of std::variant
internals to understand.
Changes:
- Add getInjectionGuideTargetMode() and getProductionGuideTargetMode()
to GroupStateHelper, delegating the Phase/CMode to GuideRateModel::Target
conversion
- Refactor initForInjector_() and initForProducer_() to construct
calculators directly instead of going through variant intermediaries
- Merge getTargetFromCalculator() and getTargetNoGuideRate() into
getGroupTargetNoGuideRate(), eliminating redundant method and
unused variant parameter
- Call GroupStateHelper directly for groupTarget() instead of extracting
from variant
The variant type is still used for calcModeRateFromRates() which requires
the polymorphic behavior.
History mode reservoir coupling only synchronizes time steps between
master and slaves. No rate allocation occurs, so GRUPSLAV (which maps
slave groups to master groups for rate constraints) is not needed.
Changes:
- Reorder master-slave initial communication so slaves receive master
group names before determining activation date
- Handle zero master groups case in getMasterGroupNamesForSlave_(),
sendMasterGroupNamesToSlaves_(), and receiveMasterGroupNamesFromMasterProcess_()
- Add numMasterGroups_() method to ReservoirCouplingSlave to detect
history mode (no GRUPMAST on master means no master groups)
- When no GRUPSLAV found and numMasterGroups is zero, assume slave
activation at simulation start (history mode)
History mode reservoir coupling only requires time synchronization, not
rate allocation. GRUPMAST is only needed for prediction mode where the
master allocates rates to slaves.
Master groups in reservoir coupling have no wells in the master
reservoir (they represent slave groups), so their GCW (Group Controlled
Wells) count was 0. This caused them to be incorrectly excluded from:
- Guide rate distribution (FractionCalculator)
- Local reduction level calculations
- Target constraint checking
Fix: Set GCW = 1 for RC master groups by convention. This is consistent
with how GCW is used throughout the code - only the condition GCW > 0
matters, not the actual count.
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
Extract duplicated target calculation algorithm from four methods
into two reusable helper methods:
- getLocalReductionLevel_(): Finds the deepest level in the group chain
where a group has both a guide rate and group-controlled wells (GCW > 0)
- applyReductionsAndFractions_(): Applies local reductions, add-back
(when applicable), and guide rate fractions to calculate the portion
of a top-level group target assigned to a bottom group
The refactored methods are:
- checkGroupConstraintsInj()
- checkGroupConstraintsProd()
- getWellGroupTargetInjector()
- getWellGroupTargetProducer()
This is a pure refactoring with no functional change. The helper methods
use templates for the reduction and fraction lambdas to avoid std::function
overhead in case of performance-critical code.
Move the auto choke exclusion logic out of the well loop in
updateGroupControlledWellsRecursive_() and into a new helper method
isAutoChokeGroupUnderperforming_(). The calculation determines whether
to exclude all wells in an auto choke group from the Group Controlled
Wells (GCW) count based on whether the group is meeting its target rate.
The original code recalculated this group-level decision redundantly
for each well in the loop, even though the result is the same for all
wells. The refactored code computes it once before the loop.
This is a pure refactoring with no functional change.