mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-26 07:00:17 -05:00
Simulation Input: Handle MULTIPLY keyword.
This commit is contained in:
1 parent
c16a5de656
commit
d053d4b0a6
2 files changed
+181
No files matched your search
@@ -45,6 +45,7 @@
|
||||
#include "opm/input/eclipse/Parser/ParserKeyword.hpp"
|
||||
#include "opm/input/eclipse/Parser/ParserKeywords/C.hpp"
|
||||
#include "opm/input/eclipse/Parser/ParserKeywords/E.hpp"
|
||||
#include "opm/input/eclipse/Parser/ParserKeywords/M.hpp"
|
||||
#include "opm/input/eclipse/Parser/ParserKeywords/O.hpp"
|
||||
#include "opm/input/eclipse/Parser/ParserKeywords/S.hpp"
|
||||
#include "opm/input/eclipse/Parser/ParserKeywords/W.hpp"
|
||||
@@ -111,6 +112,11 @@ std::expected<void, QString> RigSimulationInputTool::exportSimulationInput( RimE
|
||||
return result;
|
||||
}
|
||||
|
||||
if ( auto result = replaceMultiplyKeywordIndices( &eclipseCase, settings, deckFile ); !result )
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if ( auto result = updateWelldimsKeyword( &eclipseCase, settings, deckFile ); !result )
|
||||
{
|
||||
return result;
|
||||
@@ -407,6 +413,66 @@ std::expected<void, QString> RigSimulationInputTool::replaceEqualsKeywordIndices
|
||||
return {};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::expected<void, QString> RigSimulationInputTool::replaceMultiplyKeywordIndices( RimEclipseCase* eclipseCase,
|
||||
const RigSimulationInputSettings& settings,
|
||||
RifOpmFlowDeckFile& deckFile )
|
||||
{
|
||||
auto multiplyKeywordsWithIndices = deckFile.findAllKeywordsWithIndices( "MULTIPLY" );
|
||||
if ( !multiplyKeywordsWithIndices.empty() )
|
||||
{
|
||||
RiaLogging::info( QString( "Processing %1 occurrence(s) of MULTIPLY keyword" ).arg( multiplyKeywordsWithIndices.size() ) );
|
||||
|
||||
// Process in reverse order so indices remain valid after modifications
|
||||
for ( auto it = multiplyKeywordsWithIndices.rbegin(); it != multiplyKeywordsWithIndices.rend(); ++it )
|
||||
{
|
||||
const Opm::FileDeck::Index& index = it->first;
|
||||
const Opm::DeckKeyword& kw = it->second;
|
||||
|
||||
// Create new keyword with transformed coordinates
|
||||
Opm::DeckKeyword transformedKeyword( kw.location(), kw.name() );
|
||||
|
||||
try
|
||||
{
|
||||
for ( size_t recordIdx = 0; recordIdx < kw.size(); ++recordIdx )
|
||||
{
|
||||
const auto& record = kw.getRecord( recordIdx );
|
||||
auto result = processMultiplyRecord( record, settings.min(), settings.max(), settings.refinement() );
|
||||
|
||||
if ( result )
|
||||
{
|
||||
transformedKeyword.addRecord( std::move( result.value() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
RiaLogging::warning( QString( "Failed to process MULTIPLY record: %1" ).arg( result.error() ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Replace with transformed keyword
|
||||
if ( transformedKeyword.size() > 0 )
|
||||
{
|
||||
RiaLogging::info( QString( "Got %1 keywords." ).arg( transformedKeyword.size() ) );
|
||||
deckFile.replaceKeywordAtIndex( index, transformedKeyword );
|
||||
}
|
||||
else
|
||||
{
|
||||
// If all records failed, remove the keyword
|
||||
deckFile.replaceKeywordAtIndex( index, Opm::DeckKeyword( kw.location(), "SKIP" ) );
|
||||
}
|
||||
}
|
||||
catch ( std::exception& e )
|
||||
{
|
||||
return std::unexpected( QString( "Exception processing MULTIPLY keyword: %1" ).arg( e.what() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -784,6 +850,115 @@ std::expected<Opm::DeckRecord, QString> RigSimulationInputTool::processEqualsRec
|
||||
return Opm::DeckRecord{ std::move( items ) };
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::expected<Opm::DeckRecord, QString> RigSimulationInputTool::processMultiplyRecord( const Opm::DeckRecord& record,
|
||||
const caf::VecIjk0& min,
|
||||
const caf::VecIjk0& max,
|
||||
const cvf::Vec3st& refinement )
|
||||
{
|
||||
// MULTIPLY format: FIELD FACTOR I1 I2 J1 J2 K1 K2
|
||||
// Items: 0=FIELD, 1=FACTOR, 2=I1, 3=I2, 4=J1, 5=J2, 6=K1, 7=K2
|
||||
if ( record.size() < 8 )
|
||||
{
|
||||
return std::unexpected( QString( "MULTIPLY record has insufficient items (expected at least 8, got %1)" ).arg( record.size() ) );
|
||||
}
|
||||
|
||||
std::vector<Opm::DeckItem> items;
|
||||
|
||||
// Copy field name and factor (first two items)
|
||||
items.push_back( record.getItem( 0 ) );
|
||||
items.push_back( record.getItem( 1 ) );
|
||||
|
||||
if ( record.getItem( 2 ).hasValue( 0 ) && record.getItem( 3 ).hasValue( 0 ) && record.getItem( 4 ).hasValue( 0 ) &&
|
||||
record.getItem( 5 ).hasValue( 0 ) && record.getItem( 6 ).hasValue( 0 ) && record.getItem( 7 ).hasValue( 0 ) )
|
||||
{
|
||||
// Transform IJK box coordinates (items 2-7: I1, I2, J1, J2, K1, K2)
|
||||
// Note: MULTIPLY uses 1-based Eclipse coordinates
|
||||
int origI1 = record.getItem( 2 ).get<int>( 0 ) - 1; // Convert to 0-based
|
||||
int origI2 = record.getItem( 3 ).get<int>( 0 ) - 1;
|
||||
int origJ1 = record.getItem( 4 ).get<int>( 0 ) - 1;
|
||||
int origJ2 = record.getItem( 5 ).get<int>( 0 ) - 1;
|
||||
int origK1 = record.getItem( 6 ).get<int>( 0 ) - 1;
|
||||
int origK2 = record.getItem( 7 ).get<int>( 0 ) - 1;
|
||||
|
||||
// Create bounding boxes (both use inclusive min/max coordinates)
|
||||
RigBoundingBoxIjk multiplyBox( cvf::Vec3st( origI1, origJ1, origK1 ), cvf::Vec3st( origI2, origJ2, origK2 ) );
|
||||
RigBoundingBoxIjk sectorBox( cvf::Vec3st( min.x(), min.y(), min.z() ), cvf::Vec3st( max.x(), max.y(), max.z() ) );
|
||||
|
||||
// Check if boxes overlap and get intersection
|
||||
auto intersection = multiplyBox.intersection( sectorBox );
|
||||
if ( !intersection )
|
||||
{
|
||||
// No overlap with sector - skip this record
|
||||
QString fieldName = QString::fromStdString( record.getItem( 0 ).get<std::string>( 0 ) );
|
||||
RiaLogging::info( QString( "MULTIPLY record for field '%1' [%2-%3, %4-%5, %6-%7] does not overlap with sector - skipping" )
|
||||
.arg( fieldName )
|
||||
.arg( origI1 + 1 )
|
||||
.arg( origI2 + 1 )
|
||||
.arg( origJ1 + 1 )
|
||||
.arg( origJ2 + 1 )
|
||||
.arg( origK1 + 1 )
|
||||
.arg( origK2 + 1 ) );
|
||||
return std::unexpected( "MULTIPLY record does not overlap with sector" );
|
||||
}
|
||||
|
||||
// Get the clamped coordinates from the intersection
|
||||
cvf::Vec3st corner1 = intersection->min();
|
||||
cvf::Vec3st corner2 = intersection->max();
|
||||
|
||||
// Log if clamping occurred (partial overlap)
|
||||
if ( origI1 != static_cast<int>( corner1.x() ) || origI2 != static_cast<int>( corner2.x() ) ||
|
||||
origJ1 != static_cast<int>( corner1.y() ) || origJ2 != static_cast<int>( corner2.y() ) ||
|
||||
origK1 != static_cast<int>( corner1.z() ) || origK2 != static_cast<int>( corner2.z() ) )
|
||||
{
|
||||
QString fieldName = QString::fromStdString( record.getItem( 0 ).get<std::string>( 0 ) );
|
||||
RiaLogging::info(
|
||||
QString( "MULTIPLY record for field '%1' partially overlaps sector, clamped from [%2-%3, %4-%5, %6-%7] to [%8-%9, %10-%11, "
|
||||
"%12-%13]" )
|
||||
.arg( fieldName )
|
||||
.arg( origI1 + 1 )
|
||||
.arg( origI2 + 1 )
|
||||
.arg( origJ1 + 1 )
|
||||
.arg( origJ2 + 1 )
|
||||
.arg( origK1 + 1 )
|
||||
.arg( origK2 + 1 )
|
||||
.arg( corner1.x() + 1 )
|
||||
.arg( corner2.x() + 1 )
|
||||
.arg( corner1.y() + 1 )
|
||||
.arg( corner2.y() + 1 )
|
||||
.arg( corner1.z() + 1 )
|
||||
.arg( corner2.z() + 1 ) );
|
||||
}
|
||||
|
||||
auto transformResult1 =
|
||||
RigGridExportAdapter::transformIjkToSectorCoordinates( caf::VecIjk0( corner1.x(), corner1.y(), corner1.z() ), min, max, refinement );
|
||||
auto transformResult2 =
|
||||
RigGridExportAdapter::transformIjkToSectorCoordinates( caf::VecIjk0( corner2.x(), corner2.y(), corner2.z() ), min, max, refinement );
|
||||
|
||||
if ( !transformResult1 )
|
||||
{
|
||||
return std::unexpected( QString( "MULTIPLY I1,J1,K1 coordinate is out of sector bounds: %1" ).arg( transformResult1.error() ) );
|
||||
}
|
||||
|
||||
if ( !transformResult2 )
|
||||
{
|
||||
return std::unexpected( QString( "MULTIPLY I2,J2,K2 coordinate is out of sector bounds: %1" ).arg( transformResult2.error() ) );
|
||||
}
|
||||
|
||||
using M = Opm::ParserKeywords::MULTIPLY;
|
||||
items.push_back( RifOpmDeckTools::item( M::I1::itemName, static_cast<int>( transformResult1->x() ) ) );
|
||||
items.push_back( RifOpmDeckTools::item( M::I2::itemName, static_cast<int>( transformResult2->x() ) ) );
|
||||
items.push_back( RifOpmDeckTools::item( M::J1::itemName, static_cast<int>( transformResult1->y() ) ) );
|
||||
items.push_back( RifOpmDeckTools::item( M::J2::itemName, static_cast<int>( transformResult2->y() ) ) );
|
||||
items.push_back( RifOpmDeckTools::item( M::K1::itemName, static_cast<int>( transformResult1->z() ) ) );
|
||||
items.push_back( RifOpmDeckTools::item( M::K2::itemName, static_cast<int>( transformResult2->z() ) ) );
|
||||
}
|
||||
|
||||
return Opm::DeckRecord{ std::move( items ) };
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -54,6 +54,9 @@ public:
|
||||
static std::expected<Opm::DeckRecord, QString>
|
||||
processEqualsRecord( const Opm::DeckRecord& record, const caf::VecIjk0& min, const caf::VecIjk0& max, const cvf::Vec3st& refinement );
|
||||
|
||||
static std::expected<Opm::DeckRecord, QString>
|
||||
processMultiplyRecord( const Opm::DeckRecord& record, const caf::VecIjk0& min, const caf::VecIjk0& max, const cvf::Vec3st& refinement );
|
||||
|
||||
private:
|
||||
static std::expected<void, QString> updateCornerPointGridInDeckFile( RimEclipseCase* eclipseCase,
|
||||
const RigSimulationInputSettings& settings,
|
||||
@@ -72,6 +75,9 @@ private:
|
||||
static std::expected<void, QString>
|
||||
replaceEqualsKeywordIndices( RimEclipseCase* eclipseCase, const RigSimulationInputSettings& settings, RifOpmFlowDeckFile& deckFile );
|
||||
|
||||
static std::expected<void, QString>
|
||||
replaceMultiplyKeywordIndices( RimEclipseCase* eclipseCase, const RigSimulationInputSettings& settings, RifOpmFlowDeckFile& deckFile );
|
||||
|
||||
static std::expected<void, QString>
|
||||
addFaultsToDeckFile( RimEclipseCase* eclipseCase, const RigSimulationInputSettings& settings, RifOpmFlowDeckFile& deckFile );
|
||||
|
||||
|
||||
Reference in new issue
Block a user