Enables experimental MSW export to new folder

Adds a feature keyword to enable an experimental MSW export
to a separate folder, facilitating testing of a new data
extraction approach.
This commit is contained in:
Magne Sjaastad committed 2025-11-03 13:40:46 +01:00
1 parent 626b99dabd
commit fd5bdc96d2
9 files changed
+6830 -8

No files matched your search

@@ -92,6 +92,11 @@ RiaPreferencesSystem::RiaPreferencesSystem()
QString(),
"Keywords to enable debug logging, separated by semicolon.\nType 'enable-all' to enable logging for all objects." );
CAF_PDM_InitField( &m_featureKeywords,
"FeatureKeywords",
QString(),
"Keywords to enable experimental features separated by semicolon.\nType 'enable-all' for all." );
CAF_PDM_InitField( &m_maximumNumberOfThreads, "maximumNumberOfThreads", std::make_pair( false, QString( "4" ) ), "Maximum Number of Threads" );
m_maximumNumberOfThreads.uiCapability()->setUiEditorTypeName( caf::PdmUiCheckBoxAndTextEditor::uiEditorTypeName() );
}
@@ -271,6 +276,20 @@ bool RiaPreferencesSystem::isLoggingActivatedForKeyword( const QString& keyword
return keywords.contains( keyword );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiaPreferencesSystem::isFeatureEnabled( const QString& keyword ) const
{
if ( keyword.isEmpty() ) return false;
const QStringList keywords = m_featureKeywords().split( ";", Qt::SkipEmptyParts );
if ( keywords.contains( "enable-all" ) ) return true;
return keywords.contains( keyword );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -307,6 +326,7 @@ void RiaPreferencesSystem::defineUiOrdering( QString uiConfigName, caf::PdmUiOrd
{
caf::PdmUiGroup* group = uiOrdering.addNewGroup( "Developer Settings" );
group->add( &m_keywordsForLogging );
group->add( &m_featureKeywords );
group->add( &m_gtestFilter );
}
@@ -64,6 +64,7 @@ public:
EclipseTextFileReaderMode eclipseTextFileReaderMode() const;
bool isLoggingActivatedForKeyword( const QString& keyword ) const;
bool isFeatureEnabled( const QString& keyword ) const;
protected:
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
@@ -95,6 +96,7 @@ private:
caf::PdmField<EclipseTextFileReaderModeType> m_eclipseReaderMode;
caf::PdmField<QString> m_keywordsForLogging;
caf::PdmField<QString> m_featureKeywords;
caf::PdmField<std::pair<bool, QString>> m_maximumNumberOfThreads;
};
@@ -45,10 +45,14 @@ void RicMswTableDataTools::collectWelsegsData( RigMswTableData& tableData,
{
// Set up WELSEGS header
WelsegsHeader header;
header.wellName = exportInfo.mainBoreBranch()->wellPath()->completionSettings()->wellNameForExport().toStdString();
header.topMD = exportInfo.mainBoreBranch()->startMD();
header.topTVD = exportInfo.mainBoreBranch()->startTVD();
header.volume = exportInfo.topWellBoreVolume();
header.wellName = exportInfo.mainBoreBranch()->wellPath()->completionSettings()->wellNameForExport().toStdString();
header.topMD = exportInfo.mainBoreBranch()->startMD();
header.topTVD = exportInfo.mainBoreBranch()->startTVD();
if ( exportInfo.topWellBoreVolume() != RicMswExportInfo::defaultDoubleValue() )
{
header.volume = exportInfo.topWellBoreVolume();
}
header.lengthAndDepthText = exportInfo.lengthAndDepthText().toStdString();
header.pressureDropText = exportInfo.pressureDropText().toStdString();
@@ -19,6 +19,7 @@
#include "RicWellPathExportMswCompletionsImpl.h"
#include "RiaLogging.h"
#include "RiaPreferencesSystem.h"
#include "RicExportCompletionDataSettingsUi.h"
#include "RicExportFractureCompletionsImpl.h"
@@ -26,9 +27,14 @@
#include "RicMswTableFormatterTools.h"
#include "RicMswValveAccumulators.h"
#include "RicWellPathExportCompletionsFileTools.h"
#include "RicWellPathExportMswTableData.h"
#include "RifTextDataTableFormatter.h"
#include "CompletionsMsw/RigMswDataFormatter.h"
#include "CompletionsMsw/RigMswTableData.h"
#include "CompletionsMsw/RigMswUnifiedData.h"
#include "RigActiveCellInfo.h"
#include "RigEclipseCaseData.h"
#include "RigGridBase.h"
@@ -52,6 +58,7 @@
#include "RimWellPathTieIn.h"
#include "RimWellPathValve.h"
#include <QDir>
#include <QFile>
#include <QFileInfo>
@@ -266,6 +273,13 @@ void RicWellPathExportMswCompletionsImpl::exportWellSegmentsForAllCompletions( c
exportSettings.exportCompletionWelspecAfterMainBore() );
}
}
// Experimental export to separate folder for testing
// Add "NewMswExport" to feature keywords in System Preferences
if ( RiaPreferencesSystem::current()->isFeatureEnabled( "NewMswExport" ) )
{
exportExperimentalMswToSeparateFolder( exportSettings, wellPaths );
}
}
//--------------------------------------------------------------------------------------------------
@@ -664,8 +678,9 @@ void RicWellPathExportMswCompletionsImpl::generateFishbonesMswExportInfo( const
const double startValveTvd = RicMswTableFormatterTools::tvdFromMeasuredDepth( branch->wellPath(), startValveMd );
{
// Add completion for ICD. Insert the segment at the end of the fishbone section. The laterals flows into the ICD segment,
// and the simulator requires increasing MD on laterals. Make sure that the lateral MDs are larger than the ICD segment MDs.
// Add completion for ICD. Insert the segment at the end of the fishbone section. The laterals flows into the ICD
// segment, and the simulator requires increasing MD on laterals. Make sure that the lateral MDs are larger than the ICD
// segment MDs.
auto icdSegment = std::make_unique<RicMswSegment>( "ICD segment", startValveMd, subEndMd, startValveTvd, subEndTvd, subIndex );
for ( auto lateralIndex : lateralIndices )
@@ -1888,3 +1903,170 @@ std::pair<double, double>
}
return std::make_pair( 0.0, 0.0 );
}
//--------------------------------------------------------------------------------------------------
// New data extraction functions
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigMswUnifiedDataWIP RicWellPathExportMswCompletionsImpl::extractUnifiedMswData( RimEclipseCase* eclipseCase,
int timeStep,
const std::vector<RimWellPath*>& wellPaths )
{
RigMswUnifiedDataWIP unifiedData;
for ( RimWellPath* wellPath : wellPaths )
{
auto wellData = RicWellPathExportMswTableData::extractSingleWellMswData( eclipseCase, wellPath, timeStep );
if ( wellData.has_value() )
{
unifiedData.addWellData( std::move( wellData.value() ) );
}
}
return unifiedData;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicWellPathExportMswCompletionsImpl::exportExperimentalMswToSeparateFolder( const RicExportCompletionDataSettingsUi& exportSettings,
const std::vector<RimWellPath*>& wellPaths )
{
QDir folder( exportSettings.folder() );
folder.mkdir( "prototype" );
const auto exportFolder = exportSettings.folder() + "/prototype";
// Use new unified data extraction approach
if ( exportSettings.fileSplit() == RicExportCompletionDataSettingsUi::ExportSplit::UNIFIED_FILE )
{
exportUnifiedMswData( exportSettings, exportFolder, wellPaths );
}
else if ( exportSettings.fileSplit() == RicExportCompletionDataSettingsUi::ExportSplit::SPLIT_ON_WELL )
{
exportSplitMswData( exportSettings, exportFolder, wellPaths );
}
}
//--------------------------------------------------------------------------------------------------
/// Export MSW data to unified files using new data extraction approach
//--------------------------------------------------------------------------------------------------
void RicWellPathExportMswCompletionsImpl::exportUnifiedMswData( const RicExportCompletionDataSettingsUi& exportSettings,
const QString& exportFolder,
const std::vector<RimWellPath*>& wellPaths )
{
// Extract all MSW data using new approach
RigMswUnifiedDataWIP unifiedData = extractUnifiedMswData( exportSettings.caseToApply, exportSettings.timeStep, wellPaths );
if ( unifiedData.isEmpty() )
{
RiaLogging::warning( "No MSW data to export." );
return;
}
auto generateFileName = []( const RicExportCompletionDataSettingsUi& exportSettings, const QString& postFix ) -> QString
{
QFileInfo fi( exportSettings.customFileName() );
if ( !exportSettings.customFileName().isEmpty() )
{
return fi.baseName() + postFix;
}
else
{
return QString( "UnifiedCompletions%1_%2" ).arg( postFix ).arg( exportSettings.caseToApply->caseUserDescription() );
}
};
// Set up file names
QString fileName = generateFileName( exportSettings, "_MSW" );
// Create main grid file
auto mainGridFile =
RicWellPathExportCompletionsFileTools::openFileForExport( exportFolder, fileName, "", exportSettings.exportDataSourceAsComment() );
// Write main grid data
{
QTextStream stream( mainGridFile.get() );
RifTextDataTableFormatter formatter( stream );
formatter.setOptionalComment( exportSettings.exportDataSourceAsComment() );
RigMswDataFormatter::formatMswTables( formatter, unifiedData );
}
// Create LGR file if needed
if ( unifiedData.hasAnyLgrData() )
{
QString lgrFileName = generateFileName( exportSettings, "_LGR_MSW" );
auto lgrFile =
RicWellPathExportCompletionsFileTools::openFileForExport( exportFolder, lgrFileName, "", exportSettings.exportDataSourceAsComment() );
QTextStream stream( lgrFile.get() );
RifTextDataTableFormatter formatter( stream );
formatter.setOptionalComment( exportSettings.exportDataSourceAsComment() );
for ( const auto& tableData : unifiedData.wellDataList() )
{
RigMswDataFormatter::formatCompsegsTable( formatter, tableData, true ); // LGR only
}
}
}
//--------------------------------------------------------------------------------------------------
/// Export MSW data to separate files per well using new data extraction approach
//--------------------------------------------------------------------------------------------------
void RicWellPathExportMswCompletionsImpl::exportSplitMswData( const RicExportCompletionDataSettingsUi& exportSettings,
const QString& exportFolder,
const std::vector<RimWellPath*>& wellPaths )
{
for ( const auto& wellPath : wellPaths )
{
// Extract data for single well
auto wellDataResult =
RicWellPathExportMswTableData::extractSingleWellMswData( exportSettings.caseToApply, wellPath, exportSettings.timeStep );
if ( !wellDataResult.has_value() )
{
continue; // Skip wells with no MSW data
}
auto wellData = wellDataResult.value();
// Set up file names
QString wellFileName =
QString( "%1_UnifiedCompletions_MSW_%2" ).arg( wellPath->name(), exportSettings.caseToApply->caseUserDescription() );
// Create main grid file
auto mainGridFile = RicWellPathExportCompletionsFileTools::openFileForExport( exportFolder,
wellFileName,
"",
exportSettings.exportDataSourceAsComment() );
// Write main grid data
{
QTextStream stream( mainGridFile.get() );
RifTextDataTableFormatter formatter( stream );
formatter.setOptionalComment( exportSettings.exportDataSourceAsComment() );
RigMswDataFormatter::formatMswTables( formatter, wellData );
}
// Create LGR file if needed
if ( wellData.hasLgrData() )
{
auto lgrFile = RicWellPathExportCompletionsFileTools::openFileForExport( exportFolder,
wellFileName + "_LGR",
"",
exportSettings.exportDataSourceAsComment() );
QTextStream stream( lgrFile.get() );
RifTextDataTableFormatter formatter( stream );
formatter.setOptionalComment( exportSettings.exportDataSourceAsComment() );
RigMswDataFormatter::formatCompsegsTable( formatter, wellData, true ); // LGR only
}
}
}
@@ -32,6 +32,8 @@ class RimEclipseCase;
class RimFishbones;
class RimPerforationInterval;
class RimWellPath;
class RigMswTableData;
class RigMswUnifiedDataWIP;
class RimWellPathFracture;
class RimMswCompletionParameters;
class RigWellPath;
@@ -43,7 +45,6 @@ class QFile;
class RicWellPathExportMswCompletionsImpl
{
private:
public:
static void exportWellSegmentsForAllCompletions( const RicExportCompletionDataSettingsUi& exportSettings,
const std::vector<RimWellPath*>& wellPaths );
@@ -194,4 +195,20 @@ private:
static std::unique_ptr<RicMswBranch> createChildMswBranch( const RimWellPath* childWellPath );
static std::vector<RimWellPath*> wellPathsWithTieIn( const RimWellPath* wellPath );
//--------------------------------------------------------------------------------------------------
// New data extraction functions
//--------------------------------------------------------------------------------------------------
static void exportExperimentalMswToSeparateFolder( const RicExportCompletionDataSettingsUi& exportSettings,
const std::vector<RimWellPath*>& wellPaths );
static void exportUnifiedMswData( const RicExportCompletionDataSettingsUi& exportSettings,
const QString& exportFolder,
const std::vector<RimWellPath*>& wellPaths );
static void exportSplitMswData( const RicExportCompletionDataSettingsUi& exportSettings,
const QString& exportFolder,
const std::vector<RimWellPath*>& wellPaths );
static RigMswUnifiedDataWIP extractUnifiedMswData( RimEclipseCase* eclipseCase, int timeStep, const std::vector<RimWellPath*>& wellPaths );
};
@@ -43,7 +43,10 @@ void formatWelsegsRows( RifTextDataTableFormatter& formatter, const RowContainer
formatter.addOptionalValue( row.diameter );
formatter.addOptionalValue( row.roughness );
formatter.addOptionalComment( QString::fromStdString( row.description ) );
if ( !row.description.empty() )
{
formatter.addOptionalComment( QString::fromStdString( row.description ) );
}
formatter.rowCompleted();
}
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff