tubing-design
SKILL.md
Production Tubing Design and Force Analysis
Completions engineering skill for production tubing string design, force analysis, and buckling evaluation per Lubinski et al. (1962).
Important: Tubing force analysis is sensitive to completion geometry. Always verify packer type (free, anchored, set-on-tension/compression) before applying load case equations. For HP/HT wells, use dedicated software (WellCat, StressCheck, or equivalent).
Module 1 — Tubing Properties
API Tubing Grades and Common Sizes
| OD (in) | Weight (lb/ft) | ID (in) | Wall (in) | Grade | Yield (psi) |
|---|---|---|---|---|---|
| 1.900 | 2.90 | 1.610 | 0.145 | J-55 | 55,000 |
| 2⅜ | 4.70 | 1.995 | 0.190 | J-55 | 55,000 |
| 2⅜ | 4.70 | 1.995 | 0.190 | N-80 | 80,000 |
| 2⅞ | 6.50 | 2.441 | 0.217 | J-55 | 55,000 |
| 2⅞ | 6.50 | 2.441 | 0.217 | N-80 | 80,000 |
| 3½ | 9.30 | 2.992 | 0.254 | J-55 | 55,000 |
| 3½ | 9.30 | 2.992 | 0.254 | N-80 | 80,000 |
| 4 | 11.00 | 3.476 | 0.262 | N-80 | 80,000 |
def tubing_cross_section_areas(od_in, id_in):
"""
Returns pipe body cross-sectional area (steel) and internal area (in²).
"""
import math
A_i = math.pi / 4.0 * id_in**2 # internal (fluid) area
A_o = math.pi / 4.0 * od_in**2 # outer area
A_s = A_o - A_i # steel area
return {"A_steel_in2": A_s, "A_inner_in2": A_i, "A_outer_in2": A_o}
Material Constants (Steel)
| Property | Value | Units |
|---|---|---|
| Young's modulus (E) | 30 × 10⁶ | psi |
| Thermal expansion (α) | 6.9 × 10⁻⁶ | 1/°F |
| Poisson's ratio (ν) | 0.30 | — |
| Density (steel) | 489.5 | lb/ft³ |
Module 2 — Four Force Effects (Lubinski et al., 1962)
The total force change on a free-moving tubing string equals the sum of four independent effects. Each produces an axial force change ΔF (positive = tension, negative = compression).
Effect 1: Temperature
def delta_F_temperature(delta_T_avg_f, od_in, id_in, E=30e6, alpha=6.9e-6):
"""
ΔF_T = -E * A_steel * alpha * ΔT
Positive ΔT (heating during production): compressive force (negative)
delta_T_avg_f: average temperature change along string (°F)
Returns: ΔF_T in lbf (negative = compression added)
"""
import math
A_s = math.pi / 4.0 * (od_in**2 - id_in**2)
return -E * A_s * alpha * delta_T_avg_f
Effect 2: Ballooning
def delta_F_ballooning(delta_Pi_psi, delta_Po_psi, od_in, id_in, nu=0.30):
"""
ΔF_B = -2ν * (ΔPi * Ai - ΔPo * Ao)
Positive ΔPi (pressure increase inside): compressive (shortens tubing, piston)
delta_Pi_psi: change in average internal pressure (psi)
delta_Po_psi: change in average annulus (external) pressure (psi)
Returns: ΔF_B in lbf
"""
import math
Ai = math.pi / 4.0 * id_in**2
Ao = math.pi / 4.0 * od_in**2
return -2.0 * nu * (delta_Pi_psi * Ai - delta_Po_psi * Ao)
Effect 3: Piston Effect
def delta_F_piston(delta_Pi_psi, delta_Po_psi, od_in, id_in):
"""
ΔF_P = ΔPo * Ao - ΔPi * Ai (force at packer / area change)
Occurs at any cross-section change: packer bore, tubing end, plug
delta_Pi_psi: change in tubing pressure at packer
delta_Po_psi: change in annulus pressure at packer
Returns: ΔF_P in lbf (positive = tension)
"""
import math
Ai = math.pi / 4.0 * id_in**2
Ao = math.pi / 4.0 * od_in**2
return delta_Po_psi * Ao - delta_Pi_psi * Ai
Effect 4: Total Force Change and Buckling Check
def total_force_change(dF_T, dF_B, dF_P):
"""Returns total ΔF = ΔF_T + ΔF_B + ΔF_P (lbf)."""
return dF_T + dF_B + dF_P
def buckling_check(F_initial_lbf, dF_total_lbf, W_buoyed_lb_ft, depth_ft):
"""
Neutral point depth = (F_effective) / W_buoyed
Below neutral point: compression -> buckling risk
F_initial: initial tubing weight in fluid at packer (lbf, typically tension)
"""
F_final = F_initial_lbf + dF_total_lbf
neutral_point_ft = F_final / W_buoyed_lb_ft if W_buoyed_lb_ft > 0 else 0
buckled_length = depth_ft - neutral_point_ft
return {
"F_final_lbf": F_final,
"neutral_point_ft": neutral_point_ft,
"buckled_length_ft": max(0.0, buckled_length),
"buckling": buckled_length > 0
}
Module 3 — Buckling Analysis (Lubinski)
Critical Buckling Loads
def sinusoidal_buckling_force(w_e_lb_ft, r_c_in, EI_lbf_in2):
"""
Sinusoidal buckling onset:
F_cr_sin = 2 * sqrt(E*I * w_e / r_c)
w_e_lb_ft: buoyed weight per unit length (lb/ft)
r_c_in: radial clearance between tubing OD and casing ID (inches)
EI_lbf_in2: flexural rigidity = E * I
Returns: F_cr_sin in lbf (compressive force to initiate sinusoidal buckling)
"""
w_e_in = w_e_lb_ft / 12.0 # convert to lb/in
r_c_ft = r_c_in / 12.0
import math
return 2.0 * math.sqrt(EI_lbf_in2 * w_e_in / r_c_in)
def helical_buckling_force(w_e_lb_ft, r_c_in, EI_lbf_in2):
"""Helical onset ≈ 2.83 * F_cr_sin (Dawson-Paslay, 1984)."""
return 2.83 * sinusoidal_buckling_force(w_e_lb_ft, r_c_in, EI_lbf_in2)
def moment_of_inertia(od_in, id_in):
"""I = pi/64 * (OD^4 - ID^4) (in^4)"""
import math
return math.pi / 64.0 * (od_in**4 - id_in**4)
Helical Pitch and Lateral Force
def helical_pitch(F_comp_lbf, EI_lbf_in2, r_c_in):
"""
Pitch of helix (in): p = 2*pi * sqrt(2*E*I / (F * r_c))
Shorter pitch = tighter helix = more casing wear
"""
import math
return 2.0 * math.pi * math.sqrt(2.0 * EI_lbf_in2 / (F_comp_lbf * r_c_in))
def lateral_contact_force(w_e_lb_ft, r_c_in, p_in):
"""
Lateral contact force per unit length (lb/ft):
w_n = (4*pi^2 * w_e * r_c) / p^2
"""
import math
return (4 * math.pi**2 * w_e_lb_ft * r_c_in) / (p_in**2)
Module 4 — Seal Assembly Stroke
def seal_assembly_stroke(total_movement_in, safety_factor=1.5):
"""
Required seal assembly stroke = total tubing movement * SF
total_movement_in: calculated free-end movement (inches)
Return: minimum seal assembly length (in)
"""
return abs(total_movement_in) * safety_factor
def tubing_movement_temperature(L_ft, delta_T_avg_f, alpha=6.9e-6):
"""
Free thermal movement (in): delta_L = alpha * L * delta_T * 12
Positive ΔT (heating): tubing elongates (moves up at surface, pushes down at packer)
"""
return alpha * L_ft * delta_T_avg_f * 12.0
Module 5 — Velocity String Sizing
def velocity_string_recommendation(q_gas_mscfd, p_wellhead_psi, T_wellhead_f,
sigma=60.0, rho_l=62.4):
"""
For a liquid-loading gas well, find the largest tubing ID that keeps
gas velocity above Turner critical velocity.
Returns: max ID (inches) for unloading.
"""
import math
T_R = T_wellhead_f + 459.67
rho_g = (28.97 * 0.65 * p_wellhead_psi) / (10.73 * T_R * 0.9)
v_crit = 1.593 * sigma**0.25 * (rho_l - rho_g)**0.25 / rho_g**0.5
# q_gas (scf/day) = v_crit (ft/s) * A (ft2) * 86400 * (P/14.7) * (520/T_R)
# Solve for A_max
scfd = q_gas_mscfd * 1000.0
A_max_ft2 = scfd / (v_crit * 86400.0 * (p_wellhead_psi / 14.7) * (520.0 / T_R))
id_max_in = math.sqrt(4.0 * A_max_ft2 / math.pi) * 12.0
return {"v_crit_ft_s": v_crit, "A_max_ft2": A_max_ft2, "ID_max_in": id_max_in}
Module 6 — Packer Selection and DHSV
Packer Type Selection
| Situation | Packer Type | Notes |
|---|---|---|
| Permanent (stimulation) | Permanent set, milled to retrieve | Best isolation; costly retrieval |
| Workover anticipated | Retrievable (slip, hydraulic) | Release with string manipulation |
| High-pressure differential | Permanent or production packer | Higher pressure rating |
| Multiple zones | Retrievable straddle or permanent | Zone-specific stimulation |
| ESP completion | Bagpipe / tandem seal | Accommodates ESP motor below |
DHSV Setting Depth
def dhsv_minimum_depth_ft(wellhead_shut_in_psi, fluid_grad_psi_ft=0.433):
"""
DHSV must be set deep enough that casing burst is protected if tubing fails.
Minimum depth: DHSV setting depth > P_wellhead / fluid_gradient
Regulation: typically 100–200 ft below surface casing shoe or as specified.
Returns: minimum TVD for DHSV (ft)
"""
return wellhead_shut_in_psi / fluid_grad_psi_ft
Output Format
## Tubing String Design — [Well Name / API]
**String:** X-in OD, Grade N-80 / P-110 | **Set depth:** X,XXX ft
**Packer:** [Free / Anchored / Semi-anchored]
### Force Analysis Summary
| Load Case | ΔF_T (klbf) | ΔF_B (klbf) | ΔF_P (klbf) | ΔF_Total (klbf) |
|-----------|------------|------------|------------|----------------|
| Installation → Stimulation | | | | |
| Installation → Production | | | | |
| Production → Workover | | | | |
### Buckling Assessment
| Load Case | F_final (klbf) | Neutral Point (ft) | Buckled Length (ft) | Risk |
|-----------|---------------|-------------------|---------------------|------|
| | | | | |
### Movement and Seal Assembly
| Load Case | Free Movement (in) | Required Stroke (in) |
|-----------|-------------------|---------------------|
| | | |
### Velocity String Check (if applicable)
Required ID max: X.XX in | Selected: X-in OD, X.XXX ID
Error Handling
| Condition | Cause | Action |
|---|---|---|
| Neutral point above packer | Large compressive load | Verify packer type; increase set weight |
| Buckled length > tubing length | Extreme load case | Use anchored packer; check stimulation pressure |
| Movement exceeds seal stroke | Underdimensioned seal assembly | Specify longer seal; consider anchored completion |
| Negative torque on helix | Tension everywhere | No buckling; helix equations don't apply |
Caveats
- Lubinski four-effect analysis assumes straight wellbore and uniform temperature gradient. For deviated wells, contact forces and friction modify the analysis significantly — use dedicated software.
- Free-tubing analysis gives maximum movement; anchored packer absorbs movement and transfers force to the wellhead. Semi-anchored falls between.
- The Lubinski (1962) sinusoidal and helical buckling onset loads assume uniform tubing properties and no friction. Deviated wells have lower onset buckling loads due to gravity components.
- Thermal effects dominate in steam injection and high-GOR wells. Ensure temperature profile is accurately modeled for these cases.
- API RP 5C3 burst and collapse ratings apply; always check that tubing survives stimulation (frac) and production pressure differentials.
Weekly Installs
1
Repository
jpfielding/claude.pngeFirst Seen
4 days ago
Security Audits
Installed on
amp1
cline1
opencode1
cursor1
kimi-cli1
codex1