This commit distinguishes the reference condition pore volume from
the dynamic, pressure (and/or temperature) dependent pore volume
value. Previously we would report the latter as the 'PORV' value in
the "Field Totals" and "FIPNUM region" reports, but this commit
switches to reporting the former instead-mostly for compatibility.
We still report the dynamic pore volume value, but now we report
this on a line of its own, before the table, using one of the forms
Field total pressure dependent pore volume = 12345 RM3
FIPNUM report region 1 pressure dependent pore volume = 123 RM3
Check group limits in gas lift stage 1 to avoid adding too much ALQ which must
anyway later be removed in stage 2. This should make the optimization
more efficient for small ALQ increment values. Also adds MPI support.
This commit includes the shut wells in 'wells_ecl_' and expands the
PI/II value calculation to apply to those shut wells too. With this
in place we are able to run cases that have a 'WELPI' keyword before
the well opens, even at the very first report step.
In particular, apply explicit default constructors to most data
members and push initialisation to initialiser list if convenient.
While here, also split long lines and apply const in more places.
Finally, reset well- and connection-level PI values to zero in
WellState::shutWell(). This is in preparation of including shut
wells in BlackoilWellModel's internal state.
Adds a simple test case for gas lift optimization. Currently this is
very simplistic and only covers a fraction of the gas lift optimization
code. The plan is to use this as a building block to add more tests
in the future.
Extends PR #2824 to include support for GLIFTOPT (item 2, maximum lift
gas supply for a group) and group production constraints.
The optimization is split into two phases. First the wells are optimized
separately (as in PR #2824). In this phase LIFTOPT and WLIFTOPT constraints
(e.g. maxmimum lift gas injection for a well, minimum economic gradient) are
considered together with well production constraints.
Then, in the next phase the wells are optimized in groups. Here, the ALQ
distribution from the first phase is used as a starting point. If a group
has any production rate constraints, and/or a limit on its total rate of
lift gas supply, lift gas is redistributed to the wells that gain the most
benefit from it by considering which wells that currently has the largest
weighted incremental gradient (i.e. increase in oil rate compared to
increase in ALQ).
This commit sets the 'data::Well::dynamicStatus' based on the
dynamically updated 'Schedule' object (i.e., from ACTIONX and
similar) and the results of well/operability testing (WECON and/or
WTEST). If a well is closed due to economic limits (WECON) we still
provide summary-style data at the timestep that closed the well, but
omit this data at later steps until the well reopens.
We add a new parameter to WellState::report() to distinguish these
situations.
This is in preparation of making the 'BlackoilWellModel' manage both
open and shut wells alike.
Coalesce blocks with same conditions, split long lines, and apply
'const' where appropriate. While here, also tighten the "rate = 0"
criterion to include denormalised numbers.
With this commit the guiderate logic used for the production groups is also used for injectors
This allows for setting guiderates explicit at different group levels
Only RATE, NETV and VOID guiderate type is suppored.
When an ACTIONX has evaluated to True we inspect the keyword payload and if it
contains WELPI we query the well model for current wellpi values and pass that
along as context to the Schedule::applyAction()
This commit implements the WELPI feature. We calculate new PI/II
values for all wells in the event of a WELPI request and use those
values for well-specific WELPI request, to calculate CTF scaling
factors. We then apply those factors to all subsequent editions of
the well provided the connection factors are eligible for
WELPI-based rescaling.
If we trigger a rescaling event we also reset the WellState's
internal copies of the CTFs and reinitialize the Well PI calculators
to ensure the rescaling takes effect immediately. Since we rely on
PI values being available at the end of each time step we must also
take care to forward those values from the WellState of one report
step to the WellState of the next report step.
Finally, take care not to redo a WELPI scaling if we've already
performed the scaling operation and restart a report step. This,
in turn, happens if WELPI is requested on the first report step.
The B matrix is basically a component-wise multiplication
with a vector followed by a parallel reduction. We do that
reduction to all ranks computing for the well to save the
broadcast when applying C^T.
BlackoilWellModel now stores an instance of this class for each
well. Inside that class there is a custom communicator that only
contains ranks that will have local cells perforated by the well.
This will be used in the application of the distributed well operator.
This is another small step in the direction of distributed wells,
but it should be safe to merge this (note creation of the custom
communicators is a collective operation in MPI but done only once).
This commit adds a new helper function,
WellInterfacePtr createWellPointer(wellID, reportStep) const
which is responsible for creating appropriately typed derived well
pointers depending on well types (multi-segment vs. standard).
This, in turn, allows us to centralise this logic and use the same
factory function both when creating the 'well_container_' and when
forming the well-test objects.
Finally, this helper will become useful for calculating PI/II values
of shut/stopped wells in the context of WELPI.
This commit ensures that we calculate the well and connection level
per-phase steady-state productivity index (PI) at the end of a
completed time step (triggered from endTimeStep()).
We add a new data member,
BlackoilWellModel<>::prod_index_calc_
which holds one WellProdIndexCalculator for each of the process'
local wells and a new interface member function
WellInterface::updateProductivityIndex
which uses a per-well PI calculator to actually compute the PI
values and store those in the WellState. Implement this member
function for both StandardWell and MultisegmentWell. Were it not
for 'getMobility' existing only in the derived classes, the two
equal implementations could be merged and moved to the interface.
We also add a new data member to the WellStateFullyImplicitBlackoil
to hold the connection-level PI values. Finally, remove the
conditional PI calculation from StandardWell's well equation
assembly routine.
As it was, the getALQ() call would insert injectors into the ALQ maps,
leading to trouble.
Also, this gets rid of the slightly weird thing that the output data
structure's producer/injector status was only set after creation,
in BlackoilWellModel::wellData().
With this, a slightly more sophisticated procedure is used for well rate intialization.
Since it changes existing results, it defaults to false, giving the existing behaviour.
Implements gas lift optimization for a single StandardWell. Support for
gas lift optimization for multi-segment wells, groups of wells and
networks is not implemented yet.
The keywords LIFTOPT, WLIFTOPT, and VFPPROD are used to supply parameters for
the optimization. Also adds support for summary output of liftgas
injection rate via keyword WGLIR.
Previously, we exported an unordered map containing all names of
wells that are not present in the local part of the grid.
As we envision to have wells that are distributed across multiple
processors, this information does not seem to be enough. We need
to be able to set up communication for each well. To do this we need
to find out who handles perforations of each well.
We now export a full list of well name together with a boolean
indicating whether it perforates local cells (vector of pair of string
and bool).
This is in preparation of adding support for outputting the network
node pressure quantity, GPR, to the summary file. In particular,
'GroupValues' is renamed to 'GroupAndNetworkValues' and has new
individual datamembers for the former group-level data and the new
node-level data.
Update BlackoilWellModel::groupData() and CollectToIORank
accordingly and bring the parallel restart facility in line with the
new layout.
This commit adds support for reporting the simulator's guiderate
values at the well and group levels to the output layer through the
wellData() and groupData() member functions. We add several new
member functions that collectively assemble the values and assign
them to objects of type Opm::data::GuideRateValue for subsequent
output to the summary and restart files.
In particular
getGuideRateValues(const Well&) const
getGuideRateValues(const Group&) const
retrieve the guiderate values for all phases for those individual
wells and groups for which the guideRate_ data member defines a
value. The most complicated function of this commit is
calculateAllGroupGuideRates
which aggregates those individual contributions from the well (leaf)
level up to the root of the group tree (the FIELD group). This
process uses an ancillary array ('up') to keep track of the parent
groups of all wells and all groups, and to ensure that we only visit
each parent group once (sort+unique on subsets of the 'up' array).
We do not currently support outputting guiderates for reservoir
voidage volume (GuideRateModel::Target::RES).
This commit makes the 'groupData()' function return a
map<string, Opm::data::GroupData>
object instead of a
map<string, Opm::data::GroupConstraints>
object. The 'GroupData' structure adds a level of indirection to
the current per-group summary quantities that are directly assigned
by the simulator. While here, also move the assignment of the
current group constraints/control values out to a separate helper
to reduce the body of the per-group loop in 'groupData()'.
This is in preparation of adding support for reporting group-level
production/injection guiderates (Gx[IP]GR) to the summary file.
1) Only check GCONSALE limits at the end of a timestep. NB. The simulator still throws if some of the limits are violated
2) BUGFIX: don't remove gas consumption twice