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
The [IR]SEG and ILB[RS] arrays must be able to accommodate the
maximum number of segments and branches used in the run. This
commit incorporates the dynamic maximum sizes. If those sizes
exceed the maximum values entered in WSEGDIMS, then the resulting
restart file will not be fully compatible with other simulation
software.
Classes which inherit from FlatTableWithCopy and just call the base
class implementation of 'serializeOp()' don't really need a separate
implementation of that member function.
Noticed by: [at]blattms.
This commit adds the expected behaviour for all-defaulted records in
ROCK, provided the all-defaulted records are not the first of the
keyword. Similarly to, e.g. PVTW, all-defaulted records are treated as
copies of the immediately preceding record.
In other words, given
ROCK
-- REF. PRES COMPRESSIBILITY
280.000 5.6E-5 /
/
the second record is supposed to be a copy of the first.
this went unnoticed since there are no UDQDefines in the pre-simulation
Schedule broadcast for parallel. however it causes issues for serialized
restarts
This commit adds a special case for handling the dynamic nature of
the number of records in the ROCK keyword. In particular, if the
ROCKOPTS keyword is NOT entered before ROCK, then the number of
records is NTPVT--item 2 from TABDIMS. Conversely, when ROCKOPTS is
entered before ROCK, the number of records in the latter depends on
the setting in item 3 of ROCKOPTS.
This interaction cannot be easily captured in our JSON-based models,
so we introduce a special size class, SPECIAL_CASE_ROCK, that only
applies to the ROCK keyword and implement the logic in a dedicated
function in 'Parser.cpp'. Once we have determined the correct
number of records, we form a RawKeyword of type FIXED and defer
further processing to the existing handling of fixed-sized keywords.
Add a selection of unit tests to exercise the new behaviour.
Switch if/else chain out in favour of a map-based approach. This
simplifies adding new enumerators. While here, also return string
objects instead of constant string objects.
Most H2 properties are calculated using Helmholtz free energy EOS.
Moved Helmholtz equations from Brine_H2 to H2 class.
New file with simple H2 property calculations based on ideal gas.
If there is an EDITNNCR entry and a NNC entry for the same cell pair
then the EDITNNCR entry is not be represented inernally but we simply
overwrite the transmissibility of the corresponding NNC entry.
If there is an EDITNNC entry and an EDITNNCR entry for the same cell
pair then the EDITNNC entry is removed while internalizing EDITNNCR.
Order matters for EDITNNCR entries in the sense that later specified
values will overwrite previous entries when we internalize.
Note that similar to EDITNNC only the first 7 options are represented
and the rest is ignored by OPM flow.
Note that EDITNNCR entries for neighboring cells are ignored (like for
EDITNNC).
This commit adds logic and structures for bringing in constant flux
aquifer objects-keyword AQUFLUX-from the restart file and forming
the requisite dynamic objects in the Schedule.
In particular, the 'RstAquifer' gets a new bare-bones representation
of these aquifer types and we add new constant flux aquifer objects
to the pertinent 'ScheduleState' when these exist. We also add this
aquifer type to 'data::Aquifers' in preparation of reinitialising
the simulator's aquifer container from the restart file. In
particular, this needs the total produced volume from the aquifer so
far.
In general we'd need to link to dune-common ("target_link_library")
to get the appropriate include directories for Dune in that case,
but in this specific instance we can get by with not specialising
Dune's 'className' function if Dune is not available.
Thanks to [at]akva2 for suggesting this workaround.
We support constant flux aquifers (AQUFLUX keyword) entered both in
the SOLUTION and in the SCHEDULE sections. The primary structural
change is that we have to support analytic aquifers being introduced
dynamically, whence the connection information (xCAQ) must be
captured without knowing the full set of analytic aquifers. We
therefore allocate those output arrays purely from the maximum sizes
entered in the RUNSPEC section whereas we defer determining the
maximum aquifer ID to the point of capturing the dynamic values.
The xAAQ values for constant flux aquifers amount to a new aquifer
type integer value (=2) in IAAQ[11] and the flux value in SAAQ[0].
g++-12 needs quite some memory and time to compile it.
We now use several Builtin*.cpp for the imlementations for different
starting letters of eclipse keywords to use less resources for
compiling.
Instead we use the old fashioned way of checking the size and then
either return the address of the first element or a nullptr.
ClosesOPM/opm-simulator#4472
We only check these keywords at the report step that the keywords are
specified.
Not totally sure how it will affect the RESTART, while it is not hard to
switch back.
In the admittedly special case that "position" is equal to the
buffer's size() and "n == 0", then the expression
&buffer[position]
will index out of bounds. Use the safer expression
buffer.data() + position
instead since that's valid when position <= size().
Detected by libstdc++'s debug mode (checked iterators).
This commit adds support for constructing UDQ ASSIGN records for
enumerated well items such as those encountered in UDQs at the
segment level, e.g.,
ASSIGN SUSPECT PROD01 123.456 /
ASSIGN SUSPECT PROD02 17 654.321 /
We do not support this syntax quite yet, but this is a step on the
way there.
This is in preparation of adding UDQs at the segment level. We will
probably need to rethink the UDQ scalars and UDQ sets at some point,
since the lookup and assignment operations become more expensive
from adding this piece of information.
While here, also add containers for segment level UDQs to the UDQ
state object. These are currently unused, but adding them here
simplifies follow-up work.
Finally, add some Doxygen-style documentation to the UDQ set and
scalar types.
and the class member types are constructed with using statements.
this allows for forwarding of the enums, and for using the enums
without dragging in Well.hpp