from math import pi
from .unit_converter import convert_unit
from .collapse_calcs import calc_collapse_pressure
from .von_mises import vme
from .design_factors import api_limits
from .connections import get_conn_limits
from .utilities import *
from .prepare_cases import *
from .plot import *
import well_profile as wp
[docs]class Casing(object):
"""
Casing object.
Arguments:
pipe (dict): set the main pipe characteristics. 'od', 'id', 'shoeDepth', 'tocMd', 'top', 'casingClass',
'weight'(opt), 'grade'(opt), 'e'(opt)
factors (dict): set define factors for pipe and connection.
Attributes:
od (num): outer diameter of the casing [in]
id (num): inner diameter of the casing [in]
thickness (str or None): outer diameter of the casing [in]
dt (num): ratio --> outer diameter / thickness
area (num): effective area [in^2]
shoe (num): measured depth at shoe [m]
ellipse (list): triaxial points [x, y+, y-]
loads (list): list of loads that have been run
nominal_weight (num): weight per unit length [kg/m]
trajectory (obj): wellbore trajectory object
api_lines (list): API limits coordinates [x, y]
design_factor (dict): design factors used 'vme', 'api'
"""
def __init__(self, pipe, conn_compression=0.6, conn_tension=0.6, factors=None):
df = {'pipe': {'tension': 1.1, 'compression': 1.1, 'burst': 1.1, 'collapse': 1.1, 'triaxial': 1.25},
'connection': {'tension': 1.0, 'compression': 1.0}}
if type(factors) == dict:
for key in factors.keys():
for item in factors[key].keys():
df[key][item] = factors[key][item]
self.od = pipe['od']
self.id = pipe['id']
self.area = (pi / 4) * (self.od ** 2 - self.id ** 2)
self.thickness = (self.od - self.id) / 2
self.dt = self.od / self.thickness
self.toc_md = pipe['tocMd']
self.shoe = pipe['shoeDepth']
self.top = pipe['top']
if 'casingClass' in pipe:
self.pipe_class = pipe['casingClass']
else:
self.pipe_class = None
if 'grade' in pipe:
yield_s = float(pipe['grade'].split('-')[1]) * 1000
else:
yield_s = 80000
if 'weight' in pipe:
self.nominal_weight = pipe['weight']
else:
self.nominal_weight = 64
if 'e' in pipe:
self.e = pipe['e']
else:
self.e = 29e6
self.limits = {'burst': 0.875 * 2 * yield_s * self.thickness / self.od,
'burstDF': 0.875 * 2 * yield_s * self.thickness / self.od / df['pipe']['burst'],
'collapse': - calc_collapse_pressure(self.dt, yield_s),
'collapseDF': - calc_collapse_pressure(self.dt, yield_s) / df['pipe']['collapse'],
'compression': - yield_s * self.area,
'compressionDF': - yield_s * self.area / df['pipe']['compression'],
'tension': yield_s * self.area,
'tensionDF': yield_s * self.area / df['pipe']['tension']}
self.ellipse = vme(yield_s, self.area, self.id, self.od, df['pipe']['triaxial'])
self.loads = []
self.trajectory = None
self.settings = None
self.msgs = None
self.safety_factors = None
self.api_lines, self.collapse_curve = api_limits(self.dt, yield_s, self.limits, self.area,
df['pipe']['tension'],
df['pipe']['compression'],
df['pipe']['burst'],
df['pipe']['collapse'])
self.conn_limits = get_conn_limits(self.limits, conn_compression, conn_tension,
df['connection']['compression'],
df['connection']['tension'])
self.design_factor = {'vme': df['pipe']['triaxial'],
'api': {'compression': df['pipe']['compression'],
'tension': df['pipe']['tension'],
'burst': df['pipe']['burst'],
'collapse': df['pipe']['collapse']}}
def add_trajectory(self, survey):
trajectory = wp.load(survey, equidistant=False)
idx = [trajectory.trajectory.index(x) for x in trajectory.trajectory if self.top <= x['md'] <= self.shoe]
trajectory.md = [x['md'] - self.top for x in trajectory.trajectory][idx[0]:idx[-1] + 1]
trajectory.tvd = [x['tvd'] - self.top for x in trajectory.trajectory][idx[0]:idx[-1] + 1]
trajectory.inclination = [x['inc'] for x in trajectory.trajectory][idx[0]:idx[-1] + 1]
trajectory.azimuth = [x['azi'] for x in trajectory.trajectory][idx[0]:idx[-1] + 1]
trajectory.dls = [x['dls'] for x in trajectory.trajectory][idx[0]:idx[-1] + 1]
self.trajectory = trajectory
def plot(self, plot_type='vme'):
if plot_type == 'pressureDiff':
fig = pressure_plot(self)
elif plot_type == 'burst':
fig = burst_plot(self)
elif plot_type == 'collapse':
fig = collapse_plot(self)
elif plot_type == 'axial':
fig = axial_plot(self)
else:
fig = vme_plot(self)
return fig
def run_loads(self, settings=None):
self.define_settings(settings)
config = self.settings
gen_msgs(self)
gen_overpull(self, rho_fluid=[config['densities']['mud']], v_avg=config['tripping']['speed'],
fric=config['tripping']['slidingFriction'], a=config['tripping']['maxSpeedRatio'],
f_ov=int(config['forces']['overpull']))
gen_running(self, rho_fluid=[config['densities']['mud']], v_avg=config['tripping']['speed'],
fric=config['tripping']['slidingFriction'], a=config['tripping']['maxSpeedRatio'])
gen_green_cement(self, rho_fluid_int=config['densities']['cementDisplacingFluid'],
rho_cement=config['densities']['cement'], f_pre=config['forces']['preloading'],
p_test=config['testing']['cementingPressure'])
gen_cementing(self, rho_cement=config['densities']['cement'],
rho_fluid=config['densities']['cementDisplacingFluid'],
f_pre=config['forces']['preloading'])
if self.pipe_class in [None, 'Production']:
gen_full_evacuation(self, rho_prod_fluid=config['production']['fluidDensity'],
rho_mud=config['densities']['mud'], md_toc=self.toc_md,
poisson=config['production']['poisson'],
f_setting=config['forces']['preloading'])
gen_mud_drop(self, rho_mud=config['densities']['mud'], rho_mud_new=config['densities']['mudDropTo'])
if 'Displacement to gas' not in self.msgs:
gen_displacement_gas(self, p_res=config['production']['resPressure'],
tvd_res=config['production']['resTvd'],
rho_gas=config['densities']['gasKick'], rho_mud=config['densities']['mud'])
if 'Production' not in self.msgs and self.pipe_class in [None, 'Production']:
gen_production(self, p_res=config['production']['resPressure'],
rho_prod_fluid=config['production']['fluidDensity'],
rho_ann_fluid=config['densities']['completionFluid'],
rho_packerfluid=config['production']['packerFluidDensity'],
md_toc=self.toc_md,
tvd_packer=config['production']['packerTvd'],
tvd_perf=config['production']['perforationsTvd'],
poisson=config['production']['poisson'],
f_setting=config['forces']['preloading'])
if 'Injection' not in self.msgs and self.pipe_class in [None, 'Production']:
gen_injection(self, whp=config['injection']['whp'],
rho_injectionfluid=config['densities']['injectionFluid'],
rho_mud=config['densities']['mud'], temp=config['temp'],
t_k=config['production']['wellHeadTemp'],
poisson=config['production']['poisson'],
f_setting=config['forces']['preloading'])
if 'Pressure Test' not in self.msgs:
gen_pressure_test(self, whp=config['testing']['testPressure'],
effective_diameter=config['testing']['pipeDiameter'],
rho_testing_fluid=config['testing']['testFluidDensity'],
rho_mud=config['densities']['mud'])
if 'Gas Kick' not in self.msgs:
gen_gas_kick(self, p_res=config['production']['resPressure'], tvd_res=config['production']['resTvd'],
rho_gas=config['densities']['gasKick'], rho_mud=config['densities']['mud'],
vol_kick_initial=config['influx']['gasKickVolume'])
define_max_loads(self.loads)
define_min_df(self)
define_safety_factors(self)
def define_settings(self, settings):
default = {'densities': {'mud': 1.5, 'cement': 1.9, 'cementDisplacingFluid': 1.6, 'gasKick': 0.5,
'completionFluid': 1.8, 'injectionFluid': 1.3, 'mudDropTo': 1.1},
'tripping': {'slidingFriction': 0.24, 'speed': 0.3, 'maxSpeedRatio': 1.5},
'production': {'fluidDensity': 0.9, 'packerFluidDensity': 1.3, 'poisson': 0.3, 'wellHeadTemp': 5},
'forces': {'overpull': 0,
'preloading': 0},
'testing': {'cementingPressure': 1500},
'injection': {'whp': 2000, 'injectionFluid': 1.3},
'temp': {'seabed': {'tvd': 500, 'temp': 4},
'target': {'tvd': 1500, 'temp': 160}},
'influx': {'gasKickVolume': 20}}
if type(settings) == dict:
for key in settings.keys():
for item in settings[key].keys():
default[key][item] = settings[key][item]
self.settings = default