mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-24 14:17:52 -05:00
#14964: Use correct depth unit when creating RFT plots
Read the summary unit system from SMSPEC INTEHEAD, and fall back to vector units for ESMRY files without SMSPEC. The unit system is read on first request to keep summary import fast. Ensembles use the same realization as for addresses. New RFT plots get the depth unit from their data sources.
This commit is contained in:
1 parent
eb66255a70
commit
9229e48191
12 files changed
+230
-8
No files matched your search
@@ -146,6 +146,13 @@ std::vector<RiaDefines::EclipseUnitSystem> RifDataSourceForRftPlt::availableUnit
|
||||
systems.push_back( m_eclCase->eclipseCaseData()->unitsType() );
|
||||
}
|
||||
|
||||
auto addIfKnown = [&systems]( RiaDefines::EclipseUnitSystem system )
|
||||
{
|
||||
if ( system != RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN ) systems.push_back( system );
|
||||
};
|
||||
if ( m_summaryCase ) addIfKnown( m_summaryCase->unitsSystem() );
|
||||
if ( m_ensemble ) addIfKnown( m_ensemble->unitSystem() );
|
||||
|
||||
if ( m_wellLogFile && m_wellLogFile->wellLogData() )
|
||||
{
|
||||
auto eclipseUnit = RiaDefines::fromDepthUnit( m_wellLogFile->wellLogData()->depthUnit() );
|
||||
|
||||
@@ -132,7 +132,20 @@ RiaDefines::EclipseUnitSystem RifMultipleSummaryReaders::unitSystem() const
|
||||
{
|
||||
CAF_ASSERT( !m_readers.empty() );
|
||||
|
||||
return m_readers.at( 0 )->unitSystem();
|
||||
// Readers without unit information are ignored, conflicting readers give an unknown unit system
|
||||
auto unitSystem = RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN;
|
||||
for ( const auto& reader : m_readers )
|
||||
{
|
||||
auto readerUnitSystem = reader->unitSystem();
|
||||
if ( readerUnitSystem == RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN ) continue;
|
||||
|
||||
if ( unitSystem == RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN )
|
||||
unitSystem = readerUnitSystem;
|
||||
else if ( unitSystem != readerUnitSystem )
|
||||
return RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN;
|
||||
}
|
||||
|
||||
return unitSystem;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -179,6 +179,9 @@ bool RifOpmCommonEclipseSummary::open( const QString& fileName, bool includeRest
|
||||
populateTimeSteps();
|
||||
if ( isLoggingEnabled ) RiaLogging::logElapsedTime( "Completed populateTimeSteps", timeBeforeTimeSteps );
|
||||
|
||||
m_fileName = fileName;
|
||||
m_unitSystem = std::nullopt;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -251,8 +254,55 @@ std::string RifOpmCommonEclipseSummary::unitName( const RifEclipseSummaryAddress
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaDefines::EclipseUnitSystem RifOpmCommonEclipseSummary::unitSystem() const
|
||||
{
|
||||
// TODO: Not implemented
|
||||
return RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN;
|
||||
if ( !m_unitSystem ) m_unitSystem = detectUnitSystem();
|
||||
return *m_unitSystem;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaDefines::EclipseUnitSystem RifOpmCommonEclipseSummary::detectUnitSystem() const
|
||||
{
|
||||
auto smspecFileName = RifOpmSummaryTools::smspecSummaryFilename( m_fileName );
|
||||
auto unitSystem = RifOpmSummaryTools::readUnitSystem( smspecFileName );
|
||||
|
||||
// ESMRY files can be imported without SMSPEC, and ESMRY has no unit system flag
|
||||
if ( unitSystem == RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN && m_enhancedReader ) return unitSystemFromVectorUnits();
|
||||
|
||||
return unitSystem;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Units from different systems can be mixed (PVT-M, user defined vectors), so only accept a single match
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaDefines::EclipseUnitSystem RifOpmCommonEclipseSummary::unitSystemFromVectorUnits() const
|
||||
{
|
||||
static const std::map<std::string, RiaDefines::EclipseUnitSystem> unitToSystem = {
|
||||
{ "PSIA", RiaDefines::EclipseUnitSystem::UNITS_FIELD },
|
||||
{ "STB", RiaDefines::EclipseUnitSystem::UNITS_FIELD },
|
||||
{ "STB/DAY", RiaDefines::EclipseUnitSystem::UNITS_FIELD },
|
||||
{ "MSCF/DAY", RiaDefines::EclipseUnitSystem::UNITS_FIELD },
|
||||
{ "BARSA", RiaDefines::EclipseUnitSystem::UNITS_METRIC },
|
||||
{ "SM3", RiaDefines::EclipseUnitSystem::UNITS_METRIC },
|
||||
{ "SM3/DAY", RiaDefines::EclipseUnitSystem::UNITS_METRIC },
|
||||
{ "ATMA", RiaDefines::EclipseUnitSystem::UNITS_LAB },
|
||||
{ "SCC", RiaDefines::EclipseUnitSystem::UNITS_LAB },
|
||||
};
|
||||
|
||||
auto detected = RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN;
|
||||
for ( const auto& keyword : m_enhancedReader->keywordList() )
|
||||
{
|
||||
const auto unit = std::string( RiaStdStringTools::trimString( m_enhancedReader->get_unit( keyword ) ) );
|
||||
auto it = unitToSystem.find( unit );
|
||||
if ( it == unitToSystem.end() ) continue;
|
||||
|
||||
if ( detected == RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN )
|
||||
detected = it->second;
|
||||
else if ( detected != it->second )
|
||||
return RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN;
|
||||
}
|
||||
|
||||
return detected;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
@@ -75,6 +76,9 @@ private:
|
||||
void populateTimeSteps();
|
||||
std::string keywordForAddress( const RifEclipseSummaryAddress& address ) const;
|
||||
|
||||
RiaDefines::EclipseUnitSystem detectUnitSystem() const;
|
||||
RiaDefines::EclipseUnitSystem unitSystemFromVectorUnits() const;
|
||||
|
||||
static bool writeEsmryFile( QString& smspecFileName, bool includeRestartFiles, RiaThreadSafeLogger* threadSafeLogger );
|
||||
static void increaseEsmryFileCount();
|
||||
|
||||
@@ -90,5 +94,9 @@ private:
|
||||
bool m_useEsmryFiles;
|
||||
bool m_createEsmryFiles;
|
||||
|
||||
// Detected on first request, as reading the SMSPEC file is not needed for summary import
|
||||
QString m_fileName;
|
||||
mutable std::optional<RiaDefines::EclipseUnitSystem> m_unitSystem;
|
||||
|
||||
RifEnsembleImportConfig m_ensembleImportState;
|
||||
};
|
||||
@@ -98,6 +98,9 @@ bool RifOpmHdf5Summary::open( const QString& headerFileName, bool includeRestart
|
||||
|
||||
createAndSetAddresses();
|
||||
|
||||
m_headerFileName = headerFileName;
|
||||
m_unitSystem = std::nullopt;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -158,8 +161,11 @@ std::string RifOpmHdf5Summary::unitName( const RifEclipseSummaryAddress& resultA
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaDefines::EclipseUnitSystem RifOpmHdf5Summary::unitSystem() const
|
||||
{
|
||||
// TODO: Not implemented
|
||||
return RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN;
|
||||
if ( !m_unitSystem )
|
||||
{
|
||||
m_unitSystem = RifOpmSummaryTools::readUnitSystem( RifOpmSummaryTools::smspecSummaryFilename( m_headerFileName ) );
|
||||
}
|
||||
return *m_unitSystem;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -73,4 +74,8 @@ private:
|
||||
std::vector<time_t> m_timeSteps;
|
||||
|
||||
std::unique_ptr<RifHdf5SummaryReader> m_hdf5Reader;
|
||||
|
||||
// Detected on first request, as reading the SMSPEC file is not needed for summary import
|
||||
QString m_headerFileName;
|
||||
mutable std::optional<RiaDefines::EclipseUnitSystem> m_unitSystem;
|
||||
};
|
||||
@@ -23,11 +23,14 @@
|
||||
#include "RiaPreferencesSummary.h"
|
||||
#include "RiaQStringFormatter.h"
|
||||
|
||||
#include "RifEclipseOutputFileTools.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Disable warning from external library to make sure treat warnings as error works
|
||||
#pragma warning( disable : 4267 )
|
||||
#endif
|
||||
#include "opm/io/eclipse/ESmry.hpp"
|
||||
#include "opm/io/eclipse/EclFile.hpp"
|
||||
#include "opm/io/eclipse/ExtESmry.hpp"
|
||||
|
||||
#include <QFile>
|
||||
@@ -222,6 +225,33 @@ bool RifOpmSummaryTools::isEsmryConversionRequired( const QString& fileName )
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// The unit system is stored in INTEHEAD[0] of the SMSPEC file
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaDefines::EclipseUnitSystem RifOpmSummaryTools::readUnitSystem( const QString& smspecFileName )
|
||||
{
|
||||
if ( !QFile::exists( smspecFileName ) ) return RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN;
|
||||
|
||||
try
|
||||
{
|
||||
Opm::EclIO::EclFile smspecFile( smspecFileName.toStdString() );
|
||||
if ( smspecFile.hasKey( "INTEHEAD" ) )
|
||||
{
|
||||
const auto& intehead = smspecFile.get<int>( "INTEHEAD" );
|
||||
if ( !intehead.empty() )
|
||||
{
|
||||
return RifEclipseOutputFileTools::unitValueToEnum( intehead[0] ).value_or( RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( const std::exception& e )
|
||||
{
|
||||
RiaLogging::debug( QString( "Failed to read unit system from %1: %2" ).arg( smspecFileName, e.what() ).toStdString() );
|
||||
}
|
||||
|
||||
return RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RiaDefines.h"
|
||||
|
||||
#include "RifEclipseSummaryAddress.h"
|
||||
|
||||
#include <QString>
|
||||
@@ -51,6 +53,8 @@ QString enhancedSummaryFilename( const QString& fileName );
|
||||
QString smspecSummaryFilename( const QString& fileName );
|
||||
bool isEsmryConversionRequired( const QString& fileName );
|
||||
|
||||
RiaDefines::EclipseUnitSystem readUnitSystem( const QString& smspecFileName );
|
||||
|
||||
std::expected<int, QString> extractRealizationNumber( const QString& path );
|
||||
|
||||
}; // namespace RifOpmSummaryTools
|
||||
@@ -1917,6 +1917,21 @@ void RimWellRftPlot::initializeDataSources( RimWellRftPlot* source )
|
||||
{
|
||||
// If no source is provided, initialize with empty sources
|
||||
setOrInitializeDataSources( {} );
|
||||
|
||||
// Use the depth unit of the data in a new plot, with the unit of the grid model in the project as fallback
|
||||
auto depthUnit = RiaDefines::DepthUnitType::UNIT_NONE;
|
||||
for ( const auto& dataSource : m_selectedSources() )
|
||||
{
|
||||
for ( auto unitSystem : dataSource.availableUnitSystems() )
|
||||
{
|
||||
depthUnit = RiaDefines::fromEclipseUnit( unitSystem );
|
||||
if ( depthUnit != RiaDefines::DepthUnitType::UNIT_NONE ) break;
|
||||
}
|
||||
if ( depthUnit != RiaDefines::DepthUnitType::UNIT_NONE ) break;
|
||||
}
|
||||
|
||||
if ( depthUnit == RiaDefines::DepthUnitType::UNIT_NONE ) depthUnit = caseDepthUnit();
|
||||
if ( depthUnit != RiaDefines::DepthUnitType::UNIT_NONE ) setDepthUnit( depthUnit );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -750,11 +750,14 @@ bool RimSummaryEnsemble::operator<( const RimSummaryEnsemble& rhs ) const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaDefines::EclipseUnitSystem RimSummaryEnsemble::unitSystem() const
|
||||
{
|
||||
if ( m_cases.empty() )
|
||||
// The first realization can be missing data, use the first realization with a known unit system
|
||||
for ( auto* summaryCase : m_cases.childrenByType() )
|
||||
{
|
||||
return RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN;
|
||||
auto unitSystem = summaryCase->unitsSystem();
|
||||
if ( unitSystem != RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN ) return unitSystem;
|
||||
}
|
||||
return m_cases[0]->unitsSystem();
|
||||
|
||||
return RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -31,6 +31,27 @@ public:
|
||||
size_t keywordCount() const override { return m_allResultAddresses.size(); }
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Stand-in for a reader reporting a given unit system
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
class StubUnitSystemReader : public RifSummaryReaderInterface
|
||||
{
|
||||
public:
|
||||
explicit StubUnitSystemReader( RiaDefines::EclipseUnitSystem unitSystem )
|
||||
: m_unitSystem( unitSystem )
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<time_t> timeSteps( const RifEclipseSummaryAddress& resultAddress ) const override { return {}; }
|
||||
std::pair<bool, std::vector<double>> values( const RifEclipseSummaryAddress& resultAddress ) const override { return { false, {} }; }
|
||||
std::string unitName( const RifEclipseSummaryAddress& resultAddress ) const override { return {}; }
|
||||
RiaDefines::EclipseUnitSystem unitSystem() const override { return m_unitSystem; }
|
||||
size_t keywordCount() const override { return 0; }
|
||||
|
||||
private:
|
||||
RiaDefines::EclipseUnitSystem m_unitSystem;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Create a calculation producing a single field address
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -122,3 +143,25 @@ TEST( RifMultipleSummaryReaders, RefreshCalculatedAddressesForReaderWithNoAddres
|
||||
|
||||
RimProject::current()->calculationCollection()->deleteCalculation( calculation );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Readers without unit information are ignored, and readers with conflicting units give an unknown unit system
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RifMultipleSummaryReaders, UnitSystemFromMultipleReaders )
|
||||
{
|
||||
using Units = RiaDefines::EclipseUnitSystem;
|
||||
|
||||
{
|
||||
RifMultipleSummaryReaders readers;
|
||||
readers.addReader( std::make_unique<StubUnitSystemReader>( Units::UNITS_UNKNOWN ) );
|
||||
readers.addReader( std::make_unique<StubUnitSystemReader>( Units::UNITS_FIELD ) );
|
||||
EXPECT_EQ( Units::UNITS_FIELD, readers.unitSystem() );
|
||||
}
|
||||
|
||||
{
|
||||
RifMultipleSummaryReaders readers;
|
||||
readers.addReader( std::make_unique<StubUnitSystemReader>( Units::UNITS_FIELD ) );
|
||||
readers.addReader( std::make_unique<StubUnitSystemReader>( Units::UNITS_METRIC ) );
|
||||
EXPECT_EQ( Units::UNITS_UNKNOWN, readers.unitSystem() );
|
||||
}
|
||||
}
|
||||
@@ -160,6 +160,44 @@ TEST( OpmSummaryTests, ReadRegionToRegionValuesWithoutPrebuiltAddressMap )
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( OpmSummaryTests, ReadUnitSystem )
|
||||
{
|
||||
{
|
||||
RifOpmCommonEclipseSummary reader;
|
||||
reader.useEnhancedSummaryFiles( false );
|
||||
reader.createEnhancedSummaryFiles( false );
|
||||
ASSERT_TRUE( reader.open( H5_TEST_DATA_DIRECTORY + "NORNE_ATW2013_RFTPLT_V2.SMSPEC", false, nullptr ) );
|
||||
EXPECT_EQ( RiaDefines::EclipseUnitSystem::UNITS_METRIC, reader.unitSystem() );
|
||||
}
|
||||
|
||||
{
|
||||
// ESMRY without SMSPEC, the unit system is derived from the vector units. Create the ESMRY file in a temporary folder, as the
|
||||
// ESMRY file in the test data folder is rewritten by other tests.
|
||||
QTemporaryDir tempDir;
|
||||
ASSERT_TRUE( tempDir.isValid() );
|
||||
const QString smspecFilePath = tempDir.filePath( "NORNE_ATW2013_RFTPLT_V2.SMSPEC" );
|
||||
const QString unsmryFilePath = tempDir.filePath( "NORNE_ATW2013_RFTPLT_V2.UNSMRY" );
|
||||
const QString esmryFilePath = tempDir.filePath( "NORNE_ATW2013_RFTPLT_V2.ESMRY" );
|
||||
ASSERT_TRUE( QFile::copy( H5_TEST_DATA_DIRECTORY + "NORNE_ATW2013_RFTPLT_V2.SMSPEC", smspecFilePath ) );
|
||||
ASSERT_TRUE( QFile::copy( H5_TEST_DATA_DIRECTORY + "NORNE_ATW2013_RFTPLT_V2.UNSMRY", unsmryFilePath ) );
|
||||
{
|
||||
Opm::EclIO::ESmry eSmry( smspecFilePath.toStdString() );
|
||||
ASSERT_TRUE( eSmry.make_esmry_file() );
|
||||
}
|
||||
ASSERT_TRUE( QFile::remove( smspecFilePath ) );
|
||||
ASSERT_TRUE( QFile::remove( unsmryFilePath ) );
|
||||
|
||||
RifOpmCommonEclipseSummary reader;
|
||||
reader.useEnhancedSummaryFiles( true );
|
||||
reader.createEnhancedSummaryFiles( false );
|
||||
ASSERT_TRUE( reader.open( esmryFilePath, false, nullptr ) );
|
||||
EXPECT_EQ( RiaDefines::EclipseUnitSystem::UNITS_METRIC, reader.unitSystem() );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
Reference in new issue
Block a user