this does only matters for temperature changes due to dissolution and
evaporization of gas in oil or oil in gas. The comprehensive solution
would be to make the enthalpy of the phases composition dependent, but
ECL does not seem to support this when using the black-oil model.
this was only partially done so far: the term "heat" should be avoided
if possible because it is a somewhat fuzzy concept. Thus, replace it
by "energy" and "thermal" where it is not a well established
term. ("well established" basically means "heat capacity".)
before, if the fluid state did not provide an invB() method,
Opm::getInvB_() just returned 0.0. with this, it uses the composition
and density of the phase in question to compute that quantity.
(also, this commit contains a few stylistic cleanups for
BlackOilFluidSystem)
now the assign() function should work and all functions should exhibit
a doxygen string. note that the inverse formation volume factors are
zero if the fluid state passed as the argument to assign() does not
feature an invB() member function.
thermal laws are the heat conduction laws plus "solid energy laws"
which can be used to specify the relations which govern the volumetric
internal energy of the solid matrix of the porous medium.
- Introduce an enthalpy() method to all low-level PVT classes
- change the approach to define temperature dependent density for oil
and gas to the OPM-specific keywords GASDENT and OILDENT. Funnily
enough, ECL already has a WATDENT keyword.
i.e. enthalpy, internal energy and temperature. To make sure that this
does not affect simulatiors which do not use energy, two additional
template parameters, `enableTemperature` and `enableEnergy` are
introduced and the energy quantities are only stored
conditionally. The first parameter allows to store a temperature in
the fluid state without storing enthalpies while the second stores
everything (i.e., setting it to true also implies the first).
since the undersaturated PVT relations may use bi-linear 2D
interpolation but the saturated ones always use linear 1D
interpolation, not having this leads to a discontinuity. that
discontinuity turns out to be very bad news if the partial derivatives
are calculated using finite differences. On the other hand, the
untersaturated PVT relations cannot be used unconditionally (this
would be the clean solution, IMO) because this causes the results to
deflect from those produced by ECL. The hack to make DR[SV]DT work is
to only use the saturated PVT quantities if the R value is
sufficiently large. (This may lead to issues in the future because
there now is a discontinuity w.r.t. R, but let's burn that bridge when
we come to it.)
in the oil case the previous condition that the saturation of the gas
phase is non-zero is cheaper to evaluate, but it does not work when
the maximum Rs value at which the gas phase starts to appear is lower
than the Rs value of the saturated gas. In particular this happens for
the DRSDT keyword.
note that the best solution would be to eliminate these case
distinctions alltogether, but this does not work because ECL does not
seem to use bi-linear interpolation if the pressure gets larger than
the maximum pressure specified by the PVT table. (it only seems to use
the pressure to extrapolate linearly.)
this causes problems with things like DRSDT where
"isSaturated(oilPhasIdx)" is not necessarily related to the presence
of the gas phase. (analogous for DRVDT.)
The impact of performance seems to be negligible:
```
Total time (seconds): 550.185
Solver time (seconds): 534.769
Assembly time (seconds): 251.509 (Failed: 4.51604; 1.79558%)
Linear solve time (seconds): 263.03 (Failed: 5.78332; 2.19873%)
Update time (seconds): 11.0526 (Failed: 0.220144; 1.99177%)
Output write time (seconds): 18.1411
Overall Well Iterations: 902 (Failed: 7; 0.776053%)
Overall Linearizations: 1890 (Failed: 33; 1.74603%)
Overall Newton Iterations: 1553 (Failed: 33; 2.12492%)
Overall Linear Iterations: 23525 (Failed: 511; 2.17216%)
```
before and
```
Total time (seconds): 556.463
Solver time (seconds): 541.06
Assembly time (seconds): 253.165 (Failed: 4.42903; 1.74946%)
Linear solve time (seconds): 267.343 (Failed: 4.52042; 1.69087%)
Update time (seconds): 11.334 (Failed: 0.214721; 1.89449%)
Output write time (seconds): 18.0694
Overall Well Iterations: 903 (Failed: 8; 0.885936%)
Overall Linearizations: 1909 (Failed: 33; 1.72865%)
Overall Newton Iterations: 1572 (Failed: 33; 2.09924%)
Overall Linear Iterations: 23866 (Failed: 391; 1.63831%)
```
after this patch, i.e., on my machine the runtime for Norne went from
550 to 556 seconds due to slightly larger number of non-linear and
linear iterations. Note that this also happens if the 1e-4 threshold
value is changed instead of the case distinction being removed. (This
hints on the into the direction that the performance difference is
just numerical noise.)
this flag is way too non-descript (a complex relation for one person
may be a simple one for another), the implementation is pretty
inconsistent and it makes the code more complicated and harder to
maintain. Thus, IMO the approach turned out to be a bummer, so let's
pull the plug.
I missed the fact that in the enthalpy() function, the polynomial
coefficients are divided, i.e., this component defines a polynomial
for the heat capacity and integrates it for the enthalpy. (not
the other way around.)
I looked at all components: For the ones that use simple enthalpy
relations, heatCapacity() and enthalpy() should now be
consistent. (Here "simple" means "an approach that I understood without
reading literature for several hours".)
a reduction of Rs and Rv of a factor 1000 should be enough physically
and the numerical stability is quite a bit better with this. In
particular, this is should not really matter because the whole concept
of VAPPARS is a staggeringly ugly hack from the outset.
std::exception is a polymorphic type and catching these by values
generates warnings when using the latest GCC from SVN. Besides this,
catching objects by value is bad style and was unintended from the
start.
In fact, the temperature at the reservoir is not constant, so this
should be more thought of as "representative temperature" of the
reservoir.
In ECL, this value is specified using the RTEMP or the RTEMPA
keywords, opm-parser provides this via the table manager. (NB: is this
really something that belongs there?)