#13982 Python: Type case API with StrEnum classes for proto enums

The previous commit auto-generated StrEnum classes for caf::AppEnum scriptable
fields, but the hand-written gRPC API in rips.case still accepted bare strings
for proto-backed enums (PropertyType, PropertyDataType, NNCPropertyType) and
the AppEnum-backed PorosityModelType.

Add a new rips.enums module with hand-written StrEnum classes for the three
proto-only enums and reuse the auto-generated PorosityModelType from
resinsight_classes. Re-export the new enums from the rips package and narrow
the parameter type hints across cell_count, cell_info_for_active_cells,
available_properties, active_cell_property, selected_cell_property,
grid_property, set_active_cell_property, set_grid_property,
active_cell_centers, active_cell_corners, set_nnc_connections_values, and
grid_property_for_positions (sync and async variants).

Existing string arguments keep working because StrEnum members are strings
and protobuf's EnumTypeWrapper.Value accepts both. A new
test_10k_grid_property_strenum asserts string and enum forms return the same
data.
This commit is contained in:
Kristian Bendiksen committed 2026-05-13 13:47:40 +02:00
1 parent 21f1330232
commit 79914f2a00
32 files changed
+330 -141

No files matched your search

@@ -40,12 +40,14 @@ except rips.RipsError as e:
case = resinsight.project.case(case_id=0)
if case is not None:
results = case.active_cell_property("STATIC_NATIVE", "PORO", 0)
results = case.active_cell_property(rips.PropertyType.STATIC_NATIVE, "PORO", 0)
active_cell_count = len(results)
# Send the results back to ResInsight inside try / except construct
try:
case.set_active_cell_property(results, "GENERATED", "POROAPPENDED", 0)
case.set_active_cell_property(
results, rips.PropertyType.GENERATED, "POROAPPENDED", 0
)
print("Everything went well as expected")
except Exception as e: # Match any exception, but it should not happen
print("Ooops!", e)
@@ -55,7 +57,9 @@ if case is not None:
# This time we should get a rips.RipsError exception.
try:
case.set_active_cell_property(results, "GENERATED", "POROAPPENDED", 0)
case.set_active_cell_property(
results, rips.PropertyType.GENERATED, "POROAPPENDED", 0
)
print("Everything went well??")
except rips.RipsError as e:
print("Server Exception Received: ", e)
@@ -68,7 +72,9 @@ if case is not None:
case.chunk_size = active_cell_count
try:
case.set_active_cell_property(results, "GENERATED", "POROAPPENDED", 0)
case.set_active_cell_property(
results, rips.PropertyType.GENERATED, "POROAPPENDED", 0
)
print("Everything went well??")
except rips.RipsError as e:
print("Got unexpected server exception", e, "This should not happen now")
@@ -14,5 +14,5 @@ if resinsight is not None:
print("Got " + str(len(cases)) + " cases: ")
for case in cases:
print(case.name)
for property in case.available_properties("DYNAMIC_NATIVE"):
for property in case.available_properties(rips.PropertyType.DYNAMIC_NATIVE):
print(property)
@@ -21,4 +21,4 @@ case_group = resinsight.project.create_grid_case_group(case_paths=case_paths)
case_group.compute_statistics()
view = case_group.views()[0]
view.apply_cell_result("DYNAMIC_NATIVE", "PRESSURE_DEV")
view.apply_cell_result(rips.ResultType.DYNAMIC_NATIVE, "PRESSURE_DEV")
@@ -24,11 +24,11 @@ print("Got " + str(len(cases)) + " cases: ")
for case in cases:
time_step_info = case.time_steps()
porv_results = case.active_cell_property("STATIC_NATIVE", "PORV", 0)
porv_results = case.active_cell_property(rips.PropertyType.STATIC_NATIVE, "PORV", 0)
for time_step_index in range(0, len(time_step_info)):
pressure_results = case.active_cell_property(
"DYNAMIC_NATIVE", "PRESSURE", time_step_index
rips.PropertyType.DYNAMIC_NATIVE, "PRESSURE", time_step_index
)
results = []
@@ -37,7 +37,7 @@ for case in cases:
# set the computed values in the case
case.set_active_cell_property(
results, "GENERATED", "PRESSURE_PORV", time_step_index
results, rips.PropertyType.GENERATED, "PRESSURE_PORV", time_step_index
)
print(
@@ -49,9 +49,9 @@ for case in cases:
print("Transferred all results back to ResInsight")
# one of "GENERATED", "DYNAMIC_NATIVE", "STATIC_NATIVE", "IMPORTED"
# Pick a value from rips.ResultType (e.g. GENERATED, DYNAMIC_NATIVE, STATIC_NATIVE).
# https://api.resinsight.org/en/main/rips.html#result-definition
property_type = "GENERATED"
property_type = rips.ResultType.GENERATED
property_name = "PRESSURE_PORV"
@@ -16,8 +16,10 @@ for case in cases:
sum_poro = 0.0
cell_cout = 0
eqlnum = case.active_cell_property("STATIC_NATIVE", "EQLNUM", time_step)
poro = case.active_cell_property("STATIC_NATIVE", "PORO", time_step)
eqlnum = case.active_cell_property(
rips.PropertyType.STATIC_NATIVE, "EQLNUM", time_step
)
poro = case.active_cell_property(rips.PropertyType.STATIC_NATIVE, "PORO", time_step)
if len(eqlnum) != len(poro):
print("Size of eqlnum and poro is not identical.")
break
@@ -37,7 +37,7 @@ roff_case = resinsight.project.load_case(roff_case_path)
# PORO and EQLNUM should not be among available properties yet
print("Available properties:")
for prop in roff_case.available_properties("INPUT_PROPERTY"):
for prop in roff_case.available_properties(rips.PropertyType.INPUT_PROPERTY):
print(prop)
# Import properties with file paths
@@ -58,5 +58,5 @@ for name in imported_names.values:
# PORO and EQLNUM should now be among available properties
print("Available properties:")
for prop in roff_case.available_properties("INPUT_PROPERTY"):
for prop in roff_case.available_properties(rips.PropertyType.INPUT_PROPERTY):
print(prop)
@@ -24,18 +24,25 @@ start = time.time()
case = resinsight.project.cases()[0]
# Get a generator for the poro results. The generator will provide a chunk each time it is iterated
poro_chunks = case.active_cell_property_async("STATIC_NATIVE", "PORO", 0)
poro_chunks = case.active_cell_property_async(
rips.PropertyType.STATIC_NATIVE, "PORO", 0
)
# Get a generator for the permx results. The generator will provide a chunk each time it is iterated
permx_chunks = case.active_cell_property_async("STATIC_NATIVE", "PERMX", 0)
permx_chunks = case.active_cell_property_async(
rips.PropertyType.STATIC_NATIVE, "PERMX", 0
)
# Send back the result with the result provided by a generator object.
# Iterating the result generator will cause the script to read from the poro and permx generators
# And return the result of each iteration
case.set_active_cell_property_async(
create_result(poro_chunks, permx_chunks), "GENERATED", "POROPERMXAS", 0
create_result(poro_chunks, permx_chunks),
rips.PropertyType.GENERATED,
"POROPERMXAS",
0,
)
end = time.time()
print("Time elapsed: ", end - start)
print("Transferred all results back")
view = case.views()[0].apply_cell_result("GENERATED", "POROPERMXAS")
view = case.views()[0].apply_cell_result(rips.ResultType.GENERATED, "POROPERMXAS")
@@ -12,9 +12,9 @@ start = time.time()
case = resinsight.project.cases()[0]
# Read poro result into list
poro_results = case.active_cell_property("STATIC_NATIVE", "PORO", 0)
poro_results = case.active_cell_property(rips.PropertyType.STATIC_NATIVE, "PORO", 0)
# Read permx result into list
permx_results = case.active_cell_property("STATIC_NATIVE", "PERMX", 0)
permx_results = case.active_cell_property(rips.PropertyType.STATIC_NATIVE, "PERMX", 0)
# Generate output result
results = []
@@ -23,7 +23,9 @@ for poro, permx in zip(poro_results, permx_results):
try:
# Send back output result
case.set_active_cell_property(results, "GENERATED", "POROPERMXSY", 0)
case.set_active_cell_property(
results, rips.PropertyType.GENERATED, "POROPERMXSY", 0
)
except grpc.RpcError as e:
print("Exception Received: ", e)
@@ -32,4 +34,4 @@ end = time.time()
print("Time elapsed: ", end - start)
print("Transferred all results back")
view = case.views()[0].apply_cell_result("GENERATED", "POROPERMXSY")
view = case.views()[0].apply_cell_result(rips.ResultType.GENERATED, "POROPERMXSY")
@@ -85,7 +85,9 @@ for cell_idx, cell_center in enumerate(cell_centers):
# Step 3: Create a Generated result that stores the unique integer region value
# for every active cell. Cells not covered by any polygon receive value 0.
property_name = "POLYGON_REGION"
case.set_active_cell_property(region_values, "GENERATED", property_name, 0)
case.set_active_cell_property(
region_values, rips.PropertyType.GENERATED, property_name, 0
)
print(f"Generated property '{property_name}' created successfully")
for i, polygon in enumerate(polygons):
@@ -97,5 +99,7 @@ print(f" Unassigned (no polygon): {unassigned} cells")
# Apply the generated result in the view to visualize the regions
view = case.views()[0] if case.views() else case.create_view()
view.apply_cell_result(result_type="GENERATED", result_variable=property_name)
view.apply_cell_result(
result_type=rips.ResultType.GENERATED, result_variable=property_name
)
print(f"Applied '{property_name}' cell result to view")
@@ -37,7 +37,7 @@ roff_case = resinsight.project.load_case(roff_case_path)
# Print all available properties
print("Results on file:")
for prop in roff_case.available_properties("STATIC_NATIVE"):
for prop in roff_case.available_properties(rips.PropertyType.STATIC_NATIVE):
print(prop)
# The name "DYBDE" should point to the "DEPTH" result
@@ -48,11 +48,11 @@ roff_case.add_result_alias("BOTTOM", "PERMX")
# Print all available properties, now with two additional props
print("Results including aliases:")
for prop in roff_case.available_properties("STATIC_NATIVE"):
for prop in roff_case.available_properties(rips.PropertyType.STATIC_NATIVE):
print(prop)
real_result = roff_case.grid_property("STATIC_NATIVE", "BOTTOM", 0)
alias_result = roff_case.grid_property("STATIC_NATIVE", "PERMX", 0)
real_result = roff_case.grid_property(rips.PropertyType.STATIC_NATIVE, "BOTTOM", 0)
alias_result = roff_case.grid_property(rips.PropertyType.STATIC_NATIVE, "PERMX", 0)
if real_result[40] == alias_result[40]:
print("Result values at index 40 match!")
@@ -62,10 +62,10 @@ roff_case.clear_result_aliases()
# Print all available properties, now just the original ones
print("Original results:")
for prop in roff_case.available_properties("STATIC_NATIVE"):
for prop in roff_case.available_properties(rips.PropertyType.STATIC_NATIVE):
print(prop)
try:
alias_result = roff_case.grid_property("STATIC_NATIVE", "PERMX", 0)
alias_result = roff_case.grid_property(rips.PropertyType.STATIC_NATIVE, "PERMX", 0)
except Exception:
print("Result PERMX no longer exists!")
@@ -59,7 +59,7 @@ if resinsight is not None:
for tidx, timestep in enumerate(time_step_info):
# Read the full SOIL result for time step
soil_results = case.selected_cell_property(
"DYNAMIC_NATIVE", "SOIL", tidx
rips.PropertyType.DYNAMIC_NATIVE, "SOIL", tidx
)
print(
"SOIL: {} ({}.{}.{})".format(
@@ -6,4 +6,4 @@ import rips
resinsight = rips.Instance.find()
view = resinsight.project.views()[0]
view.apply_cell_result(result_type="STATIC_NATIVE", result_variable="DX")
view.apply_cell_result(result_type=rips.ResultType.STATIC_NATIVE, result_variable="DX")
@@ -2,9 +2,9 @@
# This script creates a discrete (integer) property for all active
# cells in the first case in the project.
#
# Passing data_type="INTEGER" flags the property as discrete regardless
# of the property name (previously this required the name to end with
# "NUM").
# Passing data_type=rips.PropertyDataType.INTEGER flags the property as
# discrete regardless of the property name (previously this required the
# name to end with "NUM").
######################################################################
import rips
@@ -13,12 +13,16 @@ resinsight = rips.Instance.find()
case = resinsight.project.case(case_id=0)
# Derive a discrete region id from a continuous property.
poro = case.active_cell_property("STATIC_NATIVE", "PORO", 0)
poro = case.active_cell_property(rips.PropertyType.STATIC_NATIVE, "PORO", 0)
region_ids = [int(value * 100) % 4 for value in poro]
print("Applying discrete values to active cells")
case.set_active_cell_property(
region_ids, "GENERATED", "MY_REGION", 0, data_type="INTEGER"
region_ids,
rips.PropertyType.GENERATED,
"MY_REGION",
0,
data_type=rips.PropertyDataType.INTEGER,
)
# Bind integer values to text labels so the legend shows names instead of numbers.
@@ -4,8 +4,9 @@
#
# A discrete property is visualized with a category legend, in contrast
# to the continuous legend used for floating point properties. Passing
# data_type="INTEGER" flags the property as discrete regardless of the
# property name (previously this required the name to end with "NUM").
# data_type=rips.PropertyDataType.INTEGER flags the property as discrete
# regardless of the property name (previously this required the name to
# end with "NUM").
######################################################################
import rips
@@ -22,7 +23,13 @@ for i in range(0, grid_cell_count):
values.append(i % 4)
print("Applying discrete values to main grid")
case.set_grid_property(values, "STATIC_NATIVE", "MY_REGION", 0, data_type="INTEGER")
case.set_grid_property(
values,
rips.PropertyType.STATIC_NATIVE,
"MY_REGION",
0,
data_type=rips.PropertyDataType.INTEGER,
)
# Bind integer values to text labels so the legend shows names instead of numbers.
# Colors are optional — values without a color get an auto-assigned palette color.
@@ -22,9 +22,9 @@ property_data_index = grid.property_data_index_from_ijk(31, 53, 21)
values[property_data_index] = 1.5
print("Applying values to main grid")
case.set_grid_property(values, "STATIC_NATIVE", "MY_DATA", 0)
case.set_grid_property(values, rips.PropertyType.STATIC_NATIVE, "MY_DATA", 0)
values_from_ri = case.grid_property("STATIC_NATIVE", "MY_DATA", 0)
values_from_ri = case.grid_property(rips.PropertyType.STATIC_NATIVE, "MY_DATA", 0)
assert values[property_data_index] == values_from_ri[property_data_index]
# Get LGR grid as grid index 1
@@ -37,5 +37,5 @@ for i in range(0, grid_cell_count):
values.append(i % 3 * 0.75)
print("Applying values to LGR grid")
case.set_grid_property(values, "STATIC_NATIVE", "MY_DATA", 0, 1)
values_from_ri = case.grid_property("STATIC_NATIVE", "MY_DATA", 0, 1)
case.set_grid_property(values, rips.PropertyType.STATIC_NATIVE, "MY_DATA", 0, 1)
values_from_ri = case.grid_property(rips.PropertyType.STATIC_NATIVE, "MY_DATA", 0, 1)
@@ -19,7 +19,9 @@ averages = []
for i in range(0, len(timeSteps)):
# Get the results from time step i asynchronously
# It actually returns a generator object almost immediately
result_chunks = case.active_cell_property_async("DYNAMIC_NATIVE", "SOIL", i)
result_chunks = case.active_cell_property_async(
rips.PropertyType.DYNAMIC_NATIVE, "SOIL", i
)
mysum = 0.0
count = 0
# Loop through and append the average. each time we loop resultChunks
@@ -17,7 +17,7 @@ time_steps = case.time_steps()
averages = []
for i in range(0, len(time_steps)):
# Get a list of all the results for time step i
results = case.active_cell_property("DYNAMIC_NATIVE", "SOIL", i)
results = case.active_cell_property(rips.PropertyType.DYNAMIC_NATIVE, "SOIL", i)
mysum = sum(results)
averages.append(mysum / len(results))
@@ -23,7 +23,9 @@ case = resinsight.project.cases()[0]
timeStepInfo = case.time_steps()
# Get a generator for the porv results. The generator will provide a chunk each time it is iterated
porv_chunks = case.active_cell_property_async("STATIC_NATIVE", "PORV", 0)
porv_chunks = case.active_cell_property_async(
rips.PropertyType.STATIC_NATIVE, "PORV", 0
)
# Read the static result into an array, so we don't have to transfer it for each iteration
# Note we use the async method even if we synchronise here, because we need the values chunked
@@ -34,12 +36,14 @@ for porv_chunk in porv_chunks:
for i in range(0, len(timeStepInfo)):
# Get a generator object for the SOIL property for time step i
soil_chunks = case.active_cell_property_async("DYNAMIC_NATIVE", "SOIL", i)
soil_chunks = case.active_cell_property_async(
rips.PropertyType.DYNAMIC_NATIVE, "SOIL", i
)
# Create the generator object for the SOIL * PORV derived result
result_generator = create_result(soil_chunks, iter(porv_array))
# Send back the result asynchronously with a generator object
case.set_active_cell_property_async(
result_generator, "GENERATED", "SOILPORVAsync", i
result_generator, rips.PropertyType.GENERATED, "SOILPORVAsync", i
)
end = time.time()
@@ -47,4 +51,4 @@ print("Time elapsed: ", end - start)
print("Transferred all results back")
view = case.views()[0].apply_cell_result("GENERATED", "SOILPORVAsync")
view = case.views()[0].apply_cell_result(rips.ResultType.GENERATED, "SOILPORVAsync")
@@ -10,12 +10,14 @@ start = time.time()
case = resinsight.project.cases()[0]
# Read the full porv result
porv_results = case.active_cell_property("STATIC_NATIVE", "PORV", 0)
porv_results = case.active_cell_property(rips.PropertyType.STATIC_NATIVE, "PORV", 0)
time_step_info = case.time_steps()
for i in range(0, len(time_step_info)):
# Read the full SOIl result for time step i
soil_results = case.active_cell_property("DYNAMIC_NATIVE", "SOIL", i)
soil_results = case.active_cell_property(
rips.PropertyType.DYNAMIC_NATIVE, "SOIL", i
)
# Generate the result by looping through both lists in order
results = []
@@ -23,11 +25,13 @@ for i in range(0, len(time_step_info)):
results.append(soil * porv)
# Send back result
case.set_active_cell_property(results, "GENERATED", "SOILPORVSync", i)
case.set_active_cell_property(
results, rips.PropertyType.GENERATED, "SOILPORVSync", i
)
end = time.time()
print("Time elapsed: ", end - start)
print("Transferred all results back")
view = case.views()[0].apply_cell_result("GENERATED", "SOILPORVSync")
view = case.views()[0].apply_cell_result(rips.ResultType.GENERATED, "SOILPORVSync")
@@ -38,7 +38,7 @@ for case in cases:
for view in case.views():
for property in property_list:
view.apply_cell_result(
result_type="DYNAMIC_NATIVE", result_variable=property
result_type=rips.ResultType.DYNAMIC_NATIVE, result_variable=property
)
for time_step in range(0, len(time_steps), 10):
view.set_time_step(time_step=time_step)
@@ -26,7 +26,9 @@ view2 = view1.clone()
view1.set_time_step(time_step=2)
# Set cell result to SOIL
view1.apply_cell_result(result_type="DYNAMIC_NATIVE", result_variable="SOIL")
view1.apply_cell_result(
result_type=rips.ResultType.DYNAMIC_NATIVE, result_variable="SOIL"
)
# Create a temporary directory which will disappear at the end of this script
@@ -27,7 +27,9 @@ view1 = case.views()[0]
view1.set_time_step(time_step=2)
# Set cell result to SOIL
view1.apply_cell_result(result_type="DYNAMIC_NATIVE", result_variable="SOIL")
view1.apply_cell_result(
result_type=rips.ResultType.DYNAMIC_NATIVE, result_variable="SOIL"
)
# Set export folder for snapshots and properties
resinsight.set_export_folder(export_type="SNAPSHOTS", path="e:/temp")
@@ -45,14 +45,14 @@ print("Overburden: ", stim_plan_model_template.overburden_formation)
# Set eclipse result for facies definition
eclipse_result = stim_plan_model_template.facies_properties().facies_definition()
eclipse_result.result_type = "INPUT_PROPERTY"
eclipse_result.result_type = rips.ResultType.INPUT_PROPERTY
eclipse_result.result_variable = "OPERNUM_1"
eclipse_result.update()
# Set eclipse result for non-net layers
non_net_layers = stim_plan_model_template.non_net_layers()
non_net_layers_result = non_net_layers.facies_definition()
non_net_layers_result.result_type = "STATIC_NATIVE"
non_net_layers_result.result_type = rips.ResultType.STATIC_NATIVE
non_net_layers_result.result_variable = "NTG"
non_net_layers_result.update()
non_net_layers.formation = "Not"
@@ -47,12 +47,12 @@ if resinsight is not None:
# Extract some properties
properties = [
("DYNAMIC_NATIVE", "PRESSURE", 0),
("STATIC_NATIVE", "FAULTDIST", 0),
(rips.PropertyType.DYNAMIC_NATIVE, "PRESSURE", 0),
(rips.PropertyType.STATIC_NATIVE, "FAULTDIST", 0),
]
for property_type, property_name, time_step in properties:
porosity_model = "MATRIX_MODEL"
porosity_model = rips.PorosityModelType.MATRIX_MODEL
result[property_name] = c.grid_property_for_positions(
positions, property_type, property_name, time_step, porosity_model
)
@@ -12,10 +12,10 @@ home_dir = expanduser("~")
properties = [
("STATIC_NATIVE", "INDEX_K", 0),
("STATIC_NATIVE", "PORO", 0),
("STATIC_NATIVE", "PERMX", 0),
("DYNAMIC_NATIVE", "PRESSURE", 0),
(rips.ResultType.STATIC_NATIVE, "INDEX_K", 0),
(rips.ResultType.STATIC_NATIVE, "PORO", 0),
(rips.ResultType.STATIC_NATIVE, "PERMX", 0),
(rips.ResultType.DYNAMIC_NATIVE, "PRESSURE", 0),
]
export_folder = tempfile.mkdtemp()
+17
View File
@@ -30,6 +30,15 @@ from .surface import RegularSurface as RegularSurface # noqa: E402
from . import well_events as well_events # noqa: F401, E402
from . import category_mapping as category_mapping # noqa: F401, E402
# Enums for proto types not visible to the AppEnum auto-generator.
# PorosityModelType is auto-generated into resinsight_classes (already imported
# above) and intentionally not re-imported here to avoid a duplicate symbol.
from .enums import ( # noqa: E402
PropertyType as PropertyType,
PropertyDataType as PropertyDataType,
NNCPropertyType as NNCPropertyType,
)
__all__: List[str] = []
for key in class_dict(): # noqa: F405
__all__.append(key)
@@ -38,4 +47,12 @@ for key in class_dict(): # noqa: F405
__all__.append("Grid")
__all__.append("Instance")
for _enum_name in (
"PropertyType",
"PropertyDataType",
"NNCPropertyType",
):
if _enum_name not in __all__:
__all__.append(_enum_name)
__all__.sort()
+71 -28
View File
@@ -53,6 +53,7 @@ from .resinsight_classes import (
Case as Case,
EclipseCase as EclipseCase,
GeoMechCase as GeoMechCase,
PorosityModelType as PorosityModelType,
Reservoir as Reservoir,
WellBoreStabilityPlot as WellBoreStabilityPlot,
WbsParameters as WbsParameters,
@@ -64,6 +65,10 @@ from .project import Project as Project
from .pdmobject import add_method
from .view import View as View
from .simulation_well import SimulationWell
from .enums import (
PropertyType,
PropertyDataType,
)
import rips.project # full name import due to circular dependency
@@ -171,7 +176,9 @@ def replace(self, new_grid_file):
@add_method(Case)
def cell_count(self, porosity_model: str = "MATRIX_MODEL") -> int:
def cell_count(
self, porosity_model: PorosityModelType = PorosityModelType.MATRIX_MODEL
) -> int:
"""Get a cell count object containing number of active cells and total number of cells
Arguments:
@@ -198,7 +205,9 @@ def cell_count(self, porosity_model: str = "MATRIX_MODEL") -> int:
@add_method(Case)
def cell_info_for_active_cells_async(self, porosity_model: str = "MATRIX_MODEL"):
def cell_info_for_active_cells_async(
self, porosity_model: PorosityModelType = PorosityModelType.MATRIX_MODEL
):
"""Get Stream of cell info objects for current case
Arguments:
@@ -218,7 +227,9 @@ def cell_info_for_active_cells_async(self, porosity_model: str = "MATRIX_MODEL")
@add_method(Case)
def cell_info_for_active_cells(self, porosity_model: str = "MATRIX_MODEL"):
def cell_info_for_active_cells(
self, porosity_model: PorosityModelType = PorosityModelType.MATRIX_MODEL
):
"""Get list of cell info objects for current case
Arguments:
@@ -626,7 +637,11 @@ def export_flow_characteristics(
@add_method(Case)
def available_properties(self, property_type, porosity_model: str = "MATRIX_MODEL"):
def available_properties(
self,
property_type: PropertyType,
porosity_model: PorosityModelType = PorosityModelType.MATRIX_MODEL,
):
"""Get a list of available properties
For argument details, see :ref:`Result Definition <result-definition-label>`
@@ -648,7 +663,11 @@ def available_properties(self, property_type, porosity_model: str = "MATRIX_MODE
@add_method(Case)
def active_cell_property_async(
self, property_type, property_name, time_step, porosity_model: str = "MATRIX_MODEL"
self,
property_type: PropertyType,
property_name,
time_step,
porosity_model: PorosityModelType = PorosityModelType.MATRIX_MODEL,
):
"""Get a cell property for all active cells. Async, so returns an iterator. For argument details, see :ref:`Result Definition <result-definition-label>`
@@ -677,7 +696,11 @@ def active_cell_property_async(
@add_method(Case)
def active_cell_property(
self, property_type, property_name, time_step, porosity_model: str = "MATRIX_MODEL"
self,
property_type: PropertyType,
property_name,
time_step,
porosity_model: PorosityModelType = PorosityModelType.MATRIX_MODEL,
):
"""Get a cell property for all active cells. Sync, so returns a list. For argument details, see :ref:`Result Definition <result-definition-label>`
@@ -703,7 +726,11 @@ def active_cell_property(
@add_method(Case)
def selected_cell_property_async(
self, property_type, property_name, time_step, porosity_model: str = "MATRIX_MODEL"
self,
property_type: PropertyType,
property_name,
time_step,
porosity_model: PorosityModelType = PorosityModelType.MATRIX_MODEL,
):
"""Get a cell property for all selected cells. Async, so returns an iterator. For argument details, see :ref:`Result Definition <result-definition-label>`
@@ -732,7 +759,11 @@ def selected_cell_property_async(
@add_method(Case)
def selected_cell_property(
self, property_type, property_name, time_step, porosity_model: str = "MATRIX_MODEL"
self,
property_type: PropertyType,
property_name,
time_step,
porosity_model: PorosityModelType = PorosityModelType.MATRIX_MODEL,
):
"""Get a cell property for all selected cells. Sync, so returns a list. For argument details, see :ref:`Result Definition <result-definition-label>`
@@ -759,11 +790,11 @@ def selected_cell_property(
@add_method(Case)
def grid_property_async(
self,
property_type,
property_type: PropertyType,
property_name,
time_step,
grid_index=0,
porosity_model: str = "MATRIX_MODEL",
porosity_model: PorosityModelType = PorosityModelType.MATRIX_MODEL,
):
"""Get a cell property for all grid cells. Async, so returns an iterator. For argument details, see :ref:`Result Definition <result-definition-label>`
@@ -795,11 +826,11 @@ def grid_property_async(
@add_method(Case)
def grid_property(
self,
property_type,
property_type: PropertyType,
property_name,
time_step,
grid_index=0,
porosity_model: str = "MATRIX_MODEL",
porosity_model: PorosityModelType = PorosityModelType.MATRIX_MODEL,
):
"""Get a cell property for all grid cells. Synchronous, so returns a list. For argument details, see :ref:`Result Definition <result-definition-label>`
@@ -827,11 +858,11 @@ def grid_property(
def set_active_cell_property_async(
self,
values_iterator,
property_type,
property_type: PropertyType,
property_name,
time_step,
porosity_model: str = "MATRIX_MODEL",
data_type: str = "FLOAT",
porosity_model: PorosityModelType = PorosityModelType.MATRIX_MODEL,
data_type: PropertyDataType = PropertyDataType.FLOAT,
):
"""Set cell property for all active cells Async. Takes an iterator to the input values. For argument details, see :ref:`Result Definition <result-definition-label>`
@@ -863,11 +894,11 @@ def set_active_cell_property_async(
def set_active_cell_property(
self,
values,
property_type,
property_type: PropertyType,
property_name,
time_step,
porosity_model: str = "MATRIX_MODEL",
data_type: str = "FLOAT",
porosity_model: PorosityModelType = PorosityModelType.MATRIX_MODEL,
data_type: PropertyDataType = PropertyDataType.FLOAT,
):
"""Set a cell property for all active cells. For argument details, see :ref:`Result Definition <result-definition-label>`
@@ -900,12 +931,12 @@ def set_active_cell_property(
def set_grid_property(
self,
values,
property_type,
property_type: PropertyType,
property_name,
time_step,
grid_index=0,
porosity_model: str = "MATRIX_MODEL",
data_type: str = "FLOAT",
porosity_model: PorosityModelType = PorosityModelType.MATRIX_MODEL,
data_type: PropertyDataType = PropertyDataType.FLOAT,
):
"""Set a cell property for all grid cells. For argument details, see :ref:`Result Definition <result-definition-label>`
@@ -1030,7 +1061,9 @@ def simulation_wells(self):
@add_method(Case)
def active_cell_centers_async(self, porosity_model: str = "MATRIX_MODEL"):
def active_cell_centers_async(
self, porosity_model: PorosityModelType = PorosityModelType.MATRIX_MODEL
):
"""Get a cell centers for all active cells. Async, so returns an iterator
Arguments:
@@ -1048,7 +1081,9 @@ def active_cell_centers_async(self, porosity_model: str = "MATRIX_MODEL"):
@add_method(Case)
def active_cell_centers(self, porosity_model: str = "MATRIX_MODEL"):
def active_cell_centers(
self, porosity_model: PorosityModelType = PorosityModelType.MATRIX_MODEL
):
"""Get a cell centers for all active cells. Synchronous, so returns a list.
Arguments:
@@ -1066,7 +1101,9 @@ def active_cell_centers(self, porosity_model: str = "MATRIX_MODEL"):
@add_method(Case)
def active_cell_corners_async(self, porosity_model: str = "MATRIX_MODEL"):
def active_cell_corners_async(
self, porosity_model: PorosityModelType = PorosityModelType.MATRIX_MODEL
):
"""Get a cell corners for all active cells. Async, so returns an iterator
Arguments:
@@ -1084,7 +1121,9 @@ def active_cell_corners_async(self, porosity_model: str = "MATRIX_MODEL"):
@add_method(Case)
def active_cell_corners(self, porosity_model: str = "MATRIX_MODEL"):
def active_cell_corners(
self, porosity_model: PorosityModelType = PorosityModelType.MATRIX_MODEL
):
"""Get a cell corners for all active cells. Synchronous, so returns a list.
Arguments:
@@ -1328,7 +1367,11 @@ def __generate_nnc_property_input_chunks(self, array, parameters):
@add_method(Case)
def set_nnc_connections_values(
self, values, property_name, time_step, porosity_model: str = "MATRIX_MODEL"
self,
values,
property_name,
time_step,
porosity_model: PorosityModelType = PorosityModelType.MATRIX_MODEL,
):
"""Set nnc connection values for all connections..
@@ -1355,10 +1398,10 @@ def set_nnc_connections_values(
def grid_property_for_positions(
self,
positions: List[List[float]],
property_type: str,
property_type: PropertyType,
property_name: str,
time_step: int,
porosity_model: str = "MATRIX_MODEL",
porosity_model: PorosityModelType = PorosityModelType.MATRIX_MODEL,
) -> List[float]:
shared_uuid = uuid.uuid4()
coordinate_x = "{}_{}".format(shared_uuid, "coordinate_x")
+42
View File
@@ -0,0 +1,42 @@
"""Typed enums mirroring the proto enums used by the rips.case API.
These are hand-written counterparts to proto enums defined in ``Properties.proto``
and ``NNCProperties.proto``. They give users typed, autocompletable enum members
while remaining wire-compatible with the existing string-based API (``StrEnum``
members are strings).
Auto-generated ``StrEnum`` classes for ``caf::AppEnum`` scriptable fields live in
``rips.generated.generated_classes`` and are emitted by ``cafPdmPythonGenerator``.
``PorosityModelType`` is one of those auto-generated enums and is imported from
``resinsight_classes``; the enums in this module cover the gRPC-only proto enums
that the auto-generator does not see.
"""
from enum import StrEnum
# Keep in sync with PropertyType in GrpcInterface/GrpcProtos/Properties.proto
class PropertyType(StrEnum):
DYNAMIC_NATIVE = "DYNAMIC_NATIVE"
STATIC_NATIVE = "STATIC_NATIVE"
SOURSIMRL = "SOURSIMRL"
GENERATED = "GENERATED"
INPUT_PROPERTY = "INPUT_PROPERTY"
FORMATION_NAMES = "FORMATION_NAMES"
FLOW_DIAGNOSTICS = "FLOW_DIAGNOSTICS"
INJECTION_FLOODING = "INJECTION_FLOODING"
REMOVED = "REMOVED"
UNDEFINED = "UNDEFINED"
# Keep in sync with PropertyDataType in GrpcInterface/GrpcProtos/Properties.proto
class PropertyDataType(StrEnum):
FLOAT = "FLOAT"
INTEGER = "INTEGER"
# Keep in sync with NNCPropertyType in GrpcInterface/GrpcProtos/NNCProperties.proto
class NNCPropertyType(StrEnum):
NNC_DYNAMIC = "NNC_DYNAMIC"
NNC_STATIC = "NNC_STATIC"
NNC_GENERATED = "NNC_GENERATED"
+33 -17
View File
@@ -205,7 +205,9 @@ def test_selected_cells(rips_instance, initialize_test):
time_step_info = case.time_steps()
for tidx, timestep in enumerate(time_step_info):
# Try to read for SOIL the time step (will be empty since nothing is selected)
soil_results = case.selected_cell_property("DYNAMIC_NATIVE", "SOIL", tidx)
soil_results = case.selected_cell_property(
rips.PropertyType.DYNAMIC_NATIVE, "SOIL", tidx
)
assert len(soil_results) == 0
@@ -235,9 +237,9 @@ def test_10k_property_for_positions(rips_instance, initialize_test):
[3598.62, 5274.48, 4181.96],
]
property_type = "STATIC_NATIVE"
property_type = rips.PropertyType.STATIC_NATIVE
property_name = "DX"
porosity_model = "MATRIX_MODEL"
porosity_model = rips.PorosityModelType.MATRIX_MODEL
time_step = 0
result = case.grid_property_for_positions(
positions, property_type, property_name, time_step, porosity_model
@@ -258,9 +260,9 @@ def test_10k_property_for_positions_outside_of_model(rips_instance, initialize_t
[3690.07, 52400.69, 4180.02],
]
property_type = "STATIC_NATIVE"
property_type = rips.PropertyType.STATIC_NATIVE
property_name = "DX"
porosity_model = "MATRIX_MODEL"
porosity_model = rips.PorosityModelType.MATRIX_MODEL
time_step = 0
result = case.grid_property_for_positions(
positions, property_type, property_name, time_step, porosity_model
@@ -278,9 +280,9 @@ def test_10k_property_for_positions_no_positions(rips_instance, initialize_test)
positions = []
property_type = "STATIC_NATIVE"
property_type = rips.PropertyType.STATIC_NATIVE
property_name = "DX"
porosity_model = "MATRIX_MODEL"
porosity_model = rips.PorosityModelType.MATRIX_MODEL
time_step = 0
with pytest.raises(rips.RipsError, match="Invalid positions specified"):
case.grid_property_for_positions(
@@ -298,9 +300,9 @@ def test_10k_property_for_positions_invalid_property_name(
[3655.67, 5145.34, 4176.63],
]
property_type = "STATIC_NATIVE"
property_type = rips.PropertyType.STATIC_NATIVE
invalid_property_name = "NON_EXISTING_RESULT"
porosity_model = "MATRIX_MODEL"
porosity_model = rips.PorosityModelType.MATRIX_MODEL
time_step = 0
with pytest.raises(rips.RipsError, match="Result property not found."):
case.grid_property_for_positions(
@@ -320,7 +322,7 @@ def test_10k_property_for_positions_invalid_property_type(
property_type = "NON_EXISTING_PROPERTY_TYPE"
invalid_property_name = "PRESSURE"
porosity_model = "MATRIX_MODEL"
porosity_model = rips.PorosityModelType.MATRIX_MODEL
time_step = 0
with pytest.raises(rips.RipsError, match="Invalid property type."):
case.grid_property_for_positions(
@@ -338,9 +340,9 @@ def test_10k_property_for_positions_invalid_time_step(rips_instance, initialize_
[3655.67, 5145.34, 4176.63],
]
property_type = "DYNAMIC_NATIVE"
property_type = rips.PropertyType.DYNAMIC_NATIVE
property_name = "PRESSURE"
porosity_model = "MATRIX_MODEL"
porosity_model = rips.PorosityModelType.MATRIX_MODEL
invalid_time_step = 99
with pytest.raises(rips.RipsError, match="Invalid time step."):
case.grid_property_for_positions(
@@ -348,23 +350,37 @@ def test_10k_property_for_positions_invalid_time_step(rips_instance, initialize_
)
def test_10k_grid_property_strenum(rips_instance, initialize_test):
case_path = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(path=case_path)
from_str = case.grid_property("DYNAMIC_NATIVE", "SOIL", 3)
from_enum = case.grid_property(
rips.PropertyType.DYNAMIC_NATIVE,
"SOIL",
3,
porosity_model=rips.PorosityModelType.MATRIX_MODEL,
)
assert from_str == from_enum
def test_10k_result_alias(rips_instance, initialize_test):
case_path = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(path=case_path)
result_permx = case.grid_property("STATIC_NATIVE", "PERMX", 0)
result_soil = case.grid_property("DYNAMIC_NATIVE", "SOIL", 3)
result_permx = case.grid_property(rips.PropertyType.STATIC_NATIVE, "PERMX", 0)
result_soil = case.grid_property(rips.PropertyType.DYNAMIC_NATIVE, "SOIL", 3)
case.add_result_alias("PERMX", "PERMW")
case.add_result_alias("SOIL", "SPOIL")
result_permw = case.grid_property("STATIC_NATIVE", "PERMW", 0)
result_permw = case.grid_property(rips.PropertyType.STATIC_NATIVE, "PERMW", 0)
assert len(result_permw) == len(result_permx)
for i in range(len(result_permx)):
assert result_permw[i] == result_permx[i]
result_spoil = case.grid_property("DYNAMIC_NATIVE", "SPOIL", 3)
result_spoil = case.grid_property(rips.PropertyType.DYNAMIC_NATIVE, "SPOIL", 3)
assert len(result_spoil) == len(result_soil)
@@ -374,4 +390,4 @@ def test_10k_result_alias(rips_instance, initialize_test):
case.clear_result_aliases()
with pytest.raises(rips.RipsError, match="No such result"):
case.grid_property("DYNAMIC_NATIVE", "SPOIL", 3)
case.grid_property(rips.PropertyType.DYNAMIC_NATIVE, "SPOIL", 3)
@@ -80,7 +80,7 @@ def check_reek_grid_box(case: rips.Case):
total_size = dimensions.i * dimensions.j * dimensions.k
assert len(cell_centers) == total_size
poro = case.active_cell_property("INPUT_PROPERTY", "PORO", 0)
poro = case.active_cell_property(rips.PropertyType.INPUT_PROPERTY, "PORO", 0)
assert len(poro) == total_size
assert math.isclose(min(poro), 0.000928084715269506)
assert math.isclose(max(poro), 0.351595014333725)
@@ -108,7 +108,7 @@ def verify_load_grid_and_separate_properties(
case: rips.Reservoir, property_name_and_paths: NameAndPath
):
# Load case without properties
available_properties = case.available_properties("INPUT_PROPERTY")
available_properties = case.available_properties(rips.PropertyType.INPUT_PROPERTY)
for [name, _path] in property_name_and_paths.items():
assert name not in available_properties
@@ -120,11 +120,13 @@ def verify_load_grid_and_separate_properties(
imported = case.import_properties(file_names=list(property_name_and_paths.values()))
imported_names = imported.values
available_properties = case.available_properties("INPUT_PROPERTY")
available_properties = case.available_properties(rips.PropertyType.INPUT_PROPERTY)
for [name, _path] in property_name_and_paths.items():
assert name in available_properties
assert name in imported_names
property_values = case.active_cell_property("INPUT_PROPERTY", name, 0)
property_values = case.active_cell_property(
rips.PropertyType.INPUT_PROPERTY, name, 0
)
assert len(property_values) == total_size
@@ -13,7 +13,9 @@ def test_10kAsync(rips_instance, initialize_test):
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(path=casePath)
resultChunks = case.active_cell_property_async("DYNAMIC_NATIVE", "SOIL", 1)
resultChunks = case.active_cell_property_async(
rips.PropertyType.DYNAMIC_NATIVE, "SOIL", 1
)
mysum = 0.0
count = 0
for chunk in resultChunks:
@@ -29,7 +31,7 @@ def test_10kSync(rips_instance, initialize_test):
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(path=casePath)
results = case.active_cell_property("DYNAMIC_NATIVE", "SOIL", 1)
results = case.active_cell_property(rips.PropertyType.DYNAMIC_NATIVE, "SOIL", 1)
mysum = sum(results)
average = mysum / len(results)
assert mysum == pytest.approx(621.768, abs=0.001)
@@ -41,29 +43,33 @@ def test_10k_set(rips_instance, initialize_test):
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(path=casePath)
results = case.active_cell_property("DYNAMIC_NATIVE", "SOIL", 1)
case.set_active_cell_property(results, "GENERATED", "SOIL", 1)
results = case.active_cell_property(rips.PropertyType.DYNAMIC_NATIVE, "SOIL", 1)
case.set_active_cell_property(results, rips.PropertyType.GENERATED, "SOIL", 1)
def test_10k_set_out_of_bounds(rips_instance, initialize_test):
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(path=casePath)
results = case.active_cell_property("DYNAMIC_NATIVE", "SOIL", 1)
results = case.active_cell_property(rips.PropertyType.DYNAMIC_NATIVE, "SOIL", 1)
results.append(5.0)
with pytest.raises(rips.RipsError):
assert case.set_active_cell_property(results, "GENERATED", "SOIL", 1)
assert case.set_active_cell_property(
results, rips.PropertyType.GENERATED, "SOIL", 1
)
def test_10k_set_out_of_bounds_client(rips_instance, initialize_test):
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(path=casePath)
results = case.active_cell_property("DYNAMIC_NATIVE", "SOIL", 1)
results = case.active_cell_property(rips.PropertyType.DYNAMIC_NATIVE, "SOIL", 1)
case.chunk_size = len(results)
results.append(5.0)
with pytest.raises(IndexError):
assert case.set_active_cell_property(results, "GENERATED", "SOIL", 1)
assert case.set_active_cell_property(
results, rips.PropertyType.GENERATED, "SOIL", 1
)
def createResult(poroChunks, permxChunks):
@@ -84,16 +90,23 @@ def test_10k_PoroPermX(rips_instance, initialize_test):
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(path=casePath)
poroChunks = case.active_cell_property_async("STATIC_NATIVE", "PORO", 0)
permxChunks = case.active_cell_property_async("STATIC_NATIVE", "PERMX", 0)
case.set_active_cell_property_async(
createResult(poroChunks, permxChunks), "GENERATED", "POROPERMXAS", 0
poroChunks = case.active_cell_property_async(
rips.PropertyType.STATIC_NATIVE, "PORO", 0
)
permxChunks = case.active_cell_property_async(
rips.PropertyType.STATIC_NATIVE, "PERMX", 0
)
poro = case.active_cell_property("STATIC_NATIVE", "PORO", 0)
permx = case.active_cell_property("STATIC_NATIVE", "PERMX", 0)
poroPermX = case.active_cell_property("GENERATED", "POROPERMXAS", 0)
case.set_active_cell_property_async(
createResult(poroChunks, permxChunks),
rips.PropertyType.GENERATED,
"POROPERMXAS",
0,
)
poro = case.active_cell_property(rips.PropertyType.STATIC_NATIVE, "PORO", 0)
permx = case.active_cell_property(rips.PropertyType.STATIC_NATIVE, "PERMX", 0)
poroPermX = case.active_cell_property(rips.PropertyType.GENERATED, "POROPERMXAS", 0)
checkResults(poro, permx, poroPermX)
@@ -102,16 +115,22 @@ def test_10k_set_integer_active_cell_property(rips_instance, initialize_test):
casePath = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(path=casePath)
results = case.active_cell_property("STATIC_NATIVE", "PORO", 0)
results = case.active_cell_property(rips.PropertyType.STATIC_NATIVE, "PORO", 0)
integer_values = [int(v * 100) for v in results]
# A name that does not end with "NUM" - only the data_type flag should
# cause this to be treated as a discrete/category property.
case.set_active_cell_property(
integer_values, "GENERATED", "MY_DISCRETE_ACTIVE", 0, data_type="INTEGER"
integer_values,
rips.PropertyType.GENERATED,
"MY_DISCRETE_ACTIVE",
0,
data_type=rips.PropertyDataType.INTEGER,
)
round_trip = case.active_cell_property("GENERATED", "MY_DISCRETE_ACTIVE", 0)
round_trip = case.active_cell_property(
rips.PropertyType.GENERATED, "MY_DISCRETE_ACTIVE", 0
)
assert len(round_trip) == len(integer_values)
for expected, actual in zip(integer_values, round_trip):
assert expected == int(actual)
@@ -126,10 +145,14 @@ def test_10k_set_integer_grid_property(rips_instance, initialize_test):
integer_values = [i % 4 for i in range(grid_cell_count)]
case.set_grid_property(
integer_values, "GENERATED", "MY_DISCRETE_GRID", 0, data_type="INTEGER"
integer_values,
rips.PropertyType.GENERATED,
"MY_DISCRETE_GRID",
0,
data_type=rips.PropertyDataType.INTEGER,
)
round_trip = case.grid_property("GENERATED", "MY_DISCRETE_GRID", 0)
round_trip = case.grid_property(rips.PropertyType.GENERATED, "MY_DISCRETE_GRID", 0)
assert len(round_trip) == len(integer_values)
for expected, actual in zip(integer_values, round_trip):
assert expected == int(actual)
@@ -26,10 +26,10 @@ def test_10k_well_log_extraction(rips_instance, initialize_test):
well_path = wells[0]
properties = [
("STATIC_NATIVE", "INDEX_K", 0),
("STATIC_NATIVE", "PORO", 0),
("STATIC_NATIVE", "PERMX", 0),
("DYNAMIC_NATIVE", "PRESSURE", 0),
(rips.ResultType.STATIC_NATIVE, "INDEX_K", 0),
(rips.ResultType.STATIC_NATIVE, "PORO", 0),
(rips.ResultType.STATIC_NATIVE, "PERMX", 0),
(rips.ResultType.DYNAMIC_NATIVE, "PRESSURE", 0),
]
well_log_plot_collection = rips_instance.project.descendants(