#13275 Import available phases from INIT and UNRST

This change centralizes the logic for determining available phases from
various file formats (ECL, OPM) and data structures (INTEHEAD keyword)
into a single, well-defined function.

The new `RiaOpmParserTools::phasesFromInteheadValue` function now handles the
conversion from an integer phase indicator to a set of `PhaseType` enums.
This function is used in both the ECL and OPM readers.

Updates the `RifEclipseUnifiedRestartFileAccess` and `RifReaderEclipseOutput`
to use `RifEclipseOutputFileTools::findAvailablePhases` to get the available phases
This commit is contained in:
Magne Sjaastad committed 2025-12-04 14:51:07 +01:00
1 parent bcb930f36a
commit c00da5e8e1
9 files changed
+139 -22

No files matched your search

@@ -20,6 +20,7 @@
#include "RifEclipseOutputFileTools.h"
#include "RiaOpmParserTools.h"
#include "RiaQDateTimeTools.h"
#include "RiaStringEncodingTools.h"
@@ -564,33 +565,17 @@ QString RifEclipseOutputFileTools::createIndexFileName( const QString& resultFil
//--------------------------------------------------------------------------------------------------
std::set<RiaDefines::PhaseType> RifEclipseOutputFileTools::findAvailablePhases( const ecl_file_type* ecl_file )
{
std::set<RiaDefines::PhaseType> phaseTypes;
if ( ecl_file )
{
const ecl_kw_type* intehead = ecl_file_iget_named_kw( ecl_file, INTEHEAD_KW, 0 );
if ( intehead )
{
int phases = ecl_kw_iget_int( intehead, INTEHEAD_PHASE_INDEX );
if ( phases & ECL_OIL_PHASE )
{
phaseTypes.insert( RiaDefines::PhaseType::OIL_PHASE );
}
if ( phases & ECL_GAS_PHASE )
{
phaseTypes.insert( RiaDefines::PhaseType::GAS_PHASE );
}
if ( phases & ECL_WATER_PHASE )
{
phaseTypes.insert( RiaDefines::PhaseType::WATER_PHASE );
}
return RiaOpmParserTools::phasesFromInteheadValue( phases );
}
}
return phaseTypes;
return std::set<RiaDefines::PhaseType>();
}
//--------------------------------------------------------------------------------------------------
@@ -120,12 +120,12 @@ bool RifEclipseUnifiedRestartFileAccess::openFile()
}
}
}
m_availablePhases = RifEclipseOutputFileTools::findAvailablePhases( m_ecl_file );
}
if ( !m_ecl_file ) return false;
m_availablePhases = RifEclipseOutputFileTools::findAvailablePhases( m_ecl_file );
return true;
}
@@ -926,6 +926,20 @@ void RifReaderEclipseOutput::buildMetaData( ecl_grid_type* grid )
m_eclipseCaseData->setUnitsType( unitsType );
}
// Set available phases from INIT or UNRST file
{
std::set<RiaDefines::PhaseType> phases;
if ( m_ecl_init_file )
{
phases = RifEclipseOutputFileTools::findAvailablePhases( m_ecl_init_file );
}
else if ( m_dynamicResultsAccess.notNull() )
{
phases = m_dynamicResultsAccess->availablePhases();
}
m_eclipseCaseData->setAvailablePhases( phases );
}
progInfo.incrementProgress();
if ( m_ecl_init_file )
@@ -20,6 +20,7 @@
#include "RiaEclipseFileNameTools.h"
#include "RiaLogging.h"
#include "RiaOpmParserTools.h"
#include "RiaPreferencesSystem.h"
#include "RiaQDateTimeTools.h"
#include "RiaResultNames.h"
@@ -971,6 +972,12 @@ void RifReaderOpmCommon::buildMetaData( RigEclipseCaseData* eclipseCaseData, caf
m_eclipseCaseData->setUnitsType( unitsType );
}
// Set available phases from INTEHEAD
{
auto phases = availablePhases();
m_eclipseCaseData->setAvailablePhases( phases );
}
auto task = progress.task( "Handling well information", 10 );
if ( loadWellDataEnabled() && !m_restartFileName.empty() )
{
@@ -1056,6 +1063,51 @@ std::vector<RifReaderOpmCommon::TimeDataFile> RifReaderOpmCommon::readTimeSteps(
return reportTimeData;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<int> RifReaderOpmCommon::readInteheadKeyword() const
{
if ( m_initFile )
{
try
{
return m_initFile->getInitData<int>( "INTEHEAD" );
}
catch ( const std::exception& e )
{
RiaLogging::warning( QString( "Failed to read INTEHEAD keyword from init file: %1" ).arg( e.what() ) );
}
}
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RifReaderOpmCommon::readPhasesFromIntehead() const
{
namespace VI = Opm::RestartIO::Helpers::VectorItems;
auto intehead = readInteheadKeyword();
if ( intehead.size() > VI::intehead::PHASE )
{
return intehead[VI::intehead::PHASE];
}
return -1;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RiaDefines::PhaseType> RifReaderOpmCommon::availablePhases() const
{
int phaseIndicator = readPhasesFromIntehead();
return RiaOpmParserTools::phasesFromInteheadValue( phaseIndicator );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -18,9 +18,11 @@
#pragma once
#include "RiaDefines.h"
#include "RifReaderInterface.h"
#include <memory>
#include <set>
#include <string>
#include <vector>
@@ -59,7 +61,8 @@ public:
bool staticResult( const QString& result, RiaDefines::PorosityModelType matrixOrFracture, std::vector<double>* values ) override;
bool dynamicResult( const QString& result, RiaDefines::PorosityModelType matrixOrFracture, size_t stepIndex, std::vector<double>* values ) override;
std::vector<QDateTime> timeStepsOnFile( QString gridFileName );
std::vector<QDateTime> timeStepsOnFile( QString gridFileName );
std::set<RiaDefines::PhaseType> availablePhases() const override;
protected:
virtual bool importGrid( RigMainGrid* mainGrid, RigEclipseCaseData* caseData );
@@ -105,6 +108,9 @@ private:
std::vector<TimeDataFile> readTimeSteps();
QDateTime dateTimeFromTimeStepOnFile( RifReaderOpmCommon::TimeDataFile timeOnFile, QDate startDate, double startDayOffset );
std::vector<int> readInteheadKeyword() const;
int readPhasesFromIntehead() const;
protected:
enum class ActiveType
{
@@ -401,4 +401,37 @@ std::string aicdTemplateId()
return "ID_NUMBER";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RiaDefines::PhaseType> phasesFromInteheadValue( int phaseIndicator )
{
std::set<RiaDefines::PhaseType> phases;
if ( phaseIndicator < 0 ) return phases;
// Phase indicator from OPM Common specification:
// ThirdParty\custom-opm-common\opm-common\opm\output\eclipse\VectorItems\intehead.hpp
// PHASE = 14, Phase indicator:
// 1: oil, 2: water, 3: O/W, 4: gas, 5: G/O, 6: G/W, 7: O/G/W
// Use bitwise logic: oil=bit 0, water=bit 1, gas=bit 2
if ( phaseIndicator & 1 ) // oil
{
phases.insert( RiaDefines::PhaseType::OIL_PHASE );
}
if ( phaseIndicator & 2 ) // water
{
phases.insert( RiaDefines::PhaseType::WATER_PHASE );
}
if ( phaseIndicator & 4 ) // gas
{
phases.insert( RiaDefines::PhaseType::GAS_PHASE );
}
return phases;
}
} // namespace RiaOpmParserTools
@@ -18,7 +18,10 @@
#pragma once
#include "RiaDefines.h"
#include <map>
#include <set>
#include <string>
#include <vector>
@@ -41,4 +44,8 @@ std::vector<AicdTemplateValues> extractWsegAicd( const std::string& filename );
std::vector<AicdTemplateValues> extractWsegAicdCompletor( const std::string& filename );
std::string aicdTemplateId();
// Phase conversion utilities
std::set<RiaDefines::PhaseType> phasesFromInteheadValue( int phaseIndicator );
}; // namespace RiaOpmParserTools
@@ -855,3 +855,19 @@ const std::vector<double>* RigEclipseCaseData::resultValues( RiaDefines::Porosit
return swatResults;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RiaDefines::PhaseType> RigEclipseCaseData::availablePhases() const
{
return m_availablePhases;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigEclipseCaseData::setAvailablePhases( const std::set<RiaDefines::PhaseType>& phases )
{
m_availablePhases = phases;
}
@@ -107,6 +107,9 @@ public:
RiaDefines::EclipseUnitSystem unitsType() const { return m_unitsType; }
void setUnitsType( RiaDefines::EclipseUnitSystem unitsType ) { m_unitsType = unitsType; }
std::set<RiaDefines::PhaseType> availablePhases() const;
void setAvailablePhases( const std::set<RiaDefines::PhaseType>& phases );
std::vector<QString> simulationWellNames() const;
bool hasSimulationWell( const QString& simWellName ) const;
@@ -148,7 +151,8 @@ private:
cvf::Collection<cvf::UIntArray> m_gridCellToResultWellIndex; //< Array pr grid with index to well pr cell telling
// which well a cell is in
RiaDefines::EclipseUnitSystem m_unitsType;
RiaDefines::EclipseUnitSystem m_unitsType;
std::set<RiaDefines::PhaseType> m_availablePhases;
bool m_hasParsedDeckForEquilData;
std::vector<RigEquil> m_equil;