2013-03-18 11:40:39 +01:00
/////////////////////////////////////////////////////////////////////////////////
//
2014-09-24 07:14:52 +02:00
// Copyright (C) Statoil ASA
// Copyright (C) Ceetron Solutions AS
2013-03-18 11:40:39 +01:00
//
// ResInsight 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 3 of the License, or
// (at your option) any later version.
//
// ResInsight 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 at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
2014-07-24 14:03:17 +02:00
#include "RimReservoirCellResultsStorage.h"
2014-07-24 10:11:43 +02:00
2014-08-22 08:07:00 +02:00
#include "RigActiveCellInfo.h"
2014-08-27 14:05:29 +02:00
#include "RigCaseCellResultsData.h"
2017-01-10 09:51:39 +01:00
#include "RigEclipseCaseData.h"
2014-08-22 08:07:00 +02:00
#include "RigCell.h"
2014-08-27 14:05:29 +02:00
#include "RigMainGrid.h"
2015-05-15 09:16:33 +02:00
#include "RimEclipseCase.h"
2014-07-24 10:11:43 +02:00
#include "RimTools.h"
2017-05-31 16:16:28 +02:00
#include "RimProject.h"
#include "RimCompletionCellIntersectionCalc.h"
2014-07-24 10:11:43 +02:00
2013-03-21 15:31:47 +01:00
#include "cafProgressInfo.h"
2017-05-11 09:23:13 +02:00
#include "cafUtils.h"
2013-05-06 10:55:00 +02:00
2014-08-27 14:05:29 +02:00
#include "cvfGeometryTools.h"
2014-07-24 10:11:43 +02:00
#include <QDebug>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QUuid>
2013-03-18 11:40:39 +01:00
2013-03-19 10:29:34 +01:00
CAF_PDM_SOURCE_INIT ( RimReservoirCellResultsStorage , "ReservoirCellResultStorage" );
2013-03-18 11:40:39 +01:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2013-03-19 10:29:34 +01:00
RimReservoirCellResultsStorage :: RimReservoirCellResultsStorage ()
2013-03-18 14:34:29 +01:00
: m_cellResults ( NULL ),
2014-04-25 14:36:34 +02:00
m_ownerMainGrid ( NULL )
2013-03-18 11:40:39 +01:00
{
CAF_PDM_InitObject ( "Cacher" , "" , "" , "" );
CAF_PDM_InitField ( & m_resultCacheFileName , "ResultCacheFileName" , QString (), "UiDummyname" , "" , "" , "" );
2015-08-05 13:27:36 +02:00
m_resultCacheFileName . uiCapability () -> setUiHidden ( true );
2013-03-18 11:40:39 +01:00
CAF_PDM_InitFieldNoDefault ( & m_resultCacheMetaData , "ResultCacheEntries" , "UiDummyname" , "" , "" , "" );
2015-08-05 13:27:36 +02:00
m_resultCacheMetaData . uiCapability () -> setUiHidden ( true );
2013-03-18 11:40:39 +01:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2013-03-19 10:29:34 +01:00
RimReservoirCellResultsStorage ::~ RimReservoirCellResultsStorage ()
2013-03-18 11:40:39 +01:00
{
m_resultCacheMetaData . deleteAllChildObjects ();
}
//--------------------------------------------------------------------------------------------------
2013-03-22 16:58:44 +01:00
/// This override populates the metainfo regarding the cell results data in the RigCaseCellResultsData
2013-03-19 09:08:37 +01:00
/// object. This metainfo will then be written to the project file when saving, and thus read on project file open.
/// This method then writes the actual double arrays to the data file in a simple format:
/// MagicNumber<uint32>, Version<uint32>, ResultVariables< Array < TimeStep< CellDataArraySize<uint64>, CellData< Array<double > > > >
2013-03-18 11:40:39 +01:00
///
//--------------------------------------------------------------------------------------------------
2013-03-19 10:29:34 +01:00
void RimReservoirCellResultsStorage :: setupBeforeSave ()
2013-03-18 11:40:39 +01:00
{
2013-03-21 15:31:47 +01:00
m_resultCacheMetaData . deleteAllChildObjects ();
QString newValidCacheFileName = getValidCacheFileName ();
// Delete the storage file
QFileInfo storageFileInfo ( newValidCacheFileName );
if ( storageFileInfo . exists ())
{
QDir storageDir = storageFileInfo . dir ();
storageDir . remove ( storageFileInfo . fileName ());
}
2013-03-18 11:40:39 +01:00
if ( ! m_cellResults ) return ;
2013-03-22 15:43:42 +01:00
const std :: vector < RigCaseCellResultsData :: ResultInfo >& resInfo = m_cellResults -> infoForEachResultIndex ();
2013-03-18 11:40:39 +01:00
2013-03-21 15:31:47 +01:00
bool hasResultsToStore = false ;
for ( size_t rIdx = 0 ; rIdx < resInfo . size (); ++ rIdx )
{
if ( resInfo [ rIdx ]. m_needsToBeStored )
{
hasResultsToStore = true ;
break ;
}
}
if ( resInfo . size () && hasResultsToStore )
2013-03-18 11:40:39 +01:00
{
QDir :: root (). mkpath ( getCacheDirectoryPath ());
QFile cacheFile ( newValidCacheFileName );
2013-03-19 09:48:30 +01:00
if ( ! cacheFile . open ( QIODevice :: WriteOnly ))
{
qWarning () << "Saving project: Can't open the cache file : " + newValidCacheFileName ;
return ;
}
m_resultCacheFileName = newValidCacheFileName ;
2013-03-18 11:40:39 +01:00
QDataStream stream ( & cacheFile );
2013-03-21 15:31:47 +01:00
stream . setVersion ( QDataStream :: Qt_4_6 );
2013-03-18 11:40:39 +01:00
stream << ( quint32 ) 0xCEECAC4E ; // magic number
2013-03-19 09:08:37 +01:00
stream << ( quint32 ) 1 ; // Version number. Increment if needing to extend the format in ways that can not be handled generically by the reader
2013-03-18 11:40:39 +01:00
2013-03-21 15:31:47 +01:00
caf :: ProgressInfo progInfo ( resInfo . size (), "Saving generated and imported properties" );
2013-03-19 08:15:27 +01:00
for ( size_t rIdx = 0 ; rIdx < resInfo . size (); ++ rIdx )
2013-03-18 11:40:39 +01:00
{
2013-03-21 15:31:47 +01:00
// If there is no data, we do not store anything for the current result variable
// (Even not the metadata, of cause)
2013-03-18 14:34:29 +01:00
size_t timestepCount = m_cellResults -> cellScalarResults ( resInfo [ rIdx ]. m_gridScalarResultIndex ). size ();
2014-04-25 14:36:34 +02:00
2013-03-21 15:31:47 +01:00
if ( timestepCount && resInfo [ rIdx ]. m_needsToBeStored )
2013-03-18 14:34:29 +01:00
{
2013-03-21 15:31:47 +01:00
progInfo . setProgressDescription ( resInfo [ rIdx ]. m_resultName );
2013-03-19 09:08:37 +01:00
// Create and setup the cache information for this result
2013-03-19 10:29:34 +01:00
RimReservoirCellResultsStorageEntryInfo * cacheEntry = new RimReservoirCellResultsStorageEntryInfo ;
2013-03-18 14:34:29 +01:00
m_resultCacheMetaData . push_back ( cacheEntry );
2013-03-18 11:40:39 +01:00
2013-03-18 14:34:29 +01:00
cacheEntry -> m_resultType = resInfo [ rIdx ]. m_resultType ;
cacheEntry -> m_resultName = resInfo [ rIdx ]. m_resultName ;
cacheEntry -> m_timeStepDates = resInfo [ rIdx ]. m_timeStepDates ;
2017-04-26 09:39:17 +02:00
cacheEntry -> m_daysSinceSimulationStart = resInfo [ rIdx ]. m_daysSinceSimulationStart ;
2013-03-18 11:40:39 +01:00
2013-03-19 09:08:37 +01:00
// Take note of the file position for fast lookup later
2013-03-18 14:34:29 +01:00
cacheEntry -> m_filePosition = cacheFile . pos ();
2013-03-18 11:40:39 +01:00
2013-03-19 09:08:37 +01:00
// Write all the scalar values for each time step to the stream,
// starting with the number of values
2013-03-19 08:15:27 +01:00
for ( size_t tsIdx = 0 ; tsIdx < resInfo [ rIdx ]. m_timeStepDates . size () ; ++ tsIdx )
2013-03-18 11:40:39 +01:00
{
2013-03-18 14:34:29 +01:00
const std :: vector < double >* data = NULL ;
if ( tsIdx < timestepCount )
{
data = & ( m_cellResults -> cellScalarResults ( resInfo [ rIdx ]. m_gridScalarResultIndex , tsIdx ));
}
2013-03-18 11:40:39 +01:00
2013-03-18 14:34:29 +01:00
if ( data && data -> size ())
2013-03-18 11:40:39 +01:00
{
2013-03-18 14:34:29 +01:00
2013-03-19 09:08:37 +01:00
stream << ( quint64 )( data -> size ());
2013-03-18 14:34:29 +01:00
for ( size_t cIdx = 0 ; cIdx < data -> size (); ++ cIdx )
{
stream << ( * data )[ cIdx ];
}
}
else
{
2013-03-19 09:08:37 +01:00
stream << ( quint64 ) 0 ;
2013-03-18 11:40:39 +01:00
}
}
}
2013-03-21 15:31:47 +01:00
progInfo . incrementProgress ();
2013-03-18 11:40:39 +01:00
}
}
}
2013-03-21 15:31:47 +01:00
2013-03-18 11:40:39 +01:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2013-03-19 10:29:34 +01:00
QString RimReservoirCellResultsStorage :: getValidCacheFileName ()
2013-03-18 11:40:39 +01:00
{
QString cacheFileName ;
if ( m_resultCacheFileName (). isEmpty ())
{
QString newCacheDirPath = getCacheDirectoryPath ();
QUuid guid = QUuid :: createUuid ();
cacheFileName = newCacheDirPath + "/" + guid . toString ();
}
else
{
// Make the path correct related to the possibly new project filename
QString newCacheDirPath = getCacheDirectoryPath ();
QFileInfo oldCacheFile ( m_resultCacheFileName ());
cacheFileName = newCacheDirPath + "/" + oldCacheFile . fileName ();
}
return cacheFileName ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2013-03-19 10:29:34 +01:00
QString RimReservoirCellResultsStorage :: getCacheDirectoryPath ()
2013-03-18 11:40:39 +01:00
{
2013-10-24 09:50:16 +02:00
QString cacheDirPath = RimTools :: getCacheRootDirectoryPathFromProject ();
cacheDirPath += "_cache" ;
2013-03-18 11:40:39 +01:00
return cacheDirPath ;
}
2013-03-18 14:34:29 +01:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2013-03-19 10:29:34 +01:00
void RimReservoirCellResultsStorage :: setReaderInterface ( RifReaderInterface * readerInterface )
2013-03-18 14:34:29 +01:00
{
m_readerInterface = readerInterface ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2013-03-19 10:29:34 +01:00
RifReaderInterface * RimReservoirCellResultsStorage :: readerInterface ()
2013-03-18 14:34:29 +01:00
{
return m_readerInterface . p ();
}
2014-08-26 14:06:55 +02:00
2013-03-18 14:34:29 +01:00
//--------------------------------------------------------------------------------------------------
2014-08-26 14:06:55 +02:00
///
2013-03-18 14:34:29 +01:00
//--------------------------------------------------------------------------------------------------
2014-08-26 14:06:55 +02:00
size_t RimReservoirCellResultsStorage :: findOrLoadScalarResult ( const QString & resultName )
2013-03-18 14:34:29 +01:00
{
2013-04-10 11:37:34 +02:00
if ( ! m_cellResults ) return cvf :: UNDEFINED_SIZE_T ;
2017-06-13 15:41:52 +02:00
size_t scalarResultIndex = this -> findOrLoadScalarResult ( RiaDefines :: STATIC_NATIVE , resultName );
2013-03-18 14:34:29 +01:00
2014-08-26 14:06:55 +02:00
if ( scalarResultIndex == cvf :: UNDEFINED_SIZE_T )
2013-03-18 14:34:29 +01:00
{
2017-06-13 15:41:52 +02:00
scalarResultIndex = this -> findOrLoadScalarResult ( RiaDefines :: DYNAMIC_NATIVE , resultName );
2013-03-18 14:34:29 +01:00
}
2014-08-26 14:06:55 +02:00
if ( scalarResultIndex == cvf :: UNDEFINED_SIZE_T )
2013-03-18 14:34:29 +01:00
{
2017-06-13 15:41:52 +02:00
scalarResultIndex = m_cellResults -> findScalarResultIndex ( RiaDefines :: GENERATED , resultName );
2014-08-26 14:06:55 +02:00
}
2013-03-18 14:34:29 +01:00
2014-08-26 14:06:55 +02:00
if ( scalarResultIndex == cvf :: UNDEFINED_SIZE_T )
{
2017-06-13 15:41:52 +02:00
scalarResultIndex = m_cellResults -> findScalarResultIndex ( RiaDefines :: INPUT_PROPERTY , resultName );
2013-03-18 14:34:29 +01:00
}
return scalarResultIndex ;
}
2017-05-31 16:16:28 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-06-13 15:41:52 +02:00
void RimReservoirCellResultsStorage :: clearScalarResult ( RiaDefines :: ResultCatType type , const QString & resultName )
2017-05-31 16:16:28 +02:00
{
size_t scalarResultIndex = m_cellResults -> findScalarResultIndex ( type , resultName );
m_cellResults -> cellScalarResults ( scalarResultIndex ). clear ();
}
2014-08-26 14:06:55 +02:00
2013-03-18 14:34:29 +01:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-06-13 15:41:52 +02:00
size_t RimReservoirCellResultsStorage :: findOrLoadScalarResult ( RiaDefines :: ResultCatType type , const QString & resultName )
2013-03-18 14:34:29 +01:00
{
2013-04-08 08:23:06 +02:00
if ( ! m_cellResults ) return cvf :: UNDEFINED_SIZE_T ;
2013-03-18 14:34:29 +01:00
2014-08-20 11:33:03 +02:00
size_t scalarResultIndex = m_cellResults -> findScalarResultIndex ( type , resultName );
if ( scalarResultIndex == cvf :: UNDEFINED_SIZE_T ) return cvf :: UNDEFINED_SIZE_T ;
2013-03-18 14:34:29 +01:00
2014-08-25 13:20:58 +02:00
// Load dependency data sets
2017-06-13 15:41:52 +02:00
if ( type == RiaDefines :: STATIC_NATIVE )
2014-08-25 13:20:58 +02:00
{
2017-06-13 15:41:52 +02:00
if ( resultName == RiaDefines :: combinedTransmissibilityResultName ())
2014-08-25 13:20:58 +02:00
{
this -> findOrLoadScalarResult ( type , "TRANX" );
this -> findOrLoadScalarResult ( type , "TRANY" );
this -> findOrLoadScalarResult ( type , "TRANZ" );
}
2017-06-13 15:41:52 +02:00
else if ( resultName == RiaDefines :: combinedMultResultName ())
2014-08-25 13:20:58 +02:00
{
this -> findOrLoadScalarResult ( type , "MULTX" );
this -> findOrLoadScalarResult ( type , "MULTX-" );
this -> findOrLoadScalarResult ( type , "MULTY" );
this -> findOrLoadScalarResult ( type , "MULTY-" );
this -> findOrLoadScalarResult ( type , "MULTZ" );
this -> findOrLoadScalarResult ( type , "MULTZ-" );
}
2017-06-13 15:41:52 +02:00
else if ( resultName == RiaDefines :: combinedRiTranResultName ())
2014-08-26 15:32:19 +02:00
{
2017-06-13 15:41:52 +02:00
computeRiTransComponent ( RiaDefines :: riTranXResultName ());
computeRiTransComponent ( RiaDefines :: riTranYResultName ());
computeRiTransComponent ( RiaDefines :: riTranZResultName ());
2014-08-26 15:32:19 +02:00
computeNncCombRiTrans ();
}
2017-06-13 15:41:52 +02:00
else if ( resultName == RiaDefines :: riTranXResultName ()
|| resultName == RiaDefines :: riTranYResultName ()
|| resultName == RiaDefines :: riTranZResultName ())
2014-08-26 15:32:19 +02:00
{
computeRiTransComponent ( resultName );
}
2017-06-13 15:41:52 +02:00
else if ( resultName == RiaDefines :: combinedRiMultResultName ())
2014-08-26 15:32:19 +02:00
{
2017-06-13 15:41:52 +02:00
computeRiMULTComponent ( RiaDefines :: riMultXResultName ());
computeRiMULTComponent ( RiaDefines :: riMultYResultName ());
computeRiMULTComponent ( RiaDefines :: riMultZResultName ());
2014-08-26 16:50:11 +02:00
computeNncCombRiTrans ();
2014-08-26 15:32:19 +02:00
computeNncCombRiMULT ();
}
2017-06-13 15:41:52 +02:00
else if ( resultName == RiaDefines :: riMultXResultName ()
|| resultName == RiaDefines :: riMultYResultName ()
|| resultName == RiaDefines :: riMultZResultName ())
2014-08-26 15:32:19 +02:00
{
computeRiMULTComponent ( resultName );
}
2017-06-13 15:41:52 +02:00
else if ( resultName == RiaDefines :: combinedRiAreaNormTranResultName ())
2014-08-27 11:41:08 +02:00
{
2017-06-13 15:41:52 +02:00
computeRiTRANSbyAreaComponent ( RiaDefines :: riAreaNormTranXResultName ());
computeRiTRANSbyAreaComponent ( RiaDefines :: riAreaNormTranYResultName ());
computeRiTRANSbyAreaComponent ( RiaDefines :: riAreaNormTranZResultName ());
2014-08-27 11:41:08 +02:00
computeNncCombRiTRANSbyArea ();
}
2017-06-13 15:41:52 +02:00
else if ( resultName == RiaDefines :: riAreaNormTranXResultName ()
|| resultName == RiaDefines :: riAreaNormTranYResultName ()
|| resultName == RiaDefines :: riAreaNormTranZResultName ())
2014-08-27 11:41:08 +02:00
{
computeRiTRANSbyAreaComponent ( resultName );
}
2014-08-25 13:20:58 +02:00
}
2014-08-21 08:39:19 +02:00
if ( isDataPresent ( scalarResultIndex ))
{
return scalarResultIndex ;
}
2013-03-21 15:31:47 +01:00
2014-08-21 08:39:19 +02:00
if ( resultName == "SOIL" )
2013-03-21 15:31:47 +01:00
{
2014-08-28 10:35:05 +02:00
if ( m_cellResults -> mustBeCalculated ( scalarResultIndex ))
2013-03-21 15:31:47 +01:00
{
2014-08-28 10:35:05 +02:00
// Trigger loading of SWAT, SGAS to establish time step count if no data has been loaded from file at this point
2017-06-13 15:41:52 +02:00
findOrLoadScalarResult ( RiaDefines :: DYNAMIC_NATIVE , "SWAT" );
findOrLoadScalarResult ( RiaDefines :: DYNAMIC_NATIVE , "SGAS" );
2014-08-21 08:39:19 +02:00
2014-08-28 10:35:05 +02:00
m_cellResults -> cellScalarResults ( scalarResultIndex ). resize ( m_cellResults -> maxTimeStepCount ());
for ( size_t timeStepIdx = 0 ; timeStepIdx < m_cellResults -> maxTimeStepCount (); timeStepIdx ++ )
{
std :: vector < double >& values = m_cellResults -> cellScalarResults ( scalarResultIndex )[ timeStepIdx ];
if ( values . size () == 0 )
{
computeSOILForTimeStep ( timeStepIdx );
}
}
2013-03-18 14:34:29 +01:00
2014-08-28 10:35:05 +02:00
return scalarResultIndex ;
}
}
2017-06-13 15:41:52 +02:00
else if ( resultName == RiaDefines :: completionTypeResultName ())
2017-05-31 16:16:28 +02:00
{
m_cellResults -> cellScalarResults ( scalarResultIndex ). resize ( m_cellResults -> maxTimeStepCount ());
for ( size_t timeStepIdx = 0 ; timeStepIdx < m_cellResults -> maxTimeStepCount (); ++ timeStepIdx )
{
computeCompletionTypeForTimeStep ( timeStepIdx );
}
}
2014-08-22 13:38:03 +02:00
2017-06-13 15:41:52 +02:00
if ( type == RiaDefines :: GENERATED )
2013-03-18 14:34:29 +01:00
{
return cvf :: UNDEFINED_SIZE_T ;
}
if ( m_readerInterface . notNull ())
{
// Add one more result to result container
2014-08-20 11:33:03 +02:00
size_t timeStepCount = m_cellResults -> infoForEachResultIndex ()[ scalarResultIndex ]. m_timeStepDates . size ();
2013-03-18 14:34:29 +01:00
bool resultLoadingSucess = true ;
2017-06-13 15:41:52 +02:00
if ( type == RiaDefines :: DYNAMIC_NATIVE && timeStepCount > 0 )
2013-03-18 14:34:29 +01:00
{
2014-08-20 11:33:03 +02:00
m_cellResults -> cellScalarResults ( scalarResultIndex ). resize ( timeStepCount );
2013-03-18 14:34:29 +01:00
size_t i ;
for ( i = 0 ; i < timeStepCount ; i ++ )
{
2014-08-20 11:33:03 +02:00
std :: vector < double >& values = m_cellResults -> cellScalarResults ( scalarResultIndex )[ i ];
2013-03-18 14:34:29 +01:00
if ( ! m_readerInterface -> dynamicResult ( resultName , RifReaderInterface :: MATRIX_RESULTS , i , & values ))
{
resultLoadingSucess = false ;
}
}
}
2017-06-13 15:41:52 +02:00
else if ( type == RiaDefines :: STATIC_NATIVE )
2013-03-18 14:34:29 +01:00
{
2014-08-20 11:33:03 +02:00
m_cellResults -> cellScalarResults ( scalarResultIndex ). resize ( 1 );
2013-03-18 14:34:29 +01:00
2014-08-20 11:33:03 +02:00
std :: vector < double >& values = m_cellResults -> cellScalarResults ( scalarResultIndex )[ 0 ];
2013-03-18 14:34:29 +01:00
if ( ! m_readerInterface -> staticResult ( resultName , RifReaderInterface :: MATRIX_RESULTS , & values ))
{
resultLoadingSucess = false ;
}
}
if ( ! resultLoadingSucess )
{
// Remove last scalar result because loading of result failed
2014-08-20 11:33:03 +02:00
m_cellResults -> cellScalarResults ( scalarResultIndex ). clear ();
2013-03-18 14:34:29 +01:00
}
}
2014-08-20 11:33:03 +02:00
return scalarResultIndex ;
2013-03-18 14:34:29 +01:00
}
2014-08-26 14:06:55 +02:00
//--------------------------------------------------------------------------------------------------
/// This method is intended to be used for multicase cross statistical calculations, when
/// we need process one timestep at a time, freeing memory as we go.
//--------------------------------------------------------------------------------------------------
2017-06-13 15:41:52 +02:00
size_t RimReservoirCellResultsStorage :: findOrLoadScalarResultForTimeStep ( RiaDefines :: ResultCatType type , const QString & resultName , size_t timeStepIndex )
2014-08-26 14:06:55 +02:00
{
if ( ! m_cellResults ) return cvf :: UNDEFINED_SIZE_T ;
// Special handling for SOIL
2017-06-13 15:41:52 +02:00
if ( type == RiaDefines :: DYNAMIC_NATIVE && resultName . toUpper () == "SOIL" )
2014-08-26 14:06:55 +02:00
{
size_t soilScalarResultIndex = m_cellResults -> findScalarResultIndex ( type , resultName );
2014-08-28 10:35:05 +02:00
if ( m_cellResults -> mustBeCalculated ( soilScalarResultIndex ))
2014-08-26 14:06:55 +02:00
{
2016-08-09 15:10:16 +02:00
m_cellResults -> cellScalarResults ( soilScalarResultIndex ). resize ( m_cellResults -> maxTimeStepCount ());
2014-08-28 10:35:05 +02:00
std :: vector < double >& values = m_cellResults -> cellScalarResults ( soilScalarResultIndex )[ timeStepIndex ];
if ( values . size () == 0 )
{
computeSOILForTimeStep ( timeStepIndex );
}
2014-08-26 14:06:55 +02:00
2014-08-28 10:35:05 +02:00
return soilScalarResultIndex ;
}
2014-08-26 14:06:55 +02:00
}
2017-06-13 15:41:52 +02:00
else if ( type == RiaDefines :: DYNAMIC_NATIVE && resultName == RiaDefines :: completionTypeResultName ())
2017-05-31 16:16:28 +02:00
{
size_t completionTypeScalarResultIndex = m_cellResults -> findScalarResultIndex ( type , resultName );
computeCompletionTypeForTimeStep ( timeStepIndex );
return completionTypeScalarResultIndex ;
}
2014-08-26 14:06:55 +02:00
size_t scalarResultIndex = m_cellResults -> findScalarResultIndex ( type , resultName );
if ( scalarResultIndex == cvf :: UNDEFINED_SIZE_T ) return cvf :: UNDEFINED_SIZE_T ;
2017-06-13 15:41:52 +02:00
if ( type == RiaDefines :: GENERATED )
2014-08-26 14:06:55 +02:00
{
return cvf :: UNDEFINED_SIZE_T ;
}
if ( m_readerInterface . notNull ())
{
size_t timeStepCount = m_cellResults -> infoForEachResultIndex ()[ scalarResultIndex ]. m_timeStepDates . size ();
bool resultLoadingSucess = true ;
2017-06-13 15:41:52 +02:00
if ( type == RiaDefines :: DYNAMIC_NATIVE && timeStepCount > 0 )
2014-08-26 14:06:55 +02:00
{
m_cellResults -> cellScalarResults ( scalarResultIndex ). resize ( timeStepCount );
std :: vector < double >& values = m_cellResults -> cellScalarResults ( scalarResultIndex )[ timeStepIndex ];
if ( values . size () == 0 )
{
if ( ! m_readerInterface -> dynamicResult ( resultName , RifReaderInterface :: MATRIX_RESULTS , timeStepIndex , & values ))
{
resultLoadingSucess = false ;
}
}
}
2017-06-13 15:41:52 +02:00
else if ( type == RiaDefines :: STATIC_NATIVE )
2014-08-26 14:06:55 +02:00
{
m_cellResults -> cellScalarResults ( scalarResultIndex ). resize ( 1 );
std :: vector < double >& values = m_cellResults -> cellScalarResults ( scalarResultIndex )[ 0 ];
if ( ! m_readerInterface -> staticResult ( resultName , RifReaderInterface :: MATRIX_RESULTS , & values ))
{
resultLoadingSucess = false ;
}
}
if ( ! resultLoadingSucess )
{
// Error logging
CVF_ASSERT ( false );
}
}
return scalarResultIndex ;
}
2013-03-18 14:34:29 +01:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2013-04-10 11:37:34 +02:00
void RimReservoirCellResultsStorage :: computeSOILForTimeStep ( size_t timeStepIndex )
2013-03-18 14:34:29 +01:00
{
2017-06-13 15:41:52 +02:00
size_t scalarIndexSWAT = findOrLoadScalarResultForTimeStep ( RiaDefines :: DYNAMIC_NATIVE , "SWAT" , timeStepIndex );
size_t scalarIndexSGAS = findOrLoadScalarResultForTimeStep ( RiaDefines :: DYNAMIC_NATIVE , "SGAS" , timeStepIndex );
2013-03-18 14:34:29 +01:00
// Early exit if none of SWAT or SGAS is present
if ( scalarIndexSWAT == cvf :: UNDEFINED_SIZE_T && scalarIndexSGAS == cvf :: UNDEFINED_SIZE_T )
{
return ;
}
2013-04-08 08:23:06 +02:00
CVF_ASSERT ( m_cellResults );
2013-03-18 14:34:29 +01:00
size_t soilResultValueCount = 0 ;
size_t soilTimeStepCount = 0 ;
if ( scalarIndexSWAT != cvf :: UNDEFINED_SIZE_T )
{
2014-04-25 14:36:34 +02:00
std :: vector < double >& swatForTimeStep = m_cellResults -> cellScalarResults ( scalarIndexSWAT , timeStepIndex );
if ( swatForTimeStep . size () > 0 )
2013-03-18 14:34:29 +01:00
{
2014-04-25 14:36:34 +02:00
soilResultValueCount = swatForTimeStep . size ();
2013-03-18 14:34:29 +01:00
soilTimeStepCount = m_cellResults -> infoForEachResultIndex ()[ scalarIndexSWAT ]. m_timeStepDates . size ();
}
}
if ( scalarIndexSGAS != cvf :: UNDEFINED_SIZE_T )
{
2014-04-25 14:36:34 +02:00
std :: vector < double >& sgasForTimeStep = m_cellResults -> cellScalarResults ( scalarIndexSGAS , timeStepIndex );
if ( sgasForTimeStep . size () > 0 )
2013-03-18 14:34:29 +01:00
{
2014-04-25 14:36:34 +02:00
soilResultValueCount = qMax ( soilResultValueCount , sgasForTimeStep . size ());
2013-03-18 14:34:29 +01:00
size_t sgasTimeStepCount = m_cellResults -> infoForEachResultIndex ()[ scalarIndexSGAS ]. m_timeStepDates . size ();
soilTimeStepCount = qMax ( soilTimeStepCount , sgasTimeStepCount );
}
}
2014-08-26 12:07:08 +02:00
2014-08-25 10:31:36 +02:00
// Make sure memory is allocated for the new SOIL results
2017-06-13 15:41:52 +02:00
size_t soilResultScalarIndex = m_cellResults -> findScalarResultIndex ( RiaDefines :: DYNAMIC_NATIVE , "SOIL" );
2014-08-25 10:31:36 +02:00
m_cellResults -> cellScalarResults ( soilResultScalarIndex ). resize ( soilTimeStepCount );
2014-08-25 13:20:58 +02:00
if ( m_cellResults -> cellScalarResults ( soilResultScalarIndex , timeStepIndex ). size () > 0 )
{
// Data is computed and allocated, nothing more to do
return ;
}
2014-08-25 10:31:36 +02:00
m_cellResults -> cellScalarResults ( soilResultScalarIndex , timeStepIndex ). resize ( soilResultValueCount );
2013-03-18 14:34:29 +01:00
2014-04-25 14:36:34 +02:00
std :: vector < double >* swatForTimeStep = NULL ;
std :: vector < double >* sgasForTimeStep = NULL ;
if ( scalarIndexSWAT != cvf :: UNDEFINED_SIZE_T )
{
swatForTimeStep = & ( m_cellResults -> cellScalarResults ( scalarIndexSWAT , timeStepIndex ));
if ( swatForTimeStep -> size () == 0 )
{
swatForTimeStep = NULL ;
}
}
if ( scalarIndexSGAS != cvf :: UNDEFINED_SIZE_T )
{
sgasForTimeStep = & ( m_cellResults -> cellScalarResults ( scalarIndexSGAS , timeStepIndex ));
if ( sgasForTimeStep -> size () == 0 )
{
sgasForTimeStep = NULL ;
}
}
2014-08-20 11:33:03 +02:00
std :: vector < double >& soilForTimeStep = m_cellResults -> cellScalarResults ( soilResultScalarIndex , timeStepIndex );
2013-03-18 14:34:29 +01:00
#pragma omp parallel for
for ( int idx = 0 ; idx < static_cast < int > ( soilResultValueCount ); idx ++ )
{
double soilValue = 1.0 ;
if ( sgasForTimeStep )
{
soilValue -= sgasForTimeStep -> at ( idx );
}
if ( swatForTimeStep )
{
soilValue -= swatForTimeStep -> at ( idx );
}
2014-09-08 08:50:42 +02:00
soilForTimeStep [ idx ] = soilValue ;
2013-03-18 14:34:29 +01:00
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2013-03-19 10:29:34 +01:00
void RimReservoirCellResultsStorage :: computeDepthRelatedResults ()
2013-03-18 14:34:29 +01:00
{
2013-04-08 08:23:06 +02:00
if ( ! m_cellResults ) return ;
2017-06-13 15:41:52 +02:00
size_t depthResultGridIndex = findOrLoadScalarResult ( RiaDefines :: STATIC_NATIVE , "DEPTH" );
size_t dxResultGridIndex = findOrLoadScalarResult ( RiaDefines :: STATIC_NATIVE , "DX" );
size_t dyResultGridIndex = findOrLoadScalarResult ( RiaDefines :: STATIC_NATIVE , "DY" );
size_t dzResultGridIndex = findOrLoadScalarResult ( RiaDefines :: STATIC_NATIVE , "DZ" );
size_t topsResultGridIndex = findOrLoadScalarResult ( RiaDefines :: STATIC_NATIVE , "TOPS" );
size_t bottomResultGridIndex = findOrLoadScalarResult ( RiaDefines :: STATIC_NATIVE , "BOTTOM" );
2013-03-18 14:34:29 +01:00
bool computeDepth = false ;
bool computeDx = false ;
bool computeDy = false ;
bool computeDz = false ;
bool computeTops = false ;
bool computeBottom = false ;
2015-11-24 14:21:02 +01:00
size_t resultValueCount = m_ownerMainGrid -> globalCellArray (). size ();
2013-03-18 14:34:29 +01:00
if ( depthResultGridIndex == cvf :: UNDEFINED_SIZE_T )
{
2017-06-13 15:41:52 +02:00
depthResultGridIndex = m_cellResults -> addStaticScalarResult ( RiaDefines :: STATIC_NATIVE , "DEPTH" , false , resultValueCount );
2013-03-18 14:34:29 +01:00
computeDepth = true ;
}
if ( dxResultGridIndex == cvf :: UNDEFINED_SIZE_T )
{
2017-06-13 15:41:52 +02:00
dxResultGridIndex = m_cellResults -> addStaticScalarResult ( RiaDefines :: STATIC_NATIVE , "DX" , false , resultValueCount );
2013-03-18 14:34:29 +01:00
computeDx = true ;
}
if ( dyResultGridIndex == cvf :: UNDEFINED_SIZE_T )
{
2017-06-13 15:41:52 +02:00
dyResultGridIndex = m_cellResults -> addStaticScalarResult ( RiaDefines :: STATIC_NATIVE , "DY" , false , resultValueCount );
2013-03-18 14:34:29 +01:00
computeDy = true ;
}
if ( dzResultGridIndex == cvf :: UNDEFINED_SIZE_T )
{
2017-06-13 15:41:52 +02:00
dzResultGridIndex = m_cellResults -> addStaticScalarResult ( RiaDefines :: STATIC_NATIVE , "DZ" , false , resultValueCount );
2013-03-18 14:34:29 +01:00
computeDz = true ;
}
if ( topsResultGridIndex == cvf :: UNDEFINED_SIZE_T )
{
2017-06-13 15:41:52 +02:00
topsResultGridIndex = m_cellResults -> addStaticScalarResult ( RiaDefines :: STATIC_NATIVE , "TOPS" , false , resultValueCount );
2013-03-18 14:34:29 +01:00
computeTops = true ;
}
if ( bottomResultGridIndex == cvf :: UNDEFINED_SIZE_T )
{
2017-06-13 15:41:52 +02:00
bottomResultGridIndex = m_cellResults -> addStaticScalarResult ( RiaDefines :: STATIC_NATIVE , "BOTTOM" , false , resultValueCount );
2013-03-18 14:34:29 +01:00
computeBottom = true ;
}
std :: vector < std :: vector < double > >& depth = m_cellResults -> cellScalarResults ( depthResultGridIndex );
std :: vector < std :: vector < double > >& dx = m_cellResults -> cellScalarResults ( dxResultGridIndex );
std :: vector < std :: vector < double > >& dy = m_cellResults -> cellScalarResults ( dyResultGridIndex );
std :: vector < std :: vector < double > >& dz = m_cellResults -> cellScalarResults ( dzResultGridIndex );
std :: vector < std :: vector < double > >& tops = m_cellResults -> cellScalarResults ( topsResultGridIndex );
std :: vector < std :: vector < double > >& bottom = m_cellResults -> cellScalarResults ( bottomResultGridIndex );
size_t cellIdx = 0 ;
2015-11-24 14:21:02 +01:00
for ( cellIdx = 0 ; cellIdx < m_ownerMainGrid -> globalCellArray (). size (); cellIdx ++ )
2013-03-18 14:34:29 +01:00
{
2015-11-24 14:21:02 +01:00
const RigCell & cell = m_ownerMainGrid -> globalCellArray ()[ cellIdx ];
2013-03-18 14:34:29 +01:00
if ( computeDepth )
{
depth [ 0 ][ cellIdx ] = cvf :: Math :: abs ( cell . center (). z ());
}
if ( computeDx )
{
cvf :: Vec3d cellWidth = cell . faceCenter ( cvf :: StructGridInterface :: NEG_I ) - cell . faceCenter ( cvf :: StructGridInterface :: POS_I );
2017-02-06 15:23:51 +01:00
dx [ 0 ][ cellIdx ] = cellWidth . length ();
2013-03-18 14:34:29 +01:00
}
if ( computeDy )
{
cvf :: Vec3d cellWidth = cell . faceCenter ( cvf :: StructGridInterface :: NEG_J ) - cell . faceCenter ( cvf :: StructGridInterface :: POS_J );
2017-02-06 15:23:51 +01:00
dy [ 0 ][ cellIdx ] = cellWidth . length ();
2013-03-18 14:34:29 +01:00
}
if ( computeDz )
{
cvf :: Vec3d cellWidth = cell . faceCenter ( cvf :: StructGridInterface :: NEG_K ) - cell . faceCenter ( cvf :: StructGridInterface :: POS_K );
2017-02-06 15:23:51 +01:00
dz [ 0 ][ cellIdx ] = cellWidth . length ();
2013-03-18 14:34:29 +01:00
}
if ( computeTops )
{
tops [ 0 ][ cellIdx ] = cvf :: Math :: abs ( cell . faceCenter ( cvf :: StructGridInterface :: NEG_K ). z ());
}
if ( computeBottom )
{
bottom [ 0 ][ cellIdx ] = cvf :: Math :: abs ( cell . faceCenter ( cvf :: StructGridInterface :: POS_K ). z ());
}
}
}
2014-08-26 13:36:38 +02:00
namespace RigTransmissibilityCalcTools
2014-08-22 08:07:00 +02:00
{
2014-08-26 13:36:38 +02:00
void calculateConnectionGeometry ( const RigCell & c1 , const RigCell & c2 , const std :: vector < cvf :: Vec3d >& nodes ,
2014-09-09 10:58:02 +02:00
cvf :: StructGridInterface :: FaceType faceId , cvf :: Vec3d * faceAreaVec )
2014-08-26 13:36:38 +02:00
{
2014-09-09 10:58:02 +02:00
CVF_TIGHT_ASSERT ( faceAreaVec );
2014-08-22 08:07:00 +02:00
2014-08-26 13:36:38 +02:00
* faceAreaVec = cvf :: Vec3d :: ZERO ;
2014-08-22 08:07:00 +02:00
2014-08-26 13:36:38 +02:00
std :: vector < size_t > polygon ;
std :: vector < cvf :: Vec3d > intersections ;
caf :: SizeTArray4 face1 ;
caf :: SizeTArray4 face2 ;
c1 . faceIndices ( faceId , & face1 );
c2 . faceIndices ( cvf :: StructGridInterface :: oppositeFace ( faceId ), & face2 );
2014-08-22 08:07:00 +02:00
2014-08-26 13:36:38 +02:00
bool foundOverlap = cvf :: GeometryTools :: calculateOverlapPolygonOfTwoQuads (
& polygon ,
& intersections ,
( cvf :: EdgeIntersectStorage < size_t >* ) NULL ,
cvf :: wrapArrayConst ( & nodes ),
face1 . data (),
face2 . data (),
1e-6 );
2014-08-22 08:07:00 +02:00
2014-08-26 13:36:38 +02:00
if ( foundOverlap )
2014-08-22 08:07:00 +02:00
{
2014-08-26 13:36:38 +02:00
std :: vector < cvf :: Vec3d > realPolygon ;
2014-08-22 08:07:00 +02:00
2014-08-26 13:36:38 +02:00
for ( size_t pIdx = 0 ; pIdx < polygon . size (); ++ pIdx )
{
if ( polygon [ pIdx ] < nodes . size ())
realPolygon . push_back ( nodes [ polygon [ pIdx ]]);
else
realPolygon . push_back ( intersections [ polygon [ pIdx ] - nodes . size ()]);
}
2014-08-22 08:07:00 +02:00
2014-08-26 13:36:38 +02:00
// Polygon area vector
2014-08-22 08:07:00 +02:00
2014-08-26 13:36:38 +02:00
* faceAreaVec = cvf :: GeometryTools :: polygonAreaNormal3D ( realPolygon );
2014-08-22 08:07:00 +02:00
2014-08-26 13:36:38 +02:00
}
2014-08-22 08:07:00 +02:00
2014-08-26 13:36:38 +02:00
}
2014-08-22 08:07:00 +02:00
2014-08-26 13:36:38 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double halfCellTransmissibility ( double perm , double ntg , const cvf :: Vec3d & centerToFace , const cvf :: Vec3d & faceAreaVec )
{
return perm * ntg * ( faceAreaVec * centerToFace ) / ( centerToFace * centerToFace );
}
2014-08-22 08:07:00 +02:00
2014-08-26 13:36:38 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double newtran ( double cdarchy , double mult , double halfCellTrans , double neighborHalfCellTrans )
{
2014-09-09 15:21:09 +02:00
if ( cvf :: Math :: abs ( halfCellTrans ) < 1e-15 || cvf :: Math :: abs ( neighborHalfCellTrans ) < 1e-15 )
{
return 0.0 ;
}
double result = cdarchy * mult / (( 1 / halfCellTrans ) + ( 1 / neighborHalfCellTrans ));
CVF_TIGHT_ASSERT ( result == result );
return result ;
2014-08-26 13:36:38 +02:00
}
2014-08-22 08:07:00 +02:00
2014-08-26 13:36:38 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
typedef size_t ( * ResultIndexFunction )( const RigActiveCellInfo * activeCellinfo , size_t reservoirCellIndex );
2014-08-22 08:07:00 +02:00
2014-08-26 13:36:38 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2014-08-22 08:07:00 +02:00
2014-08-26 13:36:38 +02:00
size_t directReservoirCellIndex ( const RigActiveCellInfo * activeCellinfo , size_t reservoirCellIndex )
{
return reservoirCellIndex ;
}
2014-08-22 08:07:00 +02:00
2014-08-26 13:36:38 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t reservoirActiveCellIndex ( const RigActiveCellInfo * activeCellinfo , size_t reservoirCellIndex )
{
return activeCellinfo -> cellResultIndex ( reservoirCellIndex );
}
2014-08-22 08:07:00 +02:00
}
2014-08-26 13:36:38 +02:00
using namespace RigTransmissibilityCalcTools ;
2014-08-22 08:07:00 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2014-08-22 13:38:03 +02:00
void RimReservoirCellResultsStorage :: computeRiTransComponent ( const QString & riTransComponentResultName )
2014-08-22 08:07:00 +02:00
{
if ( ! m_cellResults ) return ;
2014-08-22 13:38:03 +02:00
// Set up which component to compute
2015-05-27 06:23:08 -07:00
cvf :: StructGridInterface :: FaceType faceId = cvf :: StructGridInterface :: NO_FACE ;
2014-08-22 13:38:03 +02:00
QString permCompName ;
2017-06-13 15:41:52 +02:00
if ( riTransComponentResultName == RiaDefines :: riTranXResultName ())
2014-08-22 13:38:03 +02:00
{
permCompName = "PERMX" ;
faceId = cvf :: StructGridInterface :: POS_I ;
}
2017-06-13 15:41:52 +02:00
else if ( riTransComponentResultName == RiaDefines :: riTranYResultName ())
2014-08-22 13:38:03 +02:00
{
permCompName = "PERMY" ;
faceId = cvf :: StructGridInterface :: POS_J ;
}
2017-06-13 15:41:52 +02:00
else if ( riTransComponentResultName == RiaDefines :: riTranZResultName ())
2014-08-22 13:38:03 +02:00
{
permCompName = "PERMZ" ;
faceId = cvf :: StructGridInterface :: POS_K ;
}
else
{
CVF_ASSERT ( false );
}
2014-08-27 14:05:29 +02:00
double cdarchy = darchysValue ();
2014-08-22 08:07:00 +02:00
// Get the needed result indices we depend on
2017-06-13 15:41:52 +02:00
size_t permResultIdx = findOrLoadScalarResult ( RiaDefines :: STATIC_NATIVE , permCompName );
size_t ntgResultIdx = findOrLoadScalarResult ( RiaDefines :: STATIC_NATIVE , "NTG" );
2014-08-26 12:07:08 +02:00
2015-06-29 14:45:30 +02:00
bool hasNTGResults = ntgResultIdx != cvf :: UNDEFINED_SIZE_T ;
2014-08-22 13:38:03 +02:00
// Get the result index of the output
2014-08-22 08:07:00 +02:00
2017-06-13 15:41:52 +02:00
size_t riTransResultIdx = m_cellResults -> findScalarResultIndex ( RiaDefines :: STATIC_NATIVE , riTransComponentResultName );
2014-08-22 13:38:03 +02:00
CVF_ASSERT ( riTransResultIdx != cvf :: UNDEFINED_SIZE_T );
2014-08-22 08:07:00 +02:00
// Get the result count, to handle that one of them might be globally defined
size_t permxResultValueCount = m_cellResults -> cellScalarResults ( permResultIdx )[ 0 ]. size ();
2015-06-29 14:45:30 +02:00
size_t resultValueCount = permxResultValueCount ;
if ( hasNTGResults )
{
size_t ntgResultValueCount = m_cellResults -> cellScalarResults ( ntgResultIdx )[ 0 ]. size ();
resultValueCount = CVF_MIN ( permxResultValueCount , ntgResultValueCount );
}
2014-08-22 08:07:00 +02:00
2014-08-22 13:38:03 +02:00
// Get all the actual result values
2015-06-29 14:45:30 +02:00
std :: vector < double > & permResults = m_cellResults -> cellScalarResults ( permResultIdx )[ 0 ];
2014-08-22 13:38:03 +02:00
std :: vector < double > & riTransResults = m_cellResults -> cellScalarResults ( riTransResultIdx )[ 0 ];
2015-06-29 14:45:30 +02:00
std :: vector < double > * ntgResults = NULL ;
if ( hasNTGResults )
{
ntgResults = & ( m_cellResults -> cellScalarResults ( ntgResultIdx )[ 0 ]);
}
2014-08-22 08:07:00 +02:00
2014-08-22 13:38:03 +02:00
// Set up output container to correct number of results
2014-08-22 08:07:00 +02:00
2014-08-22 13:38:03 +02:00
riTransResults . resize ( resultValueCount );
2014-08-22 08:07:00 +02:00
// Prepare how to index the result values:
2015-06-29 14:45:30 +02:00
ResultIndexFunction riTranIdxFunc = NULL ;
ResultIndexFunction permIdxFunc = NULL ;
ResultIndexFunction ntgIdxFunc = NULL ;
{
bool isPermUsingResIdx = m_cellResults -> isUsingGlobalActiveIndex ( permResultIdx );
bool isTransUsingResIdx = m_cellResults -> isUsingGlobalActiveIndex ( riTransResultIdx );
bool isNtgUsingResIdx = false ;
if ( hasNTGResults )
{
isNtgUsingResIdx = m_cellResults -> isUsingGlobalActiveIndex ( ntgResultIdx );
}
2014-08-22 08:07:00 +02:00
2015-06-29 14:45:30 +02:00
// Set up result index function pointers
2014-08-22 08:07:00 +02:00
2015-06-29 14:45:30 +02:00
riTranIdxFunc = isTransUsingResIdx ? & reservoirActiveCellIndex : & directReservoirCellIndex ;
permIdxFunc = isPermUsingResIdx ? & reservoirActiveCellIndex : & directReservoirCellIndex ;
if ( hasNTGResults )
{
ntgIdxFunc = isNtgUsingResIdx ? & reservoirActiveCellIndex : & directReservoirCellIndex ;
}
}
2014-08-22 08:07:00 +02:00
const RigActiveCellInfo * activeCellInfo = m_cellResults -> activeCellInfo ();
const std :: vector < cvf :: Vec3d >& nodes = m_ownerMainGrid -> nodes ();
2014-09-23 12:24:48 +02:00
bool isFaceNormalsOutwards = m_ownerMainGrid -> isFaceNormalsOutwards ();
2014-08-22 08:07:00 +02:00
2015-11-24 14:21:02 +01:00
for ( size_t nativeResvCellIndex = 0 ; nativeResvCellIndex < m_ownerMainGrid -> globalCellArray (). size (); nativeResvCellIndex ++ )
2014-08-22 08:07:00 +02:00
{
// Do nothing if we are only dealing with active cells, and this cell is not active:
2014-08-22 13:38:03 +02:00
size_t tranResIdx = ( * riTranIdxFunc )( activeCellInfo , nativeResvCellIndex );
if ( tranResIdx == cvf :: UNDEFINED_SIZE_T ) continue ;
2014-08-22 08:07:00 +02:00
2015-11-24 14:21:02 +01:00
const RigCell & nativeCell = m_ownerMainGrid -> globalCellArray ()[ nativeResvCellIndex ];
2014-08-22 08:07:00 +02:00
RigGridBase * grid = nativeCell . hostGrid ();
size_t gridLocalNativeCellIndex = nativeCell . gridLocalCellIndex ();
size_t i , j , k , gridLocalNeighborCellIdx ;
grid -> ijkFromCellIndex ( gridLocalNativeCellIndex , & i , & j , & k );
if ( grid -> cellIJKNeighbor ( i , j , k , faceId , & gridLocalNeighborCellIdx ))
{
size_t neighborResvCellIdx = grid -> reservoirCellIndex ( gridLocalNeighborCellIdx );
2015-11-24 14:21:02 +01:00
const RigCell & neighborCell = m_ownerMainGrid -> globalCellArray ()[ neighborResvCellIdx ];
2014-08-22 08:07:00 +02:00
2014-08-22 13:38:03 +02:00
// Do nothing if neighbor cell has no results
size_t neighborCellPermResIdx = ( * permIdxFunc )( activeCellInfo , neighborResvCellIdx );
if ( neighborCellPermResIdx == cvf :: UNDEFINED_SIZE_T ) continue ;
2014-08-26 12:07:08 +02:00
2014-08-22 08:07:00 +02:00
// Connection geometry
const RigFault * fault = grid -> mainGrid () -> findFaultFromCellIndexAndCellFace ( nativeResvCellIndex , faceId );
bool isOnFault = fault ;
2014-08-26 12:07:08 +02:00
2014-08-22 08:07:00 +02:00
cvf :: Vec3d faceAreaVec ;
cvf :: Vec3d faceCenter ;
if ( isOnFault )
{
2014-09-09 10:58:02 +02:00
calculateConnectionGeometry ( nativeCell , neighborCell , nodes , faceId , & faceAreaVec );
2014-08-22 08:07:00 +02:00
}
else
{
2014-09-09 10:58:02 +02:00
2014-08-22 08:07:00 +02:00
faceAreaVec = nativeCell . faceNormalWithAreaLenght ( faceId );
}
2014-08-22 13:38:03 +02:00
if ( ! isFaceNormalsOutwards ) faceAreaVec = - faceAreaVec ;
2014-08-22 08:07:00 +02:00
double halfCellTrans = 0 ;
double neighborHalfCellTrans = 0 ;
// Native cell half cell transm
{
2014-09-09 10:58:02 +02:00
cvf :: Vec3d centerToFace = nativeCell . faceCenter ( faceId ) - nativeCell . center ();
2014-08-22 08:07:00 +02:00
size_t permResIdx = ( * permIdxFunc )( activeCellInfo , nativeResvCellIndex );
double perm = permResults [ permResIdx ];
double ntg = 1.0 ;
2015-06-29 14:45:30 +02:00
if ( hasNTGResults && faceId != cvf :: StructGridInterface :: POS_K )
2014-08-22 08:07:00 +02:00
{
size_t ntgResIdx = ( * ntgIdxFunc )( activeCellInfo , nativeResvCellIndex );
2015-06-29 14:45:30 +02:00
ntg = ( * ntgResults )[ ntgResIdx ];
2014-08-22 08:07:00 +02:00
}
halfCellTrans = halfCellTransmissibility ( perm , ntg , centerToFace , faceAreaVec );
}
// Neighbor cell half cell transm
{
2014-09-09 10:58:02 +02:00
cvf :: Vec3d centerToFace = neighborCell . faceCenter ( cvf :: StructGridInterface :: oppositeFace ( faceId )) - neighborCell . center ();
2014-08-22 08:07:00 +02:00
2014-08-22 13:38:03 +02:00
double perm = permResults [ neighborCellPermResIdx ];
2014-08-22 08:07:00 +02:00
double ntg = 1.0 ;
2015-06-29 14:45:30 +02:00
if ( hasNTGResults && faceId != cvf :: StructGridInterface :: POS_K )
2014-08-22 08:07:00 +02:00
{
size_t ntgResIdx = ( * ntgIdxFunc )( activeCellInfo , neighborResvCellIdx );
2015-06-29 14:45:30 +02:00
ntg = ( * ntgResults )[ ntgResIdx ];
2014-08-22 08:07:00 +02:00
}
neighborHalfCellTrans = halfCellTransmissibility ( perm , ntg , centerToFace , - faceAreaVec );
}
2014-09-09 15:21:09 +02:00
riTransResults [ tranResIdx ] = newtran ( cdarchy , 1.0 , halfCellTrans , neighborHalfCellTrans );
2014-08-22 08:07:00 +02:00
}
}
2014-08-26 12:07:08 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimReservoirCellResultsStorage :: computeNncCombRiTrans ()
{
if ( ! m_cellResults ) return ;
2017-06-13 15:41:52 +02:00
size_t riCombTransScalarResultIndex = m_cellResults -> findScalarResultIndex ( RiaDefines :: STATIC_NATIVE , RiaDefines :: combinedRiTranResultName ());
2014-08-26 12:07:08 +02:00
if ( m_ownerMainGrid -> nncData () -> connectionScalarResult ( riCombTransScalarResultIndex )) return ;
2014-08-27 14:05:29 +02:00
double cdarchy = darchysValue ();
2014-08-26 12:07:08 +02:00
// Get the needed result indices we depend on
2017-06-13 15:41:52 +02:00
size_t permXResultIdx = findOrLoadScalarResult ( RiaDefines :: STATIC_NATIVE , "PERMX" );
size_t permYResultIdx = findOrLoadScalarResult ( RiaDefines :: STATIC_NATIVE , "PERMY" );
size_t permZResultIdx = findOrLoadScalarResult ( RiaDefines :: STATIC_NATIVE , "PERMZ" );
2014-08-26 12:07:08 +02:00
2017-06-13 15:41:52 +02:00
size_t ntgResultIdx = findOrLoadScalarResult ( RiaDefines :: STATIC_NATIVE , "NTG" );
2014-08-26 12:07:08 +02:00
2015-06-29 14:45:30 +02:00
bool hasNTGResults = ntgResultIdx != cvf :: UNDEFINED_SIZE_T ;
2014-08-26 12:07:08 +02:00
// Get all the actual result values
std :: vector < double > & permXResults = m_cellResults -> cellScalarResults ( permXResultIdx )[ 0 ];
std :: vector < double > & permYResults = m_cellResults -> cellScalarResults ( permYResultIdx )[ 0 ];
std :: vector < double > & permZResults = m_cellResults -> cellScalarResults ( permZResultIdx )[ 0 ];
std :: vector < double > & riCombTransResults = m_ownerMainGrid -> nncData () -> makeConnectionScalarResult ( riCombTransScalarResultIndex );
2015-06-29 14:45:30 +02:00
std :: vector < double > * ntgResults = NULL ;
if ( hasNTGResults )
{
ntgResults = & ( m_cellResults -> cellScalarResults ( ntgResultIdx )[ 0 ]);
}
2014-08-26 12:07:08 +02:00
// Prepare how to index the result values:
2015-06-29 14:45:30 +02:00
ResultIndexFunction permXIdxFunc = NULL ;
ResultIndexFunction permYIdxFunc = NULL ;
ResultIndexFunction permZIdxFunc = NULL ;
ResultIndexFunction ntgIdxFunc = NULL ;
{
bool isPermXUsingResIdx = m_cellResults -> isUsingGlobalActiveIndex ( permXResultIdx );
bool isPermYUsingResIdx = m_cellResults -> isUsingGlobalActiveIndex ( permYResultIdx );
bool isPermZUsingResIdx = m_cellResults -> isUsingGlobalActiveIndex ( permZResultIdx );
bool isNtgUsingResIdx = false ;
if ( hasNTGResults )
{
isNtgUsingResIdx = m_cellResults -> isUsingGlobalActiveIndex ( ntgResultIdx );
}
2014-08-26 12:07:08 +02:00
2015-06-29 14:45:30 +02:00
// Set up result index function pointers
2014-08-26 12:07:08 +02:00
2015-06-29 14:45:30 +02:00
permXIdxFunc = isPermXUsingResIdx ? & reservoirActiveCellIndex : & directReservoirCellIndex ;
permYIdxFunc = isPermYUsingResIdx ? & reservoirActiveCellIndex : & directReservoirCellIndex ;
permZIdxFunc = isPermZUsingResIdx ? & reservoirActiveCellIndex : & directReservoirCellIndex ;
if ( hasNTGResults )
{
ntgIdxFunc = isNtgUsingResIdx ? & reservoirActiveCellIndex : & directReservoirCellIndex ;
}
}
2014-08-26 12:07:08 +02:00
const RigActiveCellInfo * activeCellInfo = m_cellResults -> activeCellInfo ();
2014-09-23 12:24:48 +02:00
bool isFaceNormalsOutwards = m_ownerMainGrid -> isFaceNormalsOutwards ();
2014-08-26 12:07:08 +02:00
// NNC calculation
std :: vector < RigConnection >& nncConnections = m_ownerMainGrid -> nncData () -> connections ();
for ( size_t connIdx = 0 ; connIdx < nncConnections . size (); connIdx ++ )
{
size_t nativeResvCellIndex = nncConnections [ connIdx ]. m_c1GlobIdx ;
size_t neighborResvCellIdx = nncConnections [ connIdx ]. m_c2GlobIdx ;
cvf :: StructGridInterface :: FaceType faceId = nncConnections [ connIdx ]. m_c1Face ;
ResultIndexFunction permIdxFunc = NULL ;
std :: vector < double > * permResults ;
switch ( faceId )
{
case cvf :: StructGridInterface :: POS_I :
case cvf :: StructGridInterface :: NEG_I :
permIdxFunc = permXIdxFunc ;
permResults = & permXResults ;
break ;
case cvf :: StructGridInterface :: POS_J :
case cvf :: StructGridInterface :: NEG_J :
permIdxFunc = permYIdxFunc ;
permResults = & permYResults ;
break ;
case cvf :: StructGridInterface :: POS_K :
case cvf :: StructGridInterface :: NEG_K :
permIdxFunc = permZIdxFunc ;
permResults = & permZResults ;
break ;
}
2014-09-03 07:35:23 +02:00
if ( ! permIdxFunc ) continue ;
2014-08-26 12:07:08 +02:00
// Do nothing if we are only dealing with active cells, and this cell is not active:
size_t nativeCellPermResIdx = ( * permIdxFunc )( activeCellInfo , nativeResvCellIndex );
if ( nativeCellPermResIdx == cvf :: UNDEFINED_SIZE_T ) continue ;
// Do nothing if neighbor cell has no results
size_t neighborCellPermResIdx = ( * permIdxFunc )( activeCellInfo , neighborResvCellIdx );
if ( neighborCellPermResIdx == cvf :: UNDEFINED_SIZE_T ) continue ;
2015-11-24 14:21:02 +01:00
const RigCell & nativeCell = m_ownerMainGrid -> globalCellArray ()[ nativeResvCellIndex ];
const RigCell & neighborCell = m_ownerMainGrid -> globalCellArray ()[ neighborResvCellIdx ];
2014-08-26 12:07:08 +02:00
// Connection geometry
cvf :: Vec3d faceAreaVec = cvf :: Vec3d :: ZERO ;;
cvf :: Vec3d faceCenter = cvf :: Vec3d :: ZERO ;;
// Polygon center
const std :: vector < cvf :: Vec3d >& realPolygon = nncConnections [ connIdx ]. m_polygon ;
for ( size_t pIdx = 0 ; pIdx < realPolygon . size (); ++ pIdx )
{
faceCenter += realPolygon [ pIdx ];
}
faceCenter *= 1.0 / realPolygon . size ();
// Polygon area vector
faceAreaVec = cvf :: GeometryTools :: polygonAreaNormal3D ( realPolygon );
if ( ! isFaceNormalsOutwards ) faceAreaVec = - faceAreaVec ;
double halfCellTrans = 0 ;
double neighborHalfCellTrans = 0 ;
// Native cell half cell transm
{
2014-09-09 10:58:02 +02:00
cvf :: Vec3d centerToFace = nativeCell . faceCenter ( faceId ) - nativeCell . center ();
2014-08-26 12:07:08 +02:00
double perm = ( * permResults )[ nativeCellPermResIdx ];
double ntg = 1.0 ;
2015-06-29 14:45:30 +02:00
if ( hasNTGResults && faceId != cvf :: StructGridInterface :: POS_K )
2014-08-26 12:07:08 +02:00
{
size_t ntgResIdx = ( * ntgIdxFunc )( activeCellInfo , nativeResvCellIndex );
2015-06-29 14:45:30 +02:00
ntg = ( * ntgResults )[ ntgResIdx ];
2014-08-26 12:07:08 +02:00
}
halfCellTrans = halfCellTransmissibility ( perm , ntg , centerToFace , faceAreaVec );
}
// Neighbor cell half cell transm
{
2014-09-09 10:58:02 +02:00
cvf :: Vec3d centerToFace = neighborCell . faceCenter ( cvf :: StructGridInterface :: oppositeFace ( faceId )) - neighborCell . center ();
2014-08-26 12:07:08 +02:00
double perm = ( * permResults )[ neighborCellPermResIdx ];
double ntg = 1.0 ;
2015-06-29 14:45:30 +02:00
if ( hasNTGResults && faceId != cvf :: StructGridInterface :: POS_K )
2014-08-26 12:07:08 +02:00
{
size_t ntgResIdx = ( * ntgIdxFunc )( activeCellInfo , neighborResvCellIdx );
2015-06-29 14:45:30 +02:00
ntg = ( * ntgResults )[ ntgResIdx ];
2014-08-26 12:07:08 +02:00
}
neighborHalfCellTrans = halfCellTransmissibility ( perm , ntg , centerToFace , - faceAreaVec );
}
double newtranTemp = newtran ( cdarchy , 1.0 , halfCellTrans , neighborHalfCellTrans );
riCombTransResults [ connIdx ] = newtranTemp ;
}
2014-08-22 08:07:00 +02:00
}
2013-03-18 14:34:29 +01:00
2014-08-26 15:32:19 +02:00
double riMult ( double transResults , double riTransResults )
{
2014-09-09 15:21:09 +02:00
if ( transResults == HUGE_VAL || riTransResults == HUGE_VAL ) return HUGE_VAL ;
2014-08-28 11:24:41 +02:00
2014-09-09 15:21:09 +02:00
// To make 0.0 values give 1.0 in mult value
if ( cvf :: Math :: abs ( riTransResults ) < 1e-12 )
2014-08-26 15:32:19 +02:00
{
2014-08-31 14:37:25 +02:00
if ( cvf :: Math :: abs ( transResults ) < 1e-12 )
2014-08-28 11:24:41 +02:00
{
return 1.0 ;
}
2014-09-09 15:21:09 +02:00
return HUGE_VAL ;
2014-08-26 15:32:19 +02:00
}
2014-08-28 11:24:41 +02:00
2014-09-09 15:21:09 +02:00
double result = transResults / riTransResults ;
return result ;
2014-08-26 15:32:19 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimReservoirCellResultsStorage :: computeRiMULTComponent ( const QString & riMultCompName )
{
if ( ! m_cellResults ) return ;
// Set up which component to compute
QString riTransCompName ;
QString transCompName ;
2017-06-13 15:41:52 +02:00
if ( riMultCompName == RiaDefines :: riMultXResultName ())
2014-08-26 15:32:19 +02:00
{
2017-06-13 15:41:52 +02:00
riTransCompName = RiaDefines :: riTranXResultName ();
2014-08-26 15:32:19 +02:00
transCompName = "TRANX" ;
}
2017-06-13 15:41:52 +02:00
else if ( riMultCompName == RiaDefines :: riMultYResultName ())
2014-08-26 15:32:19 +02:00
{
2017-06-13 15:41:52 +02:00
riTransCompName = RiaDefines :: riTranYResultName ();
2014-08-26 15:32:19 +02:00
transCompName = "TRANY" ;
}
2017-06-13 15:41:52 +02:00
else if ( riMultCompName == RiaDefines :: riMultZResultName ())
2014-08-26 15:32:19 +02:00
{
2017-06-13 15:41:52 +02:00
riTransCompName = RiaDefines :: riTranZResultName ();
2014-08-26 15:32:19 +02:00
transCompName = "TRANZ" ;
}
else
{
CVF_ASSERT ( false );
}
// Get the needed result indices we depend on
2017-06-13 15:41:52 +02:00
size_t transResultIdx = findOrLoadScalarResult ( RiaDefines :: STATIC_NATIVE , transCompName );
size_t riTransResultIdx = findOrLoadScalarResult ( RiaDefines :: STATIC_NATIVE , riTransCompName );
2014-08-26 15:32:19 +02:00
// Get the result index of the output
2017-06-13 15:41:52 +02:00
size_t riMultResultIdx = m_cellResults -> findScalarResultIndex ( RiaDefines :: STATIC_NATIVE , riMultCompName );
2014-08-26 15:32:19 +02:00
CVF_ASSERT ( riMultResultIdx != cvf :: UNDEFINED_SIZE_T );
// Get the result count, to handle that one of them might be globally defined
CVF_ASSERT ( m_cellResults -> cellScalarResults ( riTransResultIdx )[ 0 ]. size () == m_cellResults -> cellScalarResults ( transResultIdx )[ 0 ]. size ());
size_t resultValueCount = m_cellResults -> cellScalarResults ( transResultIdx )[ 0 ]. size ();
// Get all the actual result values
std :: vector < double > & riTransResults = m_cellResults -> cellScalarResults ( riTransResultIdx )[ 0 ];
std :: vector < double > & transResults = m_cellResults -> cellScalarResults ( transResultIdx )[ 0 ];
std :: vector < double > & riMultResults = m_cellResults -> cellScalarResults ( riMultResultIdx )[ 0 ];
// Set up output container to correct number of results
riMultResults . resize ( resultValueCount );
for ( size_t vIdx = 0 ; vIdx < transResults . size (); ++ vIdx )
{
riMultResults [ vIdx ] = riMult ( transResults [ vIdx ], riTransResults [ vIdx ]);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimReservoirCellResultsStorage :: computeNncCombRiMULT ()
{
if ( ! m_cellResults ) return ;
2017-06-13 15:41:52 +02:00
size_t riCombMultScalarResultIndex = m_cellResults -> findScalarResultIndex ( RiaDefines :: STATIC_NATIVE , RiaDefines :: combinedRiMultResultName ());
size_t riCombTransScalarResultIndex = m_cellResults -> findScalarResultIndex ( RiaDefines :: STATIC_NATIVE , RiaDefines :: combinedRiTranResultName ());
size_t combTransScalarResultIndex = m_cellResults -> findScalarResultIndex ( RiaDefines :: STATIC_NATIVE , RiaDefines :: combinedTransmissibilityResultName ());
2014-08-26 15:32:19 +02:00
if ( m_ownerMainGrid -> nncData () -> connectionScalarResult ( riCombMultScalarResultIndex )) return ;
std :: vector < double > & riMultResults = m_ownerMainGrid -> nncData () -> makeConnectionScalarResult ( riCombMultScalarResultIndex );
const std :: vector < double > * riTransResults = m_ownerMainGrid -> nncData () -> connectionScalarResult ( riCombTransScalarResultIndex );
const std :: vector < double > * transResults = m_ownerMainGrid -> nncData () -> connectionScalarResult ( combTransScalarResultIndex );
for ( size_t nncConIdx = 0 ; nncConIdx < riMultResults . size (); ++ nncConIdx )
{
riMultResults [ nncConIdx ] = riMult (( * transResults )[ nncConIdx ], ( * riTransResults )[ nncConIdx ]);
}
}
2014-08-27 11:41:08 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimReservoirCellResultsStorage :: computeRiTRANSbyAreaComponent ( const QString & riTransByAreaCompResultName )
{
if ( ! m_cellResults ) return ;
// Set up which component to compute
2015-05-27 06:23:08 -07:00
cvf :: StructGridInterface :: FaceType faceId = cvf :: StructGridInterface :: NO_FACE ;
2014-08-27 11:41:08 +02:00
QString transCompName ;
2017-06-13 15:41:52 +02:00
if ( riTransByAreaCompResultName == RiaDefines :: riAreaNormTranXResultName ())
2014-08-27 11:41:08 +02:00
{
transCompName = "TRANX" ;
faceId = cvf :: StructGridInterface :: POS_I ;
}
2017-06-13 15:41:52 +02:00
else if ( riTransByAreaCompResultName == RiaDefines :: riAreaNormTranYResultName ())
2014-08-27 11:41:08 +02:00
{
transCompName = "TRANY" ;
faceId = cvf :: StructGridInterface :: POS_J ;
}
2017-06-13 15:41:52 +02:00
else if ( riTransByAreaCompResultName == RiaDefines :: riAreaNormTranZResultName ())
2014-08-27 11:41:08 +02:00
{
transCompName = "TRANZ" ;
faceId = cvf :: StructGridInterface :: POS_K ;
}
else
{
CVF_ASSERT ( false );
}
// Get the needed result indices we depend on
2017-06-13 15:41:52 +02:00
size_t tranCompScResIdx = findOrLoadScalarResult ( RiaDefines :: STATIC_NATIVE , transCompName );
2014-08-27 11:41:08 +02:00
// Get the result index of the output
2017-06-13 15:41:52 +02:00
size_t riTranByAreaScResIdx = m_cellResults -> findScalarResultIndex ( RiaDefines :: STATIC_NATIVE , riTransByAreaCompResultName );
2014-08-27 11:41:08 +02:00
CVF_ASSERT ( riTranByAreaScResIdx != cvf :: UNDEFINED_SIZE_T );
// Get the result count, to handle that one of them might be globally defined
size_t resultValueCount = m_cellResults -> cellScalarResults ( tranCompScResIdx )[ 0 ]. size ();
// Get all the actual result values
std :: vector < double > & transResults = m_cellResults -> cellScalarResults ( tranCompScResIdx )[ 0 ];
std :: vector < double > & riTransByAreaResults = m_cellResults -> cellScalarResults ( riTranByAreaScResIdx )[ 0 ];
// Set up output container to correct number of results
riTransByAreaResults . resize ( resultValueCount );
// Prepare how to index the result values:
bool isUsingResIdx = m_cellResults -> isUsingGlobalActiveIndex ( tranCompScResIdx );
// Set up result index function pointers
ResultIndexFunction resValIdxFunc = isUsingResIdx ? & reservoirActiveCellIndex : & directReservoirCellIndex ;
const RigActiveCellInfo * activeCellInfo = m_cellResults -> activeCellInfo ();
const std :: vector < cvf :: Vec3d >& nodes = m_ownerMainGrid -> nodes ();
2015-11-24 14:21:02 +01:00
for ( size_t nativeResvCellIndex = 0 ; nativeResvCellIndex < m_ownerMainGrid -> globalCellArray (). size (); nativeResvCellIndex ++ )
2014-08-27 11:41:08 +02:00
{
// Do nothing if we are only dealing with active cells, and this cell is not active:
size_t nativeCellResValIdx = ( * resValIdxFunc )( activeCellInfo , nativeResvCellIndex );
if ( nativeCellResValIdx == cvf :: UNDEFINED_SIZE_T ) continue ;
2015-11-24 14:21:02 +01:00
const RigCell & nativeCell = m_ownerMainGrid -> globalCellArray ()[ nativeResvCellIndex ];
2014-08-27 11:41:08 +02:00
RigGridBase * grid = nativeCell . hostGrid ();
size_t gridLocalNativeCellIndex = nativeCell . gridLocalCellIndex ();
size_t i , j , k , gridLocalNeighborCellIdx ;
grid -> ijkFromCellIndex ( gridLocalNativeCellIndex , & i , & j , & k );
if ( grid -> cellIJKNeighbor ( i , j , k , faceId , & gridLocalNeighborCellIdx ))
{
size_t neighborResvCellIdx = grid -> reservoirCellIndex ( gridLocalNeighborCellIdx );
2015-11-24 14:21:02 +01:00
const RigCell & neighborCell = m_ownerMainGrid -> globalCellArray ()[ neighborResvCellIdx ];
2014-08-27 11:41:08 +02:00
// Connection geometry
const RigFault * fault = grid -> mainGrid () -> findFaultFromCellIndexAndCellFace ( nativeResvCellIndex , faceId );
bool isOnFault = fault ;
cvf :: Vec3d faceAreaVec ;
if ( isOnFault )
{
2014-09-09 10:58:02 +02:00
calculateConnectionGeometry ( nativeCell , neighborCell , nodes , faceId , & faceAreaVec );
2014-08-27 11:41:08 +02:00
}
else
{
faceAreaVec = nativeCell . faceNormalWithAreaLenght ( faceId );
}
double areaOfOverlap = faceAreaVec . length ();
double transCompValue = transResults [ nativeCellResValIdx ];
riTransByAreaResults [ nativeCellResValIdx ] = transCompValue / areaOfOverlap ;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimReservoirCellResultsStorage :: computeNncCombRiTRANSbyArea ()
{
if ( ! m_cellResults ) return ;
2017-06-13 15:41:52 +02:00
size_t riCombTransByAreaScResIdx = m_cellResults -> findScalarResultIndex ( RiaDefines :: STATIC_NATIVE , RiaDefines :: combinedRiAreaNormTranResultName ());
size_t combTransScalarResultIndex = m_cellResults -> findScalarResultIndex ( RiaDefines :: STATIC_NATIVE , RiaDefines :: combinedTransmissibilityResultName ());
2014-08-27 11:41:08 +02:00
if ( m_ownerMainGrid -> nncData () -> connectionScalarResult ( riCombTransByAreaScResIdx )) return ;
std :: vector < double > & riAreaNormTransResults = m_ownerMainGrid -> nncData () -> makeConnectionScalarResult ( riCombTransByAreaScResIdx );
const std :: vector < double > * transResults = m_ownerMainGrid -> nncData () -> connectionScalarResult ( combTransScalarResultIndex );
const std :: vector < RigConnection >& connections = m_ownerMainGrid -> nncData () -> connections ();
for ( size_t nncConIdx = 0 ; nncConIdx < riAreaNormTransResults . size (); ++ nncConIdx )
{
const std :: vector < cvf :: Vec3d >& realPolygon = connections [ nncConIdx ]. m_polygon ;
cvf :: Vec3d faceAreaVec = cvf :: GeometryTools :: polygonAreaNormal3D ( realPolygon );
double areaOfOverlap = faceAreaVec . length ();
riAreaNormTransResults [ nncConIdx ] = ( * transResults )[ nncConIdx ] / areaOfOverlap ;
}
}
2017-05-31 16:16:28 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimReservoirCellResultsStorage :: computeCompletionTypeForTimeStep ( size_t timeStep )
{
2017-06-13 15:41:52 +02:00
size_t completionTypeResultIndex = m_cellResults -> findScalarResultIndex ( RiaDefines :: DYNAMIC_NATIVE , RiaDefines :: completionTypeResultName ());
2017-05-31 16:16:28 +02:00
2017-06-02 10:14:01 +02:00
if ( m_cellResults -> cellScalarResults ( completionTypeResultIndex ). size () < cellResults () -> maxTimeStepCount ())
2017-05-31 16:16:28 +02:00
{
2017-06-02 10:14:01 +02:00
m_cellResults -> cellScalarResults ( completionTypeResultIndex ). resize ( cellResults () -> maxTimeStepCount ());
2017-05-31 16:16:28 +02:00
}
2017-06-02 10:14:01 +02:00
std :: vector < double >& completionTypeResult = m_cellResults -> cellScalarResults ( completionTypeResultIndex , timeStep );
2017-05-31 16:16:28 +02:00
size_t resultValues = m_ownerMainGrid -> globalCellArray (). size ();
if ( completionTypeResult . size () == resultValues )
{
return ;
}
completionTypeResult . resize ( resultValues );
std :: fill ( completionTypeResult . begin (), completionTypeResult . end (), HUGE_VAL );
RimProject * project ;
firstAncestorOrThisOfTypeAsserted ( project );
RimEclipseCase * eclipseCase ;
firstAncestorOrThisOfTypeAsserted ( eclipseCase );
QDateTime timeStepDate = eclipseCase -> timeStepDates ()[ timeStep ];
RimCompletionCellIntersectionCalc :: calculateIntersections ( project , m_ownerMainGrid , completionTypeResult , timeStepDate );
}
2013-03-18 14:34:29 +01:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2013-03-22 15:43:42 +01:00
void RimReservoirCellResultsStorage :: setCellResults ( RigCaseCellResultsData * cellResults )
2013-03-18 14:34:29 +01:00
{
m_cellResults = cellResults ;
2013-03-21 15:31:47 +01:00
if ( m_cellResults == NULL )
return ;
// Now that we have got the results container, we can finally
// Read data from the internal storage and populate it
if ( m_resultCacheFileName (). isEmpty ())
return ;
// Get the name of the cache name relative to the current project file position
QString newValidCacheFileName = getValidCacheFileName ();
// Warn if we thought we were to find some data on the storage file
2017-05-11 09:23:13 +02:00
if ( ! caf :: Utils :: fileExists ( newValidCacheFileName ) && m_resultCacheMetaData . size ())
2013-03-21 15:31:47 +01:00
{
qWarning () << "Reading stored results: Missing the storage file : " + newValidCacheFileName ;
return ;
}
2017-05-11 09:23:13 +02:00
QFile storageFile ( newValidCacheFileName );
2013-03-21 15:31:47 +01:00
if ( ! storageFile . open ( QIODevice :: ReadOnly ))
{
qWarning () << "Reading stored results: Can't open the file : " + newValidCacheFileName ;
return ;
}
QDataStream stream ( & storageFile );
stream . setVersion ( QDataStream :: Qt_4_6 );
quint32 magicNumber = 0 ;
quint32 versionNumber = 0 ;
stream >> magicNumber ;
if ( magicNumber != 0xCEECAC4E )
{
qWarning () << "Reading stored results: The storage file has wrong type " ;
return ;
}
stream >> versionNumber ;
if ( versionNumber > 1 )
{
qWarning () << "Reading stored results: The storage file has been written by a newer version of ResInsight" ;
return ;
}
caf :: ProgressInfo progress ( m_resultCacheMetaData . size (), "Reading internally stored results" );
// Fill the object with data from the storage
for ( size_t rIdx = 0 ; rIdx < m_resultCacheMetaData . size (); ++ rIdx )
{
RimReservoirCellResultsStorageEntryInfo * resInfo = m_resultCacheMetaData [ rIdx ];
size_t resultIndex = m_cellResults -> addEmptyScalarResult ( resInfo -> m_resultType (), resInfo -> m_resultName (), true );
2017-04-26 09:39:17 +02:00
m_cellResults -> setTimeStepDates ( resultIndex , resInfo -> m_timeStepDates (), resInfo -> m_daysSinceSimulationStart (), std :: vector < int > ()); // Hack: Using no report step numbers. Not really used except for Flow Diagnostics...
2013-03-21 15:31:47 +01:00
progress . setProgressDescription ( resInfo -> m_resultName );
for ( size_t tsIdx = 0 ; tsIdx < resInfo -> m_timeStepDates (). size (); ++ tsIdx )
{
std :: vector < double >* data = NULL ;
2014-04-25 14:36:34 +02:00
2013-03-21 15:31:47 +01:00
data = & ( m_cellResults -> cellScalarResults ( rIdx , tsIdx ));
quint64 cellCount = 0 ;
stream >> cellCount ;
data -> resize ( cellCount , HUGE_VAL );
for ( size_t cIdx = 0 ; cIdx < cellCount ; ++ cIdx )
{
stream >> ( * data )[ cIdx ];
}
}
progress . incrementProgress ();
}
2013-03-18 14:34:29 +01:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2013-03-19 10:29:34 +01:00
void RimReservoirCellResultsStorage :: setMainGrid ( RigMainGrid * mainGrid )
2013-03-18 14:34:29 +01:00
{
m_ownerMainGrid = mainGrid ;
}
2013-03-21 15:31:47 +01:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RimReservoirCellResultsStorage :: storedResultsCount ()
{
return m_resultCacheMetaData . size ();
}
2014-08-21 08:39:19 +02:00
//--------------------------------------------------------------------------------------------------
2014-08-22 13:38:03 +02:00
/// If we have any results on any time step, assume we have loaded results
2014-08-21 08:39:19 +02:00
//--------------------------------------------------------------------------------------------------
bool RimReservoirCellResultsStorage :: isDataPresent ( size_t scalarResultIndex ) const
{
if ( scalarResultIndex >= m_cellResults -> resultCount ())
{
return false ;
}
2017-06-20 16:29:56 +02:00
const std :: vector < std :: vector < double > >& data = m_cellResults -> cellScalarResults ( scalarResultIndex );
2014-08-21 08:39:19 +02:00
for ( size_t tsIdx = 0 ; tsIdx < data . size (); ++ tsIdx )
{
if ( data [ tsIdx ]. size ())
{
return true ;
}
}
return false ;
}
2014-08-27 14:05:29 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimReservoirCellResultsStorage :: darchysValue ()
{
// See "Cartesian transmissibility calculations" in the "Eclipse Technical Description"
// CDARCY Darcys constant
// = 0.00852702 (E300); 0.008527 (ECLIPSE 100) (METRIC)
// = 0.00112712 (E300); 0.001127 (ECLIPSE 100) (FIELD)
// = 3.6 (LAB)
// = 0.00864 (PVT - M)
double darchy = 0.008527 ; // (ECLIPSE 100) (METRIC)
2015-05-15 08:40:27 +02:00
RimEclipseCase * rimCase = NULL ;
2016-09-21 13:59:41 +02:00
this -> firstAncestorOrThisOfType ( rimCase );
2014-08-27 14:05:29 +02:00
2017-03-15 09:10:16 +01:00
if ( rimCase && rimCase -> eclipseCaseData ())
2014-08-27 14:05:29 +02:00
{
2017-06-20 10:40:39 +02:00
darchy = RiaEclipseUnitTools :: darcysConstant ( rimCase -> eclipseCaseData () -> unitsType ());
2014-08-27 14:05:29 +02:00
}
return darchy ;
}
2013-12-16 20:26:52 +01:00
2013-03-18 11:40:39 +01:00
2013-03-19 10:29:34 +01:00
CAF_PDM_SOURCE_INIT ( RimReservoirCellResultsStorageEntryInfo , "ResultStorageEntryInfo" );
2013-03-18 11:40:39 +01:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2013-03-19 10:29:34 +01:00
RimReservoirCellResultsStorageEntryInfo :: RimReservoirCellResultsStorageEntryInfo ()
2013-03-18 11:40:39 +01:00
{
CAF_PDM_InitObject ( "Cache Entry" , "" , "" , "" );
2017-06-13 15:41:52 +02:00
CAF_PDM_InitField ( & m_resultType , "ResultType" , caf :: AppEnum < RiaDefines :: ResultCatType > ( RiaDefines :: REMOVED ), "ResultType" , "" , "" , "" );
2013-03-18 11:40:39 +01:00
CAF_PDM_InitField ( & m_resultName , "ResultName" , QString (), "ResultName" , "" , "" , "" );
CAF_PDM_InitFieldNoDefault ( & m_timeStepDates , "TimeSteps" , "TimeSteps" , "" , "" , "" );
2017-04-26 09:39:17 +02:00
CAF_PDM_InitFieldNoDefault ( & m_daysSinceSimulationStart , "DaysSinceSimulationStart" , "DaysSinceSimulationStart" , "" , "" , "" );
2013-03-18 11:40:39 +01:00
CAF_PDM_InitField ( & m_filePosition , "FilePositionDataStart" , qint64 ( - 1 ), "FilePositionDataStart" , "" , "" , "" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2013-03-19 10:29:34 +01:00
RimReservoirCellResultsStorageEntryInfo ::~ RimReservoirCellResultsStorageEntryInfo ()
2013-03-18 11:40:39 +01:00
{
2014-08-31 14:37:25 +02:00
}