Skip to content

Commit f364390

Browse files
committed
Update rips module and Python examples
1 parent 31710a8 commit f364390

File tree

4 files changed

+241
-6
lines changed

4 files changed

+241
-6
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import rips
2+
3+
resinsight = rips.Instance.find()
4+
if resinsight is None:
5+
raise RuntimeError("No running ResInsight instance found on the expected ports.")
6+
7+
# Create a modeled well path and add well path targets
8+
# The coordinates are based on the Norne case
9+
10+
well_path_coll = resinsight.project.well_path_collection()
11+
well_path = well_path_coll.add_new_object(rips.ModeledWellPath)
12+
well_path.name = "Test Well-1"
13+
well_path.update()
14+
15+
geometry = well_path.well_path_geometry()
16+
17+
reference_point = geometry.reference_point
18+
reference_point[0] = 457196
19+
reference_point[1] = 7322270
20+
reference_point[2] = 2742
21+
geometry.update() # Commit updates back to ResInsight
22+
23+
# Create the first well target at the reference point
24+
coord = [0, 0, 0]
25+
geometry.append_well_target(coord)
26+
27+
# Append new well targets relative the the reference point
28+
coord = [454.28, 250, -10]
29+
target = geometry.append_well_target(coord)
30+
31+
coord = [1054.28, 250, -50]
32+
target = geometry.append_well_target(coord)
33+
34+
################################
35+
## Create a lateral well path and append it to the main well path
36+
################################
37+
38+
lateral_well = well_path_coll.add_new_object(rips.ModeledWellPath)
39+
lateral_well.name = "Lateral-1"
40+
lateral_well.update()
41+
42+
lateral_geometry = lateral_well.well_path_geometry()
43+
44+
# Only create geometry starting from the first target of the lateral
45+
lateral_geometry.use_auto_generated_target_at_sea_level = False
46+
47+
reference_point = lateral_geometry.reference_point
48+
reference_point[0] = 457550
49+
reference_point[1] = 7322481
50+
reference_point[2] = 2735
51+
lateral_geometry.update() # Commit updates back to ResInsight
52+
53+
coord = [0, 0, 0]
54+
lateral_geometry.append_well_target(coord)
55+
56+
coord = [454.28, 250, -10]
57+
target = lateral_geometry.append_well_target(coord)
58+
59+
coord = [1054.28, 250, -50]
60+
target = lateral_geometry.append_well_target(coord)
61+
62+
# Append the lateral to the main well path
63+
well_path.append_lateral(lateral_well)

docs/rips/generated/generated_classes.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,6 +1046,18 @@ def append_fishbones(self, sub_locations: List[float]=[], drilling_type: str="ST
10461046
return self._call_pdm_method_return_optional_value("AppendFishbones", Fishbones, sub_locations=sub_locations, drilling_type=drilling_type)
10471047

10481048

1049+
def append_lateral(self, well_path_lateral: Optional[WellPath]=None) -> None:
1050+
"""
1051+
1052+
1053+
Arguments:
1054+
well_path_lateral (Optional[WellPath]): Well Path Lateral
1055+
Returns:
1056+
1057+
"""
1058+
self._call_pdm_method_void("AppendLateral", well_path_lateral=well_path_lateral)
1059+
1060+
10491061
def append_perforation_interval(self, start_md: float=0.000000000000000e+00, end_md: float=0.000000000000000e+00, diameter: float=0.000000000000000e+00, skin_factor: float=0.000000000000000e+00) -> Perforation:
10501062
"""
10511063
Append Perforation Interval
@@ -1124,17 +1136,16 @@ def __init__(self, pb2_object: Optional[PdmObject_pb2.PdmObject]=None, channel:
11241136
if ModeledWellPath.__custom_init__ is not None:
11251137
ModeledWellPath.__custom_init__(self, pb2_object=pb2_object, channel=channel)
11261138

1127-
def append_lateral(self, tie_in_depth: float=0.000000000000000e+00, lateral_name: str="") -> ModeledWellPath:
1139+
def append_lateral(self, well_path_lateral: Optional[WellPath]=None) -> None:
11281140
"""
1129-
Append Well Path Lateral
1141+
11301142
11311143
Arguments:
1132-
tie_in_depth (float): Measured Depth on the Parent Well Path
1133-
lateral_name (str): Lateral Name
1144+
well_path_lateral (Optional[WellPath]): Well Path Lateral
11341145
Returns:
1135-
ModeledWellPath
1146+
11361147
"""
1137-
return self._call_pdm_method_return_value("AppendLateral", ModeledWellPath, tie_in_depth=tie_in_depth, lateral_name=lateral_name)
1148+
self._call_pdm_method_void("AppendLateral", well_path_lateral=well_path_lateral)
11381149

11391150

11401151
def duplicate(self, ) -> Optional[ModeledWellPath]:

docs/rips/tests/test_wells_path_completions.py

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,3 +236,154 @@ def test_perforation_settings(rips_instance, initialize_test):
236236
assert non_darcy_parameters_updated.porosity_scaling_factor == 0.59
237237
assert non_darcy_parameters_updated.relative_gas_density == 0.23
238238
assert non_darcy_parameters_updated.well_radius == 12.12
239+
240+
241+
def test_append_lateral(rips_instance, initialize_test):
242+
well_path_coll = rips_instance.project.well_path_collection()
243+
244+
# Create main well path
245+
main_well_path = well_path_coll.add_new_object(rips.ModeledWellPath)
246+
main_well_path.name = "main_well"
247+
main_well_path.update()
248+
249+
# Create lateral well path
250+
lateral_well_path = well_path_coll.add_new_object(rips.ModeledWellPath)
251+
lateral_well_path.name = "lateral_well"
252+
lateral_well_path.update()
253+
254+
# Test appending lateral to main well path
255+
# This should fail because well paths don't have geometry defined
256+
try:
257+
main_well_path.append_lateral(well_path_lateral=lateral_well_path)
258+
# If we get here, the operation succeeded unexpectedly
259+
assert False, "Expected append_lateral to fail due to missing geometry"
260+
except rips.RipsError as e:
261+
# Expected error message when no geometry is available
262+
expected_msg = "No geometry available for main well path. Cannot append lateral to main well path."
263+
assert str(e) == expected_msg
264+
265+
# Verify the lateral well path objects still exist and have correct names
266+
assert lateral_well_path is not None
267+
assert lateral_well_path.name == "lateral_well"
268+
assert main_well_path is not None
269+
assert main_well_path.name == "main_well"
270+
271+
272+
def test_append_lateral_with_geometry(rips_instance, initialize_test):
273+
well_path_coll = rips_instance.project.well_path_collection()
274+
275+
# Create main well path with geometry using coordinates
276+
main_coordinates = [
277+
[1000.0, 2000.0, 0.0], # Surface point
278+
[1000.0, 2000.0, -100.0], # 100m down
279+
[1000.0, 2000.0, -500.0], # 500m down
280+
[1000.0, 2000.0, -1000.0], # 1000m down
281+
]
282+
283+
main_well_path = well_path_coll.import_well_path_from_points(
284+
name="main_well_with_geometry", coordinates=main_coordinates
285+
)
286+
287+
# Create lateral well path with geometry that starts along the main well path
288+
lateral_coordinates = [
289+
[1000.0, 2000.0, -300.0], # Start along main well at 300m depth
290+
[1020.0, 2020.0, -320.0], # Deviate slightly
291+
[1050.0, 2050.0, -350.0], # Continue deviation
292+
[1100.0, 2100.0, -400.0], # Final lateral point
293+
]
294+
295+
lateral_well_path = well_path_coll.import_well_path_from_points(
296+
name="lateral_well_with_geometry", coordinates=lateral_coordinates
297+
)
298+
299+
# Test appending lateral to main well path - this should work with geometry
300+
# Note: The actual connection may still fail if the geometries don't align properly,
301+
# but we're testing that the function can be called with valid geometry objects
302+
try:
303+
main_well_path.append_lateral(well_path_lateral=lateral_well_path)
304+
# If successful, verify both well paths still exist
305+
assert main_well_path.name == "main_well_with_geometry"
306+
assert lateral_well_path.name == "lateral_well_with_geometry"
307+
except rips.RipsError as e:
308+
# If it fails, it should be for geometric reasons, not missing geometry
309+
error_msg = str(e)
310+
assert (
311+
"No geometry available" not in error_msg
312+
), f"Unexpected geometry error: {error_msg}"
313+
# Other geometric errors (like alignment issues) are acceptable for this test
314+
print(f"Geometric alignment error (expected): {error_msg}")
315+
316+
# Verify the well path objects are still valid regardless of connection result
317+
assert main_well_path is not None
318+
assert lateral_well_path is not None
319+
320+
321+
def test_append_lateral_check_connection(rips_instance, initialize_test):
322+
well_path_coll = rips_instance.project.well_path_collection()
323+
324+
# Create main well path using ModeledWellPath with targets
325+
main_well_path = well_path_coll.add_new_object(rips.ModeledWellPath)
326+
main_well_path.name = "main_well_check_connection"
327+
main_well_path.update()
328+
329+
# Add geometry targets to main well path
330+
main_geometry = main_well_path.well_path_geometry()
331+
main_geometry.append_well_target([1000.0, 2000.0, 0.0]) # Surface
332+
main_geometry.append_well_target([1000.0, 2000.0, -100.0]) # 100m down
333+
main_geometry.append_well_target([1000.0, 2000.0, -300.0]) # 300m down
334+
main_geometry.append_well_target([1000.0, 2000.0, -500.0]) # 500m down
335+
main_geometry.update()
336+
337+
# Create lateral well path using ModeledWellPath with targets
338+
lateral_well_path = well_path_coll.add_new_object(rips.ModeledWellPath)
339+
lateral_well_path.name = "lateral_well_check_connection"
340+
lateral_well_path.update()
341+
342+
# Add geometry targets to lateral well path
343+
lateral_geometry = lateral_well_path.well_path_geometry()
344+
lateral_geometry.append_well_target(
345+
[1000.0, 2000.0, -150.0]
346+
) # Start at 150m on main
347+
lateral_geometry.append_well_target([1020.0, 2020.0, -200.0]) # Deviate
348+
lateral_geometry.append_well_target([1050.0, 2050.0, -250.0]) # Continue
349+
lateral_geometry.update()
350+
351+
# Get initial geometry state
352+
initial_attached_state = lateral_geometry.attached_to_parent_well
353+
354+
# Test appending lateral to main well path
355+
try:
356+
main_well_path.append_lateral(well_path_lateral=lateral_well_path)
357+
358+
# Check if connection was successful by examining the geometry properties
359+
lateral_geometry.update() # Refresh from server
360+
final_attached_state = lateral_geometry.attached_to_parent_well
361+
362+
# If connection was successful, verify the parent relationship
363+
if final_attached_state and not initial_attached_state:
364+
print("Successfully connected lateral to parent well path")
365+
assert lateral_well_path.name == "lateral_well_check_connection"
366+
assert main_well_path.name == "main_well_check_connection"
367+
368+
# The lateral should now be marked as attached to parent
369+
assert lateral_geometry.attached_to_parent_well
370+
else:
371+
print("Connection did not change attachment state - may be geometric issue")
372+
# Still a valid test if the function completed without error
373+
374+
except rips.RipsError as e:
375+
# Log the error for debugging but don't fail the test
376+
# Different geometric configurations may result in different connection outcomes
377+
error_msg = str(e)
378+
print(f"Connection attempt resulted in error: {error_msg}")
379+
380+
# Ensure it's not a "no geometry" error since we provided geometry
381+
assert (
382+
"No geometry available" not in error_msg
383+
), f"Unexpected geometry error: {error_msg}"
384+
385+
# Verify both well paths are still valid
386+
assert main_well_path is not None
387+
assert lateral_well_path is not None
388+
assert main_well_path.name == "main_well_check_connection"
389+
assert lateral_well_path.name == "lateral_well_check_connection"

docs/source/PythonExamples_wells_and_fractures.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ All Wells
3636
:linenos:
3737
:caption: all_wells.py
3838

39+
.. _wells_and_fractures_append_lateral_to_well:
40+
41+
Append Lateral To Well
42+
----------------------
43+
44+
.. literalinclude:: ../rips/PythonExamples/wells_and_fractures/append_lateral_to_well.py
45+
:language: python
46+
:linenos:
47+
:caption: append_lateral_to_well.py
48+
3949
.. _wells_and_fractures_create_and_export_stim_plan_model:
4050

4151
Create And Export Stim Plan Model

0 commit comments

Comments
 (0)