Optionally apply a grid calculation on all grids

This commit is contained in:
Magne Sjaastad 2023-11-07 14:04:53 +01:00
parent 3bf81b44d5
commit 7eb3e98bb2
8 changed files with 215 additions and 97 deletions

View File

@ -205,6 +205,11 @@ bool RicUserDefinedCalculatorUi::calculate() const
notifyCalculatedNameChanged( m_currentCalculation()->id(), currentCurveName ); notifyCalculatedNameChanged( m_currentCalculation()->id(), currentCurveName );
} }
if ( !m_currentCalculation()->preCalculate() )
{
return false;
}
if ( !m_currentCalculation()->calculate() ) if ( !m_currentCalculation()->calculate() )
{ {
return false; return false;

View File

@ -19,12 +19,15 @@
#include "RimGridCalculation.h" #include "RimGridCalculation.h"
#include "RiaDefines.h" #include "RiaDefines.h"
#include "RiaGuiApplication.h"
#include "RiaLogging.h" #include "RiaLogging.h"
#include "RiaPorosityModel.h" #include "RiaPorosityModel.h"
#include "RigActiveCellInfo.h" #include "RigActiveCellInfo.h"
#include "RimEclipseCase.h" #include "RimEclipseCase.h"
#include "RimEclipseCaseTools.h"
#include "RimEclipseCellColors.h" #include "RimEclipseCellColors.h"
#include "RimEclipseStatisticsCase.h"
#include "RimEclipseView.h" #include "RimEclipseView.h"
#include "RimGridCalculationVariable.h" #include "RimGridCalculationVariable.h"
#include "RimProject.h" #include "RimProject.h"
@ -41,6 +44,8 @@
#include "expressionparser/ExpressionParser.h" #include "expressionparser/ExpressionParser.h"
#include <QMessageBox>
CAF_PDM_SOURCE_INIT( RimGridCalculation, "RimGridCalculation" ); CAF_PDM_SOURCE_INIT( RimGridCalculation, "RimGridCalculation" );
namespace caf namespace caf
@ -65,9 +70,28 @@ RimGridCalculation::RimGridCalculation()
CAF_PDM_InitFieldNoDefault( &m_defaultValueType, "DefaultValueType", "Non-visible Cell Value" ); CAF_PDM_InitFieldNoDefault( &m_defaultValueType, "DefaultValueType", "Non-visible Cell Value" );
CAF_PDM_InitField( &m_defaultValue, "DefaultValue", 0.0, "Custom Value" ); CAF_PDM_InitField( &m_defaultValue, "DefaultValue", 0.0, "Custom Value" );
CAF_PDM_InitFieldNoDefault( &m_destinationCase, "DestinationCase", "Destination Case" ); CAF_PDM_InitFieldNoDefault( &m_destinationCase, "DestinationCase", "Destination Case" );
CAF_PDM_InitField( &m_allCases, "AllDestinationCase", false, "Apply to All Cases" );
CAF_PDM_InitField( &m_defaultPropertyVariableIndex, "DefaultPropertyVariableName", 0, "Property Variable Name" ); CAF_PDM_InitField( &m_defaultPropertyVariableIndex, "DefaultPropertyVariableName", 0, "Property Variable Name" );
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimGridCalculation::preCalculate() const
{
if ( RiaGuiApplication::isRunning() && m_allCases() )
{
auto reply = QMessageBox::question( nullptr,
QString( "Grid Property Calculator" ),
QString( "Calculation will be executed on all grid model cases. Do you want to continue? " ),
QMessageBox::Yes | QMessageBox::No );
if ( reply == QMessageBox::No ) return false;
}
return true;
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -87,12 +111,12 @@ bool RimGridCalculation::calculate()
{ {
QString leftHandSideVariableName = RimGridCalculation::findLeftHandSide( m_expression ); QString leftHandSideVariableName = RimGridCalculation::findLeftHandSide( m_expression );
RimEclipseCase* eclipseCase = outputEclipseCase(); if ( !m_destinationCase )
if ( !eclipseCase )
{ {
RiaLogging::errorInMessageBox( nullptr, RiaLogging::errorInMessageBox( nullptr,
"Grid Property Calculator", "Grid Property Calculator",
QString( "No case found for calculation : %1" ).arg( leftHandSideVariableName ) ); QString( "No destination case found for calculation : %1" ).arg( leftHandSideVariableName ) );
return false; return false;
} }
@ -105,7 +129,7 @@ bool RimGridCalculation::calculate()
for ( auto variableCase : inputCases() ) for ( auto variableCase : inputCases() )
{ {
if ( !eclipseCase->isGridSizeEqualTo( variableCase ) ) if ( !m_destinationCase->isGridSizeEqualTo( variableCase ) )
{ {
QString msg = "Detected IJK mismatch between input cases and destination case. All grid " QString msg = "Detected IJK mismatch between input cases and destination case. All grid "
"cases must have identical IJK sizes."; "cases must have identical IJK sizes.";
@ -114,24 +138,44 @@ bool RimGridCalculation::calculate()
} }
} }
const bool isMultipleCasesPresent = outputEclipseCases().size() > 1;
if ( isMultipleCasesPresent )
{
QString txt = "Starting calculation " + description() + " for " + QString::number( outputEclipseCases().size() ) + " cases.";
RiaLogging::info( txt );
}
bool anyErrorsDetected = false;
for ( RimEclipseCase* outputEclipseCase : outputEclipseCases() )
{
if ( !outputEclipseCase )
{
RiaLogging::errorInMessageBox( nullptr,
"Grid Property Calculator",
QString( "No case found for calculation : %1" ).arg( leftHandSideVariableName ) );
anyErrorsDetected = true;
continue;
}
auto porosityModel = RiaDefines::PorosityModelType::MATRIX_MODEL; auto porosityModel = RiaDefines::PorosityModelType::MATRIX_MODEL;
RigEclipseResultAddress resAddr( RiaDefines::ResultCatType::GENERATED, leftHandSideVariableName ); RigEclipseResultAddress resAddr( RiaDefines::ResultCatType::GENERATED, leftHandSideVariableName );
if ( !eclipseCase->results( porosityModel )->ensureKnownResultLoaded( resAddr ) ) if ( !outputEclipseCase->results( porosityModel )->ensureKnownResultLoaded( resAddr ) )
{ {
bool needsToBeStored = false; bool needsToBeStored = false;
eclipseCase->results( porosityModel )->createResultEntry( resAddr, needsToBeStored ); outputEclipseCase->results( porosityModel )->createResultEntry( resAddr, needsToBeStored );
} }
eclipseCase->results( porosityModel )->clearScalarResult( resAddr ); outputEclipseCase->results( porosityModel )->clearScalarResult( resAddr );
// If an input grid is present, max time step count is zero. Make sure the time step count for the calculation is // If an input grid is present, max time step count is zero. Make sure the time step count for the calculation is
// always 1 or more. // always 1 or more.
const size_t timeStepCount = std::max( size_t( 1 ), eclipseCase->results( porosityModel )->maxTimeStepCount() ); const size_t timeStepCount = std::max( size_t( 1 ), outputEclipseCase->results( porosityModel )->maxTimeStepCount() );
std::vector<std::vector<double>>* scalarResultFrames = std::vector<std::vector<double>>* scalarResultFrames =
eclipseCase->results( porosityModel )->modifiableCellScalarResultTimesteps( resAddr ); outputEclipseCase->results( porosityModel )->modifiableCellScalarResultTimesteps( resAddr );
scalarResultFrames->resize( timeStepCount ); scalarResultFrames->resize( timeStepCount );
for ( size_t tsId = 0; tsId < timeStepCount; tsId++ ) for ( size_t tsId = 0; tsId < timeStepCount; tsId++ )
@ -141,7 +185,7 @@ bool RimGridCalculation::calculate()
{ {
RimGridCalculationVariable* v = dynamic_cast<RimGridCalculationVariable*>( m_variables[i] ); RimGridCalculationVariable* v = dynamic_cast<RimGridCalculationVariable*>( m_variables[i] );
CAF_ASSERT( v != nullptr ); CAF_ASSERT( v != nullptr );
values.push_back( getInputVectorForVariable( v, tsId, porosityModel, outputEclipseCase() ) ); values.push_back( getInputVectorForVariable( v, tsId, porosityModel, outputEclipseCase ) );
} }
ExpressionParser parser; ExpressionParser parser;
@ -163,7 +207,7 @@ bool RimGridCalculation::calculate()
{ {
if ( m_cellFilterView() ) if ( m_cellFilterView() )
{ {
filterResults( m_cellFilterView(), values, m_defaultValueType(), m_defaultValue(), resultValues, porosityModel, outputEclipseCase() ); filterResults( m_cellFilterView(), values, m_defaultValueType(), m_defaultValue(), resultValues, porosityModel, outputEclipseCase );
} }
scalarResultFrames->at( tsId ) = resultValues; scalarResultFrames->at( tsId ) = resultValues;
@ -178,19 +222,43 @@ bool RimGridCalculation::calculate()
RiaLogging::errorInMessageBox( nullptr, "Grid Property Calculator", s ); RiaLogging::errorInMessageBox( nullptr, "Grid Property Calculator", s );
return false; return false;
} }
outputEclipseCase->updateResultAddressCollection();
} }
eclipseCase->updateResultAddressCollection(); if ( isMultipleCasesPresent )
{
QString txt = " " + outputEclipseCase->caseUserDescription();
RiaLogging::info( txt );
}
}
return true; if ( isMultipleCasesPresent )
{
QString txt = "Completed calculation " + description() + " for " + QString::number( outputEclipseCases().size() ) + " cases";
RiaLogging::info( txt );
}
return !anyErrorsDetected;
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
RimEclipseCase* RimGridCalculation::outputEclipseCase() const std::vector<RimEclipseCase*> RimGridCalculation::outputEclipseCases() const
{ {
return m_destinationCase; if ( m_allCases )
{
// Find all Eclipse cases suitable for grid calculations. This includes all single grid cases and source cases in a grid case group.
// Exclude the statistics cases, as it is not possible to use them in a grid calculations.
//
// Note that data read from file can be released from memory when statistics for a time step is calculated. See
// RimEclipseStatisticsCaseEvaluator::evaluateForResults()
return RimEclipseCaseTools::allEclipseGridCases();
}
return { m_destinationCase };
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -230,6 +298,13 @@ void RimGridCalculation::defineUiOrdering( QString uiConfigName, caf::PdmUiOrder
uiOrdering.add( &m_destinationCase ); uiOrdering.add( &m_destinationCase );
uiOrdering.add( &m_allCases );
if ( !allSourceCasesAreEqualToDestinationCase() )
{
m_allCases = false;
}
m_allCases.uiCapability()->setUiReadOnly( !allSourceCasesAreEqualToDestinationCase() );
caf::PdmUiGroup* filterGroup = uiOrdering.addNewGroup( "Cell Filter" ); caf::PdmUiGroup* filterGroup = uiOrdering.addNewGroup( "Cell Filter" );
filterGroup->setCollapsedByDefault(); filterGroup->setCollapsedByDefault();
filterGroup->add( &m_cellFilterView ); filterGroup->add( &m_cellFilterView );
@ -278,27 +353,19 @@ QList<caf::PdmOptionItemInfo> RimGridCalculation::calculateValueOptions( const c
} }
else if ( fieldNeedingOptions == &m_destinationCase ) else if ( fieldNeedingOptions == &m_destinationCase )
{ {
if ( inputCases().empty() ) RimEclipseCase* firstInputCase = nullptr;
{
RimTools::eclipseCaseOptionItems( &options );
}
else
{
RimEclipseCase* firstInputCase = inputCases()[0];
RimProject* proj = RimProject::current(); if ( !inputCases().empty() )
if ( proj )
{ {
std::vector<RimCase*> cases = proj->allGridCases(); firstInputCase = inputCases()[0];
for ( RimCase* c : cases ) }
for ( auto eclipseCase : RimEclipseCaseTools::allEclipseGridCases() )
{ {
auto* eclipseCase = dynamic_cast<RimEclipseCase*>( c );
if ( !eclipseCase ) continue; if ( !eclipseCase ) continue;
if ( !firstInputCase->isGridSizeEqualTo( eclipseCase ) ) continue; if ( firstInputCase && !firstInputCase->isGridSizeEqualTo( eclipseCase ) ) continue;
options.push_back( caf::PdmOptionItemInfo( c->caseUserDescription(), c, false, c->uiIconProvider() ) ); options.push_back( caf::PdmOptionItemInfo( eclipseCase->caseUserDescription(), eclipseCase, false, eclipseCase->uiIconProvider() ) );
}
}
} }
options.push_front( caf::PdmOptionItemInfo( "None", nullptr ) ); options.push_front( caf::PdmOptionItemInfo( "None", nullptr ) );
@ -350,6 +417,25 @@ void RimGridCalculation::onVariableUpdated( const SignalEmitter* emitter )
} }
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimGridCalculation::allSourceCasesAreEqualToDestinationCase() const
{
if ( m_destinationCase() == nullptr ) return false;
for ( const auto& variable : m_variables )
{
auto gridVar = dynamic_cast<RimGridCalculationVariable*>( variable.p() );
if ( gridVar )
{
if ( gridVar->eclipseCase() != m_destinationCase() ) return false;
}
}
return true;
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -368,6 +454,11 @@ std::vector<double> RimGridCalculation::getInputVectorForVariable( RimGridCalcul
RiaDefines::PorosityModelType porosityModel, RiaDefines::PorosityModelType porosityModel,
RimEclipseCase* outputEclipseCase ) const RimEclipseCase* outputEclipseCase ) const
{ {
if ( !outputEclipseCase ) return {};
const RigMainGrid* mainGrid = outputEclipseCase->mainGrid();
if ( !mainGrid ) return {};
int timeStep = v->timeStep(); int timeStep = v->timeStep();
auto resultCategoryType = v->resultCategoryType(); auto resultCategoryType = v->resultCategoryType();
@ -388,10 +479,13 @@ std::vector<double> RimGridCalculation::getInputVectorForVariable( RimGridCalcul
RigEclipseResultAddress resAddr( resultCategoryType, v->resultVariable() ); RigEclipseResultAddress resAddr( resultCategoryType, v->resultVariable() );
auto mainGrid = v->eclipseCase()->mainGrid(); auto eclipseCaseData = outputEclipseCase->eclipseCaseData();
auto rigCaseCellResultsData = eclipseCaseData->results( porosityModel );
if ( !rigCaseCellResultsData->ensureKnownResultLoaded( resAddr ) ) return {};
size_t maxGridCount = mainGrid->gridCount(); size_t maxGridCount = mainGrid->gridCount();
auto activeCellInfo = outputEclipseCase->eclipseCaseData()->activeCellInfo( porosityModel ); auto activeCellInfo = eclipseCaseData->activeCellInfo( porosityModel );
size_t cellCount = activeCellInfo->reservoirActiveCellCount(); size_t cellCount = activeCellInfo->reservoirActiveCellCount();
std::vector<double> inputValues( cellCount ); std::vector<double> inputValues( cellCount );
@ -400,7 +494,7 @@ std::vector<double> RimGridCalculation::getInputVectorForVariable( RimGridCalcul
auto grid = mainGrid->gridByIndex( gridIdx ); auto grid = mainGrid->gridByIndex( gridIdx );
cvf::ref<RigResultAccessor> sourceResultAccessor = cvf::ref<RigResultAccessor> sourceResultAccessor =
RigResultAccessorFactory::createFromResultAddress( v->eclipseCase()->eclipseCaseData(), gridIdx, porosityModel, timeStepToUse, resAddr ); RigResultAccessorFactory::createFromResultAddress( eclipseCaseData, gridIdx, porosityModel, timeStepToUse, resAddr );
#pragma omp parallel for #pragma omp parallel for
for ( int localGridCellIdx = 0; localGridCellIdx < static_cast<int>( grid->cellCount() ); localGridCellIdx++ ) for ( int localGridCellIdx = 0; localGridCellIdx < static_cast<int>( grid->cellCount() ); localGridCellIdx++ )
@ -503,11 +597,13 @@ void RimGridCalculation::filterResults( RimGridView*
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RimGridCalculation::updateDependentObjects() void RimGridCalculation::updateDependentObjects()
{ {
RimEclipseCase* eclipseCase = outputEclipseCase(); for ( RimEclipseCase* eclipseCase : outputEclipseCases() )
{
if ( eclipseCase ) if ( eclipseCase )
{ {
RimReloadCaseTools::updateAll3dViews( eclipseCase ); RimReloadCaseTools::updateAll3dViews( eclipseCase );
} }
}
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -521,7 +617,8 @@ void RimGridCalculation::removeDependentObjects()
RigEclipseResultAddress resAddr( RiaDefines::ResultCatType::GENERATED, leftHandSideVariableName ); RigEclipseResultAddress resAddr( RiaDefines::ResultCatType::GENERATED, leftHandSideVariableName );
RimEclipseCase* eclipseCase = outputEclipseCase(); for ( RimEclipseCase* eclipseCase : outputEclipseCases() )
{
if ( eclipseCase ) if ( eclipseCase )
{ {
// Select "None" result if the result that is being removed were displayed in a view. // Select "None" result if the result that is being removed were displayed in a view.
@ -539,6 +636,7 @@ void RimGridCalculation::removeDependentObjects()
RimReloadCaseTools::updateAll3dViews( eclipseCase ); RimReloadCaseTools::updateAll3dViews( eclipseCase );
} }
}
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@ -47,11 +47,12 @@ public:
RimGridCalculation(); RimGridCalculation();
bool preCalculate() const override;
bool calculate() override; bool calculate() override;
void updateDependentObjects() override; void updateDependentObjects() override;
void removeDependentObjects() override; void removeDependentObjects() override;
RimEclipseCase* outputEclipseCase() const; std::vector<RimEclipseCase*> outputEclipseCases() const;
RigEclipseResultAddress outputAddress() const; RigEclipseResultAddress outputAddress() const;
std::vector<RimEclipseCase*> inputCases() const; std::vector<RimEclipseCase*> inputCases() const;
@ -96,11 +97,14 @@ protected:
private: private:
void onVariableUpdated( const SignalEmitter* emitter ); void onVariableUpdated( const SignalEmitter* emitter );
bool allSourceCasesAreEqualToDestinationCase() const;
private: private:
caf::PdmPtrField<RimGridView*> m_cellFilterView; caf::PdmPtrField<RimGridView*> m_cellFilterView;
caf::PdmField<caf::AppEnum<DefaultValueType>> m_defaultValueType; caf::PdmField<caf::AppEnum<DefaultValueType>> m_defaultValueType;
caf::PdmField<double> m_defaultValue; caf::PdmField<double> m_defaultValue;
caf::PdmPtrField<RimEclipseCase*> m_destinationCase; caf::PdmPtrField<RimEclipseCase*> m_destinationCase;
caf::PdmField<bool> m_allCases;
caf::PdmField<int> m_defaultPropertyVariableIndex; caf::PdmField<int> m_defaultPropertyVariableIndex;
}; };

View File

@ -57,14 +57,14 @@ std::vector<RimGridCalculation*> RimGridCalculationCollection::sortedGridCalcula
// Check if source calculation is depending on other. Will check one level dependency. // Check if source calculation is depending on other. Will check one level dependency.
auto isSourceDependingOnOther = []( const RimGridCalculation* source, const RimGridCalculation* other ) -> bool auto isSourceDependingOnOther = []( const RimGridCalculation* source, const RimGridCalculation* other ) -> bool
{ {
auto outputCase = source->outputEclipseCase(); auto outputCases = source->outputEclipseCases();
auto outputAdr = source->outputAddress(); auto outputAdr = source->outputAddress();
for ( auto v : other->allVariables() ) for ( auto v : other->allVariables() )
{ {
auto gridVariable = dynamic_cast<RimGridCalculationVariable*>( v ); auto gridVariable = dynamic_cast<RimGridCalculationVariable*>( v );
if ( gridVariable->eclipseCase() == outputCase && outputAdr.resultCatType() == gridVariable->resultCategoryType() && if ( std::find( outputCases.begin(), outputCases.end(), gridVariable->eclipseCase() ) != outputCases.end() &&
outputAdr.resultName() == gridVariable->resultVariable() ) outputAdr.resultCatType() == gridVariable->resultCategoryType() && outputAdr.resultName() == gridVariable->resultVariable() )
{ {
return true; return true;
} }

View File

@ -110,8 +110,7 @@ QList<caf::PdmOptionItemInfo> RimResultSelectionUi::calculateValueOptions( const
if ( fieldNeedingOptions == &m_eclipseCase ) if ( fieldNeedingOptions == &m_eclipseCase )
{ {
auto cases = RimEclipseCaseTools::eclipseCases(); for ( auto* c : RimEclipseCaseTools::allEclipseGridCases() )
for ( auto* c : cases )
{ {
options.push_back( caf::PdmOptionItemInfo( c->caseUserDescription(), c, false, c->uiIconProvider() ) ); options.push_back( caf::PdmOptionItemInfo( c->caseUserDescription(), c, false, c->uiIconProvider() ) );
} }

View File

@ -244,6 +244,14 @@ bool RimUserDefinedCalculation::parseExpression()
return true; return true;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimUserDefinedCalculation::preCalculate() const
{
return true;
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// Find the last assignment using := and interpret the text before the := as LHS /// Find the last assignment using := and interpret the text before the := as LHS
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@ -56,6 +56,7 @@ public:
QString unitName() const; QString unitName() const;
bool parseExpression(); bool parseExpression();
virtual bool preCalculate() const;
virtual bool calculate() = 0; virtual bool calculate() = 0;
virtual void updateDependentObjects() = 0; virtual void updateDependentObjects() = 0;
virtual void removeDependentObjects() = 0; virtual void removeDependentObjects() = 0;

View File

@ -2626,8 +2626,11 @@ void RigCaseCellResultsData::computeCompletionTypeForTimeStep( size_t timeStep )
{ {
for ( auto userCalculation : RimProject::current()->gridCalculationCollection()->calculations() ) for ( auto userCalculation : RimProject::current()->gridCalculationCollection()->calculations() )
{ {
auto gridCalculation = dynamic_cast<RimGridCalculation*>( userCalculation ); if ( auto gridCalculation = dynamic_cast<RimGridCalculation*>( userCalculation ) )
if ( gridCalculation && gridCalculation->outputEclipseCase() != eclipseCase ) continue; {
auto outputCases = gridCalculation->outputEclipseCases();
if ( std::find( outputCases.begin(), outputCases.end(), eclipseCase ) == outputCases.end() ) continue;
}
QString generatedPropertyName = RimUserDefinedCalculation::findLeftHandSide( userCalculation->expression() ); QString generatedPropertyName = RimUserDefinedCalculation::findLeftHandSide( userCalculation->expression() );
if ( generatedPropertyName == propertyName ) if ( generatedPropertyName == propertyName )