Skip to content

Commit 808b04e

Browse files
committed
Update rips module, proto files, and Python examples
1 parent 5674e01 commit 808b04e

File tree

2 files changed

+233
-54
lines changed

2 files changed

+233
-54
lines changed

docs/rips/PythonExamples/wells_and_fractures/completion_data.py

Lines changed: 169 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -39,72 +39,156 @@ def fieldValueOrDefaultText(grpc_object, optional_field_name: str):
3939
print("WELSPECS")
4040

4141
welspecs = completion_data.welspecs
42+
welspecl_entries = []
43+
4244
for line in welspecs:
43-
txt = line.well_name + " "
44-
txt += line.group_name + " "
45-
txt += str(line.grid_i) + " "
46-
txt += str(line.grid_j) + " "
47-
txt += fieldValueOrDefaultText(line, "bhp_depth") + " "
48-
txt += line.phase + " "
49-
txt += fieldValueOrDefaultText(line, "drainage_radius") + " "
50-
txt += fieldValueOrDefaultText(line, "inflow_equation") + " "
51-
txt += fieldValueOrDefaultText(line, "auto_shut_in") + " "
52-
txt += fieldValueOrDefaultText(line, "cross_flow") + " "
53-
txt += fieldValueOrDefaultText(line, "pvt_num") + " "
54-
txt += fieldValueOrDefaultText(line, "hydrostatic_density_calc") + " "
55-
txt += fieldValueOrDefaultText(line, "fip_region") + " "
56-
txt += "/"
57-
58-
print(txt)
45+
# Check if grid_name is present and not empty
46+
has_grid_name = (
47+
hasattr(line, "grid_name")
48+
and line.HasField("grid_name")
49+
and line.grid_name.strip()
50+
)
51+
52+
if has_grid_name:
53+
# Store for WELSPECL section
54+
welspecl_entries.append(line)
55+
else:
56+
# Output as WELSPECS
57+
txt = line.well_name + " "
58+
txt += line.group_name + " "
59+
txt += str(line.grid_i) + " "
60+
txt += str(line.grid_j) + " "
61+
txt += fieldValueOrDefaultText(line, "bhp_depth") + " "
62+
txt += line.phase + " "
63+
txt += fieldValueOrDefaultText(line, "drainage_radius") + " "
64+
txt += fieldValueOrDefaultText(line, "inflow_equation") + " "
65+
txt += fieldValueOrDefaultText(line, "auto_shut_in") + " "
66+
txt += fieldValueOrDefaultText(line, "cross_flow") + " "
67+
txt += fieldValueOrDefaultText(line, "pvt_num") + " "
68+
txt += fieldValueOrDefaultText(line, "hydrostatic_density_calc") + " "
69+
txt += fieldValueOrDefaultText(line, "fip_region") + " "
70+
txt += "/"
71+
72+
print(txt)
5973

6074
print("/\n")
6175

76+
# Output WELSPECL section if there are entries with grid_name
77+
if len(welspecl_entries) > 0:
78+
print("WELSPECL")
79+
80+
for line in welspecl_entries:
81+
txt = line.well_name + " "
82+
txt += line.group_name + " "
83+
txt += line.grid_name + " "
84+
txt += str(line.grid_i) + " "
85+
txt += str(line.grid_j) + " "
86+
txt += fieldValueOrDefaultText(line, "bhp_depth") + " "
87+
txt += line.phase + " "
88+
txt += fieldValueOrDefaultText(line, "drainage_radius") + " "
89+
txt += fieldValueOrDefaultText(line, "inflow_equation") + " "
90+
txt += fieldValueOrDefaultText(line, "auto_shut_in") + " "
91+
txt += fieldValueOrDefaultText(line, "cross_flow") + " "
92+
txt += fieldValueOrDefaultText(line, "pvt_num") + " "
93+
txt += fieldValueOrDefaultText(line, "hydrostatic_density_calc") + " "
94+
txt += fieldValueOrDefaultText(line, "fip_region") + " "
95+
txt += "/"
96+
97+
print(txt)
98+
99+
print("/\n")
100+
62101
compdat = completion_data.compdat
63102

64103
complump_entries = []
104+
compdatl_entries = []
65105

66106
print("COMPDAT")
67107

68108
for line in compdat:
69-
txt = ""
70-
complump = ""
71-
72-
if line.HasField("start_md"):
73-
txt += "-- Perforation MD In " + str(line.start_md)
74-
txt += ", MD Out " + str(line.end_md) + "--\n"
75-
76-
txt += " "
77-
txt += line.well_name + " "
78-
txt += str(line.grid_i) + " "
79-
txt += str(line.grid_j) + " "
80-
txt += str(line.upper_k) + " "
81-
txt += str(line.lower_k) + " "
82-
txt += line.open_shut_flag + " "
83-
txt += fieldValueOrDefaultText(line, "saturation") + " "
84-
txt += str(line.transmissibility) + " "
85-
txt += str(line.diameter) + " "
86-
txt += str(line.kh) + " "
87-
txt += fieldValueOrDefaultText(line, "skin_factor") + " "
88-
txt += fieldValueOrDefaultText(line, "d_factor") + " "
89-
txt += "'%s'" % line.direction
90-
txt += " /"
91-
92-
if (line.HasField("completion_number")) and (line.completion_number > 0):
93-
complump += " "
94-
complump += line.well_name + " "
95-
complump += str(line.grid_i) + " "
96-
complump += str(line.grid_j) + " "
97-
complump += str(line.upper_k) + " "
98-
complump += str(line.lower_k) + " "
99-
complump += str(line.completion_number) + " "
100-
complump += " /"
101-
102-
complump_entries.append(complump)
103-
104-
print(txt)
109+
# Check if grid_name is present and not empty
110+
has_grid_name = (
111+
hasattr(line, "grid_name")
112+
and line.HasField("grid_name")
113+
and line.grid_name.strip()
114+
)
115+
116+
if has_grid_name:
117+
# Store for COMPDATL section
118+
compdatl_entries.append(line)
119+
else:
120+
# Output as COMPDAT
121+
txt = ""
122+
complump = ""
123+
124+
if line.HasField("start_md"):
125+
txt += "-- Perforation MD In " + str(line.start_md)
126+
txt += ", MD Out " + str(line.end_md) + "--\n"
127+
128+
txt += " "
129+
txt += line.well_name + " "
130+
txt += str(line.grid_i) + " "
131+
txt += str(line.grid_j) + " "
132+
txt += str(line.upper_k) + " "
133+
txt += str(line.lower_k) + " "
134+
txt += line.open_shut_flag + " "
135+
txt += fieldValueOrDefaultText(line, "saturation") + " "
136+
txt += str(line.transmissibility) + " "
137+
txt += str(line.diameter) + " "
138+
txt += str(line.kh) + " "
139+
txt += fieldValueOrDefaultText(line, "skin_factor") + " "
140+
txt += fieldValueOrDefaultText(line, "d_factor") + " "
141+
txt += "'%s'" % line.direction
142+
txt += " /"
143+
144+
if (line.HasField("completion_number")) and (line.completion_number > 0):
145+
complump += " "
146+
complump += line.well_name + " "
147+
complump += str(line.grid_i) + " "
148+
complump += str(line.grid_j) + " "
149+
complump += str(line.upper_k) + " "
150+
complump += str(line.lower_k) + " "
151+
complump += str(line.completion_number) + " "
152+
complump += " /"
153+
154+
complump_entries.append(complump)
155+
156+
print(txt)
105157

106158
print("/\n")
107159

160+
# Output COMPDATL section if there are entries with grid_name
161+
if len(compdatl_entries) > 0:
162+
print("COMPDATL")
163+
164+
for line in compdatl_entries:
165+
txt = ""
166+
167+
if line.HasField("start_md"):
168+
txt += "-- Perforation MD In " + str(line.start_md)
169+
txt += ", MD Out " + str(line.end_md) + "--\n"
170+
171+
txt += " "
172+
txt += line.well_name + " "
173+
txt += line.grid_name + " "
174+
txt += str(line.grid_i) + " "
175+
txt += str(line.grid_j) + " "
176+
txt += str(line.upper_k) + " "
177+
txt += str(line.lower_k) + " "
178+
txt += line.open_shut_flag + " "
179+
txt += fieldValueOrDefaultText(line, "saturation") + " "
180+
txt += str(line.transmissibility) + " "
181+
txt += str(line.diameter) + " "
182+
txt += str(line.kh) + " "
183+
txt += fieldValueOrDefaultText(line, "skin_factor") + " "
184+
txt += fieldValueOrDefaultText(line, "d_factor") + " "
185+
txt += "'%s'" % line.direction
186+
txt += " /"
187+
188+
print(txt)
189+
190+
print("/\n")
191+
108192
if len(complump_entries) > 0:
109193
print("COMPLUMP")
110194
for complump_entry in complump_entries:
@@ -151,19 +235,50 @@ def fieldValueOrDefaultText(grpc_object, optional_field_name: str):
151235
# Print COMPSEGS (MSW completion segments)
152236
print("\nCOMPSEGS")
153237
compsegs = completion_data.compsegs
238+
compsegl_entries = []
239+
154240
if (compsegs is None) or (len(compsegs) == 0):
155241
print(" -- No COMPSEGS data --")
156242
else:
157243
for compseg in compsegs:
244+
# Check if grid_name is present and not empty
245+
has_grid_name = (
246+
hasattr(compseg, "grid_name")
247+
and compseg.HasField("grid_name")
248+
and compseg.grid_name.strip()
249+
)
250+
251+
if has_grid_name:
252+
# Store for COMPSEGL section
253+
compsegl_entries.append(compseg)
254+
else:
255+
# Output as COMPSEGS
256+
txt = " "
257+
txt += str(compseg.i) + " "
258+
txt += str(compseg.j) + " "
259+
txt += str(compseg.k) + " "
260+
txt += str(compseg.branch) + " "
261+
txt += str(compseg.distance_start) + " "
262+
txt += str(compseg.distance_end) + " "
263+
txt += " /"
264+
print(txt)
265+
266+
print("/\n")
267+
268+
# Output COMPSEGL section if there are entries with grid_name
269+
if len(compsegl_entries) > 0:
270+
print("COMPSEGL")
271+
272+
for compseg in compsegl_entries:
158273
txt = " "
274+
txt += compseg.grid_name + " "
159275
txt += str(compseg.i) + " "
160276
txt += str(compseg.j) + " "
161277
txt += str(compseg.k) + " "
162278
txt += str(compseg.branch) + " "
163279
txt += str(compseg.distance_start) + " "
164280
txt += str(compseg.distance_end) + " "
165-
txt += fieldValueOrDefaultText(compseg, "grid_name")
166281
txt += " /"
167282
print(txt)
168283

169-
print("/\n")
284+
print("/\n")

docs/rips/tests/test_get_completion_data.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,70 @@ def test_completion_data_reference_failure_simulation(rips_instance, initialize_
731731
print("Reference test correctly detects data changes")
732732

733733

734+
def test_welspecs_grid_name_field(rips_instance, initialize_test):
735+
"""Test WELSPECS grid_name field behavior for main grid vs LGR grids"""
736+
case_root_path = dataroot.PATH + "/TEST10K_FLT_LGR_NNC"
737+
case_path = case_root_path + "/TEST10K_FLT_LGR_NNC.EGRID"
738+
case = rips_instance.project.load_case(path=case_path)
739+
740+
well_path_file = case_root_path + "/wellpath_a.dev"
741+
rips_instance.project.import_well_paths([well_path_file])
742+
well_path = rips_instance.project.well_paths()[0]
743+
well_path.name = "GridNameTestWell"
744+
well_path.update()
745+
746+
# Add completion
747+
result = well_path.trajectory_properties(resampling_interval=10.0)
748+
measured_depths = result["measured_depth"]
749+
start_md = measured_depths[len(measured_depths) // 2]
750+
end_md = (
751+
measured_depths[len(measured_depths) // 2 + 5]
752+
if len(measured_depths) > 10
753+
else measured_depths[-1]
754+
)
755+
756+
perf_interval = well_path.append_perforation_interval(start_md, end_md, 0.25, 0.1)
757+
assert perf_interval is not None
758+
759+
# Get completion data
760+
completion_data = well_path.completion_data(case.id)
761+
assert completion_data is not None
762+
assert len(completion_data.welspecs) > 0
763+
764+
# Test WELSPECS grid_name field
765+
for welspec in completion_data.welspecs:
766+
assert welspec.well_name == "GridNameTestWell"
767+
768+
# For main grid wells, grid_name should be empty or not present
769+
# This results in WELSPECS output (not WELSPECL)
770+
if welspec.HasField("grid_name"):
771+
# If grid_name field exists, it should be empty for main grid
772+
assert (
773+
welspec.grid_name.strip() == ""
774+
), "Main grid wells should have empty grid_name"
775+
776+
# Verify required WELSPECS fields
777+
assert welspec.group_name, "Should have group name"
778+
779+
# Test specific grid coordinates (these should be deterministic for the test well path)
780+
assert welspec.grid_i == 29, f"Expected grid_i=29, got {welspec.grid_i}"
781+
assert welspec.grid_j == 41, f"Expected grid_j=41, got {welspec.grid_j}"
782+
783+
assert welspec.phase in [
784+
"OIL",
785+
"GAS",
786+
"WATER",
787+
"LIQ",
788+
], "Should have valid phase"
789+
790+
print(
791+
"Note: WELSPECL testing requires LGR grids. Current test case uses main grid only."
792+
)
793+
print(
794+
"WELSPECL functionality would be tested when grid_name contains a non-empty string."
795+
)
796+
797+
734798
def test_completion_data_cross_validation(rips_instance, initialize_test):
735799
"""Cross-validate completion data with perforation interval properties"""
736800
case_root_path = dataroot.PATH + "/TEST10K_FLT_LGR_NNC"

0 commit comments

Comments
 (0)