Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions ApplicationLibCode/ProjectDataModel/RimCornerPointCase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "RigCaseCellResultsData.h"
#include "RigEclipseCaseData.h"
#include "RigMainGrid.h"
#include "RimReloadCaseTools.h"

#include "RimEclipseInputProperty.h"
#include "RimReservoirCellResultsStorage.h"
Expand Down Expand Up @@ -108,6 +109,40 @@ std::expected<RimCornerPointCase*, QString> RimCornerPointCase::createFromCoordi
return cornerPointCase;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::expected<void, QString> RimCornerPointCase::replaceGridFromCoordinatesArray( RimCornerPointCase& cornerPointCase,
const int nx,
const int ny,
const int nz,
const std::vector<float>& coord,
const std::vector<float>& zcorn,
const std::vector<float>& actnum )
{
RigActiveCellInfo* activeCellInfo = cornerPointCase.eclipseCaseData()->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL );
CVF_ASSERT( activeCellInfo );
activeCellInfo->clear();

RigActiveCellInfo* fractureActiveCellInfo =
cornerPointCase.eclipseCaseData()->activeCellInfo( RiaDefines::PorosityModelType::FRACTURE_MODEL );
CVF_ASSERT( fractureActiveCellInfo );
fractureActiveCellInfo->clear();

RimReloadCaseTools::clearAllGridData( cornerPointCase.eclipseCaseData() );

// Clear the existing grid geometry before building the new grid
RigMainGrid* mainGrid = cornerPointCase.eclipseCaseData()->mainGrid();
CVF_ASSERT( mainGrid );
mainGrid->reservoirCells().clear();
mainGrid->nodes().clear();

buildGrid( *cornerPointCase.eclipseCaseData(), nx, ny, nz, coord, zcorn, actnum );
cornerPointCase.computeCachedData();

return {};
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Expand Down
8 changes: 8 additions & 0 deletions ApplicationLibCode/ProjectDataModel/RimCornerPointCase.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ class RimCornerPointCase : public RimEclipseCase
const std::vector<float>& zcorn,
const std::vector<float>& actnum );

static std::expected<void, QString> replaceGridFromCoordinatesArray( RimCornerPointCase& cornerPointCase,
const int nx,
const int ny,
const int nz,
const std::vector<float>& coord,
const std::vector<float>& zcorn,
const std::vector<float>& actnum );

protected:
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;

Expand Down
2 changes: 1 addition & 1 deletion ApplicationLibCode/ProjectDataModel/RimReloadCaseTools.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ class RimReloadCaseTools
static RimEclipseCase* gridModelFromSummaryCase( const RimSummaryCase* summaryCase );
static RimSummaryCase* findSummaryCaseFromEclipseResultCase( const RimEclipseResultCase* eclResCase );
static bool openOrImportGridModelFromSummaryCase( const RimSummaryCase* summaryCase );
static void clearAllGridData( RigEclipseCaseData* eclipseCaseData );

private:
static void reloadEclipseData( RimEclipseCase* eclipseCase, bool reloadSummaryData );
static void clearAllGridData( RigEclipseCaseData* eclipseCaseData );
static void updateAllPlots();

static bool findGridModelAndActivateFirstView( const RimSummaryCase* summaryCase );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,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}/RimcCornerPointCase.h
${CMAKE_CURRENT_LIST_DIR}/RimcEclipseCase.h
${CMAKE_CURRENT_LIST_DIR}/RimcEclipseStatisticsCase.h
${CMAKE_CURRENT_LIST_DIR}/RimcGridView.h
Expand Down Expand Up @@ -63,6 +64,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}/RimcCornerPointCase.cpp
${CMAKE_CURRENT_LIST_DIR}/RimcEclipseCase.cpp
${CMAKE_CURRENT_LIST_DIR}/RimcEclipseStatisticsCase.cpp
${CMAKE_CURRENT_LIST_DIR}/RimcGridView.cpp
Expand Down
117 changes: 117 additions & 0 deletions ApplicationLibCode/ProjectDataModelCommands/RimcCornerPointCase.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimcCornerPointCase.h"

#include "RiaApplication.h"
#include "RiaKeyValueStoreUtil.h"
#include "RiaViewRedrawScheduler.h"

#include "Rim3dView.h"
#include "RimCornerPointCase.h"
#include "RimEclipseView.h"

#include "cafPdmFieldScriptingCapability.h"

#include <expected>

CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimCornerPointCase, RimcCornerPointCase_replaceCornerPointGridInternal, "replace_corner_point_grid_internal" );

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimcCornerPointCase_replaceCornerPointGridInternal::RimcCornerPointCase_replaceCornerPointGridInternal( caf::PdmObjectHandle* self )
: caf::PdmVoidObjectMethod( self )
{
CAF_PDM_InitObject( "Replace Corner Point Grid", "", "", "Replace Corner Point Grid" );

CAF_PDM_InitScriptableFieldNoDefault( &m_nx, "Nx", "" );
CAF_PDM_InitScriptableFieldNoDefault( &m_ny, "Ny", "" );
CAF_PDM_InitScriptableFieldNoDefault( &m_nz, "Nz", "" );
CAF_PDM_InitScriptableFieldNoDefault( &m_coordKey, "CoordKey", "" );
CAF_PDM_InitScriptableFieldNoDefault( &m_zcornKey, "ZcornKey", "" );
CAF_PDM_InitScriptableFieldNoDefault( &m_actnumKey, "ActnumKey", "" );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::expected<caf::PdmObjectHandle*, QString> RimcCornerPointCase_replaceCornerPointGridInternal::execute()
{
auto cornerPointCase = self<RimCornerPointCase>();
if ( !cornerPointCase )
{
return std::unexpected( "Unable to get corner point case." );
}

int nx = m_nx();
int ny = m_ny();
int nz = m_nz();
if ( nx <= 0 || ny <= 0 || nz <= 0 )
{
return std::unexpected( "Invalid grid dimensions. nx, ny and nz must be positive." );
}

auto keyValueStore = RiaApplication::instance()->keyValueStore();

std::vector<float> coord = RiaKeyValueStoreUtil::convertToFloatVector( keyValueStore->get( m_coordKey().toStdString() ) );
std::vector<float> zcorn = RiaKeyValueStoreUtil::convertToFloatVector( keyValueStore->get( m_zcornKey().toStdString() ) );
std::vector<float> actnum = RiaKeyValueStoreUtil::convertToFloatVector( keyValueStore->get( m_actnumKey().toStdString() ) );

if ( coord.empty() || zcorn.empty() || actnum.empty() )
{
return std::unexpected( "Found unexpected empty coord, zcorn or actnum array." );
}

// Block view updates while the grid is being replaced.
RiaViewRedrawScheduler::instance()->clearViewsScheduledForUpdate();
RiaViewRedrawScheduler::instance()->blockUpdate( true );

// Create a new corner point grid from the provided geometry
auto result = RimCornerPointCase::replaceGridFromCoordinatesArray( *cornerPointCase, nx, ny, nz, coord, zcorn, actnum );
if ( !result.has_value() )
{
RiaViewRedrawScheduler::instance()->blockUpdate( false );
return std::unexpected( "Failed to replace grid" );
}

// Update all 3D views to reflect the new grid
// We must completely reinitialize the views because the grid size has changed
std::vector<Rim3dView*> views = cornerPointCase->views();
for ( Rim3dView* view : views )
{
if ( RimEclipseView* eclView = dynamic_cast<RimEclipseView*>( view ) )
{
// Force complete regeneration by calling loadDataAndUpdate
// This will reinitialize all geometry managers with the new grid size
eclView->loadDataAndUpdate();
}
}

RiaViewRedrawScheduler::instance()->blockUpdate( false );

// Update connected editors
cornerPointCase->updateConnectedEditors();

// Clean up key-value store
keyValueStore->remove( m_coordKey().toStdString() );
keyValueStore->remove( m_zcornKey().toStdString() );
keyValueStore->remove( m_actnumKey().toStdString() );

return nullptr;
}
47 changes: 47 additions & 0 deletions ApplicationLibCode/ProjectDataModelCommands/RimcCornerPointCase.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cafPdmField.h"
#include "cafPdmObjectMethod.h"

#include <QString>

#include <expected>

//==================================================================================================
///
//==================================================================================================
class RimcCornerPointCase_replaceCornerPointGridInternal : public caf::PdmVoidObjectMethod
{
CAF_PDM_HEADER_INIT;

public:
RimcCornerPointCase_replaceCornerPointGridInternal( caf::PdmObjectHandle* self );

std::expected<caf::PdmObjectHandle*, QString> execute() override;

private:
caf::PdmField<int> m_nx;
caf::PdmField<int> m_ny;
caf::PdmField<int> m_nz;
caf::PdmField<QString> m_coordKey;
caf::PdmField<QString> m_zcornKey;
caf::PdmField<QString> m_actnumKey;
};
53 changes: 53 additions & 0 deletions GrpcInterface/Python/rips/case.py
Original file line number Diff line number Diff line change
Expand Up @@ -1435,3 +1435,56 @@ def export_corner_point_grid(
return (zcorn, coord, actnum, nx, ny, nz)
else:
return ([], [], [], 0, 0, 0)


@add_method(Case)
def replace_corner_point_grid(
self,
nx: int,
ny: int,
nz: int,
coord: List[float],
zcorn: List[float],
actnum: List[int],
):
"""Replace the current case grid with new corner point grid geometry

This method modifies the geometry of an existing case by replacing it with
new grid parameters. All existing properties will be cleared.

Arguments:
nx(int): Number of cells in x direction
ny(int): Number of cells in y direction
nz(int): Number of cells in z direction
coord(list[float]): Coordinate lines as COORD keyword in Eclipse.
Each coordinate line is defined by two points (top and bottom).
Size: (nx+1) * (ny+1) * 2 * 3. Points are ordered as in Eclipse.
zcorn(list[float]): Corner depths as defined by the Eclipse keyword ZCORN.
Size: nx * ny * nz * 8
actnum(list[int]): Active cell info: cells with values > 0 are active.
Size: nx * ny * nz
"""
# Generate unique keys for three arrays
coord_key = "{}_{}".format(uuid.uuid4(), "coord")
zcorn_key = "{}_{}".format(uuid.uuid4(), "zcorn")
actnum_key = "{}_{}".format(uuid.uuid4(), "actnum")

# Get project to access key-value store
project = self.ancestor(rips.project.Project)
if not project:
raise RuntimeError("Unable to get project from case")

# Store arrays in key-value store
project.set_key_values(coord_key, coord)
project.set_key_values(zcorn_key, zcorn)
project.set_key_values(actnum_key, actnum)

# Call internal C++ method to replace the grid
self.replace_corner_point_grid_internal(
nx=nx,
ny=ny,
nz=nz,
coord_key=coord_key,
zcorn_key=zcorn_key,
actnum_key=actnum_key,
)
Loading