mirror of
https://github.com/OPM/ResInsight.git
synced 2026-08-27 05:37:21 -05:00
#13467 Add model padding functionality for sector model export
Add Z-direction padding support for sector models based on OPM-Flow's padmodel.cpp. This feature enables users to add padding layers above and/or below the exported sector model grid. Adapts padmodel.cpp from https://github.com/hnil/opm-flowgeomechanics/blob/geomech_hypre_cgal/examples/padmodel.cpp Commit: 5ee483e Fixes #13467.
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
#include "RicExportEclipseSectorModelFeature.h"
|
||||
#include "RicExportSectorModelUi.h"
|
||||
|
||||
#include "RigModelPaddingSettings.h"
|
||||
#include "RigSimulationInputSettings.h"
|
||||
#include "RigSimulationInputTool.h"
|
||||
|
||||
@@ -117,6 +118,7 @@ void RicExportSectorModelFeature::doExport( RicExportSectorModelUi* exportSettin
|
||||
settings.setBcpropKeywords( bcpropKeywords );
|
||||
settings.setBoundaryCondition( exportSettings->boundaryCondition() );
|
||||
settings.setPorvMultiplier( exportSettings->porvMultiplier() );
|
||||
settings.setPaddingSettings( exportSettings->paddingSettings() );
|
||||
|
||||
// Get input deck file name from eclipse case
|
||||
QFileInfo fi( view->eclipseCase()->gridFileName() );
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "RigEclipseCaseData.h"
|
||||
#include "RigEclipseResultTools.h"
|
||||
#include "RigMainGrid.h"
|
||||
#include "RigModelPaddingSettings.h"
|
||||
|
||||
#include "Jobs/RimKeywordBcprop.h"
|
||||
#include "RimEclipseCase.h"
|
||||
@@ -101,6 +102,38 @@ RicExportSectorModelUi::RicExportSectorModelUi()
|
||||
m_keywordsToRemove.uiCapability()->setUiEditorTypeName( caf::PdmUiListEditor::uiEditorTypeName() );
|
||||
setDefaultKeywordsToRemove();
|
||||
|
||||
// Model padding fields
|
||||
CAF_PDM_InitField( &m_enablePadding, "EnablePadding", false, "Enable Model Padding" );
|
||||
caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &m_enablePadding );
|
||||
|
||||
CAF_PDM_InitField( &m_paddingNzUpper, "PaddingNzUpper", 0, "Number of Z Layers" );
|
||||
m_paddingNzUpper.setRange( 0, 100 );
|
||||
|
||||
CAF_PDM_InitField( &m_paddingTopUpper, "PaddingTopUpper", 0.0, "Top Depth" );
|
||||
|
||||
CAF_PDM_InitField( &m_paddingUpperPorosity, "PaddingUpperPorosity", 0.0, "Porosity" );
|
||||
m_paddingUpperPorosity.setRange( 0.0, 1.0 );
|
||||
|
||||
CAF_PDM_InitField( &m_paddingUpperEquilnum, "PaddingUpperEquilnum", 1, "EQUILNUM" );
|
||||
m_paddingUpperEquilnum.setMinValue( 1 );
|
||||
|
||||
CAF_PDM_InitField( &m_paddingNzLower, "PaddingNzLower", 0, "Number of Z Layers" );
|
||||
m_paddingNzLower.setRange( 0, 100 );
|
||||
|
||||
CAF_PDM_InitField( &m_paddingBottomLower, "PaddingBottomLower", 0.0, "Bottom Depth" );
|
||||
|
||||
CAF_PDM_InitField( &m_paddingMinThickness, "PaddingMinThickness", 0.1, "Minimum Layer Thickness" );
|
||||
m_paddingMinThickness.setMinValue( 0.001 );
|
||||
|
||||
CAF_PDM_InitField( &m_paddingFillGaps, "PaddingFillGaps", false, "Fill Gaps in Z Direction" );
|
||||
caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &m_paddingFillGaps );
|
||||
|
||||
CAF_PDM_InitField( &m_paddingMonotonicZcorn, "PaddingMonotonicZcorn", false, "Enforce Monotonic Z-Corners" );
|
||||
caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &m_paddingMonotonicZcorn );
|
||||
|
||||
CAF_PDM_InitField( &m_paddingVerticalPillars, "PaddingVerticalPillars", false, "Make Pillars Vertical" );
|
||||
caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &m_paddingVerticalPillars );
|
||||
|
||||
CAF_PDM_InitField( &m_createSimulationJob, "CreateSimulationJob", false, "Create New Simulation Job" );
|
||||
caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &m_createSimulationJob );
|
||||
CAF_PDM_InitFieldNoDefault( &m_simulationJobFolder, "SimulationJobFolder", "Working Folder" );
|
||||
@@ -135,6 +168,9 @@ RicExportSectorModelUi::RicExportSectorModelUi()
|
||||
m_pageNames << "Keyword Adjustments";
|
||||
m_pageSubtitles << "Set up special handling of certain keywords.";
|
||||
|
||||
m_pageNames << "Model Padding";
|
||||
m_pageSubtitles << "Configure optional Z-direction padding for the sector model grid.";
|
||||
|
||||
m_pageNames << "Simulation Job Settings";
|
||||
m_pageSubtitles << "Optionally create and/or run a simulation job using the exported sector model.";
|
||||
}
|
||||
@@ -235,6 +271,30 @@ void RicExportSectorModelUi::defineUiOrdering( QString uiConfigName, caf::PdmUiO
|
||||
updateConnectedEditors();
|
||||
} );
|
||||
}
|
||||
else if ( uiConfigName == m_pageNames[WizardPageEnum::ModelPadding] )
|
||||
{
|
||||
uiOrdering.add( &m_enablePadding );
|
||||
uiOrdering.addNewLabel( "" );
|
||||
|
||||
if ( m_enablePadding() )
|
||||
{
|
||||
auto upperGrp = uiOrdering.addNewGroup( "Upper Padding" );
|
||||
upperGrp->add( &m_paddingNzUpper );
|
||||
upperGrp->add( &m_paddingTopUpper );
|
||||
upperGrp->add( &m_paddingUpperPorosity );
|
||||
upperGrp->add( &m_paddingUpperEquilnum );
|
||||
|
||||
auto lowerGrp = uiOrdering.addNewGroup( "Lower Padding" );
|
||||
lowerGrp->add( &m_paddingNzLower );
|
||||
lowerGrp->add( &m_paddingBottomLower );
|
||||
|
||||
auto optionsGrp = uiOrdering.addNewGroup( "Grid Options" );
|
||||
optionsGrp->add( &m_paddingMinThickness );
|
||||
optionsGrp->add( &m_paddingFillGaps );
|
||||
optionsGrp->add( &m_paddingMonotonicZcorn );
|
||||
optionsGrp->add( &m_paddingVerticalPillars );
|
||||
}
|
||||
}
|
||||
else if ( uiConfigName == m_pageNames[WizardPageEnum::SimulationJob] )
|
||||
{
|
||||
auto simGrp = uiOrdering.addNewGroup( "OPM Flow Simulation" );
|
||||
@@ -478,7 +538,7 @@ void RicExportSectorModelUi::fieldChangedByUi( const caf::PdmFieldHandle* change
|
||||
{
|
||||
applyBoundaryDefaults();
|
||||
}
|
||||
else if ( ( changedField == &m_boundaryCondition ) || ( changedField == &m_refineGrid ) )
|
||||
else if ( ( changedField == &m_boundaryCondition ) || ( changedField == &m_refineGrid ) || ( changedField == &m_enablePadding ) )
|
||||
{
|
||||
updateConnectedEditors();
|
||||
}
|
||||
@@ -592,6 +652,26 @@ QString RicExportSectorModelUi::newSimulationJobName() const
|
||||
return m_simulationJobName();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RigModelPaddingSettings RicExportSectorModelUi::paddingSettings() const
|
||||
{
|
||||
RigModelPaddingSettings settings;
|
||||
settings.setEnabled( m_enablePadding() );
|
||||
settings.setNzUpper( m_paddingNzUpper() );
|
||||
settings.setTopUpper( m_paddingTopUpper() );
|
||||
settings.setUpperPorosity( m_paddingUpperPorosity() );
|
||||
settings.setUpperEquilnum( m_paddingUpperEquilnum() );
|
||||
settings.setNzLower( m_paddingNzLower() );
|
||||
settings.setBottomLower( m_paddingBottomLower() );
|
||||
settings.setMinLayerThickness( m_paddingMinThickness() );
|
||||
settings.setFillGaps( m_paddingFillGaps() );
|
||||
settings.setMonotonicZcorn( m_paddingMonotonicZcorn() );
|
||||
settings.setVerticalPillars( m_paddingVerticalPillars() );
|
||||
return settings;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -696,6 +776,18 @@ std::map<QString, QString> RicExportSectorModelUi::validate( const QString& conf
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( configName == m_pageNames[WizardPageEnum::ModelPadding] )
|
||||
{
|
||||
if ( m_enablePadding() )
|
||||
{
|
||||
auto settings = paddingSettings();
|
||||
auto errMessage = settings.validate();
|
||||
if ( !errMessage.isEmpty() )
|
||||
{
|
||||
fieldErrors[m_enablePadding.keyword()] = errMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( configName == m_pageNames[WizardPageEnum::SimulationJob] )
|
||||
{
|
||||
if ( m_createSimulationJob() )
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include <map>
|
||||
|
||||
class RigModelPaddingSettings;
|
||||
class RimKeywordBcprop;
|
||||
class RimEclipseCase;
|
||||
class RimEclipseView;
|
||||
@@ -77,6 +78,9 @@ public:
|
||||
QString newSimulationJobFolder() const;
|
||||
QString newSimulationJobName() const;
|
||||
|
||||
// Model padding settings accessor
|
||||
RigModelPaddingSettings paddingSettings() const;
|
||||
|
||||
protected:
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override;
|
||||
@@ -93,8 +97,9 @@ private:
|
||||
GridRefinement = 2,
|
||||
BoundaryConditions = 3,
|
||||
KeywordAdjustments = 4,
|
||||
SimulationJob = 5,
|
||||
TotalPages = 6
|
||||
ModelPadding = 5,
|
||||
SimulationJob = 6,
|
||||
TotalPages = 7
|
||||
};
|
||||
|
||||
void applyBoundaryDefaults();
|
||||
@@ -125,6 +130,19 @@ private:
|
||||
|
||||
caf::PdmField<std::vector<QString>> m_keywordsToRemove;
|
||||
|
||||
// Model padding fields
|
||||
caf::PdmField<bool> m_enablePadding;
|
||||
caf::PdmField<int> m_paddingNzUpper;
|
||||
caf::PdmField<double> m_paddingTopUpper;
|
||||
caf::PdmField<double> m_paddingUpperPorosity;
|
||||
caf::PdmField<int> m_paddingUpperEquilnum;
|
||||
caf::PdmField<int> m_paddingNzLower;
|
||||
caf::PdmField<double> m_paddingBottomLower;
|
||||
caf::PdmField<double> m_paddingMinThickness;
|
||||
caf::PdmField<bool> m_paddingFillGaps;
|
||||
caf::PdmField<bool> m_paddingMonotonicZcorn;
|
||||
caf::PdmField<bool> m_paddingVerticalPillars;
|
||||
|
||||
caf::PdmField<bool> m_createSimulationJob;
|
||||
caf::PdmField<caf::FilePath> m_simulationJobFolder;
|
||||
caf::PdmField<QString> m_simulationJobName;
|
||||
|
||||
@@ -254,12 +254,14 @@ bool RifOpmFlowDeckFile::loadDeck( std::string filename )
|
||||
{
|
||||
auto deck = Opm::Parser{}.parseFile( filename, internal::defaultParseContext(), errors );
|
||||
|
||||
m_deck = std::make_unique<Opm::Deck>( deck );
|
||||
m_fileDeck = std::make_unique<Opm::FileDeck>( deck );
|
||||
|
||||
splitDatesIfNecessary();
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
m_deck.reset();
|
||||
m_fileDeck.reset();
|
||||
return false;
|
||||
}
|
||||
@@ -1050,6 +1052,22 @@ bool RifOpmFlowDeckFile::addIncludeKeyword( std::string section, std::string key
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Opm::FileDeck* RifOpmFlowDeckFile::fileDeck()
|
||||
{
|
||||
return m_fileDeck.get();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const Opm::Deck* RifOpmFlowDeckFile::deck() const
|
||||
{
|
||||
return m_deck.get();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
class Deck;
|
||||
class DeckKeyword;
|
||||
class DeckItem;
|
||||
class DeckRecord;
|
||||
@@ -91,6 +92,9 @@ public:
|
||||
|
||||
bool addIncludeKeyword( std::string section, std::string keyword, std::string filePath );
|
||||
|
||||
Opm::FileDeck* fileDeck();
|
||||
const Opm::Deck* deck() const;
|
||||
|
||||
bool addKeyword( const std::string& section, const Opm::DeckKeyword& keyword );
|
||||
|
||||
bool replaceKeyword( const std::string& section, const Opm::DeckKeyword& keyword );
|
||||
@@ -106,5 +110,6 @@ private:
|
||||
void splitDatesIfNecessary();
|
||||
|
||||
private:
|
||||
std::unique_ptr<Opm::Deck> m_deck;
|
||||
std::unique_ptr<Opm::FileDeck> m_fileDeck;
|
||||
};
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
set(SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigModelPaddingSettings.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigPadModel.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigSimulationInputSettings.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigSimulationInputTool.h
|
||||
)
|
||||
|
||||
set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigModelPaddingSettings.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigPadModel.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigSimulationInputSettings.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigSimulationInputTool.cpp
|
||||
)
|
||||
|
||||
@@ -0,0 +1,267 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RigModelPaddingSettings.h"
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RigModelPaddingSettings::RigModelPaddingSettings()
|
||||
: m_enabled( false )
|
||||
, m_nzUpper( 0 )
|
||||
, m_topUpper( 0.0 )
|
||||
, m_upperPorosity( 0.0 )
|
||||
, m_upperEquilnum( 1 )
|
||||
, m_nzLower( 0 )
|
||||
, m_bottomLower( 0.0 )
|
||||
, m_minLayerThickness( 0.1 )
|
||||
, m_fillGaps( false )
|
||||
, m_monotonicZcorn( false )
|
||||
, m_verticalPillars( false )
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RigModelPaddingSettings::isEnabled() const
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigModelPaddingSettings::setEnabled( bool enabled )
|
||||
{
|
||||
m_enabled = enabled;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
int RigModelPaddingSettings::nzUpper() const
|
||||
{
|
||||
return m_nzUpper;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigModelPaddingSettings::setNzUpper( int value )
|
||||
{
|
||||
m_nzUpper = value;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigModelPaddingSettings::topUpper() const
|
||||
{
|
||||
return m_topUpper;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigModelPaddingSettings::setTopUpper( double value )
|
||||
{
|
||||
m_topUpper = value;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigModelPaddingSettings::upperPorosity() const
|
||||
{
|
||||
return m_upperPorosity;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigModelPaddingSettings::setUpperPorosity( double value )
|
||||
{
|
||||
m_upperPorosity = value;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
int RigModelPaddingSettings::upperEquilnum() const
|
||||
{
|
||||
return m_upperEquilnum;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigModelPaddingSettings::setUpperEquilnum( int value )
|
||||
{
|
||||
m_upperEquilnum = value;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
int RigModelPaddingSettings::nzLower() const
|
||||
{
|
||||
return m_nzLower;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigModelPaddingSettings::setNzLower( int value )
|
||||
{
|
||||
m_nzLower = value;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigModelPaddingSettings::bottomLower() const
|
||||
{
|
||||
return m_bottomLower;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigModelPaddingSettings::setBottomLower( double value )
|
||||
{
|
||||
m_bottomLower = value;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigModelPaddingSettings::minLayerThickness() const
|
||||
{
|
||||
return m_minLayerThickness;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigModelPaddingSettings::setMinLayerThickness( double value )
|
||||
{
|
||||
m_minLayerThickness = value;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RigModelPaddingSettings::fillGaps() const
|
||||
{
|
||||
return m_fillGaps;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigModelPaddingSettings::setFillGaps( bool value )
|
||||
{
|
||||
m_fillGaps = value;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RigModelPaddingSettings::monotonicZcorn() const
|
||||
{
|
||||
return m_monotonicZcorn;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigModelPaddingSettings::setMonotonicZcorn( bool value )
|
||||
{
|
||||
m_monotonicZcorn = value;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RigModelPaddingSettings::verticalPillars() const
|
||||
{
|
||||
return m_verticalPillars;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigModelPaddingSettings::setVerticalPillars( bool value )
|
||||
{
|
||||
m_verticalPillars = value;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RigModelPaddingSettings::validate() const
|
||||
{
|
||||
if ( !m_enabled )
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
QStringList errors;
|
||||
|
||||
// Check upper padding
|
||||
if ( m_nzUpper < 0 )
|
||||
{
|
||||
errors << "Number of upper padding layers cannot be negative.";
|
||||
}
|
||||
|
||||
if ( m_nzUpper > 0 )
|
||||
{
|
||||
if ( m_upperPorosity < 0.0 || m_upperPorosity > 1.0 )
|
||||
{
|
||||
errors << "Upper porosity must be between 0.0 and 1.0.";
|
||||
}
|
||||
|
||||
if ( m_upperEquilnum < 1 )
|
||||
{
|
||||
errors << "Upper EQUILNUM must be at least 1.";
|
||||
}
|
||||
}
|
||||
|
||||
// Check lower padding
|
||||
if ( m_nzLower < 0 )
|
||||
{
|
||||
errors << "Number of lower padding layers cannot be negative.";
|
||||
}
|
||||
|
||||
// Check geometry options
|
||||
if ( m_minLayerThickness <= 0.0 )
|
||||
{
|
||||
errors << "Minimum layer thickness must be positive.";
|
||||
}
|
||||
|
||||
// Check that at least one padding direction is specified
|
||||
if ( m_nzUpper == 0 && m_nzLower == 0 )
|
||||
{
|
||||
errors << "At least one padding direction (upper or lower) must have layers > 0.";
|
||||
}
|
||||
|
||||
return errors.join( "\n" );
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// Settings for model padding (adding Z-direction layers to sector models)
|
||||
///
|
||||
//==================================================================================================
|
||||
class RigModelPaddingSettings
|
||||
{
|
||||
public:
|
||||
RigModelPaddingSettings();
|
||||
|
||||
// Enable/disable
|
||||
bool isEnabled() const;
|
||||
void setEnabled( bool enabled );
|
||||
|
||||
// Upper padding
|
||||
int nzUpper() const;
|
||||
void setNzUpper( int value );
|
||||
double topUpper() const;
|
||||
void setTopUpper( double value );
|
||||
double upperPorosity() const;
|
||||
void setUpperPorosity( double value );
|
||||
int upperEquilnum() const;
|
||||
void setUpperEquilnum( int value );
|
||||
|
||||
// Lower padding
|
||||
int nzLower() const;
|
||||
void setNzLower( int value );
|
||||
double bottomLower() const;
|
||||
void setBottomLower( double value );
|
||||
|
||||
// Geometry options
|
||||
double minLayerThickness() const;
|
||||
void setMinLayerThickness( double value );
|
||||
bool fillGaps() const;
|
||||
void setFillGaps( bool value );
|
||||
bool monotonicZcorn() const;
|
||||
void setMonotonicZcorn( bool value );
|
||||
bool verticalPillars() const;
|
||||
void setVerticalPillars( bool value );
|
||||
|
||||
// Validation
|
||||
QString validate() const;
|
||||
|
||||
private:
|
||||
bool m_enabled;
|
||||
int m_nzUpper;
|
||||
double m_topUpper;
|
||||
double m_upperPorosity;
|
||||
int m_upperEquilnum;
|
||||
int m_nzLower;
|
||||
double m_bottomLower;
|
||||
double m_minLayerThickness;
|
||||
bool m_fillGaps;
|
||||
bool m_monotonicZcorn;
|
||||
bool m_verticalPillars;
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,61 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include <expected>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
class Deck;
|
||||
class FileDeck;
|
||||
} // namespace Opm
|
||||
|
||||
class RifOpmFlowDeckFile;
|
||||
class RigModelPaddingSettings;
|
||||
|
||||
//==================================================================================================
|
||||
/// Grid padding utilities adapted from OPM-Flow's padmodel.cpp
|
||||
/// Source: https://github.com/hnil/opm-flowgeomechanics/blob/geomech_hypre_cgal/examples/padmodel.cpp
|
||||
///
|
||||
/// This class provides functions to extend eclipse grid data in the Z-direction by adding
|
||||
/// padding layers above and/or below the existing grid. This is useful for sector models
|
||||
/// that need additional layers for geomechanical simulations.
|
||||
//==================================================================================================
|
||||
class RigPadModel
|
||||
{
|
||||
public:
|
||||
// Main entry point - extends all grid data via FileDeck in-place modification
|
||||
static std::expected<void, QString> extendGrid( RifOpmFlowDeckFile& deckFile, const RigModelPaddingSettings& settings );
|
||||
|
||||
// Helper functions for property array extension
|
||||
static double getPropsDefaultValue( const Opm::Deck& deck, const std::string& keyword );
|
||||
|
||||
static std::vector<double> extendPropertyArray( const std::vector<double>& original,
|
||||
int nx,
|
||||
int ny,
|
||||
int nz,
|
||||
int nzUpper,
|
||||
int nzLower,
|
||||
double upperDefault,
|
||||
double lowerDefault );
|
||||
};
|
||||
@@ -175,3 +175,19 @@ void RigSimulationInputSettings::setOutputDeckFileName( const QString& fileName
|
||||
{
|
||||
m_outputDeckFileName = fileName;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const RigModelPaddingSettings& RigSimulationInputSettings::paddingSettings() const
|
||||
{
|
||||
return m_paddingSettings;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigSimulationInputSettings::setPaddingSettings( const RigModelPaddingSettings& settings )
|
||||
{
|
||||
m_paddingSettings = settings;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "RiaModelExportDefines.h"
|
||||
#include "RigModelPaddingSettings.h"
|
||||
|
||||
#include "cafAppEnum.h"
|
||||
#include "cafVecIjk.h"
|
||||
@@ -76,6 +77,10 @@ public:
|
||||
QString outputDeckFileName() const;
|
||||
void setOutputDeckFileName( const QString& fileName );
|
||||
|
||||
// Model padding
|
||||
const RigModelPaddingSettings& paddingSettings() const;
|
||||
void setPaddingSettings( const RigModelPaddingSettings& settings );
|
||||
|
||||
private:
|
||||
caf::VecIjk0 m_min;
|
||||
caf::VecIjk0 m_max;
|
||||
@@ -86,4 +91,5 @@ private:
|
||||
double m_porvMultiplier;
|
||||
QString m_inputDeckFileName;
|
||||
QString m_outputDeckFileName;
|
||||
RigModelPaddingSettings m_paddingSettings;
|
||||
};
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
#include "RiaLogging.h"
|
||||
#include "RiaNncDefines.h"
|
||||
|
||||
#include "RigModelPaddingSettings.h"
|
||||
#include "RigPadModel.h"
|
||||
|
||||
#include "RifEclipseInputFileTools.h"
|
||||
#include "RifOpmDeckTools.h"
|
||||
#include "RifOpmFlowDeckFile.h"
|
||||
@@ -152,6 +155,15 @@ std::expected<void, QString> RigSimulationInputTool::exportSimulationInput( RimE
|
||||
return result;
|
||||
}
|
||||
|
||||
// Apply model padding if enabled
|
||||
if ( settings.paddingSettings().isEnabled() )
|
||||
{
|
||||
if ( auto result = applyModelPadding( deckFile, settings.paddingSettings() ); !result )
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove SKIP keywords that were used as placeholders for filtered-out keywords
|
||||
deckFile.removeKeywords( "SKIP" );
|
||||
|
||||
@@ -1777,3 +1789,12 @@ std::expected<void, QString> RigSimulationInputTool::exportEditNncKeyword( RimEc
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::expected<void, QString> RigSimulationInputTool::applyModelPadding( RifOpmFlowDeckFile& deckFile,
|
||||
const RigModelPaddingSettings& paddingSettings )
|
||||
{
|
||||
return RigPadModel::extendGrid( deckFile, paddingSettings );
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
class RimEclipseView;
|
||||
class RimEclipseCase;
|
||||
class RigModelPaddingSettings;
|
||||
class RigSimulationInputSettings;
|
||||
class RifOpmFlowDeckFile;
|
||||
class RigSimWellData;
|
||||
@@ -153,6 +154,8 @@ private:
|
||||
static std::expected<void, QString>
|
||||
exportEditNncKeyword( RimEclipseCase* eclipseCase, const RigSimulationInputSettings& settings, RifOpmFlowDeckFile& deckFile );
|
||||
|
||||
static std::expected<void, QString> applyModelPadding( RifOpmFlowDeckFile& deckFile, const RigModelPaddingSettings& paddingSettings );
|
||||
|
||||
// Utility: Transform global IJK to sector-relative coordinates with refinement
|
||||
static caf::VecIjk0 transformToSectorCoordinates( const caf::VecIjk0& globalIjk, const caf::VecIjk0& min, const cvf::Vec3st& refinement );
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ endif(MSVC)
|
||||
set(SOURCE_UNITTEST_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/cvfGeometryTools-Test.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/Ert-Test.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigModelPaddingSettings-Test.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigPadModel-Test.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigSimulationInputTool-Test.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RigBoundingBoxIjk-Test.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifcCommandCore-Test.cpp
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "RigModelPaddingSettings.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test default values
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigModelPaddingSettings, DefaultValues )
|
||||
{
|
||||
RigModelPaddingSettings settings;
|
||||
|
||||
EXPECT_FALSE( settings.isEnabled() );
|
||||
EXPECT_EQ( 0, settings.nzUpper() );
|
||||
EXPECT_DOUBLE_EQ( 0.0, settings.topUpper() );
|
||||
EXPECT_DOUBLE_EQ( 0.0, settings.upperPorosity() );
|
||||
EXPECT_EQ( 1, settings.upperEquilnum() );
|
||||
EXPECT_EQ( 0, settings.nzLower() );
|
||||
EXPECT_DOUBLE_EQ( 0.0, settings.bottomLower() );
|
||||
EXPECT_DOUBLE_EQ( 0.1, settings.minLayerThickness() );
|
||||
EXPECT_FALSE( settings.fillGaps() );
|
||||
EXPECT_FALSE( settings.monotonicZcorn() );
|
||||
EXPECT_FALSE( settings.verticalPillars() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test setters and getters
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigModelPaddingSettings, SettersAndGetters )
|
||||
{
|
||||
RigModelPaddingSettings settings;
|
||||
|
||||
settings.setEnabled( true );
|
||||
settings.setNzUpper( 5 );
|
||||
settings.setTopUpper( 1000.0 );
|
||||
settings.setUpperPorosity( 0.25 );
|
||||
settings.setUpperEquilnum( 2 );
|
||||
settings.setNzLower( 3 );
|
||||
settings.setBottomLower( 3500.0 );
|
||||
settings.setMinLayerThickness( 0.5 );
|
||||
settings.setFillGaps( true );
|
||||
settings.setMonotonicZcorn( true );
|
||||
settings.setVerticalPillars( true );
|
||||
|
||||
EXPECT_TRUE( settings.isEnabled() );
|
||||
EXPECT_EQ( 5, settings.nzUpper() );
|
||||
EXPECT_DOUBLE_EQ( 1000.0, settings.topUpper() );
|
||||
EXPECT_DOUBLE_EQ( 0.25, settings.upperPorosity() );
|
||||
EXPECT_EQ( 2, settings.upperEquilnum() );
|
||||
EXPECT_EQ( 3, settings.nzLower() );
|
||||
EXPECT_DOUBLE_EQ( 3500.0, settings.bottomLower() );
|
||||
EXPECT_DOUBLE_EQ( 0.5, settings.minLayerThickness() );
|
||||
EXPECT_TRUE( settings.fillGaps() );
|
||||
EXPECT_TRUE( settings.monotonicZcorn() );
|
||||
EXPECT_TRUE( settings.verticalPillars() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test validation when disabled
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigModelPaddingSettings, Validation_WhenDisabled )
|
||||
{
|
||||
RigModelPaddingSettings settings;
|
||||
settings.setEnabled( false );
|
||||
|
||||
QString errors = settings.validate();
|
||||
|
||||
EXPECT_TRUE( errors.isEmpty() ) << "Validation should pass when padding is disabled";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test validation with valid upper padding settings
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigModelPaddingSettings, Validation_ValidUpperPadding )
|
||||
{
|
||||
RigModelPaddingSettings settings;
|
||||
settings.setEnabled( true );
|
||||
settings.setNzUpper( 5 );
|
||||
settings.setTopUpper( 1000.0 );
|
||||
settings.setUpperPorosity( 0.25 );
|
||||
settings.setUpperEquilnum( 1 );
|
||||
settings.setMinLayerThickness( 0.1 );
|
||||
|
||||
QString errors = settings.validate();
|
||||
|
||||
EXPECT_TRUE( errors.isEmpty() ) << "Validation should pass with valid upper padding: " << errors.toStdString();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test validation with valid lower padding settings
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigModelPaddingSettings, Validation_ValidLowerPadding )
|
||||
{
|
||||
RigModelPaddingSettings settings;
|
||||
settings.setEnabled( true );
|
||||
settings.setNzLower( 3 );
|
||||
settings.setBottomLower( 3500.0 );
|
||||
settings.setMinLayerThickness( 0.1 );
|
||||
|
||||
QString errors = settings.validate();
|
||||
|
||||
EXPECT_TRUE( errors.isEmpty() ) << "Validation should pass with valid lower padding: " << errors.toStdString();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test validation with valid both upper and lower padding
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigModelPaddingSettings, Validation_ValidBothPadding )
|
||||
{
|
||||
RigModelPaddingSettings settings;
|
||||
settings.setEnabled( true );
|
||||
settings.setNzUpper( 2 );
|
||||
settings.setTopUpper( 1000.0 );
|
||||
settings.setUpperPorosity( 0.3 );
|
||||
settings.setUpperEquilnum( 1 );
|
||||
settings.setNzLower( 3 );
|
||||
settings.setBottomLower( 3500.0 );
|
||||
settings.setMinLayerThickness( 0.5 );
|
||||
|
||||
QString errors = settings.validate();
|
||||
|
||||
EXPECT_TRUE( errors.isEmpty() ) << "Validation should pass with valid both padding: " << errors.toStdString();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test validation fails when no layers specified
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigModelPaddingSettings, Validation_NoLayersSpecified )
|
||||
{
|
||||
RigModelPaddingSettings settings;
|
||||
settings.setEnabled( true );
|
||||
settings.setNzUpper( 0 );
|
||||
settings.setNzLower( 0 );
|
||||
|
||||
QString errors = settings.validate();
|
||||
|
||||
EXPECT_FALSE( errors.isEmpty() );
|
||||
EXPECT_TRUE( errors.contains( "At least one padding direction" ) );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test validation fails with negative upper layers
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigModelPaddingSettings, Validation_NegativeUpperLayers )
|
||||
{
|
||||
RigModelPaddingSettings settings;
|
||||
settings.setEnabled( true );
|
||||
settings.setNzUpper( -1 );
|
||||
settings.setNzLower( 5 );
|
||||
|
||||
QString errors = settings.validate();
|
||||
|
||||
EXPECT_FALSE( errors.isEmpty() );
|
||||
EXPECT_TRUE( errors.contains( "cannot be negative" ) );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test validation fails with negative lower layers
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigModelPaddingSettings, Validation_NegativeLowerLayers )
|
||||
{
|
||||
RigModelPaddingSettings settings;
|
||||
settings.setEnabled( true );
|
||||
settings.setNzUpper( 5 );
|
||||
settings.setNzLower( -2 );
|
||||
|
||||
QString errors = settings.validate();
|
||||
|
||||
EXPECT_FALSE( errors.isEmpty() );
|
||||
EXPECT_TRUE( errors.contains( "cannot be negative" ) );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test validation fails with invalid porosity (< 0)
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigModelPaddingSettings, Validation_InvalidPorosityNegative )
|
||||
{
|
||||
RigModelPaddingSettings settings;
|
||||
settings.setEnabled( true );
|
||||
settings.setNzUpper( 5 );
|
||||
settings.setUpperPorosity( -0.1 );
|
||||
|
||||
QString errors = settings.validate();
|
||||
|
||||
EXPECT_FALSE( errors.isEmpty() );
|
||||
EXPECT_TRUE( errors.contains( "porosity" ) );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test validation fails with invalid porosity (> 1)
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigModelPaddingSettings, Validation_InvalidPorosityTooHigh )
|
||||
{
|
||||
RigModelPaddingSettings settings;
|
||||
settings.setEnabled( true );
|
||||
settings.setNzUpper( 5 );
|
||||
settings.setUpperPorosity( 1.5 );
|
||||
|
||||
QString errors = settings.validate();
|
||||
|
||||
EXPECT_FALSE( errors.isEmpty() );
|
||||
EXPECT_TRUE( errors.contains( "porosity" ) );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test validation fails with invalid EQUILNUM
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigModelPaddingSettings, Validation_InvalidEquilnum )
|
||||
{
|
||||
RigModelPaddingSettings settings;
|
||||
settings.setEnabled( true );
|
||||
settings.setNzUpper( 5 );
|
||||
settings.setUpperPorosity( 0.25 );
|
||||
settings.setUpperEquilnum( 0 );
|
||||
|
||||
QString errors = settings.validate();
|
||||
|
||||
EXPECT_FALSE( errors.isEmpty() );
|
||||
EXPECT_TRUE( errors.contains( "EQUILNUM" ) );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test validation fails with non-positive layer thickness
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigModelPaddingSettings, Validation_NonPositiveLayerThickness )
|
||||
{
|
||||
RigModelPaddingSettings settings;
|
||||
settings.setEnabled( true );
|
||||
settings.setNzUpper( 5 );
|
||||
settings.setUpperPorosity( 0.25 );
|
||||
settings.setMinLayerThickness( 0.0 );
|
||||
|
||||
QString errors = settings.validate();
|
||||
|
||||
EXPECT_FALSE( errors.isEmpty() );
|
||||
EXPECT_TRUE( errors.contains( "thickness" ) );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test validation with edge case porosity values (0 and 1)
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigModelPaddingSettings, Validation_EdgeCasePorosity )
|
||||
{
|
||||
RigModelPaddingSettings settings;
|
||||
settings.setEnabled( true );
|
||||
settings.setNzUpper( 5 );
|
||||
settings.setMinLayerThickness( 0.1 );
|
||||
|
||||
// Test porosity = 0 (valid)
|
||||
settings.setUpperPorosity( 0.0 );
|
||||
QString errors = settings.validate();
|
||||
EXPECT_TRUE( errors.isEmpty() ) << "Porosity 0.0 should be valid: " << errors.toStdString();
|
||||
|
||||
// Test porosity = 1 (valid)
|
||||
settings.setUpperPorosity( 1.0 );
|
||||
errors = settings.validate();
|
||||
EXPECT_TRUE( errors.isEmpty() ) << "Porosity 1.0 should be valid: " << errors.toStdString();
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "RigPadModel.h"
|
||||
|
||||
#include "opm/input/eclipse/Deck/Deck.hpp"
|
||||
#include "opm/input/eclipse/Parser/Parser.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test extendPropertyArray with only upper padding
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigPadModel, ExtendPropertyArray_UpperOnly )
|
||||
{
|
||||
// Create a 2x2x2 grid (8 cells)
|
||||
int nx = 2, ny = 2, nz = 2;
|
||||
std::vector<double> original( nx * ny * nz, 0.25 ); // PORO = 0.25
|
||||
|
||||
// Add 2 upper padding layers
|
||||
int nzUpper = 2;
|
||||
int nzLower = 0;
|
||||
double upperDefault = 0.1;
|
||||
double lowerDefault = 0.0;
|
||||
|
||||
auto result = RigPadModel::extendPropertyArray( original, nx, ny, nz, nzUpper, nzLower, upperDefault, lowerDefault );
|
||||
|
||||
// Expected size: nx * ny * (nz + nzUpper + nzLower) = 2 * 2 * 4 = 16
|
||||
EXPECT_EQ( 16u, result.size() );
|
||||
|
||||
// First 8 values (2 upper layers * 4 cells) should be upperDefault
|
||||
for ( int i = 0; i < 8; i++ )
|
||||
{
|
||||
EXPECT_DOUBLE_EQ( upperDefault, result[i] ) << "Upper padding cell " << i << " should be " << upperDefault;
|
||||
}
|
||||
|
||||
// Next 8 values should be original data
|
||||
for ( int i = 8; i < 16; i++ )
|
||||
{
|
||||
EXPECT_DOUBLE_EQ( 0.25, result[i] ) << "Original cell " << ( i - 8 ) << " should be 0.25";
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test extendPropertyArray with only lower padding
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigPadModel, ExtendPropertyArray_LowerOnly )
|
||||
{
|
||||
// Create a 2x2x2 grid (8 cells)
|
||||
int nx = 2, ny = 2, nz = 2;
|
||||
std::vector<double> original( nx * ny * nz, 0.25 ); // PORO = 0.25
|
||||
|
||||
// Add 3 lower padding layers
|
||||
int nzUpper = 0;
|
||||
int nzLower = 3;
|
||||
double upperDefault = 0.1;
|
||||
double lowerDefault = 0.0;
|
||||
|
||||
auto result = RigPadModel::extendPropertyArray( original, nx, ny, nz, nzUpper, nzLower, upperDefault, lowerDefault );
|
||||
|
||||
// Expected size: nx * ny * (nz + nzUpper + nzLower) = 2 * 2 * 5 = 20
|
||||
EXPECT_EQ( 20u, result.size() );
|
||||
|
||||
// First 8 values should be original data
|
||||
for ( int i = 0; i < 8; i++ )
|
||||
{
|
||||
EXPECT_DOUBLE_EQ( 0.25, result[i] ) << "Original cell " << i << " should be 0.25";
|
||||
}
|
||||
|
||||
// Last 12 values (3 lower layers * 4 cells) should be lowerDefault
|
||||
for ( int i = 8; i < 20; i++ )
|
||||
{
|
||||
EXPECT_DOUBLE_EQ( lowerDefault, result[i] ) << "Lower padding cell " << ( i - 8 ) << " should be " << lowerDefault;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test extendPropertyArray with both upper and lower padding
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigPadModel, ExtendPropertyArray_BothPadding )
|
||||
{
|
||||
// Create a 3x3x2 grid (18 cells)
|
||||
int nx = 3, ny = 3, nz = 2;
|
||||
std::vector<double> original( nx * ny * nz );
|
||||
for ( int i = 0; i < nx * ny * nz; i++ )
|
||||
{
|
||||
original[i] = 0.3; // PORO = 0.3
|
||||
}
|
||||
|
||||
// Add 1 upper and 2 lower padding layers
|
||||
int nzUpper = 1;
|
||||
int nzLower = 2;
|
||||
double upperDefault = 0.05;
|
||||
double lowerDefault = 0.02;
|
||||
|
||||
auto result = RigPadModel::extendPropertyArray( original, nx, ny, nz, nzUpper, nzLower, upperDefault, lowerDefault );
|
||||
|
||||
// Expected size: 3 * 3 * (2 + 1 + 2) = 45
|
||||
EXPECT_EQ( 45u, result.size() );
|
||||
|
||||
// First 9 values (1 upper layer * 9 cells) should be upperDefault
|
||||
for ( int i = 0; i < 9; i++ )
|
||||
{
|
||||
EXPECT_DOUBLE_EQ( upperDefault, result[i] );
|
||||
}
|
||||
|
||||
// Middle 18 values should be original data
|
||||
for ( int i = 9; i < 27; i++ )
|
||||
{
|
||||
EXPECT_DOUBLE_EQ( 0.3, result[i] );
|
||||
}
|
||||
|
||||
// Last 18 values (2 lower layers * 9 cells) should be lowerDefault
|
||||
for ( int i = 27; i < 45; i++ )
|
||||
{
|
||||
EXPECT_DOUBLE_EQ( lowerDefault, result[i] );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test extendPropertyArray with zero padding (no change)
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigPadModel, ExtendPropertyArray_NoPadding )
|
||||
{
|
||||
int nx = 2, ny = 2, nz = 2;
|
||||
std::vector<double> original( nx * ny * nz, 0.5 );
|
||||
|
||||
auto result = RigPadModel::extendPropertyArray( original, nx, ny, nz, 0, 0, 0.0, 0.0 );
|
||||
|
||||
EXPECT_EQ( original.size(), result.size() );
|
||||
for ( size_t i = 0; i < original.size(); i++ )
|
||||
{
|
||||
EXPECT_DOUBLE_EQ( original[i], result[i] );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test extendPropertyArray preserves original data order
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigPadModel, ExtendPropertyArray_DataOrder )
|
||||
{
|
||||
// Create a 2x2x2 grid with sequential values
|
||||
int nx = 2, ny = 2, nz = 2;
|
||||
std::vector<double> original( nx * ny * nz );
|
||||
for ( int i = 0; i < nx * ny * nz; i++ )
|
||||
{
|
||||
original[i] = static_cast<double>( i + 1 );
|
||||
}
|
||||
|
||||
// Add 1 upper and 1 lower padding layer
|
||||
auto result = RigPadModel::extendPropertyArray( original, nx, ny, nz, 1, 1, 0.0, 99.0 );
|
||||
|
||||
// Check that original data is preserved in the middle
|
||||
int xyCount = nx * ny;
|
||||
for ( int i = 0; i < nx * ny * nz; i++ )
|
||||
{
|
||||
EXPECT_DOUBLE_EQ( original[i], result[xyCount + i] ) << "Original data at index " << i << " should be preserved";
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test empty input arrays
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigPadModel, ExtendPropertyArray_EmptyInput )
|
||||
{
|
||||
std::vector<double> empty;
|
||||
|
||||
auto result = RigPadModel::extendPropertyArray( empty, 2, 2, 0, 2, 2, 0.5, 0.5 );
|
||||
|
||||
// Should have 2*2*(0+2+2) = 16 elements, all with padding values
|
||||
EXPECT_EQ( 16u, result.size() );
|
||||
for ( const auto& v : result )
|
||||
{
|
||||
EXPECT_DOUBLE_EQ( 0.5, v );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test large grid dimensions
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigPadModel, ExtendPropertyArray_LargeGrid )
|
||||
{
|
||||
// Simulate a typical sector model size
|
||||
int nx = 50, ny = 50, nz = 20;
|
||||
std::vector<double> original( nx * ny * nz, 0.2 );
|
||||
|
||||
// Add padding
|
||||
int nzUpper = 5;
|
||||
int nzLower = 10;
|
||||
|
||||
auto result = RigPadModel::extendPropertyArray( original, nx, ny, nz, nzUpper, nzLower, 0.1, 0.0 );
|
||||
|
||||
size_t expectedSize = static_cast<size_t>( nx ) * ny * ( nz + nzUpper + nzLower );
|
||||
EXPECT_EQ( expectedSize, result.size() );
|
||||
|
||||
// Verify structure: upper padding, original, lower padding
|
||||
int xyCount = nx * ny;
|
||||
|
||||
// Sample check on upper padding
|
||||
EXPECT_DOUBLE_EQ( 0.1, result[0] );
|
||||
EXPECT_DOUBLE_EQ( 0.1, result[nzUpper * xyCount - 1] );
|
||||
|
||||
// Sample check on original
|
||||
EXPECT_DOUBLE_EQ( 0.2, result[nzUpper * xyCount] );
|
||||
EXPECT_DOUBLE_EQ( 0.2, result[( nzUpper + nz ) * xyCount - 1] );
|
||||
|
||||
// Sample check on lower padding
|
||||
EXPECT_DOUBLE_EQ( 0.0, result[( nzUpper + nz ) * xyCount] );
|
||||
EXPECT_DOUBLE_EQ( 0.0, result[result.size() - 1] );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test getPropsDefaultValue returns physically correct defaults from saturation tables.
|
||||
/// A minimal deck with SWOF/SGOF tables is parsed, and the function should return
|
||||
/// non-zero values for saturation endpoint keywords (not the old hardcoded 0.0).
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigPadModel, GetPropsDefaultValue_FromSaturationTables )
|
||||
{
|
||||
// Minimal deck with OIL/WATER/GAS phases and SWOF+SGOF tables
|
||||
std::string deckString = R"(
|
||||
RUNSPEC
|
||||
OIL
|
||||
WATER
|
||||
GAS
|
||||
TABDIMS
|
||||
1 /
|
||||
EQLDIMS
|
||||
1 /
|
||||
DIMENS
|
||||
2 2 1 /
|
||||
|
||||
GRID
|
||||
DX
|
||||
4*100 /
|
||||
DY
|
||||
4*100 /
|
||||
DZ
|
||||
4*10 /
|
||||
TOPS
|
||||
4*2000 /
|
||||
|
||||
PROPS
|
||||
SWOF
|
||||
0.2 0.0 1.0 0.0
|
||||
0.5 0.3 0.5 0.0
|
||||
1.0 1.0 0.0 0.0
|
||||
/
|
||||
SGOF
|
||||
0.0 0.0 1.0 0.0
|
||||
0.3 0.2 0.5 0.0
|
||||
0.8 1.0 0.0 0.0
|
||||
/
|
||||
|
||||
SOLUTION
|
||||
EQUIL
|
||||
2000 200 2200 0 1800 0 /
|
||||
|
||||
SCHEDULE
|
||||
)";
|
||||
|
||||
auto deck = Opm::Parser{}.parseString( deckString );
|
||||
|
||||
// SWATINIT should default to 1.0 (padding cells fully water-saturated)
|
||||
EXPECT_DOUBLE_EQ( 1.0, RigPadModel::getPropsDefaultValue( deck, "SWATINIT" ) );
|
||||
|
||||
// SWU (max water saturation) should be 1.0 from the SWOF table (last Sw entry)
|
||||
EXPECT_DOUBLE_EQ( 1.0, RigPadModel::getPropsDefaultValue( deck, "SWU" ) );
|
||||
|
||||
// SWL (connate water) should be 0.2 from the SWOF table (first Sw entry)
|
||||
EXPECT_DOUBLE_EQ( 0.2, RigPadModel::getPropsDefaultValue( deck, "SWL" ) );
|
||||
|
||||
// SGU (max gas saturation) should be 0.8 from the SGOF table (last Sg entry)
|
||||
EXPECT_DOUBLE_EQ( 0.8, RigPadModel::getPropsDefaultValue( deck, "SGU" ) );
|
||||
|
||||
// KRW (max water relperm) should be 1.0 from the SWOF table
|
||||
EXPECT_DOUBLE_EQ( 1.0, RigPadModel::getPropsDefaultValue( deck, "KRW" ) );
|
||||
|
||||
// KRG (max gas relperm) should be 1.0 from the SGOF table
|
||||
EXPECT_DOUBLE_EQ( 1.0, RigPadModel::getPropsDefaultValue( deck, "KRG" ) );
|
||||
|
||||
// KRO (max oil relperm) should be 1.0 from the SWOF table
|
||||
EXPECT_DOUBLE_EQ( 1.0, RigPadModel::getPropsDefaultValue( deck, "KRO" ) );
|
||||
|
||||
// Directional variant (SWL with X suffix) should map to same value as SWL
|
||||
EXPECT_DOUBLE_EQ( 0.2, RigPadModel::getPropsDefaultValue( deck, "SWLX" ) );
|
||||
|
||||
// Imbibition variant (ISWL) should map to SWL
|
||||
EXPECT_DOUBLE_EQ( 0.2, RigPadModel::getPropsDefaultValue( deck, "ISWL" ) );
|
||||
|
||||
// Unknown keyword should return 0.0
|
||||
EXPECT_DOUBLE_EQ( 0.0, RigPadModel::getPropsDefaultValue( deck, "UNKNOWN_KEYWORD" ) );
|
||||
}
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "RigEclipseCaseData.h"
|
||||
#include "RigEclipseCaseDataTools.h"
|
||||
#include "RigMainGrid.h"
|
||||
#include "RigModelPaddingSettings.h"
|
||||
#include "RigSimulationInputSettings.h"
|
||||
#include "RimEclipseResultCase.h"
|
||||
|
||||
@@ -1306,3 +1307,125 @@ TEST( RigSimulationInputTool, RefineEDITNNCConnection_CorrespondingSubcells )
|
||||
EXPECT_EQ( caf::VecIjk0( 7, 9, 5 ), refined[3].cell1 );
|
||||
EXPECT_EQ( caf::VecIjk0( 13, 17, 7 ), refined[3].cell2 );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Test exportSimulationInput with model5 data and model padding
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RigSimulationInputTool, ExportModel5WithPadding )
|
||||
{
|
||||
// Load model5 test data
|
||||
QDir baseFolder( TEST_DATA_DIR );
|
||||
bool subFolderExists = baseFolder.cd( "RigSimulationInputTool/model5" );
|
||||
ASSERT_TRUE( subFolderExists );
|
||||
|
||||
QString egridFilename( "0_BASE_MODEL5.EGRID" );
|
||||
QString egridFilePath = baseFolder.absoluteFilePath( egridFilename );
|
||||
ASSERT_TRUE( QFile::exists( egridFilePath ) );
|
||||
|
||||
QString dataFilename( "0_BASE_MODEL5.DATA" );
|
||||
QString dataFilePath = baseFolder.absoluteFilePath( dataFilename );
|
||||
ASSERT_TRUE( QFile::exists( dataFilePath ) );
|
||||
|
||||
// Create Eclipse case and load grid
|
||||
std::unique_ptr<RimEclipseResultCase> resultCase( new RimEclipseResultCase );
|
||||
cvf::ref<RigEclipseCaseData> caseData = new RigEclipseCaseData( resultCase.get() );
|
||||
|
||||
cvf::ref<RifReaderEclipseOutput> reader = new RifReaderEclipseOutput;
|
||||
bool loadResult = reader->open( egridFilePath, caseData.p() );
|
||||
ASSERT_TRUE( loadResult );
|
||||
|
||||
// Verify grid dimensions (20x30x10)
|
||||
ASSERT_TRUE( caseData->mainGrid() != nullptr );
|
||||
EXPECT_EQ( 20u, caseData->mainGrid()->cellCountI() );
|
||||
EXPECT_EQ( 30u, caseData->mainGrid()->cellCountJ() );
|
||||
EXPECT_EQ( 10u, caseData->mainGrid()->cellCountK() );
|
||||
|
||||
// Create temporary directory for export
|
||||
QTemporaryDir tempDir;
|
||||
ASSERT_TRUE( tempDir.isValid() );
|
||||
|
||||
QString exportFilePath = tempDir.path() + "/exported_model_padded.DATA";
|
||||
|
||||
// Set up export settings for sector export with padding
|
||||
RigSimulationInputSettings settings;
|
||||
settings.setMin( caf::VecIjk0( 0, 0, 0 ) );
|
||||
settings.setMax( caf::VecIjk0( 19, 14, 9 ) ); // Sector (0-based inclusive) -> 20x15x10
|
||||
settings.setRefinement( cvf::Vec3st( 1, 1, 1 ) ); // No refinement
|
||||
settings.setInputDeckFileName( dataFilePath );
|
||||
settings.setOutputDeckFileName( exportFilePath );
|
||||
|
||||
// Configure padding: 2 upper, 3 lower
|
||||
RigModelPaddingSettings paddingSettings;
|
||||
paddingSettings.setEnabled( true );
|
||||
paddingSettings.setNzUpper( 2 );
|
||||
paddingSettings.setNzLower( 3 );
|
||||
paddingSettings.setTopUpper( 1000.0 );
|
||||
paddingSettings.setBottomLower( 3600.0 );
|
||||
paddingSettings.setUpperPorosity( 0.1 );
|
||||
paddingSettings.setMinLayerThickness( 10.0 );
|
||||
paddingSettings.setVerticalPillars( true );
|
||||
paddingSettings.setMonotonicZcorn( true );
|
||||
paddingSettings.setFillGaps( true );
|
||||
settings.setPaddingSettings( paddingSettings );
|
||||
|
||||
// Create visibility from IJK bounds
|
||||
cvf::ref<cvf::UByteArray> visibility =
|
||||
RigEclipseCaseDataTools::createVisibilityFromIjkBounds( caseData.p(), settings.min(), settings.max() );
|
||||
|
||||
// Export simulation input
|
||||
resultCase->setReservoirData( caseData.p() );
|
||||
auto exportResult = RigSimulationInputTool::exportSimulationInput( *resultCase, settings, visibility.p() );
|
||||
ASSERT_TRUE( exportResult.has_value() ) << "Export failed: " << exportResult.error().toStdString();
|
||||
|
||||
// Verify exported file exists
|
||||
ASSERT_TRUE( QFile::exists( exportFilePath ) );
|
||||
|
||||
// Load the exported deck file using RifOpmFlowDeckFile
|
||||
RifOpmFlowDeckFile deckFile;
|
||||
bool deckLoadResult = deckFile.loadDeck( exportFilePath.toStdString() );
|
||||
ASSERT_TRUE( deckLoadResult ) << "Failed to load exported deck file";
|
||||
|
||||
// Get all keywords from the deck
|
||||
std::vector<std::string> allKeywords = deckFile.keywords( false );
|
||||
|
||||
// Verify key keywords exist in the file
|
||||
EXPECT_TRUE( std::find( allKeywords.begin(), allKeywords.end(), "DIMENS" ) != allKeywords.end() );
|
||||
EXPECT_TRUE( std::find( allKeywords.begin(), allKeywords.end(), "SPECGRID" ) != allKeywords.end() )
|
||||
<< "SPECGRID keyword missing from exported file";
|
||||
EXPECT_TRUE( std::find( allKeywords.begin(), allKeywords.end(), "COORD" ) != allKeywords.end() );
|
||||
EXPECT_TRUE( std::find( allKeywords.begin(), allKeywords.end(), "ZCORN" ) != allKeywords.end() );
|
||||
EXPECT_TRUE( std::find( allKeywords.begin(), allKeywords.end(), "ACTNUM" ) != allKeywords.end() );
|
||||
EXPECT_TRUE( std::find( allKeywords.begin(), allKeywords.end(), "PORO" ) != allKeywords.end() );
|
||||
|
||||
// Read the file content to verify padded dimensions
|
||||
QFile file( exportFilePath );
|
||||
ASSERT_TRUE( file.open( QIODevice::ReadOnly | QIODevice::Text ) );
|
||||
QString fileContent = file.readAll();
|
||||
file.close();
|
||||
|
||||
// Verify dimensions are correct for the padded sector (20x15x15)
|
||||
// Original sector: 20x15x10, with nzUpper=2, nzLower=3: 20x15x(10+2+3) = 20x15x15
|
||||
EXPECT_TRUE( fileContent.contains( " 20 15 15 /" ) ) << "File does not contain expected padded dimensions 20 15 15";
|
||||
|
||||
// Verify SPECGRID/DIMENS show correct padded dimensions
|
||||
auto specgridKw = deckFile.findKeyword( "SPECGRID" );
|
||||
ASSERT_TRUE( specgridKw.has_value() );
|
||||
EXPECT_EQ( 20, specgridKw->getRecord( 0 ).getItem( 0 ).get<int>( 0 ) );
|
||||
EXPECT_EQ( 15, specgridKw->getRecord( 0 ).getItem( 1 ).get<int>( 0 ) );
|
||||
EXPECT_EQ( 15, specgridKw->getRecord( 0 ).getItem( 2 ).get<int>( 0 ) );
|
||||
|
||||
// Verify COORD array size: (NX+1)*(NY+1)*6 = 21*16*6 = 2016 (unchanged by padding)
|
||||
auto coordKw = deckFile.findKeyword( "COORD" );
|
||||
ASSERT_TRUE( coordKw.has_value() );
|
||||
EXPECT_EQ( 2016u, coordKw->getRecord( 0 ).getItem( 0 ).data_size() );
|
||||
|
||||
// Verify ZCORN array size: NX*NY*NZ_new*8 = 20*15*15*8 = 36000
|
||||
auto zcornKw = deckFile.findKeyword( "ZCORN" );
|
||||
ASSERT_TRUE( zcornKw.has_value() );
|
||||
EXPECT_EQ( 36000u, zcornKw->getRecord( 0 ).getItem( 0 ).data_size() );
|
||||
|
||||
// Verify ACTNUM array size: NX*NY*NZ_new = 20*15*15 = 4500
|
||||
auto actnumKw = deckFile.findKeyword( "ACTNUM" );
|
||||
ASSERT_TRUE( actnumKw.has_value() );
|
||||
EXPECT_EQ( 4500u, actnumKw->getRecord( 0 ).getItem( 0 ).data_size() );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user