mirror of
https://github.com/OPM/ResInsight.git
synced 2026-11-02 20:30:46 -06:00
Refactor: move opm-flow deck keyword generation to factory.
This commit is contained in:
1 parent
04dfa4ecba
commit
4e736a8cc0
7 files changed
+216
-227
No files matched your search
@@ -471,10 +471,13 @@ std::expected<void, QString> RicExportEclipseSectorModelFeature::addBorderBounda
|
|||||||
|
|
||||||
if ( !borderCellFaces.empty() )
|
if ( !borderCellFaces.empty() )
|
||||||
{
|
{
|
||||||
// Add BCCON keyword
|
// Create BCCON keyword using the factory
|
||||||
if ( !deckFile.addBcconKeyword( "GRID", borderCellFaces ) )
|
Opm::DeckKeyword bcconKw = RimKeywordFactory::bcconKeyword( borderCellFaces );
|
||||||
|
|
||||||
|
// Replace BCCON keyword in GRID section
|
||||||
|
if ( !deckFile.replaceKeyword( "GRID", bcconKw ) )
|
||||||
{
|
{
|
||||||
return std::unexpected( "Failed to add BCCON keyword to deck file" );
|
return std::unexpected( "Failed to replace BCCON keyword in deck file" );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build BCPROP records from the UI configuration
|
// Build BCPROP records from the UI configuration
|
||||||
@@ -489,10 +492,13 @@ std::expected<void, QString> RicExportEclipseSectorModelFeature::addBorderBounda
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add BCPROP keyword
|
// Create BCPROP keyword using the factory
|
||||||
if ( !deckFile.addBcpropKeyword( "GRID", borderCellFaces, bcpropRecords ) )
|
Opm::DeckKeyword bcpropKw = RimKeywordFactory::bcpropKeyword( borderCellFaces, bcpropRecords );
|
||||||
|
|
||||||
|
// Replace BCPROP keyword in GRID section
|
||||||
|
if ( !deckFile.replaceKeyword( "GRID", bcpropKw ) )
|
||||||
{
|
{
|
||||||
return std::unexpected( "Failed to add BCPROP keyword to deck file" );
|
return std::unexpected( "Failed to replace BCPROP keyword in deck file" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -20,8 +20,6 @@
|
|||||||
|
|
||||||
#include "RifOpmDeckTools.h"
|
#include "RifOpmDeckTools.h"
|
||||||
|
|
||||||
#include "RigEclipseResultTools.h"
|
|
||||||
|
|
||||||
#include "opm/common/utility/TimeService.hpp"
|
#include "opm/common/utility/TimeService.hpp"
|
||||||
#include "opm/input/eclipse/Deck/Deck.hpp"
|
#include "opm/input/eclipse/Deck/Deck.hpp"
|
||||||
#include "opm/input/eclipse/Deck/FileDeck.hpp"
|
#include "opm/input/eclipse/Deck/FileDeck.hpp"
|
||||||
@@ -29,19 +27,16 @@
|
|||||||
#include "opm/input/eclipse/Parser/InputErrorAction.hpp"
|
#include "opm/input/eclipse/Parser/InputErrorAction.hpp"
|
||||||
#include "opm/input/eclipse/Parser/ParseContext.hpp"
|
#include "opm/input/eclipse/Parser/ParseContext.hpp"
|
||||||
#include "opm/input/eclipse/Parser/Parser.hpp"
|
#include "opm/input/eclipse/Parser/Parser.hpp"
|
||||||
#include "opm/input/eclipse/Parser/ParserKeywords/B.hpp"
|
|
||||||
#include "opm/input/eclipse/Parser/ParserKeywords/C.hpp"
|
#include "opm/input/eclipse/Parser/ParserKeywords/C.hpp"
|
||||||
#include "opm/input/eclipse/Parser/ParserKeywords/D.hpp"
|
#include "opm/input/eclipse/Parser/ParserKeywords/D.hpp"
|
||||||
#include "opm/input/eclipse/Parser/ParserKeywords/E.hpp"
|
#include "opm/input/eclipse/Parser/ParserKeywords/E.hpp"
|
||||||
#include "opm/input/eclipse/Parser/ParserKeywords/G.hpp"
|
#include "opm/input/eclipse/Parser/ParserKeywords/G.hpp"
|
||||||
#include "opm/input/eclipse/Parser/ParserKeywords/I.hpp"
|
#include "opm/input/eclipse/Parser/ParserKeywords/I.hpp"
|
||||||
#include "opm/input/eclipse/Parser/ParserKeywords/O.hpp"
|
|
||||||
#include "opm/input/eclipse/Parser/ParserKeywords/R.hpp"
|
#include "opm/input/eclipse/Parser/ParserKeywords/R.hpp"
|
||||||
#include "opm/input/eclipse/Parser/ParserKeywords/S.hpp"
|
#include "opm/input/eclipse/Parser/ParserKeywords/S.hpp"
|
||||||
#include "opm/input/eclipse/Parser/ParserKeywords/W.hpp"
|
#include "opm/input/eclipse/Parser/ParserKeywords/W.hpp"
|
||||||
|
|
||||||
#include "cvfStructGrid.h"
|
#include <cmath>
|
||||||
|
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@@ -752,189 +747,6 @@ bool RifOpmFlowDeckFile::addIncludeKeyword( std::string section, std::string key
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
|
||||||
///
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
|
||||||
bool RifOpmFlowDeckFile::addOperaterKeyword( std::string section,
|
|
||||||
std::string targetProperty,
|
|
||||||
int regionId,
|
|
||||||
std::string equation,
|
|
||||||
std::string inputProperty,
|
|
||||||
std::optional<float> alpha,
|
|
||||||
std::optional<float> beta )
|
|
||||||
{
|
|
||||||
if ( m_fileDeck.get() == nullptr ) return false;
|
|
||||||
|
|
||||||
// Find insertion point within the section
|
|
||||||
auto insertIdx = internal::findSectionInsertionPoint( m_fileDeck, section );
|
|
||||||
if ( !insertIdx.has_value() ) return false; // Section not found
|
|
||||||
|
|
||||||
using O = Opm::ParserKeywords::OPERATER;
|
|
||||||
|
|
||||||
// Create the OPERATER keyword
|
|
||||||
Opm::DeckKeyword operaterKw( ( Opm::ParserKeywords::OPERATER() ) );
|
|
||||||
|
|
||||||
std::vector<Opm::DeckItem> recordItems;
|
|
||||||
recordItems.push_back( RifOpmDeckTools::item( O::TARGET_ARRAY::itemName, targetProperty ) );
|
|
||||||
recordItems.push_back( RifOpmDeckTools::item( O::REGION_NUMBER::itemName, regionId ) );
|
|
||||||
recordItems.push_back( RifOpmDeckTools::item( O::OPERATION::itemName, equation ) );
|
|
||||||
recordItems.push_back( RifOpmDeckTools::item( O::ARRAY_PARAMETER::itemName, inputProperty ) );
|
|
||||||
|
|
||||||
// Add alpha parameter
|
|
||||||
if ( alpha.has_value() )
|
|
||||||
{
|
|
||||||
recordItems.push_back( RifOpmDeckTools::item( O::PARAM1::itemName, std::to_string( alpha.value() ) ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
recordItems.push_back( RifOpmDeckTools::defaultItem( O::PARAM1::itemName ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add beta parameter
|
|
||||||
if ( beta.has_value() )
|
|
||||||
{
|
|
||||||
recordItems.push_back( RifOpmDeckTools::item( O::PARAM2::itemName, std::to_string( beta.value() ) ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
recordItems.push_back( RifOpmDeckTools::defaultItem( O::PARAM2::itemName ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add final default item
|
|
||||||
recordItems.push_back( RifOpmDeckTools::defaultItem( O::REGION_NAME::itemName ) ); // 1* for the last field
|
|
||||||
|
|
||||||
operaterKw.addRecord( Opm::DeckRecord{ std::move( recordItems ) } );
|
|
||||||
|
|
||||||
m_fileDeck->insert( insertIdx.value(), operaterKw );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
|
||||||
///
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
|
||||||
bool RifOpmFlowDeckFile::addBcconKeyword( std::string section, const std::vector<RigEclipseResultTools::BorderCellFace>& borderCellFaces )
|
|
||||||
{
|
|
||||||
if ( m_fileDeck.get() == nullptr ) return false;
|
|
||||||
|
|
||||||
if ( borderCellFaces.empty() ) return true; // Nothing to add
|
|
||||||
|
|
||||||
// Find insertion point within the section
|
|
||||||
auto insertPos = internal::findSectionInsertionPoint( m_fileDeck, section );
|
|
||||||
if ( !insertPos.has_value() )
|
|
||||||
{
|
|
||||||
return false; // Section not found
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper lambda to convert FaceType to string
|
|
||||||
auto faceTypeToString = []( cvf::StructGridInterface::FaceType faceType ) -> std::string
|
|
||||||
{
|
|
||||||
switch ( faceType )
|
|
||||||
{
|
|
||||||
case cvf::StructGridInterface::POS_I:
|
|
||||||
return "X";
|
|
||||||
case cvf::StructGridInterface::NEG_I:
|
|
||||||
return "X-";
|
|
||||||
case cvf::StructGridInterface::POS_J:
|
|
||||||
return "Y";
|
|
||||||
case cvf::StructGridInterface::NEG_J:
|
|
||||||
return "Y-";
|
|
||||||
case cvf::StructGridInterface::POS_K:
|
|
||||||
return "Z";
|
|
||||||
case cvf::StructGridInterface::NEG_K:
|
|
||||||
return "Z-";
|
|
||||||
default:
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create the BCCON keyword using OPM's BCCON parser keyword
|
|
||||||
using B = Opm::ParserKeywords::BCCON;
|
|
||||||
|
|
||||||
Opm::DeckKeyword bcconKw( ( Opm::ParserKeywords::BCCON() ) );
|
|
||||||
|
|
||||||
for ( const auto& borderFace : borderCellFaces )
|
|
||||||
{
|
|
||||||
// Convert from 0-based to 1-based Eclipse indexing
|
|
||||||
int i1 = static_cast<int>( borderFace.ijk[0] ) + 1;
|
|
||||||
int j1 = static_cast<int>( borderFace.ijk[1] ) + 1;
|
|
||||||
int k1 = static_cast<int>( borderFace.ijk[2] ) + 1;
|
|
||||||
|
|
||||||
std::string faceStr = faceTypeToString( borderFace.faceType );
|
|
||||||
|
|
||||||
// Create items for the record using proper BCCON item names
|
|
||||||
std::vector<Opm::DeckItem> recordItems;
|
|
||||||
|
|
||||||
recordItems.push_back( RifOpmDeckTools::item( B::INDEX::itemName, borderFace.boundaryCondition ) );
|
|
||||||
recordItems.push_back( RifOpmDeckTools::item( B::I1::itemName, i1 ) );
|
|
||||||
recordItems.push_back( RifOpmDeckTools::item( B::I2::itemName, i1 ) ); // Same as i1 for single cell
|
|
||||||
recordItems.push_back( RifOpmDeckTools::item( B::J1::itemName, j1 ) );
|
|
||||||
recordItems.push_back( RifOpmDeckTools::item( B::J2::itemName, j1 ) ); // Same as j1 for single cell
|
|
||||||
recordItems.push_back( RifOpmDeckTools::item( B::K1::itemName, k1 ) );
|
|
||||||
recordItems.push_back( RifOpmDeckTools::item( B::K2::itemName, k1 ) ); // Same as k1 for single cell
|
|
||||||
recordItems.push_back( RifOpmDeckTools::item( B::DIRECTION::itemName, faceStr ) );
|
|
||||||
|
|
||||||
bcconKw.addRecord( Opm::DeckRecord{ std::move( recordItems ) } );
|
|
||||||
}
|
|
||||||
|
|
||||||
m_fileDeck->insert( insertPos.value(), bcconKw );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
|
||||||
///
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
|
||||||
bool RifOpmFlowDeckFile::addBcpropKeyword( std::string section,
|
|
||||||
const std::vector<RigEclipseResultTools::BorderCellFace>& boundaryConditions,
|
|
||||||
const std::vector<Opm::DeckRecord>& boundaryConditionProperties )
|
|
||||||
{
|
|
||||||
if ( m_fileDeck.get() == nullptr ) return false;
|
|
||||||
|
|
||||||
if ( boundaryConditions.empty() ) return true; // Nothing to add
|
|
||||||
|
|
||||||
// Find insertion point within the section
|
|
||||||
auto insertPos = internal::findSectionInsertionPoint( m_fileDeck, section );
|
|
||||||
if ( !insertPos.has_value() )
|
|
||||||
{
|
|
||||||
return false; // Section not found
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the BCPROP keyword using OPM's BCPROP parser keyword
|
|
||||||
using B = Opm::ParserKeywords::BCPROP;
|
|
||||||
|
|
||||||
Opm::DeckKeyword bcpropKw( ( Opm::ParserKeywords::BCPROP() ) );
|
|
||||||
|
|
||||||
// Add one entry per boundary condition
|
|
||||||
for ( const auto& bc : boundaryConditions )
|
|
||||||
{
|
|
||||||
if ( bc.boundaryCondition <= 0 ) continue; // Skip entries without a valid boundary condition
|
|
||||||
|
|
||||||
// Find the corresponding property record
|
|
||||||
// The properties vector should be indexed by boundaryCondition - 1
|
|
||||||
size_t propIndex = static_cast<size_t>( bc.boundaryCondition - 1 );
|
|
||||||
if ( propIndex < boundaryConditionProperties.size() )
|
|
||||||
{
|
|
||||||
const auto& propRecord = boundaryConditionProperties[propIndex];
|
|
||||||
|
|
||||||
// Create a new record with the boundary condition INDEX
|
|
||||||
std::vector<Opm::DeckItem> recordItems;
|
|
||||||
|
|
||||||
// Add INDEX field
|
|
||||||
recordItems.push_back( RifOpmDeckTools::item( B::INDEX::itemName, bc.boundaryCondition ) );
|
|
||||||
|
|
||||||
// Copy all items from the property record (which doesn't include INDEX)
|
|
||||||
for ( size_t i = 0; i < propRecord.size(); ++i )
|
|
||||||
{
|
|
||||||
recordItems.push_back( propRecord.getItem( i ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
bcpropKw.addRecord( Opm::DeckRecord{ std::move( recordItems ) } );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_fileDeck->insert( insertPos.value(), bcpropKw );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
@@ -942,6 +754,13 @@ bool RifOpmFlowDeckFile::replaceKeyword( const std::string& section, const Opm::
|
|||||||
{
|
{
|
||||||
if ( m_fileDeck.get() == nullptr ) return false;
|
if ( m_fileDeck.get() == nullptr ) return false;
|
||||||
|
|
||||||
|
// Add keyword to specified section if it doesn't exist
|
||||||
|
auto insertPos = internal::findSectionInsertionPoint( m_fileDeck, section );
|
||||||
|
if ( !insertPos.has_value() )
|
||||||
|
{
|
||||||
|
return false; // Section not found
|
||||||
|
}
|
||||||
|
|
||||||
// Find and replace keyword in deck
|
// Find and replace keyword in deck
|
||||||
auto keywordIdx = m_fileDeck->find( keyword.name() );
|
auto keywordIdx = m_fileDeck->find( keyword.name() );
|
||||||
if ( keywordIdx.has_value() )
|
if ( keywordIdx.has_value() )
|
||||||
@@ -952,12 +771,6 @@ bool RifOpmFlowDeckFile::replaceKeyword( const std::string& section, const Opm::
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Add keyword to specified section if it doesn't exist
|
|
||||||
auto insertPos = internal::findSectionInsertionPoint( m_fileDeck, section );
|
|
||||||
if ( !insertPos.has_value() )
|
|
||||||
{
|
|
||||||
return false; // Section not found
|
|
||||||
}
|
|
||||||
m_fileDeck->insert( insertPos.value(), keyword );
|
m_fileDeck->insert( insertPos.value(), keyword );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,11 +34,6 @@ class DeckRecord;
|
|||||||
class ParseContext;
|
class ParseContext;
|
||||||
} // namespace Opm
|
} // namespace Opm
|
||||||
|
|
||||||
namespace RigEclipseResultTools
|
|
||||||
{
|
|
||||||
struct BorderCellFace;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
@@ -81,18 +76,6 @@ public:
|
|||||||
bool ensureRegdimsKeyword();
|
bool ensureRegdimsKeyword();
|
||||||
|
|
||||||
bool addIncludeKeyword( std::string section, std::string keyword, std::string filePath );
|
bool addIncludeKeyword( std::string section, std::string keyword, std::string filePath );
|
||||||
bool addOperaterKeyword( std::string section,
|
|
||||||
std::string targetProperty,
|
|
||||||
int regionId,
|
|
||||||
std::string equation,
|
|
||||||
std::string inputProperty,
|
|
||||||
std::optional<float> alpha,
|
|
||||||
std::optional<float> beta );
|
|
||||||
|
|
||||||
bool addBcconKeyword( std::string section, const std::vector<RigEclipseResultTools::BorderCellFace>& borderCellFaces );
|
|
||||||
bool addBcpropKeyword( std::string section,
|
|
||||||
const std::vector<RigEclipseResultTools::BorderCellFace>& boundaryConditions,
|
|
||||||
const std::vector<Opm::DeckRecord>& boundaryConditionProperties );
|
|
||||||
|
|
||||||
bool replaceKeywordData( const std::string& keyword, const std::vector<double>& data );
|
bool replaceKeywordData( const std::string& keyword, const std::vector<double>& data );
|
||||||
bool replaceKeywordData( const std::string& keyword, const std::vector<int>& data );
|
bool replaceKeywordData( const std::string& keyword, const std::vector<int>& data );
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include "RifEclipseInputFileTools.h"
|
#include "RifEclipseInputFileTools.h"
|
||||||
#include "RifOpmDeckTools.h"
|
#include "RifOpmDeckTools.h"
|
||||||
|
|
||||||
|
#include "RigEclipseResultTools.h"
|
||||||
#include "RigFault.h"
|
#include "RigFault.h"
|
||||||
#include "RigMainGrid.h"
|
#include "RigMainGrid.h"
|
||||||
|
|
||||||
@@ -38,8 +39,10 @@
|
|||||||
#include "opm/input/eclipse/Deck/DeckKeyword.hpp"
|
#include "opm/input/eclipse/Deck/DeckKeyword.hpp"
|
||||||
#include "opm/input/eclipse/Deck/DeckRecord.hpp"
|
#include "opm/input/eclipse/Deck/DeckRecord.hpp"
|
||||||
#include "opm/input/eclipse/Parser/ParserKeyword.hpp"
|
#include "opm/input/eclipse/Parser/ParserKeyword.hpp"
|
||||||
|
#include "opm/input/eclipse/Parser/ParserKeywords/B.hpp"
|
||||||
#include "opm/input/eclipse/Parser/ParserKeywords/C.hpp"
|
#include "opm/input/eclipse/Parser/ParserKeywords/C.hpp"
|
||||||
#include "opm/input/eclipse/Parser/ParserKeywords/F.hpp"
|
#include "opm/input/eclipse/Parser/ParserKeywords/F.hpp"
|
||||||
|
#include "opm/input/eclipse/Parser/ParserKeywords/O.hpp"
|
||||||
#include "opm/input/eclipse/Parser/ParserKeywords/W.hpp"
|
#include "opm/input/eclipse/Parser/ParserKeywords/W.hpp"
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
@@ -289,4 +292,161 @@ Opm::DeckKeyword faultsKeyword( const RigMainGrid* mainGrid, const cvf::Vec3st&
|
|||||||
return kw;
|
return kw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
Opm::DeckKeyword bcconKeyword( const std::vector<RigEclipseResultTools::BorderCellFace>& borderCellFaces )
|
||||||
|
{
|
||||||
|
if ( borderCellFaces.empty() )
|
||||||
|
{
|
||||||
|
return Opm::DeckKeyword();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper lambda to convert FaceType to Eclipse face string
|
||||||
|
auto faceTypeToString = []( cvf::StructGridInterface::FaceType faceType ) -> std::string
|
||||||
|
{
|
||||||
|
switch ( faceType )
|
||||||
|
{
|
||||||
|
case cvf::StructGridInterface::POS_I:
|
||||||
|
return "X";
|
||||||
|
case cvf::StructGridInterface::NEG_I:
|
||||||
|
return "X-";
|
||||||
|
case cvf::StructGridInterface::POS_J:
|
||||||
|
return "Y";
|
||||||
|
case cvf::StructGridInterface::NEG_J:
|
||||||
|
return "Y-";
|
||||||
|
case cvf::StructGridInterface::POS_K:
|
||||||
|
return "Z";
|
||||||
|
case cvf::StructGridInterface::NEG_K:
|
||||||
|
return "Z-";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using B = Opm::ParserKeywords::BCCON;
|
||||||
|
|
||||||
|
Opm::DeckKeyword kw{ Opm::ParserKeywords::BCCON() };
|
||||||
|
|
||||||
|
for ( const auto& borderFace : borderCellFaces )
|
||||||
|
{
|
||||||
|
// Convert from 0-based to 1-based Eclipse indexing
|
||||||
|
int i1 = static_cast<int>( borderFace.ijk[0] ) + 1;
|
||||||
|
int j1 = static_cast<int>( borderFace.ijk[1] ) + 1;
|
||||||
|
int k1 = static_cast<int>( borderFace.ijk[2] ) + 1;
|
||||||
|
|
||||||
|
std::string faceStr = faceTypeToString( borderFace.faceType );
|
||||||
|
|
||||||
|
// Create items for the record
|
||||||
|
std::vector<Opm::DeckItem> items;
|
||||||
|
|
||||||
|
items.push_back( RifOpmDeckTools::item( B::INDEX::itemName, borderFace.boundaryCondition ) );
|
||||||
|
items.push_back( RifOpmDeckTools::item( B::I1::itemName, i1 ) );
|
||||||
|
items.push_back( RifOpmDeckTools::item( B::I2::itemName, i1 ) );
|
||||||
|
items.push_back( RifOpmDeckTools::item( B::J1::itemName, j1 ) );
|
||||||
|
items.push_back( RifOpmDeckTools::item( B::J2::itemName, j1 ) );
|
||||||
|
items.push_back( RifOpmDeckTools::item( B::K1::itemName, k1 ) );
|
||||||
|
items.push_back( RifOpmDeckTools::item( B::K2::itemName, k1 ) );
|
||||||
|
items.push_back( RifOpmDeckTools::item( B::DIRECTION::itemName, faceStr ) );
|
||||||
|
|
||||||
|
kw.addRecord( Opm::DeckRecord{ std::move( items ) } );
|
||||||
|
}
|
||||||
|
|
||||||
|
return kw;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
Opm::DeckKeyword bcpropKeyword( const std::vector<RigEclipseResultTools::BorderCellFace>& boundaryConditions,
|
||||||
|
const std::vector<Opm::DeckRecord>& boundaryConditionProperties )
|
||||||
|
{
|
||||||
|
if ( boundaryConditions.empty() )
|
||||||
|
{
|
||||||
|
return Opm::DeckKeyword();
|
||||||
|
}
|
||||||
|
|
||||||
|
using B = Opm::ParserKeywords::BCPROP;
|
||||||
|
|
||||||
|
Opm::DeckKeyword kw{ Opm::ParserKeywords::BCPROP() };
|
||||||
|
|
||||||
|
// Add one entry per boundary condition
|
||||||
|
for ( const auto& bc : boundaryConditions )
|
||||||
|
{
|
||||||
|
if ( bc.boundaryCondition <= 0 ) continue; // Skip entries without a valid boundary condition
|
||||||
|
|
||||||
|
// Find the corresponding property record
|
||||||
|
// The properties vector should be indexed by boundaryCondition - 1
|
||||||
|
size_t propIndex = static_cast<size_t>( bc.boundaryCondition - 1 );
|
||||||
|
if ( propIndex < boundaryConditionProperties.size() )
|
||||||
|
{
|
||||||
|
const auto& propRecord = boundaryConditionProperties[propIndex];
|
||||||
|
|
||||||
|
// Create a new record with the boundary condition INDEX
|
||||||
|
std::vector<Opm::DeckItem> items;
|
||||||
|
|
||||||
|
// Add INDEX field
|
||||||
|
items.push_back( RifOpmDeckTools::item( B::INDEX::itemName, bc.boundaryCondition ) );
|
||||||
|
|
||||||
|
// Copy all items from the property record (which doesn't include INDEX)
|
||||||
|
for ( size_t i = 0; i < propRecord.size(); ++i )
|
||||||
|
{
|
||||||
|
items.push_back( propRecord.getItem( i ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
kw.addRecord( Opm::DeckRecord{ std::move( items ) } );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return kw;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
Opm::DeckKeyword operaterKeyword( std::string targetProperty,
|
||||||
|
int regionId,
|
||||||
|
std::string equation,
|
||||||
|
std::string inputProperty,
|
||||||
|
std::optional<float> alpha,
|
||||||
|
std::optional<float> beta )
|
||||||
|
{
|
||||||
|
using O = Opm::ParserKeywords::OPERATER;
|
||||||
|
|
||||||
|
// Create the OPERATER keyword
|
||||||
|
Opm::DeckKeyword operaterKw( ( Opm::ParserKeywords::OPERATER() ) );
|
||||||
|
|
||||||
|
std::vector<Opm::DeckItem> recordItems;
|
||||||
|
recordItems.push_back( RifOpmDeckTools::item( O::TARGET_ARRAY::itemName, targetProperty ) );
|
||||||
|
recordItems.push_back( RifOpmDeckTools::item( O::REGION_NUMBER::itemName, regionId ) );
|
||||||
|
recordItems.push_back( RifOpmDeckTools::item( O::OPERATION::itemName, equation ) );
|
||||||
|
recordItems.push_back( RifOpmDeckTools::item( O::ARRAY_PARAMETER::itemName, inputProperty ) );
|
||||||
|
|
||||||
|
// Add alpha parameter
|
||||||
|
if ( alpha.has_value() )
|
||||||
|
{
|
||||||
|
recordItems.push_back( RifOpmDeckTools::item( O::PARAM1::itemName, std::to_string( alpha.value() ) ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
recordItems.push_back( RifOpmDeckTools::defaultItem( O::PARAM1::itemName ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add beta parameter
|
||||||
|
if ( beta.has_value() )
|
||||||
|
{
|
||||||
|
recordItems.push_back( RifOpmDeckTools::item( O::PARAM2::itemName, std::to_string( beta.value() ) ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
recordItems.push_back( RifOpmDeckTools::defaultItem( O::PARAM2::itemName ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add final default item
|
||||||
|
recordItems.push_back( RifOpmDeckTools::defaultItem( O::REGION_NAME::itemName ) ); // 1* for the last field
|
||||||
|
|
||||||
|
operaterKw.addRecord( Opm::DeckRecord{ std::move( recordItems ) } );
|
||||||
|
return operaterKw;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace RimKeywordFactory
|
} // namespace RimKeywordFactory
|
||||||
@@ -20,7 +20,9 @@
|
|||||||
|
|
||||||
#include "cvfVector3.h"
|
#include "cvfVector3.h"
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class RigMainGrid;
|
class RigMainGrid;
|
||||||
class RimEclipseCase;
|
class RimEclipseCase;
|
||||||
@@ -29,12 +31,18 @@ class RimWellPath;
|
|||||||
namespace Opm
|
namespace Opm
|
||||||
{
|
{
|
||||||
class DeckKeyword;
|
class DeckKeyword;
|
||||||
|
class DeckRecord;
|
||||||
} // namespace Opm
|
} // namespace Opm
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
namespace RigEclipseResultTools
|
||||||
|
{
|
||||||
|
struct BorderCellFace;
|
||||||
|
}
|
||||||
|
|
||||||
namespace RimKeywordFactory
|
namespace RimKeywordFactory
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -44,5 +52,14 @@ Opm::DeckKeyword faultsKeyword( const RigMainGrid* mainGrid,
|
|||||||
const cvf::Vec3st& min = cvf::Vec3st::ZERO,
|
const cvf::Vec3st& min = cvf::Vec3st::ZERO,
|
||||||
const cvf::Vec3st& max = cvf::Vec3st::UNDEFINED,
|
const cvf::Vec3st& max = cvf::Vec3st::UNDEFINED,
|
||||||
const cvf::Vec3st& refinement = cvf::Vec3st( 1, 1, 1 ) );
|
const cvf::Vec3st& refinement = cvf::Vec3st( 1, 1, 1 ) );
|
||||||
|
Opm::DeckKeyword bcconKeyword( const std::vector<RigEclipseResultTools::BorderCellFace>& borderCellFaces );
|
||||||
|
Opm::DeckKeyword bcpropKeyword( const std::vector<RigEclipseResultTools::BorderCellFace>& boundaryConditions,
|
||||||
|
const std::vector<Opm::DeckRecord>& boundaryConditionProperties );
|
||||||
|
Opm::DeckKeyword operaterKeyword( std::string targetProperty,
|
||||||
|
int regionId,
|
||||||
|
std::string equation,
|
||||||
|
std::string inputProperty,
|
||||||
|
std::optional<float> alpha = std::nullopt,
|
||||||
|
std::optional<float> beta = std::nullopt );
|
||||||
|
|
||||||
} // namespace RimKeywordFactory
|
} // namespace RimKeywordFactory
|
||||||
@@ -7,9 +7,12 @@
|
|||||||
|
|
||||||
#include "RigEclipseResultTools.h"
|
#include "RigEclipseResultTools.h"
|
||||||
|
|
||||||
|
#include "ProjectDataModel/Jobs/RimKeywordFactory.h"
|
||||||
|
|
||||||
#include "cvfStructGrid.h"
|
#include "cvfStructGrid.h"
|
||||||
|
|
||||||
#include "opm/input/eclipse/Deck/DeckItem.hpp"
|
#include "opm/input/eclipse/Deck/DeckItem.hpp"
|
||||||
|
#include "opm/input/eclipse/Deck/DeckKeyword.hpp"
|
||||||
#include "opm/input/eclipse/Deck/DeckRecord.hpp"
|
#include "opm/input/eclipse/Deck/DeckRecord.hpp"
|
||||||
#include "opm/input/eclipse/Parser/ParserKeywords/B.hpp"
|
#include "opm/input/eclipse/Parser/ParserKeywords/B.hpp"
|
||||||
|
|
||||||
@@ -268,11 +271,12 @@ TEST( RifOpmFlowDeckFileTest, AddOperaterKeyword )
|
|||||||
ASSERT_TRUE( loadSuccess ) << "Failed to load test deck file";
|
ASSERT_TRUE( loadSuccess ) << "Failed to load test deck file";
|
||||||
|
|
||||||
// Add OPERATER statement to GRID section: PORV 9 MULTX PORV 1.0e6 1* 1*
|
// Add OPERATER statement to GRID section: PORV 9 MULTX PORV 1.0e6 1* 1*
|
||||||
bool addSuccess = deckFile.addOperaterKeyword( "GRID", "PORV", 9, "MULTX", "PORV", 1.0e6f, std::nullopt );
|
bool addSuccess = deckFile.replaceKeyword( "GRID", RimKeywordFactory::operaterKeyword( "PORV", 9, "MULTX", "PORV", 1.0e6f, std::nullopt ) );
|
||||||
EXPECT_TRUE( addSuccess ) << "Should successfully add OPERATER statement in GRID section";
|
EXPECT_TRUE( addSuccess ) << "Should successfully add OPERATER statement in GRID section";
|
||||||
|
|
||||||
// Test adding to non-existent section
|
// Test adding to non-existent section
|
||||||
bool addFailure = deckFile.addOperaterKeyword( "NONEXISTENT", "PORV", 1, "MULTX", "PORV", std::nullopt, std::nullopt );
|
bool addFailure = deckFile.replaceKeyword( "NONEXISTENT",
|
||||||
|
RimKeywordFactory::operaterKeyword( "PORV", 1, "MULTX", "PORV", std::nullopt, std::nullopt ) );
|
||||||
EXPECT_FALSE( addFailure ) << "Should fail when adding to non-existent section";
|
EXPECT_FALSE( addFailure ) << "Should fail when adding to non-existent section";
|
||||||
|
|
||||||
// Verify the keywords list contains our OPERATER statement
|
// Verify the keywords list contains our OPERATER statement
|
||||||
@@ -304,7 +308,7 @@ TEST( RifOpmFlowDeckFileTest, AddOperaterSaveAndReload )
|
|||||||
ASSERT_TRUE( loadSuccess ) << "Failed to load test deck file";
|
ASSERT_TRUE( loadSuccess ) << "Failed to load test deck file";
|
||||||
|
|
||||||
// Add OPERATER statement: PORV 9 MULTX PORV 1.0e6 1* 1*
|
// Add OPERATER statement: PORV 9 MULTX PORV 1.0e6 1* 1*
|
||||||
bool addSuccess = deckFile.addOperaterKeyword( "GRID", "PORV", 9, "MULTX", "PORV", 1.0e6f, std::nullopt );
|
bool addSuccess = deckFile.replaceKeyword( "GRID", RimKeywordFactory::operaterKeyword( "PORV", 9, "MULTX", "PORV", 1.0e6f, std::nullopt ) );
|
||||||
EXPECT_TRUE( addSuccess ) << "Should successfully add OPERATER statement";
|
EXPECT_TRUE( addSuccess ) << "Should successfully add OPERATER statement";
|
||||||
|
|
||||||
// Save the deck to a temporary location
|
// Save the deck to a temporary location
|
||||||
@@ -406,9 +410,10 @@ TEST( RifOpmFlowDeckFileTest, BcpropKeyword )
|
|||||||
bcProperties.push_back( Opm::DeckRecord{ std::move( items ) } );
|
bcProperties.push_back( Opm::DeckRecord{ std::move( items ) } );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add BCPROP keyword
|
// Create BCPROP keyword using factory and replace in deck
|
||||||
bool bcpropAdded = deckFile.addBcpropKeyword( "GRID", boundaryConditions, bcProperties );
|
Opm::DeckKeyword bcpropKw = RimKeywordFactory::bcpropKeyword( boundaryConditions, bcProperties );
|
||||||
ASSERT_TRUE( bcpropAdded ) << "Failed to add BCPROP keyword";
|
bool bcpropAdded = deckFile.replaceKeyword( "GRID", bcpropKw );
|
||||||
|
ASSERT_TRUE( bcpropAdded ) << "Failed to replace BCPROP keyword";
|
||||||
|
|
||||||
// Save deck and verify format
|
// Save deck and verify format
|
||||||
QString outputDeckPath = tempDir.filePath( "output_bcprop.DATA" );
|
QString outputDeckPath = tempDir.filePath( "output_bcprop.DATA" );
|
||||||
|
|||||||
@@ -25,6 +25,8 @@
|
|||||||
#include "RifReaderEclipseOutput.h"
|
#include "RifReaderEclipseOutput.h"
|
||||||
#include "RigEclipseResultTools.h"
|
#include "RigEclipseResultTools.h"
|
||||||
|
|
||||||
|
#include "ProjectDataModel/Jobs/RimKeywordFactory.h"
|
||||||
|
|
||||||
#include "RigActiveCellInfo.h"
|
#include "RigActiveCellInfo.h"
|
||||||
#include "RigCaseCellResultsData.h"
|
#include "RigCaseCellResultsData.h"
|
||||||
#include "RigEclipseCaseData.h"
|
#include "RigEclipseCaseData.h"
|
||||||
@@ -32,6 +34,8 @@
|
|||||||
#include "RigMainGrid.h"
|
#include "RigMainGrid.h"
|
||||||
#include "RimEclipseResultCase.h"
|
#include "RimEclipseResultCase.h"
|
||||||
|
|
||||||
|
#include "opm/input/eclipse/Deck/DeckKeyword.hpp"
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QTemporaryDir>
|
#include <QTemporaryDir>
|
||||||
@@ -175,9 +179,10 @@ TEST( RigEclipseResultToolsTest, BorderCellBcconGeneration )
|
|||||||
bool deckLoaded = deckFile.loadDeck( deckFilePath.toStdString() );
|
bool deckLoaded = deckFile.loadDeck( deckFilePath.toStdString() );
|
||||||
ASSERT_TRUE( deckLoaded ) << "Failed to load deck file";
|
ASSERT_TRUE( deckLoaded ) << "Failed to load deck file";
|
||||||
|
|
||||||
// Add BCCON keyword
|
// Create BCCON keyword using factory and replace in deck
|
||||||
bool bcconAdded = deckFile.addBcconKeyword( "GRID", borderCellFaces );
|
Opm::DeckKeyword bcconKw = RimKeywordFactory::bcconKeyword( borderCellFaces );
|
||||||
ASSERT_TRUE( bcconAdded ) << "Failed to add BCCON keyword";
|
bool bcconAdded = deckFile.replaceKeyword( "GRID", bcconKw );
|
||||||
|
ASSERT_TRUE( bcconAdded ) << "Failed to replace BCCON keyword";
|
||||||
|
|
||||||
// Step 7: Save deck and verify format
|
// Step 7: Save deck and verify format
|
||||||
QString outputDeckPath = tempDir.filePath( "output_bccon.DATA" );
|
QString outputDeckPath = tempDir.filePath( "output_bccon.DATA" );
|
||||||
|
|||||||
Reference in new issue
Block a user