mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-12 08:25:03 -05: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:
1 parent
f3faf4642a
commit
862e67755a
12 files changed
+27220
-5
No files matched your search
@@ -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)
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user