Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add gas lift valve for the SCORE converter #10

Merged
merged 3 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion src/alfasim_score/constants.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from barril.units import Scalar

from alfasim_score.units import DENSITY_UNIT
from alfasim_score.units import DIAMETER_UNIT
from alfasim_score.units import DIMENSIONLESS
from alfasim_score.units import FRACTION_UNIT
from alfasim_score.units import HEAT_TRANSFER_COEFFICIENT_UNIT
from alfasim_score.units import LENGTH_UNIT
from alfasim_score.units import MASS_FLOW_RATE_UNIT
from alfasim_score.units import PRESSURE_UNIT
from alfasim_score.units import ROUGHNESS_UNIT
from alfasim_score.units import STD_VOLUMETRIC_FLOW_RATE_UNIT

Expand All @@ -14,6 +17,7 @@
ANNULUS_TOP_NODE_NAME = "WELLBORE_ANNULUS_TOP_NODE"
GAS_LIFT_MASS_NODE_NAME = "GAS_LIFT_MASS_NODE"
CEMENT_NAME = "cement"
GAS_LIFT_VALVE_NAME = "GAS_LIFT_VALVE"

ROCK_DEFAULT_ROUGHNESS = Scalar(0.1, ROUGHNESS_UNIT)
ROCK_DEFAULT_HEAT_TRANSFER_COEFFICIENT = Scalar(1000.0, HEAT_TRANSFER_COEFFICIENT_UNIT)
Expand All @@ -22,7 +26,7 @@

REFERENCE_VERTICAL_COORDINATE = Scalar(0.0, LENGTH_UNIT, "length")

# This default fluid name for packer and fluid above filler
# this default fluid name for packer and fluid above filler
FLUID_DEFAULT_NAME = "fluid_default"

# nodes data
Expand All @@ -37,3 +41,8 @@
# default values used in the context of black-oil models
H2S_MOLAR_FRACTION_DEFAULT = Scalar(0.0, FRACTION_UNIT)
CO2_MOLAR_FRACTION_DEFAULT = Scalar(0.0, FRACTION_UNIT)

# gas lift default values
GAS_LIFT_VALVE_DEFAULT_DIAMETER = Scalar(0.25, DIAMETER_UNIT, "diameter")
GAS_LIFT_VALVE_DEFAULT_DISCHARGE = Scalar(0.826, DIMENSIONLESS)
GAS_LIFT_VALVE_DEFAULT_DELTA_P_MIN = Scalar(0.0, PRESSURE_UNIT)
Original file line number Diff line number Diff line change
Expand Up @@ -954,7 +954,7 @@ wells:
values:
- 288.6
unit: K
top_node: WELLBORE_ANNULUS_TOP_NODE
top_node: GAS_LIFT_MASS_NODE
formation:
reference_y_coordinate:
value: 0.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ pipes: []
nodes:
- name: WELLBORE_TOP_NODE
node_type: mass_source_boundary
pvt_model: base
pvt_model: DFLT_BLACK_OIL_27.40_230.00_1.17
pressure_properties:
pressure:
value: 100000.0
Expand Down Expand Up @@ -217,7 +217,7 @@ nodes:
max_rate_of_change: 1e+50
- name: WELLBORE_BOTTOM_NODE
node_type: pressure_boundary
pvt_model: base
pvt_model: DFLT_BLACK_OIL_27.40_230.00_1.17
pressure_properties:
pressure:
value: 9814.11
Expand Down Expand Up @@ -298,7 +298,7 @@ nodes:
max_rate_of_change: 1e+50
- name: GAS_LIFT_MASS_NODE
node_type: mass_source_boundary
pvt_model: gas_lift
pvt_model: DFLT_BLACK_OIL_27.40_230.00_1.17
pressure_properties:
pressure:
value: 100000.0
Expand Down Expand Up @@ -389,7 +389,7 @@ nodes:
max_rate_of_change: 1e+50
wells:
- name: WELLBORE
pvt_model: base
pvt_model: DFLT_BLACK_OIL_27.40_230.00_1.17
stagnant_fluid: fluid_default
profile:
x_and_y:
Expand Down Expand Up @@ -803,7 +803,8 @@ wells:
value: 0.1
unit: mm
annulus:
has_annulus_flow: False
has_annulus_flow: True
pvt_model: DFLT_BLACK_OIL_27.40_230.00_1.17
initial_conditions:
pressures:
position_input_type: length
Expand Down Expand Up @@ -954,7 +955,23 @@ wells:
values:
- 288.6
unit: K
top_node: WELLBORE_ANNULUS_TOP_NODE
equipment:
gas_lift_valves:
GAS_LIFT_VALVE_1:
position:
value: 928.0
unit: m
diameter:
value: 0.25
unit: in
valve_type: check_valve
delta_p_min:
value: 0.0
unit: psi
discharge_coefficient:
value: 0.826
unit: unitless
top_node: GAS_LIFT_MASS_NODE
formation:
reference_y_coordinate:
value: 0.0
Expand Down
61 changes: 60 additions & 1 deletion src/alfasim_score/converter/alfacase/base_operation.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,36 @@
from typing import Dict
from typing import List

import attr
from alfasim_sdk import AnnulusDescription
from alfasim_sdk import AnnulusEquipmentDescription
from alfasim_sdk import GasLiftValveEquipmentDescription
from alfasim_sdk import InitialConditionsDescription
from alfasim_sdk import InitialPressuresDescription
from alfasim_sdk import InitialTemperaturesDescription
from alfasim_sdk import InitialVelocitiesDescription
from alfasim_sdk import InitialVolumeFractionsDescription
from alfasim_sdk import MassInflowSplitType
from alfasim_sdk import MassSourceNodePropertiesDescription
from alfasim_sdk import MassSourceType
from alfasim_sdk import MultiInputType
from alfasim_sdk import NodeDescription
from alfasim_sdk import PressureContainerDescription
from alfasim_sdk import PressureNodePropertiesDescription
from alfasim_sdk import TableInputType
from alfasim_sdk import ValveType
from alfasim_sdk import WellDescription
from alfasim_sdk._internal.constants import FLUID_GAS
from alfasim_sdk._internal.constants import FLUID_OIL
from alfasim_sdk._internal.constants import FLUID_WATER

from alfasim_score.common import LiftMethod
from alfasim_score.common import ModelFluidType
from alfasim_score.constants import GAS_LIFT_MASS_NODE_NAME
from alfasim_score.constants import GAS_LIFT_VALVE_DEFAULT_DELTA_P_MIN
from alfasim_score.constants import GAS_LIFT_VALVE_DEFAULT_DIAMETER
from alfasim_score.constants import GAS_LIFT_VALVE_DEFAULT_DISCHARGE
from alfasim_score.constants import GAS_LIFT_VALVE_NAME
from alfasim_score.constants import NULL_VOLUMETRIC_FLOW_RATE
from alfasim_score.constants import WELLBORE_BOTTOM_NODE_NAME
from alfasim_score.constants import WELLBORE_TOP_NODE_NAME
Expand All @@ -23,7 +42,37 @@ class BaseOperationBuilder(ScoreAlfacaseConverter):
def __init__(self, score_reader: ScoreInputReader):
super().__init__(score_reader)

def has_gas_lift(self) -> bool:
"""Check the operation has gas lift."""
return self.score_input.read_operation_data()["lift_method"] == LiftMethod.GAS_LIFT

def _get_gas_lift_valves(self) -> Dict[str, GasLiftValveEquipmentDescription]:
"""Create the gas lift valves for the annulus."""
gas_lift_data = self.score_input.read_operation_method_data()
valves = {
f"{GAS_LIFT_VALVE_NAME}_1": GasLiftValveEquipmentDescription(
position=self._get_position_in_well(gas_lift_data["valve_depth"]),
diameter=GAS_LIFT_VALVE_DEFAULT_DIAMETER,
valve_type=ValveType.CheckValve,
delta_p_min=GAS_LIFT_VALVE_DEFAULT_DELTA_P_MIN,
discharge_coefficient=GAS_LIFT_VALVE_DEFAULT_DISCHARGE,
)
}
return valves

def build_annulus(self) -> AnnulusDescription:
"""Configure the annulus with data from SCORE operation."""
return AnnulusDescription(
has_annulus_flow=self.has_gas_lift(),
pvt_model=self.get_fluid_model_name(),
equipment=AnnulusEquipmentDescription(
gas_lift_valves=self._get_gas_lift_valves(),
),
top_node=GAS_LIFT_MASS_NODE_NAME,
)

def build_nodes(self) -> List[NodeDescription]:
""" "Configure the nodes with data from SCORE operation."""
operation_data = self.score_input.read_operation_data()
default_nodes = {node.name: node for node in super().build_nodes()}
configured_nodes = [
Expand All @@ -40,6 +89,7 @@ def build_nodes(self) -> List[NodeDescription]:
FLUID_WATER: -1.0 * operation_data["water_flow_rate"],
},
),
pvt_model=self.get_fluid_model_name(),
),
attr.evolve(
default_nodes.pop(WELLBORE_BOTTOM_NODE_NAME),
Expand All @@ -48,9 +98,10 @@ def build_nodes(self) -> List[NodeDescription]:
pressure=operation_data["flow_initial_pressure"],
split_type=MassInflowSplitType.Pvt,
),
pvt_model=self.get_fluid_model_name(),
),
]
if GAS_LIFT_MASS_NODE_NAME in default_nodes:
if self.has_gas_lift():
gas_lift_data = self.score_input.read_operation_method_data()
configured_nodes.append(
attr.evolve(
Expand All @@ -65,6 +116,14 @@ def build_nodes(self) -> List[NodeDescription]:
FLUID_WATER: NULL_VOLUMETRIC_FLOW_RATE,
},
),
pvt_model=self.get_fluid_model_name(),
)
)
return configured_nodes

def build_well(self) -> WellDescription:
"""Create the description for the well."""
return attr.evolve(
super().build_well(),
pvt_model=self.get_fluid_model_name(),
)
52 changes: 25 additions & 27 deletions src/alfasim_score/converter/alfacase/convert_alfacase.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,10 @@
from alfasim_sdk._internal.constants import FLUID_WATER
from barril.units import Scalar

from alfasim_score.common import LiftMethod
from alfasim_score.common import ModelFluidType
from alfasim_score.common import convert_api_gravity_to_oil_density
from alfasim_score.common import convert_gas_gravity_to_gas_density
from alfasim_score.common import convert_quota_to_tvd
from alfasim_score.constants import ANNULUS_TOP_NODE_NAME
from alfasim_score.constants import BASE_PVT_TABLE_NAME
from alfasim_score.constants import CASING_DEFAULT_ROUGHNESS
from alfasim_score.constants import CEMENT_NAME
Expand All @@ -58,6 +57,7 @@
from alfasim_score.constants import WELLBORE_TOP_NODE_NAME
from alfasim_score.converter.alfacase.score_input_reader import ScoreInputReader
from alfasim_score.units import LENGTH_UNIT
from alfasim_score.units import PRESSURE_UNIT
from alfasim_score.units import TEMPERATURE_UNIT


Expand Down Expand Up @@ -90,6 +90,10 @@ def _get_position_in_well(self, position: Scalar) -> Scalar:
"""Get the position relative to the well start position."""
return position - self.well_start_position

def get_fluid_model_name(self) -> ModelFluidType:
"""Get the name of the fluid model used for this operation."""
return self.score_input.read_operation_fluid_data()["name"]

def _convert_well_trajectory(self) -> ProfileDescription:
"""
Convert the trajectory for the imported well.
Expand Down Expand Up @@ -123,11 +127,9 @@ def _convert_materials(self) -> List[MaterialDescription]:
)
return filter_duplicated_materials(material_descriptions)

def _convert_annulus(self) -> AnnulusDescription:
# TODO PWPA-1937: implement this method
# TODO PWPA-1937: Use the GAS_LIFT_MASS_NODE, check for the gas lift presence
# and set flow rate zero with the flag false for annulus flow.
return AnnulusDescription(has_annulus_flow=False, top_node=ANNULUS_TOP_NODE_NAME)
def build_annulus(self) -> AnnulusDescription:
"""Create the description for the annulus."""
return AnnulusDescription(has_annulus_flow=False, top_node=GAS_LIFT_MASS_NODE_NAME)

def _convert_formation(self) -> FormationDescription:
"""Create the description for the formations."""
Expand Down Expand Up @@ -305,25 +307,21 @@ def build_nodes(self) -> List[NodeDescription]:
split_type=MassInflowSplitType.Pvt,
),
),
NodeDescription(
name=GAS_LIFT_MASS_NODE_NAME,
node_type=NodeCellType.MassSource,
pvt_model=GAS_LIFT_PVT_TABLE_NAME,
mass_source_properties=MassSourceNodePropertiesDescription(
temperature_input_type=MultiInputType.Constant,
source_type=MassSourceType.AllVolumetricFlowRates,
volumetric_flow_rates_std={
FLUID_GAS: NULL_VOLUMETRIC_FLOW_RATE,
FLUID_OIL: NULL_VOLUMETRIC_FLOW_RATE,
FLUID_WATER: NULL_VOLUMETRIC_FLOW_RATE,
},
),
),
]
operation_input_data = self.score_input.read_operation_data()
if operation_input_data["lift_method"] == LiftMethod.GAS_LIFT:
nodes.append(
NodeDescription(
name=GAS_LIFT_MASS_NODE_NAME,
node_type=NodeCellType.MassSource,
pvt_model=GAS_LIFT_PVT_TABLE_NAME,
mass_source_properties=MassSourceNodePropertiesDescription(
temperature_input_type=MultiInputType.Constant,
source_type=MassSourceType.AllVolumetricFlowRates,
volumetric_flow_rates_std={
"gas": NULL_VOLUMETRIC_FLOW_RATE,
"oil": NULL_VOLUMETRIC_FLOW_RATE,
"water": NULL_VOLUMETRIC_FLOW_RATE,
},
),
)
)
return nodes

def build_well(self) -> WellDescription:
Expand All @@ -334,15 +332,15 @@ def build_well(self) -> WellDescription:
stagnant_fluid=FLUID_DEFAULT_NAME,
profile=self._convert_well_trajectory(),
casing=self._convert_casings(),
annulus=self._convert_annulus(),
annulus=self.build_annulus(),
formation=self._convert_formation(),
top_node=WELLBORE_TOP_NODE_NAME,
bottom_node=WELLBORE_BOTTOM_NODE_NAME,
environment=self._convert_well_environment(),
)

def build_case_description(self) -> CaseDescription:
""" "Create the description for the alfacase."""
"""Create the description for the alfacase."""
return CaseDescription(
name=self.general_data["case_name"],
physics=self.build_physics(),
Expand Down
1 change: 1 addition & 0 deletions src/alfasim_score/units.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@
TEMPERATURE_UNIT = "degC"
GAS_OIL_RATIO_UNIT = "sm3/sm3"
HEAT_TRANSFER_COEFFICIENT_UNIT = "W/m2.K"
DIMENSIONLESS = "unitless"
Loading