This is mostly to have a general solution for matching region level
summary keywords which may reference a user-defined region set (FIP
keyword, e.g., FIPXYZ) through tags like
RPR__XYZ -- Average pressure in region, FIPXYZ region set
ROPR_XYZ -- Oil production rate in region, FIPXYZ region set
RODENXYZ -- Average oil density in region, FIPXYZ region set
The initial approach introduced in commit cfbafc236 was limited to
selected keywords.
To this end, add a new data member
std::string ParserKeyword::m_matchRegexSuffix
and introduce a new member function
bool ParserKeyword::matchesDeckNames()
which matches a candidate keyword string against the m_deckNames,
and, if applicable, as a regular expression against m_deckNames when
appended m_matchRegexSuffix.
The MULTREGT keyword has an independent way of defining the default
region--the default value of item 6--and does not need the default
GRIDOPTS-base region protocol of the other *REG keywords.
Mostly to group related functions and have the same order in the
declaration and the implementation files. While here, replace an
'enum' with a strong enum since the type does not need to support
arithmetic operations.
This commit adds a new, focused, member function
NumericalAquifers::allAquiferCellIds()
which returns a vector of those Cartesian/global cells that have
been marked as defining the model's numerical aquifers through the
AQUNUM keyword. We intend to use this to identify those NNCs that
go to numerical aquifers--or between numerical aquifer cells--as
those may need special treatment when processing the MULTREGT
keyword.
The 'base' checks that the input string looks like a valid keyword
and, if so, matches the string against the builtin set of known
keywords. The full keyword recognition process additionally
includes those keywords that match against keyword collections,
typically the SUMMARY section "meta" keywords in the *_PROBE files.
We will use the 'base' recognition separately to introduce support
for extension keywords with long--more than eight character--names.
This commit replaces the data members 'nx', 'ny', and 'nz' with a
copy of the GridDims object passed as an argument to the
constructor. In turn, this enables using GridDims::getIJK() to
compute the cell's IJK tuple from its global Cartesian index instead
of implementing the same calculation locally (and incorrectly).
While here, also include the layer index (K) in determining whether
or not a connection is an NNC, and do this just once instead of once
for each MULTREGT record. Cells (I,J,K) and (I,J,K+3) might be
connected across pinched-out layers and for the purposes of MULTREGT
that connection should be treated as an NNC.
In particular, ensure that we include all requisite headers, hide
type aliases that are not needed outside the class, consistently use
std::size_t, split a few long lines, and switch to range-for in one
location.
A numeric index serves the same purpose as a pointer in this very
specific instance and also has the benefit of being easily
transferable between processes. This, in turn, means we can remove
the 'getSearchMap()' and 'constructSearchMap()' member functions.
These are not directionally dependent, and they have a unit string
of 'Pressure'. This didn't use to matter, but upcoming changes
will depend on the unit string being correct.
In particular:
- Order include statements
- Simplify logic
- Adjust whitespace
This is in preparation of making FIP* array names unique only up to
the first six characters (i.e., "FIP" + at most three others).
Without the include compilation fails with
```
/opm/io/eclipse/EclFile.hpp:92:17: error: ‘uint64_t’ was not declared in this scope
92 | std::vector<uint64_t> ifStreamPos;
| ^~~~~~~~
In file included from src/opm/io/eclipse/EclOutput.cpp:20:
opm/io/eclipse/EclUtil.hpp:56:5: error: 'uint64_t' does not name a type
56 | uint64_t sizeOnDiskBinary(int64_t num, Opm::EclIO::eclArrType arrType, int elementSize);
| ^~~~~~~~
```
This commit adds a new member, well_structure_change, to the
SimulatorUpdate structure. The member defaults to 'false', but
will be set to 'true' if an ACTIONX block contains at least one of
a select group of keywords that affect the model's well topology.
In particular, set this member to 'true' if the ACTIONX block has
at least one of the keywords
- COMPDAT
- WELOPEN
- WELSPECS
This will enable adding simulator logic to open or create wells in
the middle of a report step.
This commit adds the requisite backing storage and parser support
for capturing and transporting simulator-level calculation of phase
and mixture density value for purpose of summary file output. To
this end, make 'SegmentQuantity' into a template on a set of defined
items and make SegmentPhaseQuantity into a specialisation of this
template. Add a new specialisation, SegmentPhaseDensity, which
holds phase densities (oil, gas, water), and fluid mixture densities
with and without flowing fraction exponents.
These will be used to transport the values needed to output segment
level summary vectors
SDENx -- Phase density of phase 'x' (O, G, W)
SDENM -- Fluid mixture density without flowing fraction exponents
SMDEN -- Fluid mixture density with flowing fraction exponents
This commit implements the WPAVE keyword and its associate WBPn
well level report quantities. We support all valid settings of
WPAVE and WWPAVE. The various weighted averages are accumulated
through compensated summation of both the numerator and denominator
terms for the inner block, the direct/immediate level 1 neighbours,
and the diagonal level 2 neighbours. We combine those contributions
to the WBP, WBP4, WBP5, and WBP9 terms when we "commit" the
contributions (Accumulator::commitContributions()), per connection
for values weighted by the connection transmissibility factor, and
per well for values weighted by pore volumes.
We distinguish OPEN from ALL connections through callback functions
in the implementation of accumulateLocalContributions() and the per
connection weighting terms are provided as another set of callback
functions depending on the value of the inner block weighting factor
F1.
Depth correction (NONE, WELL, or RES) is affected through a separate
set of callback functions used in the implementation of
'connectionPressureOffset'.
We discover source locations in a two-step process. At WBPn
calculation construction time, we exclude only those cells that are
outside the model's dimensions. The user is then expected to call
member function pruneInactiveWBPCells(), typically at the
CalculatorCollection level, at a later time in order to prune
inactive cells. This two-step split is necessary because we do not
have a complete global view of the model's active cells in a
parallel run. It is very possible that the WBPn calculation on one
rank will require source values from another rank and that begets
this extra caution.
The user must call inferBlockAveragePressures() to compute the WBPn
values. Once completed, the result values may be extracted by
calling member function averagePressures(). We expect that the user
will provide a complete set of up-to-date source values when calling
this member function, both at the reservoir and the well connection
levels.
Mostly for readability. While here, also switch to using compiled
item names instead of raw strings to access the DeckItems which
constitute the WPAVE and WWPAVE keywords.
with more testing, it looks like when multiple records are entered. The
records with WREV mode and records with CIRR and CREV modes work
differently in term of overwriting the previous records. So it is
necessary to store them separately.
In particular
* Tag a single argument constructor as 'explicit',
* Remove an unused private function
* Fix mismatched tags (struct vs. class) in forward declaration
* Return 'false' in an impossible updateHyst() case
While here, also use a real UnitSystem object instead of creating
a METRIC system just to infer unit strings.
An assignment of the form
ASSIGN WUPPERTAL 354.572 /
should create a UDQ set of size equal to the number of wells in
the model, not just the wells already flowing-especially if the
assignment happens on the very first report step before any wells
are flowing.
This commit adds a new container class,
PAvgDynamicSourceData
which wraps a single vector<double> which in turn backs source data
items for
- pressure values
- fluid mixture densities
- dynamic pore-volumes
at a collection of source locations-active cells or well reservoir
connections. We provide read-only and read-write accessors to the
underlying data items for a single source location through subscript
operator (read only) and named assignment (set(), read-write) member
functions. The latter is available only when the underlying range
of data values is mutable (e.g., SourceDataSpan<double>) as opposed
to immutable (e.g., SourceDataSpan<const double>).
This initial commit changes the Summary class's API for consuming
block-averaged well level pressure values (summary keywords WBPn).
The former approach was intended to consume a collection of source
values--pressures, densities, and pore-volumes--and then to defer
calculation of the WBPn summary vectors to the Summary class.
This commit introduces a 'WellBlockAvgPress' container class which
holds precomputed WBPn results and the intention is to move the
calculation to the simulator side for greater parallelism.
In particular, check that
1. Number of MS wells <= WSEGDIMS(1)
2. Number of segments per well <= WSEGDIMS(2)
3. Number of branches per well <= WSEGDIMS(3)
for all report steps in the simulation run.
Example diagnostic message of a case that violates limits 2 and 3:
Error: Problem with keyword WSEGDIMS
In CASE.DATA line 60
The case has a multi-segmented well with 246 well segments, but at most 200 are allowed in WSEGDIMS.
Please increase item 2 of WSEGDIMS to at least 246
Error: Problem with keyword WSEGDIMS
In CASE.DATA line 60
The case has a multi-segmented well with 105 lateral branches, but at most 5 are allowed in WSEGDIMS.
Please increase item 3 of WSEGDIMS to at least 105