mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-24 22:27:55 -05:00
RimEclipseResultCase_createSaturationPressurePlots exposes the time step (the legacy command hardcodes 0) and returns an error when no plots could be created. It only shows the plot window when a GUI is running; the legacy code dereferenced RiaGuiApplication::instance() unconditionally. RicfCreateSaturationPressurePlots resolves the cases and loops, treating per-case failures as warnings as before. The hand-written Case.create_saturation_pressure_plots() Python wrapper is removed since the generated EclipseCase method shadows it.
1508 lines
69 KiB
C++
1508 lines
69 KiB
C++
/////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (C) 2020- Equinor 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 "RimcEclipseCase.h"
|
|
|
|
#include "RiaApplication.h"
|
|
#include "RiaGuiApplication.h"
|
|
#include "RiaKeyValueStoreUtil.h"
|
|
#include "RiaLogging.h"
|
|
|
|
#include "CompletionExportCommands/RicWellPathExportCompletionDataFeatureImpl.h"
|
|
#include "CompletionExportCommands/RicWellPathExportMswCompletionsImpl.h"
|
|
#include "ExportCommands/RicEclipseCellResultToFileImpl.h"
|
|
#include "ExportCommands/RicExportLgrFeature.h"
|
|
#include "FractureCommands/RicCreateMultipleFracturesOptionItemUi.h"
|
|
#include "FractureCommands/RicCreateMultipleFracturesUi.h"
|
|
#include "GridCrossPlotCommands/RicCreateSaturationPressurePlotsFeature.h"
|
|
#include "RicCreateTemporaryLgrFeature.h"
|
|
#include "RicDeleteTemporaryLgrsFeature.h"
|
|
|
|
#include "RifInputPropertyLoader.h"
|
|
|
|
#include "RigActiveCellInfo.h"
|
|
#include "RigCaseCellResultsData.h"
|
|
#include "RigEclipseCaseData.h"
|
|
#include "RigEclipseResultAddress.h"
|
|
#include "RigGridBase.h"
|
|
#include "RigGridExportAdapter.h"
|
|
#include "RigMainGrid.h"
|
|
#include "RigNoRefinement.h"
|
|
#include "RigResdataGridConverter.h"
|
|
#include "RigReservoirGridTools.h"
|
|
#include "RigResultAccessor.h"
|
|
#include "RigResultAccessorFactory.h"
|
|
|
|
#include "RimCase.h"
|
|
#include "RimCellFilter.h"
|
|
#include "RimDialogData.h"
|
|
#include "RimEclipseCase.h"
|
|
#include "RimEclipseResultCase.h"
|
|
#include "RimFlowCharacteristicsPlot.h"
|
|
#include "RimFlowPlotCollection.h"
|
|
#include "RimFractureTemplate.h"
|
|
#include "RimMainPlotCollection.h"
|
|
#include "RimOilField.h"
|
|
#include "RimProject.h"
|
|
#include "RimRoffCase.h"
|
|
#include "RimSaturationPressurePlotCollection.h"
|
|
#include "RimWellPath.h"
|
|
#include "RimWellPathCollection.h"
|
|
|
|
#include "RimcDataContainerString.h"
|
|
|
|
#include "cafCmdFeatureManager.h"
|
|
#include "cafPdmFieldScriptingCapability.h"
|
|
|
|
#include "cvfArray.h"
|
|
|
|
#include <QDir>
|
|
#include <QFile>
|
|
#include <QFileInfo>
|
|
#include <QTextStream>
|
|
|
|
#include <algorithm>
|
|
#include <expected>
|
|
#include <limits>
|
|
#include <vector>
|
|
|
|
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimEclipseCase, RimcEclipseCase_importProperties, "import_properties" );
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimcEclipseCase_importProperties::RimcEclipseCase_importProperties( caf::PdmObjectHandle* self )
|
|
: caf::PdmObjectMethod( self, PdmObjectMethod::NullPointerType::NULL_IS_INVALID, PdmObjectMethod::ResultType::PERSISTENT_FALSE )
|
|
{
|
|
CAF_PDM_InitObject( "Import Properties", "", "", "Import Properties" );
|
|
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_fileNames, "FileNames", "" );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::expected<caf::PdmObjectHandle*, QString> RimcEclipseCase_importProperties::execute()
|
|
{
|
|
std::vector<QString> absolutePaths;
|
|
for ( auto path : m_fileNames() )
|
|
{
|
|
QFileInfo projectPathInfo( path );
|
|
if ( !projectPathInfo.exists() )
|
|
{
|
|
QDir startDir( RiaApplication::instance()->startDir() );
|
|
path = startDir.absoluteFilePath( path );
|
|
}
|
|
absolutePaths.push_back( path );
|
|
}
|
|
|
|
std::vector<QString> propertyNames;
|
|
|
|
if ( auto eclipseCase = self<RimEclipseCase>() )
|
|
{
|
|
propertyNames = RifInputPropertyLoader::loadAndSynchronizeInputProperties( eclipseCase->inputPropertyCollection(),
|
|
eclipseCase->eclipseCaseData(),
|
|
absolutePaths,
|
|
false /* no faults */ );
|
|
}
|
|
|
|
auto dataObject = new RimcDataContainerString();
|
|
dataObject->m_stringValues = propertyNames;
|
|
|
|
return dataObject;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RimcEclipseCase_importProperties::classKeywordReturnedType() const
|
|
{
|
|
return RimcDataContainerString::classKeywordStatic();
|
|
}
|
|
|
|
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimEclipseCase, RimcEclipseCase_exportValuesInternal, "export_values_internal" );
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimcEclipseCase_exportValuesInternal::RimcEclipseCase_exportValuesInternal( caf::PdmObjectHandle* self )
|
|
: caf::PdmVoidObjectMethod( self )
|
|
{
|
|
CAF_PDM_InitObject( "Export Values Internal", "", "", "Export Values Internal" );
|
|
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_coordinateX, "CoordinateX", "" );
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_coordinateY, "CoordinateY", "" );
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_coordinateZ, "CoordinateZ", "" );
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_resultKey, "ResultKey", "" );
|
|
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_propertyType, "PropertyType", "" );
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_propertyName, "PropertyName", "" );
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_timeStep, "TimeStep", "" );
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_porosityModel, "PorosityModel", "" );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::expected<caf::PdmObjectHandle*, QString> RimcEclipseCase_exportValuesInternal::execute()
|
|
{
|
|
auto eclipseCase = self<RimEclipseCase>();
|
|
|
|
RigEclipseCaseData* eclipseCaseData = eclipseCase->eclipseCaseData();
|
|
if ( !eclipseCaseData )
|
|
{
|
|
return std::unexpected( "Unable to load eclipse case data." );
|
|
}
|
|
|
|
const RigMainGrid* mainGrid = eclipseCase->mainGrid();
|
|
if ( !mainGrid )
|
|
{
|
|
return std::unexpected( "Unable to load main grid for eclipse case." );
|
|
}
|
|
|
|
caf::AppEnum<RiaDefines::ResultCatType> resultCatTypeEnum;
|
|
if ( !resultCatTypeEnum.setFromText( m_propertyType ) )
|
|
{
|
|
return std::unexpected( "Invalid property type." );
|
|
}
|
|
|
|
caf::AppEnum<RiaDefines::PorosityModelType> porosityModel;
|
|
if ( !porosityModel.setFromText( m_porosityModel ) )
|
|
{
|
|
return std::unexpected( "Invalid porosity model." );
|
|
}
|
|
|
|
RigEclipseResultAddress resVarAddr( resultCatTypeEnum, m_propertyName );
|
|
eclipseCase->results( porosityModel )->ensureKnownResultLoaded( resVarAddr );
|
|
|
|
cvf::ref<RigResultAccessor> resultAccessor =
|
|
RigResultAccessorFactory::createFromResultAddress( eclipseCaseData, 0, porosityModel, m_timeStep, resVarAddr );
|
|
if ( resultAccessor.isNull() )
|
|
{
|
|
return std::unexpected( "Result property not found." );
|
|
}
|
|
|
|
// Num timesteps can be zero for roff cases.
|
|
int numTimesteps = static_cast<int>( eclipseCase->timeStepDates().size() );
|
|
if ( m_timeStep < 0 || ( m_timeStep >= numTimesteps && numTimesteps != 0 ) )
|
|
{
|
|
return std::unexpected( "Invalid time step." );
|
|
}
|
|
|
|
auto keyValueStore = RiaApplication::instance()->keyValueStore();
|
|
|
|
std::vector<float> xs = RiaKeyValueStoreUtil::convertToFloatVector( keyValueStore->get( m_coordinateX().toStdString() ) );
|
|
std::vector<float> ys = RiaKeyValueStoreUtil::convertToFloatVector( keyValueStore->get( m_coordinateY().toStdString() ) );
|
|
std::vector<float> zs = RiaKeyValueStoreUtil::convertToFloatVector( keyValueStore->get( m_coordinateZ().toStdString() ) );
|
|
if ( xs.empty() || xs.size() != ys.size() || xs.size() != zs.size() )
|
|
{
|
|
return std::unexpected( "Invalid positions specified." );
|
|
}
|
|
|
|
std::vector<cvf::Vec3d> positions;
|
|
for ( size_t i = 0; i < xs.size(); i++ )
|
|
{
|
|
positions.push_back( cvf::Vec3d( xs[i], ys[i], -zs[i] ) );
|
|
}
|
|
|
|
std::vector<float> values;
|
|
for ( const cvf::Vec3d& position : positions )
|
|
{
|
|
auto cellIdx = mainGrid->findReservoirCellIndexFromPoint( position );
|
|
if ( cellIdx != cvf::UNDEFINED_SIZE_T )
|
|
{
|
|
float valueFromEclipse = static_cast<float>( resultAccessor->cellScalar( cellIdx ) );
|
|
values.push_back( valueFromEclipse );
|
|
}
|
|
else
|
|
{
|
|
// Use inf as signal that nothing was found for the position
|
|
values.push_back( std::numeric_limits<float>::infinity() );
|
|
}
|
|
}
|
|
|
|
keyValueStore->set( m_resultKey().toStdString(), RiaKeyValueStoreUtil::convertToByteVector( values ) );
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimEclipseCase, RimcEclipseCase_exportCornerPointGridInternal, "export_corner_point_grid_internal" );
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimcEclipseCase_exportCornerPointGridInternal::RimcEclipseCase_exportCornerPointGridInternal( caf::PdmObjectHandle* self )
|
|
: caf::PdmVoidObjectMethod( self )
|
|
{
|
|
CAF_PDM_InitObject( "Export Corner Point Grid Internal", "", "", "Export Corner Point Grid Internal" );
|
|
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_zcornKey, "ZcornKey", "" );
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_coordKey, "CoordKey", "" );
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_actnumKey, "ActnumKey", "" );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::expected<caf::PdmObjectHandle*, QString> RimcEclipseCase_exportCornerPointGridInternal::execute()
|
|
{
|
|
auto eclipseCase = self<RimEclipseCase>();
|
|
if ( !eclipseCase )
|
|
{
|
|
return std::unexpected( "Unable to get Eclipse case." );
|
|
}
|
|
|
|
RigEclipseCaseData* eclipseCaseData = eclipseCase->eclipseCaseData();
|
|
if ( !eclipseCaseData )
|
|
{
|
|
return std::unexpected( "Unable to load eclipse case data." );
|
|
}
|
|
|
|
auto keyValueStore = RiaApplication::instance()->keyValueStore();
|
|
|
|
// Use RigGridExportAdapter to handle full grid export
|
|
// Export the full grid (no min/max bounds, no refinement, no visibility override)
|
|
const auto* mainGrid = eclipseCaseData->mainGrid();
|
|
cvf::Vec3st fullSize( mainGrid->cellCountI(), mainGrid->cellCountJ(), mainGrid->cellCountK() );
|
|
cvf::Vec3st fullMax( mainGrid->cellCountI() - 1, mainGrid->cellCountJ() - 1, mainGrid->cellCountK() - 1 );
|
|
RigGridExportAdapter gridAdapter( eclipseCaseData, cvf::Vec3st::ZERO, fullMax, RigNoRefinement( fullSize ), nullptr );
|
|
|
|
// Use the existing conversion utility to get the arrays in the correct format
|
|
std::vector<float> coordArray;
|
|
std::vector<float> zcornArray;
|
|
std::vector<int> actnumArray;
|
|
|
|
RigResdataGridConverter::convertGridToCornerPointArrays( gridAdapter, coordArray, zcornArray, actnumArray );
|
|
|
|
// Convert actnum from int to float for key-value store
|
|
std::vector<float> actnumFloat;
|
|
actnumFloat.reserve( actnumArray.size() );
|
|
for ( int value : actnumArray )
|
|
{
|
|
actnumFloat.push_back( static_cast<float>( value ) );
|
|
}
|
|
|
|
// Store arrays in key-value store
|
|
keyValueStore->set( m_zcornKey().toStdString(), RiaKeyValueStoreUtil::convertToByteVector( zcornArray ) );
|
|
keyValueStore->set( m_coordKey().toStdString(), RiaKeyValueStoreUtil::convertToByteVector( coordArray ) );
|
|
keyValueStore->set( m_actnumKey().toStdString(), RiaKeyValueStoreUtil::convertToByteVector( actnumFloat ) );
|
|
|
|
// Store grid dimensions as well
|
|
std::vector<float> dimensions = { static_cast<float>( gridAdapter.cellCountI() ),
|
|
static_cast<float>( gridAdapter.cellCountJ() ),
|
|
static_cast<float>( gridAdapter.cellCountK() ) };
|
|
keyValueStore->set( ( m_zcornKey().toStdString() + "_dimensions" ), RiaKeyValueStoreUtil::convertToByteVector( dimensions ) );
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimEclipseCase, RimcEclipseCase_addResultAlias, "add_result_alias" );
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimcEclipseCase_addResultAlias::RimcEclipseCase_addResultAlias( caf::PdmObjectHandle* self )
|
|
: caf::PdmVoidObjectMethod( self )
|
|
{
|
|
CAF_PDM_InitObject( "Add Result Alias", "", "", "Add Result Alias" );
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_resultName, "ResultName", "" );
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_aliasName, "AliasName", "" );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::expected<caf::PdmObjectHandle*, QString> RimcEclipseCase_addResultAlias::execute()
|
|
{
|
|
auto eclipseCase = self<RimEclipseCase>();
|
|
if ( !eclipseCase )
|
|
{
|
|
return std::unexpected( "Unable to get Eclipse case." );
|
|
}
|
|
eclipseCase->addResultAlias( m_resultName(), m_aliasName() );
|
|
return nullptr;
|
|
}
|
|
|
|
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimEclipseCase, RimcEclipseCase_clearResultAliases, "clear_result_aliases" );
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimcEclipseCase_clearResultAliases::RimcEclipseCase_clearResultAliases( caf::PdmObjectHandle* self )
|
|
: caf::PdmVoidObjectMethod( self )
|
|
{
|
|
CAF_PDM_InitObject( "Clear Result Aliases", "", "", "Clear Result Aliases" );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::expected<caf::PdmObjectHandle*, QString> RimcEclipseCase_clearResultAliases::execute()
|
|
{
|
|
auto eclipseCase = self<RimEclipseCase>();
|
|
if ( !eclipseCase )
|
|
{
|
|
return std::unexpected( "Unable to get Eclipse case." );
|
|
}
|
|
eclipseCase->clearResultAliases();
|
|
return nullptr;
|
|
}
|
|
|
|
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimEclipseCase, RimcEclipseCase_filteredCellsInternal, "filtered_cells_internal" );
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimcEclipseCase_filteredCellsInternal::RimcEclipseCase_filteredCellsInternal( caf::PdmObjectHandle* self )
|
|
: caf::PdmVoidObjectMethod( self )
|
|
{
|
|
CAF_PDM_InitObject( "Filtered Cells Internal",
|
|
"",
|
|
"",
|
|
"Apply a cell filter to this case for a grid + time step and write a per-cell 0/1 mask "
|
|
"to the key-value store. The vector length and ordering match grid_property(...) for the "
|
|
"same grid index." );
|
|
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_filter, "Filter", "", "", "", "Cell Filter" );
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_maskKey, "MaskKey", "" );
|
|
CAF_PDM_InitScriptableField( &m_timeStep, "TimeStep", 0, "" );
|
|
CAF_PDM_InitScriptableField( &m_gridIndex, "GridIndex", 0, "" );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::expected<caf::PdmObjectHandle*, QString> RimcEclipseCase_filteredCellsInternal::execute()
|
|
{
|
|
auto* eclipseCase = self<RimEclipseCase>();
|
|
if ( !eclipseCase || !eclipseCase->eclipseCaseData() )
|
|
{
|
|
return std::unexpected( QString( "Self is not an Eclipse case with case data." ) );
|
|
}
|
|
if ( m_maskKey().isEmpty() )
|
|
{
|
|
return std::unexpected( QString( "Mask key is empty." ) );
|
|
}
|
|
|
|
RimCellFilter* filter = m_filter();
|
|
if ( !filter )
|
|
{
|
|
return std::unexpected( QString( "Filter argument is null." ) );
|
|
}
|
|
|
|
RigEclipseCaseData* caseData = eclipseCase->eclipseCaseData();
|
|
const size_t gridIdx = static_cast<size_t>( std::max( 0, m_gridIndex() ) );
|
|
if ( gridIdx >= caseData->gridCount() )
|
|
{
|
|
return std::unexpected( QString( "Grid index out of range." ) );
|
|
}
|
|
|
|
const RigGridBase* grid = caseData->grid( gridIdx );
|
|
const size_t n = grid->cellCount();
|
|
|
|
cvf::UByteArray cellVis( n );
|
|
cellVis.setAll( 1 );
|
|
filter->applyToCellVisibility( &cellVis, grid, static_cast<size_t>( std::max( 0, m_timeStep() ) ) );
|
|
|
|
std::vector<float> values;
|
|
values.reserve( n );
|
|
for ( size_t i = 0; i < n; ++i )
|
|
{
|
|
values.push_back( cellVis[i] ? 1.0f : 0.0f );
|
|
}
|
|
|
|
auto keyValueStore = RiaApplication::instance()->keyValueStore();
|
|
keyValueStore->set( m_maskKey().toStdString(), RiaKeyValueStoreUtil::convertToByteVector( values ) );
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimEclipseCase, RimcEclipseCase_propertyDataType, "property_data_type" );
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimcEclipseCase_propertyDataType::RimcEclipseCase_propertyDataType( caf::PdmObjectHandle* self )
|
|
: caf::PdmEnumObjectMethod<RiaDefines::ResultDataType>( self )
|
|
{
|
|
CAF_PDM_InitObject( "Property Data Type", "", "", "Get the data type (FLOAT or INTEGER) of a grid property" );
|
|
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_propertyType, "PropertyType", "" );
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_propertyName, "PropertyName", "" );
|
|
CAF_PDM_InitScriptableField( &m_porosityModel,
|
|
"PorosityModel",
|
|
caf::AppEnum<RiaDefines::PorosityModelType>( RiaDefines::PorosityModelType::MATRIX_MODEL ),
|
|
"" );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::expected<RiaDefines::ResultDataType, QString> RimcEclipseCase_propertyDataType::executeEnum()
|
|
{
|
|
auto eclipseCase = self<RimEclipseCase>();
|
|
if ( !eclipseCase ) return std::unexpected( "No eclipse case" );
|
|
|
|
auto resultsData = eclipseCase->results( m_porosityModel() );
|
|
if ( !resultsData )
|
|
{
|
|
return std::unexpected( "Eclipse case has no result data." );
|
|
}
|
|
|
|
for ( const auto& address : resultsData->existingResults() )
|
|
{
|
|
if ( address.resultCatType() == m_propertyType() && address.resultName() == m_propertyName() )
|
|
{
|
|
return address.dataType();
|
|
}
|
|
}
|
|
|
|
return std::unexpected( QString( "Property not found: %1" ).arg( m_propertyName() ) );
|
|
}
|
|
|
|
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimEclipseCase, RimEclipseCase_exportProperty, "exportProperty" );
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimEclipseCase_exportProperty::RimEclipseCase_exportProperty( caf::PdmObjectHandle* self )
|
|
: caf::PdmVoidObjectMethod( self )
|
|
{
|
|
CAF_PDM_InitObject( "Export Property", "", "", "Export a cell property of the case to a GRDECL style text file" );
|
|
|
|
CAF_PDM_InitScriptableField( &m_timeStep, "TimeStep", -1, "Time Step", "", "", "Zero-based time step index. Ignored for static properties." );
|
|
CAF_PDM_InitScriptableField( &m_propertyName, "PropertyName", QString(), "Property Name", "", "", "Name of the property to export" );
|
|
CAF_PDM_InitScriptableField( &m_eclipseKeyword,
|
|
"EclipseKeyword",
|
|
QString(),
|
|
"Eclipse Keyword",
|
|
"",
|
|
"",
|
|
"Keyword written to the file header. Defaults to the property name." );
|
|
CAF_PDM_InitScriptableField( &m_undefinedValue, "UndefinedValue", 0.0, "Undefined Value", "", "", "Value written for undefined cells" );
|
|
CAF_PDM_InitScriptableField( &m_exportFile, "ExportFile", QString(), "Export File", "", "", "Full path of the file to write" );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportProperty::setTimeStep( int timeStep )
|
|
{
|
|
m_timeStep = timeStep;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportProperty::setPropertyName( const QString& propertyName )
|
|
{
|
|
m_propertyName = propertyName;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportProperty::setEclipseKeyword( const QString& eclipseKeyword )
|
|
{
|
|
m_eclipseKeyword = eclipseKeyword;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportProperty::setUndefinedValue( double undefinedValue )
|
|
{
|
|
m_undefinedValue = undefinedValue;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportProperty::setExportFile( const QString& exportFile )
|
|
{
|
|
m_exportFile = exportFile;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::expected<caf::PdmObjectHandle*, QString> RimEclipseCase_exportProperty::execute()
|
|
{
|
|
auto* eclipseCase = self<RimEclipseCase>();
|
|
if ( !eclipseCase ) return std::unexpected( "No case is available." );
|
|
|
|
if ( m_propertyName().isEmpty() ) return std::unexpected( "No property name specified." );
|
|
if ( m_exportFile().isEmpty() ) return std::unexpected( "No export file specified." );
|
|
|
|
if ( !eclipseCase->eclipseCaseData() && !eclipseCase->openReservoirCase() )
|
|
{
|
|
return std::unexpected( QString( "Could not open case '%1'" ).arg( eclipseCase->caseUserDescription() ) );
|
|
}
|
|
|
|
RigEclipseCaseData* eclipseCaseData = eclipseCase->eclipseCaseData();
|
|
RigCaseCellResultsData* cellResultsData = eclipseCaseData->results( RiaDefines::PorosityModelType::MATRIX_MODEL );
|
|
|
|
if ( !cellResultsData->ensureKnownResultLoaded( RigEclipseResultAddress( m_propertyName() ) ) )
|
|
{
|
|
return std::unexpected( QString( "Could not find result property '%1'" ).arg( m_propertyName() ) );
|
|
}
|
|
|
|
QString eclipseKeyword = m_eclipseKeyword();
|
|
if ( eclipseKeyword.isEmpty() ) eclipseKeyword = m_propertyName();
|
|
|
|
const bool writeEchoKeywords = false;
|
|
QString errorMessage;
|
|
if ( !RicEclipseCellResultToFileImpl::writePropertyToTextFile( m_exportFile(),
|
|
eclipseCaseData,
|
|
m_timeStep(),
|
|
m_propertyName(),
|
|
eclipseKeyword,
|
|
m_undefinedValue(),
|
|
writeEchoKeywords,
|
|
&errorMessage ) )
|
|
{
|
|
return std::unexpected( errorMessage );
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimEclipseCase, RimEclipseCase_exportCompletions, "exportCompletions" );
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimEclipseCase_exportCompletions::RimEclipseCase_exportCompletions( caf::PdmObjectHandle* self )
|
|
: caf::PdmVoidObjectMethod( self )
|
|
{
|
|
CAF_PDM_InitObject( "Export Completions", "", "", "Export completion data (COMPDAT, WELSPECS, MSW keywords etc.) for well paths in this case" );
|
|
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_wellPaths,
|
|
"WellPaths",
|
|
"Well Paths",
|
|
"",
|
|
"",
|
|
"Well paths to export. Empty list exports all visible well paths." );
|
|
CAF_PDM_InitScriptableField( &m_timeStep, "TimeStep", 0, "Time Step", "", "", "Zero-based time step index" );
|
|
CAF_PDM_InitScriptableField( &m_exportFolder, "ExportFolder", QString(), "Export Folder", "", "", "Folder to write the export files to" );
|
|
CAF_PDM_InitScriptableField( &m_customFileName,
|
|
"CustomFileName",
|
|
QString(),
|
|
"Custom File Name",
|
|
"",
|
|
"",
|
|
"Optional file name (without folder) used when FileSplit is UNIFIED_FILE" );
|
|
|
|
CAF_PDM_InitScriptableField( &m_fileSplit,
|
|
"FileSplit",
|
|
RicExportCompletionDataSettingsUi::ExportSplitType(),
|
|
"File Split",
|
|
"",
|
|
"",
|
|
"Controls how export data is split into files" );
|
|
CAF_PDM_InitScriptableField( &m_compdatExport,
|
|
"CompdatExport",
|
|
RicExportCompletionDataSettingsUi::CompdatExportType(),
|
|
"Compdat Export",
|
|
"",
|
|
"",
|
|
"Compdat export type" );
|
|
|
|
CAF_PDM_InitScriptableField( &m_includeMsw, "IncludeMsw", true, "Include MSW", "", "", "Export Multi Segment Well model" );
|
|
CAF_PDM_InitScriptableField( &m_useNtgHorizontally, "UseNtgHorizontally", false, "Use NTG Horizontally" );
|
|
CAF_PDM_InitScriptableField( &m_includePerforations, "IncludePerforations", true, "Include Perforations" );
|
|
CAF_PDM_InitScriptableField( &m_includeFishbones, "IncludeFishbones", true, "Include Fishbones" );
|
|
CAF_PDM_InitScriptableField( &m_includeFractures, "IncludeFractures", true, "Include Fractures" );
|
|
CAF_PDM_InitScriptableField( &m_excludeMainBoreForFishbones, "ExcludeMainBoreForFishbones", false, "Exclude Main Bore for Fishbones" );
|
|
|
|
CAF_PDM_InitScriptableField( &m_performTransScaling, "PerformTransScaling", false, "Perform Transmissibility Scaling" );
|
|
CAF_PDM_InitScriptableField( &m_transScalingTimeStep, "TransScalingTimeStep", 0, "Transmissibility Scaling Pressure Time Step" );
|
|
CAF_PDM_InitScriptableField( &m_transScalingWbhpSource,
|
|
"TransScalingWbhpSource",
|
|
RicExportCompletionDataSettingsUi::TransScalingWBHPSource(),
|
|
"Transmissibility Scaling WBHP Source" );
|
|
CAF_PDM_InitScriptableField( &m_transScalingWbhp, "TransScalingWbhp", 200.0, "Transmissibility Scaling Constant WBHP Value" );
|
|
|
|
CAF_PDM_InitScriptableField( &m_exportComments, "ExportComments", true, "Export Comments", "", "", "Export data source as comments" );
|
|
CAF_PDM_InitScriptableField( &m_exportWelspec, "ExportWelspec", true, "Export WELSPEC", "", "", "Export WELSPEC keyword" );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportCompletions::setWellPaths( const std::vector<RimWellPath*>& wellPaths )
|
|
{
|
|
m_wellPaths.setValue( wellPaths );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportCompletions::setTimeStep( int timeStep )
|
|
{
|
|
m_timeStep = timeStep;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportCompletions::setExportFolder( const QString& exportFolder )
|
|
{
|
|
m_exportFolder = exportFolder;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportCompletions::setCustomFileName( const QString& customFileName )
|
|
{
|
|
m_customFileName = customFileName;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportCompletions::setFileSplit( RicExportCompletionDataSettingsUi::ExportSplit fileSplit )
|
|
{
|
|
m_fileSplit = fileSplit;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportCompletions::setCompdatExport( RicExportCompletionDataSettingsUi::CompdatExport compdatExport )
|
|
{
|
|
m_compdatExport = compdatExport;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportCompletions::setIncludeMsw( bool enable )
|
|
{
|
|
m_includeMsw = enable;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportCompletions::setUseNtgHorizontally( bool enable )
|
|
{
|
|
m_useNtgHorizontally = enable;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportCompletions::setIncludePerforations( bool enable )
|
|
{
|
|
m_includePerforations = enable;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportCompletions::setIncludeFishbones( bool enable )
|
|
{
|
|
m_includeFishbones = enable;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportCompletions::setIncludeFractures( bool enable )
|
|
{
|
|
m_includeFractures = enable;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportCompletions::setExcludeMainBoreForFishbones( bool enable )
|
|
{
|
|
m_excludeMainBoreForFishbones = enable;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportCompletions::setPerformTransScaling( bool enable )
|
|
{
|
|
m_performTransScaling = enable;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportCompletions::setTransScalingTimeStep( int timeStep )
|
|
{
|
|
m_transScalingTimeStep = timeStep;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportCompletions::setTransScalingWbhpSource( RicExportFractureCompletionsImpl::PressureDepletionWBHPSource source )
|
|
{
|
|
m_transScalingWbhpSource = source;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportCompletions::setTransScalingWbhp( double wbhp )
|
|
{
|
|
m_transScalingWbhp = wbhp;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportCompletions::setExportComments( bool enable )
|
|
{
|
|
m_exportComments = enable;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportCompletions::setExportWelspec( bool enable )
|
|
{
|
|
m_exportWelspec = enable;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::expected<caf::PdmObjectHandle*, QString> RimEclipseCase_exportCompletions::execute()
|
|
{
|
|
auto* eclipseCase = self<RimEclipseCase>();
|
|
if ( !eclipseCase ) return std::unexpected( "No case is available." );
|
|
|
|
if ( m_exportFolder().isEmpty() ) return std::unexpected( "No export folder specified." );
|
|
|
|
QDir folder( m_exportFolder() );
|
|
if ( !folder.exists() ) return std::unexpected( QString( "The export folder '%1' does not exist." ).arg( m_exportFolder() ) );
|
|
|
|
eclipseCase->ensureReservoirCaseIsOpen();
|
|
if ( !eclipseCase->eclipseCaseData() )
|
|
{
|
|
return std::unexpected( QString( "No data available for case '%1'" ).arg( eclipseCase->caseUserDescription() ) );
|
|
}
|
|
|
|
std::vector<RimWellPath*> wellPaths = m_wellPaths.ptrReferencedObjectsByType();
|
|
if ( wellPaths.empty() )
|
|
{
|
|
RimProject* project = RimProject::current();
|
|
for ( RimWellPath* wellPath : project->activeOilField()->wellPathCollection->allWellPaths() )
|
|
{
|
|
if ( wellPath->showWellPath() ) wellPaths.push_back( wellPath );
|
|
}
|
|
}
|
|
|
|
if ( wellPaths.empty() ) return std::unexpected( "No well paths to export." );
|
|
|
|
RicExportCompletionDataSettingsUi exportSettings;
|
|
exportSettings.caseToApply = eclipseCase;
|
|
exportSettings.folder = m_exportFolder();
|
|
exportSettings.timeStep = std::max( 0, m_timeStep() );
|
|
|
|
exportSettings.fileSplit = m_fileSplit();
|
|
exportSettings.compdatExport = m_compdatExport();
|
|
|
|
exportSettings.performTransScaling = m_performTransScaling();
|
|
exportSettings.transScalingTimeStep = m_transScalingTimeStep();
|
|
exportSettings.transScalingWBHPSource = m_transScalingWbhpSource();
|
|
exportSettings.transScalingWBHP = m_transScalingWbhp();
|
|
|
|
exportSettings.includeMsw = m_includeMsw();
|
|
exportSettings.useLateralNTG = m_useNtgHorizontally();
|
|
exportSettings.includePerforations = m_includePerforations();
|
|
exportSettings.includeFishbones = m_includeFishbones();
|
|
exportSettings.excludeMainBoreForFishbones = m_excludeMainBoreForFishbones();
|
|
exportSettings.includeFractures = m_includeFractures();
|
|
|
|
exportSettings.setExportDataSourceAsComment( m_exportComments() );
|
|
exportSettings.setExportWelspec( m_exportWelspec() );
|
|
|
|
if ( !m_customFileName().isEmpty() ) exportSettings.setCustomFileName( m_customFileName() );
|
|
|
|
RicWellPathExportCompletionDataFeatureImpl::exportCompletions( wellPaths, exportSettings );
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimEclipseCase, RimEclipseCase_exportMswCompletions, "exportMswCompletions" );
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimEclipseCase_exportMswCompletions::RimEclipseCase_exportMswCompletions( caf::PdmObjectHandle* self )
|
|
: caf::PdmVoidObjectMethod( self )
|
|
{
|
|
CAF_PDM_InitObject( "Export MSW Completions", "", "", "Export the Multi Segment Well model keywords for well paths in this case" );
|
|
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_wellPaths, "WellPaths", "Well Paths", "", "", "Well paths to export" );
|
|
CAF_PDM_InitScriptableField( &m_exportFolder, "ExportFolder", QString(), "Export Folder", "", "", "Folder to write the export files to" );
|
|
CAF_PDM_InitScriptableField( &m_fileSplit,
|
|
"FileSplit",
|
|
RicExportCompletionDataSettingsUi::ExportSplitType(),
|
|
"File Split",
|
|
"",
|
|
"",
|
|
"Controls how export data is split into files" );
|
|
CAF_PDM_InitScriptableField( &m_includePerforations, "IncludePerforations", true, "Include Perforations" );
|
|
CAF_PDM_InitScriptableField( &m_includeFishbones, "IncludeFishbones", true, "Include Fishbones" );
|
|
CAF_PDM_InitScriptableField( &m_includeFractures, "IncludeFractures", true, "Include Fractures" );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportMswCompletions::setWellPaths( const std::vector<RimWellPath*>& wellPaths )
|
|
{
|
|
m_wellPaths.setValue( wellPaths );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportMswCompletions::setExportFolder( const QString& exportFolder )
|
|
{
|
|
m_exportFolder = exportFolder;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportMswCompletions::setFileSplit( RicExportCompletionDataSettingsUi::ExportSplit fileSplit )
|
|
{
|
|
m_fileSplit = fileSplit;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportMswCompletions::setIncludePerforations( bool enable )
|
|
{
|
|
m_includePerforations = enable;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportMswCompletions::setIncludeFishbones( bool enable )
|
|
{
|
|
m_includeFishbones = enable;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportMswCompletions::setIncludeFractures( bool enable )
|
|
{
|
|
m_includeFractures = enable;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::expected<caf::PdmObjectHandle*, QString> RimEclipseCase_exportMswCompletions::execute()
|
|
{
|
|
auto* eclipseCase = self<RimEclipseCase>();
|
|
if ( !eclipseCase ) return std::unexpected( "No case is available." );
|
|
|
|
if ( m_exportFolder().isEmpty() ) return std::unexpected( "No export folder specified." );
|
|
|
|
QDir folder( m_exportFolder() );
|
|
if ( !folder.exists() ) return std::unexpected( QString( "The export folder '%1' does not exist." ).arg( m_exportFolder() ) );
|
|
|
|
std::vector<RimWellPath*> wellPaths = m_wellPaths.ptrReferencedObjectsByType();
|
|
if ( wellPaths.empty() ) return std::unexpected( "No well paths specified." );
|
|
|
|
eclipseCase->ensureReservoirCaseIsOpen();
|
|
if ( !eclipseCase->eclipseCaseData() )
|
|
{
|
|
return std::unexpected( QString( "No data available for case '%1'" ).arg( eclipseCase->caseUserDescription() ) );
|
|
}
|
|
|
|
RicExportCompletionDataSettingsUi exportSettings;
|
|
exportSettings.caseToApply = eclipseCase;
|
|
exportSettings.folder = m_exportFolder();
|
|
exportSettings.fileSplit = m_fileSplit();
|
|
exportSettings.includePerforations = m_includePerforations();
|
|
exportSettings.includeFishbones = m_includeFishbones();
|
|
exportSettings.includeFractures = m_includeFractures();
|
|
|
|
RicWellPathExportMswCompletionsImpl::exportWellSegmentsForAllCompletions( exportSettings, wellPaths );
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimEclipseCase, RimEclipseCase_createLgrForCompletions, "createLgrForCompletions" );
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimEclipseCase_createLgrForCompletions::RimEclipseCase_createLgrForCompletions( caf::PdmObjectHandle* self )
|
|
: caf::PdmVoidObjectMethod( self )
|
|
{
|
|
CAF_PDM_InitObject( "Create LGR for Completions",
|
|
"",
|
|
"",
|
|
"Create temporary local grid refinements around the completions of the given well paths" );
|
|
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_wellPaths, "WellPaths", "Well Paths", "", "", "Well paths to create LGRs for" );
|
|
CAF_PDM_InitScriptableField( &m_timeStep, "TimeStep", 0, "Time Step", "", "", "Zero-based time step index" );
|
|
CAF_PDM_InitScriptableField( &m_refinementI, "RefinementI", 1, "Refinement I", "", "", "Number of refined cells in I direction" );
|
|
CAF_PDM_InitScriptableField( &m_refinementJ, "RefinementJ", 1, "Refinement J", "", "", "Number of refined cells in J direction" );
|
|
CAF_PDM_InitScriptableField( &m_refinementK, "RefinementK", 1, "Refinement K", "", "", "Number of refined cells in K direction" );
|
|
CAF_PDM_InitScriptableField( &m_splitType, "SplitType", Lgr::SplitTypeEnum(), "Split Type", "", "", "Defines how to split the LGRs" );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_createLgrForCompletions::setWellPaths( const std::vector<RimWellPath*>& wellPaths )
|
|
{
|
|
m_wellPaths.setValue( wellPaths );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_createLgrForCompletions::setTimeStep( int timeStep )
|
|
{
|
|
m_timeStep = timeStep;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_createLgrForCompletions::setRefinement( int refinementI, int refinementJ, int refinementK )
|
|
{
|
|
m_refinementI = refinementI;
|
|
m_refinementJ = refinementJ;
|
|
m_refinementK = refinementK;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_createLgrForCompletions::setSplitType( Lgr::SplitType splitType )
|
|
{
|
|
m_splitType = splitType;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QStringList RimEclipseCase_createLgrForCompletions::wellsIntersectingOtherLgrs() const
|
|
{
|
|
return m_wellsIntersectingOtherLgrs;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::expected<caf::PdmObjectHandle*, QString> RimEclipseCase_createLgrForCompletions::execute()
|
|
{
|
|
auto* eclipseCase = self<RimEclipseCase>();
|
|
if ( !eclipseCase ) return std::unexpected( "No case is available." );
|
|
|
|
std::vector<RimWellPath*> wellPaths = m_wellPaths.ptrReferencedObjectsByType();
|
|
if ( wellPaths.empty() ) return std::unexpected( "No well paths specified." );
|
|
|
|
if ( m_refinementI() < 1 || m_refinementJ() < 1 || m_refinementK() < 1 )
|
|
{
|
|
return std::unexpected( "Refinement must be at least 1 in all directions." );
|
|
}
|
|
|
|
auto* feature = dynamic_cast<RicCreateTemporaryLgrFeature*>(
|
|
caf::CmdFeatureManager::instance()->getCommandFeature( "RicCreateTemporaryLgrFeature" ) );
|
|
if ( !feature ) return std::unexpected( "The create LGR feature is not available." );
|
|
|
|
RicDeleteTemporaryLgrsFeature::deleteAllTemporaryLgrs( eclipseCase );
|
|
|
|
cvf::Vec3st lgrCellCounts( m_refinementI(), m_refinementJ(), m_refinementK() );
|
|
m_wellsIntersectingOtherLgrs.clear();
|
|
|
|
feature->createLgrsForWellPaths( wellPaths,
|
|
eclipseCase,
|
|
m_timeStep(),
|
|
lgrCellCounts,
|
|
m_splitType(),
|
|
{ RigCompletionData::CompletionType::PERFORATION,
|
|
RigCompletionData::CompletionType::FRACTURE,
|
|
RigCompletionData::CompletionType::FISHBONES },
|
|
&m_wellsIntersectingOtherLgrs );
|
|
|
|
RigReservoirGridTools::refreshEclipseCaseDataAndViews( eclipseCase );
|
|
|
|
if ( !m_wellsIntersectingOtherLgrs.empty() )
|
|
{
|
|
RiaLogging::warning( QString( "No LGRs created for some wells due to existing intersecting LGR(s). Affected wells: %1" )
|
|
.arg( m_wellsIntersectingOtherLgrs.join( ", " ) )
|
|
.toStdString() );
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimEclipseCase, RimEclipseCase_exportLgrForCompletions, "exportLgrForCompletions" );
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimEclipseCase_exportLgrForCompletions::RimEclipseCase_exportLgrForCompletions( caf::PdmObjectHandle* self )
|
|
: caf::PdmVoidObjectMethod( self )
|
|
{
|
|
CAF_PDM_InitObject( "Export LGR for Completions",
|
|
"",
|
|
"",
|
|
"Export local grid refinements around the completions of the given well paths to CARFIN files" );
|
|
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_wellPaths, "WellPaths", "Well Paths", "", "", "Well paths to export LGRs for" );
|
|
CAF_PDM_InitScriptableField( &m_timeStep, "TimeStep", 0, "Time Step", "", "", "Zero-based time step index" );
|
|
CAF_PDM_InitScriptableField( &m_exportFolder, "ExportFolder", QString(), "Export Folder", "", "", "Folder to write the export files to" );
|
|
CAF_PDM_InitScriptableField( &m_refinementI, "RefinementI", 1, "Refinement I", "", "", "Number of refined cells in I direction" );
|
|
CAF_PDM_InitScriptableField( &m_refinementJ, "RefinementJ", 1, "Refinement J", "", "", "Number of refined cells in J direction" );
|
|
CAF_PDM_InitScriptableField( &m_refinementK, "RefinementK", 1, "Refinement K", "", "", "Number of refined cells in K direction" );
|
|
CAF_PDM_InitScriptableField( &m_splitType, "SplitType", Lgr::SplitTypeEnum(), "Split Type", "", "", "Defines how to split the LGRs" );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportLgrForCompletions::setWellPaths( const std::vector<RimWellPath*>& wellPaths )
|
|
{
|
|
m_wellPaths.setValue( wellPaths );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportLgrForCompletions::setTimeStep( int timeStep )
|
|
{
|
|
m_timeStep = timeStep;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportLgrForCompletions::setExportFolder( const QString& exportFolder )
|
|
{
|
|
m_exportFolder = exportFolder;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportLgrForCompletions::setRefinement( int refinementI, int refinementJ, int refinementK )
|
|
{
|
|
m_refinementI = refinementI;
|
|
m_refinementJ = refinementJ;
|
|
m_refinementK = refinementK;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_exportLgrForCompletions::setSplitType( Lgr::SplitType splitType )
|
|
{
|
|
m_splitType = splitType;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QStringList RimEclipseCase_exportLgrForCompletions::wellsIntersectingOtherLgrs() const
|
|
{
|
|
return m_wellsIntersectingOtherLgrs;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::expected<caf::PdmObjectHandle*, QString> RimEclipseCase_exportLgrForCompletions::execute()
|
|
{
|
|
auto* eclipseCase = self<RimEclipseCase>();
|
|
if ( !eclipseCase ) return std::unexpected( "No case is available." );
|
|
|
|
std::vector<RimWellPath*> wellPaths = m_wellPaths.ptrReferencedObjectsByType();
|
|
if ( wellPaths.empty() ) return std::unexpected( "No well paths specified." );
|
|
|
|
if ( m_exportFolder().isEmpty() ) return std::unexpected( "No export folder specified." );
|
|
|
|
if ( m_refinementI() < 1 || m_refinementJ() < 1 || m_refinementK() < 1 )
|
|
{
|
|
return std::unexpected( "Refinement must be at least 1 in all directions." );
|
|
}
|
|
|
|
cvf::Vec3st lgrCellCounts( m_refinementI(), m_refinementJ(), m_refinementK() );
|
|
m_wellsIntersectingOtherLgrs.clear();
|
|
|
|
RicExportLgrFeature::exportLgrsForWellPaths( m_exportFolder(),
|
|
wellPaths,
|
|
eclipseCase,
|
|
m_timeStep(),
|
|
lgrCellCounts,
|
|
m_splitType(),
|
|
{ RigCompletionData::CompletionType::PERFORATION,
|
|
RigCompletionData::CompletionType::FRACTURE,
|
|
RigCompletionData::CompletionType::FISHBONES },
|
|
&m_wellsIntersectingOtherLgrs );
|
|
|
|
if ( !m_wellsIntersectingOtherLgrs.empty() )
|
|
{
|
|
RiaLogging::warning( QString( "No export for some wells due to existing intersecting LGR(s). Affected wells: %1" )
|
|
.arg( m_wellsIntersectingOtherLgrs.join( ", " ) )
|
|
.toStdString() );
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimEclipseCase, RimEclipseCase_createMultipleFractures, "createMultipleFractures" );
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimEclipseCase_createMultipleFractures::RimEclipseCase_createMultipleFractures( caf::PdmObjectHandle* self )
|
|
: caf::PdmVoidObjectMethod( self )
|
|
{
|
|
CAF_PDM_InitObject( "Create Multiple Fractures", "", "", "Create multiple fractures along the given well paths using a fracture template" );
|
|
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_wellPaths, "WellPaths", "Well Paths", "", "", "Well paths to create fractures for" );
|
|
CAF_PDM_InitScriptableFieldNoDefault( &m_fractureTemplate, "FractureTemplate", "Fracture Template", "", "", "Template used for the created fractures" );
|
|
CAF_PDM_InitScriptableField( &m_minDistFromWellTd,
|
|
"MinDistFromWellTd",
|
|
100.0,
|
|
"Min Distance From Well TD",
|
|
"",
|
|
"",
|
|
"Minimum distance from the well total depth" );
|
|
CAF_PDM_InitScriptableField( &m_maxFracturesPerWell, "MaxFracturesPerWell", 100, "Max Fractures per Well" );
|
|
CAF_PDM_InitScriptableField( &m_topLayer, "TopLayer", -1, "Top Layer", "", "", "Zero-based K index of the top layer. -1 uses the top of the grid." );
|
|
CAF_PDM_InitScriptableField( &m_baseLayer,
|
|
"BaseLayer",
|
|
-1,
|
|
"Base Layer",
|
|
"",
|
|
"",
|
|
"Zero-based K index of the base layer. -1 uses the bottom of the grid." );
|
|
CAF_PDM_InitScriptableField( &m_spacing, "Spacing", 300.0, "Spacing", "", "", "Distance between fractures" );
|
|
CAF_PDM_InitScriptableField( &m_action,
|
|
"Action",
|
|
caf::AppEnum<MultipleFractures::Action>( MultipleFractures::Action::APPEND_FRACTURES ),
|
|
"Action",
|
|
"",
|
|
"",
|
|
"Append to or replace the existing fractures on the well paths" );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_createMultipleFractures::setWellPaths( const std::vector<RimWellPath*>& wellPaths )
|
|
{
|
|
m_wellPaths.setValue( wellPaths );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_createMultipleFractures::setFractureTemplate( RimFractureTemplate* fractureTemplate )
|
|
{
|
|
m_fractureTemplate = fractureTemplate;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_createMultipleFractures::setMinDistFromWellTd( double minDist )
|
|
{
|
|
m_minDistFromWellTd = minDist;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_createMultipleFractures::setMaxFracturesPerWell( int maxFractures )
|
|
{
|
|
m_maxFracturesPerWell = maxFractures;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_createMultipleFractures::setTopLayer( int topLayer )
|
|
{
|
|
m_topLayer = topLayer;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_createMultipleFractures::setBaseLayer( int baseLayer )
|
|
{
|
|
m_baseLayer = baseLayer;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_createMultipleFractures::setSpacing( double spacing )
|
|
{
|
|
m_spacing = spacing;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseCase_createMultipleFractures::setAction( MultipleFractures::Action action )
|
|
{
|
|
m_action = action;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::expected<caf::PdmObjectHandle*, QString> RimEclipseCase_createMultipleFractures::execute()
|
|
{
|
|
auto* eclipseCase = self<RimEclipseCase>();
|
|
if ( !eclipseCase ) return std::unexpected( "No case is available." );
|
|
|
|
std::vector<RimWellPath*> wellPaths = m_wellPaths.ptrReferencedObjectsByType();
|
|
if ( wellPaths.empty() ) return std::unexpected( "No well paths specified." );
|
|
|
|
RimFractureTemplate* fractureTemplate = m_fractureTemplate();
|
|
if ( !fractureTemplate ) return std::unexpected( "No fracture template specified." );
|
|
|
|
if ( m_action() == MultipleFractures::Action::NONE ) return std::unexpected( "Action must be APPEND_FRACTURES or REPLACE_FRACTURES." );
|
|
|
|
auto* feature = dynamic_cast<RicCreateMultipleFracturesFeature*>(
|
|
caf::CmdFeatureManager::instance()->getCommandFeature( "RicCreateMultipleFracturesFeature" ) );
|
|
if ( !feature ) return std::unexpected( "The create multiple fractures feature is not available." );
|
|
|
|
RimProject* project = RimProject::current();
|
|
RiuCreateMultipleFractionsUi* settings = project->dialogData()->multipleFractionsData();
|
|
|
|
// Default layers
|
|
int topLayer = m_topLayer();
|
|
int baseLayer = m_baseLayer();
|
|
if ( topLayer < 0 || baseLayer < 0 )
|
|
{
|
|
auto ijkRange = feature->ijkRangeForGrid( eclipseCase );
|
|
if ( topLayer < 0 ) topLayer = static_cast<int>( ijkRange.min().z() );
|
|
if ( baseLayer < 0 ) baseLayer = static_cast<int>( ijkRange.max().z() );
|
|
}
|
|
|
|
auto* options = new RicCreateMultipleFracturesOptionItemUi();
|
|
options->setValues( topLayer, baseLayer, fractureTemplate, m_spacing() );
|
|
|
|
settings->clearWellPaths();
|
|
for ( RimWellPath* wellPath : wellPaths )
|
|
{
|
|
settings->addWellPath( wellPath );
|
|
}
|
|
|
|
settings->setValues( eclipseCase, m_minDistFromWellTd(), m_maxFracturesPerWell() );
|
|
settings->clearOptions();
|
|
settings->insertOptionItem( nullptr, options );
|
|
|
|
if ( m_action() == MultipleFractures::Action::APPEND_FRACTURES ) feature->appendFractures();
|
|
if ( m_action() == MultipleFractures::Action::REPLACE_FRACTURES ) feature->replaceFractures();
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimEclipseResultCase, RimEclipseResultCase_exportFlowCharacteristics, "exportFlowCharacteristics" );
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimEclipseResultCase_exportFlowCharacteristics::RimEclipseResultCase_exportFlowCharacteristics( caf::PdmObjectHandle* self )
|
|
: caf::PdmVoidObjectMethod( self )
|
|
{
|
|
CAF_PDM_InitObject( "Export Flow Characteristics", "", "", "Export flow characteristics computed by flow diagnostics to a text file" );
|
|
|
|
CAF_PDM_InitScriptableField( &m_timeSteps, "TimeSteps", std::vector<int>(), "Time Steps", "", "", "Zero-based time step indices" );
|
|
CAF_PDM_InitScriptableField( &m_injectors, "Injectors", std::vector<QString>(), "Injectors", "", "", "Injector well names" );
|
|
CAF_PDM_InitScriptableField( &m_producers, "Producers", std::vector<QString>(), "Producers", "", "", "Producer well names" );
|
|
CAF_PDM_InitScriptableField( &m_fileName,
|
|
"FileName",
|
|
QString(),
|
|
"File Name",
|
|
"",
|
|
"",
|
|
"File to write. Relative paths are resolved against the project folder." );
|
|
CAF_PDM_InitScriptableField( &m_minimumCommunication, "MinimumCommunication", 0.0, "Minimum Communication" );
|
|
CAF_PDM_InitScriptableField( &m_aquiferCellThreshold, "AquiferCellThreshold", 0.1, "Aquifer Cell Threshold" );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseResultCase_exportFlowCharacteristics::setTimeSteps( const std::vector<int>& timeSteps )
|
|
{
|
|
m_timeSteps = timeSteps;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseResultCase_exportFlowCharacteristics::setInjectors( const std::vector<QString>& injectors )
|
|
{
|
|
m_injectors = injectors;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseResultCase_exportFlowCharacteristics::setProducers( const std::vector<QString>& producers )
|
|
{
|
|
m_producers = producers;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseResultCase_exportFlowCharacteristics::setFileName( const QString& fileName )
|
|
{
|
|
m_fileName = fileName;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseResultCase_exportFlowCharacteristics::setMinimumCommunication( double minimumCommunication )
|
|
{
|
|
m_minimumCommunication = minimumCommunication;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseResultCase_exportFlowCharacteristics::setAquiferCellThreshold( double aquiferCellThreshold )
|
|
{
|
|
m_aquiferCellThreshold = aquiferCellThreshold;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::expected<caf::PdmObjectHandle*, QString> RimEclipseResultCase_exportFlowCharacteristics::execute()
|
|
{
|
|
auto* eclipseCase = self<RimEclipseResultCase>();
|
|
if ( !eclipseCase ) return std::unexpected( "No case is available." );
|
|
|
|
if ( m_fileName().isEmpty() ) return std::unexpected( "No file name specified." );
|
|
|
|
QString exportFileName = m_fileName();
|
|
QFileInfo fi( exportFileName );
|
|
if ( !fi.isAbsolute() )
|
|
{
|
|
QString exportFolder = RiaApplication::instance()->createAbsolutePathFromProjectRelativePath( fi.path() );
|
|
|
|
QDir exportDir( exportFolder );
|
|
if ( !exportDir.exists() && !exportDir.mkpath( "." ) )
|
|
{
|
|
return std::unexpected( QString( "Failed to create folder - %1" ).arg( exportFolder ) );
|
|
}
|
|
|
|
exportFileName = exportFolder + "/" + fi.fileName();
|
|
}
|
|
|
|
RimFlowPlotCollection* flowPlotColl = RimMainPlotCollection::current()->flowPlotCollection();
|
|
if ( !flowPlotColl ) return std::unexpected( "No flow plot collection is available." );
|
|
|
|
RimFlowCharacteristicsPlot* plot = flowPlotColl->defaultFlowCharacteristicsPlot();
|
|
plot->setFromFlowSolution( eclipseCase->defaultFlowDiagSolution() );
|
|
plot->setTimeSteps( m_timeSteps() );
|
|
plot->setInjectorsAndProducers( m_injectors(), m_producers() );
|
|
plot->setAquiferCellThreshold( m_aquiferCellThreshold() );
|
|
plot->setMinimumCommunication( m_minimumCommunication() );
|
|
|
|
plot->loadDataAndUpdate();
|
|
|
|
QFile file( exportFileName );
|
|
if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) )
|
|
{
|
|
return std::unexpected( QString( "Failed to export file - %1" ).arg( exportFileName ) );
|
|
}
|
|
|
|
QTextStream textstream( &file );
|
|
textstream << plot->curveDataAsText();
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimEclipseResultCase, RimEclipseResultCase_createSaturationPressurePlots, "createSaturationPressurePlots" );
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimEclipseResultCase_createSaturationPressurePlots::RimEclipseResultCase_createSaturationPressurePlots( caf::PdmObjectHandle* self )
|
|
: caf::PdmVoidObjectMethod( self )
|
|
{
|
|
CAF_PDM_InitObject( "Create Saturation Pressure Plots",
|
|
"",
|
|
"",
|
|
"Create saturation pressure plots (PRESSURE vs PBUB/PDEW per EQUIL region) for the case" );
|
|
|
|
CAF_PDM_InitScriptableField( &m_timeStep, "TimeStep", 0, "Time Step", "", "", "Zero-based time step index" );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimEclipseResultCase_createSaturationPressurePlots::setTimeStep( int timeStep )
|
|
{
|
|
m_timeStep = timeStep;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::expected<caf::PdmObjectHandle*, QString> RimEclipseResultCase_createSaturationPressurePlots::execute()
|
|
{
|
|
auto* eclipseCase = self<RimEclipseResultCase>();
|
|
if ( !eclipseCase ) return std::unexpected( "No case is available." );
|
|
|
|
auto plots = RicCreateSaturationPressurePlotsFeature::createPlots( eclipseCase, m_timeStep() );
|
|
if ( plots.empty() )
|
|
{
|
|
return std::unexpected( QString( "No saturation pressure plots created for case '%1'. The case must have EQUIL data and the "
|
|
"PRESSURE, PBUB and PDEW results." )
|
|
.arg( eclipseCase->caseUserDescription() ) );
|
|
}
|
|
|
|
if ( auto* collection = RimMainPlotCollection::current()->saturationPressurePlotCollection() )
|
|
{
|
|
collection->updateAllRequiredEditors();
|
|
}
|
|
|
|
if ( RiaGuiApplication::isRunning() )
|
|
{
|
|
RiaGuiApplication::instance()->getOrCreateAndShowMainPlotWindow();
|
|
}
|
|
|
|
return nullptr;
|
|
}
|