o The status of a well is maintened as a small object which is managed by a new
std::shared_ptr member in the well objects. The consequence of this is that
several well objects can share the same underlying status object. The
advantage of this is that runtime (i.e. ACTIONX) updates of well status will
affect the correct set of wells.
o The general Schedule::updateWell() will use the DynamicState::upadte_equal()
Heed advice from [at]joakim-hove to keep client code as close to
strictly SI as possible. We must nevertheless continue to store the
raw (input/output units) requested PI value internally as this is
the only way to ensure that both the client and implementation has
consistent view of the well's preferred phase. This means pushing
the unit conversion into Well::getWellPIScalingFactor().
Thanks to [at]joakim-hove for pointing out that the Well already
maintains an internal UnitSystem data member which makes the process
of converting the PI units trivial.
This commit ensures that we record a general, Schedule-level
WELL_PRODUCTIVITY_INDEX
event in addition to the well-specific event already recorded when
we encounter a WELPI keyword. We need this information in order to
trigger a PI calculation across all MPI processes in opm-simulators.
This makes the interface less convenient to use, but it is the only
way to guarantee that we have a consistent notion of preferred phase
for injectors. The downside is that the users of
Well::getWellPIScalingFactor()
must convert the argument to raw/input units before calling the
function.
This commit adds a new member function
applyWellProdIndexScaling(well_name, report_step, scalingFactor)
which applies WELPI-based CTF scaling (by scalingFactor) for all
pertinent report steps from 'report_step' and until the end of the
simulation run. We use the 'scalingApplicable' array to communicate
connection eligibility between report steps and only apply the
scaling if the internal connections pointers differ between report
steps.
This commit adds a new in/out parameter, scalingApplicable, to the
applyWellProdIndexScaling functions. This parameter carries time
(history) information on whether or not a particular connection is
eligible for WELPI-based CTF scaling. Entries are marked ineligible
(false) and left untouched on subsequent calls if the corresponding
connection is ineligible at any point--e.g., as a result of new
COMPDAT entries.
This ability enables implementing WELPI CTF scaling at the Schedule
level which is the only level that has sufficient time information
to identify all the unique Well/WellConnections object combinations.
First part, implemented in a new member function
Well::getWellPIScalingFactor
calculates a CTF scaling factor from stored WELPI information and a
dynamically calculated well-level PI value. The second part, using
the original name applyWellProdIndexScaling, applies an externally
calculate CTF scaling factor to all eligble connections.
This is needed to enable applying multiple scalings across the time
direction. Update unit tests accordingly.
Since the Well stores a pointer to its connections, rather than the
connections themselves, we must take care not change the existing
state of the connections' WELPI eligibility flag. Do the update
check on a copy of the connections instead of the real connections.
Pointy Hat: [at]bska
This is different from COMPLETION_CHANGE which is unconditionally
recorded when processing COMPDAT. This event is recorded only when
the Well's internal WellConnections structure actually changes and
informs clients that they may need to rerun any dynamic WELPI
scaling. Such scaling will not be automatically forwarded onto the
new WellConnections structure.
This is arguably a hack.
This commit adds logic implementing the static parts of the WELPI
keyword. We internalize the keyword data, record appropriate events
and provide hooks for dynamically adjusting the per-connection
transmissibility factor (Connection::CF()) when those events occur.
We implement support at three levels
- WellConnections:
Add new public member functions prepareWellPIScaling and
applyWellPIScaling which, respectively, creates bookkeeping
data to track those connections which are subject to CF scaling
and actually applies that CF scaling.
- Well:
Add new data member 'productivity_index' which holds the 'WELPI'
data value from the input keyword (converted to SI) and new
member functions updateWellProductivityIndex and
applyWellProdIndexScaling. The first follows the 'update*'
protocol (return 'true' if state change) and assigns new values
to 'productivity_index' while the second uses the stored PI
value and a dynamically calculated effective PI value to rescale
the pertinent connections' CF value.
- Schedule:
Add new member function handleWELPI which internalizes the WELPI
keyword and its data and records WELPI events for subsequent
playback in the simulator layer.
Also add a set of unit tests to exercise the new features at all
levels.
In particular, include standard library headers as needed, fix
function declarations (operator<<() for Well::WellProductionProperties),
and make a few helper functions 'static' to avoid warnings of the
form "no previous declaration for".
For the Schedule's keyword handlers, also switch to storing member
function pointers directly instead of std::function objects. This
saves space and does not incur function pointer conversions. Use
std::invoke to call those handlers to avoid having to spell out the
'->*' operator.