mirror of
https://github.com/OPM/ResInsight.git
synced 2025-01-08 15:14:07 -06:00
0c90f67dcc
* Refactor interface to PdmObjectHandle and PdmFieldHandle Return objects instead of passing in structures as parameters * Add nodiscard to several functions * Remove redundant this-> * Rename to ptrReferencedObjectsByType
911 lines
42 KiB
C++
911 lines
42 KiB
C++
/////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (C) 2016- Statoil ASA
|
|
//
|
|
// 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.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "RigFlowDiagResults.h"
|
|
|
|
#include "RigActiveCellInfo.h"
|
|
#include "RigEclipseCaseData.h"
|
|
#include "RigFlowDiagSolverInterface.h"
|
|
#include "RigFlowDiagStatCalc.h"
|
|
#include "RigMainGrid.h"
|
|
|
|
#include "RigFlowDiagResultFrames.h"
|
|
#include "RigNumberOfFloodedPoreVolumesCalculator.h"
|
|
#include "RigStatisticsDataCache.h"
|
|
#include "RimEclipseCase.h"
|
|
#include "RimEclipseResultCase.h"
|
|
#include "RimFlowDiagSolution.h"
|
|
|
|
#include <cmath> // Needed for HUGE_VAL on Linux
|
|
|
|
namespace caf
|
|
{
|
|
template <>
|
|
void RigFlowDiagResults::CellFilterEnum::setUp()
|
|
{
|
|
addItem( RigFlowDiagResults::CELLS_ACTIVE, "CELLS_ACTIVE", "All Active Cells" );
|
|
addItem( RigFlowDiagResults::CELLS_VISIBLE, "CELLS_VISIBLE", "Visible Cells" );
|
|
addItem( RigFlowDiagResults::CELLS_COMMUNICATION, "CELLS_COMMUNICATION", "Injector Producer Communication" );
|
|
addItem( RigFlowDiagResults::CELLS_FLOODED, "CELLS_FLOODED", "Flooded by Injector" );
|
|
addItem( RigFlowDiagResults::CELLS_DRAINED, "CELLS_DRAINED", "Drained by Producer" );
|
|
setDefault( RigFlowDiagResults::CELLS_ACTIVE );
|
|
}
|
|
} // namespace caf
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RigFlowDiagResults::RigFlowDiagResults( RimFlowDiagSolution* flowSolution, size_t timeStepCount )
|
|
: m_flowDiagSolution( flowSolution )
|
|
{
|
|
m_timeStepCount = timeStepCount;
|
|
m_hasAtemptedNativeResults.resize( timeStepCount );
|
|
m_injProdPairFluxCommunicationTimesteps.resize( timeStepCount );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RigFlowDiagResults::~RigFlowDiagResults()
|
|
{
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const std::vector<double>* RigFlowDiagResults::resultValues( const RigFlowDiagResultAddress& resVarAddr, size_t timeStepIndex )
|
|
{
|
|
CVF_ASSERT( m_timeStepCount != cvf::UNDEFINED_SIZE_T ); // Forgotten to call init
|
|
|
|
return findOrCalculateResult( resVarAddr, timeStepIndex );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const RigActiveCellInfo* RigFlowDiagResults::activeCellInfo( const RigFlowDiagResultAddress& resVarAddr )
|
|
{
|
|
auto eclCase = m_flowDiagSolution->firstAncestorOrThisOfType<RimEclipseResultCase>();
|
|
|
|
return eclCase->eclipseCaseData()->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL ); // Todo: base on
|
|
// resVarAddr member
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const std::vector<double>* RigFlowDiagResults::findOrCalculateResult( const RigFlowDiagResultAddress& resVarAddr, size_t timeStepIndex )
|
|
{
|
|
std::vector<double>* frameData = findScalarResultFrame( resVarAddr, timeStepIndex );
|
|
|
|
if ( frameData ) return frameData;
|
|
|
|
frameData = calculateDerivedResult( resVarAddr, timeStepIndex );
|
|
|
|
if ( frameData ) return frameData;
|
|
|
|
// We need to access the native data from the opm solver
|
|
|
|
if ( !solverInterface() ) return nullptr;
|
|
|
|
calculateNativeResultsIfNotPreviouslyAttempted( timeStepIndex, resVarAddr.phaseSelection );
|
|
|
|
return findScalarResultFrame( resVarAddr, timeStepIndex );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFlowDiagResults::calculateNativeResultsIfNotPreviouslyAttempted( size_t timeStepIndex,
|
|
RigFlowDiagResultAddress::PhaseSelection phaseSelection )
|
|
{
|
|
if ( timeStepIndex >= m_hasAtemptedNativeResults.size() ) return;
|
|
|
|
auto it = m_hasAtemptedNativeResults[timeStepIndex].find( phaseSelection );
|
|
if ( it == m_hasAtemptedNativeResults[timeStepIndex].end() || !it->second )
|
|
{
|
|
RigFlowDiagTimeStepResult nativeTimestepResults =
|
|
solverInterface()->calculate( timeStepIndex,
|
|
phaseSelection,
|
|
m_flowDiagSolution->allInjectorTracerActiveCellIndices( timeStepIndex ),
|
|
m_flowDiagSolution->allProducerTracerActiveCellIndices( timeStepIndex ) );
|
|
|
|
std::map<RigFlowDiagResultAddress, std::vector<double>>& nativeResults = nativeTimestepResults.nativeResults();
|
|
|
|
for ( auto& resIt : nativeResults )
|
|
{
|
|
RigFlowDiagResultFrames* nativeResFrames = findScalarResult( resIt.first );
|
|
if ( !nativeResFrames ) nativeResFrames = createScalarResult( resIt.first );
|
|
|
|
nativeResFrames->frameData( timeStepIndex ).swap( resIt.second );
|
|
}
|
|
|
|
m_injProdPairFluxCommunicationTimesteps[timeStepIndex][phaseSelection].swap( nativeTimestepResults.injProdWellPairFluxes() );
|
|
|
|
m_hasAtemptedNativeResults[timeStepIndex][phaseSelection] = true;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<double>* RigFlowDiagResults::findScalarResultFrame( const RigFlowDiagResultAddress& resVarAddr, size_t timeStepIndex )
|
|
{
|
|
RigFlowDiagResultFrames* resFrames = findScalarResult( resVarAddr );
|
|
|
|
if ( resFrames )
|
|
{
|
|
std::vector<double>& frame = resFrames->frameData( timeStepIndex );
|
|
if ( frame.size() ) return ( &frame );
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RigFlowDiagSolverInterface* RigFlowDiagResults::solverInterface()
|
|
{
|
|
auto eclCase = m_flowDiagSolution->firstAncestorOrThisOfType<RimEclipseResultCase>();
|
|
|
|
return eclCase->flowDiagSolverInterface();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RigFlowDiagResultFrames* RigFlowDiagResults::createScalarResult( const RigFlowDiagResultAddress& resVarAddr )
|
|
{
|
|
cvf::ref<RigFlowDiagResultFrames> newFrameSet = new RigFlowDiagResultFrames( m_timeStepCount );
|
|
m_resultSets[resVarAddr] = newFrameSet;
|
|
|
|
return newFrameSet.p();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RigFlowDiagResultFrames* RigFlowDiagResults::findScalarResult( const RigFlowDiagResultAddress& resVarAddr )
|
|
{
|
|
decltype( m_resultSets )::iterator it = m_resultSets.find( resVarAddr );
|
|
|
|
if ( it == m_resultSets.end() ) return nullptr;
|
|
|
|
return it->second.p();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<double>* RigFlowDiagResults::calculateDerivedResult( const RigFlowDiagResultAddress& resVarAddr, size_t timeStepIndex )
|
|
{
|
|
if ( resVarAddr.isNativeResult() ) return nullptr;
|
|
|
|
if ( resVarAddr.variableName == RIG_FLD_TOF_RESNAME )
|
|
{
|
|
return calculateAverageTOFResult( resVarAddr, timeStepIndex );
|
|
}
|
|
else if ( resVarAddr.variableName == RIG_FLD_CELL_FRACTION_RESNAME )
|
|
{
|
|
return calculateSumOfFractionsResult( resVarAddr, timeStepIndex );
|
|
}
|
|
else if ( resVarAddr.variableName == RIG_FLD_COMMUNICATION_RESNAME )
|
|
{
|
|
return calculateCommunicationResult( resVarAddr, timeStepIndex );
|
|
}
|
|
else if ( resVarAddr.variableName == RIG_FLD_MAX_FRACTION_TRACER_RESNAME )
|
|
{
|
|
return calculateTracerWithMaxFractionResult( resVarAddr, timeStepIndex );
|
|
}
|
|
else if ( resVarAddr.variableName == RIG_NUM_FLOODED_PV )
|
|
{
|
|
calculateNumFloodedPV( resVarAddr );
|
|
return findScalarResultFrame( resVarAddr, timeStepIndex );
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<double>* RigFlowDiagResults::calculateAverageTOFResult( const RigFlowDiagResultAddress& resVarAddr, size_t timeStepIndex )
|
|
{
|
|
std::vector<const std::vector<double>*> injectorTOFs =
|
|
findResultsForSelectedTracers( resVarAddr, timeStepIndex, RIG_FLD_TOF_RESNAME, RimFlowDiagSolution::TracerStatusType::INJECTOR );
|
|
std::vector<const std::vector<double>*> injectorFractions =
|
|
findResultsForSelectedTracers( resVarAddr, timeStepIndex, RIG_FLD_CELL_FRACTION_RESNAME, RimFlowDiagSolution::TracerStatusType::INJECTOR );
|
|
|
|
std::vector<const std::vector<double>*> producerTOFs =
|
|
findResultsForSelectedTracers( resVarAddr, timeStepIndex, RIG_FLD_TOF_RESNAME, RimFlowDiagSolution::TracerStatusType::PRODUCER );
|
|
std::vector<const std::vector<double>*> producerFractions =
|
|
findResultsForSelectedTracers( resVarAddr, timeStepIndex, RIG_FLD_CELL_FRACTION_RESNAME, RimFlowDiagSolution::TracerStatusType::PRODUCER );
|
|
size_t activeCellCount = this->activeCellInfo( resVarAddr )->reservoirActiveCellCount();
|
|
|
|
std::vector<double> injectorTotalFractions;
|
|
std::vector<double> injectorFractMultTof;
|
|
calculateSumOfFractionAndFractionMultTOF( activeCellCount, injectorFractions, injectorTOFs, &injectorTotalFractions, &injectorFractMultTof );
|
|
|
|
std::vector<double> producerTotalFractions;
|
|
std::vector<double> producerFractMultTof;
|
|
calculateSumOfFractionAndFractionMultTOF( activeCellCount, producerFractions, producerTOFs, &producerTotalFractions, &producerFractMultTof );
|
|
|
|
RigFlowDiagResultFrames* averageTofFrames = this->createScalarResult( resVarAddr );
|
|
std::vector<double>& averageTof = averageTofFrames->frameData( timeStepIndex );
|
|
averageTof.resize( activeCellCount, HUGE_VAL );
|
|
|
|
for ( size_t acIdx = 0; acIdx < activeCellCount; ++acIdx )
|
|
{
|
|
if ( injectorTotalFractions[acIdx] == 0.0 && producerTotalFractions[acIdx] == 0.0 )
|
|
{
|
|
averageTof[acIdx] = HUGE_VAL;
|
|
}
|
|
else
|
|
{
|
|
double retVal = 0.0;
|
|
if ( injectorTotalFractions[acIdx] != 0.0 ) retVal += ( 1.0 / injectorTotalFractions[acIdx] ) * injectorFractMultTof[acIdx];
|
|
if ( producerTotalFractions[acIdx] != 0.0 ) retVal += ( 1.0 / producerTotalFractions[acIdx] ) * producerFractMultTof[acIdx];
|
|
averageTof[acIdx] = retVal;
|
|
}
|
|
}
|
|
|
|
/// Test to remove all averaging
|
|
// if (injectorTOFs.size()) averageTof = (*injectorTOFs[0]);
|
|
|
|
return &averageTof;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFlowDiagResults::calculateSumOfFractionAndFractionMultTOF( size_t activeCellCount,
|
|
const std::vector<const std::vector<double>*>& fractions,
|
|
const std::vector<const std::vector<double>*>& TOFs,
|
|
std::vector<double>* sumOfFractions,
|
|
std::vector<double>* fractionMultTOF )
|
|
{
|
|
sumOfFractions->resize( activeCellCount, 0.0 );
|
|
fractionMultTOF->resize( activeCellCount, 0.0 );
|
|
|
|
for ( size_t iIdx = 0; iIdx < fractions.size(); ++iIdx )
|
|
{
|
|
const std::vector<double>* frInj = fractions[iIdx];
|
|
const std::vector<double>* tofInj = TOFs[iIdx];
|
|
|
|
if ( !( frInj && tofInj ) ) continue;
|
|
|
|
for ( size_t acIdx = 0; acIdx < activeCellCount; ++acIdx )
|
|
{
|
|
if ( ( *frInj )[acIdx] == HUGE_VAL ) continue;
|
|
|
|
( *sumOfFractions )[acIdx] += ( *frInj )[acIdx];
|
|
( *fractionMultTOF )[acIdx] += ( *frInj )[acIdx] * ( *tofInj )[acIdx];
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<double>* RigFlowDiagResults::calculateSumOfFractionsResult( const RigFlowDiagResultAddress& resVarAddr, size_t timeStepIndex )
|
|
{
|
|
std::vector<const std::vector<double>*> fractions = findResultsForSelectedTracers( resVarAddr,
|
|
timeStepIndex,
|
|
RIG_FLD_CELL_FRACTION_RESNAME,
|
|
RimFlowDiagSolution::TracerStatusType::UNDEFINED );
|
|
|
|
RigFlowDiagResultFrames* sumOfFractionsFrames = this->createScalarResult( resVarAddr );
|
|
std::vector<double>& sumOfFractions = sumOfFractionsFrames->frameData( timeStepIndex );
|
|
|
|
size_t activeCellCount = this->activeCellInfo( resVarAddr )->reservoirActiveCellCount();
|
|
|
|
calculateSumOfFractions( fractions, activeCellCount, &sumOfFractions );
|
|
|
|
return &sumOfFractions;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<double>* RigFlowDiagResults::calculateTracerWithMaxFractionResult( const RigFlowDiagResultAddress& resVarAddr, size_t timeStepIndex )
|
|
{
|
|
std::vector<std::pair<std::string, const std::vector<double>*>> fractions =
|
|
findNamedResultsForSelectedTracers( resVarAddr,
|
|
timeStepIndex,
|
|
RIG_FLD_CELL_FRACTION_RESNAME,
|
|
RimFlowDiagSolution::TracerStatusType::UNDEFINED );
|
|
|
|
std::vector<int> resultTracerIdxToGlobalTracerIdx;
|
|
{
|
|
resultTracerIdxToGlobalTracerIdx.resize( fractions.size(), -1 );
|
|
|
|
std::vector<QString> allTracerNames = m_flowDiagSolution->tracerNames();
|
|
int selTracerIdx = 0;
|
|
for ( const auto& trNameFractionPair : fractions )
|
|
{
|
|
for ( size_t globIdx = 0; globIdx < allTracerNames.size(); ++globIdx )
|
|
{
|
|
if ( allTracerNames[globIdx].toStdString() == trNameFractionPair.first )
|
|
{
|
|
resultTracerIdxToGlobalTracerIdx[selTracerIdx] = static_cast<int>( globIdx );
|
|
break;
|
|
}
|
|
}
|
|
|
|
++selTracerIdx;
|
|
}
|
|
}
|
|
|
|
size_t activeCellCount = this->activeCellInfo( resVarAddr )->reservoirActiveCellCount();
|
|
|
|
RigFlowDiagResultFrames* maxFractionTracerIdxFrames = this->createScalarResult( resVarAddr );
|
|
std::vector<double>& maxFractionTracerIdx = maxFractionTracerIdxFrames->frameData( timeStepIndex );
|
|
{
|
|
maxFractionTracerIdx.resize( activeCellCount, HUGE_VAL );
|
|
|
|
std::vector<double> maxFraction;
|
|
maxFraction.resize( activeCellCount, -HUGE_VAL );
|
|
|
|
for ( size_t frIdx = 0; frIdx < fractions.size(); ++frIdx )
|
|
{
|
|
const std::vector<double>* fr = fractions[frIdx].second;
|
|
|
|
if ( !fr ) continue;
|
|
|
|
for ( size_t acIdx = 0; acIdx < activeCellCount; ++acIdx )
|
|
{
|
|
if ( ( *fr )[acIdx] == HUGE_VAL ) continue;
|
|
|
|
if ( maxFraction[acIdx] < ( *fr )[acIdx] )
|
|
{
|
|
maxFraction[acIdx] = ( *fr )[acIdx];
|
|
maxFractionTracerIdx[acIdx] = resultTracerIdxToGlobalTracerIdx[frIdx];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return &maxFractionTracerIdx;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<double>* RigFlowDiagResults::calculateCommunicationResult( const RigFlowDiagResultAddress& resVarAddr, size_t timeStepIndex )
|
|
{
|
|
std::vector<const std::vector<double>*> injectorFractions =
|
|
findResultsForSelectedTracers( resVarAddr, timeStepIndex, RIG_FLD_CELL_FRACTION_RESNAME, RimFlowDiagSolution::TracerStatusType::INJECTOR );
|
|
std::vector<const std::vector<double>*> producerFractions =
|
|
findResultsForSelectedTracers( resVarAddr, timeStepIndex, RIG_FLD_CELL_FRACTION_RESNAME, RimFlowDiagSolution::TracerStatusType::PRODUCER );
|
|
size_t activeCellCount = this->activeCellInfo( resVarAddr )->reservoirActiveCellCount();
|
|
|
|
std::vector<double> sumOfInjectorFractions;
|
|
calculateSumOfFractions( injectorFractions, activeCellCount, &sumOfInjectorFractions );
|
|
|
|
std::vector<double> sumOfProducerFractions;
|
|
calculateSumOfFractions( producerFractions, activeCellCount, &sumOfProducerFractions );
|
|
|
|
RigFlowDiagResultFrames* commFrames = this->createScalarResult( resVarAddr );
|
|
std::vector<double>& commPI = commFrames->frameData( timeStepIndex );
|
|
commPI.resize( activeCellCount, HUGE_VAL );
|
|
|
|
for ( size_t acIdx = 0; acIdx < activeCellCount; ++acIdx )
|
|
{
|
|
if ( ( sumOfInjectorFractions )[acIdx] == HUGE_VAL ) continue;
|
|
if ( ( sumOfProducerFractions )[acIdx] == HUGE_VAL ) continue;
|
|
|
|
( commPI )[acIdx] = ( sumOfInjectorFractions )[acIdx] * ( sumOfProducerFractions )[acIdx];
|
|
}
|
|
|
|
return &commPI;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFlowDiagResults::calculateNumFloodedPV( const RigFlowDiagResultAddress& resVarAddr )
|
|
{
|
|
auto eclipseCase = m_flowDiagSolution->firstAncestorOrThisOfTypeAsserted<RimEclipseCase>();
|
|
std::vector<QString> tracerNames;
|
|
for ( const std::string& tracerName : resVarAddr.selectedTracerNames )
|
|
{
|
|
tracerNames.push_back( QString::fromUtf8( tracerName.c_str() ) );
|
|
}
|
|
RigNumberOfFloodedPoreVolumesCalculator calc( eclipseCase, tracerNames );
|
|
|
|
RigFlowDiagResultFrames* frames = this->createScalarResult( resVarAddr );
|
|
for ( size_t frameIdx = 0; frameIdx < m_timeStepCount; ++frameIdx )
|
|
{
|
|
std::vector<double>& frame = frames->frameData( frameIdx );
|
|
|
|
frame.swap( calc.numberOfFloodedPorevolumes()[frameIdx] );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<const std::vector<double>*> RigFlowDiagResults::findResultsForSelectedTracers( const RigFlowDiagResultAddress& resVarAddr,
|
|
size_t timeStepIndex,
|
|
const std::string& nativeResultName,
|
|
RimFlowDiagSolution::TracerStatusType wantedTracerType )
|
|
{
|
|
std::vector<const std::vector<double>*> selectedTracersResults;
|
|
|
|
for ( const std::string& tracerName : resVarAddr.selectedTracerNames )
|
|
{
|
|
RimFlowDiagSolution::TracerStatusType tracerType =
|
|
m_flowDiagSolution->tracerStatusInTimeStep( QString::fromStdString( tracerName ), timeStepIndex );
|
|
|
|
if ( tracerType != RimFlowDiagSolution::TracerStatusType::CLOSED &&
|
|
( tracerType == wantedTracerType || wantedTracerType == RimFlowDiagSolution::TracerStatusType::UNDEFINED ) )
|
|
{
|
|
selectedTracersResults.push_back(
|
|
findOrCalculateResult( RigFlowDiagResultAddress( nativeResultName, resVarAddr.phaseSelection, tracerName ), timeStepIndex ) );
|
|
}
|
|
}
|
|
|
|
return selectedTracersResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<std::pair<std::string, const std::vector<double>*>>
|
|
RigFlowDiagResults::findNamedResultsForSelectedTracers( const RigFlowDiagResultAddress& resVarAddr,
|
|
size_t timeStepIndex,
|
|
const std::string& nativeResultName,
|
|
RimFlowDiagSolution::TracerStatusType wantedTracerType )
|
|
{
|
|
std::vector<std::pair<std::string, const std::vector<double>*>> selectedTracersResults;
|
|
|
|
for ( const std::string& tracerName : resVarAddr.selectedTracerNames )
|
|
{
|
|
RimFlowDiagSolution::TracerStatusType tracerType =
|
|
m_flowDiagSolution->tracerStatusInTimeStep( QString::fromStdString( tracerName ), timeStepIndex );
|
|
|
|
if ( tracerType != RimFlowDiagSolution::TracerStatusType::CLOSED &&
|
|
( tracerType == wantedTracerType || wantedTracerType == RimFlowDiagSolution::TracerStatusType::UNDEFINED ) )
|
|
{
|
|
selectedTracersResults.push_back(
|
|
std::make_pair( tracerName,
|
|
findOrCalculateResult( RigFlowDiagResultAddress( nativeResultName, resVarAddr.phaseSelection, tracerName ),
|
|
timeStepIndex ) ) );
|
|
}
|
|
}
|
|
|
|
return selectedTracersResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RigStatisticsDataCache* RigFlowDiagResults::statistics( const RigFlowDiagResultAddress& resVarAddr )
|
|
{
|
|
RigStatisticsDataCache* statCache = m_resultStatistics[resVarAddr].p();
|
|
if ( !statCache )
|
|
{
|
|
RigFlowDiagStatCalc* calculator = new RigFlowDiagStatCalc( this, resVarAddr );
|
|
statCache = new RigStatisticsDataCache( calculator );
|
|
m_resultStatistics[resVarAddr] = statCache;
|
|
}
|
|
|
|
return statCache;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFlowDiagResults::calculateSumOfFractions( const std::vector<const std::vector<double>*>& fractions,
|
|
size_t activeCellCount,
|
|
std::vector<double>* sumOfFractions )
|
|
{
|
|
sumOfFractions->resize( activeCellCount, HUGE_VAL );
|
|
|
|
for ( size_t iIdx = 0; iIdx < fractions.size(); ++iIdx )
|
|
{
|
|
const std::vector<double>* fraction = fractions[iIdx];
|
|
|
|
if ( !( fraction ) ) continue;
|
|
|
|
for ( size_t acIdx = 0; acIdx < activeCellCount; ++acIdx )
|
|
{
|
|
if ( ( *fraction )[acIdx] == HUGE_VAL ) continue;
|
|
|
|
if ( ( *sumOfFractions )[acIdx] == HUGE_VAL ) ( *sumOfFractions )[acIdx] = 0.0;
|
|
|
|
( *sumOfFractions )[acIdx] += ( *fraction )[acIdx];
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFlowDiagResults::minMaxScalarValues( const RigFlowDiagResultAddress& resVarAddr, int timeStepIndex, double* localMin, double* localMax )
|
|
{
|
|
this->statistics( resVarAddr )->minMaxCellScalarValues( timeStepIndex, *localMin, *localMax );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFlowDiagResults::minMaxScalarValues( const RigFlowDiagResultAddress& resVarAddr, double* globalMin, double* globalMax )
|
|
{
|
|
this->statistics( resVarAddr )->minMaxCellScalarValues( *globalMin, *globalMax );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFlowDiagResults::posNegClosestToZero( const RigFlowDiagResultAddress& resVarAddr,
|
|
int timeStepIndex,
|
|
double* localPosClosestToZero,
|
|
double* localNegClosestToZero )
|
|
{
|
|
this->statistics( resVarAddr )->posNegClosestToZero( timeStepIndex, *localPosClosestToZero, *localNegClosestToZero );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFlowDiagResults::posNegClosestToZero( const RigFlowDiagResultAddress& resVarAddr,
|
|
double* globalPosClosestToZero,
|
|
double* globalNegClosestToZero )
|
|
{
|
|
this->statistics( resVarAddr )->posNegClosestToZero( *globalPosClosestToZero, *globalNegClosestToZero );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFlowDiagResults::meanScalarValue( const RigFlowDiagResultAddress& resVarAddr, double* meanValue )
|
|
{
|
|
CVF_ASSERT( meanValue );
|
|
|
|
this->statistics( resVarAddr )->meanCellScalarValues( *meanValue );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFlowDiagResults::meanScalarValue( const RigFlowDiagResultAddress& resVarAddr, int timeStepIndex, double* meanValue )
|
|
{
|
|
this->statistics( resVarAddr )->meanCellScalarValues( timeStepIndex, *meanValue );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFlowDiagResults::p10p90ScalarValues( const RigFlowDiagResultAddress& resVarAddr, double* p10, double* p90 )
|
|
{
|
|
this->statistics( resVarAddr )->p10p90CellScalarValues( *p10, *p90 );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFlowDiagResults::p10p90ScalarValues( const RigFlowDiagResultAddress& resVarAddr, int timeStepIndex, double* p10, double* p90 )
|
|
{
|
|
this->statistics( resVarAddr )->p10p90CellScalarValues( timeStepIndex, *p10, *p90 );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFlowDiagResults::sumScalarValue( const RigFlowDiagResultAddress& resVarAddr, double* sum )
|
|
{
|
|
CVF_ASSERT( sum );
|
|
|
|
this->statistics( resVarAddr )->sumCellScalarValues( *sum );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFlowDiagResults::sumScalarValue( const RigFlowDiagResultAddress& resVarAddr, int timeStepIndex, double* sum )
|
|
{
|
|
CVF_ASSERT( sum );
|
|
|
|
this->statistics( resVarAddr )->sumCellScalarValues( timeStepIndex, *sum );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const std::vector<size_t>& RigFlowDiagResults::scalarValuesHistogram( const RigFlowDiagResultAddress& resVarAddr )
|
|
{
|
|
return this->statistics( resVarAddr )->cellScalarValuesHistogram();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const std::vector<size_t>& RigFlowDiagResults::scalarValuesHistogram( const RigFlowDiagResultAddress& resVarAddr, int timeStepIndex )
|
|
{
|
|
return this->statistics( resVarAddr )->cellScalarValuesHistogram( timeStepIndex );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const std::vector<int>& RigFlowDiagResults::uniqueCellScalarValues( const RigFlowDiagResultAddress& resVarAddr )
|
|
{
|
|
return this->statistics( resVarAddr )->uniqueCellScalarValues();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const std::vector<int>& RigFlowDiagResults::uniqueCellScalarValues( const RigFlowDiagResultAddress& resVarAddr, int timeStepIndex )
|
|
{
|
|
return this->statistics( resVarAddr )->uniqueCellScalarValues( timeStepIndex );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFlowDiagResults::mobileVolumeWeightedMean( const RigFlowDiagResultAddress& resVarAddr, int timeStepIndex, double* mean )
|
|
{
|
|
this->statistics( resVarAddr )->mobileVolumeWeightedMean( timeStepIndex, *mean );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFlowDiagResults::mobileVolumeWeightedMean( const RigFlowDiagResultAddress& resVarAddr, double* mean )
|
|
{
|
|
this->statistics( resVarAddr )->mobileVolumeWeightedMean( *mean );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::pair<double, double>
|
|
RigFlowDiagResults::injectorProducerPairFluxes( const std::string& injTracername, const std::string& prodTracerName, int timeStepIndex )
|
|
{
|
|
calculateNativeResultsIfNotPreviouslyAttempted( timeStepIndex, RigFlowDiagResultAddress::PHASE_ALL );
|
|
|
|
auto commPair = m_injProdPairFluxCommunicationTimesteps[timeStepIndex][RigFlowDiagResultAddress::PHASE_ALL].find(
|
|
std::make_pair( injTracername, prodTracerName ) );
|
|
if ( commPair != m_injProdPairFluxCommunicationTimesteps[timeStepIndex][RigFlowDiagResultAddress::PHASE_ALL].end() )
|
|
{
|
|
return commPair->second;
|
|
}
|
|
else
|
|
{
|
|
return std::make_pair( 0.0, 0.0 );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
double RigFlowDiagResults::maxAbsPairFlux( int timeStepIndex )
|
|
{
|
|
calculateNativeResultsIfNotPreviouslyAttempted( timeStepIndex, RigFlowDiagResultAddress::PHASE_ALL );
|
|
double maxFlux = 0.0;
|
|
|
|
if ( (size_t)timeStepIndex < m_injProdPairFluxCommunicationTimesteps.size() )
|
|
{
|
|
for ( const auto& commPair : m_injProdPairFluxCommunicationTimesteps[timeStepIndex][RigFlowDiagResultAddress::PHASE_ALL] )
|
|
{
|
|
if ( fabs( commPair.second.first ) > maxFlux ) maxFlux = fabs( commPair.second.first );
|
|
if ( fabs( commPair.second.second ) > maxFlux ) maxFlux = fabs( commPair.second.second );
|
|
}
|
|
}
|
|
|
|
return maxFlux;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<int> RigFlowDiagResults::calculatedTimeSteps( RigFlowDiagResultAddress::PhaseSelection phaseSelection )
|
|
{
|
|
std::vector<int> timestepIndices;
|
|
for ( size_t tsIdx = 0; tsIdx < m_timeStepCount; ++tsIdx )
|
|
{
|
|
auto it = m_hasAtemptedNativeResults[tsIdx].find( phaseSelection );
|
|
if ( it != m_hasAtemptedNativeResults[tsIdx].end() && it->second )
|
|
{
|
|
timestepIndices.push_back( static_cast<int>( tsIdx ) );
|
|
}
|
|
}
|
|
|
|
return timestepIndices;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RigFlowDiagSolverInterface::FlowCharacteristicsResultFrame RigFlowDiagResults::flowCharacteristicsResults( int timeStepIndex,
|
|
CellFilter cellSelection,
|
|
const std::vector<QString>& tracerNames,
|
|
double max_pv_fraction,
|
|
double minCommunication,
|
|
int maxTof )
|
|
{
|
|
std::set<std::string> injectorNames;
|
|
std::set<std::string> producerNames;
|
|
|
|
for ( const QString& tracerName : tracerNames )
|
|
{
|
|
RimFlowDiagSolution::TracerStatusType status = m_flowDiagSolution->tracerStatusInTimeStep( tracerName, timeStepIndex );
|
|
if ( status == RimFlowDiagSolution::TracerStatusType::INJECTOR )
|
|
{
|
|
injectorNames.insert( tracerName.toStdString() );
|
|
}
|
|
else if ( status == RimFlowDiagSolution::TracerStatusType::PRODUCER )
|
|
{
|
|
producerNames.insert( tracerName.toStdString() );
|
|
}
|
|
}
|
|
|
|
RigFlowDiagResultAddress injectorAddress( RIG_FLD_TOF_RESNAME, RigFlowDiagResultAddress::PHASE_ALL, injectorNames );
|
|
RigFlowDiagResultAddress producerAddress( RIG_FLD_TOF_RESNAME, RigFlowDiagResultAddress::PHASE_ALL, producerNames );
|
|
|
|
const std::vector<double>* allInjectorResults = resultValues( injectorAddress, timeStepIndex );
|
|
const std::vector<double>* allProducerResults = resultValues( producerAddress, timeStepIndex );
|
|
|
|
std::vector<double> injectorResults;
|
|
std::vector<double> producerResults;
|
|
std::vector<size_t> selectedCellIndices;
|
|
|
|
if ( cellSelection == CELLS_COMMUNICATION )
|
|
{
|
|
std::set<std::string> allTracers;
|
|
allTracers.insert( injectorNames.begin(), injectorNames.end() );
|
|
allTracers.insert( producerNames.begin(), producerNames.end() );
|
|
|
|
RigFlowDiagResultAddress communicationAddress( RIG_FLD_COMMUNICATION_RESNAME, RigFlowDiagResultAddress::PHASE_ALL, allTracers );
|
|
const std::vector<double>* communicationResult = resultValues( communicationAddress, timeStepIndex );
|
|
|
|
for ( size_t i = 0; i < communicationResult->size(); ++i )
|
|
{
|
|
if ( communicationResult->at( i ) != HUGE_VAL && communicationResult->at( i ) >= minCommunication )
|
|
{
|
|
selectedCellIndices.push_back( i );
|
|
if ( allInjectorResults != nullptr ) injectorResults.push_back( allInjectorResults->at( i ) );
|
|
if ( allProducerResults != nullptr ) producerResults.push_back( allProducerResults->at( i ) );
|
|
}
|
|
}
|
|
}
|
|
else if ( cellSelection == CELLS_FLOODED )
|
|
{
|
|
if ( allInjectorResults != nullptr )
|
|
{
|
|
for ( size_t i = 0; i < allInjectorResults->size(); ++i )
|
|
{
|
|
if ( allInjectorResults->at( i ) != HUGE_VAL && allInjectorResults->at( i ) <= maxTof )
|
|
{
|
|
selectedCellIndices.push_back( i );
|
|
injectorResults.push_back( allInjectorResults->at( i ) );
|
|
if ( allProducerResults != nullptr )
|
|
{
|
|
producerResults.push_back( allProducerResults->at( i ) );
|
|
}
|
|
else
|
|
{
|
|
producerResults.push_back( 0 );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ( cellSelection == CELLS_DRAINED )
|
|
{
|
|
if ( allProducerResults != nullptr )
|
|
{
|
|
for ( size_t i = 0; i < allProducerResults->size(); ++i )
|
|
{
|
|
if ( allProducerResults->at( i ) != HUGE_VAL && allProducerResults->at( i ) <= maxTof )
|
|
{
|
|
selectedCellIndices.push_back( i );
|
|
producerResults.push_back( allProducerResults->at( i ) );
|
|
if ( allInjectorResults != nullptr )
|
|
{
|
|
injectorResults.push_back( allInjectorResults->at( i ) );
|
|
}
|
|
else
|
|
{
|
|
injectorResults.push_back( 0 );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( allInjectorResults != nullptr ) injectorResults = *allInjectorResults;
|
|
if ( allProducerResults != nullptr ) producerResults = *allProducerResults;
|
|
|
|
for ( size_t i = 0; i < injectorResults.size(); ++i )
|
|
{
|
|
selectedCellIndices.push_back( i );
|
|
}
|
|
}
|
|
|
|
return solverInterface()->calculateFlowCharacteristics( &injectorResults, &producerResults, selectedCellIndices, max_pv_fraction );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RigFlowDiagSolverInterface::FlowCharacteristicsResultFrame
|
|
RigFlowDiagResults::flowCharacteristicsResults( int timeStepIndex, const std::vector<char>& visibleActiveCells, double max_pv_fraction )
|
|
{
|
|
std::vector<QString> tracerNames = m_flowDiagSolution->tracerNames();
|
|
|
|
std::set<std::string> injectorNames;
|
|
std::set<std::string> producerNames;
|
|
|
|
for ( const QString& tracerName : tracerNames )
|
|
{
|
|
RimFlowDiagSolution::TracerStatusType status = m_flowDiagSolution->tracerStatusInTimeStep( tracerName, timeStepIndex );
|
|
if ( status == RimFlowDiagSolution::TracerStatusType::INJECTOR )
|
|
{
|
|
injectorNames.insert( tracerName.toStdString() );
|
|
}
|
|
else if ( status == RimFlowDiagSolution::TracerStatusType::PRODUCER )
|
|
{
|
|
producerNames.insert( tracerName.toStdString() );
|
|
}
|
|
}
|
|
|
|
RigFlowDiagResultAddress injectorAddress( RIG_FLD_TOF_RESNAME, RigFlowDiagResultAddress::PHASE_ALL, injectorNames );
|
|
RigFlowDiagResultAddress producerAddress( RIG_FLD_TOF_RESNAME, RigFlowDiagResultAddress::PHASE_ALL, producerNames );
|
|
|
|
const std::vector<double>* allInjectorResults = resultValues( injectorAddress, timeStepIndex );
|
|
const std::vector<double>* allProducerResults = resultValues( producerAddress, timeStepIndex );
|
|
|
|
std::vector<size_t> selectedCellIndices;
|
|
std::vector<double> injectorResults;
|
|
std::vector<double> producerResults;
|
|
|
|
for ( size_t i = 0; i < visibleActiveCells.size(); ++i )
|
|
{
|
|
if ( visibleActiveCells[i] )
|
|
{
|
|
selectedCellIndices.push_back( i );
|
|
injectorResults.push_back( allInjectorResults->at( i ) );
|
|
producerResults.push_back( allProducerResults->at( i ) );
|
|
}
|
|
}
|
|
|
|
return solverInterface()->calculateFlowCharacteristics( &injectorResults, &producerResults, selectedCellIndices, max_pv_fraction );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimFlowDiagSolution* RigFlowDiagResults::flowDiagSolution()
|
|
{
|
|
{
|
|
return m_flowDiagSolution;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigFlowDiagResults::setStatisticsDataCacheNumBins( const RigFlowDiagResultAddress& resVarAddr, size_t numBins )
|
|
{
|
|
this->statistics( resVarAddr )->setNumBins( numBins );
|
|
}
|