2019-04-23 08:56:06 +02:00
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2015-06-18 13:43:59 +02:00
// vi: set et ts=4 sw=4 sts=4:
2014-11-28 12:58:48 +01:00
/*
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
2016-03-14 13:21:47 +01:00
Consult the COPYING file in the top-level source directory of this
module for the precise wording of the license and the list of
copyright holders.
2014-11-28 12:58:48 +01:00
*/
/*!
* \file
* \copydoc Ewoms::EclOutputBlackOilModule
*/
#ifndef EWOMS_ECL_OUTPUT_BLACK_OIL_MODULE_HH
#define EWOMS_ECL_OUTPUT_BLACK_OIL_MODULE_HH
#include "eclwriter.hh"
2018-03-12 14:31:36 +01:00
#include <ewoms/models/blackoil/blackoilproperties.hh>
2015-04-28 11:58:21 +02:00
#include <ewoms/common/propertysystem.hh>
2014-11-28 12:58:48 +01:00
#include <ewoms/common/parametersystem.hh>
2018-02-01 14:40:01 +01:00
#include <opm/material/common/Valgrind.hpp>
2018-03-05 13:00:51 +01:00
2017-12-07 12:38:48 +01:00
#include <opm/parser/eclipse/Units/Units.hpp>
2018-01-12 15:32:43 +01:00
#include <opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp>
2017-12-07 12:38:48 +01:00
#include <opm/output/data/Cells.hpp>
#include <opm/output/eclipse/EclipseIO.hpp>
2018-03-12 14:31:36 +01:00
#include <opm/common/OpmLog/OpmLog.hpp>
2016-11-07 15:14:07 +01:00
2014-11-28 12:58:48 +01:00
#include <dune/common/fvector.hh>
#include <type_traits>
2018-06-14 16:06:05 +02:00
BEGIN_PROPERTIES
2017-12-07 12:38:48 +01:00
// create new type tag for the Ecl-output
2014-11-28 12:58:48 +01:00
NEW_TYPE_TAG ( EclOutputBlackOil );
2018-07-26 12:31:32 +02:00
NEW_PROP_TAG ( ForceDisableFluidInPlaceOutput );
SET_BOOL_PROP ( EclOutputBlackOil , ForceDisableFluidInPlaceOutput , false );
2018-06-14 16:06:05 +02:00
END_PROPERTIES
namespace Ewoms {
2014-11-28 12:58:48 +01:00
// forward declaration
template < class TypeTag >
class EcfvDiscretization ;
/*!
2014-12-22 19:19:03 +01:00
* \ingroup EclBlackOilSimulator
2014-11-28 12:58:48 +01:00
*
* \brief Output module for the results black oil model writing in
* ECL binary format.
*/
template < class TypeTag >
2017-12-07 12:38:48 +01:00
class EclOutputBlackOilModule
2014-11-28 12:58:48 +01:00
{
typedef typename GET_PROP_TYPE ( TypeTag , Simulator ) Simulator ;
typedef typename GET_PROP_TYPE ( TypeTag , Discretization ) Discretization ;
typedef typename GET_PROP_TYPE ( TypeTag , Scalar ) Scalar ;
2015-05-21 16:18:45 +02:00
typedef typename GET_PROP_TYPE ( TypeTag , Evaluation ) Evaluation ;
2014-11-28 12:58:48 +01:00
typedef typename GET_PROP_TYPE ( TypeTag , ElementContext ) ElementContext ;
2017-12-07 12:38:48 +01:00
typedef typename GET_PROP_TYPE ( TypeTag , MaterialLaw ) MaterialLaw ;
typedef typename GET_PROP_TYPE ( TypeTag , MaterialLawParams ) MaterialLawParams ;
2014-11-28 12:58:48 +01:00
typedef typename GET_PROP_TYPE ( TypeTag , FluidSystem ) FluidSystem ;
2018-01-16 15:44:01 +01:00
typedef typename GET_PROP_TYPE ( TypeTag , GridView ) GridView ;
typedef typename GridView :: template Codim < 0 >:: Entity Element ;
typedef typename GridView :: template Codim < 0 >:: Iterator ElementIterator ;
2014-11-28 12:58:48 +01:00
enum { numPhases = FluidSystem :: numPhases };
enum { oilPhaseIdx = FluidSystem :: oilPhaseIdx };
enum { gasPhaseIdx = FluidSystem :: gasPhaseIdx };
enum { waterPhaseIdx = FluidSystem :: waterPhaseIdx };
enum { gasCompIdx = FluidSystem :: gasCompIdx };
2015-02-03 13:58:18 +01:00
enum { oilCompIdx = FluidSystem :: oilCompIdx };
2018-11-16 14:51:07 +01:00
enum { enableEnergy = GET_PROP_VALUE ( TypeTag , EnableEnergy ) };
2014-11-28 12:58:48 +01:00
2017-12-07 12:38:48 +01:00
typedef std :: vector < Scalar > ScalarBuffer ;
2014-11-28 12:58:48 +01:00
2018-04-30 17:17:22 +02:00
struct FipDataType
{
enum FipId
{
2018-01-16 14:24:21 +01:00
WaterInPlace = 0 , //WIP
OilInPlace = 1 , //OIP
GasInPlace = 2 , //GIP
OilInPlaceInLiquidPhase = 3 , //OIPL
OilInPlaceInGasPhase = 4 , //OIPG
GasInPlaceInLiquidPhase = 5 , //GIPL
2018-01-17 15:24:24 +01:00
GasInPlaceInGasPhase = 6 , //GIPG
2018-04-30 17:17:22 +02:00
PoreVolume = 7 , //PV
2018-01-12 15:32:43 +01:00
};
2018-01-17 15:24:24 +01:00
static const int numFipValues = PoreVolume + 1 ;
2018-01-12 15:32:43 +01:00
};
2014-11-28 12:58:48 +01:00
public :
2018-02-01 13:16:37 +01:00
template < class CollectDataToIORankType >
EclOutputBlackOilModule ( const Simulator & simulator , const CollectDataToIORankType & collectToIORank )
2017-12-07 12:38:48 +01:00
: simulator_ ( simulator )
2018-01-12 15:32:43 +01:00
{
createLocalFipnum_ ();
2018-02-01 13:16:37 +01:00
// Summary output is for all steps
2018-02-01 16:26:58 +01:00
const Opm :: SummaryConfig summaryConfig = simulator_ . vanguard (). summaryConfig ();
2018-02-01 13:16:37 +01:00
// Initialize block output
2018-04-30 17:17:22 +02:00
for ( const auto & node : summaryConfig ) {
2018-02-01 13:16:37 +01:00
if ( node . type () == ECL_SMSPEC_BLOCK_VAR ) {
2018-04-30 17:17:22 +02:00
if ( collectToIORank . isGlobalIdxOnThisRank ( node . num () - 1 )) {
2018-02-01 13:16:37 +01:00
std :: pair < std :: string , int > key = std :: make_pair ( node . keyword (), node . num ());
2018-02-09 12:57:34 +01:00
blockData_ [ key ] = 0.0 ;
2018-02-01 13:16:37 +01:00
}
}
}
2018-07-26 12:31:32 +02:00
forceDisableFipOutput_ = EWOMS_GET_PARAM ( TypeTag , bool , ForceDisableFluidInPlaceOutput );
}
/*!
* \brief Register all run-time parameters for the Vtk output module.
*/
static void registerParameters ()
{
EWOMS_REGISTER_PARAM ( TypeTag , bool , ForceDisableFluidInPlaceOutput ,
"Do not print fluid-in-place values after each report step even if requested by the deck." );
2018-01-12 15:32:43 +01:00
}
2014-11-28 12:58:48 +01:00
/*!
* \brief Allocate memory for the scalar fields we would like to
2017-12-07 12:38:48 +01:00
* write to ECL output files
2014-11-28 12:58:48 +01:00
*/
2018-02-01 13:16:37 +01:00
void allocBuffers ( unsigned bufferSize , unsigned reportStepNum , const bool substep , const bool log )
2014-11-28 12:58:48 +01:00
{
2018-01-09 14:01:30 +01:00
if ( ! std :: is_same < Discretization , Ewoms :: EcfvDiscretization < TypeTag > >:: value )
return ;
2018-01-19 15:45:42 +01:00
// Summary output is for all steps
2018-02-01 16:26:58 +01:00
const Opm :: SummaryConfig summaryConfig = simulator_ . vanguard (). summaryConfig ();
2018-01-23 09:46:56 +01:00
2018-01-22 13:38:50 +01:00
// Only output RESTART_AUXILIARY asked for by the user.
2018-02-01 16:26:58 +01:00
const Opm :: RestartConfig & restartConfig = simulator_ . vanguard (). eclState (). getRestartConfig ();
2018-01-22 13:38:50 +01:00
std :: map < std :: string , int > rstKeywords = restartConfig . getRestartKeywords ( reportStepNum );
2018-04-30 17:17:22 +02:00
for ( auto & keyValue : rstKeywords ) {
2018-01-22 13:38:50 +01:00
keyValue . second = restartConfig . getKeyword ( keyValue . first , reportStepNum );
}
outputFipRestart_ = false ;
2018-01-23 09:46:56 +01:00
computeFip_ = false ;
2018-01-19 15:45:42 +01:00
// Fluid in place
2018-01-29 12:23:23 +01:00
for ( int i = 0 ; i < FipDataType :: numFipValues ; i ++ ) {
2018-01-29 08:43:42 +01:00
if ( ! substep || summaryConfig . require3DField ( fipEnumToString_ ( i ))) {
2018-01-22 13:38:50 +01:00
if ( rstKeywords [ "FIP" ] > 0 ) {
rstKeywords [ "FIP" ] = 0 ;
outputFipRestart_ = true ;
}
2018-01-19 15:45:42 +01:00
fip_ [ i ]. resize ( bufferSize , 0.0 );
2018-01-23 09:46:56 +01:00
computeFip_ = true ;
2018-01-19 15:45:42 +01:00
}
2018-04-30 17:17:22 +02:00
else
fip_ [ i ]. clear ();
2018-01-19 15:45:42 +01:00
}
if ( ! substep || summaryConfig . hasKeyword ( "FPR" ) || summaryConfig . hasKeyword ( "FPRP" ) || summaryConfig . hasKeyword ( "RPR" )) {
2018-01-29 12:23:23 +01:00
fip_ [ FipDataType :: PoreVolume ]. resize ( bufferSize , 0.0 );
2018-01-29 08:43:42 +01:00
hydrocarbonPoreVolume_ . resize ( bufferSize , 0.0 );
pressureTimesPoreVolume_ . resize ( bufferSize , 0.0 );
pressureTimesHydrocarbonVolume_ . resize ( bufferSize , 0.0 );
2018-04-30 17:17:22 +02:00
}
else {
2018-01-29 08:43:42 +01:00
hydrocarbonPoreVolume_ . clear ();
pressureTimesPoreVolume_ . clear ();
pressureTimesHydrocarbonVolume_ . clear ();
2017-12-07 12:38:48 +01:00
}
2018-02-07 14:30:43 +01:00
// Well RFT data
if ( ! substep ) {
2019-04-04 07:27:39 +02:00
const auto & schedule = simulator_ . vanguard (). schedule ();
const auto & rft_config = schedule . rftConfig ();
2019-05-02 12:51:25 +02:00
for ( const auto & well : schedule . getWells2 ( reportStepNum )) {
2018-02-07 14:30:43 +01:00
// don't bother with wells not on this process
2018-04-30 17:17:22 +02:00
const auto & defunctWellNames = simulator_ . vanguard (). defunctWellNames ();
2019-05-02 12:51:25 +02:00
if ( defunctWellNames . find ( well . name ()) != defunctWellNames . end ()) {
2018-02-07 14:30:43 +01:00
continue ;
}
2019-04-04 07:27:39 +02:00
if ( ! rft_config . active ( reportStepNum ))
2018-02-07 14:30:43 +01:00
continue ;
2019-05-02 12:51:25 +02:00
for ( const auto & connection : well . getConnections ()) {
2018-06-28 15:49:45 +02:00
const size_t i = size_t ( connection . getI ());
const size_t j = size_t ( connection . getJ ());
const size_t k = size_t ( connection . getK ());
2018-04-30 17:17:22 +02:00
const size_t index = simulator_ . vanguard (). eclState (). getInputGrid (). getGlobalIndex ( i , j , k );
2018-01-19 15:45:42 +01:00
2018-06-28 15:49:45 +02:00
oilConnectionPressures_ . emplace ( std :: make_pair ( index , 0.0 ));
waterConnectionSaturations_ . emplace ( std :: make_pair ( index , 0.0 ));
gasConnectionSaturations_ . emplace ( std :: make_pair ( index , 0.0 ));
2018-02-07 14:30:43 +01:00
}
}
}
2018-12-17 11:37:07 +01:00
// always allocate memory for temperature
temperature_ . resize ( bufferSize , 0.0 );
2018-02-07 14:30:43 +01:00
// Only provide restart on restart steps
2018-12-07 15:56:45 +01:00
if ( ! restartConfig . getWriteRestartFile ( reportStepNum , log ) || substep )
2018-02-07 14:30:43 +01:00
return ;
2018-01-12 15:32:43 +01:00
2018-01-22 13:38:50 +01:00
// always output saturation of active phases
2018-01-09 14:01:30 +01:00
for ( unsigned phaseIdx = 0 ; phaseIdx < numPhases ; ++ phaseIdx ) {
if ( ! FluidSystem :: phaseIsActive ( phaseIdx ))
continue ;
2014-11-28 12:58:48 +01:00
2018-04-30 17:17:22 +02:00
saturation_ [ phaseIdx ]. resize ( bufferSize , 0.0 );
2017-12-07 12:38:48 +01:00
}
2018-01-22 13:38:50 +01:00
// and oil pressure
2018-04-30 17:17:22 +02:00
oilPressure_ . resize ( bufferSize , 0.0 );
2018-01-12 15:32:43 +01:00
2018-04-30 17:17:22 +02:00
if ( FluidSystem :: enableDissolvedGas ())
rs_ . resize ( bufferSize , 0.0 );
if ( FluidSystem :: enableVaporizedOil ())
rv_ . resize ( bufferSize , 0.0 );
2018-01-09 14:01:30 +01:00
2018-04-30 17:17:22 +02:00
if ( GET_PROP_VALUE ( TypeTag , EnableSolvent ))
sSol_ . resize ( bufferSize , 0.0 );
if ( GET_PROP_VALUE ( TypeTag , EnablePolymer ))
cPolymer_ . resize ( bufferSize , 0.0 );
2017-12-07 12:38:48 +01:00
2018-01-22 13:38:50 +01:00
if ( simulator_ . problem (). vapparsActive ())
2018-04-30 17:17:22 +02:00
soMax_ . resize ( bufferSize , 0.0 );
2018-01-22 13:38:50 +01:00
if ( simulator_ . problem (). materialLawManager () -> enableHysteresis ()) {
2018-04-30 17:17:22 +02:00
pcSwMdcOw_ . resize ( bufferSize , 0.0 );
krnSwMdcOw_ . resize ( bufferSize , 0.0 );
pcSwMdcGo_ . resize ( bufferSize , 0.0 );
krnSwMdcGo_ . resize ( bufferSize , 0.0 );
2018-01-12 15:32:43 +01:00
}
2017-12-07 12:38:48 +01:00
2018-09-07 10:19:00 +02:00
if ( simulator_ . vanguard (). eclState (). get3DProperties (). hasDeckDoubleGridProperty ( "SWATINIT" ))
ppcw_ . resize ( bufferSize , 0.0 );
2018-01-22 13:38:50 +01:00
if ( FluidSystem :: enableDissolvedGas () && rstKeywords [ "RSSAT" ] > 0 ) {
rstKeywords [ "RSSAT" ] = 0 ;
2018-04-30 17:17:22 +02:00
gasDissolutionFactor_ . resize ( bufferSize , 0.0 );
2018-01-19 15:45:42 +01:00
}
2018-01-22 13:38:50 +01:00
if ( FluidSystem :: enableVaporizedOil () && rstKeywords [ "RVSAT" ] > 0 ) {
rstKeywords [ "RVSAT" ] = 0 ;
2018-04-30 17:17:22 +02:00
oilVaporizationFactor_ . resize ( bufferSize , 0.0 );
2017-12-07 12:38:48 +01:00
}
2018-04-30 17:17:22 +02:00
if ( FluidSystem :: phaseIsActive ( waterPhaseIdx ) && rstKeywords [ "BW" ] > 0 ) {
2018-01-09 14:01:30 +01:00
rstKeywords [ "BW" ] = 0 ;
2018-04-30 17:17:22 +02:00
invB_ [ waterPhaseIdx ]. resize ( bufferSize , 0.0 );
2018-01-09 14:01:30 +01:00
}
2018-04-30 17:17:22 +02:00
if ( FluidSystem :: phaseIsActive ( oilPhaseIdx ) && rstKeywords [ "BO" ] > 0 ) {
2018-01-09 14:01:30 +01:00
rstKeywords [ "BO" ] = 0 ;
2018-04-30 17:17:22 +02:00
invB_ [ oilPhaseIdx ]. resize ( bufferSize , 0.0 );
2018-01-09 14:01:30 +01:00
}
2018-04-30 17:17:22 +02:00
if ( FluidSystem :: phaseIsActive ( gasPhaseIdx ) && rstKeywords [ "BG" ] > 0 ) {
2018-01-09 14:01:30 +01:00
rstKeywords [ "BG" ] = 0 ;
2018-04-30 17:17:22 +02:00
invB_ [ gasPhaseIdx ]. resize ( bufferSize , 0.0 );
2018-01-09 14:01:30 +01:00
}
if ( rstKeywords [ "DEN" ] > 0 ) {
2017-12-07 12:38:48 +01:00
rstKeywords [ "DEN" ] = 0 ;
for ( unsigned phaseIdx = 0 ; phaseIdx < numPhases ; ++ phaseIdx ) {
if ( ! FluidSystem :: phaseIsActive ( phaseIdx ))
continue ;
2018-04-30 17:17:22 +02:00
density_ [ phaseIdx ]. resize ( bufferSize , 0.0 );
2017-12-07 12:38:48 +01:00
}
}
2018-01-09 14:01:30 +01:00
const bool hasVWAT = ( rstKeywords [ "VISC" ] > 0 ) || ( rstKeywords [ "VWAT" ] > 0 );
const bool hasVOIL = ( rstKeywords [ "VISC" ] > 0 ) || ( rstKeywords [ "VOIL" ] > 0 );
const bool hasVGAS = ( rstKeywords [ "VISC" ] > 0 ) || ( rstKeywords [ "VGAS" ] > 0 );
rstKeywords [ "VISC" ] = 0 ;
2017-12-07 12:38:48 +01:00
2018-04-30 17:17:22 +02:00
if ( FluidSystem :: phaseIsActive ( waterPhaseIdx ) && hasVWAT ) {
2018-01-09 14:01:30 +01:00
rstKeywords [ "VWAT" ] = 0 ;
2018-04-30 17:17:22 +02:00
viscosity_ [ waterPhaseIdx ]. resize ( bufferSize , 0.0 );
2017-12-07 12:38:48 +01:00
}
2018-04-30 17:17:22 +02:00
if ( FluidSystem :: phaseIsActive ( oilPhaseIdx ) && hasVOIL > 0 ) {
2018-01-09 14:01:30 +01:00
rstKeywords [ "VOIL" ] = 0 ;
2018-04-30 17:17:22 +02:00
viscosity_ [ oilPhaseIdx ]. resize ( bufferSize , 0.0 );
2017-12-07 12:38:48 +01:00
}
2018-04-30 17:17:22 +02:00
if ( FluidSystem :: phaseIsActive ( gasPhaseIdx ) && hasVGAS > 0 ) {
2018-01-09 14:01:30 +01:00
rstKeywords [ "VGAS" ] = 0 ;
2018-04-30 17:17:22 +02:00
viscosity_ [ gasPhaseIdx ]. resize ( bufferSize , 0.0 );
2017-12-07 12:38:48 +01:00
}
2018-04-30 17:17:22 +02:00
if ( FluidSystem :: phaseIsActive ( waterPhaseIdx ) && rstKeywords [ "KRW" ] > 0 ) {
2019-04-23 08:56:06 +02:00
rstKeywords [ "KRW" ] = 0 ;
2018-04-30 17:17:22 +02:00
relativePermeability_ [ waterPhaseIdx ]. resize ( bufferSize , 0.0 );
2018-01-09 14:01:30 +01:00
}
2018-04-30 17:17:22 +02:00
if ( FluidSystem :: phaseIsActive ( oilPhaseIdx ) && rstKeywords [ "KRO" ] > 0 ) {
2018-01-09 14:01:30 +01:00
rstKeywords [ "KRO" ] = 0 ;
2018-04-30 17:17:22 +02:00
relativePermeability_ [ oilPhaseIdx ]. resize ( bufferSize , 0.0 );
2018-01-09 14:01:30 +01:00
}
2018-04-30 17:17:22 +02:00
if ( FluidSystem :: phaseIsActive ( gasPhaseIdx ) && rstKeywords [ "KRG" ] > 0 ) {
2018-01-09 14:01:30 +01:00
rstKeywords [ "KRG" ] = 0 ;
2018-04-30 17:17:22 +02:00
relativePermeability_ [ gasPhaseIdx ]. resize ( bufferSize , 0.0 );
2018-01-09 14:01:30 +01:00
}
2017-12-07 12:38:48 +01:00
if ( rstKeywords [ "PBPD" ] > 0 ) {
rstKeywords [ "PBPD" ] = 0 ;
2018-04-30 17:17:22 +02:00
bubblePointPressure_ . resize ( bufferSize , 0.0 );
dewPointPressure_ . resize ( bufferSize , 0.0 );
2017-12-07 12:38:48 +01:00
}
2018-11-14 13:10:01 +01:00
// tracers
const int numTracers = simulator_ . problem (). tracerModel (). numTracers ();
if ( numTracers > 0 ){
tracerConcentrations_ . resize ( numTracers );
for ( int tracerIdx = 0 ; tracerIdx < numTracers ; ++ tracerIdx )
{
tracerConcentrations_ [ tracerIdx ]. resize ( bufferSize , 0.0 );
}
}
2019-03-12 15:51:41 +01:00
// ROCKC
if ( rstKeywords [ "ROCKC" ] > 0 ) {
rstKeywords [ "ROCKC" ] = 0 ;
rockCompPorvMultiplier_ . resize ( bufferSize , 0.0 );
rockCompTransMultiplier_ . resize ( bufferSize , 0.0 );
swMax_ . resize ( bufferSize , 0.0 );
minimumOilPressure_ . resize ( bufferSize , 0.0 );
overburdenPressure_ . resize ( bufferSize , 0.0 );
}
2017-12-07 12:38:48 +01:00
//Warn for any unhandled keyword
if ( log ) {
2018-04-30 17:17:22 +02:00
for ( auto & keyValue : rstKeywords ) {
2017-12-07 12:38:48 +01:00
if ( keyValue . second > 0 ) {
std :: string logstring = "Keyword '" ;
logstring . append ( keyValue . first );
logstring . append ( "' is unhandled for output to file." );
Opm :: OpmLog :: warning ( "Unhandled output keyword" , logstring );
}
}
}
failedCellsPb_ . clear ();
failedCellsPd_ . clear ();
2018-01-09 14:01:30 +01:00
// Not supported in flow legacy
if ( false )
2018-04-30 17:17:22 +02:00
saturatedOilFormationVolumeFactor_ . resize ( bufferSize , 0.0 );
2018-01-09 14:01:30 +01:00
if ( false )
2018-04-30 17:17:22 +02:00
oilSaturationPressure_ . resize ( bufferSize , 0.0 );
2018-11-14 13:10:01 +01:00
2014-11-28 12:58:48 +01:00
}
/*!
* \brief Modify the internal buffers according to the intensive quanties relevant
* for an element
*/
2016-11-07 15:14:07 +01:00
void processElement ( const ElementContext & elemCtx )
2014-11-28 12:58:48 +01:00
{
if ( ! std :: is_same < Discretization , Ewoms :: EcfvDiscretization < TypeTag > >:: value )
return ;
2019-03-12 15:51:41 +01:00
const auto & problem = elemCtx . simulator (). problem ();
2015-11-18 11:54:35 +01:00
for ( unsigned dofIdx = 0 ; dofIdx < elemCtx . numPrimaryDof ( /*timeIdx=*/ 0 ); ++ dofIdx ) {
2017-12-07 12:38:48 +01:00
const auto & intQuants = elemCtx . intensiveQuantities ( dofIdx , /*timeIdx=*/ 0 );
const auto & fs = intQuants . fluidState ();
2018-01-12 15:32:43 +01:00
2016-01-04 15:32:55 +01:00
typedef typename std :: remove_const < typename std :: remove_reference < decltype ( fs ) >:: type >:: type FluidState ;
2015-11-18 11:54:35 +01:00
unsigned globalDofIdx = elemCtx . globalSpaceIndex ( dofIdx , /*timeIdx=*/ 0 );
2015-12-31 13:20:41 +01:00
unsigned pvtRegionIdx = elemCtx . primaryVars ( dofIdx , /*timeIdx=*/ 0 ). pvtRegionIndex ();
2014-11-28 12:58:48 +01:00
2018-01-09 14:01:30 +01:00
for ( unsigned phaseIdx = 0 ; phaseIdx < numPhases ; ++ phaseIdx ) {
if ( saturation_ [ phaseIdx ]. size () == 0 )
continue ;
2016-11-15 18:00:48 +01:00
2018-01-29 08:43:42 +01:00
saturation_ [ phaseIdx ][ globalDofIdx ] = Opm :: getValue ( fs . saturation ( phaseIdx ));
2018-01-09 14:01:30 +01:00
Opm :: Valgrind :: CheckDefined ( saturation_ [ phaseIdx ][ globalDofIdx ]);
2014-11-28 12:58:48 +01:00
}
2018-01-09 14:01:30 +01:00
2017-12-07 12:38:48 +01:00
if ( oilPressure_ . size () > 0 ) {
2018-01-29 08:43:42 +01:00
oilPressure_ [ globalDofIdx ] = Opm :: getValue ( fs . pressure ( oilPhaseIdx ));
2017-12-07 12:38:48 +01:00
Opm :: Valgrind :: CheckDefined ( oilPressure_ [ globalDofIdx ]);
2018-01-31 11:10:37 +01:00
}
2016-11-15 18:00:48 +01:00
2018-12-17 11:37:07 +01:00
if ( enableEnergy ) {
2018-01-31 11:10:37 +01:00
temperature_ [ globalDofIdx ] = Opm :: getValue ( fs . temperature ( oilPhaseIdx ));
Opm :: Valgrind :: CheckDefined ( temperature_ [ globalDofIdx ]);
2014-11-28 12:58:48 +01:00
}
2017-12-07 12:38:48 +01:00
if ( gasDissolutionFactor_ . size () > 0 ) {
2017-12-19 18:00:14 +01:00
Scalar SoMax = elemCtx . problem (). maxOilSaturation ( globalDofIdx );
2014-11-28 12:58:48 +01:00
gasDissolutionFactor_ [ globalDofIdx ] =
2017-12-07 12:38:48 +01:00
FluidSystem :: template saturatedDissolutionFactor < FluidState , Scalar > ( fs , oilPhaseIdx , pvtRegionIdx , SoMax );
2017-02-09 18:25:44 +01:00
Opm :: Valgrind :: CheckDefined ( gasDissolutionFactor_ [ globalDofIdx ]);
2017-12-07 12:38:48 +01:00
2014-11-28 12:58:48 +01:00
}
2017-12-07 12:38:48 +01:00
if ( oilVaporizationFactor_ . size () > 0 ) {
2017-12-19 18:00:14 +01:00
Scalar SoMax = elemCtx . problem (). maxOilSaturation ( globalDofIdx );
2017-12-07 12:38:48 +01:00
oilVaporizationFactor_ [ globalDofIdx ] =
FluidSystem :: template saturatedDissolutionFactor < FluidState , Scalar > ( fs , gasPhaseIdx , pvtRegionIdx , SoMax );
Opm :: Valgrind :: CheckDefined ( oilVaporizationFactor_ [ globalDofIdx ]);
2016-11-15 18:00:48 +01:00
}
2017-12-07 12:38:48 +01:00
if ( gasFormationVolumeFactor_ . size () > 0 ) {
2015-01-26 11:55:37 +01:00
gasFormationVolumeFactor_ [ globalDofIdx ] =
2016-01-29 11:57:41 +01:00
1.0 / FluidSystem :: template inverseFormationVolumeFactor < FluidState , Scalar > ( fs , gasPhaseIdx , pvtRegionIdx );
2017-02-09 18:25:44 +01:00
Opm :: Valgrind :: CheckDefined ( gasFormationVolumeFactor_ [ globalDofIdx ]);
2017-12-07 12:38:48 +01:00
2014-11-28 12:58:48 +01:00
}
2017-12-07 12:38:48 +01:00
if ( saturatedOilFormationVolumeFactor_ . size () > 0 ) {
saturatedOilFormationVolumeFactor_ [ globalDofIdx ] =
1.0 / FluidSystem :: template saturatedInverseFormationVolumeFactor < FluidState , Scalar > ( fs , oilPhaseIdx , pvtRegionIdx );
Opm :: Valgrind :: CheckDefined ( saturatedOilFormationVolumeFactor_ [ globalDofIdx ]);
}
if ( oilSaturationPressure_ . size () > 0 ) {
2014-11-28 12:58:48 +01:00
oilSaturationPressure_ [ globalDofIdx ] =
2015-12-31 13:20:41 +01:00
FluidSystem :: template saturationPressure < FluidState , Scalar > ( fs , oilPhaseIdx , pvtRegionIdx );
2017-02-09 18:25:44 +01:00
Opm :: Valgrind :: CheckDefined ( oilSaturationPressure_ [ globalDofIdx ]);
2017-12-07 12:38:48 +01:00
}
if ( rs_ . size ()) {
2018-01-29 08:43:42 +01:00
rs_ [ globalDofIdx ] = Opm :: getValue ( fs . Rs ());
2017-12-07 12:38:48 +01:00
Opm :: Valgrind :: CheckDefined ( rs_ [ globalDofIdx ]);
}
if ( rv_ . size ()) {
2018-01-29 08:43:42 +01:00
rv_ [ globalDofIdx ] = Opm :: getValue ( fs . Rv ());
2017-12-07 12:38:48 +01:00
Opm :: Valgrind :: CheckDefined ( rv_ [ globalDofIdx ]);
2014-11-28 12:58:48 +01:00
}
2017-12-07 12:38:48 +01:00
2018-01-09 14:01:30 +01:00
for ( unsigned phaseIdx = 0 ; phaseIdx < numPhases ; ++ phaseIdx ) {
if ( invB_ [ phaseIdx ]. size () == 0 )
continue ;
2017-12-07 12:38:48 +01:00
2018-01-29 08:43:42 +01:00
invB_ [ phaseIdx ][ globalDofIdx ] = Opm :: getValue ( fs . invB ( phaseIdx ));
2018-01-09 14:01:30 +01:00
Opm :: Valgrind :: CheckDefined ( invB_ [ phaseIdx ][ globalDofIdx ]);
2017-12-07 12:38:48 +01:00
}
2018-01-09 14:01:30 +01:00
for ( unsigned phaseIdx = 0 ; phaseIdx < numPhases ; ++ phaseIdx ) {
if ( density_ [ phaseIdx ]. size () == 0 )
continue ;
2017-12-07 12:38:48 +01:00
2018-01-29 08:43:42 +01:00
density_ [ phaseIdx ][ globalDofIdx ] = Opm :: getValue ( fs . density ( phaseIdx ));
2018-01-09 14:01:30 +01:00
Opm :: Valgrind :: CheckDefined ( density_ [ phaseIdx ][ globalDofIdx ]);
2017-12-07 12:38:48 +01:00
}
2018-01-09 14:01:30 +01:00
for ( unsigned phaseIdx = 0 ; phaseIdx < numPhases ; ++ phaseIdx ) {
if ( viscosity_ [ phaseIdx ]. size () == 0 )
continue ;
2017-12-07 12:38:48 +01:00
2018-01-29 08:43:42 +01:00
viscosity_ [ phaseIdx ][ globalDofIdx ] = Opm :: getValue ( fs . viscosity ( phaseIdx ));
2018-01-09 14:01:30 +01:00
Opm :: Valgrind :: CheckDefined ( viscosity_ [ phaseIdx ][ globalDofIdx ]);
2017-12-07 12:38:48 +01:00
}
2018-01-09 14:01:30 +01:00
for ( unsigned phaseIdx = 0 ; phaseIdx < numPhases ; ++ phaseIdx ) {
if ( relativePermeability_ [ phaseIdx ]. size () == 0 )
continue ;
2017-12-07 12:38:48 +01:00
2018-01-29 08:43:42 +01:00
relativePermeability_ [ phaseIdx ][ globalDofIdx ] = Opm :: getValue ( intQuants . relativePermeability ( phaseIdx ));
2018-01-09 14:01:30 +01:00
Opm :: Valgrind :: CheckDefined ( relativePermeability_ [ phaseIdx ][ globalDofIdx ]);
2017-12-07 12:38:48 +01:00
}
if ( sSol_ . size () > 0 ) {
sSol_ [ globalDofIdx ] = intQuants . solventSaturation (). value ();
}
if ( cPolymer_ . size () > 0 ) {
cPolymer_ [ globalDofIdx ] = intQuants . polymerConcentration (). value ();
}
2018-04-30 17:17:22 +02:00
if ( bubblePointPressure_ . size () > 0 ) {
2017-12-07 12:38:48 +01:00
try {
2018-01-29 08:43:42 +01:00
bubblePointPressure_ [ globalDofIdx ] = Opm :: getValue ( FluidSystem :: bubblePointPressure ( fs , intQuants . pvtRegionIndex ()));
2017-12-07 12:38:48 +01:00
}
2018-03-03 13:06:58 +01:00
catch ( const Opm :: NumericalIssue & ) {
2018-04-30 17:17:22 +02:00
const auto cartesianIdx = elemCtx . simulator (). vanguard (). grid (). globalCell ()[ globalDofIdx ];
failedCellsPb_ . push_back ( cartesianIdx );
2017-12-07 12:38:48 +01:00
}
}
2018-04-30 17:17:22 +02:00
if ( dewPointPressure_ . size () > 0 ) {
2017-12-07 12:38:48 +01:00
try {
2018-01-29 08:43:42 +01:00
dewPointPressure_ [ globalDofIdx ] = Opm :: getValue ( FluidSystem :: dewPointPressure ( fs , intQuants . pvtRegionIndex ()));
2017-12-07 12:38:48 +01:00
}
2018-03-03 13:06:58 +01:00
catch ( const Opm :: NumericalIssue & ) {
2018-04-30 17:17:22 +02:00
const auto cartesianIdx = elemCtx . simulator (). vanguard (). grid (). globalCell ()[ globalDofIdx ];
failedCellsPd_ . push_back ( cartesianIdx );
2017-12-07 12:38:48 +01:00
}
}
if ( soMax_ . size () > 0 )
2019-03-12 15:51:41 +01:00
soMax_ [ globalDofIdx ] =
std :: max ( Opm :: getValue ( fs . saturation ( oilPhaseIdx )),
problem . maxOilSaturation ( globalDofIdx ));
if ( swMax_ . size () > 0 )
swMax_ [ globalDofIdx ] =
std :: max ( Opm :: getValue ( fs . saturation ( waterPhaseIdx )),
problem . maxWaterSaturation ( globalDofIdx ));
if ( minimumOilPressure_ . size () > 0 )
minimumOilPressure_ [ globalDofIdx ] =
std :: min ( Opm :: getValue ( fs . pressure ( oilPhaseIdx )),
problem . minOilPressure ( globalDofIdx ));
2017-12-07 12:38:48 +01:00
2019-03-12 15:51:41 +01:00
if ( overburdenPressure_ . size () > 0 )
overburdenPressure_ [ globalDofIdx ] = problem . overburdenPressure ( globalDofIdx );
if ( rockCompPorvMultiplier_ . size () > 0 )
rockCompPorvMultiplier_ [ globalDofIdx ] = problem . template rockCompPoroMultiplier < Scalar > ( intQuants , globalDofIdx );
if ( rockCompTransMultiplier_ . size () > 0 )
rockCompTransMultiplier_ [ globalDofIdx ] = problem . template rockCompTransMultiplier < Scalar > ( intQuants , globalDofIdx );
const auto & matLawManager = problem . materialLawManager ();
2018-01-09 14:01:30 +01:00
if ( matLawManager -> enableHysteresis ()) {
if ( pcSwMdcOw_ . size () > 0 && krnSwMdcOw_ . size () > 0 ) {
2017-12-07 12:38:48 +01:00
matLawManager -> oilWaterHysteresisParams (
pcSwMdcOw_ [ globalDofIdx ],
krnSwMdcOw_ [ globalDofIdx ],
globalDofIdx );
2018-01-09 14:01:30 +01:00
}
if ( pcSwMdcGo_ . size () > 0 && krnSwMdcGo_ . size () > 0 ) {
2017-12-07 12:38:48 +01:00
matLawManager -> gasOilHysteresisParams (
pcSwMdcGo_ [ globalDofIdx ],
krnSwMdcGo_ [ globalDofIdx ],
globalDofIdx );
}
}
2018-09-07 10:19:00 +02:00
if ( ppcw_ . size () > 0 )
ppcw_ [ globalDofIdx ] = matLawManager -> oilWaterScaledEpsInfoDrainage ( globalDofIdx ). maxPcow ;
2017-12-07 12:38:48 +01:00
// hack to make the intial output of rs and rv Ecl compatible.
// For cells with swat == 1 Ecl outputs; rs = rsSat and rv=rvSat, in all but the initial step
// where it outputs rs and rv values calculated by the initialization. To be compatible we overwrite
// rs and rv with the values computed in the initially.
// Volume factors, densities and viscosities need to be recalculated with the updated rs and rv values.
// This can be removed when ebos has 100% controll over output
2018-04-30 17:17:22 +02:00
if ( elemCtx . simulator (). episodeIndex () < 0 && FluidSystem :: phaseIsActive ( oilPhaseIdx ) && FluidSystem :: phaseIsActive ( gasPhaseIdx )) {
2017-12-07 12:38:48 +01:00
2019-03-12 15:51:41 +01:00
const auto & fsInitial = problem . initialFluidState ( globalDofIdx );
2017-12-07 12:38:48 +01:00
// use initial rs and rv values
2018-01-09 14:01:30 +01:00
if ( rv_ . size () > 0 )
2018-04-30 17:17:22 +02:00
rv_ [ globalDofIdx ] = fsInitial . Rv ();
2018-01-09 14:01:30 +01:00
if ( rs_ . size () > 0 )
2018-04-30 17:17:22 +02:00
rs_ [ globalDofIdx ] = fsInitial . Rs ();
2017-12-07 12:38:48 +01:00
// re-compute the volume factors, viscosities and densities if asked for
if ( density_ [ oilPhaseIdx ]. size () > 0 )
2018-04-30 17:17:22 +02:00
density_ [ oilPhaseIdx ][ globalDofIdx ] = FluidSystem :: density ( fsInitial ,
oilPhaseIdx ,
intQuants . pvtRegionIndex ());
2017-12-07 12:38:48 +01:00
if ( density_ [ gasPhaseIdx ]. size () > 0 )
2018-04-30 17:17:22 +02:00
density_ [ gasPhaseIdx ][ globalDofIdx ] = FluidSystem :: density ( fsInitial ,
gasPhaseIdx ,
intQuants . pvtRegionIndex ());
2017-12-07 12:38:48 +01:00
if ( invB_ [ oilPhaseIdx ]. size () > 0 )
2018-04-30 17:17:22 +02:00
invB_ [ oilPhaseIdx ][ globalDofIdx ] = FluidSystem :: inverseFormationVolumeFactor ( fsInitial ,
oilPhaseIdx ,
intQuants . pvtRegionIndex ());
2017-12-07 12:38:48 +01:00
if ( invB_ [ gasPhaseIdx ]. size () > 0 )
2018-04-30 17:17:22 +02:00
invB_ [ gasPhaseIdx ][ globalDofIdx ] = FluidSystem :: inverseFormationVolumeFactor ( fsInitial ,
gasPhaseIdx ,
intQuants . pvtRegionIndex ());
2017-12-07 12:38:48 +01:00
if ( viscosity_ [ oilPhaseIdx ]. size () > 0 )
2018-04-30 17:17:22 +02:00
viscosity_ [ oilPhaseIdx ][ globalDofIdx ] = FluidSystem :: viscosity ( fsInitial ,
oilPhaseIdx ,
intQuants . pvtRegionIndex ());
2017-12-07 12:38:48 +01:00
if ( viscosity_ [ gasPhaseIdx ]. size () > 0 )
2018-04-30 17:17:22 +02:00
viscosity_ [ gasPhaseIdx ][ globalDofIdx ] = FluidSystem :: viscosity ( fsInitial ,
gasPhaseIdx ,
intQuants . pvtRegionIndex ());
2017-12-07 12:38:48 +01:00
}
2018-01-29 08:43:42 +01:00
// Add fluid in Place values
updateFluidInPlace_ ( elemCtx , dofIdx );
2018-01-12 15:32:43 +01:00
2018-02-09 12:57:34 +01:00
// Adding block data
2018-04-30 17:17:22 +02:00
const auto cartesianIdx = elemCtx . simulator (). vanguard (). grid (). globalCell ()[ globalDofIdx ];
for ( auto & val : blockData_ ) {
2018-01-23 09:46:56 +01:00
const auto & key = val . first ;
2018-04-30 17:17:22 +02:00
int cartesianIdxBlock = key . second - 1 ;
if ( cartesianIdx == cartesianIdxBlock ) {
if ( key . first == "BWSAT" )
2018-01-29 08:43:42 +01:00
val . second = Opm :: getValue ( fs . saturation ( waterPhaseIdx ));
2018-04-30 17:17:22 +02:00
else if ( key . first == "BGSAT" )
2018-01-29 08:43:42 +01:00
val . second = Opm :: getValue ( fs . saturation ( gasPhaseIdx ));
2019-06-03 11:11:41 +02:00
else if ( key . first == "BOSAT" )
2019-04-12 16:48:27 +02:00
val . second = 1. - Opm :: getValue ( fs . saturation ( gasPhaseIdx )) - Opm :: getValue ( fs . saturation ( waterPhaseIdx ));
2018-04-30 17:17:22 +02:00
else if ( key . first == "BPR" )
2018-01-29 08:43:42 +01:00
val . second = Opm :: getValue ( fs . pressure ( oilPhaseIdx ));
2019-06-03 11:11:41 +02:00
else if ( key . first == "BWKR" || key . first == "BKRW" )
2019-04-12 16:48:27 +02:00
val . second = Opm :: getValue ( intQuants . relativePermeability ( waterPhaseIdx ));
2019-06-03 11:11:41 +02:00
else if ( key . first == "BGKR" || key . first == "BKRG" )
2019-04-12 16:48:27 +02:00
val . second = Opm :: getValue ( intQuants . relativePermeability ( gasPhaseIdx ));
2019-06-03 11:11:41 +02:00
else if ( key . first == "BOKR" || key . first == "BKRO" )
2019-04-12 16:48:27 +02:00
val . second = Opm :: getValue ( intQuants . relativePermeability ( oilPhaseIdx ));
2019-06-03 11:11:41 +02:00
else if ( key . first == "BWPC" )
2019-04-12 16:48:27 +02:00
val . second = Opm :: getValue ( fs . pressure ( oilPhaseIdx )) - Opm :: getValue ( fs . pressure ( waterPhaseIdx ));
2019-06-03 11:11:41 +02:00
else if ( key . first == "BGPC" )
2019-04-12 16:48:27 +02:00
val . second = Opm :: getValue ( fs . pressure ( gasPhaseIdx )) - Opm :: getValue ( fs . pressure ( oilPhaseIdx ));
2019-06-03 11:11:41 +02:00
else if ( key . first == "BVWAT" || key . first == "BWVIS" )
2019-04-12 16:48:27 +02:00
val . second = Opm :: getValue ( fs . viscosity ( waterPhaseIdx ));
2019-06-03 11:11:41 +02:00
else if ( key . first == "BVGAS" || key . first == "BGVIS" )
2019-04-12 16:48:27 +02:00
val . second = Opm :: getValue ( fs . viscosity ( gasPhaseIdx ));
2019-06-03 11:11:41 +02:00
else if ( key . first == "BVOIL" || key . first == "BOVIS" )
2019-04-12 16:48:27 +02:00
val . second = Opm :: getValue ( fs . viscosity ( oilPhaseIdx ));
2018-04-30 17:17:22 +02:00
else {
2018-01-23 09:46:56 +01:00
std :: string logstring = "Keyword '" ;
logstring . append ( key . first );
logstring . append ( "' is unhandled for output to file." );
Opm :: OpmLog :: warning ( "Unhandled output keyword" , logstring );
2018-01-19 15:45:42 +01:00
}
}
}
2018-02-07 14:30:43 +01:00
// Adding Well RFT data
2018-06-28 15:49:45 +02:00
if ( oilConnectionPressures_ . count ( cartesianIdx ) > 0 ) {
oilConnectionPressures_ [ cartesianIdx ] = Opm :: getValue ( fs . pressure ( oilPhaseIdx ));
2018-02-07 14:30:43 +01:00
}
2018-06-28 15:49:45 +02:00
if ( waterConnectionSaturations_ . count ( cartesianIdx ) > 0 ) {
waterConnectionSaturations_ [ cartesianIdx ] = Opm :: getValue ( fs . saturation ( waterPhaseIdx ));
2018-02-07 14:30:43 +01:00
}
2018-06-28 15:49:45 +02:00
if ( gasConnectionSaturations_ . count ( cartesianIdx ) > 0 ) {
gasConnectionSaturations_ [ cartesianIdx ] = Opm :: getValue ( fs . saturation ( gasPhaseIdx ));
2018-02-07 14:30:43 +01:00
}
2018-11-14 13:10:01 +01:00
// tracers
const auto & tracerModel = simulator_ . problem (). tracerModel ();
if ( tracerConcentrations_ . size () > 0 ) {
for ( int tracerIdx = 0 ; tracerIdx < tracerModel . numTracers (); tracerIdx ++ ){
if ( tracerConcentrations_ [ tracerIdx ]. size () == 0 )
continue ;
tracerConcentrations_ [ tracerIdx ][ globalDofIdx ] = tracerModel . tracerConcentration ( tracerIdx , globalDofIdx );
}
}
2017-12-07 12:38:48 +01:00
}
}
void outputErrorLog ()
{
const size_t maxNumCellsFaillog = 20 ;
2018-04-30 17:17:22 +02:00
int pbSize = failedCellsPb_ . size (), pdSize = failedCellsPd_ . size ();
2017-12-07 12:38:48 +01:00
std :: vector < int > displPb , displPd , recvLenPb , recvLenPd ;
const auto & comm = simulator_ . gridView (). comm ();
2018-04-30 17:17:22 +02:00
if ( isIORank_ ()) {
2017-12-07 12:38:48 +01:00
displPb . resize ( comm . size () + 1 , 0 );
displPd . resize ( comm . size () + 1 , 0 );
recvLenPb . resize ( comm . size ());
recvLenPd . resize ( comm . size ());
}
comm . gather ( & pbSize , recvLenPb . data (), 1 , 0 );
2018-04-30 17:17:22 +02:00
comm . gather ( & pdSize , recvLenPd . data (), 1 , 0 );
2017-12-07 12:38:48 +01:00
std :: partial_sum ( recvLenPb . begin (), recvLenPb . end (), displPb . begin () + 1 );
std :: partial_sum ( recvLenPd . begin (), recvLenPd . end (), displPd . begin () + 1 );
std :: vector < int > globalFailedCellsPb , globalFailedCellsPd ;
2018-04-30 17:17:22 +02:00
if ( isIORank_ ()) {
2017-12-07 12:38:48 +01:00
globalFailedCellsPb . resize ( displPb . back ());
globalFailedCellsPd . resize ( displPd . back ());
}
comm . gatherv ( failedCellsPb_ . data (), static_cast < int > ( failedCellsPb_ . size ()),
globalFailedCellsPb . data (), recvLenPb . data (),
displPb . data (), 0 );
comm . gatherv ( failedCellsPd_ . data (), static_cast < int > ( failedCellsPd_ . size ()),
globalFailedCellsPd . data (), recvLenPd . data (),
displPd . data (), 0 );
std :: sort ( globalFailedCellsPb . begin (), globalFailedCellsPb . end ());
std :: sort ( globalFailedCellsPd . begin (), globalFailedCellsPd . end ());
if ( globalFailedCellsPb . size () > 0 ) {
std :: stringstream errlog ;
errlog << "Finding the bubble point pressure failed for " << globalFailedCellsPb . size () << " cells [" ;
errlog << globalFailedCellsPb [ 0 ];
2018-04-30 17:17:22 +02:00
const size_t maxElems = std :: min ( maxNumCellsFaillog , globalFailedCellsPb . size ());
for ( size_t i = 1 ; i < maxElems ; ++ i ) {
2017-12-07 12:38:48 +01:00
errlog << ", " << globalFailedCellsPb [ i ];
}
if ( globalFailedCellsPb . size () > maxNumCellsFaillog ) {
errlog << ", ..." ;
}
errlog << "]" ;
Opm :: OpmLog :: warning ( "Bubble point numerical problem" , errlog . str ());
}
if ( globalFailedCellsPd . size () > 0 ) {
std :: stringstream errlog ;
errlog << "Finding the dew point pressure failed for " << globalFailedCellsPd . size () << " cells [" ;
errlog << globalFailedCellsPd [ 0 ];
2018-04-30 17:17:22 +02:00
const size_t maxElems = std :: min ( maxNumCellsFaillog , globalFailedCellsPd . size ());
for ( size_t i = 1 ; i < maxElems ; ++ i ) {
2017-12-07 12:38:48 +01:00
errlog << ", " << globalFailedCellsPd [ i ];
}
if ( globalFailedCellsPd . size () > maxNumCellsFaillog ) {
errlog << ", ..." ;
}
errlog << "]" ;
Opm :: OpmLog :: warning ( "Dew point numerical problem" , errlog . str ());
2014-11-28 12:58:48 +01:00
}
}
2018-02-07 14:30:43 +01:00
void addRftDataToWells ( Opm :: data :: Wells & wellDatas , size_t reportStepNum )
2018-03-12 14:31:36 +01:00
{
2019-04-04 07:27:39 +02:00
const auto & schedule = simulator_ . vanguard (). schedule ();
const auto & rft_config = schedule . rftConfig ();
2019-05-02 12:51:25 +02:00
for ( const auto & well : schedule . getWells2 ( reportStepNum )) {
2018-02-07 14:30:43 +01:00
// don't bother with wells not on this process
2018-04-30 17:17:22 +02:00
const auto & defunctWellNames = simulator_ . vanguard (). defunctWellNames ();
2019-05-02 12:51:25 +02:00
if ( defunctWellNames . find ( well . name ()) != defunctWellNames . end ()) {
2018-02-07 14:30:43 +01:00
continue ;
}
//add data infrastructure for shut wells
2019-05-02 12:51:25 +02:00
if ( ! wellDatas . count ( well . name ())) {
2018-02-07 14:30:43 +01:00
Opm :: data :: Well wellData ;
2019-04-04 07:27:39 +02:00
if ( ! rft_config . active ( reportStepNum ))
2018-02-07 14:30:43 +01:00
continue ;
2019-04-04 07:27:39 +02:00
2019-05-02 12:51:25 +02:00
wellData . connections . resize ( well . getConnections (). size ());
2018-02-07 14:30:43 +01:00
size_t count = 0 ;
2019-05-02 12:51:25 +02:00
for ( const auto & connection : well . getConnections ()) {
2018-06-28 15:49:45 +02:00
const size_t i = size_t ( connection . getI ());
const size_t j = size_t ( connection . getJ ());
const size_t k = size_t ( connection . getK ());
2018-02-07 14:30:43 +01:00
2018-04-30 17:17:22 +02:00
const size_t index = simulator_ . vanguard (). eclState (). getInputGrid (). getGlobalIndex ( i , j , k );
2018-06-28 15:49:45 +02:00
auto & connectionData = wellData . connections [ count ];
connectionData . index = index ;
2018-02-07 14:30:43 +01:00
count ++ ;
}
2019-05-02 12:51:25 +02:00
wellDatas . emplace ( std :: make_pair ( well . name (), wellData ));
2018-02-07 14:30:43 +01:00
}
2019-05-02 12:51:25 +02:00
Opm :: data :: Well & wellData = wellDatas . at ( well . name ());
2018-06-28 15:49:45 +02:00
for ( auto & connectionData : wellData . connections ) {
const auto index = connectionData . index ;
if ( oilConnectionPressures_ . count ( index ) > 0 )
connectionData . cell_pressure = oilConnectionPressures_ . at ( index );
if ( waterConnectionSaturations_ . count ( index ) > 0 )
connectionData . cell_saturation_water = waterConnectionSaturations_ . at ( index );
if ( gasConnectionSaturations_ . count ( index ) > 0 )
connectionData . cell_saturation_gas = gasConnectionSaturations_ . at ( index );
2018-02-07 14:30:43 +01:00
}
}
2018-06-28 15:49:45 +02:00
oilConnectionPressures_ . clear ();
waterConnectionSaturations_ . clear ();
gasConnectionSaturations_ . clear ();
2018-02-07 14:30:43 +01:00
}
2014-11-28 12:58:48 +01:00
/*!
2018-01-09 11:28:20 +01:00
* \brief Move all buffers to data::Solution.
2014-11-28 12:58:48 +01:00
*/
2017-12-07 12:38:48 +01:00
void assignToSolution ( Opm :: data :: Solution & sol )
2014-11-28 12:58:48 +01:00
{
2018-04-30 17:17:22 +02:00
if ( ! std :: is_same < Discretization , Ewoms :: EcfvDiscretization < TypeTag >>:: value )
2014-11-28 12:58:48 +01:00
return ;
2018-04-30 17:17:22 +02:00
if ( oilPressure_ . size () > 0 ) {
sol . insert ( "PRESSURE" , Opm :: UnitSystem :: measure :: pressure , std :: move ( oilPressure_ ), Opm :: data :: TargetType :: RESTART_SOLUTION );
2017-12-07 12:38:48 +01:00
}
2014-11-28 12:58:48 +01:00
2018-11-16 14:51:07 +01:00
if ( enableEnergy ) {
2018-04-30 17:17:22 +02:00
sol . insert ( "TEMP" , Opm :: UnitSystem :: measure :: temperature , std :: move ( temperature_ ), Opm :: data :: TargetType :: RESTART_SOLUTION );
2017-12-07 12:38:48 +01:00
}
2015-01-25 17:27:08 +01:00
2018-04-30 17:17:22 +02:00
if ( FluidSystem :: phaseIsActive ( waterPhaseIdx ) && saturation_ [ waterPhaseIdx ]. size () > 0 ) {
sol . insert ( "SWAT" , Opm :: UnitSystem :: measure :: identity , std :: move ( saturation_ [ waterPhaseIdx ]), Opm :: data :: TargetType :: RESTART_SOLUTION );
2017-12-07 12:38:48 +01:00
}
2018-04-30 17:17:22 +02:00
if ( FluidSystem :: phaseIsActive ( gasPhaseIdx ) && saturation_ [ gasPhaseIdx ]. size () > 0 ) {
sol . insert ( "SGAS" , Opm :: UnitSystem :: measure :: identity , std :: move ( saturation_ [ gasPhaseIdx ]), Opm :: data :: TargetType :: RESTART_SOLUTION );
2018-01-09 14:01:30 +01:00
}
2018-09-07 10:19:00 +02:00
if ( ppcw_ . size () > 0 ) {
sol . insert ( "PPCW" , Opm :: UnitSystem :: measure :: pressure , std :: move ( ppcw_ ), Opm :: data :: TargetType :: RESTART_SOLUTION );
2018-09-04 09:07:18 +02:00
}
2018-01-09 14:01:30 +01:00
2018-04-30 17:17:22 +02:00
if ( gasDissolutionFactor_ . size () > 0 ) {
sol . insert ( "RSSAT" , Opm :: UnitSystem :: measure :: gas_oil_ratio , std :: move ( gasDissolutionFactor_ ), Opm :: data :: TargetType :: RESTART_AUXILIARY );
2017-12-07 12:38:48 +01:00
}
2018-04-30 17:17:22 +02:00
if ( oilVaporizationFactor_ . size () > 0 ) {
sol . insert ( "RVSAT" , Opm :: UnitSystem :: measure :: oil_gas_ratio , std :: move ( oilVaporizationFactor_ ), Opm :: data :: TargetType :: RESTART_AUXILIARY );
2017-12-07 12:38:48 +01:00
}
2018-04-30 17:17:22 +02:00
if ( rs_ . size () > 0 ) {
sol . insert ( "RS" , Opm :: UnitSystem :: measure :: gas_oil_ratio , std :: move ( rs_ ), Opm :: data :: TargetType :: RESTART_SOLUTION );
2017-12-07 12:38:48 +01:00
}
2018-04-30 17:17:22 +02:00
if ( rv_ . size () > 0 ) {
sol . insert ( "RV" , Opm :: UnitSystem :: measure :: oil_gas_ratio , std :: move ( rv_ ), Opm :: data :: TargetType :: RESTART_SOLUTION );
2017-12-07 12:38:48 +01:00
}
2018-04-30 17:17:22 +02:00
if ( invB_ [ waterPhaseIdx ]. size () > 0 ) {
sol . insert ( "1OVERBW" , Opm :: UnitSystem :: measure :: water_inverse_formation_volume_factor , std :: move ( invB_ [ waterPhaseIdx ]), Opm :: data :: TargetType :: RESTART_AUXILIARY );
2017-12-07 12:38:48 +01:00
}
2018-04-30 17:17:22 +02:00
if ( invB_ [ oilPhaseIdx ]. size () > 0 ) {
sol . insert ( "1OVERBO" , Opm :: UnitSystem :: measure :: oil_inverse_formation_volume_factor , std :: move ( invB_ [ oilPhaseIdx ]), Opm :: data :: TargetType :: RESTART_AUXILIARY );
2017-12-07 12:38:48 +01:00
}
2018-04-30 17:17:22 +02:00
if ( invB_ [ gasPhaseIdx ]. size () > 0 ) {
sol . insert ( "1OVERBG" , Opm :: UnitSystem :: measure :: gas_inverse_formation_volume_factor , std :: move ( invB_ [ gasPhaseIdx ]), Opm :: data :: TargetType :: RESTART_AUXILIARY );
2017-12-07 12:38:48 +01:00
}
2018-01-09 14:01:30 +01:00
2018-04-30 17:17:22 +02:00
if ( density_ [ waterPhaseIdx ]. size () > 0 ) {
sol . insert ( "WAT_DEN" , Opm :: UnitSystem :: measure :: density , std :: move ( density_ [ waterPhaseIdx ]), Opm :: data :: TargetType :: RESTART_AUXILIARY );
2018-01-09 14:01:30 +01:00
}
2018-04-30 17:17:22 +02:00
if ( density_ [ oilPhaseIdx ]. size () > 0 ) {
sol . insert ( "OIL_DEN" , Opm :: UnitSystem :: measure :: density , std :: move ( density_ [ oilPhaseIdx ]), Opm :: data :: TargetType :: RESTART_AUXILIARY );
2018-01-09 14:01:30 +01:00
}
2018-04-30 17:17:22 +02:00
if ( density_ [ gasPhaseIdx ]. size () > 0 ) {
sol . insert ( "GAS_DEN" , Opm :: UnitSystem :: measure :: density , std :: move ( density_ [ gasPhaseIdx ]), Opm :: data :: TargetType :: RESTART_AUXILIARY );
2018-01-09 14:01:30 +01:00
}
2018-04-30 17:17:22 +02:00
if ( viscosity_ [ waterPhaseIdx ]. size () > 0 ) {
sol . insert ( "WAT_VISC" , Opm :: UnitSystem :: measure :: viscosity , std :: move ( viscosity_ [ waterPhaseIdx ]), Opm :: data :: TargetType :: RESTART_AUXILIARY );
2018-01-09 14:01:30 +01:00
}
2018-04-30 17:17:22 +02:00
if ( viscosity_ [ oilPhaseIdx ]. size () > 0 ) {
sol . insert ( "OIL_VISC" , Opm :: UnitSystem :: measure :: viscosity , std :: move ( viscosity_ [ oilPhaseIdx ]), Opm :: data :: TargetType :: RESTART_AUXILIARY );
2018-01-09 14:01:30 +01:00
}
2018-04-30 17:17:22 +02:00
if ( viscosity_ [ gasPhaseIdx ]. size () > 0 ) {
sol . insert ( "GAS_VISC" , Opm :: UnitSystem :: measure :: viscosity , std :: move ( viscosity_ [ gasPhaseIdx ]), Opm :: data :: TargetType :: RESTART_AUXILIARY );
2018-01-09 14:01:30 +01:00
}
if ( relativePermeability_ [ waterPhaseIdx ]. size () > 0 ) {
2018-04-30 17:17:22 +02:00
sol . insert ( "WATKR" , Opm :: UnitSystem :: measure :: identity , std :: move ( relativePermeability_ [ waterPhaseIdx ]), Opm :: data :: TargetType :: RESTART_AUXILIARY );
2018-01-09 14:01:30 +01:00
}
2018-04-30 17:17:22 +02:00
if ( relativePermeability_ [ oilPhaseIdx ]. size () > 0 ) {
sol . insert ( "OILKR" , Opm :: UnitSystem :: measure :: identity , std :: move ( relativePermeability_ [ oilPhaseIdx ]), Opm :: data :: TargetType :: RESTART_AUXILIARY );
2018-01-09 14:01:30 +01:00
}
2018-04-30 17:17:22 +02:00
if ( relativePermeability_ [ gasPhaseIdx ]. size () > 0 ) {
sol . insert ( "GASKR" , Opm :: UnitSystem :: measure :: identity , std :: move ( relativePermeability_ [ gasPhaseIdx ]), Opm :: data :: TargetType :: RESTART_AUXILIARY );
2017-12-07 12:38:48 +01:00
}
2018-09-07 10:19:00 +02:00
if ( pcSwMdcOw_ . size () > 0 )
sol . insert ( "PCSWM_OW" , Opm :: UnitSystem :: measure :: identity , std :: move ( pcSwMdcOw_ ), Opm :: data :: TargetType :: RESTART_AUXILIARY );
2018-01-09 14:01:30 +01:00
if ( krnSwMdcOw_ . size () > 0 )
2018-01-09 11:28:20 +01:00
sol . insert ( "KRNSW_OW" , Opm :: UnitSystem :: measure :: identity , std :: move ( krnSwMdcOw_ ), Opm :: data :: TargetType :: RESTART_AUXILIARY );
2018-01-09 14:01:30 +01:00
if ( pcSwMdcGo_ . size () > 0 )
2018-01-09 11:28:20 +01:00
sol . insert ( "PCSWM_GO" , Opm :: UnitSystem :: measure :: identity , std :: move ( pcSwMdcGo_ ), Opm :: data :: TargetType :: RESTART_AUXILIARY );
2018-01-09 14:01:30 +01:00
if ( krnSwMdcGo_ . size () > 0 )
2018-01-09 11:28:20 +01:00
sol . insert ( "KRNSW_GO" , Opm :: UnitSystem :: measure :: identity , std :: move ( krnSwMdcGo_ ), Opm :: data :: TargetType :: RESTART_AUXILIARY );
2017-12-07 12:38:48 +01:00
2018-01-09 14:01:30 +01:00
if ( soMax_ . size () > 0 )
2018-01-09 11:28:20 +01:00
sol . insert ( "SOMAX" , Opm :: UnitSystem :: measure :: identity , std :: move ( soMax_ ), Opm :: data :: TargetType :: RESTART_SOLUTION );
2017-12-07 12:38:48 +01:00
2018-01-09 14:01:30 +01:00
if ( sSol_ . size () > 0 )
2018-05-09 14:52:43 +02:00
sol . insert ( "SSOLVENT" , Opm :: UnitSystem :: measure :: identity , std :: move ( sSol_ ), Opm :: data :: TargetType :: RESTART_SOLUTION );
2017-12-07 12:38:48 +01:00
2018-01-09 14:01:30 +01:00
if ( cPolymer_ . size () > 0 )
2018-01-09 11:28:20 +01:00
sol . insert ( "POLYMER" , Opm :: UnitSystem :: measure :: identity , std :: move ( cPolymer_ ), Opm :: data :: TargetType :: RESTART_SOLUTION );
2017-12-07 12:38:48 +01:00
2018-01-09 14:01:30 +01:00
if ( dewPointPressure_ . size () > 0 )
2018-01-09 11:28:20 +01:00
sol . insert ( "PDEW" , Opm :: UnitSystem :: measure :: pressure , std :: move ( dewPointPressure_ ), Opm :: data :: TargetType :: RESTART_AUXILIARY );
2017-12-07 12:38:48 +01:00
2018-01-09 14:01:30 +01:00
if ( bubblePointPressure_ . size () > 0 )
2018-01-09 11:28:20 +01:00
sol . insert ( "PBUB" , Opm :: UnitSystem :: measure :: pressure , std :: move ( bubblePointPressure_ ), Opm :: data :: TargetType :: RESTART_AUXILIARY );
2017-12-07 12:38:48 +01:00
2019-03-12 15:51:41 +01:00
if ( swMax_ . size () > 0 )
sol . insert ( "SWMAX" , Opm :: UnitSystem :: measure :: identity , std :: move ( swMax_ ), Opm :: data :: TargetType :: RESTART_SOLUTION );
if ( minimumOilPressure_ . size () > 0 )
sol . insert ( "PRESROCC" , Opm :: UnitSystem :: measure :: pressure , std :: move ( minimumOilPressure_ ), Opm :: data :: TargetType :: RESTART_SOLUTION );
if ( overburdenPressure_ . size () > 0 )
sol . insert ( "PRES_OVB" , Opm :: UnitSystem :: measure :: pressure , std :: move ( overburdenPressure_ ), Opm :: data :: TargetType :: RESTART_SOLUTION );
if ( rockCompPorvMultiplier_ . size () > 0 )
sol . insert ( "PORV_RC" , Opm :: UnitSystem :: measure :: identity , std :: move ( rockCompPorvMultiplier_ ), Opm :: data :: TargetType :: RESTART_SOLUTION );
if ( rockCompTransMultiplier_ . size () > 0 )
sol . insert ( "TMULT_RC" , Opm :: UnitSystem :: measure :: identity , std :: move ( rockCompTransMultiplier_ ), Opm :: data :: TargetType :: RESTART_SOLUTION );
2018-01-12 15:32:43 +01:00
// Fluid in place
2018-01-29 12:23:23 +01:00
for ( int i = 0 ; i < FipDataType :: numFipValues ; i ++ ) {
2018-01-22 13:38:50 +01:00
if ( outputFipRestart_ && fip_ [ i ]. size () > 0 ) {
2018-01-29 08:43:42 +01:00
sol . insert ( fipEnumToString_ ( i ),
2018-01-12 15:32:43 +01:00
Opm :: UnitSystem :: measure :: volume ,
2018-04-30 17:17:22 +02:00
fip_ [ i ],
2018-01-12 15:32:43 +01:00
Opm :: data :: TargetType :: SUMMARY );
}
}
2018-11-14 13:10:01 +01:00
// tracers
const auto & tracerModel = simulator_ . problem (). tracerModel ();
2019-02-01 17:33:30 +01:00
if ( tracerConcentrations_ . size () > 0 ) {
2018-11-14 13:10:01 +01:00
for ( int tracerIdx = 0 ; tracerIdx < tracerModel . numTracers (); tracerIdx ++ ){
std :: string tmp = tracerModel . tracerName ( tracerIdx ) + "F" ;
2019-02-01 17:33:30 +01:00
sol . insert ( tmp , Opm :: UnitSystem :: measure :: identity , std :: move ( tracerConcentrations_ [ tracerIdx ]), Opm :: data :: TargetType :: RESTART_SOLUTION );
2018-11-14 13:10:01 +01:00
}
}
2018-01-12 15:32:43 +01:00
}
2018-01-16 14:24:21 +01:00
// write Fluid In Place to output log
2018-04-30 17:17:22 +02:00
void outputFipLog ( std :: map < std :: string , double >& miscSummaryData , std :: map < std :: string , std :: vector < double >>& regionData , const bool substep )
{
2018-01-12 15:32:43 +01:00
const auto & comm = simulator_ . gridView (). comm ();
2019-03-22 15:14:08 +01:00
auto maxElement = std :: max_element ( fipnum_ . begin (), fipnum_ . end ());
size_t ntFip = 0 ;
if ( maxElement != fipnum_ . end () ) {
ntFip = * maxElement ;
}
2018-01-12 15:32:43 +01:00
ntFip = comm . max ( ntFip );
// sum values over each region
2018-01-29 12:23:23 +01:00
ScalarBuffer regionFipValues [ FipDataType :: numFipValues ];
2018-04-30 17:17:22 +02:00
for ( int i = 0 ; i < FipDataType :: numFipValues ; i ++ ) {
2018-01-29 08:43:42 +01:00
regionFipValues [ i ] = computeFipForRegions_ ( fip_ [ i ], fipnum_ , ntFip );
2018-01-12 15:32:43 +01:00
if ( isIORank_ () && origRegionValues_ [ i ]. empty ())
2018-01-22 13:38:50 +01:00
origRegionValues_ [ i ] = regionFipValues [ i ];
2018-01-12 15:32:43 +01:00
}
// sum all region values to compute the field total
std :: vector < int > fieldNum ( ntFip , 1 );
2018-04-30 17:17:22 +02:00
ScalarBuffer fieldFipValues ( FipDataType :: numFipValues , 0.0 );
2018-01-22 13:38:50 +01:00
bool comunicateSum = false ; // the regionValues are already summed over all ranks.
2018-01-29 12:23:23 +01:00
for ( int i = 0 ; i < FipDataType :: numFipValues ; i ++ ) {
2018-01-29 08:43:42 +01:00
const ScalarBuffer & tmp = computeFipForRegions_ ( regionFipValues [ i ], fieldNum , 1 , comunicateSum );
fieldFipValues [ i ] = tmp [ 0 ];
2018-01-12 15:32:43 +01:00
}
2018-01-17 15:24:24 +01:00
// compute the hydrocarbon averaged pressure over the regions.
2018-01-29 08:43:42 +01:00
ScalarBuffer regPressurePv = computeFipForRegions_ ( pressureTimesPoreVolume_ , fipnum_ , ntFip );
ScalarBuffer regPvHydrocarbon = computeFipForRegions_ ( hydrocarbonPoreVolume_ , fipnum_ , ntFip );
ScalarBuffer regPressurePvHydrocarbon = computeFipForRegions_ ( pressureTimesHydrocarbonVolume_ , fipnum_ , ntFip );
2018-01-22 13:38:50 +01:00
2018-01-29 08:43:42 +01:00
ScalarBuffer fieldPressurePv = computeFipForRegions_ ( regPressurePv , fieldNum , 1 , comunicateSum );
ScalarBuffer fieldPvHydrocarbon = computeFipForRegions_ ( regPvHydrocarbon , fieldNum , 1 , comunicateSum );
ScalarBuffer fieldPressurePvHydrocarbon = computeFipForRegions_ ( regPressurePvHydrocarbon , fieldNum , 1 , comunicateSum );
2018-01-12 15:32:43 +01:00
2018-01-17 15:24:24 +01:00
// output on io rank
2018-01-12 15:32:43 +01:00
// the original Fip values are stored on the first step
// TODO: Store initial Fip in the init file and restore them
// and use them here.
2018-02-01 16:26:58 +01:00
const Opm :: SummaryConfig summaryConfig = simulator_ . vanguard (). summaryConfig ();
2018-04-30 17:17:22 +02:00
if ( isIORank_ ()) {
2018-01-17 15:24:24 +01:00
// Field summary output
2018-01-29 12:23:23 +01:00
for ( int i = 0 ; i < FipDataType :: numFipValues ; i ++ ) {
2018-01-29 08:43:42 +01:00
std :: string key = "F" + fipEnumToString_ ( i );
2018-01-17 15:24:24 +01:00
if ( summaryConfig . hasKeyword ( key ))
2018-01-22 13:38:50 +01:00
miscSummaryData [ key ] = fieldFipValues [ i ];
2018-01-12 15:32:43 +01:00
}
2018-01-17 15:24:24 +01:00
if ( summaryConfig . hasKeyword ( "FOE" ) && ! origTotalValues_ . empty ())
2018-01-29 12:23:23 +01:00
miscSummaryData [ "FOE" ] = fieldFipValues [ FipDataType :: OilInPlace ] / origTotalValues_ [ FipDataType :: OilInPlace ];
2018-01-12 15:32:43 +01:00
2018-01-17 15:24:24 +01:00
if ( summaryConfig . hasKeyword ( "FPR" ))
2018-01-29 12:23:23 +01:00
miscSummaryData [ "FPR" ] = pressureAverage_ ( fieldPressurePvHydrocarbon [ 0 ], fieldPvHydrocarbon [ 0 ], fieldPressurePv [ 0 ], fieldFipValues [ FipDataType :: PoreVolume ], true );
2018-01-12 15:32:43 +01:00
2018-01-17 15:24:24 +01:00
if ( summaryConfig . hasKeyword ( "FPRP" ))
2019-05-27 11:24:55 +02:00
miscSummaryData [ "FPRP" ] = pressureAverage_ ( fieldPressurePvHydrocarbon [ 0 ], fieldPvHydrocarbon [ 0 ], fieldPressurePv [ 0 ], fieldFipValues [ FipDataType :: PoreVolume ], false );
2018-01-12 15:32:43 +01:00
2018-01-17 15:24:24 +01:00
// Region summary output
2018-01-29 12:23:23 +01:00
for ( int i = 0 ; i < FipDataType :: numFipValues ; i ++ ) {
2018-01-29 08:43:42 +01:00
std :: string key = "R" + fipEnumToString_ ( i );
2018-01-17 15:24:24 +01:00
if ( summaryConfig . hasKeyword ( key ))
2018-01-22 13:38:50 +01:00
regionData [ key ] = regionFipValues [ i ];
2018-01-17 15:24:24 +01:00
}
if ( summaryConfig . hasKeyword ( "RPR" ))
2018-01-29 12:23:23 +01:00
regionData [ "RPR" ] = pressureAverage_ ( regPressurePvHydrocarbon , regPvHydrocarbon , regPressurePv , regionFipValues [ FipDataType :: PoreVolume ], true );
2018-01-17 15:24:24 +01:00
2018-01-22 13:38:50 +01:00
if ( summaryConfig . hasKeyword ( "RPRP" ))
2018-01-29 12:23:23 +01:00
regionData [ "RPRP" ] = pressureAverage_ ( regPressurePvHydrocarbon , regPvHydrocarbon , regPressurePv , regionFipValues [ FipDataType :: PoreVolume ], false );
2018-01-17 15:24:24 +01:00
// Output to log
if ( ! substep ) {
2018-01-29 08:43:42 +01:00
fipUnitConvert_ ( fieldFipValues );
2018-01-17 15:24:24 +01:00
if ( origTotalValues_ . empty ())
2018-01-22 13:38:50 +01:00
origTotalValues_ = fieldFipValues ;
2018-01-17 15:24:24 +01:00
2018-01-29 12:23:23 +01:00
Scalar fieldHydroCarbonPoreVolumeAveragedPressure = pressureAverage_ ( fieldPressurePvHydrocarbon [ 0 ], fieldPvHydrocarbon [ 0 ], fieldPressurePv [ 0 ], fieldFipValues [ FipDataType :: PoreVolume ], true );
2018-01-22 13:38:50 +01:00
pressureUnitConvert_ ( fieldHydroCarbonPoreVolumeAveragedPressure );
outputRegionFluidInPlace_ ( origTotalValues_ , fieldFipValues , fieldHydroCarbonPoreVolumeAveragedPressure , 0 );
2018-04-30 17:17:22 +02:00
for ( size_t reg = 0 ; reg < ntFip ; ++ reg ) {
ScalarBuffer tmpO ( FipDataType :: numFipValues , 0.0 );
2018-01-29 12:23:23 +01:00
for ( int i = 0 ; i < FipDataType :: numFipValues ; i ++ ) {
2018-01-17 15:24:24 +01:00
tmpO [ i ] = origRegionValues_ [ i ][ reg ];
}
2018-01-29 08:43:42 +01:00
fipUnitConvert_ ( tmpO );
2018-04-30 17:17:22 +02:00
ScalarBuffer tmp ( FipDataType :: numFipValues , 0.0 );
2018-01-29 12:23:23 +01:00
for ( int i = 0 ; i < FipDataType :: numFipValues ; i ++ ) {
2018-01-22 13:38:50 +01:00
tmp [ i ] = regionFipValues [ i ][ reg ];
2018-01-17 15:24:24 +01:00
}
2018-01-29 08:43:42 +01:00
fipUnitConvert_ ( tmp );
2018-01-29 12:23:23 +01:00
Scalar regHydroCarbonPoreVolumeAveragedPressure = pressureAverage_ ( regPressurePvHydrocarbon [ reg ], regPvHydrocarbon [ reg ], regPressurePv [ reg ], regionFipValues [ FipDataType :: PoreVolume ][ reg ], true );
2018-01-22 13:38:50 +01:00
pressureUnitConvert_ ( regHydroCarbonPoreVolumeAveragedPressure );
outputRegionFluidInPlace_ ( tmpO , tmp , regHydroCarbonPoreVolumeAveragedPressure , reg + 1 );
2018-01-17 15:24:24 +01:00
}
2018-01-12 15:32:43 +01:00
}
}
2018-01-17 15:24:24 +01:00
2018-01-12 15:32:43 +01:00
}
2017-12-07 12:38:48 +01:00
2019-06-03 11:11:41 +02:00
void setRestart ( const Opm :: data :: Solution & sol , unsigned elemIdx , unsigned globalDofIndex )
2017-12-07 12:38:48 +01:00
{
Scalar so = 1.0 ;
2018-04-30 17:17:22 +02:00
if ( saturation_ [ waterPhaseIdx ]. size () > 0 && sol . has ( "SWAT" )) {
2017-12-07 12:38:48 +01:00
saturation_ [ waterPhaseIdx ][ elemIdx ] = sol . data ( "SWAT" )[ globalDofIndex ];
so -= sol . data ( "SWAT" )[ globalDofIndex ];
}
2018-04-30 17:17:22 +02:00
if ( saturation_ [ gasPhaseIdx ]. size () > 0 && sol . has ( "SGAS" )) {
2017-12-07 12:38:48 +01:00
saturation_ [ gasPhaseIdx ][ elemIdx ] = sol . data ( "SGAS" )[ globalDofIndex ];
so -= sol . data ( "SGAS" )[ globalDofIndex ];
}
2018-02-19 08:49:02 +01:00
assert ( saturation_ [ oilPhaseIdx ]. size () > 0 );
2017-12-07 12:38:48 +01:00
saturation_ [ oilPhaseIdx ][ elemIdx ] = so ;
2018-04-30 17:17:22 +02:00
if ( oilPressure_ . size () > 0 && sol . has ( "PRESSURE" ))
oilPressure_ [ elemIdx ] = sol . data ( "PRESSURE" )[ globalDofIndex ];
2018-12-17 11:37:07 +01:00
if ( enableEnergy && sol . has ( "TEMP" ))
2018-04-30 17:17:22 +02:00
temperature_ [ elemIdx ] = sol . data ( "TEMP" )[ globalDofIndex ];
if ( rs_ . size () > 0 && sol . has ( "RS" ))
2017-12-07 12:38:48 +01:00
rs_ [ elemIdx ] = sol . data ( "RS" )[ globalDofIndex ];
2018-04-30 17:17:22 +02:00
if ( rv_ . size () > 0 && sol . has ( "RV" ))
2017-12-07 12:38:48 +01:00
rv_ [ elemIdx ] = sol . data ( "RV" )[ globalDofIndex ];
2018-05-09 14:52:43 +02:00
if ( sSol_ . size () > 0 ) {
// keep the SSOL option for backward compatibility
// should be removed after 10.2018 release
if ( sol . has ( "SSOL" ))
sSol_ [ elemIdx ] = sol . data ( "SSOL" )[ globalDofIndex ];
else if ( sol . has ( "SSOLVENT" ))
sSol_ [ elemIdx ] = sol . data ( "SSOLVENT" )[ globalDofIndex ];
}
2018-04-30 17:17:22 +02:00
if ( cPolymer_ . size () > 0 && sol . has ( "POLYMER" ))
2017-12-07 12:38:48 +01:00
cPolymer_ [ elemIdx ] = sol . data ( "POLYMER" )[ globalDofIndex ];
2018-04-30 17:17:22 +02:00
if ( soMax_ . size () > 0 && sol . has ( "SOMAX" ))
2017-12-07 12:38:48 +01:00
soMax_ [ elemIdx ] = sol . data ( "SOMAX" )[ globalDofIndex ];
2018-04-30 17:17:22 +02:00
if ( pcSwMdcOw_ . size () > 0 && sol . has ( "PCSWM_OW" ))
2017-12-07 12:38:48 +01:00
pcSwMdcOw_ [ elemIdx ] = sol . data ( "PCSWM_OW" )[ globalDofIndex ];
2018-04-30 17:17:22 +02:00
if ( krnSwMdcOw_ . size () > 0 && sol . has ( "KRNSW_OW" ))
2017-12-07 12:38:48 +01:00
krnSwMdcOw_ [ elemIdx ] = sol . data ( "KRNSW_OW" )[ globalDofIndex ];
2018-04-30 17:17:22 +02:00
if ( pcSwMdcGo_ . size () > 0 && sol . has ( "PCSWM_GO" ))
2017-12-07 12:38:48 +01:00
pcSwMdcGo_ [ elemIdx ] = sol . data ( "PCSWM_GO" )[ globalDofIndex ];
2018-04-30 17:17:22 +02:00
if ( krnSwMdcGo_ . size () > 0 && sol . has ( "KRNSW_GO" ))
2017-12-07 12:38:48 +01:00
krnSwMdcGo_ [ elemIdx ] = sol . data ( "KRNSW_GO" )[ globalDofIndex ];
2018-09-07 10:19:00 +02:00
if ( ppcw_ . size () > 0 && sol . has ( "PPCW" ))
ppcw_ [ elemIdx ] = sol . data ( "PPCW" )[ globalDofIndex ];
2017-12-07 12:38:48 +01:00
}
template < class FluidState >
2018-04-30 17:17:22 +02:00
void assignToFluidState ( FluidState & fs , unsigned elemIdx ) const
2017-12-07 12:38:48 +01:00
{
2018-01-09 14:01:30 +01:00
for ( unsigned phaseIdx = 0 ; phaseIdx < numPhases ; ++ phaseIdx ) {
if ( saturation_ [ phaseIdx ]. size () == 0 )
continue ;
2015-01-25 17:27:08 +01:00
2018-01-09 14:01:30 +01:00
fs . setSaturation ( phaseIdx , saturation_ [ phaseIdx ][ elemIdx ]);
2014-11-28 12:58:48 +01:00
}
2018-01-09 14:01:30 +01:00
if ( oilPressure_ . size () > 0 ) {
2017-12-07 12:38:48 +01:00
// this assumes that capillary pressures only depend on the phase saturations
// and possibly on temperature. (this is always the case for ECL problems.)
2018-04-30 17:17:22 +02:00
Dune :: FieldVector < Scalar , numPhases > pc ( 0 );
2017-12-07 12:38:48 +01:00
const MaterialLawParams & matParams = simulator_ . problem (). materialLawParams ( elemIdx );
MaterialLaw :: capillaryPressures ( pc , matParams , fs );
Opm :: Valgrind :: CheckDefined ( oilPressure_ [ elemIdx ]);
Opm :: Valgrind :: CheckDefined ( pc );
assert ( FluidSystem :: phaseIsActive ( oilPhaseIdx ));
for ( unsigned phaseIdx = 0 ; phaseIdx < numPhases ; ++ phaseIdx ) {
if ( ! FluidSystem :: phaseIsActive ( phaseIdx ))
continue ;
fs . setPressure ( phaseIdx , oilPressure_ [ elemIdx ] + ( pc [ phaseIdx ] - pc [ oilPhaseIdx ]));
}
2015-01-25 17:27:08 +01:00
}
2017-12-07 12:38:48 +01:00
2018-12-17 11:37:07 +01:00
if ( enableEnergy )
2018-04-30 17:17:22 +02:00
fs . setTemperature ( temperature_ [ elemIdx ]);
if ( rs_ . size () > 0 )
2017-12-07 12:38:48 +01:00
fs . setRs ( rs_ [ elemIdx ]);
2018-04-30 17:17:22 +02:00
if ( rv_ . size () > 0 )
2017-12-07 12:38:48 +01:00
fs . setRv ( rv_ [ elemIdx ]);
2014-11-28 12:58:48 +01:00
}
2019-02-01 17:33:30 +01:00
void initHysteresisParams ( Simulator & simulator , unsigned elemIdx ) const
{
2018-01-09 14:01:30 +01:00
if ( soMax_ . size () > 0 )
2018-02-19 08:46:27 +01:00
simulator . problem (). setMaxOilSaturation ( elemIdx , soMax_ [ elemIdx ]);
2017-12-07 12:38:48 +01:00
if ( simulator . problem (). materialLawManager () -> enableHysteresis ()) {
auto matLawManager = simulator . problem (). materialLawManager ();
2018-01-09 14:01:30 +01:00
if ( pcSwMdcOw_ . size () > 0 && krnSwMdcOw_ . size () > 0 ) {
2017-12-07 12:38:48 +01:00
matLawManager -> setOilWaterHysteresisParams (
2018-01-09 14:01:30 +01:00
pcSwMdcOw_ [ elemIdx ],
krnSwMdcOw_ [ elemIdx ],
elemIdx );
}
if ( pcSwMdcGo_ . size () > 0 && krnSwMdcGo_ . size () > 0 ) {
2017-12-07 12:38:48 +01:00
matLawManager -> setGasOilHysteresisParams (
2018-01-09 14:01:30 +01:00
pcSwMdcGo_ [ elemIdx ],
krnSwMdcGo_ [ elemIdx ],
elemIdx );
}
2017-12-07 12:38:48 +01:00
}
2018-09-07 10:19:00 +02:00
if ( simulator_ . vanguard (). eclState (). get3DProperties (). hasDeckDoubleGridProperty ( "SWATINIT" )) {
auto oilWaterScaledEpsInfoDrainage = simulator . problem (). materialLawManager () -> oilWaterScaledEpsInfoDrainagePointerReferenceHack ( elemIdx );
oilWaterScaledEpsInfoDrainage -> maxPcow = ppcw_ [ elemIdx ];
}
2017-12-07 12:38:48 +01:00
}
2019-02-01 17:33:30 +01:00
Scalar getSolventSaturation ( unsigned elemIdx ) const
{
2018-04-30 17:17:22 +02:00
if ( sSol_ . size () > 0 )
2017-12-07 12:38:48 +01:00
return sSol_ [ elemIdx ];
return 0 ;
}
2019-02-01 17:33:30 +01:00
Scalar getPolymerConcentration ( unsigned elemIdx ) const
{
2018-04-30 17:17:22 +02:00
if ( cPolymer_ . size () > 0 )
2017-12-07 12:38:48 +01:00
return cPolymer_ [ elemIdx ];
return 0 ;
}
2019-02-01 17:33:30 +01:00
const std :: map < std :: pair < std :: string , int > , double >& getBlockData ()
{ return blockData_ ; }
2018-01-19 15:45:42 +01:00
2014-11-28 12:58:48 +01:00
private :
2017-12-07 12:38:48 +01:00
2018-01-09 14:01:30 +01:00
bool isIORank_ () const
2017-12-07 12:38:48 +01:00
{
const auto & comm = simulator_ . gridView (). comm ();
return comm . rank () == 0 ;
}
2018-01-29 08:43:42 +01:00
void updateFluidInPlace_ ( const ElementContext & elemCtx , unsigned dofIdx )
{
const auto & intQuants = elemCtx . intensiveQuantities ( dofIdx , /*timeIdx=*/ 0 );
const auto & fs = intQuants . fluidState ();
unsigned globalDofIdx = elemCtx . globalSpaceIndex ( dofIdx , /*timeIdx=*/ 0 );
// Fluid in Place calculations
// calculate the pore volume of the current cell. Note that the porosity
// returned by the intensive quantities is defined as the ratio of pore
// space to total cell volume and includes all pressure dependent (->
// rock compressibility) and static modifiers (MULTPV, MULTREGP, NTG,
// PORV, MINPV and friends). Also note that because of this, the porosity
// returned by the intensive quantities can be outside of the physical
// range [0, 1] in pathetic cases.
const double pv =
elemCtx . simulator (). model (). dofTotalVolume ( globalDofIdx )
* intQuants . porosity (). value ();
if ( pressureTimesHydrocarbonVolume_ . size () > 0 && pressureTimesPoreVolume_ . size () > 0 ) {
assert ( hydrocarbonPoreVolume_ . size () == pressureTimesHydrocarbonVolume_ . size ());
2018-04-30 17:17:22 +02:00
assert ( fip_ [ FipDataType :: PoreVolume ]. size () == pressureTimesPoreVolume_ . size ());
2018-01-29 08:43:42 +01:00
2018-01-29 12:23:23 +01:00
fip_ [ FipDataType :: PoreVolume ][ globalDofIdx ] = pv ;
2018-01-29 08:43:42 +01:00
Scalar hydrocarbon = 0.0 ;
if ( FluidSystem :: phaseIsActive ( oilPhaseIdx ))
hydrocarbon += Opm :: getValue ( fs . saturation ( oilPhaseIdx ));
if ( FluidSystem :: phaseIsActive ( gasPhaseIdx ))
hydrocarbon += Opm :: getValue ( fs . saturation ( gasPhaseIdx ));
hydrocarbonPoreVolume_ [ globalDofIdx ] = pv * hydrocarbon ;
if ( FluidSystem :: phaseIsActive ( oilPhaseIdx )) {
pressureTimesPoreVolume_ [ globalDofIdx ] = Opm :: getValue ( fs . pressure ( oilPhaseIdx )) * pv ;
pressureTimesHydrocarbonVolume_ [ globalDofIdx ] = pressureTimesPoreVolume_ [ globalDofIdx ] * hydrocarbon ;
}
}
if ( computeFip_ ) {
Scalar fip [ FluidSystem :: numPhases ];
2018-04-30 17:17:22 +02:00
for ( unsigned phaseIdx = 0 ; phaseIdx < FluidSystem :: numPhases ; ++ phaseIdx ) {
fip [ phaseIdx ] = 0.0 ;
if ( ! FluidSystem :: phaseIsActive ( phaseIdx ))
2018-01-29 08:43:42 +01:00
continue ;
2018-04-30 17:17:22 +02:00
const double b = Opm :: getValue ( fs . invB ( phaseIdx ));
const double s = Opm :: getValue ( fs . saturation ( phaseIdx ));
fip [ phaseIdx ] = b * s * pv ;
2018-01-29 08:43:42 +01:00
}
2018-01-29 12:23:23 +01:00
if ( FluidSystem :: phaseIsActive ( oilPhaseIdx ) && fip_ [ FipDataType :: OilInPlace ]. size () > 0 )
fip_ [ FipDataType :: OilInPlace ][ globalDofIdx ] = fip [ oilPhaseIdx ];
if ( FluidSystem :: phaseIsActive ( gasPhaseIdx ) && fip_ [ FipDataType :: GasInPlace ]. size () > 0 )
fip_ [ FipDataType :: GasInPlace ][ globalDofIdx ] = fip [ gasPhaseIdx ];
if ( FluidSystem :: phaseIsActive ( waterPhaseIdx ) && fip_ [ FipDataType :: WaterInPlace ]. size () > 0 )
fip_ [ FipDataType :: WaterInPlace ][ globalDofIdx ] = fip [ waterPhaseIdx ];
2018-01-29 08:43:42 +01:00
2018-01-29 12:23:23 +01:00
// Store the pure oil and gas Fip
if ( FluidSystem :: phaseIsActive ( oilPhaseIdx ) && fip_ [ FipDataType :: OilInPlaceInLiquidPhase ]. size () > 0 )
fip_ [ FipDataType :: OilInPlaceInLiquidPhase ][ globalDofIdx ] = fip [ oilPhaseIdx ];
2018-01-29 08:43:42 +01:00
2018-01-29 12:23:23 +01:00
if ( FluidSystem :: phaseIsActive ( gasPhaseIdx ) && fip_ [ FipDataType :: GasInPlaceInGasPhase ]. size () > 0 )
fip_ [ FipDataType :: GasInPlaceInGasPhase ][ globalDofIdx ] = fip [ gasPhaseIdx ];
2018-01-29 08:43:42 +01:00
if ( FluidSystem :: phaseIsActive ( oilPhaseIdx ) && FluidSystem :: phaseIsActive ( gasPhaseIdx )) {
// Gas dissolved in oil and vaporized oil
Scalar gasInPlaceLiquid = Opm :: getValue ( fs . Rs ()) * fip [ oilPhaseIdx ];
Scalar oilInPlaceGas = Opm :: getValue ( fs . Rv ()) * fip [ gasPhaseIdx ];
2019-05-22 15:39:57 +02:00
if ( fip_ [ FipDataType :: GasInPlaceInLiquidPhase ]. size () > 0 )
2018-01-29 12:23:23 +01:00
fip_ [ FipDataType :: GasInPlaceInLiquidPhase ][ globalDofIdx ] = gasInPlaceLiquid ;
if ( fip_ [ FipDataType :: OilInPlaceInGasPhase ]. size () > 0 )
fip_ [ FipDataType :: OilInPlaceInGasPhase ][ globalDofIdx ] = oilInPlaceGas ;
// Add dissolved gas and vaporized oil to total Fip
if ( fip_ [ FipDataType :: OilInPlace ]. size () > 0 )
fip_ [ FipDataType :: OilInPlace ][ globalDofIdx ] += oilInPlaceGas ;
if ( fip_ [ FipDataType :: GasInPlace ]. size () > 0 )
fip_ [ FipDataType :: GasInPlace ][ globalDofIdx ] += gasInPlaceLiquid ;
2018-01-29 08:43:42 +01:00
}
}
}
2018-01-12 15:32:43 +01:00
void createLocalFipnum_ ()
{
2018-04-30 17:17:22 +02:00
const std :: vector < int >& fipnumGlobal = simulator_ . vanguard (). eclState (). get3DProperties (). getIntGridProperty ( "FIPNUM" ). getData ();
2018-01-12 15:32:43 +01:00
// Get compressed cell fipnum.
2018-02-01 16:26:58 +01:00
const auto & gridView = simulator_ . vanguard (). gridView ();
2018-01-12 15:32:43 +01:00
unsigned numElements = gridView . size ( /*codim=*/ 0 );
2018-01-16 15:44:01 +01:00
fipnum_ . resize ( numElements , 0.0 );
2018-04-30 17:17:22 +02:00
if ( ! fipnumGlobal . empty ()) {
2018-01-16 15:44:01 +01:00
ElementContext elemCtx ( simulator_ );
ElementIterator elemIt = gridView . template begin < /*codim=*/ 0 > ();
const ElementIterator & elemEndIt = gridView . template end < /*codim=*/ 0 > ();
for (; elemIt != elemEndIt ; ++ elemIt ) {
const Element & elem = * elemIt ;
if ( elem . partitionType () != Dune :: InteriorEntity )
continue ; // assign no fipnum regions to ghost elements
elemCtx . updatePrimaryStencil ( elem );
const unsigned elemIdx = elemCtx . globalSpaceIndex ( /*spaceIdx=*/ 0 , /*timeIdx=*/ 0 );
2018-04-30 17:17:22 +02:00
fipnum_ [ elemIdx ] = fipnumGlobal [ simulator_ . vanguard (). cartesianIndex ( elemIdx )];
2018-01-12 15:32:43 +01:00
}
}
}
// Sum Fip values over regions.
2018-01-29 08:43:42 +01:00
ScalarBuffer computeFipForRegions_ ( const ScalarBuffer & fip , std :: vector < int >& regionId , size_t maxNumberOfRegions , bool commSum = true )
2018-01-12 15:32:43 +01:00
{
ScalarBuffer totals ( maxNumberOfRegions , 0.0 );
2018-02-01 13:16:37 +01:00
if ( fip . empty ())
return totals ;
2018-01-12 15:32:43 +01:00
assert ( regionId . size () == fip . size ());
for ( size_t j = 0 ; j < regionId . size (); ++ j ) {
const int regionIdx = regionId [ j ] - 1 ;
// the cell is not attributed to any region. ignore it!
if ( regionIdx < 0 )
continue ;
assert ( regionIdx < static_cast < int > ( maxNumberOfRegions ));
totals [ regionIdx ] += fip [ j ];
}
if ( commSum ) {
const auto & comm = simulator_ . gridView (). comm ();
for ( size_t i = 0 ; i < maxNumberOfRegions ; ++ i )
totals [ i ] = comm . sum ( totals [ i ]);
}
return totals ;
}
2018-04-30 17:17:22 +02:00
ScalarBuffer pressureAverage_ ( const ScalarBuffer & pressurePvHydrocarbon , const ScalarBuffer & pvHydrocarbon , const ScalarBuffer & pressurePv , const ScalarBuffer & pv , bool hydrocarbon )
{
2018-01-22 13:38:50 +01:00
size_t size = pressurePvHydrocarbon . size ();
assert ( pvHydrocarbon . size () == size );
assert ( pressurePv . size () == size );
assert ( pv . size () == size );
2018-01-12 15:32:43 +01:00
2018-04-30 17:17:22 +02:00
ScalarBuffer fraction ( size , 0.0 );
2018-01-22 13:38:50 +01:00
for ( size_t i = 0 ; i < size ; ++ i ) {
fraction [ i ] = pressureAverage_ ( pressurePvHydrocarbon [ i ], pvHydrocarbon [ i ], pressurePv [ i ], pv [ i ], hydrocarbon );
}
return fraction ;
}
2018-01-17 15:24:24 +01:00
2018-04-30 17:17:22 +02:00
Scalar pressureAverage_ ( const Scalar & pressurePvHydrocarbon , const Scalar & pvHydrocarbon , const Scalar & pressurePv , const Scalar & pv , bool hydrocarbon )
{
2018-01-22 13:38:50 +01:00
if ( pvHydrocarbon > 1e-10 && hydrocarbon )
return pressurePvHydrocarbon / pvHydrocarbon ;
2018-01-12 15:32:43 +01:00
2018-01-22 13:38:50 +01:00
return pressurePv / pv ;
2018-01-12 15:32:43 +01:00
}
2018-01-29 08:43:42 +01:00
void fipUnitConvert_ ( ScalarBuffer & fip )
2018-01-12 15:32:43 +01:00
{
2018-02-01 16:26:58 +01:00
const Opm :: UnitSystem & units = simulator_ . vanguard (). eclState (). getUnits ();
2018-01-12 15:32:43 +01:00
if ( units . getType () == Opm :: UnitSystem :: UnitType :: UNIT_TYPE_FIELD ) {
2018-01-29 12:23:23 +01:00
fip [ FipDataType :: WaterInPlace ] = Opm :: unit :: convert :: to ( fip [ FipDataType :: WaterInPlace ], Opm :: unit :: stb );
fip [ FipDataType :: OilInPlace ] = Opm :: unit :: convert :: to ( fip [ FipDataType :: OilInPlace ], Opm :: unit :: stb );
fip [ FipDataType :: OilInPlaceInLiquidPhase ] = Opm :: unit :: convert :: to ( fip [ FipDataType :: OilInPlaceInLiquidPhase ], Opm :: unit :: stb );
fip [ FipDataType :: OilInPlaceInGasPhase ] = Opm :: unit :: convert :: to ( fip [ FipDataType :: OilInPlaceInGasPhase ], Opm :: unit :: stb );
fip [ FipDataType :: GasInPlace ] = Opm :: unit :: convert :: to ( fip [ FipDataType :: GasInPlace ], 1000 * Opm :: unit :: cubic ( Opm :: unit :: feet ));
fip [ FipDataType :: GasInPlaceInLiquidPhase ] = Opm :: unit :: convert :: to ( fip [ FipDataType :: GasInPlaceInLiquidPhase ], 1000 * Opm :: unit :: cubic ( Opm :: unit :: feet ));
fip [ FipDataType :: GasInPlaceInGasPhase ] = Opm :: unit :: convert :: to ( fip [ FipDataType :: GasInPlaceInGasPhase ], 1000 * Opm :: unit :: cubic ( Opm :: unit :: feet ));
fip [ FipDataType :: PoreVolume ] = Opm :: unit :: convert :: to ( fip [ FipDataType :: PoreVolume ], Opm :: unit :: stb );
2018-01-12 15:32:43 +01:00
}
2019-01-21 14:55:40 +01:00
else if ( units . getType () == Opm :: UnitSystem :: UnitType :: UNIT_TYPE_LAB ) {
Scalar scc = Opm :: unit :: cubic ( Opm :: prefix :: centi * Opm :: unit :: meter ); //standard cubic cm.
fip [ FipDataType :: WaterInPlace ] = Opm :: unit :: convert :: to ( fip [ FipDataType :: WaterInPlace ], scc );
fip [ FipDataType :: OilInPlace ] = Opm :: unit :: convert :: to ( fip [ FipDataType :: OilInPlace ], scc );
fip [ FipDataType :: OilInPlaceInLiquidPhase ] = Opm :: unit :: convert :: to ( fip [ FipDataType :: OilInPlaceInLiquidPhase ], scc );
fip [ FipDataType :: OilInPlaceInGasPhase ] = Opm :: unit :: convert :: to ( fip [ FipDataType :: OilInPlaceInGasPhase ], scc );
fip [ FipDataType :: GasInPlace ] = Opm :: unit :: convert :: to ( fip [ FipDataType :: GasInPlace ], scc );
fip [ FipDataType :: GasInPlaceInLiquidPhase ] = Opm :: unit :: convert :: to ( fip [ FipDataType :: GasInPlaceInLiquidPhase ], scc );
fip [ FipDataType :: GasInPlaceInGasPhase ] = Opm :: unit :: convert :: to ( fip [ FipDataType :: GasInPlaceInGasPhase ], scc );
fip [ FipDataType :: PoreVolume ] = Opm :: unit :: convert :: to ( fip [ FipDataType :: PoreVolume ], scc );
}
2018-01-12 15:32:43 +01:00
else if ( units . getType () == Opm :: UnitSystem :: UnitType :: UNIT_TYPE_METRIC ) {
2018-01-17 15:24:24 +01:00
// nothing to do
2018-01-12 15:32:43 +01:00
}
else {
2018-02-01 14:40:01 +01:00
throw std :: runtime_error ( "Unsupported unit type for fluid in place output." );
2018-01-12 15:32:43 +01:00
}
}
2018-04-30 17:17:22 +02:00
void pressureUnitConvert_ ( Scalar & pav )
{
2018-02-01 16:26:58 +01:00
const Opm :: UnitSystem & units = simulator_ . vanguard (). eclState (). getUnits ();
2018-01-17 15:24:24 +01:00
if ( units . getType () == Opm :: UnitSystem :: UnitType :: UNIT_TYPE_FIELD ) {
pav = Opm :: unit :: convert :: to ( pav , Opm :: unit :: psia );
2018-04-30 17:17:22 +02:00
}
else if ( units . getType () == Opm :: UnitSystem :: UnitType :: UNIT_TYPE_METRIC ) {
2018-01-17 15:24:24 +01:00
pav = Opm :: unit :: convert :: to ( pav , Opm :: unit :: barsa );
}
2019-01-21 14:55:40 +01:00
else if ( units . getType () == Opm :: UnitSystem :: UnitType :: UNIT_TYPE_LAB ) {
pav = Opm :: unit :: convert :: to ( pav , Opm :: unit :: atm );
}
2018-01-17 15:24:24 +01:00
else {
2018-02-01 14:40:01 +01:00
throw std :: runtime_error ( "Unsupported unit type for fluid in place output." );
2018-01-17 15:24:24 +01:00
}
}
void outputRegionFluidInPlace_ ( const ScalarBuffer & oip , const ScalarBuffer & cip , const Scalar & pav , const int reg )
2018-01-12 15:32:43 +01:00
{
2018-07-26 12:31:32 +02:00
if ( forceDisableFipOutput_ )
return ;
2018-11-06 09:02:30 +01:00
// don't output FIPNUM report if the region has no porv.
if ( cip [ FipDataType :: PoreVolume ] == 0 )
return ;
2018-02-01 16:26:58 +01:00
const Opm :: UnitSystem & units = simulator_ . vanguard (). eclState (). getUnits ();
2018-01-12 15:32:43 +01:00
std :: ostringstream ss ;
if ( ! reg ) {
ss << " =================================================== \n "
<< " : Field Totals : \n " ;
2018-04-30 17:17:22 +02:00
}
else {
2018-01-12 15:32:43 +01:00
ss << " =================================================== \n "
<< " : FIPNUM report region "
<< std :: setw ( 2 ) << reg << " : \n " ;
}
if ( units . getType () == Opm :: UnitSystem :: UnitType :: UNIT_TYPE_METRIC ) {
2018-01-17 15:24:24 +01:00
ss << " : PAV =" << std :: setw ( 14 ) << pav << " BARSA : \n "
2018-01-12 15:32:43 +01:00
<< std :: fixed << std :: setprecision ( 0 )
2018-01-29 12:23:23 +01:00
<< " : PORV =" << std :: setw ( 14 ) << cip [ FipDataType :: PoreVolume ] << " RM3 : \n " ;
2018-01-12 15:32:43 +01:00
if ( ! reg ) {
ss << " : Pressure is weighted by hydrocarbon pore volume : \n "
<< " : Porv volumes are taken at reference conditions : \n " ;
}
ss << " :--------------- Oil SM3 ---------------:-- Wat SM3 --:--------------- Gas SM3 ---------------: \n " ;
}
if ( units . getType () == Opm :: UnitSystem :: UnitType :: UNIT_TYPE_FIELD ) {
2018-01-17 15:24:24 +01:00
ss << " : PAV =" << std :: setw ( 14 ) << pav << " PSIA : \n "
2018-01-12 15:32:43 +01:00
<< std :: fixed << std :: setprecision ( 0 )
2018-01-29 12:23:23 +01:00
<< " : PORV =" << std :: setw ( 14 ) << cip [ FipDataType :: PoreVolume ] << " RB : \n " ;
2018-01-12 15:32:43 +01:00
if ( ! reg ) {
ss << " : Pressure is weighted by hydrocarbon pore volume : \n "
<< " : Pore volumes are taken at reference conditions : \n " ;
}
ss << " :--------------- Oil STB ---------------:-- Wat STB --:--------------- Gas MSCF ---------------: \n " ;
}
ss << " : Liquid Vapour Total : Total : Free Dissolved Total :" << " \n "
<< ":------------------------:------------------------------------------:----------------:------------------------------------------:" << " \n "
2018-01-29 12:23:23 +01:00
<< ":Currently in place :" << std :: setw ( 14 ) << cip [ FipDataType :: OilInPlaceInLiquidPhase ] << std :: setw ( 14 ) << cip [ FipDataType :: OilInPlaceInGasPhase ] << std :: setw ( 14 ) << cip [ FipDataType :: OilInPlace ] << ":"
<< std :: setw ( 13 ) << cip [ FipDataType :: WaterInPlace ] << " :" << std :: setw ( 14 ) << ( cip [ FipDataType :: GasInPlaceInGasPhase ]) << std :: setw ( 14 ) << cip [ FipDataType :: GasInPlaceInLiquidPhase ] << std :: setw ( 14 ) << cip [ FipDataType :: GasInPlace ] << ": \n "
2018-01-12 15:32:43 +01:00
<< ":------------------------:------------------------------------------:----------------:------------------------------------------: \n "
2018-01-29 12:23:23 +01:00
<< ":Originally in place :" << std :: setw ( 14 ) << oip [ FipDataType :: OilInPlaceInLiquidPhase ] << std :: setw ( 14 ) << oip [ FipDataType :: OilInPlaceInGasPhase ] << std :: setw ( 14 ) << oip [ FipDataType :: OilInPlace ] << ":"
<< std :: setw ( 13 ) << oip [ FipDataType :: WaterInPlace ] << " :" << std :: setw ( 14 ) << oip [ FipDataType :: GasInPlaceInGasPhase ] << std :: setw ( 14 ) << oip [ FipDataType :: GasInPlaceInLiquidPhase ] << std :: setw ( 14 ) << oip [ FipDataType :: GasInPlace ] << ": \n "
2018-01-12 15:32:43 +01:00
<< ":========================:==========================================:================:==========================================: \n " ;
Opm :: OpmLog :: note ( ss . str ());
}
2018-04-30 17:17:22 +02:00
std :: string fipEnumToString_ ( int i )
{
2018-01-29 12:23:23 +01:00
typedef typename FipDataType :: FipId FipId ;
2018-04-30 17:17:22 +02:00
switch ( static_cast < FipId > ( i ))
2018-01-12 15:32:43 +01:00
{
2018-01-29 12:23:23 +01:00
case FipDataType :: WaterInPlace : return "WIP" ;
case FipDataType :: OilInPlace : return "OIP" ;
case FipDataType :: GasInPlace : return "GIP" ;
case FipDataType :: OilInPlaceInLiquidPhase : return "OIPL" ;
case FipDataType :: OilInPlaceInGasPhase : return "OIPG" ;
case FipDataType :: GasInPlaceInLiquidPhase : return "GIPL" ;
case FipDataType :: GasInPlaceInGasPhase : return "GIPG" ;
case FipDataType :: PoreVolume : return "PV" ;
2018-01-12 15:32:43 +01:00
}
return "ERROR" ;
}
2017-12-07 12:38:48 +01:00
const Simulator & simulator_ ;
2018-01-22 13:38:50 +01:00
bool outputFipRestart_ ;
2018-01-23 09:46:56 +01:00
bool computeFip_ ;
2018-07-26 12:31:32 +02:00
bool forceDisableFipOutput_ ;
2018-01-19 15:45:42 +01:00
2014-11-28 12:58:48 +01:00
ScalarBuffer saturation_ [ numPhases ];
2017-12-07 12:38:48 +01:00
ScalarBuffer oilPressure_ ;
ScalarBuffer temperature_ ;
2014-11-28 12:58:48 +01:00
ScalarBuffer gasDissolutionFactor_ ;
2016-11-15 18:00:48 +01:00
ScalarBuffer oilVaporizationFactor_ ;
2015-01-26 11:55:37 +01:00
ScalarBuffer gasFormationVolumeFactor_ ;
2017-12-07 12:38:48 +01:00
ScalarBuffer saturatedOilFormationVolumeFactor_ ;
2014-11-28 12:58:48 +01:00
ScalarBuffer oilSaturationPressure_ ;
2017-12-07 12:38:48 +01:00
ScalarBuffer rs_ ;
ScalarBuffer rv_ ;
ScalarBuffer invB_ [ numPhases ];
ScalarBuffer density_ [ numPhases ];
ScalarBuffer viscosity_ [ numPhases ];
ScalarBuffer relativePermeability_ [ numPhases ];
ScalarBuffer sSol_ ;
ScalarBuffer cPolymer_ ;
ScalarBuffer soMax_ ;
ScalarBuffer pcSwMdcOw_ ;
ScalarBuffer krnSwMdcOw_ ;
ScalarBuffer pcSwMdcGo_ ;
ScalarBuffer krnSwMdcGo_ ;
2018-09-07 10:19:00 +02:00
ScalarBuffer ppcw_ ;
2017-12-07 12:38:48 +01:00
ScalarBuffer bubblePointPressure_ ;
ScalarBuffer dewPointPressure_ ;
2019-03-12 15:51:41 +01:00
ScalarBuffer rockCompPorvMultiplier_ ;
ScalarBuffer rockCompTransMultiplier_ ;
ScalarBuffer swMax_ ;
ScalarBuffer overburdenPressure_ ;
ScalarBuffer minimumOilPressure_ ;
2017-12-07 12:38:48 +01:00
std :: vector < int > failedCellsPb_ ;
std :: vector < int > failedCellsPd_ ;
2018-01-12 15:32:43 +01:00
std :: vector < int > fipnum_ ;
2018-01-29 12:23:23 +01:00
ScalarBuffer fip_ [ FipDataType :: numFipValues ];
2018-01-12 15:32:43 +01:00
ScalarBuffer origTotalValues_ ;
2018-01-29 12:23:23 +01:00
ScalarBuffer origRegionValues_ [ FipDataType :: numFipValues ];
2018-01-29 08:43:42 +01:00
ScalarBuffer hydrocarbonPoreVolume_ ;
ScalarBuffer pressureTimesPoreVolume_ ;
ScalarBuffer pressureTimesHydrocarbonVolume_ ;
2018-02-09 12:57:34 +01:00
std :: map < std :: pair < std :: string , int > , double > blockData_ ;
2018-06-28 15:49:45 +02:00
std :: map < size_t , Scalar > oilConnectionPressures_ ;
std :: map < size_t , Scalar > waterConnectionSaturations_ ;
std :: map < size_t , Scalar > gasConnectionSaturations_ ;
2018-11-14 13:10:01 +01:00
std :: vector < ScalarBuffer > tracerConcentrations_ ;
2014-11-28 12:58:48 +01:00
};
} // namespace Ewoms
#endif