mirror of
https://github.com/OPM/ResInsight.git
synced 2024-12-28 01:41:42 -06:00
Add Python support for import of property files for .roff and .grdecl (#10183)
- Add RimcEclipseCase - Add tests for import case properties (.roff and .grdecl) - Make rips handle list of strings as input in Pyton API
This commit is contained in:
parent
f3faf4642a
commit
862e67755a
@ -89,7 +89,7 @@ CAF_PDM_XML_ABSTRACT_SOURCE_INIT( RimEclipseCase, "RimReservoir" );
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimEclipseCase::RimEclipseCase()
|
||||
{
|
||||
CAF_PDM_InitScriptableObjectWithNameAndComment( "EclipseCase", ":/Case48x48.png", "", "", "Reservoir", "Abtract base class for Eclipse Cases" );
|
||||
CAF_PDM_InitScriptableObjectWithNameAndComment( "EclipseCase", ":/Case48x48.png", "", "", "Reservoir", "Abstract base class for Eclipse Cases" );
|
||||
|
||||
CAF_PDM_InitScriptableFieldWithScriptKeywordNoDefault( &reservoirViews, "ReservoirViews", "Views", "", "", "", "All Eclipse Views in the case" );
|
||||
reservoirViews.uiCapability()->setUiTreeHidden( true );
|
||||
|
@ -23,6 +23,7 @@ set(SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimcFractureTemplate.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimcThermalFractureTemplate.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimcIntersection.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimcEclipseCase.h
|
||||
)
|
||||
|
||||
set(SOURCE_GROUP_SOURCE_FILES
|
||||
@ -50,6 +51,7 @@ set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimcFractureTemplate.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimcThermalFractureTemplate.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimcIntersection.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimcEclipseCase.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
|
||||
|
@ -0,0 +1,99 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- 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 "RimcEclipseCase.h"
|
||||
|
||||
#include "RiaApplication.h"
|
||||
#include "RiaGuiApplication.h"
|
||||
|
||||
#include "RicImportSummaryCasesFeature.h"
|
||||
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimFileSummaryCase.h"
|
||||
#include "RimOilField.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimSummaryCase.h"
|
||||
#include "RimSurfaceCollection.h"
|
||||
#include "RiuPlotMainWindow.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
|
||||
#include <memory>
|
||||
|
||||
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimEclipseCase, RimcEclipseCase_importProperties, "import_properties" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimcEclipseCase_importProperties::RimcEclipseCase_importProperties( caf::PdmObjectHandle* self )
|
||||
: caf::PdmObjectMethod( self )
|
||||
{
|
||||
CAF_PDM_InitObject( "Import Properties", "", "", "Import Properties" );
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_fileNames, "FileNames", "" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
caf::PdmObjectHandle* RimcEclipseCase_importProperties::execute()
|
||||
{
|
||||
std::vector<QString> absolutePaths = m_fileNames;
|
||||
for ( auto& path : absolutePaths )
|
||||
{
|
||||
QFileInfo projectPathInfo( path );
|
||||
if ( !projectPathInfo.exists() )
|
||||
{
|
||||
QDir startDir( RiaApplication::instance()->startDir() );
|
||||
path = startDir.absoluteFilePath( path );
|
||||
}
|
||||
}
|
||||
|
||||
const QStringList propertyFileNames = QStringList::fromVector( QVector<QString>::fromStdVector( absolutePaths ) );
|
||||
|
||||
auto eclipseCase = self<RimEclipseCase>();
|
||||
eclipseCase->importAsciiInputProperties( propertyFileNames );
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimcEclipseCase_importProperties::resultIsPersistent() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::unique_ptr<caf::PdmObjectHandle> RimcEclipseCase_importProperties::defaultResult() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimcEclipseCase_importProperties::isNullptrValidResult() const
|
||||
{
|
||||
return true;
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2020- 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 "cafPdmField.h"
|
||||
#include "cafPdmObjectHandle.h"
|
||||
#include "cafPdmObjectMethod.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include <memory>
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimcEclipseCase_importProperties : public caf::PdmObjectMethod
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimcEclipseCase_importProperties( caf::PdmObjectHandle* self );
|
||||
|
||||
caf::PdmObjectHandle* execute() override;
|
||||
bool resultIsPersistent() const override;
|
||||
std::unique_ptr<PdmObjectHandle> defaultResult() const override;
|
||||
bool isNullptrValidResult() const override;
|
||||
|
||||
private:
|
||||
caf::PdmField<std::vector<QString>> m_fileNames;
|
||||
};
|
@ -246,6 +246,8 @@ struct PdmFieldScriptingCapabilityIOHandler<std::vector<T>>
|
||||
QChar chr = errorMessageContainer->readCharWithLineNumberCount( inputStream );
|
||||
if ( chr == QChar( '[' ) )
|
||||
{
|
||||
std::vector<QString> allValues;
|
||||
QString currentValue;
|
||||
while ( !inputStream.atEnd() )
|
||||
{
|
||||
errorMessageContainer->skipWhiteSpaceWithLineNumberCount( inputStream );
|
||||
@ -259,11 +261,25 @@ struct PdmFieldScriptingCapabilityIOHandler<std::vector<T>>
|
||||
{
|
||||
nextChar = errorMessageContainer->readCharWithLineNumberCount( inputStream );
|
||||
errorMessageContainer->skipWhiteSpaceWithLineNumberCount( inputStream );
|
||||
if ( !currentValue.isEmpty() ) allValues.push_back( currentValue );
|
||||
currentValue = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
currentValue += errorMessageContainer->readCharWithLineNumberCount( inputStream );
|
||||
}
|
||||
}
|
||||
if ( !currentValue.isEmpty() ) allValues.push_back( currentValue );
|
||||
|
||||
T value;
|
||||
PdmFieldScriptingCapabilityIOHandler<T>::writeToField( value, inputStream, errorMessageContainer, true );
|
||||
fieldValue.push_back( value );
|
||||
for ( QString textValue : allValues )
|
||||
{
|
||||
QTextStream singleValueStream( &textValue, QIODevice::ReadOnly );
|
||||
T singleValue;
|
||||
PdmFieldScriptingCapabilityIOHandler<T>::writeToField( singleValue,
|
||||
singleValueStream,
|
||||
errorMessageContainer,
|
||||
false );
|
||||
fieldValue.push_back( singleValue );
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1,13 +1,22 @@
|
||||
import sys
|
||||
import os
|
||||
from typing import Any, Dict, List, TypedDict
|
||||
import math
|
||||
|
||||
from generated.generated_classes import Case
|
||||
|
||||
sys.path.insert(1, os.path.join(sys.path[0], "../../"))
|
||||
import rips
|
||||
|
||||
import dataroot
|
||||
|
||||
|
||||
class NameAndPath(TypedDict):
|
||||
# Typed dict container for name of property and path of property file
|
||||
name: str
|
||||
path: str
|
||||
|
||||
|
||||
def check_corner(actual, expected):
|
||||
assert math.isclose(actual.x, expected[0], abs_tol=0.1)
|
||||
assert math.isclose(actual.y, expected[1], abs_tol=0.1)
|
||||
@ -60,7 +69,7 @@ def test_10k(rips_instance, initialize_test):
|
||||
check_corner(cell_corners[cell_index].c7, expected_corners[7])
|
||||
|
||||
|
||||
def check_reek_grid_box(case):
|
||||
def check_reek_grid_box(case: Case):
|
||||
assert len(case.grids()) == 1
|
||||
grid = case.grid(index=0)
|
||||
|
||||
@ -95,3 +104,46 @@ def test_load_grdecl_grid(rips_instance, initialize_test):
|
||||
casePath = dataroot.PATH + "/reek/reek_box_grid_w_props.grdecl"
|
||||
case = rips_instance.project.load_case(path=casePath)
|
||||
check_reek_grid_box(case)
|
||||
|
||||
|
||||
def verify_load_grid_and_separate_properties(
|
||||
case: Case, property_name_and_paths: NameAndPath
|
||||
):
|
||||
# Load case without properties
|
||||
available_properties = case.available_properties("INPUT_PROPERTY")
|
||||
for [name, _path] in property_name_and_paths.items():
|
||||
assert name not in available_properties
|
||||
|
||||
grid = case.grid(index=0)
|
||||
dimensions = grid.dimensions()
|
||||
total_size = dimensions.i * dimensions.j * dimensions.k
|
||||
|
||||
# Import properties to case
|
||||
case.import_properties(file_names=list(property_name_and_paths.values()))
|
||||
available_properties = case.available_properties("INPUT_PROPERTY")
|
||||
for [name, _path] in property_name_and_paths.items():
|
||||
assert name in available_properties
|
||||
property_values = case.active_cell_property("INPUT_PROPERTY", name, 0)
|
||||
assert len(property_values) == total_size
|
||||
|
||||
|
||||
def test_load_grdecl_grid_with_separate_properties(rips_instance, initialize_test):
|
||||
grid_file_path: str = dataroot.PATH + "/reek/reek_box_grid_w_out_props.grdecl"
|
||||
property_name_and_paths: NameAndPath = {
|
||||
"EQLNUM": dataroot.PATH + "/reek/reek_box_EQLNUM_property.grdecl",
|
||||
"PORO": dataroot.PATH + "/reek/reek_box_PORO_property.grdecl",
|
||||
}
|
||||
case = rips_instance.project.load_case(path=grid_file_path)
|
||||
|
||||
verify_load_grid_and_separate_properties(case, property_name_and_paths)
|
||||
|
||||
|
||||
def test_load_roff_grid_with_separate_properties(rips_instance, initialize_test):
|
||||
grid_file_path: str = dataroot.PATH + "/reek/reek_box_grid_w_out_props.roffasc"
|
||||
property_name_and_paths: NameAndPath = {
|
||||
"EQLNUM": dataroot.PATH + "/reek/reek_box_EQLNUM_property.roffasc",
|
||||
"PORO": dataroot.PATH + "/reek/reek_box_PORO_property.roffasc",
|
||||
}
|
||||
case = rips_instance.project.load_case(path=grid_file_path)
|
||||
|
||||
verify_load_grid_and_separate_properties(case, property_name_and_paths)
|
||||
|
1357
TestModels/reek/reek_box_EQLNUM_property.grdecl
Normal file
1357
TestModels/reek/reek_box_EQLNUM_property.grdecl
Normal file
File diff suppressed because it is too large
Load Diff
1155
TestModels/reek/reek_box_EQLNUM_property.roffasc
Normal file
1155
TestModels/reek/reek_box_EQLNUM_property.roffasc
Normal file
File diff suppressed because it is too large
Load Diff
1357
TestModels/reek/reek_box_PORO_property.grdecl
Normal file
1357
TestModels/reek/reek_box_PORO_property.grdecl
Normal file
File diff suppressed because it is too large
Load Diff
1714
TestModels/reek/reek_box_PORO_property.roffasc
Normal file
1714
TestModels/reek/reek_box_PORO_property.roffasc
Normal file
File diff suppressed because it is too large
Load Diff
15469
TestModels/reek/reek_box_grid_w_out_props.grdecl
Normal file
15469
TestModels/reek/reek_box_grid_w_out_props.grdecl
Normal file
File diff suppressed because it is too large
Load Diff
5948
TestModels/reek/reek_box_grid_w_out_props.roffasc
Normal file
5948
TestModels/reek/reek_box_grid_w_out_props.roffasc
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user