RimReservoirGridEnsembleBase: Make optional methods non-pure virtual with default implementations

mainGrid(), unionOfActiveCells(), computeUnionOfActiveCells(), and statisticsCaseCollection() default to null/no-op. Remove redundant overrides from RimEclipseCaseEnsemble.
This commit is contained in:
Magne Sjaastad
2026-03-03 07:35:48 +01:00
parent 570fbf111f
commit 8fdaa83f15
17 changed files with 491 additions and 117 deletions
@@ -20,6 +20,7 @@
#include "ContourMap/RimStatisticsContourMap.h"
#include "RimEclipseCaseEnsemble.h"
#include "RimReservoirGridEnsemble.h"
#include "Riu3DMainWindowTools.h"
@@ -47,12 +48,30 @@ void RicNewStatisticsContourMapFeature::addStatisticsContourMap( RimEclipseCaseE
Riu3DMainWindowTools::selectAsCurrentItem( statisticsContourMap );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewStatisticsContourMapFeature::addStatisticsContourMap( RimReservoirGridEnsemble* gridEnsemble )
{
if ( !gridEnsemble ) return;
std::vector<RimEclipseCase*> cases = gridEnsemble->cases();
if ( cases.empty() ) return;
auto statisticsContourMap = new RimStatisticsContourMap();
statisticsContourMap->setEclipseCase( cases[0] );
gridEnsemble->addStatisticsContourMap( statisticsContourMap );
gridEnsemble->updateConnectedEditors();
Riu3DMainWindowTools::selectAsCurrentItem( statisticsContourMap );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicNewStatisticsContourMapFeature::isCommandEnabled() const
{
return selectedEclipseCaseEnsemble() != nullptr;
return selectedEclipseCaseEnsemble() != nullptr || selectedGridEnsemble() != nullptr;
}
//--------------------------------------------------------------------------------------------------
@@ -60,8 +79,14 @@ bool RicNewStatisticsContourMapFeature::isCommandEnabled() const
//--------------------------------------------------------------------------------------------------
void RicNewStatisticsContourMapFeature::onActionTriggered( bool isChecked )
{
RimEclipseCaseEnsemble* eclipseCaseEnsemble = selectedEclipseCaseEnsemble();
addStatisticsContourMap( eclipseCaseEnsemble );
if ( auto* eclipseCaseEnsemble = selectedEclipseCaseEnsemble() )
{
addStatisticsContourMap( eclipseCaseEnsemble );
}
else if ( auto* gridEnsemble = selectedGridEnsemble() )
{
addStatisticsContourMap( gridEnsemble );
}
}
//--------------------------------------------------------------------------------------------------
@@ -80,3 +105,11 @@ RimEclipseCaseEnsemble* RicNewStatisticsContourMapFeature::selectedEclipseCaseEn
{
return caf::SelectionManager::instance()->selectedItemOfType<RimEclipseCaseEnsemble>();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimReservoirGridEnsemble* RicNewStatisticsContourMapFeature::selectedGridEnsemble()
{
return caf::SelectionManager::instance()->selectedItemOfType<RimReservoirGridEnsemble>();
}
@@ -21,6 +21,7 @@
#include "cafCmdFeature.h"
class RimEclipseCaseEnsemble;
class RimReservoirGridEnsemble;
//==================================================================================================
///
@@ -31,11 +32,13 @@ class RicNewStatisticsContourMapFeature : public caf::CmdFeature
public:
static void addStatisticsContourMap( RimEclipseCaseEnsemble* eclipseCaseEnsemble );
static void addStatisticsContourMap( RimReservoirGridEnsemble* gridEnsemble );
protected:
bool isCommandEnabled() const override;
void onActionTriggered( bool isChecked ) override;
void setupActionLook( QAction* actionToSetup ) override;
static RimEclipseCaseEnsemble* selectedEclipseCaseEnsemble();
static RimEclipseCaseEnsemble* selectedEclipseCaseEnsemble();
static RimReservoirGridEnsemble* selectedGridEnsemble();
};
@@ -20,6 +20,7 @@
#include "RimEclipseCase.h"
#include "RimEclipseCaseEnsemble.h"
#include "RimReservoirGridEnsemble.h"
#include "RimWellTargetMapping.h"
#include "RiuMainWindow.h"
@@ -45,6 +46,16 @@ void RicNewWellTargetMappingFeature::onActionTriggered( bool isChecked )
ensemble->updateConnectedEditors();
RiuMainWindow::instance()->selectAsCurrentItem( wellTargetMapping );
}
else if ( auto gridEnsembles = caf::selectedObjectsByTypeStrict<RimReservoirGridEnsemble*>(); !gridEnsembles.empty() )
{
auto ensemble = gridEnsembles.front();
auto wellTargetMapping = new RimWellTargetMapping();
ensemble->addWellTargetMapping( wellTargetMapping );
wellTargetMapping->setDefaults();
ensemble->updateConnectedEditors();
RiuMainWindow::instance()->selectAsCurrentItem( wellTargetMapping );
}
else if ( auto eclipseCases = caf::selectedObjectsByTypeStrict<RimEclipseCase*>(); !eclipseCases.empty() )
{
auto eclipseCase = eclipseCases.front();
@@ -44,6 +44,7 @@
#include "RimEclipseCaseEnsemble.h"
#include "RimEclipseContourMapProjection.h"
#include "RimEclipseResultDefinition.h"
#include "RimReservoirGridEnsemble.h"
#include "RimSimWellInViewCollection.h"
#include "RimStatisticsContourMapProjection.h"
#include "RimStatisticsContourMapView.h"
@@ -150,9 +151,9 @@ RimStatisticsContourMap::RimStatisticsContourMap()
//--------------------------------------------------------------------------------------------------
void RimStatisticsContourMap::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
if ( ( eclipseCase() == nullptr ) && ( !ensemble()->cases().empty() ) )
if ( ( eclipseCase() == nullptr ) && ( !ensembleCases().empty() ) )
{
auto selCase = ensemble()->cases().front();
auto selCase = ensembleCases().front();
setEclipseCase( selCase );
}
@@ -203,7 +204,7 @@ void RimStatisticsContourMap::defineUiOrdering( QString uiConfigName, caf::PdmUi
tsGroup->setCollapsedByDefault();
tsGroup->add( &m_selectedTimeSteps );
if ( eclipseCase() && eclipseCase()->activeFormationNames() )
if ( activeFormationNames() )
{
auto formationGrp = uiOrdering.addNewGroup( "Formation Selection" );
if ( !m_enableFormationFilter ) formationGrp->setCollapsedByDefault();
@@ -260,9 +261,45 @@ void RimStatisticsContourMap::setEclipseCase( RimEclipseCase* eCase )
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimEclipseCaseEnsemble* RimStatisticsContourMap::ensemble() const
QString RimStatisticsContourMap::ensembleName() const
{
return firstAncestorOrThisOfType<RimEclipseCaseEnsemble>();
if ( auto* ens = firstAncestorOrThisOfType<RimReservoirGridEnsembleBase>() ) return ens->ensembleName();
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFormationNames* RimStatisticsContourMap::activeFormationNames() const
{
if ( auto* gridCase = eclipseCase() )
{
if ( auto* formationNames = gridCase->activeFormationNames() ) return formationNames;
}
if ( auto* ensemble = firstAncestorOrThisOfType<RimReservoirGridEnsembleBase>() )
{
return ensemble->activeFormationNames();
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimEclipseCase*> RimStatisticsContourMap::ensembleCases() const
{
if ( auto* ens = firstAncestorOrThisOfType<RimReservoirGridEnsembleBase>() ) return ens->sourceCases();
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RimEclipseCase*> RimStatisticsContourMap::ensembleCasesInViews() const
{
if ( auto* ens = firstAncestorOrThisOfType<RimReservoirGridEnsembleBase>() ) return ens->casesInViews();
return {};
}
//--------------------------------------------------------------------------------------------------
@@ -321,7 +358,7 @@ void RimStatisticsContourMap::switchToSelectedSourceCase()
{
newCase->ensureReservoirCaseIsOpen();
if ( m_openEclipseCase && !ensemble()->casesInViews().contains( m_openEclipseCase ) )
if ( m_openEclipseCase && !ensembleCasesInViews().contains( m_openEclipseCase ) )
{
m_openEclipseCase->closeReservoirCase();
}
@@ -353,7 +390,7 @@ QList<caf::PdmOptionItemInfo> RimStatisticsContourMap::calculateValueOptions( co
}
else if ( &m_primaryCase == fieldNeedingOptions )
{
for ( auto eCase : ensemble()->cases() )
for ( auto eCase : ensembleCases() )
{
options.push_back( caf::PdmOptionItemInfo( eCase->caseUserDescription(), eCase, false, eCase->uiIconProvider() ) );
}
@@ -361,16 +398,13 @@ QList<caf::PdmOptionItemInfo> RimStatisticsContourMap::calculateValueOptions( co
}
else if ( &m_selectedFormations == fieldNeedingOptions )
{
if ( auto eCase = eclipseCase() )
if ( auto formations = activeFormationNames() )
{
if ( auto formations = eCase->activeFormationNames() )
if ( formations->formationNamesData() )
{
if ( formations->formationNamesData() )
for ( auto& f : formations->formationNamesData()->formationNames() )
{
for ( auto& f : formations->formationNamesData()->formationNames() )
{
options.push_back( caf::PdmOptionItemInfo( f, f, false ) );
}
options.push_back( caf::PdmOptionItemInfo( f, f, false ) );
}
}
}
@@ -418,8 +452,7 @@ void RimStatisticsContourMap::defineEditorAttribute( const caf::PdmFieldHandle*
//--------------------------------------------------------------------------------------------------
void RimStatisticsContourMap::initAfterRead()
{
auto ensemble = firstAncestorOrThisOfType<RimEclipseCaseEnsemble>();
if ( !ensemble ) return;
if ( ensembleCases().empty() ) return;
switchToSelectedSourceCase();
@@ -498,10 +531,8 @@ void RimStatisticsContourMap::computeStatistics()
if ( m_computeStatisticsButton.isReadOnly() ) return;
RiaLogging::info( "Computing statistics" );
auto ensemble = firstAncestorOrThisOfType<RimEclipseCaseEnsemble>();
if ( !ensemble ) return;
if ( ensemble->cases().empty() ) return;
auto cases = ensembleCases();
if ( cases.empty() ) return;
if ( eclipseCase() == nullptr ) return;
RigFloodingSettings floodSettings( m_oilFloodingType(), m_userDefinedFloodingOil(), m_gasFloodingType(), m_userDefinedFloodingGas() );
@@ -518,7 +549,7 @@ void RimStatisticsContourMap::computeStatistics()
auto contourMapGrid = std::make_unique<RigContourMapGrid>( gridBoundingBox, sampleSpacing );
const size_t nCases = ensemble->cases().size();
const size_t nCases = cases.size();
std::map<size_t, std::vector<std::vector<double>>> timestep_results;
@@ -526,12 +557,35 @@ void RimStatisticsContourMap::computeStatistics()
auto readerSettings = RiaPreferencesGrid::gridOnlyReaderSettings();
readerSettings.onlyLoadActiveCells = true;
auto casesInViews = ensemble->casesInViews();
auto casesInViews = ensembleCasesInViews();
auto oldReaderType = RiaPreferencesGrid::current()->gridModelReaderOverride();
RiaPreferencesGrid::current()->setGridModelReaderOverride( RiaDefines::GridModelReader::OPM_COMMON );
// For shared grids (RimReservoirGridEnsemble in shared mode), the grid geometry is identical
// across all cases, so the expensive grid mapping only needs to be computed once.
std::unique_ptr<RigEclipseContourMapProjection> sharedProjection;
if ( auto* gridEnsemble = firstAncestorOrThisOfType<RimReservoirGridEnsembleBase>() )
{
if ( ( gridEnsemble->gridMode() == RimReservoirGridEnsembleBase::GridModeType::SHARED_GRID ) &&
eclipseCase()->ensureReservoirCaseIsOpen() )
{
std::set<int> sharedKLayers;
auto formationNames = selectedFormations();
if ( !formationNames.empty() )
{
if ( auto names = activeFormationNames() )
if ( auto fData = names->formationNamesData() ) sharedKLayers = fData->findKLayers( formationNames );
}
auto* primaryCaseData = eclipseCase()->eclipseCaseData();
auto* primaryResultData = primaryCaseData->results( RiaDefines::PorosityModelType::MATRIX_MODEL );
sharedProjection = std::make_unique<RigEclipseContourMapProjection>( *contourMapGrid, *primaryCaseData, *primaryResultData );
sharedProjection->generateGridMapping( resultAggregation, {}, sharedKLayers, selectedPolygons() );
}
}
int i = 1;
for ( RimEclipseCase* eCase : ensemble->cases() )
for ( RimEclipseCase* eCase : cases )
{
auto task = progInfo.task( QString( "Processing Case %1 of %2" ).arg( i++ ).arg( nCases ) );
@@ -545,59 +599,99 @@ void RimStatisticsContourMap::computeStatistics()
auto eclipseCaseData = eCase->eclipseCaseData();
auto resultData = eclipseCaseData->results( RiaDefines::PorosityModelType::MATRIX_MODEL );
RigEclipseContourMapProjection contourMapProjection( *contourMapGrid, *eclipseCaseData, *resultData );
std::set<int> usedKLayers;
auto formationNames = selectedFormations();
bool formationNamesOk = true;
if ( !formationNames.empty() )
if ( sharedProjection )
{
if ( auto names = eCase->activeFormationNames() )
// Shared grid mode: grid mapping was already computed from the primary case.
// Only extract results from the per-case result data.
if ( m_resultDefinition()->hasDynamicResult() )
{
if ( auto fData = names->formationNamesData() )
for ( auto [localTs, globalTs] : mapLocalToGlobalTimeSteps( eCase->timeStepDates() ) )
{
usedKLayers = fData->findKLayers( formationNames );
auto result = RigEclipseContourMapProjection::generateResults( *sharedProjection,
*contourMapGrid,
*resultData,
m_resultDefinition()->eclipseResultAddress(),
resultAggregation,
localTs,
floodSettings )
.second;
timestep_results[globalTs].push_back( result );
}
}
else
{
auto result = RigEclipseContourMapProjection::generateResults( *sharedProjection,
*contourMapGrid,
*resultData,
m_resultDefinition()->eclipseResultAddress(),
resultAggregation,
0,
floodSettings )
.second;
timestep_results[0].push_back( result );
}
}
else
{
// Individual grids: compute grid mapping per case.
RigEclipseContourMapProjection contourMapProjection( *contourMapGrid, *eclipseCaseData, *resultData );
std::set<int> usedKLayers;
auto selectedFormations = this->selectedFormations();
bool formationNamesOk = true;
if ( !selectedFormations.empty() )
{
auto formationNames = eCase->activeFormationNames();
if ( !formationNames ) formationNames = activeFormationNames();
if ( formationNames )
{
if ( auto fData = formationNames->formationNamesData() )
{
usedKLayers = fData->findKLayers( selectedFormations );
}
else
{
formationNamesOk = false;
}
}
else
{
formationNamesOk = false;
}
}
else
if ( formationNamesOk )
{
formationNamesOk = false;
}
}
contourMapProjection.generateGridMapping( resultAggregation, {}, usedKLayers, selectedPolygons() );
if ( formationNamesOk )
{
contourMapProjection.generateGridMapping( resultAggregation, {}, usedKLayers, selectedPolygons() );
if ( m_resultDefinition()->hasDynamicResult() )
{
std::vector<std::pair<int, int>> timeSteps = mapLocalToGlobalTimeSteps( eCase->timeStepDates() );
for ( auto [localTs, globalTs] : timeSteps )
if ( m_resultDefinition()->hasDynamicResult() )
{
for ( auto [localTs, globalTs] : mapLocalToGlobalTimeSteps( eCase->timeStepDates() ) )
{
std::vector<double> result = contourMapProjection.generateResults( m_resultDefinition()->eclipseResultAddress(),
resultAggregation,
localTs,
floodSettings );
timestep_results[globalTs].push_back( result );
}
}
else
{
std::vector<double> result = contourMapProjection.generateResults( m_resultDefinition()->eclipseResultAddress(),
resultAggregation,
localTs,
0,
floodSettings );
timestep_results[globalTs].push_back( result );
timestep_results[0].push_back( result );
}
}
else
{
std::vector<double> result =
contourMapProjection.generateResults( m_resultDefinition()->eclipseResultAddress(), resultAggregation, 0, floodSettings );
timestep_results[0].push_back( result );
RiaLogging::warning(
QString( "Formation names are missing for case %1, skipping case." ).arg( eCase->caseUserDescription() ) );
}
}
else
{
RiaLogging::warning( QString( "Formation names are missing for case %1, skipping case." ).arg( eCase->caseUserDescription() ) );
}
}
eCase->setReaderSettings( oldSettings );
@@ -37,6 +37,8 @@
class RimEclipseCase;
class RimEclipseResultDefinition;
class RimEclipseCaseEnsemble;
class RimFormationNames;
class RimReservoirGridEnsemble;
class RimEclipseContourMapView;
class RimStatisticsContourMapView;
class RimPolygon;
@@ -65,7 +67,7 @@ public:
void setEclipseCase( RimEclipseCase* eclipseCase );
RimEclipseCase* eclipseCase() const;
RimEclipseCaseEnsemble* ensemble() const;
QString ensembleName() const;
RigContourMapGrid* contourMapGrid() const;
std::vector<double> result( size_t timeStep, StatisticsType statisticsType ) const;
@@ -101,6 +103,10 @@ private:
void computeStatistics();
void doStatisticsCalculation( std::map<size_t, std::vector<std::vector<double>>>& timestep_results );
RimFormationNames* activeFormationNames() const;
std::vector<RimEclipseCase*> ensembleCases() const;
std::set<RimEclipseCase*> ensembleCasesInViews() const;
std::vector<std::pair<int, int>> mapLocalToGlobalTimeSteps( std::vector<QDateTime> localDates ) const;
caf::PdmField<double> m_boundingBoxExpPercent;
@@ -83,9 +83,10 @@ QString RimStatisticsContourMapView::createAutoName() const
QStringList generatedAutoTags;
if ( nameConfig()->addCaseName() && m_statisticsContourMap->ensemble() )
if ( nameConfig()->addCaseName() )
{
generatedAutoTags.push_back( m_statisticsContourMap->ensemble()->name() );
auto ensName = m_statisticsContourMap->ensembleName();
if ( !ensName.isEmpty() ) generatedAutoTags.push_back( ensName );
}
if ( nameConfig()->addAggregationType() )
@@ -69,6 +69,7 @@
#include "RimProject.h"
#include "RimReloadCaseTools.h"
#include "RimReservoirCellResultsStorage.h"
#include "RimReservoirGridEnsembleBase.h"
#include "RimResultNameAlias.h"
#include "RimStimPlanColors.h"
#include "RimWellLogPlotCollection.h"
@@ -543,6 +544,26 @@ void RimEclipseCase::childFieldChangedByUi( const caf::PdmFieldHandle* changedCh
}
}
//--------------------------------------------------------------------------------------------------
/// Returns the formation names data for the case, falling back to the parent ensemble's
/// shared formation names if the case has none of its own.
//--------------------------------------------------------------------------------------------------
const RigFormationNames* RimEclipseCase::effectiveFormationNames() const
{
auto resolve = [&]( RimFormationNames* rim ) -> const RigFormationNames* { return rim ? rim->formationNamesData() : nullptr; };
if ( auto* formationNames = resolve( activeFormationNames() ) ) return formationNames;
if ( auto* coll = const_cast<RimEclipseCase*>( this )->parentCaseCollection() )
{
if ( auto* ensembleBase = coll->parentGridEnsembleBase() )
{
return resolve( ensembleBase->activeFormationNames() );
}
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -551,14 +572,8 @@ void RimEclipseCase::updateFormationNamesData()
RigEclipseCaseData* rigEclipseCase = eclipseCaseData();
if ( rigEclipseCase )
{
if ( activeFormationNames() )
{
rigEclipseCase->setActiveFormationNames( activeFormationNames()->formationNamesData() );
}
else
{
rigEclipseCase->setActiveFormationNames( nullptr );
}
auto* formationNames = effectiveFormationNames();
rigEclipseCase->setActiveFormationNames( formationNames );
// Update plots based on formations
RimMainPlotCollection::current()->updatePlotsWithFormations();
@@ -570,7 +585,7 @@ void RimEclipseCase::updateFormationNamesData()
if ( eclView && eclView->isUsingFormationNames() )
{
if ( !activeFormationNames() )
if ( !formationNames )
{
if ( eclView->cellResult()->resultType() == RiaDefines::ResultCatType::FORMATION_NAMES )
{
@@ -730,14 +745,8 @@ void RimEclipseCase::computeCachedData()
{
auto task = pInf.task( "Calculating Formation Names Result", 2 );
if ( activeFormationNames() )
{
rigEclipseCase->setActiveFormationNames( activeFormationNames()->formationNamesData() );
}
else
{
rigEclipseCase->setActiveFormationNames( nullptr );
}
rigEclipseCase->setActiveFormationNames( effectiveFormationNames() );
}
}
}
@@ -747,7 +756,9 @@ void RimEclipseCase::computeCachedData()
//--------------------------------------------------------------------------------------------------
RimCaseCollection* RimEclipseCase::parentCaseCollection()
{
return dynamic_cast<RimCaseCollection*>( parentField()->ownerObject() );
auto* field = parentField();
if ( !field ) return nullptr;
return dynamic_cast<RimCaseCollection*>( field->ownerObject() );
}
//--------------------------------------------------------------------------------------------------
@@ -43,6 +43,7 @@ class QString;
class RimWellTargetMapping;
class RigCaseCellResultsData;
class RigEclipseCaseData;
class RigFormationNames;
class RigGridBase;
class RigMainGrid;
class RigVirtualPerforationTransmissibilities;
@@ -141,6 +142,8 @@ public:
void addResultAlias( const QString& resultName, const QString& aliasName );
void clearResultAliases();
void updateFormationNamesData() override;
protected:
void initAfterRead() override;
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
@@ -149,7 +152,6 @@ protected:
void resultAliasUiOrdering( caf::PdmUiOrdering& uiOrdering );
void updateFormationNamesData() override;
void syncResultAliases();
// Internal methods
@@ -166,6 +168,8 @@ private:
void buildResultChildNodes();
const RigFormationNames* effectiveFormationNames() const;
protected:
caf::PdmField<bool> m_flipXAxis;
caf::PdmField<bool> m_flipYAxis;
@@ -70,6 +70,39 @@ RimEclipseCaseEnsemble::~RimEclipseCaseEnsemble()
m_viewCollection = nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimEclipseCase* RimEclipseCaseEnsemble::mainCase()
{
auto c = cases();
return c.empty() ? nullptr : c.front();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimEclipseCase*> RimEclipseCaseEnsemble::sourceCases() const
{
return cases();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimReservoirGridEnsembleBase::GridModeType RimEclipseCaseEnsemble::gridMode() const
{
return GridModeType::INDIVIDUAL_GRIDS;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimEclipseCaseEnsemble::ensembleName() const
{
return RimNamedObject::name();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -19,6 +19,7 @@
#pragma once
#include "RimNamedObject.h"
#include "RimReservoirGridEnsembleBase.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmChildField.h"
@@ -39,7 +40,7 @@ class RimStatisticsContourMap;
//
//
//==================================================================================================
class RimEclipseCaseEnsemble : public RimNamedObject
class RimEclipseCaseEnsemble : public RimNamedObject, public RimReservoirGridEnsembleBase
{
CAF_PDM_HEADER_INIT;
@@ -47,6 +48,11 @@ public:
RimEclipseCaseEnsemble();
~RimEclipseCaseEnsemble() override;
RimEclipseCase* mainCase() override;
std::vector<RimEclipseCase*> sourceCases() const override;
GridModeType gridMode() const override;
QString ensembleName() const override;
void addCase( RimEclipseCase* reservoir );
void removeCase( RimEclipseCase* reservoir );
bool contains( RimEclipseCase* reservoir ) const;
@@ -54,7 +60,7 @@ public:
RimEclipseCase* findByFileName( const QString& gridFileName ) const;
std::vector<RimEclipseCase*> cases() const;
std::set<RimEclipseCase*> casesInViews() const;
std::set<RimEclipseCase*> casesInViews() const override;
void addView( RimEclipseView* view );
RimEclipseView* addViewForCase( RimEclipseCase* eclipseCase );
@@ -251,6 +251,22 @@ void RimIdenticalGridCaseGroup::loadMainCaseAndActiveCellInfo()
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimReservoirGridEnsembleBase::GridModeType RimIdenticalGridCaseGroup::gridMode() const
{
return GridModeType::SHARED_GRID;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimIdenticalGridCaseGroup::ensembleName() const
{
return name.v();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -71,6 +71,9 @@ public:
RigActiveCellInfo* unionOfActiveCells( RiaDefines::PorosityModelType porosityType ) override;
void computeUnionOfActiveCells() override;
GridModeType gridMode() const override;
QString ensembleName() const override;
static bool isStatisticsCaseCollection( RimCaseCollection* rimCaseCollection );
protected:
@@ -31,6 +31,8 @@
#include "ContourMap/RimStatisticsContourMap.h"
#include "ContourMap/RimStatisticsContourMapView.h"
#include "EnsembleFileSet/RimEnsembleFileSet.h"
#include "Formations/RimFormationNames.h"
#include "Formations/RimFormationNamesCollection.h"
#include "RimCaseCollection.h"
#include "RimEclipseCase.h"
#include "RimEclipseCellColors.h"
@@ -38,6 +40,7 @@
#include "RimEclipseStatisticsCase.h"
#include "RimEclipseView.h"
#include "RimEclipseViewCollection.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimWellTargetMapping.h"
@@ -53,12 +56,11 @@ CAF_PDM_SOURCE_INIT( RimReservoirGridEnsemble, "RimReservoirGridEnsemble" );
namespace caf
{
template <>
void caf::AppEnum<RimReservoirGridEnsemble::GridModeType>::setUp()
void caf::AppEnum<RimReservoirGridEnsembleBase::GridModeType>::setUp()
{
addItem( RimReservoirGridEnsemble::GridModeType::AUTO_DETECT, "AutoDetect", "Auto Detect" );
addItem( RimReservoirGridEnsemble::GridModeType::SHARED_GRID, "SharedGrid", "Shared Grid" );
addItem( RimReservoirGridEnsemble::GridModeType::INDIVIDUAL_GRIDS, "IndividualGrids", "Individual Grids" );
setDefault( RimReservoirGridEnsemble::GridModeType::AUTO_DETECT );
addItem( RimReservoirGridEnsembleBase::GridModeType::SHARED_GRID, "SharedGrid", "Shared Grid" );
addItem( RimReservoirGridEnsembleBase::GridModeType::INDIVIDUAL_GRIDS, "IndividualGrids", "Individual Grids" );
setDefault( RimReservoirGridEnsembleBase::GridModeType::SHARED_GRID );
}
} // namespace caf
@@ -82,7 +84,12 @@ RimReservoirGridEnsemble::RimReservoirGridEnsemble()
CAF_PDM_InitFieldNoDefault( &m_ensembleFileSet, "EnsembleFileSet", "Ensemble File Set" );
m_ensembleFileSet.uiCapability()->setUiReadOnly( true );
CAF_PDM_InitField( &m_gridMode, "GridMode", GridModeType::AUTO_DETECT, "Grid Mode" );
CAF_PDM_InitField( &m_autoDetectGridType, "AutoDetectGridType", true, "Auto Detect Grid Type" );
CAF_PDM_InitField( &m_gridMode, "GridMode", GridModeType::SHARED_GRID, "Grid Mode" );
CAF_PDM_InitField( &m_detectedGridMode, "DetectedGridMode", GridModeType::SHARED_GRID, "Detected Grid Mode" );
m_detectedGridMode.uiCapability()->setUiReadOnly( true );
CAF_PDM_InitFieldNoDefault( &m_activeFormationNames, "DefaultFormationNames", "Formation Names" );
CAF_PDM_InitFieldNoDefault( &m_caseCollection, "CaseCollection", "Source Cases" );
m_caseCollection = new RimCaseCollection;
@@ -263,7 +270,7 @@ RimEclipseCase* RimReservoirGridEnsemble::findByFileName( const QString& gridFil
//--------------------------------------------------------------------------------------------------
bool RimReservoirGridEnsemble::hasSharedGrid() const
{
return m_gridMode.v() == GridModeType::SHARED_GRID;
return gridMode() == GridModeType::SHARED_GRID;
}
//--------------------------------------------------------------------------------------------------
@@ -277,17 +284,18 @@ bool RimReservoirGridEnsemble::isGridDataLoaded() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimReservoirGridEnsemble::GridModeType RimReservoirGridEnsemble::effectiveGridMode() const
RimReservoirGridEnsembleBase::GridModeType RimReservoirGridEnsemble::gridMode() const
{
if ( m_autoDetectGridType ) return m_detectedGridMode.v();
return m_gridMode.v();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimReservoirGridEnsemble::setGridMode( GridModeType mode )
QString RimReservoirGridEnsemble::ensembleName() const
{
m_gridMode = mode;
return RimNamedObject::name();
}
//--------------------------------------------------------------------------------------------------
@@ -586,6 +594,7 @@ void RimReservoirGridEnsemble::appendMenuItems( caf::CmdFeatureMenuBuilder& menu
{
menuBuilder << "RicNewViewForGridEnsembleFeature";
menuBuilder << "RicNewStatisticsContourMapFeature";
menuBuilder << "RicNewWellTargetMappingFeature";
if ( hasSharedGrid() )
{
@@ -593,6 +602,39 @@ void RimReservoirGridEnsemble::appendMenuItems( caf::CmdFeatureMenuBuilder& menu
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFormationNames* RimReservoirGridEnsemble::activeFormationNames() const
{
if ( !hasSharedGrid() ) return nullptr;
return m_activeFormationNames();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimReservoirGridEnsemble::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions )
{
QList<caf::PdmOptionItemInfo> options;
if ( fieldNeedingOptions == &m_activeFormationNames )
{
RimProject* proj = RimProject::current();
if ( proj && proj->activeOilField() && proj->activeOilField()->formationNamesCollection() )
{
for ( RimFormationNames* fnames : proj->activeOilField()->formationNamesCollection()->formationNamesList() )
{
options.push_back( caf::PdmOptionItemInfo( fnames->shortName(), fnames, false, fnames->uiCapability()->uiIconProvider() ) );
}
}
options.push_front( caf::PdmOptionItemInfo( "None", nullptr ) );
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -601,11 +643,44 @@ void RimReservoirGridEnsemble::defineUiOrdering( QString uiConfigName, caf::PdmU
uiOrdering.add( nameField() );
uiOrdering.add( &m_groupId );
uiOrdering.add( &m_ensembleFileSet );
uiOrdering.add( &m_gridMode );
uiOrdering.add( &m_autoDetectGridType );
if ( m_autoDetectGridType )
{
uiOrdering.add( &m_detectedGridMode );
}
else
{
uiOrdering.add( &m_gridMode );
}
if ( hasSharedGrid() )
{
uiOrdering.add( &m_activeFormationNames );
}
uiOrdering.skipRemainingFields();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimReservoirGridEnsemble::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
{
if ( changedField == &m_autoDetectGridType || changedField == &m_gridMode )
{
updateStatisticsVisibility();
updateConnectedEditors();
}
else if ( changedField == &m_activeFormationNames )
{
for ( auto rimCase : cases() )
{
rimCase->updateFormationNamesData();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -648,6 +723,8 @@ void RimReservoirGridEnsemble::initAfterRead()
{
m_viewCollection->setEclipseCaseProvider( [this]() { return this->cases(); } );
}
updateStatisticsVisibility();
}
//--------------------------------------------------------------------------------------------------
@@ -696,6 +773,15 @@ void RimReservoirGridEnsemble::clearStatisticsResults()
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimReservoirGridEnsemble::updateStatisticsVisibility()
{
bool hidden = !hasSharedGrid();
m_statisticsCaseCollection->uiCapability()->setUiTreeHidden( hidden );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -762,16 +848,14 @@ void RimReservoirGridEnsemble::loadGridDataFromFiles()
if ( allCases.empty() ) return;
// Determine effective grid mode
GridModeType effectiveMode = m_gridMode.v();
if ( effectiveMode == GridModeType::AUTO_DETECT )
if ( m_autoDetectGridType )
{
// Run dimension detection
bool identical = detectGridDimensionEquality();
effectiveMode = identical ? GridModeType::SHARED_GRID : GridModeType::INDIVIDUAL_GRIDS;
m_gridMode = effectiveMode; // Update to detected mode
bool identical = detectGridDimensionEquality();
m_detectedGridMode = identical ? GridModeType::SHARED_GRID : GridModeType::INDIVIDUAL_GRIDS;
}
GridModeType effectiveMode = gridMode();
// Load grids based on effective mode
if ( effectiveMode == GridModeType::SHARED_GRID )
{
@@ -783,6 +867,7 @@ void RimReservoirGridEnsemble::loadGridDataFromFiles()
// loadGridsInIndividualMode();
}
updateStatisticsVisibility();
updateConnectedEditors();
}
@@ -40,6 +40,7 @@ class RimEclipseStatisticsCase;
class RimEclipseView;
class RimEclipseViewCollection;
class RimEnsembleFileSet;
class RimFormationNames;
class RimStatisticsContourMap;
class RimWellTargetMapping;
@@ -57,13 +58,6 @@ class RimReservoirGridEnsemble : public RimNamedObject, public RimReservoirGridE
CAF_PDM_HEADER_INIT;
public:
enum class GridModeType
{
AUTO_DETECT,
SHARED_GRID,
INDIVIDUAL_GRIDS
};
RimReservoirGridEnsemble();
// Ensemble file set connection
@@ -90,16 +84,19 @@ public:
// Deferred loading control
void loadGridDataFromFiles();
bool isGridDataLoaded() const;
void setGridMode( GridModeType mode );
// Helper methods
bool hasSharedGrid() const;
GridModeType effectiveGridMode() const;
GridModeType gridMode() const override;
QString ensembleName() const override;
// Active cells
RigActiveCellInfo* unionOfActiveCells( RiaDefines::PorosityModelType porosityType ) override;
void computeUnionOfActiveCells() override;
// Formation names
RimFormationNames* activeFormationNames() const override;
// Statistics
RimCaseCollection* statisticsCaseCollection() const override;
RimEclipseStatisticsCase* createAndAppendStatisticsCase() override;
@@ -108,7 +105,7 @@ public:
void addView( RimEclipseView* view );
RimEclipseView* addViewForCase( RimEclipseCase* eclipseCase );
std::vector<RimEclipseView*> allViews() const;
std::set<RimEclipseCase*> casesInViews() const;
std::set<RimEclipseCase*> casesInViews() const override;
// Well target mapping
void addWellTargetMapping( RimWellTargetMapping* wellTargetMapping );
@@ -124,13 +121,17 @@ public:
protected:
void appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const override;
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
void initAfterRead() override;
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override;
private:
void onFileSetChanged( const caf::SignalEmitter* emitter );
void clearActiveCellUnions();
void clearStatisticsResults();
void updateMainGridAndActiveCellsForStatisticsCases();
void updateStatisticsVisibility();
void createCaseObjectsFromEnsembleFileSet();
bool detectGridDimensionEquality();
@@ -141,6 +142,9 @@ private:
// File set reference
caf::PdmPtrField<RimEnsembleFileSet*> m_ensembleFileSet;
// Formation names (shared across all realizations, only valid in shared grid mode)
caf::PdmPtrField<RimFormationNames*> m_activeFormationNames;
// Ensemble id
caf::PdmField<int> m_groupId;
@@ -149,7 +153,9 @@ private:
caf::PdmChildField<RimCaseCollection*> m_statisticsCaseCollection;
// Grid mode
caf::PdmField<bool> m_autoDetectGridType;
caf::PdmField<caf::AppEnum<GridModeType>> m_gridMode;
caf::PdmField<caf::AppEnum<GridModeType>> m_detectedGridMode;
// Views and mappings
caf::PdmChildField<RimEclipseViewCollection*> m_viewCollection;
@@ -21,6 +21,53 @@
#include "RimCaseCollection.h"
#include "RimEclipseStatisticsCase.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigMainGrid* RimReservoirGridEnsembleBase::mainGrid()
{
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigActiveCellInfo* RimReservoirGridEnsembleBase::unionOfActiveCells( RiaDefines::PorosityModelType porosityType )
{
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimReservoirGridEnsembleBase::computeUnionOfActiveCells()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimCaseCollection* RimReservoirGridEnsembleBase::statisticsCaseCollection() const
{
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RimEclipseCase*> RimReservoirGridEnsembleBase::casesInViews() const
{
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFormationNames* RimReservoirGridEnsembleBase::activeFormationNames() const
{
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -20,6 +20,9 @@
#include "RiaPorosityModel.h"
#include <QString>
#include <set>
#include <vector>
class RigActiveCellInfo;
@@ -27,18 +30,29 @@ class RigMainGrid;
class RimCaseCollection;
class RimEclipseCase;
class RimEclipseStatisticsCase;
class RimFormationNames;
class RimReservoirGridEnsembleBase
{
public:
enum class GridModeType
{
SHARED_GRID,
INDIVIDUAL_GRIDS
};
virtual ~RimReservoirGridEnsembleBase() = default;
virtual RigMainGrid* mainGrid() = 0;
virtual RimEclipseCase* mainCase() = 0;
virtual std::vector<RimEclipseCase*> sourceCases() const = 0;
virtual RigActiveCellInfo* unionOfActiveCells( RiaDefines::PorosityModelType porosityType ) = 0;
virtual void computeUnionOfActiveCells() = 0;
virtual RimCaseCollection* statisticsCaseCollection() const = 0;
virtual QString ensembleName() const = 0;
virtual GridModeType gridMode() const = 0;
virtual std::vector<RimEclipseCase*> sourceCases() const = 0;
virtual RimEclipseCase* mainCase() = 0;
virtual RigMainGrid* mainGrid();
virtual RigActiveCellInfo* unionOfActiveCells( RiaDefines::PorosityModelType porosityType );
virtual void computeUnionOfActiveCells();
virtual std::set<RimEclipseCase*> casesInViews() const;
virtual RimCaseCollection* statisticsCaseCollection() const;
virtual RimFormationNames* activeFormationNames() const;
virtual RimEclipseStatisticsCase* createAndAppendStatisticsCase();
};
+1
View File
@@ -62,4 +62,5 @@ When working with Python code:
Follow these conventions:
- Start with issue number: `#12773 Python: Add API for creating valve templates`
- Use standard git commit message format
- Only use line breaks between paragraphs in the description
- Keep first line concise and descriptive