Performance improvements ensemble curves

* Do not create ensemble in initAfterRead
* Check if filter is active before update
* Do not recompute statistics on every loadData
* Removes unnecessary resampling
* MSVC: Add support for dynamic deoptimalization
* Make sure RFT plots are initialized based on curves in project file
* Make sure the progress dialog is always on top
* Add more progress info when loading project file
* Make sure names in RFT plots are updated
This commit is contained in:
Magne Sjaastad authored and GitHub committed 2025-05-28 15:10:43 +02:00
1 parent 6da41a4c5a
commit 118ecf941a
10 files changed
+78 -14

No files matched your search

@@ -469,6 +469,9 @@ bool RiaApplication::loadProject( const QString& projectFileName, ProjectLoadAct
{
// First Close the current project
caf::ProgressInfo progress( 7, "Loading Project File" );
progress.setProgressDescription( "Reading Project Structure from File" );
closeProject();
onProjectBeingOpened();
@@ -541,6 +544,9 @@ bool RiaApplication::loadProject( const QString& projectFileName, ProjectLoadAct
m_preferences->writePreferencesToApplicationStore();
}
progress.incrementProgress();
progress.setProgressDescription( "Loading Grid Data" );
for ( size_t oilFieldIdx = 0; oilFieldIdx < m_project->oilFields().size(); oilFieldIdx++ )
{
RimOilField* oilField = m_project->oilFields[oilFieldIdx];
@@ -598,6 +604,9 @@ bool RiaApplication::loadProject( const QString& projectFileName, ProjectLoadAct
oilField->polygonCollection()->loadData();
}
progress.incrementProgress();
progress.setProgressDescription( "Loading 2D Plot Data" );
{
RimMainPlotCollection* mainPlotColl = RimMainPlotCollection::current();
mainPlotColl->ensureDefaultFlowPlotsAreCreated();
@@ -650,6 +659,9 @@ bool RiaApplication::loadProject( const QString& projectFileName, ProjectLoadAct
oilField->surfaceCollection()->loadData();
}
progress.incrementProgress();
progress.setProgressDescription( "Calculation Grid Statistics" );
// If load action is specified to recalculate statistics, do it now.
// Apparently this needs to be done before the views are loaded, lest the number of time steps for statistics will
// be clamped
@@ -666,6 +678,9 @@ bool RiaApplication::loadProject( const QString& projectFileName, ProjectLoadAct
}
}
progress.incrementProgress();
progress.setProgressDescription( "Create 3D Views" );
// Now load the ReservoirViews for the cases
// Add all "native" cases in the project
std::vector<RimCase*> casesToLoad = m_project->allGridCases();
@@ -773,6 +788,9 @@ bool RiaApplication::loadProject( const QString& projectFileName, ProjectLoadAct
}
}
progress.incrementProgress();
progress.setProgressDescription( "Load Summary Data" );
// Init summary case groups
for ( RimOilField* oilField : m_project->oilFields )
{
@@ -803,6 +821,9 @@ bool RiaApplication::loadProject( const QString& projectFileName, ProjectLoadAct
// Default behavior for scripts is to use current active view for data read/write
onProjectOpened();
progress.incrementProgress();
progress.setProgressDescription( "Performing Grid Calculations" );
// Recalculate the results from grid property calculations.
// Has to be done late since the results are filtered by view cell visibility
for ( auto gridCalculation : m_project->gridCalculationCollection()->sortedGridCalculations() )
+12
View File
@@ -214,6 +214,18 @@ list(APPEND ALL_SOURCE_FILES ${CPP_SOURCES} ${MOC_SOURCE_FILES}
add_library(${PROJECT_NAME} OBJECT ${ALL_SOURCE_FILES})
option(RESINSIGHT_ENABLE_DYNAMIC_DEOPTIMALIZATION
"Ensable Dynamic Deoptimalization" OFF
)
mark_as_advanced(FORCE RESINSIGHT_ENABLE_DYNAMIC_DEOPTIMALIZATION)
if(MSVC AND RESINSIGHT_ENABLE_DYNAMIC_DEOPTIMALIZATION)
message("Dynamic Deoptimalization is enabled on : ${PROJECT_NAME}")
target_compile_options(${PROJECT_NAME} PRIVATE /dynamicdeopt)
target_link_options(${PROJECT_NAME} PRIVATE /DYNAMICDEOPT)
else()
message("Dynamic Deoptimalization is disabled on : ${PROJECT_NAME}")
endif()
option(RESINSIGHT_ENABLE_PRECOMPILED_HEADERS "Use Precompiled Headers" OFF)
mark_as_advanced(FORCE RESINSIGHT_ENABLE_PRECOMPILED_HEADERS)
if(RESINSIGHT_ENABLE_PRECOMPILED_HEADERS)
@@ -384,7 +384,7 @@ void RimWellRftPlot::updateEditorsFromPreviousSelection()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellRftPlot::updateEditorsFromCurves()
void RimWellRftPlot::setSelectedSourcesFromCurves()
{
std::set<RifDataSourceForRftPlt> selectedSources;
std::set<QDateTime> selectedTimeSteps;
@@ -1218,7 +1218,6 @@ void RimWellRftPlot::onLoadDataAndUpdate()
RimWellLogPlot::onLoadDataAndUpdate();
createEnsembleCurveSets();
updateEditorsFromCurves();
// Update of curve color must happen here when loading data from project file, as the curve color is blended by
// the background color. The background color is taken from the viewer.
@@ -1247,6 +1246,12 @@ void RimWellRftPlot::initAfterRead()
m_wellLogPlot_OBSOLETE = nullptr;
}
// TODO: m_selectedSources and m_selectedTimeSteps are not stored in the project file, so we need to set them here
// to ensure that the plot is initialized with the correct sources and time steps. Refactor m_selectedSources and m_selectedTimeSteps to
// be stored in the project file, and disable storing of curves to the project file. This is a temporary solution to ensure that the
// plot is initialized correctly
setSelectedSourcesFromCurves();
RimWellLogPlot::initAfterRead();
}
@@ -114,7 +114,7 @@ protected:
private:
std::map<QString, QStringList> findWellSources();
void updateEditorsFromPreviousSelection();
void updateEditorsFromCurves();
void setSelectedSourcesFromCurves();
void syncCurvesFromUiSelection();
void assignWellPathToExtractionCurves();
@@ -184,7 +184,6 @@ void RimSummaryFileSetEnsemble::initAfterRead()
RimSummaryEnsemble::initAfterRead();
connectSignals();
createSummaryCasesFromEnsembleFileSet();
}
//--------------------------------------------------------------------------------------------------
@@ -217,7 +217,12 @@ void RimEnsembleCurveFilterCollection::defineEditorAttribute( const caf::PdmFiel
void RimEnsembleCurveFilterCollection::loadDataAndUpdate()
{
for ( auto& filter : m_filters )
filter->loadDataAndUpdate();
{
if ( filter->isActive() )
{
filter->loadDataAndUpdate();
}
}
}
//--------------------------------------------------------------------------------------------------
@@ -364,9 +364,6 @@ void RimEnsembleCurveSet::loadDataAndUpdate( bool updateParentPlot )
{
m_yValuesSummaryAddressUiField = m_yValuesSummaryAddress->address();
// Recreate the statistics case, as the statistics data is cached internally
m_ensembleStatCaseY = std::make_unique<RimEnsembleStatisticsCase>();
m_curveFilters->loadDataAndUpdate();
updateAddressesUiField();
@@ -20,6 +20,7 @@
#include "RiaCurveMerger.h"
#include "RiaHashTools.h"
#include "RiaLogging.h"
#include "RiaTimeHistoryCurveResampler.h"
#include "Summary/RiaSummaryTools.h"
@@ -134,6 +135,13 @@ void RimEnsembleStatisticsCase::calculate( const std::vector<RimSummaryCase*>& s
auto hash = RiaHashTools::hash( summaryCases, inputAddress.toEclipseTextAddress(), includeIncompleteCurves );
if ( hash == m_hash ) return;
bool showDebugTiming = false;
if ( showDebugTiming )
{
QString timingText = "RimEnsembleStatisticsCase::calculate" + QString::fromStdString( inputAddress.toEclipseTextAddress() );
RiaLogging::resetTimer( timingText );
}
m_hash = hash;
clearData();
@@ -149,8 +157,6 @@ void RimEnsembleStatisticsCase::calculate( const std::vector<RimSummaryCase*>& s
// The last time step for the individual realizations in an ensemble is usually identical. Add a small threshold to improve robustness.
const auto timeThreshold = RiaSummaryTools::calculateTimeThreshold( minTime, maxTime );
RiaDefines::DateTimePeriod period = findBestResamplingPeriod( minTime, maxTime );
RiaTimeHistoryCurveMerger curveMerger;
for ( const auto& sumCase : summaryCases )
{
@@ -164,9 +170,7 @@ void RimEnsembleStatisticsCase::calculate( const std::vector<RimSummaryCase*>& s
if ( !includeIncompleteCurves && ( timeSteps.back() < timeThreshold ) ) continue;
const auto [resampledTimeSteps, resampledValues] =
RiaSummaryTools::resampledValuesForPeriod( inputAddress, timeSteps, values, period );
curveMerger.addCurveData( resampledTimeSteps, resampledValues );
curveMerger.addCurveData( timeSteps, values );
}
}
@@ -180,6 +184,11 @@ void RimEnsembleStatisticsCase::calculate( const std::vector<RimSummaryCase*>& s
m_timeSteps = curveMerger.allXValues();
m_p10Data.reserve( m_timeSteps.size() );
m_p50Data.reserve( m_timeSteps.size() );
m_p90Data.reserve( m_timeSteps.size() );
m_meanData.reserve( m_timeSteps.size() );
for ( size_t timeStepIndex = 0; timeStepIndex < m_timeSteps.size(); timeStepIndex++ )
{
std::vector<double> valuesAtTimeStep;
@@ -197,6 +206,11 @@ void RimEnsembleStatisticsCase::calculate( const std::vector<RimSummaryCase*>& s
m_p90Data.push_back( p90 );
m_meanData.push_back( mean );
}
if ( showDebugTiming )
{
RiaLogging::logTimeElapsed( "" );
}
}
//--------------------------------------------------------------------------------------------------
@@ -39,13 +39,16 @@
#include "RimDeltaSummaryEnsemble.h"
#include "RimEclipseResultCase.h"
#include "RimFileSummaryCase.h"
#include "RimMainPlotCollection.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimRftPlotCollection.h"
#include "RimSummaryCase.h"
#include "RimSummaryCurve.h"
#include "RimSummaryEnsemble.h"
#include "RimSummaryMultiPlotCollection.h"
#include "RimSummaryPlot.h"
#include "RimWellRftPlot.h"
#include "cafPdmFieldReorderCapability.h"
#include "cafProgressInfo.h"
@@ -544,6 +547,13 @@ void RimSummaryCaseMainCollection::onCaseNameChanged( const SignalEmitter* emitt
RimSummaryMultiPlotCollection* summaryPlotColl = RiaSummaryTools::summaryMultiPlotCollection();
summaryPlotColl->updateSummaryNameHasChanged();
// Update RFT plots, as they may depend on the summary case ensemble names
auto rftPlotColl = RimMainPlotCollection::current()->rftPlotCollection();
for ( auto plot : rftPlotColl->rftPlots() )
{
plot->loadDataAndUpdate();
}
updateConnectedEditors();
}
@@ -258,7 +258,8 @@ static QProgressDialog* progressDialog()
static QPointer<QProgressDialog> progDialog;
if ( progDialog.isNull() && dynamic_cast<QApplication*>( QCoreApplication::instance() ) )
{
progDialog = new QProgressDialog( nullptr, Qt::WindowTitleHint | Qt::WindowSystemMenuHint );
progDialog =
new QProgressDialog( nullptr, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowStaysOnTopHint );
progDialog->hide();
progDialog->setAutoClose( false );