Skip to content

Commit

Permalink
Generate multi-trajectory schedule files
Browse files Browse the repository at this point in the history
  • Loading branch information
verveerpj committed Jul 6, 2024
1 parent 952fef1 commit 5943fb6
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 51 deletions.
110 changes: 62 additions & 48 deletions src/everest_models/jobs/fm_well_trajectory/resinsight.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import datetime
import logging
from pathlib import Path
from typing import Iterable, Optional, Tuple
from typing import Any, Dict, Iterable, Optional, Tuple

import lasio
import pandas
Expand Down Expand Up @@ -62,7 +62,7 @@ def create_well(
well_config: WellConfig,
guide_points: Trajectory,
project: rips.Project,
) -> None:
) -> Any:
_create_perforation_view(
connection.perforations,
connection.formations_file,
Expand Down Expand Up @@ -109,6 +109,34 @@ def create_well(
)
)

return well_path


def create_branches(
well_config: WellConfig,
well_path: Any,
mlt_guide_points: Dict[str, Tuple[float, Trajectory]],
project: rips.Project,
) -> Any:
for md, guide_points in mlt_guide_points.values():
lateral = well_path.append_lateral(md)
geometry = lateral.well_path_geometry()

intersection_points = []
for point in zip(guide_points.x[1:], guide_points.y[1:], guide_points.z[1:]):
coord = [str(item) for item in point]
target = geometry.append_well_target(coordinate=coord, absolute=True)
target.dogleg1 = well_config.dogleg
target.dogleg2 = well_config.dogleg
target.update()
intersection_points.append(coord)
geometry.update()

intersection_collection = project.descendants(rips.IntersectionCollection)[0]
intersection = intersection_collection.add_new_object(rips.CurveIntersection)
intersection.points = intersection_points
intersection.update()


def _find_time_step(
case: rips.Case, date: Optional[datetime.date] = None
Expand Down Expand Up @@ -144,7 +172,8 @@ def create_well_logs(
project: rips.Project,
eclipse_model: Path,
project_path: Path,
date: Optional[datetime.date] = None,
date: Optional[datetime.date],
has_mlt: bool,
) -> None:
case = project.cases()[0]

Expand All @@ -155,7 +184,11 @@ def create_well_logs(

well_log_plot = well_log_plot_collection.new_well_log_plot(case, well_path)

perforation = next(item for item in perforations if item.well == well_path.name)
perforation = next(
item
for item in perforations
if item.well == (well_path.name.split()[0] if has_mlt else well_path.name)
)

if perforation.dynamic:
restart = eclipse_model.with_suffix(".UNRST")
Expand Down Expand Up @@ -243,46 +276,52 @@ def _filter_perforation_properties(
return df_selected["DEPTH"]


def _make_perforations(
well: WellConfig,
case,
well_path,
perf_depths: pandas.Series,
well_depth: Optional[float],
project_path: Path,
) -> None:
export_filename = (project_path / well.name.replace(" ", "_")).with_suffix(".SCH")
def _read_las_file(las: Path) -> pandas.DataFrame:
return lasio.read(las).df().reset_index()

diameter = well.radius * 2
skin_factor = well.skin

def make_perforations(
project: rips.Project,
well_name: str,
perforations: Iterable[PerforationConfig],
wells: Iterable[WellConfig],
has_mlt: bool,
path: Path,
):
well_name_base = well_name.split()[0] if has_mlt else well_name
perf_depths, well_depth = _select_perforations(
perforation=next(item for item in perforations if item.well == well_name_base),
df=_read_las_file(next(path.glob(f"{well_name.replace(' ', '_')}*.las"))),
)
well = next(item for item in wells if item.name == well_name_base)

if well_depth is not None:
well_path = project.well_path_by_name(well_name)
total_perf_length = 0
if perf_depths.size > 0:
for start, end in zip(perf_depths.iloc[::2], perf_depths.iloc[1::2]):
well_path.append_perforation_interval(
start_md=start,
end_md=end,
diameter=diameter,
skin_factor=skin_factor,
diameter=2 * well.radius,
skin_factor=well.skin,
)

total_perf_length = round(total_perf_length + end - start, 2)
logger.info(f"Total perforation length is {total_perf_length}")

else: # create one dummy connection and shut it thereafter
well_path.append_perforation_interval(
start_md=well_depth - 1,
end_md=well_depth,
diameter=diameter,
skin_factor=skin_factor,
diameter=2 * well.radius,
skin_factor=well.skin,
)

export_filename = (path / well_name.replace(" ", "_")).with_suffix(".SCH")
logger.info(
f"Exporting well completion data to: {export_filename}"
f"\ncwd = {Path.cwd()}"
)
case.export_well_path_completions(
project.cases()[0].export_well_path_completions(
time_step=0,
well_path_names=[well_path.name],
file_split="UNIFIED_FILE",
Expand All @@ -292,34 +331,9 @@ def _make_perforations(
)

_generate_welspecs(
well.name, well.phase, well.group, export_filename, perf_depths, project_path
well.name, well.phase, well.group, export_filename, perf_depths, path
)


def _read_las_file(las: Path) -> pandas.DataFrame:
return lasio.read(las).df().reset_index()


def make_perforations(
project: rips.Project,
well_name: str,
perforations: Iterable[PerforationConfig],
wells: Iterable[WellConfig],
path: Path,
):
perforation_depth, well_depth = _select_perforations(
perforation=next(item for item in perforations if item.well == well_name),
df=_read_las_file(next(path.glob(f"{well_name.replace(' ', '_')}*.las"))),
)
well = next(item for item in wells if item.name == well_name)
_make_perforations(
well=well,
case=project.cases()[0],
well_path=project.well_path_by_name(well.name),
perf_depths=perforation_depth,
well_depth=well_depth,
project_path=path,
)
project.update()
return None if well_depth is None else well

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@
from .models.config import ConfigSchema, ResInsightInterpolationConfig
from .outputs import write_well_costs
from .read_trajectories import read_laterals
from .resinsight import create_well, create_well_logs, make_perforations, read_wells
from .resinsight import (
create_branches,
create_well,
create_well_logs,
make_perforations,
read_wells,
)
from .well_costs import compute_well_costs
from .well_trajectory_simple import Trajectory

Expand Down Expand Up @@ -71,13 +77,15 @@ def well_trajectory_resinsight(

if isinstance(config.interpolation, ResInsightInterpolationConfig):
# Interpolate trajectories and save smooth trajectories:
for well_config in config.wells:
create_well(
well_paths = {
well_config.name: create_well(
config.connections,
well_config,
guide_points[well_config.name],
resinsight.project,
)
for well_config in config.wells
}
_save_paths(
project_path,
resinsight.project,
Expand All @@ -88,6 +96,13 @@ def well_trajectory_resinsight(
config.scales, config.references, config.wells
)
if mlt_guide_points:
for well_config in config.wells:
create_branches(
well_config,
well_paths[well_config.name],
mlt_guide_points[well_config.name],
resinsight.project,
)
_save_paths(
project_path,
resinsight.project,
Expand All @@ -107,6 +122,7 @@ def well_trajectory_resinsight(
eclipse_model,
project_path,
config.connections.date,
bool(mlt_guide_points)
)
wells = itertools.filterfalse(
lambda x: x is None,
Expand All @@ -116,6 +132,7 @@ def well_trajectory_resinsight(
well_path.name,
config.connections.perforations,
config.wells,
bool(mlt_guide_points),
project_path,
)
for well_path in resinsight.project.well_paths()
Expand Down
13 changes: 13 additions & 0 deletions tests/testdata/well_trajectory/spe1case1_mlt/expected/INJ_Y2.SCH
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-- WELL GROUP BHP PHASE DRAIN INFLOW OPEN CROSS PVT HYDS FIP
-- NAME NAME I J DEPTH FLUID AREA EQUANS SHUT FLOW TABLE DENS REGN
WELSPECS
INJ G1 3 3 1* GAS 0.0 STD STOP YES 0 SEG 0 /
/
-- WELL OPEN SAT CONN WELL KH SKIN D DIR
-- NAME I J K1 K2 SHUT TAB FACT DIA FACT FACT FACT PEN
COMPDAT
INJ 3 3 1 1 OPEN 1* 7.456398E+01 0.30000 1.000000E+04 0.00000 1* 'Z' /
INJ 3 3 2 2 OPEN 1* 1.121509E+01 0.30000 1.503705E+03 0.00000 1* 'Z' /
INJ 3 3 3 3 OPEN 1* 7.928836E+01 0.30000 1.057577E+04 0.00000 1* 'Z' /
INJ 2 3 3 3 OPEN 1* 3.470050E+02 0.30000 4.440705E+04 0.00000 1* 'Z' /
/
16 changes: 16 additions & 0 deletions tests/testdata/well_trajectory/spe1case1_mlt/expected/INJ_Y3.SCH
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-- WELL GROUP BHP PHASE DRAIN INFLOW OPEN CROSS PVT HYDS FIP
-- NAME NAME I J DEPTH FLUID AREA EQUANS SHUT FLOW TABLE DENS REGN
WELSPECS
INJ G1 3 3 1* GAS 0.0 STD STOP YES 0 SEG 0 /
/
-- WELL OPEN SAT CONN WELL KH SKIN D DIR
-- NAME I J K1 K2 SHUT TAB FACT DIA FACT FACT FACT PEN
COMPDAT
INJ 3 3 1 1 OPEN 1* 7.456398E+01 0.30000 1.000000E+04 0.00000 1* 'Z' /
INJ 3 3 2 2 OPEN 1* 1.118459E+01 0.30000 1.499999E+03 0.00000 1* 'Z' /
INJ 3 3 3 3 OPEN 1* 7.465564E+01 0.30000 1.001114E+04 0.00000 1* 'Z' /
INJ 3 6 3 3 OPEN 1* 2.026594E+03 0.30000 2.588101E+05 0.00000 1* 'Y' /
INJ 3 8 3 3 OPEN 1* 3.133136E+03 0.30000 4.000000E+05 0.00000 1* 'Y' /
INJ 3 9 3 3 OPEN 1* 3.133136E+03 0.30000 4.000000E+05 0.00000 1* 'Y' /
INJ 3 10 3 3 OPEN 1* 7.832840E+02 0.30000 9.999998E+04 0.00000 1* 'Y' /
/
14 changes: 14 additions & 0 deletions tests/testdata/well_trajectory/spe1case1_mlt/expected/PROD_Y2.SCH
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
-- WELL GROUP BHP PHASE DRAIN INFLOW OPEN CROSS PVT HYDS FIP
-- NAME NAME I J DEPTH FLUID AREA EQUANS SHUT FLOW TABLE DENS REGN
WELSPECS
PROD G1 8 8 1* OIL 0.0 STD STOP YES 0 SEG 0 /
/
-- WELL OPEN SAT CONN WELL KH SKIN D DIR
-- NAME I J K1 K2 SHUT TAB FACT DIA FACT FACT FACT PEN
COMPDAT
PROD 8 8 1 1 OPEN 1* 7.459173E+01 0.30000 1.000336E+04 0.00000 1* 'Z' /
PROD 8 8 2 2 OPEN 1* 1.120798E+01 0.30000 1.502841E+03 0.00000 1* 'Z' /
PROD 8 8 3 3 OPEN 1* 7.528431E+01 0.30000 1.008758E+04 0.00000 1* 'Z' /
PROD 9 9 3 3 OPEN 1* 8.896967E+02 0.30000 1.136119E+05 0.00000 1* 'Z' /
PROD 10 10 3 3 OPEN 1* 2.216264E+03 0.30000 2.829557E+05 0.00000 1* 'Y' /
/

0 comments on commit 5943fb6

Please sign in to comment.