mirror of
https://github.com/OPM/ResInsight.git
synced 2026-08-27 05:37:21 -05:00
#14223 Calculate geometry grid properties when creating grid from python API
Compute the depth related geometry properties (DEPTH, DX, DY, DZ, TOPS, BOTTOM) in RimCornerPointCase::createFromCoordinatesArray and replaceGridFromCoordinatesArray, matching the behavior when importing a grid from file. The computation is guarded by the same autoComputeDepthRelatedProperties preference used by the file importers.
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
#include "RiaApplication.h"
|
||||
#include "RiaDefines.h"
|
||||
#include "RiaLogging.h"
|
||||
#include "RiaPreferencesGrid.h"
|
||||
#include "RiaQStringFormatter.h"
|
||||
|
||||
#include "RifInputPropertyLoader.h"
|
||||
@@ -108,6 +109,7 @@ std::expected<RimCornerPointCase*, QString> RimCornerPointCase::createFromCoordi
|
||||
|
||||
buildGrid( *cornerPointCase->eclipseCaseData(), nx, ny, nz, coord, zcorn, actnum );
|
||||
cornerPointCase->computeCachedData();
|
||||
computeDepthRelatedResults( *cornerPointCase );
|
||||
|
||||
return cornerPointCase;
|
||||
}
|
||||
@@ -142,6 +144,7 @@ std::expected<void, QString> RimCornerPointCase::replaceGridFromCoordinatesArray
|
||||
|
||||
buildGrid( *cornerPointCase.eclipseCaseData(), nx, ny, nz, coord, zcorn, actnum );
|
||||
cornerPointCase.computeCachedData();
|
||||
computeDepthRelatedResults( cornerPointCase );
|
||||
|
||||
return {};
|
||||
}
|
||||
@@ -369,6 +372,19 @@ void RimCornerPointCase::createActnumResult( RigEclipseCaseData& eclipseCaseData
|
||||
std::fill( ( *modifiableData )[0].begin(), ( *modifiableData )[0].end(), 1.0 );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Compute the depth related geometry properties (DEPTH, DX, DY, DZ, TOPS, BOTTOM), matching the
|
||||
/// behavior when a grid is imported from file.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimCornerPointCase::computeDepthRelatedResults( RimCornerPointCase& cornerPointCase )
|
||||
{
|
||||
if ( RiaPreferencesGrid::current()->autoComputeDepthRelatedProperties() )
|
||||
{
|
||||
cornerPointCase.results( RiaDefines::PorosityModelType::MATRIX_MODEL )->computeDepthRelatedResults();
|
||||
cornerPointCase.results( RiaDefines::PorosityModelType::FRACTURE_MODEL )->computeDepthRelatedResults();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -71,6 +71,8 @@ protected:
|
||||
|
||||
static void createActnumResult( RigEclipseCaseData& eclipseCaseData );
|
||||
|
||||
static void computeDepthRelatedResults( RimCornerPointCase& cornerPointCase );
|
||||
|
||||
static std::array<cvf::Vec3d, 8> getCorners( const RigMainGrid& grid,
|
||||
const std::vector<float>& coord,
|
||||
const std::vector<float>& zcorn,
|
||||
|
||||
+6
-1
@@ -37,4 +37,9 @@ nx = grid.dimensions.ncol
|
||||
ny = grid.dimensions.nrow
|
||||
nz = grid.dimensions.nlay
|
||||
|
||||
project.create_corner_point_grid(name, nx, ny, nz, coord, zcorn, actnum)
|
||||
case = project.create_corner_point_grid(name, nx, ny, nz, coord, zcorn, actnum)
|
||||
|
||||
# Geometry properties (DEPTH, DX, DY, DZ, TOPS, BOTTOM) are computed automatically
|
||||
print("Static properties: ", case.available_properties("STATIC_NATIVE"))
|
||||
depth = case.active_cell_property("STATIC_NATIVE", "DEPTH", 0)
|
||||
print("DEPTH min/max: ", min(depth), max(depth))
|
||||
|
||||
@@ -2,9 +2,13 @@ import sys
|
||||
import os
|
||||
import math
|
||||
|
||||
import pytest
|
||||
|
||||
sys.path.insert(1, os.path.join(sys.path[0], "../../"))
|
||||
import dataroot
|
||||
|
||||
GEOMETRY_PROPERTIES = ["DEPTH", "DX", "DY", "DZ", "TOPS", "BOTTOM"]
|
||||
|
||||
|
||||
def test_export_corner_point_grid_basic(rips_instance, initialize_test):
|
||||
"""Test the export_corner_point_grid method with a simple created grid"""
|
||||
@@ -58,6 +62,10 @@ def test_export_corner_point_grid_basic(rips_instance, initialize_test):
|
||||
assert len(actnum_values) == active_count
|
||||
assert all(v == 1.0 for v in actnum_values)
|
||||
|
||||
# Geometry properties should be computed automatically (issue #14223)
|
||||
for prop in GEOMETRY_PROPERTIES:
|
||||
assert prop in case.available_properties("STATIC_NATIVE")
|
||||
|
||||
# Test our export function
|
||||
exported_zcorn, exported_coord, exported_actnum, export_nx, export_ny, export_nz = (
|
||||
case.export_corner_point_grid()
|
||||
@@ -144,6 +152,58 @@ def test_create_corner_point_grid_with_inactive_cells(rips_instance, initialize_
|
||||
assert sum(1 for x in exported_actnum if x > 0) == expected_active
|
||||
|
||||
|
||||
def test_create_corner_point_grid_geometry_properties(rips_instance, initialize_test):
|
||||
"""Geometry properties (DEPTH, DX, DY, DZ, TOPS, BOTTOM) are computed automatically
|
||||
when creating a grid from the python API, as when importing a grid from file (issue #14223)."""
|
||||
|
||||
# 2x2x2 grid of 100 m cubic cells in two layers: 1000-1100 and 1100-1200
|
||||
nx, ny, nz = 2, 2, 2
|
||||
|
||||
coord = []
|
||||
for j in range(ny + 1):
|
||||
for i in range(nx + 1):
|
||||
x = i * 100.0
|
||||
y = j * 100.0
|
||||
coord.extend([x, y, 1000.0])
|
||||
coord.extend([x, y, 1200.0])
|
||||
|
||||
# ZCORN uses the Eclipse layout: for each layer, the 4*nx*ny top corner depths
|
||||
# followed by the 4*nx*ny bottom corner depths.
|
||||
zcorn = []
|
||||
for k in range(nz):
|
||||
top_depth = 1000.0 + k * 100.0
|
||||
zcorn.extend([top_depth] * (4 * nx * ny))
|
||||
zcorn.extend([top_depth + 100.0] * (4 * nx * ny))
|
||||
|
||||
actnum = [1] * (nx * ny * nz)
|
||||
|
||||
case = rips_instance.project.create_corner_point_grid(
|
||||
"GeometryPropertiesGrid", nx, ny, nz, coord, zcorn, actnum
|
||||
)
|
||||
|
||||
for prop in GEOMETRY_PROPERTIES:
|
||||
assert prop in case.available_properties("STATIC_NATIVE")
|
||||
|
||||
active_count = case.cell_count().active_cell_count
|
||||
values = {
|
||||
prop: case.active_cell_property("STATIC_NATIVE", prop, 0)
|
||||
for prop in GEOMETRY_PROPERTIES
|
||||
}
|
||||
for prop in GEOMETRY_PROPERTIES:
|
||||
assert len(values[prop]) == active_count
|
||||
|
||||
# Active cell index order follows the cell index order (i fastest, k slowest),
|
||||
# so the first 4 cells are in layer k=0 and the last 4 in layer k=1.
|
||||
for active_index in range(active_count):
|
||||
k = active_index // (nx * ny)
|
||||
assert values["DX"][active_index] == pytest.approx(100.0)
|
||||
assert values["DY"][active_index] == pytest.approx(100.0)
|
||||
assert values["DZ"][active_index] == pytest.approx(100.0)
|
||||
assert values["TOPS"][active_index] == pytest.approx(1000.0 + k * 100.0)
|
||||
assert values["BOTTOM"][active_index] == pytest.approx(1100.0 + k * 100.0)
|
||||
assert values["DEPTH"][active_index] == pytest.approx(1050.0 + k * 100.0)
|
||||
|
||||
|
||||
def test_export_corner_point_grid_return_types(rips_instance, initialize_test):
|
||||
"""Test that export_corner_point_grid returns the correct types"""
|
||||
|
||||
@@ -352,6 +412,12 @@ def test_replace_corner_point_grid_basic(rips_instance, initialize_test):
|
||||
assert new_cell_count.reservoir_cell_count == nx_new * ny_new * nz_new
|
||||
assert new_cell_count.reservoir_cell_count == 27 # 3x3x3
|
||||
|
||||
# Geometry properties should be re-computed for the replaced grid (issue #14223)
|
||||
for prop in GEOMETRY_PROPERTIES:
|
||||
assert prop in case.available_properties("STATIC_NATIVE")
|
||||
prop_values = case.active_cell_property("STATIC_NATIVE", prop, 0)
|
||||
assert len(prop_values) == new_cell_count.active_cell_count
|
||||
|
||||
# ACTNUM should be re-created for the replaced grid (issue #14109)
|
||||
assert "ACTNUM" in case.available_properties("STATIC_NATIVE")
|
||||
actnum_values = case.active_cell_property("STATIC_NATIVE", "ACTNUM", 0)
|
||||
|
||||
Reference in New Issue
Block a user