Update error handling in Rimc* classes.

This commit is contained in:
Kristian Bendiksen
2025-05-12 17:31:48 +02:00
parent 135695fcb5
commit 752d4efc42
17 changed files with 136 additions and 143 deletions
@@ -103,14 +103,16 @@ void RicCreateEnsembleSurfaceFeature::executeCommand( const RicCreateEnsembleSur
auto fileName = fileNames[i];
// Not possible to use structured bindings here due to a bug in clang
auto surfaceResult = RimcCommandRouter_extractSurfaces::extractSurfaces( fileName, layers );
auto isOk = surfaceResult.first;
auto surfaceFileNames = surfaceResult.second;
auto surfaceResult = RimcCommandRouter_extractSurfaces::extractSurfaces( fileName, layers );
if ( surfaceResult.has_value() )
{
auto surfaceFileNames = surfaceResult.value();
#pragma omp critical( RicCreateEnsembleSurfaceFeature )
{
auto task = progress.task( QString( "Extracting surfaces for %1" ).arg( fileName ) );
if ( isOk ) allSurfaceFileNames << surfaceFileNames;
{
auto task = progress.task( QString( "Extracting surfaces for %1" ).arg( fileName ) );
allSurfaceFileNames << surfaceFileNames;
}
}
}
progress.setProgress( fileNames.size() );
@@ -76,12 +76,12 @@ bool RimCornerPointCase::openEclipseGridFile()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<RimCornerPointCase*, QString> RimCornerPointCase::createFromCoordinatesArray( const int nx,
const int ny,
const int nz,
const std::vector<float>& coord,
const std::vector<float>& zcorn,
const std::vector<float>& actnum )
std::expected<RimCornerPointCase*, QString> RimCornerPointCase::createFromCoordinatesArray( const int nx,
const int ny,
const int nz,
const std::vector<float>& coord,
const std::vector<float>& zcorn,
const std::vector<float>& actnum )
{
CAF_ASSERT( nx > 0 );
CAF_ASSERT( ny > 0 );
@@ -92,20 +92,20 @@ std::pair<RimCornerPointCase*, QString> RimCornerPointCase::createFromCoordinate
size_t ntot = nx * ny * nz;
if ( coord.size() != ncoord )
return { nullptr, QString( "Wrong size of coord array. Expected %1, but got %2" ).arg( ncoord ).arg( coord.size() ) };
return std::unexpected( QString( "Wrong size of coord array. Expected %1, but got %2" ).arg( ncoord ).arg( coord.size() ) );
if ( zcorn.size() != nzcorn )
return { nullptr, QString( "Wrong size of zcorn array. Expected %1, but got %2" ).arg( nzcorn ).arg( zcorn.size() ) };
return std::unexpected( QString( "Wrong size of zcorn array. Expected %1, but got %2" ).arg( nzcorn ).arg( zcorn.size() ) );
if ( actnum.size() != ntot )
return { nullptr, QString( "Wrong size of actnum array. Expected %1, but got %2" ).arg( ntot ).arg( actnum.size() ) };
return std::unexpected( QString( "Wrong size of actnum array. Expected %1, but got %2" ).arg( ntot ).arg( actnum.size() ) );
auto cornerPointCase = new RimCornerPointCase;
buildGrid( *cornerPointCase->eclipseCaseData(), nx, ny, nz, coord, zcorn, actnum );
cornerPointCase->ensureFaultDataIsComputed();
return { cornerPointCase, "" };
return cornerPointCase;
}
//--------------------------------------------------------------------------------------------------
@@ -22,6 +22,8 @@
#include "cafPdmObject.h"
#include <expected>
//==================================================================================================
//
//
@@ -41,12 +43,12 @@ public:
QString locationOnDisc() const override;
static std::pair<RimCornerPointCase*, QString> createFromCoordinatesArray( const int nx,
const int ny,
const int nz,
const std::vector<float>& coord,
const std::vector<float>& zcorn,
const std::vector<float>& actnum );
static std::expected<RimCornerPointCase*, QString> createFromCoordinatesArray( const int nx,
const int ny,
const int nz,
const std::vector<float>& coord,
const std::vector<float>& zcorn,
const std::vector<float>& actnum );
protected:
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
@@ -31,8 +31,6 @@
#include <QDir>
#include <QFileInfo>
#include <memory>
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimCommandRouter, RimcCommandRouter_extractSurfaces, "ExtractSurfaces" );
//--------------------------------------------------------------------------------------------------
@@ -56,19 +54,22 @@ RimcCommandRouter_extractSurfaces::RimcCommandRouter_extractSurfaces( caf::PdmOb
//--------------------------------------------------------------------------------------------------
std::expected<caf::PdmObjectHandle*, QString> RimcCommandRouter_extractSurfaces::execute()
{
extractSurfaces( m_gridModelFilename, m_layers(), m_minimumI(), m_maximumI(), m_minimumJ(), m_maximumJ() );
return nullptr;
auto result = extractSurfaces( m_gridModelFilename, m_layers(), m_minimumI(), m_maximumI(), m_minimumJ(), m_maximumJ() );
if ( result.has_value() )
return nullptr;
else
return std::unexpected( result.error() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<bool, QStringList> RimcCommandRouter_extractSurfaces::extractSurfaces( const QString& gridModelFilename,
const std::vector<int>& layers,
int minI,
int maxI,
int minJ,
int maxJ )
std::expected<QStringList, QString> RimcCommandRouter_extractSurfaces::extractSurfaces( const QString& gridModelFilename,
const std::vector<int>& layers,
int minI,
int maxI,
int minJ,
int maxJ )
{
QStringList surfaceFileNames;
@@ -132,8 +133,7 @@ std::pair<bool, QStringList> RimcCommandRouter_extractSurfaces::extractSurfaces(
{
if ( !fi.absoluteDir().mkpath( surfaceExportDirName ) )
{
RiaLogging::error( "Unable to create directory for surface export: " + fi.absoluteDir().absolutePath() );
return std::make_pair( false, surfaceFileNames );
return std::unexpected( "Unable to create directory for surface export: " + fi.absoluteDir().absolutePath() );
}
}
@@ -143,8 +143,7 @@ std::pair<bool, QStringList> RimcCommandRouter_extractSurfaces::extractSurfaces(
// TODO: Add more info in surface comment
if ( !RifSurfaceExporter::writeGocadTSurfFile( surfaceFilename, "Surface comment", vertices, triangleIndices ) )
{
RiaLogging::error( "Failed to export surface data to " + surfaceFilename );
return std::make_pair( false, surfaceFileNames );
return std::unexpected( "Failed to export surface data to " + surfaceFilename );
}
else
{
@@ -153,12 +152,11 @@ std::pair<bool, QStringList> RimcCommandRouter_extractSurfaces::extractSurfaces(
}
}
return std::make_pair( true, surfaceFileNames );
return surfaceFileNames;
}
catch ( ... )
{
RiaLogging::error( "Error during creation of surface data for model " + gridModelFilename );
return std::make_pair( false, surfaceFileNames );
return std::unexpected( "Error during creation of surface data for model " + gridModelFilename );
}
}
@@ -22,12 +22,10 @@
#include "cafPdmField.h"
#include "cvfVector3.h"
#include <QString>
#include <QStringList>
#include <memory>
#include <expected>
//==================================================================================================
///
@@ -41,13 +39,13 @@ public:
std::expected<caf::PdmObjectHandle*, QString> execute() override;
static bool readMinMaxLayerFromGridFile( const QString& gridFileName, int& minK, int& maxK );
static std::pair<bool, QStringList> extractSurfaces( const QString& gridModelFileName,
const std::vector<int>& layers,
int minI = -1,
int maxI = -1,
int minJ = -1,
int maxJ = -1 );
static bool readMinMaxLayerFromGridFile( const QString& gridFileName, int& minK, int& maxK );
static std::expected<QStringList, QString> extractSurfaces( const QString& gridModelFileName,
const std::vector<int>& layers,
int minI = -1,
int maxI = -1,
int minJ = -1,
int maxJ = -1 );
private:
caf::PdmField<QString> m_gridModelFilename;
@@ -53,13 +53,12 @@ std::expected<caf::PdmObjectHandle*, QString> RimcEclipseStatisticsCase_setSourc
{
auto eclipseCase = self<RimEclipseStatisticsCase>();
eclipseCase->setSourceProperties( myEnum, m_propertyNames );
return nullptr;
}
else
{
RiaLogging::error( "Wrong result type. Supported types are DYNAMIC_NATIVE, STATIC_NATIVE, INPUT_PROPERTY, GENERATED" );
return std::unexpected( "Wrong result type. Supported types are DYNAMIC_NATIVE, STATIC_NATIVE, INPUT_PROPERTY, GENERATED" );
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
@@ -48,7 +48,7 @@ std::expected<caf::PdmObjectHandle*, QString> RimcElasticProperties_addPropertyS
RimElasticProperties* elasticProperties = self<RimElasticProperties>();
RimElasticPropertyScalingCollection* scalingColl = elasticProperties->scalingCollection();
if ( !scalingColl ) return nullptr;
if ( !scalingColl ) return std::unexpected( "No scaling collection found" );
RimElasticPropertyScaling* propertyScaling = new RimElasticPropertyScaling;
propertyScaling->setFormation( m_formation() );
@@ -47,13 +47,12 @@ RimcFishbonesCollection_appendFishbones::RimcFishbonesCollection_appendFishbones
std::expected<caf::PdmObjectHandle*, QString> RimcFishbonesCollection_appendFishbones::execute()
{
auto fishbonesCollection = self<RimFishbonesCollection>();
if ( !fishbonesCollection ) return nullptr;
if ( !fishbonesCollection ) return std::unexpected( "No fishbones collection found" );
if ( m_subLocations().empty() )
{
RiaLogging::error(
return std::unexpected(
"Sub locations are empty, expected list of float values defining measured depths. Cannot create fishbones object." );
return nullptr;
}
auto* fishbonesObject = fishbonesCollection->appendFishbonesSubsAtLocations( m_subLocations(), m_drillingType() );
@@ -46,8 +46,7 @@ std::expected<caf::PdmObjectHandle*, QString> RimcFractureTemplate_setScaleFacto
{
if ( m_halfLength() <= 0.0 || m_height() <= 0.0 || m_dFactor() <= 0.0 || m_conductivity() <= 0.0 )
{
RiaLogging::error( "Invalid scale factors." );
return nullptr;
return std::unexpected( "Invalid scale factors." );
}
RimFractureTemplate* fractureTemplate = self<RimFractureTemplate>();
@@ -232,7 +232,7 @@ std::expected<caf::PdmObjectHandle*, QString> RimcExtrudedCurveIntersection_geom
return triangleGeometry;
}
return new RimcTriangleGeometry;
return std::unexpected( "No intersection geometry found." );
}
//--------------------------------------------------------------------------------------------------
@@ -307,9 +307,7 @@ std::expected<caf::PdmObjectHandle*, QString> RimcExtrudedCurveIntersection_geom
auto eclView = intersection->firstAncestorOfType<RimEclipseView>();
if ( !eclView )
{
RiaLogging::error( "No Eclipse view found. Extraction of intersection result is only supported for "
"Eclipse view." );
return nullptr;
return std::unexpected( "No Eclipse view found. Extraction of intersection result is only supported for Eclipse view." );
}
RimEclipseResultDefinition* eclResultDef = nullptr;
@@ -337,7 +335,7 @@ std::expected<caf::PdmObjectHandle*, QString> RimcExtrudedCurveIntersection_geom
return RimcDataContainerDouble::create( values );
}
return new RimcDataContainerDouble();
return std::unexpected( "No intersection geometry result found." );
}
//--------------------------------------------------------------------------------------------------
@@ -257,15 +257,12 @@ std::expected<caf::PdmObjectHandle*, QString> RimProject_createGridFromKeyValues
RiaLogging::info( "Creating grid from key values" );
QString name = m_name();
if ( name.isEmpty() )
{
RiaLogging::error( "Empty name not allowed" );
return nullptr;
}
if ( name.isEmpty() ) return std::unexpected( "Empty name not allowed" );
int nx = m_nx();
int ny = m_ny();
int nz = m_nz();
if ( nx <= 0 || ny <= 0 || nz <= 0 ) return std::unexpected( "Invalid grid size. nx, ny and nz must be positive." );
RiaLogging::info( QString( "Grid dimensions: [%1 %2 %3]" ).arg( nx ).arg( ny ).arg( nz ) );
RiaLogging::info( QString( "Coord: %1" ).arg( m_coordKey() ) );
@@ -304,27 +301,28 @@ std::expected<caf::PdmObjectHandle*, QString> RimProject_createGridFromKeyValues
std::vector<float> actnum = convertToFloatVector( keyValueStore->get( m_actnumKey().toStdString() ) );
if ( coord.empty() || zcorn.empty() || actnum.empty() )
{
RiaLogging::error( "Found unexcepted empty coord, zcorn or actnum array." );
return nullptr;
return std::unexpected( "Found unexcepted empty coord, zcorn or actnum array." );
}
auto [grid, errorMessage] = RimCornerPointCase::createFromCoordinatesArray( nx, ny, nz, coord, zcorn, actnum );
if ( grid )
RimProject* project = RimProject::current();
if ( !project ) return std::unexpected( "Invalid project." );
RimEclipseCaseCollection* analysisModels = project->activeOilField() ? project->activeOilField()->analysisModels() : nullptr;
if ( !analysisModels ) return std::unexpected( "Missing analysis models." );
auto result = RimCornerPointCase::createFromCoordinatesArray( nx, ny, nz, coord, zcorn, actnum );
if ( !result.has_value() ) return result;
RimCornerPointCase* grid = result.value();
grid->setCustomCaseName( name );
project->assignCaseIdToCase( grid );
analysisModels->cases.push_back( grid );
RimMainPlotCollection::current()->ensureDefaultFlowPlotsAreCreated();
if ( RimEclipseView* riv = grid->createAndAddReservoirView() )
{
RimProject* project = RimProject::current();
if ( !project ) return nullptr;
grid->setCustomCaseName( name );
project->assignCaseIdToCase( grid );
RimEclipseCaseCollection* analysisModels = project->activeOilField() ? project->activeOilField()->analysisModels() : nullptr;
if ( !analysisModels ) return nullptr;
analysisModels->cases.push_back( grid );
RimMainPlotCollection::current()->ensureDefaultFlowPlotsAreCreated();
RimEclipseView* riv = grid->createAndAddReservoirView();
riv->loadDataAndUpdate();
if ( !riv->cellResult()->hasResult() )
@@ -339,10 +337,6 @@ std::expected<caf::PdmObjectHandle*, QString> RimProject_createGridFromKeyValues
if ( RiuMainWindow::instance() ) RiuMainWindow::instance()->selectAsCurrentItem( riv->cellResult() );
}
}
else
{
RiaLogging::error( QString( "Creating corner point grid failed: %1" ).arg( errorMessage ) );
}
keyValueStore->remove( m_coordKey().toStdString() );
keyValueStore->remove( m_zcornKey().toStdString() );
@@ -64,9 +64,12 @@ std::expected<caf::PdmObjectHandle*, QString> RimcStimPlanModelCollection_append
stimPlanModel->setMD( m_md() );
stimPlanModel->setStimPlanModelTemplate( m_stimPlanModelTemplate() );
stimPlanModelCollection->updateAllRequiredEditors();
return stimPlanModel;
}
else
{
return std::unexpected( "Unable to add StimPlan model." );
}
return stimPlanModel;
}
//--------------------------------------------------------------------------------------------------
@@ -198,38 +198,39 @@ RimSummaryCase_resampleValues::RimSummaryCase_resampleValues( caf::PdmObjectHand
//--------------------------------------------------------------------------------------------------
std::expected<caf::PdmObjectHandle*, QString> RimSummaryCase_resampleValues::execute()
{
auto* summaryCase = self<RimSummaryCase>();
RifSummaryReaderInterface* sumReader = summaryCase->summaryReader();
auto* summaryCase = self<RimSummaryCase>();
RifSummaryReaderInterface* sumReader = summaryCase->summaryReader();
if ( !sumReader )
{
return std::unexpected( "No reader found for summary case." );
}
auto adr = RifEclipseSummaryAddress::fromEclipseTextAddressParseErrorTokens( m_addressString().toStdString() );
auto dataObject = new RimcSummaryResampleData();
if ( sumReader )
auto [isOk, values] = sumReader->values( adr );
if ( !isOk )
{
auto [isOk, values] = sumReader->values( adr );
if ( !isOk )
{
// Error message
}
return std::unexpected( QString( "No values found for address: '%1'" ).arg( m_addressString ) );
}
const auto& timeValues = sumReader->timeSteps( adr );
const auto& timeValues = sumReader->timeSteps( adr );
QString periodString = m_resamplingPeriod().trimmed();
RiaDefines::DateTimePeriod period = RiaDefines::DateTimePeriodEnum::fromText( periodString );
QString periodString = m_resamplingPeriod().trimmed();
RiaDefines::DateTimePeriod period = RiaDefines::DateTimePeriodEnum::fromText( periodString );
if ( period != RiaDefines::DateTimePeriod::NONE )
{
auto [resampledTimeSteps, resampledValues] = RiaSummaryTools::resampledValuesForPeriod( adr, timeValues, values, period );
auto dataObject = new RimcSummaryResampleData();
if ( period != RiaDefines::DateTimePeriod::NONE )
{
auto [resampledTimeSteps, resampledValues] = RiaSummaryTools::resampledValuesForPeriod( adr, timeValues, values, period );
dataObject->m_timeValues = resampledTimeSteps;
dataObject->m_doubleValues = resampledValues;
}
else
{
dataObject->m_timeValues = timeValues;
dataObject->m_doubleValues = values;
}
dataObject->m_timeValues = resampledTimeSteps;
dataObject->m_doubleValues = resampledValues;
}
else
{
dataObject->m_timeValues = timeValues;
dataObject->m_doubleValues = values;
}
return dataObject;
@@ -38,7 +38,7 @@ CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimSurface, RimcSurface_exportToFile, "Export
RimcSurface_exportToFile::RimcSurface_exportToFile( caf::PdmObjectHandle* self )
: caf::PdmObjectMethod( self )
{
CAF_PDM_InitObject( "Export Surface To fiole", "", "", "Export a surface to file" );
CAF_PDM_InitObject( "Export Surface To file", "", "", "Export a surface to file" );
CAF_PDM_InitScriptableFieldNoDefault( &m_fileName, "FileName", "", "", "", "Filename to export surface to" );
}
@@ -48,21 +48,23 @@ RimcSurface_exportToFile::RimcSurface_exportToFile( caf::PdmObjectHandle* self )
std::expected<caf::PdmObjectHandle*, QString> RimcSurface_exportToFile::execute()
{
RimSurface* surface = self<RimSurface>();
auto dataObject = new RimcDataContainerString();
if ( surface )
if ( !surface )
{
RigSurface* surfaceData = surface->surfaceData();
RifSurfaceExporter::writeGocadTSurfFile( m_fileName(),
surface->userDescription(),
surfaceData->vertices(),
surfaceData->triangleIndices() );
dataObject->m_stringValues = { m_fileName() };
return std::unexpected( "No surface found" );
}
RigSurface* surfaceData = surface->surfaceData();
if ( !RifSurfaceExporter::writeGocadTSurfFile( m_fileName(),
surface->userDescription(),
surfaceData->vertices(),
surfaceData->triangleIndices() ) )
{
return std::unexpected( QString( "Failed to write surface to file: '%1'" ).arg( m_fileName() ) );
}
auto dataObject = new RimcDataContainerString();
dataObject->m_stringValues = { m_fileName() };
return dataObject;
}
@@ -54,7 +54,7 @@ std::expected<caf::PdmObjectHandle*, QString> RimcWellLogPlot_newWellLogTrack::e
{
RimWellLogPlot* wellLogPlot = self<RimWellLogPlot>();
if ( !wellLogPlot ) return nullptr;
if ( !wellLogPlot ) return std::unexpected( "No well log plot found" );
return createWellLogTrack( wellLogPlot, m_case(), m_wellPath(), m_title() );
}
@@ -18,13 +18,13 @@ try:
except rips.RipsError as e:
print("Expected Server Exception Received while loading case: ", e)
# Try loading well paths from a non-existing folder. We should get a grpc.RpcError exception from the server
# Try loading well paths from a non-existing folder. We should get a rips.RipsError exception from the server
try:
well_path_files = resinsight.project.import_well_paths(
well_path_folder="NONSENSE/NONSENSE"
)
except rips.RipsError as e:
print("Expected Server Exception Received while loading wellpaths: ", e)
print("Server Exception Received while loading wellpaths: ", e)
# Try loading well paths from an existing but empty folder. We should get a warning.
try:
@@ -55,12 +55,12 @@ if case is not None:
# Add another value, so this is outside the bounds of the active cell result storage
results.append(1.0)
# This time we should get a grpc.RpcError exception, which is a server side error.
# This time we should get a rips.RipsError exception.
try:
case.set_active_cell_property(results, "GENERATED", "POROAPPENDED", 0)
print("Everything went well??")
except RipsError as e:
print("Expected Server Exception Received: ", e)
print("Server Exception Received: ", e)
except IndexError:
print("Got index out of bounds error. This shouldn't happen here")
@@ -6,6 +6,8 @@ import rips
import dataroot
import pytest
def test_10k(rips_instance, initialize_test):
case_root_path = dataroot.PATH + "/TEST10K_FLT_LGR_NNC"
@@ -80,13 +82,9 @@ def test_empty_well_intersection(rips_instance, initialize_test):
well_path_intersection.well_path = None
well_path_intersection.update()
# Test with empty geometry. This will also test that an empty list in CAF is converted to an empty list in Python
# See __makelist in pdmobject.py
geometry = well_path_intersection.geometry()
coord_count = len(geometry.x_coords)
assert coord_count == 0
# Test with empty geometry.
with pytest.raises(rips.RipsError):
well_path_intersection.geometry()
# One value per triangle
geometry_result_values = well_path_intersection.geometry_result()
result_count = len(geometry_result_values.values)
assert result_count == 0
with pytest.raises(rips.RipsError):
well_path_intersection.geometry_result()