mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-24 22:27:55 -05:00
Sector model export: support WLIST kw (#13641)
* Support ADD and NEW operations in WLIST kw * Add support for DEL operation
This commit is contained in:
6 files changed
+183
-9
No files matched your search
@@ -135,4 +135,26 @@ Opm::DeckItem optionalItem( std::string name, std::optional<float> value )
|
||||
return defaultItem( name );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Opm::DeckItem item( std::string name, std::set<std::string> values )
|
||||
{
|
||||
Opm::DeckItem item1( name, "" );
|
||||
for ( const auto& value : values )
|
||||
item1.push_back( value );
|
||||
return item1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Opm::DeckItem item( std::string name, std::vector<std::string> values )
|
||||
{
|
||||
Opm::DeckItem item1( name, "" );
|
||||
for ( const auto& value : values )
|
||||
item1.push_back( value );
|
||||
return item1;
|
||||
}
|
||||
|
||||
} // namespace RifOpmDeckTools
|
||||
@@ -19,7 +19,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
@@ -38,5 +40,7 @@ Opm::DeckItem item( std::string name, double value );
|
||||
Opm::DeckItem optionalItem( std::string name, std::optional<float> value );
|
||||
Opm::DeckItem optionalItem( std::string name, std::optional<double> value );
|
||||
Opm::DeckItem defaultItem( std::string name );
|
||||
Opm::DeckItem item( std::string name, std::set<std::string> values );
|
||||
Opm::DeckItem item( std::string name, std::vector<std::string> values );
|
||||
|
||||
} // namespace RifOpmDeckTools
|
||||
@@ -986,6 +986,19 @@ bool RifOpmFlowDeckFile::replaceKeywordAtIndex( const Opm::FileDeck::Index& inde
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RifOpmFlowDeckFile::removeKeywordAtIndex( const Opm::FileDeck::Index& index )
|
||||
{
|
||||
if ( m_fileDeck.get() == nullptr ) return false;
|
||||
|
||||
// Erase the keyword at the given index and insert the new one
|
||||
m_fileDeck->erase( index );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Returns number of removed keywords
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -104,7 +104,8 @@ public:
|
||||
bool replaceAllKeywords( const std::string& keywordName, const std::vector<Opm::DeckKeyword>& keywords );
|
||||
bool replaceKeywordAtIndex( const Opm::FileDeck::Index& index, const Opm::DeckKeyword& keyword );
|
||||
|
||||
int removeKeywords( const std::string& keywordName );
|
||||
int removeKeywords( const std::string& keywordName );
|
||||
bool removeKeywordAtIndex( const Opm::FileDeck::Index& index );
|
||||
|
||||
private:
|
||||
void splitDatesIfNecessary();
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "RiaLogging.h"
|
||||
#include "RiaNncDefines.h"
|
||||
#include "RiaStdStringTools.h"
|
||||
|
||||
#include "RigModelPaddingSettings.h"
|
||||
#include "RigPadModel.h"
|
||||
@@ -145,7 +146,14 @@ std::expected<void, QString> RigSimulationInputTool::exportSimulationInput( RimE
|
||||
return result;
|
||||
}
|
||||
|
||||
if ( auto result = filterAndUpdateWellKeywords( &eclipseCase, settings, deckFile ); !result )
|
||||
auto validWellNames = wellNamesToInclude( &eclipseCase, settings );
|
||||
|
||||
if ( auto result = filterAndUpdateWellKeywords( validWellNames, settings, deckFile ); !result )
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if ( auto result = updateWellListKeywords( validWellNames, settings, deckFile ); !result )
|
||||
{
|
||||
return result;
|
||||
}
|
||||
@@ -1269,9 +1277,7 @@ std::expected<Opm::DeckRecord, QString> RigSimulationInputTool::processBoxRecord
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::expected<void, QString> RigSimulationInputTool::filterAndUpdateWellKeywords( RimEclipseCase* eclipseCase,
|
||||
const RigSimulationInputSettings& settings,
|
||||
RifOpmFlowDeckFile& deckFile )
|
||||
std::set<std::string> RigSimulationInputTool::wellNamesToInclude( RimEclipseCase* eclipseCase, const RigSimulationInputSettings& settings )
|
||||
{
|
||||
// Find wells that intersect with the sector
|
||||
auto intersectingWells = findIntersectingWells( eclipseCase, settings.min(), settings.max() );
|
||||
@@ -1306,6 +1312,126 @@ std::expected<void, QString> RigSimulationInputTool::filterAndUpdateWellKeywords
|
||||
return names;
|
||||
}() ) ) );
|
||||
|
||||
return validWellNames;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::expected<void, QString> RigSimulationInputTool::updateWellListKeywords( std::set<std::string>& validWellNames,
|
||||
const RigSimulationInputSettings& settings,
|
||||
RifOpmFlowDeckFile& deckFile )
|
||||
{
|
||||
using W = Opm::ParserKeywords::WLIST;
|
||||
|
||||
int replacedCount = 0;
|
||||
int removedCount = 0;
|
||||
|
||||
// gather existing lists
|
||||
|
||||
auto keywordsWithIndices = deckFile.findAllKeywordsWithIndices( W::keywordName );
|
||||
if ( keywordsWithIndices.empty() ) return {};
|
||||
|
||||
std::set<std::string> existingLists;
|
||||
|
||||
// for each WLIST keyword
|
||||
for ( auto [index, kw] : keywordsWithIndices )
|
||||
{
|
||||
std::map<std::string, std::set<std::string>> wellLists;
|
||||
std::map<std::string, std::set<std::string>> deleteLists;
|
||||
|
||||
// for each list operation in this keyword
|
||||
for ( size_t recordIdx = 0; recordIdx < kw.size(); recordIdx++ )
|
||||
{
|
||||
const auto& record = kw.getRecord( recordIdx );
|
||||
if ( record.size() < 3 ) continue;
|
||||
|
||||
// the list name
|
||||
const auto& listNameItem = record.getItem( 0 );
|
||||
if ( !listNameItem.hasValue( 0 ) || listNameItem.getType() != Opm::type_tag::string ) continue;
|
||||
std::string listName = listNameItem.get<std::string>( 0 );
|
||||
|
||||
// the list operation
|
||||
const auto& operationItem = record.getItem( 1 );
|
||||
if ( !operationItem.hasValue( 0 ) || operationItem.getType() != Opm::type_tag::string ) continue;
|
||||
std::string operationName = operationItem.get<std::string>( 0 );
|
||||
operationName = RiaStdStringTools::toUpper( operationName );
|
||||
|
||||
bool delOperation = operationName == "DEL";
|
||||
if ( operationName != "ADD" && operationName != "NEW" && !delOperation )
|
||||
{
|
||||
RiaLogging::warning( QString( "Unsupported %1 operation '%2' in list '%3', skipping" )
|
||||
.arg( W::keywordName.c_str() )
|
||||
.arg( operationName.c_str() )
|
||||
.arg( listName.c_str() ) );
|
||||
continue;
|
||||
}
|
||||
|
||||
// the list of wells to do something with, only include the ones in our valid list
|
||||
const auto& wellsItem = record.getItem( 2 );
|
||||
for ( size_t i = 0; i < wellsItem.data_size(); i++ )
|
||||
{
|
||||
std::string wellName = wellsItem.get<std::string>( i );
|
||||
if ( validWellNames.contains( wellName ) )
|
||||
{
|
||||
if ( delOperation )
|
||||
deleteLists[listName].insert( wellName );
|
||||
else
|
||||
wellLists[listName].insert( wellName );
|
||||
}
|
||||
}
|
||||
}
|
||||
Opm::DeckKeyword newKw( kw.location(), kw.name() );
|
||||
|
||||
for ( const auto& [listName, wells] : wellLists )
|
||||
{
|
||||
if ( wells.empty() ) continue;
|
||||
std::vector<Opm::DeckItem> items;
|
||||
items.push_back( RifOpmDeckTools::item( "NAME", listName ) );
|
||||
const std::string action = existingLists.contains( listName ) ? "ADD" : "NEW";
|
||||
items.push_back( RifOpmDeckTools::item( "ACTION", action ) );
|
||||
items.push_back( RifOpmDeckTools::item( "WELLS", wells ) );
|
||||
newKw.addRecord( Opm::DeckRecord{ std::move( items ) } );
|
||||
existingLists.insert( listName );
|
||||
}
|
||||
|
||||
for ( const auto& [listName, wells] : deleteLists )
|
||||
{
|
||||
if ( wells.empty() ) continue;
|
||||
std::vector<Opm::DeckItem> items;
|
||||
items.push_back( RifOpmDeckTools::item( "NAME", listName ) );
|
||||
items.push_back( RifOpmDeckTools::item( "ACTION", "DEL" ) );
|
||||
items.push_back( RifOpmDeckTools::item( "WELLS", wells ) );
|
||||
newKw.addRecord( Opm::DeckRecord{ std::move( items ) } );
|
||||
}
|
||||
|
||||
if ( newKw.size() > 0 )
|
||||
{
|
||||
// replace the first wlist kw with the new one, remove remaining kws
|
||||
deckFile.replaceKeywordAtIndex( index, std::move( newKw ) );
|
||||
replacedCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// replace with SKIP kw to remove later
|
||||
deckFile.replaceKeywordAtIndex( index, Opm::DeckKeyword( kw.location(), "SKIP" ) );
|
||||
removedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
RiaLogging::info(
|
||||
QString( "Processed keyword '%1': %2 updated, %3 removed" ).arg( W::keywordName.c_str() ).arg( replacedCount ).arg( removedCount ) );
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::expected<void, QString> RigSimulationInputTool::filterAndUpdateWellKeywords( std::set<std::string>& validWellNames,
|
||||
const RigSimulationInputSettings& settings,
|
||||
RifOpmFlowDeckFile& deckFile )
|
||||
{
|
||||
// List of well-related keywords to filter (keywords that reference well names)
|
||||
std::vector<std::string> wellKeywords = { "COMPDAT", "COMPLUMP", "COMPORD", "COMPSEGS", "WCONHIST", "WCONINJE", "WCONINJH",
|
||||
"WCONPROD", "WCYCLE", "WDFAC", "WDFACCOR", "WEFAC", "WELCNTL", "WELOPEN",
|
||||
@@ -1361,7 +1487,7 @@ std::expected<void, QString> RigSimulationInputTool::filterAndUpdateWellKeywords
|
||||
if ( keywordName == "COMPSEGS" || keywordName == "WELSEGS" )
|
||||
{
|
||||
currentSegmentWell = wellName;
|
||||
keepSegmentRecords = ( validWellNames.find( wellName ) != validWellNames.end() );
|
||||
keepSegmentRecords = ( validWellNames.contains( wellName ) );
|
||||
}
|
||||
}
|
||||
else if ( keywordName == "COMPSEGS" || keywordName == "WELSEGS" )
|
||||
@@ -1371,7 +1497,7 @@ std::expected<void, QString> RigSimulationInputTool::filterAndUpdateWellKeywords
|
||||
}
|
||||
|
||||
// Check if this well is in our valid set
|
||||
if ( ( isWellNameRecord && validWellNames.find( wellName ) != validWellNames.end() ) ||
|
||||
if ( ( isWellNameRecord && validWellNames.contains( wellName ) ) ||
|
||||
( !isWellNameRecord && ( keywordName == "COMPSEGS" || keywordName == "WELSEGS" ) && keepSegmentRecords ) )
|
||||
{
|
||||
// For keywords with IJK coordinates, we need to transform them
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <expected>
|
||||
#include <functional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -148,8 +149,15 @@ private:
|
||||
static std::expected<void, QString>
|
||||
addFaultsToDeckFile( RimEclipseCase* eclipseCase, const RigSimulationInputSettings& settings, RifOpmFlowDeckFile& deckFile );
|
||||
|
||||
static std::expected<void, QString>
|
||||
filterAndUpdateWellKeywords( RimEclipseCase* eclipseCase, const RigSimulationInputSettings& settings, RifOpmFlowDeckFile& deckFile );
|
||||
static std::expected<void, QString> filterAndUpdateWellKeywords( std::set<std::string>& validWellNames,
|
||||
const RigSimulationInputSettings& settings,
|
||||
RifOpmFlowDeckFile& deckFile );
|
||||
|
||||
static std::expected<void, QString> updateWellListKeywords( std::set<std::string>& validWellNames,
|
||||
const RigSimulationInputSettings& settings,
|
||||
RifOpmFlowDeckFile& deckFile );
|
||||
|
||||
static std::set<std::string> wellNamesToInclude( RimEclipseCase* eclipseCase, const RigSimulationInputSettings& settings );
|
||||
|
||||
static std::expected<void, QString>
|
||||
exportEditNncKeyword( RimEclipseCase* eclipseCase, const RigSimulationInputSettings& settings, RifOpmFlowDeckFile& deckFile );
|
||||
|
||||
Reference in new issue
Block a user