mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-26 07:00:17 -05:00
#13281 Improve unit system handling for Eclipse files
- Add shared utility functions in RifEclipseOutputFileTools: - unitValueToEnum(): Convert int unit value to optional enum - determineUnitSystem(): Apply unit preference hierarchy and log warnings - Implement correct unit preference hierarchy: egrid > init > unrst (previously was unrst > init > egrid) - Add validation and warning when different unit systems are detected across files - Enhance grid unit parsing with debug logging to explicitly document support for "m" as abbreviation for "METRES"
This commit is contained in:
1 parent
1ed297e124
commit
37ee50cc9e
5 files changed
+165
-49
No files matched your search
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "RifEclipseOutputFileTools.h"
|
||||
|
||||
#include "RiaLogging.h"
|
||||
#include "RiaOpmParserTools.h"
|
||||
#include "RiaQDateTimeTools.h"
|
||||
#include "RiaStringEncodingTools.h"
|
||||
@@ -951,3 +952,90 @@ void RifEclipseOutputFileTools::extractResultValuesBasedOnPorosityModel( RigEcli
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::optional<RiaDefines::EclipseUnitSystem> RifEclipseOutputFileTools::unitValueToEnum( int unitValue )
|
||||
{
|
||||
if ( unitValue == 1 )
|
||||
return RiaDefines::EclipseUnitSystem::UNITS_METRIC;
|
||||
else if ( unitValue == 2 )
|
||||
return RiaDefines::EclipseUnitSystem::UNITS_FIELD;
|
||||
else if ( unitValue == 3 )
|
||||
return RiaDefines::EclipseUnitSystem::UNITS_LAB;
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaDefines::EclipseUnitSystem RifEclipseOutputFileTools::determineUnitSystem( const std::optional<RiaDefines::EclipseUnitSystem>& egridUnit,
|
||||
const std::optional<RiaDefines::EclipseUnitSystem>& initUnit,
|
||||
const std::optional<RiaDefines::EclipseUnitSystem>& unrstUnit )
|
||||
{
|
||||
// Helper lambda to get unit name string
|
||||
auto getUnitName = []( RiaDefines::EclipseUnitSystem unit ) -> QString
|
||||
{
|
||||
if ( unit == RiaDefines::EclipseUnitSystem::UNITS_METRIC ) return "METRIC";
|
||||
if ( unit == RiaDefines::EclipseUnitSystem::UNITS_FIELD ) return "FIELD";
|
||||
if ( unit == RiaDefines::EclipseUnitSystem::UNITS_LAB ) return "LAB";
|
||||
return "UNKNOWN";
|
||||
};
|
||||
|
||||
// Determine which unit to use based on priority: egrid > init > unrst
|
||||
std::optional<RiaDefines::EclipseUnitSystem> selectedUnit;
|
||||
QString selectedSource;
|
||||
|
||||
if ( egridUnit.has_value() )
|
||||
{
|
||||
selectedUnit = egridUnit;
|
||||
selectedSource = "EGRID";
|
||||
}
|
||||
else if ( initUnit.has_value() )
|
||||
{
|
||||
selectedUnit = initUnit;
|
||||
selectedSource = "INIT";
|
||||
}
|
||||
else if ( unrstUnit.has_value() )
|
||||
{
|
||||
selectedUnit = unrstUnit;
|
||||
selectedSource = "UNRST";
|
||||
}
|
||||
|
||||
// Check for mismatches and warn
|
||||
if ( selectedUnit.has_value() )
|
||||
{
|
||||
// Build list of sources that differ from selected
|
||||
QStringList conflicts;
|
||||
|
||||
if ( egridUnit.has_value() && initUnit.has_value() && egridUnit.value() != initUnit.value() )
|
||||
{
|
||||
conflicts.append( QString( "INIT file has %1" ).arg( getUnitName( initUnit.value() ) ) );
|
||||
}
|
||||
if ( egridUnit.has_value() && unrstUnit.has_value() && egridUnit.value() != unrstUnit.value() )
|
||||
{
|
||||
conflicts.append( QString( "UNRST file has %1" ).arg( getUnitName( unrstUnit.value() ) ) );
|
||||
}
|
||||
if ( !egridUnit.has_value() && initUnit.has_value() && unrstUnit.has_value() && initUnit.value() != unrstUnit.value() )
|
||||
{
|
||||
conflicts.append( QString( "UNRST file has %1" ).arg( getUnitName( unrstUnit.value() ) ) );
|
||||
}
|
||||
|
||||
if ( !conflicts.isEmpty() )
|
||||
{
|
||||
QString warning = QString( "Unit system mismatch detected: Using %1 from %2 file, but %3. "
|
||||
"Please verify your simulation files have consistent unit systems." )
|
||||
.arg( getUnitName( selectedUnit.value() ) )
|
||||
.arg( selectedSource )
|
||||
.arg( conflicts.join( " and " ) );
|
||||
RiaLogging::warning( warning );
|
||||
}
|
||||
|
||||
return selectedUnit.value();
|
||||
}
|
||||
|
||||
// Default to METRIC if no unit found
|
||||
return RiaDefines::EclipseUnitSystem::UNITS_METRIC;
|
||||
}
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
using ecl_file_type = struct ecl_file_struct;
|
||||
@@ -114,6 +115,12 @@ public:
|
||||
std::vector<double>* values,
|
||||
const std::vector<double>& fileValues );
|
||||
|
||||
// Unit system handling utilities
|
||||
static std::optional<RiaDefines::EclipseUnitSystem> unitValueToEnum( int unitValue );
|
||||
static RiaDefines::EclipseUnitSystem determineUnitSystem( const std::optional<RiaDefines::EclipseUnitSystem>& egridUnit,
|
||||
const std::optional<RiaDefines::EclipseUnitSystem>& initUnit,
|
||||
const std::optional<RiaDefines::EclipseUnitSystem>& unrstUnit );
|
||||
|
||||
private:
|
||||
static void getDayMonthYear( const ecl_kw_type* intehead_kw, int* day, int* month, int* year );
|
||||
static RifEclipseReportKeywords createReportStepsMetaData( const std::vector<ecl_file_type*>& ecl_files );
|
||||
|
||||
@@ -895,34 +895,30 @@ void RifReaderEclipseOutput::buildMetaData( ecl_grid_type* grid )
|
||||
|
||||
// Unit system
|
||||
{
|
||||
// Default units type is METRIC
|
||||
RiaDefines::EclipseUnitSystem unitsType = RiaDefines::EclipseUnitSystem::UNITS_METRIC;
|
||||
int unitsTypeValue;
|
||||
std::optional<RiaDefines::EclipseUnitSystem> egridUnit;
|
||||
std::optional<RiaDefines::EclipseUnitSystem> initUnit;
|
||||
std::optional<RiaDefines::EclipseUnitSystem> unrstUnit;
|
||||
|
||||
// Read from grid file
|
||||
if ( grid )
|
||||
{
|
||||
egridUnit = RifEclipseOutputFileTools::unitValueToEnum( ecl_grid_get_unit_system( grid ) );
|
||||
}
|
||||
|
||||
// Read from init file
|
||||
if ( m_ecl_init_file )
|
||||
{
|
||||
initUnit = RifEclipseOutputFileTools::unitValueToEnum( RifEclipseOutputFileTools::readUnitsType( m_ecl_init_file ) );
|
||||
}
|
||||
|
||||
// Read from restart file
|
||||
if ( m_dynamicResultsAccess.notNull() )
|
||||
{
|
||||
unitsTypeValue = m_dynamicResultsAccess->readUnitsType();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_ecl_init_file )
|
||||
{
|
||||
unitsTypeValue = RifEclipseOutputFileTools::readUnitsType( m_ecl_init_file );
|
||||
}
|
||||
else
|
||||
{
|
||||
unitsTypeValue = ecl_grid_get_unit_system( grid );
|
||||
}
|
||||
unrstUnit = RifEclipseOutputFileTools::unitValueToEnum( m_dynamicResultsAccess->readUnitsType() );
|
||||
}
|
||||
|
||||
if ( unitsTypeValue == 2 )
|
||||
{
|
||||
unitsType = RiaDefines::EclipseUnitSystem::UNITS_FIELD;
|
||||
}
|
||||
else if ( unitsTypeValue == 3 )
|
||||
{
|
||||
unitsType = RiaDefines::EclipseUnitSystem::UNITS_LAB;
|
||||
}
|
||||
// Determine final unit system using hierarchy (egrid > init > unrst) with warnings
|
||||
RiaDefines::EclipseUnitSystem unitsType = RifEclipseOutputFileTools::determineUnitSystem( egridUnit, initUnit, unrstUnit );
|
||||
m_eclipseCaseData->setUnitsType( unitsType );
|
||||
}
|
||||
|
||||
|
||||
@@ -189,13 +189,30 @@ bool RifReaderOpmCommon::importGrid( RigMainGrid* mainGrid, RigEclipseCaseData*
|
||||
mainGrid->setDualPorosity( opmGrid.porosity_mode() > 0 );
|
||||
|
||||
// assign grid unit, if found (1 = Metric, 2 = Field, 3 = Lab)
|
||||
// Note: Accepts "m" or "M" as abbreviation for "METRES" (METRIC units)
|
||||
auto gridUnitStr = RiaStdStringTools::toUpper( opmGrid.grid_unit() );
|
||||
if ( gridUnitStr.starts_with( 'M' ) )
|
||||
{
|
||||
m_gridUnit = 1;
|
||||
RiaLogging::debug(
|
||||
QString( "Grid unit from EGRID file: '%1' (interpreted as METRIC)" ).arg( QString::fromStdString( opmGrid.grid_unit() ) ) );
|
||||
}
|
||||
else if ( gridUnitStr.starts_with( 'F' ) )
|
||||
{
|
||||
m_gridUnit = 2;
|
||||
RiaLogging::debug(
|
||||
QString( "Grid unit from EGRID file: '%1' (interpreted as FIELD)" ).arg( QString::fromStdString( opmGrid.grid_unit() ) ) );
|
||||
}
|
||||
else if ( gridUnitStr.starts_with( 'C' ) )
|
||||
{
|
||||
m_gridUnit = 3;
|
||||
RiaLogging::debug(
|
||||
QString( "Grid unit from EGRID file: '%1' (interpreted as LAB)" ).arg( QString::fromStdString( opmGrid.grid_unit() ) ) );
|
||||
}
|
||||
else if ( !gridUnitStr.empty() )
|
||||
{
|
||||
RiaLogging::warning( QString( "Unknown grid unit from EGRID file: '%1'" ).arg( QString::fromStdString( opmGrid.grid_unit() ) ) );
|
||||
}
|
||||
|
||||
auto totalCellCount = opmGrid.totalNumberOfCells();
|
||||
auto globalMatrixActiveSize = opmGrid.activeCells();
|
||||
@@ -925,12 +942,23 @@ void RifReaderOpmCommon::buildMetaData( RigEclipseCaseData* eclipseCaseData, caf
|
||||
|
||||
// Unit system
|
||||
{
|
||||
// Default units type is METRIC, look in restart file, then init file and then grid file until we find something
|
||||
RiaDefines::EclipseUnitSystem unitsType = RiaDefines::EclipseUnitSystem::UNITS_METRIC;
|
||||
int unitsTypeValue = -1;
|
||||
std::optional<RiaDefines::EclipseUnitSystem> egridUnit = RifEclipseOutputFileTools::unitValueToEnum( m_gridUnit );
|
||||
std::optional<RiaDefines::EclipseUnitSystem> initUnit;
|
||||
std::optional<RiaDefines::EclipseUnitSystem> unrstUnit;
|
||||
|
||||
namespace VI = Opm::RestartIO::Helpers::VectorItems;
|
||||
|
||||
// Read from init file
|
||||
if ( m_initFile != nullptr )
|
||||
{
|
||||
const auto& intHeader = m_initFile->getInitData<int>( "INTEHEAD" );
|
||||
if ( intHeader.size() > 2 )
|
||||
{
|
||||
initUnit = RifEclipseOutputFileTools::unitValueToEnum( intHeader[2] );
|
||||
}
|
||||
}
|
||||
|
||||
// Read from restart file
|
||||
if ( m_restartFile != nullptr )
|
||||
{
|
||||
for ( auto reportStep : m_restartFile->listOfReportStepNumbers() )
|
||||
@@ -940,35 +968,15 @@ void RifReaderOpmCommon::buildMetaData( RigEclipseCaseData* eclipseCaseData, caf
|
||||
const auto& intHeader = m_restartFile->getRestartData<int>( "INTEHEAD", reportStep );
|
||||
if ( intHeader.size() > VI::intehead::UNIT )
|
||||
{
|
||||
unitsTypeValue = intHeader[VI::intehead::UNIT];
|
||||
unrstUnit = RifEclipseOutputFileTools::unitValueToEnum( intHeader[VI::intehead::UNIT] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( unitsTypeValue < 0 )
|
||||
{
|
||||
if ( m_initFile != nullptr )
|
||||
{
|
||||
const auto& intHeader = m_initFile->getInitData<int>( "INTEHEAD" );
|
||||
if ( intHeader.size() > 2 ) unitsTypeValue = intHeader[2];
|
||||
}
|
||||
}
|
||||
|
||||
if ( unitsTypeValue < 0 )
|
||||
{
|
||||
unitsTypeValue = m_gridUnit;
|
||||
}
|
||||
|
||||
if ( unitsTypeValue == 2 )
|
||||
{
|
||||
unitsType = RiaDefines::EclipseUnitSystem::UNITS_FIELD;
|
||||
}
|
||||
else if ( unitsTypeValue == 3 )
|
||||
{
|
||||
unitsType = RiaDefines::EclipseUnitSystem::UNITS_LAB;
|
||||
}
|
||||
// Determine final unit system using hierarchy (egrid > init > unrst) with warnings
|
||||
RiaDefines::EclipseUnitSystem unitsType = RifEclipseOutputFileTools::determineUnitSystem( egridUnit, initUnit, unrstUnit );
|
||||
m_eclipseCaseData->setUnitsType( unitsType );
|
||||
}
|
||||
|
||||
|
||||
@@ -77,13 +77,30 @@ bool RifReaderOpmCommonActive::importGrid( RigMainGrid* /* mainGrid*/, RigEclips
|
||||
activeGrid->setDualPorosity( opmGrid.porosity_mode() > 0 );
|
||||
|
||||
// assign grid unit, if found (1 = Metric, 2 = Field, 3 = Lab)
|
||||
// Note: Accepts "m" or "M" as abbreviation for "METRES" (METRIC units)
|
||||
auto gridUnitStr = RiaStdStringTools::toUpper( opmGrid.grid_unit() );
|
||||
if ( gridUnitStr.starts_with( 'M' ) )
|
||||
{
|
||||
m_gridUnit = 1;
|
||||
RiaLogging::debug(
|
||||
QString( "Grid unit from EGRID file: '%1' (interpreted as METRIC)" ).arg( QString::fromStdString( opmGrid.grid_unit() ) ) );
|
||||
}
|
||||
else if ( gridUnitStr.starts_with( 'F' ) )
|
||||
{
|
||||
m_gridUnit = 2;
|
||||
RiaLogging::debug(
|
||||
QString( "Grid unit from EGRID file: '%1' (interpreted as FIELD)" ).arg( QString::fromStdString( opmGrid.grid_unit() ) ) );
|
||||
}
|
||||
else if ( gridUnitStr.starts_with( 'C' ) )
|
||||
{
|
||||
m_gridUnit = 3;
|
||||
RiaLogging::debug(
|
||||
QString( "Grid unit from EGRID file: '%1' (interpreted as LAB)" ).arg( QString::fromStdString( opmGrid.grid_unit() ) ) );
|
||||
}
|
||||
else if ( !gridUnitStr.empty() )
|
||||
{
|
||||
RiaLogging::warning( QString( "Unknown grid unit from EGRID file: '%1'" ).arg( QString::fromStdString( opmGrid.grid_unit() ) ) );
|
||||
}
|
||||
|
||||
auto totalCellCount = opmGrid.totalNumberOfCells();
|
||||
auto totalActiveCellCount = opmGrid.totalActiveCells();
|
||||
|
||||
Reference in new issue
Block a user