Source code for kappa_sdk.keg5.keg5_well_property_inputs

import uuid
from typing import Optional, List


[docs] class Point3D: """ Class to store coordinates of a 3D point """ def __init__(self, x: float, y: float, z: float): self.x = x self.y = y self.z = z
[docs] class Keg5WellPropertyInputs: """ Class to store the properties to use to create a well in KEG5 """ __default_radius: float = 0.09144 def __init__(self, name: str, uwi: str, x: float, y: float, permeability: float, porosity: float, thickness: float, is_horizontal: bool, radius: Optional[float], perforation_length: Optional[float], skin: Optional[float]): """ Initialization of the well properties to use in a KEG to create a well Parameters ---------- name: well name uwi: unique well id x: x wellhead coordinate y: y wellhead coordinate permeability: permeability to apply to the zone where the well is porosity: porosity to apply to the zone where the well is thickness: thickness to apply to the zone where the well is is_horizontal: True if the well is horizontal, False if it is vertical radius: well radius, can be None, in that case the default radius (0.09144) will be used perforation_length: perforation length to apply, mandatory for horizontal wells, can be None for vertical ones, in that case all the well will be perforated skin: skin to apply """ if is_horizontal and perforation_length is None: raise ValueError(f"Error building well '{name}': perforation length has to be defined for a horizontal well") self.__name: str = name self.__uwi: str = uwi self.__x: float = x self.__y: float = y self.__permeability = permeability self.__porosity = porosity self.__thickness = thickness self.__is_horizontal = is_horizontal self.__radius = self.__default_radius if radius is None else radius self.__perforation_length = perforation_length self.__skin = skin self.__well_id: str = str(uuid.uuid4()) self.__perforation_id: str = str(uuid.uuid4()) self.__borehole_id: str = str(uuid.uuid4()) @property def name(self) -> str: """ Name of the well """ return self.__name @property def uwi(self) -> str: """ Unique well id of the well """ return self.__uwi @property def x(self) -> float: """ x well head coordinate """ return self.__x @property def y(self) -> float: """ x well head coordinate """ return self.__y @property def permeability(self) -> float: """ Permeability to apply to the zone where the well is """ return self.__permeability @property def porosity(self) -> float: """ Porosity to apply to the zone where the well is """ return self.__porosity @property def thickness(self) -> float: """ Permeability to apply to the zone where the well is """ return self.__thickness @property def radius(self) -> float: """ Well radius """ return self.__radius @property def skin(self) -> Optional[float]: """ Skin """ return self.__skin @property def well_id(self) -> str: """ WellId that will be used internally in KEG5 objects linked to this well """ return self.__well_id @property def perforation_id(self) -> str: """ PerforationId that will be used internally in KEG5 objects linked to this well """ return self.__perforation_id @property def borehole_id(self) -> str: """ BoreholeId that will be used internally in KEG5 objects linked to this well """ return self.__borehole_id def __get_perforation_length(self) -> float: assert self.__perforation_length is not None return self.__perforation_length def get_perforation_md_start(self, z_top: float) -> float: """ Returns the md start to use for the well perforation, for vertical wells: if the initial perforation length is undefined, we take md_start = well_md_start so the perforations will be present all along the well. If perforation length is defined, we apply that length from the end of the well. For horizontal wells we take z_top + thickness/2, which correspond to the first point of the well. Parameters ---------- z_top: z_top at the wellhead position Returns ------- md start of the perforation """ if self.__is_horizontal: return z_top + self.thickness/2 if self.__perforation_length is None: return z_top return max(z_top, z_top + self.thickness - self.__get_perforation_length()) def get_perforation_md_end(self, z_top: float) -> float: """ Returns the md end to use for the well perforation, for both type of wells we take the last point of the well Parameters ---------- z_top: z_top at the wellhead position Returns ------- md start of the perforation """ if self.__is_horizontal: return z_top + self.thickness/2 + self.__get_perforation_length() return z_top + self.thickness def get_well_trajectory(self, z_top: float) -> List[Point3D]: """ Calculates the trajectory of the well according to its type (horizontal of vertical) Parameters ---------- z_top: z_top at the well position Returns ------- A list of Point3D representing the trajectory of the well """ if self.__is_horizontal: z = z_top + self.thickness / 2 return [Point3D(self.x, self.y, z), Point3D(self.x + self.__get_perforation_length(), self.y, z)] return [Point3D(self.x, self.y, z_top), Point3D(self.x, self.y, z_top + self.thickness)] def get_well_type(self) -> str: return "HORIZONTAL" if self.__is_horizontal else "VERTICAL"