mirror of
https://github.com/OPM/ResInsight.git
synced 2026-11-10 08:15:31 -06:00
#12950 Sector Model: Add BCPROP keyword.
This commit is contained in:
1 parent
dd689aec50
commit
5373484615
3 files changed
+186
-8
No files matched your search
@@ -922,14 +922,14 @@ bool RifOpmFlowDeckFile::addBcconKeyword( std::string section, const std::vector
|
||||
// Create items for the record using proper BCCON item names
|
||||
std::vector<Opm::DeckItem> recordItems;
|
||||
|
||||
recordItems.push_back( item( B::INDEX::itemName, borderFace.boundaryCondition ) );
|
||||
recordItems.push_back( item( B::I1::itemName, i1 ) );
|
||||
recordItems.push_back( item( B::I2::itemName, i1 ) ); // Same as i1 for single cell
|
||||
recordItems.push_back( item( B::J1::itemName, j1 ) );
|
||||
recordItems.push_back( item( B::J2::itemName, j1 ) ); // Same as j1 for single cell
|
||||
recordItems.push_back( item( B::K1::itemName, k1 ) );
|
||||
recordItems.push_back( item( B::K2::itemName, k1 ) ); // Same as k1 for single cell
|
||||
recordItems.push_back( item( B::DIRECTION::itemName, faceStr ) );
|
||||
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 ) } );
|
||||
}
|
||||
@@ -938,6 +938,61 @@ bool RifOpmFlowDeckFile::addBcconKeyword( std::string section, const std::vector
|
||||
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;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -29,6 +29,8 @@ namespace Opm
|
||||
{
|
||||
class FileDeck;
|
||||
class DeckKeyword;
|
||||
class DeckItem;
|
||||
class DeckRecord;
|
||||
class ParseContext;
|
||||
} // namespace Opm
|
||||
|
||||
@@ -87,6 +89,9 @@ public:
|
||||
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 );
|
||||
|
||||
private:
|
||||
void splitDatesIfNecessary();
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "RiaTestDataDirectory.h"
|
||||
|
||||
#include "RifOpmDeckTools.h"
|
||||
#include "RifOpmFlowDeckFile.h"
|
||||
|
||||
#include "RigEclipseResultTools.h"
|
||||
|
||||
#include "cvfStructGrid.h"
|
||||
|
||||
#include "opm/input/eclipse/Deck/DeckItem.hpp"
|
||||
#include "opm/input/eclipse/Deck/DeckRecord.hpp"
|
||||
#include "opm/input/eclipse/Parser/ParserKeywords/B.hpp"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
@@ -322,3 +332,111 @@ TEST( RifOpmFlowDeckFileTest, AddOperaterSaveAndReload )
|
||||
// The test validates that our addOperaterKeyword functionality works correctly
|
||||
// by checking that the OPERATER statement is properly saved to the file.
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test BCPROP keyword generation
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RifOpmFlowDeckFileTest, BcpropKeyword )
|
||||
{
|
||||
QTemporaryDir tempDir;
|
||||
ASSERT_TRUE( tempDir.isValid() ) << "Failed to create temporary directory";
|
||||
|
||||
// Load the deck file
|
||||
static const QString testDataFolder = QString( "%1/RifOpmFlowDeckFile/" ).arg( TEST_DATA_DIR );
|
||||
QString fileName = testDataFolder + "SIMPLE_NO_REGDIMS.DATA";
|
||||
|
||||
RifOpmFlowDeckFile deckFile;
|
||||
bool loadSuccess = deckFile.loadDeck( fileName.toStdString() );
|
||||
|
||||
ASSERT_TRUE( loadSuccess ) << "Failed to load deck file";
|
||||
|
||||
// Create boundary conditions with different indices
|
||||
std::vector<RigEclipseResultTools::BorderCellFace> boundaryConditions;
|
||||
boundaryConditions.push_back( { cvf::Vec3st( 5, 5, 2 ), cvf::StructGridInterface::POS_I, 1 } );
|
||||
boundaryConditions.push_back( { cvf::Vec3st( 5, 6, 2 ), cvf::StructGridInterface::POS_J, 1 } );
|
||||
boundaryConditions.push_back( { cvf::Vec3st( 6, 5, 2 ), cvf::StructGridInterface::NEG_I, 2 } );
|
||||
boundaryConditions.push_back( { cvf::Vec3st( 7, 5, 2 ), cvf::StructGridInterface::POS_K, 2 } );
|
||||
|
||||
// Create boundary condition properties
|
||||
// BC 1: Free flow boundary with specified pressure
|
||||
// BC 2: Fixed pressure boundary with temperature
|
||||
std::vector<Opm::DeckRecord> bcProperties;
|
||||
|
||||
using B = Opm::ParserKeywords::BCPROP;
|
||||
|
||||
// Property for BC 1 (index will be added by addBcpropKeyword)
|
||||
{
|
||||
std::vector<Opm::DeckItem> items;
|
||||
items.push_back( RifOpmDeckTools::item( B::TYPE::itemName, std::string( "FREE" ) ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::COMPONENT::itemName, std::string( "NONE" ) ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::RATE::itemName, 0.0 ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::PRESSURE::itemName, 200.0 ) ); // 200 bar
|
||||
items.push_back( RifOpmDeckTools::item( B::TEMPERATURE::itemName, 80.0 ) ); // 80 C
|
||||
items.push_back( RifOpmDeckTools::item( B::MECHTYPE::itemName, std::string( "NONE" ) ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::FIXEDX::itemName, 1 ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::FIXEDY::itemName, 1 ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::FIXEDZ::itemName, 1 ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::STRESSXX::itemName, 0.0 ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::STRESSYY::itemName, 0.0 ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::STRESSZZ::itemName, 0.0 ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::DISPX::itemName, 0.0 ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::DISPY::itemName, 0.0 ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::DISPZ::itemName, 0.0 ) );
|
||||
bcProperties.push_back( Opm::DeckRecord{ std::move( items ) } );
|
||||
}
|
||||
|
||||
// Property for BC 2
|
||||
{
|
||||
std::vector<Opm::DeckItem> items;
|
||||
items.push_back( RifOpmDeckTools::item( B::TYPE::itemName, std::string( "DIRICH" ) ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::COMPONENT::itemName, std::string( "WATER" ) ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::RATE::itemName, 0.0 ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::PRESSURE::itemName, 250.0 ) ); // 250 bar
|
||||
items.push_back( RifOpmDeckTools::item( B::TEMPERATURE::itemName, 90.0 ) ); // 90 C
|
||||
items.push_back( RifOpmDeckTools::item( B::MECHTYPE::itemName, std::string( "NONE" ) ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::FIXEDX::itemName, 1 ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::FIXEDY::itemName, 1 ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::FIXEDZ::itemName, 1 ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::STRESSXX::itemName, 0.0 ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::STRESSYY::itemName, 0.0 ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::STRESSZZ::itemName, 0.0 ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::DISPX::itemName, 0.0 ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::DISPY::itemName, 0.0 ) );
|
||||
items.push_back( RifOpmDeckTools::item( B::DISPZ::itemName, 0.0 ) );
|
||||
bcProperties.push_back( Opm::DeckRecord{ std::move( items ) } );
|
||||
}
|
||||
|
||||
// Add BCPROP keyword
|
||||
bool bcpropAdded = deckFile.addBcpropKeyword( "GRID", boundaryConditions, bcProperties );
|
||||
ASSERT_TRUE( bcpropAdded ) << "Failed to add BCPROP keyword";
|
||||
|
||||
// Save deck and verify format
|
||||
QString outputDeckPath = tempDir.filePath( "output_bcprop.DATA" );
|
||||
bool deckSaved = deckFile.saveDeck( tempDir.path().toStdString(), "output_bcprop.DATA" );
|
||||
ASSERT_TRUE( deckSaved ) << "Failed to save deck file";
|
||||
ASSERT_TRUE( QFile::exists( outputDeckPath ) ) << "Output deck file not created";
|
||||
|
||||
// Read and verify BCPROP content
|
||||
QFile outputFile( outputDeckPath );
|
||||
ASSERT_TRUE( outputFile.open( QIODevice::ReadOnly | QIODevice::Text ) );
|
||||
QString content = QTextStream( &outputFile ).readAll();
|
||||
outputFile.close();
|
||||
|
||||
// Verify BCPROP keyword is present
|
||||
EXPECT_TRUE( content.contains( "BCPROP" ) ) << "BCPROP keyword not found in output";
|
||||
|
||||
// Verify boundary condition types are present
|
||||
EXPECT_TRUE( content.contains( "FREE" ) ) << "FREE boundary condition type not found";
|
||||
EXPECT_TRUE( content.contains( "DIRICH" ) ) << "DIRICH boundary condition type not found";
|
||||
|
||||
// Verify pressure values
|
||||
EXPECT_TRUE( content.contains( "200" ) ) << "Pressure 200 bar not found";
|
||||
EXPECT_TRUE( content.contains( "250" ) ) << "Pressure 250 bar not found";
|
||||
|
||||
// Verify temperature values
|
||||
EXPECT_TRUE( content.contains( "80" ) ) << "Temperature 80 C not found";
|
||||
EXPECT_TRUE( content.contains( "90" ) ) << "Temperature 90 C not found";
|
||||
|
||||
// Verify component
|
||||
EXPECT_TRUE( content.contains( "WATER" ) ) << "Component WATER not found";
|
||||
}
|
||||
Reference in new issue
Block a user