Adds files

This commit is contained in:
Patrick McDonagh
2016-05-27 17:38:12 -05:00
commit 0adef36b26
8 changed files with 1911 additions and 0 deletions

726
algorithm.py Normal file
View File

@@ -0,0 +1,726 @@
import math
import matplotlib
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
from collections import deque
import datetime
import time
import csv
import json
import setupTapers
print("Be sure that this folder includes setupTapers.py and that you've put a surface card in surface_card.json.")
ready = str(raw_input("Are you ready to start? (y/n): ")).lower()
if not (ready == 'y'):
raise Exception("Not ready to start!")
well_setup = setupTapers.get_setup()
surface = []
with open('surface_card.json') as sc:
surface = json.loads(sc.read())
load_before = 0.0
load_after = 0.0
load_before_3 = 0.0
load_after_3 = 0.0
blank_array = [0.0]*100
top_pos_array = deque()
top_load_array = deque()
for i in range(0, 10):
top_pos_array.append(blank_array[:])
top_load_array.append(blank_array[:])
pump_pos_array = []
pump_load_array = []
pr_l = [0.0, 0.0]
pr_p = [0.0, 0.0]
pmp_p = [0.0, 0.0]
pmp_l = [0.0, 0.0]
count = [0] * (well_setup['num_tapers']+1)
position_load_counter = 0
surface_pos_array = []
surface_load_array = []
class Card:
def __init__(self, id, s_p_array, s_l_array, d_p_array, d_l_array, t, u_c):
self.card_id = id
self.date_time = datetime.datetime.now()
self.tapers = t
self.well_setup = u_c
self.surface_pos = s_p_array[:]
self.surface_load = s_l_array[:]
self.downhole_pos = d_p_array[:]
self.downhole_load = d_l_array[:]
self.downhole_fluid_load_adjustment = 223.907
print("downhole_fluid_load_adjustment not configured")
self.card_type = "NotConfigured"
print("card_type not configured")
self.riemann_slices = 100
def set_strokes_per_minute(self, strokes_per_minute):
self.strokes_per_minute = strokes_per_minute
def find_limits(self):
surface_max_position_position = max(self.surface_pos)
surface_max_position_load = self.surface_load[self.surface_pos.index(surface_max_position_position)]
self.surface_max_position = [surface_max_position_position, surface_max_position_load]
surface_min_position_position = min(self.surface_pos)
surface_min_position_load = self.surface_load[self.surface_pos.index(surface_min_position_position)]
self.surface_min_position = [surface_min_position_position, surface_min_position_load]
surface_max_load_load = max(self.surface_load)
surface_max_load_position = self.surface_pos[self.surface_load.index(surface_max_load_load)]
self.surface_max_load = [surface_max_load_position, surface_max_load_load]
surface_min_load_load = min(self.surface_load)
surface_min_load_position = self.surface_pos[self.surface_load.index(surface_min_load_load)]
self.surface_min_load = [surface_min_load_position, surface_min_load_load]
downhole_max_load_load = max(self.downhole_load)
downhole_max_load_position = self.downhole_pos[self.downhole_load.index(downhole_max_load_load)]
self.downhole_max_load = [downhole_max_load_position, downhole_max_load_load]
downhole_min_load_load = min(self.downhole_load)
downhole_min_load_position = self.downhole_pos[self.downhole_load.index(downhole_min_load_load)]
self.downhole_min_load = [downhole_min_load_position, downhole_min_load_load]
downhole_min_position_position = min(self.downhole_pos)
downhole_min_position_load = self.downhole_load[self.downhole_pos.index(downhole_min_position_position)]
self.downhole_min_position = [downhole_min_position_position, downhole_min_position_load]
downhole_max_position_position = max(self.downhole_pos)
downhole_max_position_load = self.downhole_load[self.downhole_pos.index(downhole_max_position_position)]
self.downhole_max_position = [downhole_max_position_position, downhole_max_position_load]
self.downhole_fluid_load = (self.downhole_max_load[1] - self.downhole_min_load[1]) - self.downhole_fluid_load_adjustment
self.surface_stroke_length = self.surface_max_position[0] - self.surface_min_position[0]
def print_limits(self):
if not ('self.surface_stroke_length' in locals()):
self.find_limits()
print("Surface Max Position:", self.surface_max_position)
print("Surface Min Position:", self.surface_min_position)
print("Surface Max Load:", self.surface_max_load)
print("Surface Min Load:", self.surface_min_load)
print("Downhole Max Load:", self.downhole_max_load)
print("Downhole Min Load:", self.downhole_min_load)
print("Downhole Min Position:", self.downhole_min_position)
print("Downhole Max Position:", self.downhole_max_position)
def distance_to_line(self, x0, y0):
""" Finds the perpendicular distance from a point to the line between max and min points"""
x1 = self.downhole_min_position[0]
x2 = self.downhole_max_position[0]
y1 = self.downhole_min_load[1]
y2 = self.downhole_max_load[1]
d = abs((y2-y1)*x0 - (x2-x1)*y0 + x2*y1 - y2*x1) / math.sqrt(math.pow(y2-y1, 2) + math.pow(x2-x1, 2))
return d
def find_corners(self, sl=100):
self.find_limits()
def lineresolve(x1, x2, y1, y2, targ):
m = ((y2 - y1) / (x2 - x1))
b = y1 - m * x1
return(m * targ + b)
slices = int(sl)
num_points = len(self.downhole_pos)
dh_pos = self.downhole_pos
dh_lod = self.downhole_load
delta_p = (self.downhole_max_position[0] - self.downhole_min_position[0]) / float(slices)
position_targets = []
for i in range(0, slices):
position_targets.append(self.downhole_min_position[0] + i * delta_p)
self.top_slices = []
last_pos_index = 0
for i in range(0, slices):
targ = position_targets[i]
for j in range(last_pos_index, num_points - 1):
if (dh_pos[j] <= targ and dh_pos[j+1] > targ):
found_i = j
next_i = j+1
fake_load = lineresolve(dh_pos[found_i], dh_pos[next_i], dh_lod[found_i], dh_lod[next_i], targ)
self.top_slices.append((targ, fake_load))
last_pos_index = found_i
break
self.bot_slices = []
last_pos_index = 0
for i in range(0, slices):
targ = position_targets[i]
for j in range(0, num_points - 1):
if (dh_pos[j] > targ and dh_pos[j+1] <= targ):
found_i = j
next_i = j+1
fake_load = lineresolve(dh_pos[found_i], dh_pos[next_i], dh_lod[found_i], dh_lod[next_i], targ)
self.bot_slices.append((targ, fake_load))
break
top_d = []
bot_d = []
# Here's where we get the distance from each point to the line
for i in range(1, slices):
try:
top_d.append(self.distance_to_line(self.top_slices[i][0], self.top_slices[i][1]))
except Exception as e:
print e
print("Error - top_d, index: {0}".format(i))
try:
bot_d.append(self.distance_to_line(self.bot_slices[i][0], self.bot_slices[i][1]))
except Exception:
print("Error - bot_d, index: {0}".format(i))
top_cor_i = top_d.index(max(top_d))
bot_cor_i = bot_d.index(max(bot_d))
self.corner_top_left = self.top_slices[top_cor_i]
self.corner_fillage = self.bot_slices[bot_cor_i]
self.corner_top_right = self.downhole_max_position
self.corner_bottom_left = self.downhole_min_position
def print_corners(self):
if self.corner_fillage:
self.find_corners(100)
print("Bottom Left:", self.corner_bottom_left)
print("Top Left:", self.corner_top_left)
print("Top Right:", self.corner_top_right)
print("Fill Point:", self.corner_fillage)
def calc_fillage(self):
if not ('self.corner_fillage' in locals()):
self.find_corners(100)
self.downhole_gross_stroke = self.downhole_max_position[0] - self.downhole_min_position[0]
self.tubing_movement = 12 * (tapers.rod_depth_total - self.well_setup['anchor_depth'])*self.downhole_fluid_load / (30500000 * self.tapers.tubing_cross_sectional_area)
self.downhole_adjusted_gross_stroke = self.downhole_gross_stroke - self.tubing_movement
self.downhole_net_stroke = self.corner_fillage[0] - self.corner_bottom_left[0]
# self.fillage_estimated = ((self.corner_fillage[0] - self.corner_bottom_left[0])/(self.corner_full_fillage_point[0] - self.corner_bottom_left[0])) * 100
self.fillage_calculated = ((self.downhole_net_stroke + self.tubing_movement) / self.downhole_gross_stroke) * 100
def listSurface(self):
for i in range(0, len(self.surface_pos)):
print([self.surface_pos[i], self.surface_load[i]])
def listDownhole(self):
for i in range(0, len(self.downhole_pos)):
print([self.downhole_pos[i], self.downhole_load[i]])
def calc_hp_and_analyze(self):
self.polished_rod_horsepower = 0
self.pump_horsepower = 0
if not self.surface_stroke_length:
self.find_limits()
if not self.downhole_net_stroke:
self.calc_fillage()
dx_surface = self.surface_stroke_length / (self.riemann_slices + 1)
dx_downhole = self.downhole_net_stroke / (self.riemann_slices + 1)
for i in range(1, self.riemann_slices):
target_surface = dx_surface * i + self.surface_min_position[0]
target_downhole = dx_downhole*i + self.downhole_min_position[0]
slice_surface = self.__find_incremental_load(target_surface, self.surface_pos, self.surface_load)
slice_downhole = self.__find_incremental_load(target_downhole, self.downhole_pos, self.downhole_load)
top_slices.push(slice_downhole[1])
bottom_slices.push(slice_downhole[2])
self.polished_rod_horsepower += (dx_surface / 12) * slice_surface[0] * self.strokes_per_minute / 33000
self.pump_horsepower += (dx_downhole / 12) * slice_downhole[0] * self.strokes_per_minute / 33000
# CARD ANALYSIS / $$$ MAKER
def prepare_points(analysis_slices):
if (analysis_slices > (self.riemann_slices * 0.50)):
return 911
top_left_average = 0
top_right_average = 0
top_mid_average = 0
bot_left_average = 0
bot_right_average = 0
bot_mid_average = 0
pct_slices = (analysis_slices / self.riemann_slices) * 100
first_x_pct_end = math.floor(self.riemann_slices*pct_slices)
x_pct_ct = math.floor(self.riemann_slices*pct_slices)
last_x_pct_start = self.riemann_slices - math.floor(self.riemann_slices * pct_slices)
num_btw_slices = self.riemann_slices - (3 * x_pct_ct) # number of slices between the measurements used for top/bottom average and the mid point average
# Find average of leftmost Points
for la_i in range(0, first_x_pct_end):
top_left_average += self.top_slices[la_i] * (1/x_pct_ct)
bot_left_average += self.bottom_slices[la_i] * (1/x_pct_ct)
# Find average of rightmost points
for ra_i in range(last_x_pct_start, self.riemann_slices):
top_right_average += self.top_slices[ra_i] * (1/x_pct_ct)
bot_right_average += self.bottom_slices[ra_i] * (1/x_pct_ct)
# Find average of middle points
for ma_i in range(math.floor((self.riemann_slices/2) - self.riemann_slices * (pct_corners / 2)), math.floor((self.riemann_slices / 2) + self.riemann_slices * (pct_corners / 2))):
top_mid_average += self.top_slices[ma_i] * (1/x_pct_ct)
bot_mid_average += self.bottom_slices[ma_i] * (1/x_pct_ct)
def calc_fluid_level(self):
if not ('self.downhole_fluid_load' in locals()):
self.find_limits()
self.pump_intake_pressure = self.tapers.params['fluid_gradient'] * self.tapers.rod_depth_total - (self.downhole_fluid_load / self.well_setup['pump_area'])
self.fluid_above_pump = self.pump_intake_pressure / self.tapers.params['fluid_gradient']
def write_csv(self):
if not ('self.fluid_above_pump' in locals()):
self.calc_fluid_level()
if not ('self.polished_rod_horsepower' in locals()):
self.calc_hp_and_analyze(100)
if not ('self.fillage_calculated' in locals()):
self.calc_fillage(25, 25)
csvData = {}
csvData['card_id'] = self.card_id
csvData['num_tapers'] = self.tapers.params['num_tapers']
csvData['num_points'] = len(self.surface_pos)
csvData['card_type'] = self.card_type
csvData['_year'] = self.date_time.year
csvData['_month'] = self.date_time.month
csvData['_day'] = self.date_time.day
csvData['_hour'] = self.date_time.hour
csvData['_minute'] = self.date_time.minute
csvData['_second'] = self.date_time.second
csvData['well_name'] = self.well_setup['well_name']
csvData['tubing_head_pressure'] = self.tapers.params['tubing_head_pressure']
csvData['fluid_gradient'] = self.tapers.params['fluid_gradient']
csvData['stuffing_box_friction'] = self.tapers.params['stuffing_box_friction']
csvData['dt'] = self.tapers.dt
csvData['downhole_max_load'] = self.downhole_max_load[1]
csvData['downhole_min_load'] = self.downhole_min_load[1]
csvData['downhole_max_position'] = self.downhole_max_position[0]
csvData['downhole_min_position'] = self.downhole_min_position[0]
csvData['downhole_gross_stroke'] = self.downhole_gross_stroke
csvData['downhole_adjusted_gross_stroke'] = self.downhole_adjusted_gross_stroke
csvData['downhole_net_stroke'] = self.downhole_net_stroke
csvData['downhole_fluid_load'] = self.downhole_fluid_load
csvData['surface_max_load'] = self.surface_max_load[1]
csvData['surface_min_load'] = self.surface_min_load[1]
csvData['surface_max_position'] = self.surface_max_position[0]
csvData['surface_min_position'] = self.surface_min_position[0]
csvData['tubing_movement'] = self.tubing_movement
csvData['surface_stroke_length'] = self.surface_stroke_length
csvData['fillage_percent'] = self.fillage_calculated
csvData['polished_rod_horsepower'] = self.polished_rod_horsepower
csvData['pump_horsepower'] = self.pump_horsepower
csvData['strokes_per_minute'] = self.strokes_per_minute
csvData['fluid_above_pump'] = self.fluid_above_pump
file_date = str(self.date_time.year) + str(self.date_time.month) + str(self.date_time.day)
file_time = str(self.date_time.hour) + str(self.date_time.minute) + str(self.date_time.second)
file_fillage = str(round(self.fillage_calculated, 3))
filename = file_date + '_' + file_time + '_' + str(self.card_id) + '_' + self.card_type + '_' + str(self.fillage_calculated).replace(".", "-") + ".csv"
with open(filename, 'wt', newline='') as card_file:
writer = csv.writer(card_file)
for data_point in csvData:
writer.writerow([data_point, csvData[data_point]])
writer.writerow(["s_pos", "s_load"])
for i in range(0, len(self.surface_pos)):
writer.writerow([self.surface_pos[i], self.surface_load[i]])
writer.writerow(["d_pos", "d_load"])
for j in range(0, len(self.downhole_pos)):
writer.writerow([self.downhole_pos[j], self.downhole_load[j]])
def plot(self):
fig = plt.figure(figsize=(12, 9))
fig.canvas.set_window_title('Well Load & Position Cards')
ax1 = fig.add_subplot(2, 1, 1)
ax2 = fig.add_subplot(2, 1, 2)
ax1.set_title("Surface Card")
ax2.set_title("Downhole Card")
ax1.set_xlabel('Position')
ax2.set_xlabel('Position')
ax1.set_ylabel('Load')
ax2.set_ylabel('Load')
ax1.fill(self.surface_pos, self.surface_load, 'g')
ax2.fill(self.downhole_pos, self.downhole_load, 'b')
fig.subplots_adjust(hspace=.4)
ax1.grid(True)
ax2.grid(True)
# plt.ion()
plt.show()
class Taper:
def __init__(self, params):
self.params = params
self.buoyant_force_total = 0.0
self.rod_weight_in_fluid_total = 0.0
self.rod_weight_in_air_total = 0.0
self.weight_data_total = 0.0
self.rod_depth_total = 0.0
self.annular_force_data_total = 0.0
self.a = []
self.area = []
self.pressure = [self.params['tubing_head_pressure']]
self.buoyant_force = []
self.stretch = []
self.weight_data = []
self.annular_force_data = []
self.force = []
self.alpha = []
self.x_over_a = []
self.factor_array = []
self.lag_index_array = []
self.center_point = []
self.sum_center_point = []
self.length_required = []
self.dt = params['dt']
self.rod_depth = []
self.rod_weight_in_air = []
self.rod_weight_in_fluid = []
for x in range(0, self.params['num_tapers'] + 2):
self.area.append(0.0)
self.pressure.append(0.0)
self.buoyant_force.append(0.0)
self.rod_weight_in_air.append(0.0)
self.rod_depth.append(0.0)
self.rod_weight_in_fluid.append(0.0)
self.weight_data.append(0.0)
self.annular_force_data.append(0.0)
self.a.append(0.0)
self.stretch.append(0.0)
self.force.append(0.0)
self.alpha.append(0.0)
self.x_over_a.append(0.0)
self.factor_array.append(0.0)
self.lag_index_array.append(0.0)
self.center_point.append(0.0)
self.sum_center_point.append(0.0)
self.length_required.append(0.0)
for area_i in range(1, self.params['num_tapers']+1):
self.area[area_i] = (math.pi / 4.0) * (self.params['rod_diameter_data'][area_i] ** 2.0)
for i in range(1, self.params['num_tapers']+1):
self.a[i] = 1000.0 * (32.2 * self.params['rod_youngs_modulus_data'][i] * self.area[i] / self.params['rod_weight_data'][i])**(0.5)
self.rod_depth[i] = self.rod_depth[i-1] + self.params['rod_length_data'][i]
self.pressure[i] = self.pressure[i-1] + self.params['fluid_gradient'] * self.params['rod_length_data'][i]
self.buoyant_force[i] = self.pressure[i] * (self.area[i+1] - self.area[i])
self.rod_weight_in_air[i] = self.params['rod_weight_data'][i] * self.params['rod_length_data'][i]
self.rod_weight_in_fluid[i] = self.rod_weight_in_air[i] + self.buoyant_force[i]
for j in range(1, self.params['num_tapers']+1):
for k in range(j+1, self.params['num_tapers']+1):
self.weight_data[j] = self.weight_data[j] + self.params['rod_weight_data'][k] * self.params['rod_length_data'][k]
for l in range(j, self.params['num_tapers']):
self.annular_force_data[j] = self.annular_force_data[j] + self.pressure[l] * (self.area[l] - self.area[l+1])
self.force[j] = (-self.area[self.params['num_tapers']] * self.pressure[self.params['num_tapers']]) + self.weight_data[j] - self.annular_force_data[j]
self.alpha[j] = (self.force[j] + self.params['rod_weight_data'][j] * self.params['rod_length_data'][j]) / (self.params['rod_youngs_modulus_data'][j] * 10**6 * self.area[j])
self.stretch[j] = self.stretch[j-1] + self.alpha[j] * self.params['rod_length_data'][j] - (self.params['rod_weight_data'][j] * self.params['rod_length_data'][j]**2) / (2 * self.params['rod_youngs_modulus_data'][j] * 10**6 * self.area[j])
for m in range(1, self.params['num_tapers']+1):
self.x_over_a[m] = self.params['rod_length_data'][m] / self.a[m]
self.lag_index_array[m] = math.trunc(self.params['rod_length_data'][m] / (self.a[m] * self.dt))
self.factor_array[m] = (self.x_over_a[m] - self.lag_index_array[m] * self.dt) / self.dt
self.center_point[m] = self.lag_index_array[m] + 2
self.length_required[m] = 2 * (self.lag_index_array[m] + 1) + 1
self.sum_center_point[1] = self.center_point[1]
for n in range(2, self.params['num_tapers']):
self.sum_center_point[n] = self.sum_center_point[n-1] + self.center_point[n] - 1
for b in self.buoyant_force:
self.buoyant_force_total = self.buoyant_force_total + b
for r in self.rod_weight_in_air:
self.rod_weight_in_air_total = self.rod_weight_in_air_total + r
for r1 in self.rod_weight_in_fluid:
self.rod_weight_in_fluid_total = self.rod_weight_in_fluid_total + r1
for r2 in self.params['rod_length_data']:
self.rod_depth_total = self.rod_depth_total + r2
for a1 in self.annular_force_data:
self.annular_force_data_total = self.annular_force_data_total + a1
for w in self.weight_data:
self.weight_data_total = self.weight_data_total + w
self.tubing_cross_sectional_area = (math.pi / 4) * (self.params['tubing_od']**2 - self.params['tubing_id']**2)
def set_real_dt(self, dt):
self.dt = dt
for m in range(1, self.params['num_tapers']+1):
self.lag_index_array[m] = math.trunc(self.params['rod_length_data'][m] / (self.a[m] * self.dt))
self.factor_array[m] = (self.x_over_a[m] - self.lag_index_array[m] * self.dt) / self.dt
def printSetup(self):
print("------------ Well Params ---------------------")
print("Tubing Head pressure: ", self.params['tubing_head_pressure'])
print("Fluid Gradient: ", self.params['fluid_gradient'])
print("Stuffing Box Friction: ", self.params['stuffing_box_friction'])
print("Number of Tapers: ", self.params['num_tapers'])
print("Damping Factor: ", self.params['c'])
print("Rod Length Data: ", self.params['rod_length_data'])
print("Rod Diameter Data: ", self.params['rod_diameter_data'])
print("Rod Young's Modulus Data: ", self.params['rod_youngs_modulus_data'])
print("Rod Weight Data: ", self.params['rod_weight_data'])
print("dt: ", self.dt)
print("tubing_id:", self.params['tubing_id'])
print("tubing_od:", self.params['tubing_od'])
print("----------------------------------------------")
def printTaper(self):
print("------------ Taper Params --------------------")
print("area:", self.area)
print("Speed of Sound in Rod(a):", self.a)
print("Rod Depth:", self.rod_depth)
print("pressure:", self.pressure)
print("Buoyant force:", self.buoyant_force)
print("Rod Weight in Air:", self.rod_weight_in_air)
print("Weight Data:", self.weight_data)
print("Annulus pressure Data:", self.annular_force_data)
print("force Data:", self.force)
print("alpha Data:", self.alpha)
print("stretch Data:", self.stretch)
print("X over A:", self.x_over_a)
print("Factor Array:", self.factor_array)
print("Lag Index Array:", self.lag_index_array)
print("center_point:", self.center_point)
print("sum_center_point:", self.sum_center_point)
print("Length Required:", self.length_required)
print("TubingCSA:", self.tubing_cross_sectional_area)
print("------------ Taper Totals --------------------")
print("buoyant_force_total:", self.buoyant_force_total)
print("rod_weight_in_air_total:", self.rod_weight_in_air_total)
print("rod_weight_in_fluid_total:", self.rod_weight_in_fluid_total)
print("rod_depth_total:", self.rod_depth_total)
print("annular_force_data_total:", self.annular_force_data_total)
print("weight_data_total:", self.weight_data_total)
print("----------------------------------------------")
def position_function(p, tap): # CHECKED LOGIC ON 1/21/2015
global top_load_array
global top_pos_array
global load_before
global load_after
global load_before_3
global load_after_3
load_before = 0.0
load_after = 0.0
load_before_3 = 0.0
load_after_3 = 0.0
dt = tap.dt
a1 = tap.a[p]
cd = tap.params['c'][p]
factor = tap.factor_array[p]
rod_length = tap.params['rod_length_data'][p]
lag_index = tap.lag_index_array[p]
Y1 = tap.params['rod_youngs_modulus_data'][p]
Y1 = Y1 * 10**6
A1 = tap.area[p]
center_of_array = tap.center_point[p]
# print("p:", p, "a1:", a1, "| cd:", cd, "| factor:", factor, "| rod_length:", rod_length, "| lag_index:", lag_index, "| Y1:", Y1, "| A1:", A1, "| center_of_array:", center_of_array)
i_before = center_of_array - lag_index
i_after = center_of_array + lag_index
# print("------")
pump_pos = 0.0
pump_pos = math.exp((cd * rod_length) / (2.0 * a1)) * (top_pos_array[p][i_after] + factor * (top_pos_array[p][i_after + 1] - top_pos_array[p][i_after]))
pump_pos = pump_pos + math.exp(-(cd * rod_length) / (2.0 * a1)) * (top_pos_array[p][i_before] + factor * (top_pos_array[p][i_before - 1] - top_pos_array[p][i_before]))
pump_pos = 0.5 * pump_pos
inside_integral = 0.0
q = 1
while(q < 2 * lag_index - 1):
inside_integral = inside_integral + dt * (1.0 / (Y1 * A1)) * (math.exp(-(cd * (lag_index - q) * dt) / 2.0) * top_load_array[p][i_before + q])
q += 1
inside_integral = inside_integral + (0.5) * dt * (1.0 / (Y1 * A1)) * (math.exp(-(cd * lag_index * dt) / 2.0) * top_load_array[p][i_before] + math.exp(- (cd * (-lag_index) * dt) / 2.0) * top_load_array[p][i_after])
load_before = math.exp(-(cd * lag_index * dt) / 2.0) * top_load_array[p][i_before] + factor * (math.exp(-(cd * (lag_index + 1.0) * dt) / 2.0) * top_load_array[p][i_before - 1] - math.exp(-(cd * (lag_index) * dt) / 2.0) * top_load_array[p][i_before])
load_after = math.exp(-(cd * (-lag_index) * dt) / 2.0) * top_load_array[p][i_after] + factor * (math.exp(-(cd * (-lag_index - 1.0) * dt) / 2.0) * top_load_array[p][i_after + 1] - math.exp(-(cd * (-lag_index) * dt) / 2.0) * top_load_array[p][i_after])
inside_integral = inside_integral + 0.5 * factor * dt * (1.0 / (Y1 * A1)) * (load_before + math.exp(-(cd * (lag_index) * dt) / 2.0) * top_load_array[p][i_before])
inside_integral = inside_integral + 0.5 * factor * dt * (1.0 / (Y1 * A1)) * (load_after + math.exp(-(cd * (-lag_index) * dt) / 2.0) * top_load_array[p][i_after])
inside_integral = (0.5) * a1 * inside_integral
pump_pos = pump_pos + inside_integral
inside_integral = 0.0
r = 1
while(r < 2 * lag_index - 1):
inside_integral = inside_integral + dt * (math.exp(-(cd * (lag_index - r) * dt) / 2) * (top_pos_array[p][i_before + r]))
r = r+1
inside_integral = inside_integral + (0.5) * dt * (math.exp(-(cd * lag_index * dt) / 2.0) * top_pos_array[p][i_before] + math.exp(-(cd * (-lag_index) * dt)/2.0) * top_pos_array[p][i_after])
load_before_3 = math.exp(-(cd * (lag_index) * dt) / 2.0) * top_pos_array[p][i_before] + factor * (math.exp(-(cd * (lag_index + 1) * dt) / 2.0) * top_pos_array[p][i_before - 1] - math.exp(-(cd * (lag_index) * dt) / 2.0) * top_pos_array[p][i_before])
load_after_3 = math.exp(-(cd * (-lag_index) * dt) / 2.0) * top_pos_array[p][i_after] + factor * (math.exp(-(cd * (-lag_index - 1.0) * dt) / 2.0) * top_pos_array[p][i_after + 1] - math.exp(-(cd * (-lag_index) * dt) / 2.0) * top_pos_array[p][i_after])
inside_integral = inside_integral + (0.5) * factor * dt * (load_before_3 + math.exp(-(cd * (lag_index) * dt) / 2.0) * top_pos_array[p][i_before])
inside_integral = inside_integral + (0.5) * factor * dt * (load_after_3 + math.exp(-(cd * (-lag_index) * dt) / 2.0) * top_pos_array[p][i_after])
inside_integral = -((cd * rod_length) / 4.0) * ((0.5) * (cd / (2.0 * a1))) * inside_integral
pump_pos = pump_pos + inside_integral
return(pump_pos)
def load_function(s, tap):
global top_load_array
global top_pos_array
global load_before
global load_after
global load_before_3
global load_after_3
dt = tap.dt
a1 = tap.a[s]
cd = tap.params['c'][s]
rod_length = tap.params['rod_length_data'][s]
lag_index = tap.lag_index_array[s]
Y1 = tap.params['rod_youngs_modulus_data'][s]
Y1 = Y1 * 10.0**6
A1 = tap.area[s]
center_of_array = tap.center_point[s]
i_before = center_of_array - lag_index
i_after = center_of_array + lag_index
pump_load = 0.0
pump_load = (0.5) * (a1 / (Y1*A1)) * (1.0 / a1) * (load_before + load_after)
pump_load = pump_load - ((cd * rod_length) / 4.0) * ((0.5) * (cd / (2.0 * a1))) * (1.0 / a1) * (load_before_3 + load_after_3)
first_part = 0.0
point_after = (top_pos_array[s][i_after+1] - top_pos_array[s][i_after - 1]) / (2.0 * dt)
point_before = (top_pos_array[s][i_before+1] - top_pos_array[s][i_before - 1]) / (2.0 * dt)
first_part = (math.exp((cd*rod_length)/(2.0*a1)) * point_after - math.exp(-(cd*rod_length)/(2*a1)) * point_before) / (2.0 * a1)
first_part = first_part + (cd * math.exp((cd*rod_length)/(2.0*a1))*top_pos_array[s][i_after] - cd * math.exp((-cd*rod_length)/(2*a1))*top_pos_array[s][i_before]) / (4.0 * a1)
pump_load = Y1 * A1 * (first_part + pump_load)
return(pump_load)
def calc(pos, load, t):
global pr_p
global pr_l
global pmp_p
global pmp_l
global top_pos_array
global top_load_array
global position_load_counter
global surface_pos_array
global surface_load_array
USE_SHIFT = False
surface_pos_array.append(pos)
surface_load_array.append(load)
load_mult = 1
tapers_allowed = 1
pr_l[0] = pr_l[1]
pmp_l[0] = pmp_l[1]
pr_p[0] = pr_p[1]
pmp_p[0] = pmp_p[1]
pr_p[1] = pos
pr_l[1] = load
for ii in range(1, t.length_required[1]+1):
top_pos_array[1][ii-1] = top_pos_array[1][ii]
top_load_array[1][ii-1] = top_load_array[1][ii]
top_pos_array[1][t.length_required[1]] = -(pr_p[1] / 12.0)
if(pr_p[1] > pr_p[0]):
top_load_array[1][t.length_required[1]] = load_mult * (pr_l[1] - t.rod_weight_in_fluid_total) - t.params['stuffing_box_friction']
elif (pr_p[1] < pr_p[0]):
top_load_array[1][t.length_required[1]] = load_mult * (pr_l[1] - t.rod_weight_in_fluid_total) + t.params['stuffing_box_friction']
else:
top_load_array[1][t.length_required[1]] = load_mult * (pr_l[1] - t.rod_weight_in_fluid_total)
j = 1
while j <= tapers_allowed:
count[j] = count[j] + 1
if (count[j] >= t.length_required[j]):
if((j+1) <= t.params['num_tapers']):
for ii in range(2, t.length_required[j+1]+1):
top_pos_array[j+1][ii-1] = top_pos_array[j+1][ii]
top_load_array[j+1][ii-1] = top_load_array[j+1][ii]
top_pos_array[j+1][t.length_required[j+1]] = position_function(j, t)
top_load_array[j+1][t.length_required[j+1]] = load_function(j, t)
else:
if USE_SHIFT:
pmp_p[1] = -12 * (position_function(j, t) + t.stretch[t.params['num_tapers']])
else:
pmp_p[1] = -12 * position_function(j, t)
pmp_l[1] = load_function(j, t) + t.force[t.params['num_tapers']]
pump_pos_array.append(pmp_p[1])
pump_load_array.append(pmp_l[1])
position_load_counter += 1
count[j] = count[j] - 1
tapers_allowed = tapers_allowed + 1
if(tapers_allowed > t.params['num_tapers']):
tapers_allowed = t.params['num_tapers']
j = j+1
return [[pr_p[1], pr_l[1]], [pmp_p[1], pmp_l[1]]]
tapers = Taper(well_setup)
if __name__ == '__main__':
def loop(iterations):
stroke_start_time = time.time()
point_times = [0, 0]
for point in range(0, len(surface)):
# print ("calc for", surface[point][0], surface[point][1] )
point_time_delta = point_times[1] - point_times[0]
# print("pt took:", point_time_delta)
point_times[0] = point_times[1]
point_times[1] = time.time()
current = calc(surface[point][0], surface[point][1], tapers)
print(current)
if ((point_time_delta > 0) and (point_time_delta < 2)):
tapers.set_real_dt(point_time_delta)
time.sleep(tapers.params['dt'])
stroke_end_time = time.time()
stroke_time_delta = stroke_end_time - stroke_start_time
pump_pos_array.append(pump_pos_array[0])
pump_load_array.append(pump_load_array[0])
surface_pos_array.append(surface_pos_array[0])
surface_load_array.append(surface_load_array[0])
last_card = Card(1, surface_pos_array, surface_load_array, pump_pos_array, pump_load_array, tapers, well_setup)
last_card.set_strokes_per_minute((1 / stroke_time_delta) * 60.0)
last_card.calc_fillage()
last_card.print_corners()
# last_card.calc_hp_and_analyze(100)
# print("polished_rod_horsepower:", last_card.polished_rod_horsepower)
# print("pump_horsepower:", last_card.pump_horsepower)
# print("strokes_per_minute:", last_card.strokes_per_minute)
iterations -= 1
if (iterations > 0):
loop(iterations)
if (iterations == 0):
# last_card.print_corners()
# last_card.write_csv()
last_card.plot()
loop(2)
# pprint(vars(last_card))

713
algorithm_velocity.py Normal file
View File

@@ -0,0 +1,713 @@
import math
import matplotlib as mpl
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from collections import deque
import datetime
import time
from pprint import pprint
import csv
### Create Surface & Load Files ###
import tkinter as tk
import tkinter.filedialog as fd
from time import sleep
root = tk.Tk()
root.withdraw()
surface = []
taper_setup = {}
taper_setup['tubing_head_pressure'] = 50
taper_setup['fluid_gradient'] = .45
taper_setup['stuffing_box_friction']= 100
taper_setup['c'] = [0, .08 , .08]
taper_setup['rod_length_data'] = [0, 10095, 300 ]
taper_setup['num_tapers'] = len(taper_setup['rod_length_data'])-1
taper_setup['rod_diameter_data'] = [0, .750 , 1.5 ]
taper_setup['rod_youngs_modulus_data'] = [0, 30.5, 30.5 ]
taper_setup['rod_weight_data'] = [0, 1.634 , 6]
taper_setup['dt'] = 0.0500
taper_setup['tubing_id'] = 1.995
taper_setup['tubing_od'] = 2.375
unit_config = {}
unit_config['anchor_depth'] = 8923.0
unit_config['well_name'] = "Python Demo Well"
unit_config['pump_diameter'] = 1.25
unit_config['pump_area'] = (unit_config['pump_diameter']**2) * math.pi
load_before = 0
load_after = 0
load_before_3 = 0
load_after_3 = 0
blank_array = [0]*100
top_pos_array = deque()
top_load_array = deque()
for i in range(0,10):
top_pos_array.append(blank_array[:])
top_load_array.append(blank_array[:])
pump_pos_array = []
pump_load_array = []
pr_l = [0,0]
pr_p = [0,0]
pmp_p = [0,0]
pmp_l = [0,0]
count = [0]* (taper_setup['num_tapers']+1)
position_load_counter = 0
surface_pos_array = []
surface_load_array = []
class Card:
def __init__(self, id, s_p_array, s_l_array, d_p_array, d_l_array, t, u_c):
self.card_id = id
self.date_time = datetime.datetime.now()
self.tapers = t
self.unit_config = u_c
self.surface_pos = s_p_array[:]
self.surface_load = s_l_array[:]
self.downhole_pos = d_p_array[:]
self.downhole_load = d_l_array[:]
self.downhole_fluid_load_adjustment = 223.907
print("downhole_fluid_load_adjustment not configured")
self.card_type = "NotConfigured"
print("card_type not configured")
def set_strokes_per_minute(self, strokes_per_minute):
self.strokes_per_minute = strokes_per_minute
def __find_nearest_point_to_load(self, direction, card_half ,target_load, pos_array, load_array):
left_ignore = min(pos_array) + (min(pos_array)+ max(pos_array))*(.75)
right_ignore = min(pos_array) + (min(pos_array)+ max(pos_array))*(.25)
if (direction=="up"):
for i in range(1, len(pos_array)):
if (card_half=="right" and pos_array[i] >= right_ignore):
if ((load_array[i] <= target_load) & (load_array[i-1] > target_load)):
return [pos_array[i], load_array[i]]
elif( card_half =="left" and pos_array[i] <= left_ignore):
if ((load_array[i] >= target_load) & (load_array[i-1] < target_load)):
return [pos_array[i], load_array[i]]
else:
for j in range(len(pos_array)-1, 1, -1):
if (card_half=="right" and pos_array[i] >= right_ignore):
if ((load_array[i] >= target_load) & (load_array[i-1] < target_load)):
return [pos_array[i], load_array[i]]
elif( card_half =="left" and pos_array[i] <= left_ignore):
if ((load_array[i] <= target_load) & (load_array[i-1] > target_load)):
return [pos_array[i], load_array[i]]
def __find_incremental_load(self, target_position, pos_array, load_array):
for i in range(1, len(pos_array)):
if ((pos_array[i] > target_position) and (pos_array[i-1] < target_position)):
up_point_greater = [pos_array[i], load_array[i]]
up_point_lesser = [pos_array[i-1], load_array[i-1]]
if ((pos_array[i] < target_position) and (pos_array[i-1] > target_position)):
down_point_greater = [pos_array[i], load_array[i]]
down_point_lesser = [pos_array[i-1], load_array[i-1]]
m_up = (up_point_greater[1] - up_point_lesser[1]) / (up_point_greater[0] - up_point_lesser[0])
b_up = up_point_greater[1] - (m_up * up_point_greater[0])
up_middle = (m_up*target_position) + b_up
m_down = (down_point_greater[1] - down_point_lesser[1]) / (down_point_greater[0] - down_point_lesser[0])
b_down = down_point_greater[1] - (m_down * down_point_greater[0])
down_middle = (m_down*target_position) + b_down
return up_middle - down_middle
def find_limits(self):
surface_max_position_position = max(self.surface_pos)
surface_max_position_load = self.surface_load[self.surface_pos.index(surface_max_position_position)]
self.surface_max_position = [surface_max_position_position, surface_max_position_load]
surface_min_position_position = min(self.surface_pos)
surface_min_position_load = self.surface_load[self.surface_pos.index(surface_min_position_position)]
self.surface_min_position = [surface_min_position_position, surface_min_position_load]
surface_max_load_load = max(self.surface_load)
surface_max_load_position = self.surface_pos[self.surface_load.index(surface_max_load_load)]
self.surface_max_load = [surface_max_load_position, surface_max_load_load]
surface_min_load_load = min(self.surface_load)
surface_min_load_position = self.surface_pos[self.surface_load.index(surface_min_load_load)]
self.surface_min_load = [surface_min_load_position, surface_min_load_load]
downhole_max_load_load = max(self.downhole_load)
downhole_max_load_position = self.downhole_pos[self.downhole_load.index(downhole_max_load_load)]
self.downhole_max_load = [downhole_max_load_position, downhole_max_load_load]
downhole_min_load_load = min(self.downhole_load)
downhole_min_load_position = self.downhole_pos[self.downhole_load.index(downhole_min_load_load)]
self.downhole_min_load = [downhole_min_load_position, downhole_min_load_load]
downhole_min_position_position = min(self.downhole_pos)
downhole_min_position_load = self.downhole_load[self.downhole_pos.index(downhole_min_position_position)]
self.downhole_min_position = [downhole_min_position_position, downhole_min_position_load]
downhole_max_position_position = max(self.downhole_pos)
downhole_max_position_load = self.downhole_load[self.downhole_pos.index(downhole_max_position_position)]
self.downhole_max_position = [downhole_max_position_position, downhole_max_position_load]
self.downhole_fluid_load = (self.downhole_max_load[1] - self.downhole_min_load[1]) - self.downhole_fluid_load_adjustment
self.surface_stroke_length = self.surface_max_position[0] - self.surface_min_position[0]
def print_limits(self):
if not ('self.surface_stroke_length' in locals()):
self.find_limits()
print("Surface Max Position:", self.surface_max_position)
print("Surface Min Position:", self.surface_min_position)
print("Surface Max Load:", self.surface_max_load)
print("Surface Min Load:", self.surface_min_load)
print("Downhole Max Load:", self.downhole_max_load)
print("Downhole Min Load:", self.downhole_min_load)
print("Downhole Min Position:", self.downhole_min_position)
print("Downhole Max Position:", self.downhole_max_position)
def find_corners(self, pct_top, pct_bottom):
if not ('self.surface_stroke_length' in locals()):
self.find_limits()
downhole_load_span = self.downhole_max_load[1] - self.downhole_min_load[1]
half_load_load = self.downhole_min_load[1] + downhole_load_span / 2
half_load = self.__find_nearest_point_to_load("up", "left", half_load_load , self.downhole_pos, self.downhole_load)
if(self.downhole_min_position[0] < half_load[0]):
self.corner_bottom_left = self.downhole_min_position
self.corner_top_left = self.__find_nearest_point_to_load("up", "left", self.downhole_max_load[1]-downhole_load_span*(pct_top/100), self.downhole_pos, self.downhole_load)
else:
self.corner_bottom_left = self.__find_nearest_point_to_load("up", "left", self.downhole_min_load[1]+downhole_load_span*(pct_bottom/100), self.downhole_pos, self.downhole_load)
self.corner_top_left = self.downhole_min_position
self.corner_top_right = self.downhole_max_position
self.corner_fillage = self.__find_nearest_point_to_load("up", "right", self.downhole_min_load[1]+downhole_load_span*(pct_bottom/100), self.downhole_pos, self.downhole_load)
self.corner_full_fillage_point = [self.corner_bottom_left[0]+ self.corner_top_right[0] - self.corner_top_left[0], self.corner_bottom_left[1]]
def print_corners(self):
if not ('self.corner_fillage' in locals()):
self.find_corners(25, 25)
print("Bottom Left:", self.corner_bottom_left)
print("Bottom Left:", self.corner_top_left)
print("Bottom Left:", self.corner_top_right)
print("Bottom Left:", self.corner_fillage)
print("Bottom Left:", self.corner_full_fillage_point)
def calc_fillage(self, pct_top, pct_bottom):
if not ('self.corner_fillage' in locals()):
self.find_corners(pct_top, pct_bottom)
self.downhole_gross_stroke = self.downhole_max_position[0] - self.downhole_min_position[0]
self.tubing_movement = 12 * (tapers.rod_depth_total - self.unit_config['anchor_depth'])*self.downhole_fluid_load / (30500000* self.tapers.tubing_cross_sectional_area)
self.downhole_adjusted_gross_stroke = self.downhole_gross_stroke - self.tubing_movement
self.downhole_net_stroke = self.corner_fillage[0] - self.corner_bottom_left[0]
self.fillage_estimated = ((self.corner_fillage[0] - self.corner_bottom_left[0])/(self.corner_full_fillage_point[0] - self.corner_bottom_left[0])) * 100
self.fillage_calculated = ((self.downhole_net_stroke + self.tubing_movement) / self.downhole_gross_stroke) * 100
def listSurface(self):
for i in range(0,len(self.surface_pos)):
print([self.surface_pos[i], self.surface_load[i]])
def listDownhole(self):
for i in range(0,len(self.downhole_pos)):
print([self.downhole_pos[i], self.downhole_load[i]])
def calc_hp(self, riemann_slices):
self.polished_rod_horsepower = 0
self.pump_horsepower = 0
downSlices = []
if not ('self.surface_stroke_length' in locals()):
self.find_limits()
if not ('self.downhole_net_stroke' in locals()):
self.calc_fillage(25,25)
dx_surface = self.surface_stroke_length / (riemann_slices + 1)
dx_downhole = self.downhole_net_stroke / (riemann_slices + 1)
for i in range(1, riemann_slices):
target_surface = dx_surface * i + self.surface_min_position[0]
target_downhole = dx_downhole*i + self.downhole_min_position[0]
slice_surface = self.__find_incremental_load(target_surface, self.surface_pos, self.surface_load)
slice_downhole = self.__find_incremental_load(target_downhole, self.downhole_pos, self.downhole_load)
self.polished_rod_horsepower += (dx_surface / 12) * slice_surface * self.strokes_per_minute / 33000
self.pump_horsepower += (dx_downhole / 12) * slice_downhole * self.strokes_per_minute / 33000
def calc_fluid_level(self):
if not ('self.downhole_fluid_load' in locals()):
self.find_limits()
self.pump_intake_pressure = self.tapers.params['fluid_gradient'] * self.tapers.rod_depth_total - (self.downhole_fluid_load / self.unit_config['pump_area'])
self.fluid_above_pump = self.pump_intake_pressure / self.tapers.params['fluid_gradient']
def write_csv(self):
if not ('self.fluid_above_pump' in locals()):
self.calc_fluid_level()
if not ('self.polished_rod_horsepower' in locals()):
self.calc_hp(100)
if not ('self.fillage_calculated' in locals()):
self.calc_fillage(25,25)
csvData = {}
csvData['card_id'] = self.card_id
csvData['num_tapers'] = self.tapers.params['num_tapers']
csvData['num_points'] = len(self.surface_pos)
csvData['card_type'] = self.card_type
csvData['_year'] = self.date_time.year
csvData['_month'] = self.date_time.month
csvData['_day'] = self.date_time.day
csvData['_hour'] = self.date_time.hour
csvData['_minute'] = self.date_time.minute
csvData['_second'] = self.date_time.second
csvData['well_name'] = self.unit_config['well_name']
csvData['tubing_head_pressure'] = self.tapers.params['tubing_head_pressure']
csvData['fluid_gradient'] = self.tapers.params['fluid_gradient']
csvData['stuffing_box_friction'] = self.tapers.params['stuffing_box_friction']
csvData['dt'] = self.tapers.dt
csvData['downhole_max_load'] = self.downhole_max_load[1]
csvData['downhole_min_load'] = self.downhole_min_load[1]
csvData['downhole_max_position'] = self.downhole_max_position[0]
csvData['downhole_min_position'] = self.downhole_min_position[0]
csvData['downhole_gross_stroke'] = self.downhole_gross_stroke
csvData['downhole_adjusted_gross_stroke'] = self.downhole_adjusted_gross_stroke
csvData['downhole_net_stroke'] = self.downhole_net_stroke
csvData['downhole_fluid_load'] = self.downhole_fluid_load
csvData['surface_max_load'] = self.surface_max_load[1]
csvData['surface_min_load'] = self.surface_min_load[1]
csvData['surface_max_position'] = self.surface_max_position[0]
csvData['surface_min_position'] = self.surface_min_position[0]
csvData['tubing_movement'] = self.tubing_movement
csvData['surface_stroke_length'] = self.surface_stroke_length
csvData['fillage_percent'] = self.fillage_calculated
csvData['polished_rod_horsepower'] = self.polished_rod_horsepower
csvData['pump_horsepower'] = self.pump_horsepower
csvData['strokes_per_minute'] = self.strokes_per_minute
csvData['fluid_above_pump'] = self.fluid_above_pump
file_date = str(self.date_time.year) + str(self.date_time.month) + str(self.date_time.day)
file_time = str(self.date_time.hour) + str(self.date_time.minute) + str(self.date_time.second)
file_fillage = str(round(self.fillage_calculated,3))
filename = file_date + '_' + file_time + '_' + str(self.card_id) + '_' + self.card_type + '_' + str(self.fillage_calculated).replace(".", "-") + ".csv"
with open(filename, 'wt', newline='') as card_file:
writer = csv.writer(card_file)
for data_point in csvData:
writer.writerow([data_point, csvData[data_point]])
writer.writerow(["s_pos", "s_load"])
for i in range(0, len(self.surface_pos)):
writer.writerow([self.surface_pos[i], self.surface_load[i]])
writer.writerow(["d_pos", "d_load"])
for j in range(0, len(self.downhole_pos)):
writer.writerow([self.downhole_pos[j], self.downhole_load[j]])
def plot(self):
fig = plt.figure(figsize=(12, 9))
fig.canvas.set_window_title('Well Load & Position Cards')
ax1 = fig.add_subplot(2,1,1)
ax2 = fig.add_subplot(2,1,2)
ax1.set_title("Surface Card")
ax2.set_title("Downhole Card")
ax1.set_xlabel('Position')
ax2.set_xlabel('Position')
ax1.set_ylabel('Load')
ax2.set_ylabel('Load')
ax1.fill(self.surface_pos, self.surface_load, 'g')
ax2.fill(self.downhole_pos, self.downhole_load, 'b')
leg1 = ax1.legend()
leg2 = ax2.legend()
fig.subplots_adjust(hspace=.4)
ax1.grid(True)
ax2.grid(True)
plt.ion()
plt.show()
class Taper:
def __init__(self,params):
self.params = params
self.buoyant_force_total = 0
self.rod_weight_in_fluid_total = 0
self.rod_weight_in_air_total = 0
self.weight_data_total = 0
self.rod_depth_total = 0
self.annular_force_data_total = 0
self.a = []
self.area = []
self.pressure = [self.params['tubing_head_pressure']]
self.buoyant_force = []
self.stretch = []
self.weight_data = []
self.annular_force_data = []
self.force = []
self.alpha = []
self.x_over_a = []
self.factor_array = []
self.lag_index_array = []
self.center_point = []
self.sum_center_point = []
self.length_required =[]
self.dt = params['dt']
self.rod_depth = []
self.rod_weight_in_air = []
self.rod_weight_in_fluid = []
for x in range(0, self.params['num_tapers'] + 2):
self.area.append(0)
self.pressure.append(0)
self.buoyant_force.append(0)
self.rod_weight_in_air.append(0)
self.rod_depth.append(0)
self.rod_weight_in_fluid.append(0)
self.weight_data.append(0)
self.annular_force_data.append(0)
self.a.append(0)
self.stretch.append(0)
self.force.append(0)
self.alpha.append(0)
self.x_over_a.append(0)
self.factor_array.append(0)
self.lag_index_array.append(0)
self.center_point.append(0)
self.sum_center_point.append(0)
self.length_required.append(0)
for area_i in range(1, self.params['num_tapers']+1):
self.area[area_i] = (math.pi / 4) * (self.params['rod_diameter_data'][area_i] ** 2)
for i in range(1, self.params['num_tapers']+1):
self.a[i] = 1000 * (32.2 * self.params['rod_youngs_modulus_data'][i] * self.area[i] / self.params['rod_weight_data'][i])**(0.5)
self.rod_depth[i] = self.rod_depth[i-1] + self.params['rod_length_data'][i]
self.pressure[i] = self.pressure[i-1] + self.params['fluid_gradient'] * self.params['rod_length_data'][i]
self.buoyant_force[i] = self.pressure[i] * (self.area[i+1] - self.area[i])
self.rod_weight_in_air[i] = self.params['rod_weight_data'][i] * self.params['rod_length_data'][i]
self.rod_weight_in_fluid[i] = self.rod_weight_in_air[i] + self.buoyant_force[i]
for j in range(1, self.params['num_tapers']+1):
for k in range(j+1, self.params['num_tapers']+1):
self.weight_data[j] = self.weight_data[j] + self.params['rod_weight_data'][k] * self.params['rod_length_data'][k]
for l in range(j, self.params['num_tapers']):
self.annular_force_data[j] = self.annular_force_data[j] + self.pressure[l] * (self.area[l] - self.area[l+1])
self.force[j] = (-self.area[self.params['num_tapers']] * self.pressure[self.params['num_tapers']]) + self.weight_data[j] - self.annular_force_data[j]
self.alpha[j] = (self.force[j] + self.params['rod_weight_data'][j] * self.params['rod_length_data'][j]) / (self.params['rod_youngs_modulus_data'][j] * 10**6 * self.area[j])
self.stretch[j] = self.stretch[j-1] + self.alpha[j] * self.params['rod_length_data'][j] - (self.params['rod_weight_data'][j] * self.params['rod_length_data'][j]**2) / (2 * self.params['rod_youngs_modulus_data'][j] * 10**6 * self.area[j])
for m in range(1, self.params['num_tapers']+1):
self.x_over_a[m] = self.params['rod_length_data'][m] / self.a[m]
self.lag_index_array[m] = math.trunc(self.params['rod_length_data'][m] / (self.a[m] * self.dt))
self.factor_array[m] = (self.x_over_a[m] - self.lag_index_array[m] * self.dt) / self.dt
self.center_point[m] = self.lag_index_array[m] + 2
self.length_required[m] = 2 * (self.lag_index_array[m] + 1) + 1
self.sum_center_point[1] = self.center_point[1]
for n in range(2, self.params['num_tapers']):
self.sum_center_point[n] = self.sum_center_point[n-1] + self.center_point[n] - 1
for b in self.buoyant_force:
self.buoyant_force_total = self.buoyant_force_total + b
for r in self.rod_weight_in_air:
self.rod_weight_in_air_total = self.rod_weight_in_air_total + r
for r1 in self.rod_weight_in_fluid:
self.rod_weight_in_fluid_total = self.rod_weight_in_fluid_total + r1
for r2 in self.params['rod_length_data']:
self.rod_depth_total = self.rod_depth_total + r2
for a1 in self.annular_force_data:
self.annular_force_data_total = self.annular_force_data_total + a1
for w in self.weight_data:
self.weight_data_total = self.weight_data_total + w
self.tubing_cross_sectional_area = (math.pi / 4) * (self.params['tubing_od']**2 - self.params['tubing_id']**2)
def set_real_dt(self, dt):
self.dt = dt
for m in range(1, self.params['num_tapers']+1):
self.lag_index_array[m] = math.trunc(self.params['rod_length_data'][m] / (self.a[m] * self.dt))
self.factor_array[m] = (self.x_over_a[m] - self.lag_index_array[m] * self.dt) / self.dt
def printSetup(self):
print("------------ Well Params ---------------------")
print("Tubing Head pressure: ", self.params['tubing_head_pressure'])
print("Fluid Gradient: ", self.params['fluid_gradient'])
print("Stuffing Box Friction: ", self.params['stuffing_box_friction'])
print("Number of Tapers: ", self.params['num_tapers'])
print("Damping Factor: " , self.params['c'] )
print("Rod Length Data: " , self.params['rod_length_data'])
print("Rod Diameter Data: ", self.params['rod_diameter_data'])
print("Rod Young's Modulus Data: ", self.params['rod_youngs_modulus_data'])
print("Rod Weight Data: ", self.params['rod_weight_data'])
print("dt: ", self.dt)
print("tubing_id:", self.params['tubing_id'])
print("tubing_od:", self.params['tubing_od'])
print("----------------------------------------------")
def printTaper(self):
print("------------ Taper Params --------------------")
print("area:", self.area)
print("Speed of Sound in Rod(a):", self.a)
print("Rod Depth:", self.rod_depth)
print("pressure:", self.pressure)
print("Buoyant force:", self.buoyant_force)
print("Rod Weight in Air:", self.rod_weight_in_air)
print("Weight Data:", self.weight_data)
print("Annulus pressure Data:", self.annular_force_data)
print("force Data:", self.force)
print("alpha Data:", self.alpha)
print("stretch Data:", self.stretch)
print("X over A:", self.x_over_a)
print("Factor Array:", self.factor_array)
print("Lag Index Array:", self.lag_index_array)
print("center_point:", self.center_point)
print("sum_center_point:", self.sum_center_point)
print("Length Required:", self.length_required)
print("TubingCSA:", self.tubing_cross_sectional_area)
print("------------ Taper Totals --------------------")
print("buoyant_force_total:", self.buoyant_force_total)
print("rod_weight_in_air_total:", self.rod_weight_in_air_total)
print("rod_weight_in_fluid_total:", self.rod_weight_in_fluid_total)
print("rod_depth_total:", self.rod_depth_total)
print("annular_force_data_total:", self.annular_force_data_total)
print("weight_data_total:", self.weight_data_total)
print("----------------------------------------------")
def position_function(p,tap): #CHECKED LOGIC ON 1/21/2015
global top_load_array
global top_pos_array
global load_before
global load_after
global load_before_3
global load_after_3
load_before = 0
load_after = 0
load_before_3 = 0
load_after_3 = 0
dt = tap.dt
a1= tap.a[p]
cd = tap.params['c'][p]
factor = tap.factor_array[p]
rod_length = tap.params['rod_length_data'][p]
lag_index = tap.lag_index_array[p]
Y1 = tap.params['rod_youngs_modulus_data'][p]
Y1 = Y1 * 10**6
A1 = tap.area[p]
center_of_array = tap.center_point[p]
#print("p:", p, "a1:", a1, "| cd:", cd, "| factor:", factor, "| rod_length:", rod_length, "| lag_index:", lag_index, "| Y1:", Y1, "| A1:", A1, "| center_of_array:", center_of_array)
i_before = center_of_array - lag_index
i_after = center_of_array + lag_index
#print("------")
pump_pos = 0
pump_pos = math.exp((cd * rod_length) / (2 * a1)) * (top_pos_array[p][i_after] + factor * (top_pos_array[p][i_after + 1] - top_pos_array[p][i_after]))
pump_pos = pump_pos + math.exp(-(cd * rod_length) / (2 * a1)) * (top_pos_array[p][i_before] + factor * (top_pos_array[p][i_before - 1] - top_pos_array[p][i_before]))
pump_pos = 0.5 * pump_pos
inside_integral = 0
q = 1
while(q < 2* lag_index - 1):
inside_integral = inside_integral + dt * (1 / (Y1 * A1)) * (math.exp(-(cd * (lag_index - q ) * dt) / 2 ) * top_load_array[p][i_before +q])
q+=1
inside_integral = inside_integral + (1/2) * dt * (1 / (Y1 * A1)) * (math.exp(-(cd *lag_index * dt)/ 2) * top_load_array[p][i_before] + math.exp(- (cd* (-lag_index ) * dt) / 2) * top_load_array[p][i_after])
load_before = math.exp(-(cd * lag_index * dt) / 2) * top_load_array[p][i_before] + factor * (math.exp(-(cd * (lag_index + 1) * dt) / 2) * top_load_array[p][i_before - 1] - math.exp(-(cd* (lag_index) * dt ) / 2 ) * top_load_array[p][i_before])
load_after = math.exp(-(cd * (-lag_index) * dt) / 2) * top_load_array[p][i_after] + factor * (math.exp(-(cd * (-lag_index - 1) * dt) / 2) * top_load_array[p][i_after + 1] - math.exp(-(cd* (-lag_index) * dt ) / 2 ) * top_load_array[p][i_after])
inside_integral = inside_integral + 0.5 * factor * dt * (1 / (Y1 * A1)) * (load_before + math.exp(-(cd * (lag_index) * dt ) / 2) * top_load_array[p][i_before])
inside_integral = inside_integral + 0.5 * factor * dt * (1 / (Y1 * A1)) * (load_after + math.exp(-(cd * (-lag_index) * dt ) / 2) * top_load_array[p][i_after])
inside_integral = (1/2) * a1 * inside_integral
pump_pos = pump_pos + inside_integral
inside_integral = 0
r = 1
while(r < 2 * lag_index - 1):
inside_integral = inside_integral + dt * (math.exp(-(cd *(lag_index - r) * dt)/2) * (top_pos_array[p][i_before + r]))
r = r+1
inside_integral = inside_integral + (1/2) * dt * (math.exp(-(cd * lag_index * dt) / 2) * top_pos_array[p][i_before] + math.exp(-(cd * (-lag_index) * dt)/2) * top_pos_array[p][i_after])
load_before_3 = math.exp(-(cd * (lag_index) *dt) / 2) * top_pos_array[p][i_before] + factor * (math.exp(-(cd * (lag_index + 1) *dt) / 2) * top_pos_array[p][i_before - 1] - math.exp(-(cd * (lag_index) * dt)/2) * top_pos_array[p][i_before])
load_after_3 = math.exp(-(cd * (-lag_index) *dt) / 2) * top_pos_array[p][i_after] + factor * (math.exp(-(cd * (-lag_index - 1) *dt) / 2) * top_pos_array[p][i_after + 1] - math.exp(-(cd * (-lag_index) * dt)/2) * top_pos_array[p][i_after])
inside_integral = inside_integral + (1/2) * factor * dt * (load_before_3 + math.exp(-(cd * (lag_index) * dt)/2) * top_pos_array[p][i_before])
inside_integral = inside_integral + (1/2) * factor * dt * (load_after_3 + math.exp(-(cd * (-lag_index) * dt)/2) * top_pos_array[p][i_after])
inside_integral = -((cd * rod_length) / 4 ) * ((1/2) * (cd / (2*a1))) * inside_integral
pump_pos = pump_pos + inside_integral
return(pump_pos)
def load_function(s, tap):
global top_load_array
global top_pos_array
global load_before
global load_after
global load_before_3
global load_after_3
dt = tap.dt
a1= tap.a[s]
cd = tap.params['c'][s]
factor = tap.factor_array[s]
rod_length = tap.params['rod_length_data'][s]
lag_index = tap.lag_index_array[s]
Y1 = tap.params['rod_youngs_modulus_data'][s]
Y1 = Y1 * 10**6
A1 = tap.area[s]
center_of_array = tap.center_point[s]
i_before = center_of_array - lag_index
i_after = center_of_array + lag_index
pump_load = 0
pump_load = (1/2) * (a1 / (Y1*A1)) * (1 / a1) * (load_before + load_after)
temp_result = Y1 * A1 * pump_load
pump_load = pump_load -((cd * rod_length) / 4 ) * ((1/2) * (cd / (2*a1))) * (1/a1) * (load_before_3 + load_after_3)
first_part = 0
point_after = (top_pos_array[s][i_after+1] - top_pos_array[s][i_after -1]) / (2 * dt)
point_before = (top_pos_array[s][i_before+1] - top_pos_array[s][i_before -1]) / (2 * dt)
first_part = (math.exp((cd*rod_length)/(2*a1)) * point_after - math.exp(-(cd*rod_length)/(2*a1)) * point_before) / (2 *a1)
first_part = first_part +(cd * math.exp((cd*rod_length)/(2*a1))*top_pos_array[s][i_after] - cd * math.exp((-cd*rod_length)/(2*a1))*top_pos_array[s][i_before]) / (4 * a1)
pump_load = Y1 * A1 * (first_part + pump_load)
return(pump_load)
def calc(pos, load, t):
global pr_p
global pr_l
global pmp_p
global pmp_l
global top_pos_array
global top_load_array
global position_load_counter
global surface_pos_array
global surface_load_array
USE_SHIFT = False
surface_pos_array.append(pos)
surface_load_array.append(load)
load_mult = 1
tapers_allowed = 1
pr_l[0] = pr_l[1]
pmp_l[0] = pmp_l[1]
pr_p[0] = pr_p[1]
pmp_p[0] = pmp_p[1]
pr_p[1] = pos
pr_l[1] = load
for ii in range(1, t.length_required[1]+1):
top_pos_array[1][ii-1] = top_pos_array[1][ii]
top_load_array[1][ii-1] = top_load_array[1][ii]
top_pos_array[1][t.length_required[1]] = -(pr_p[1] / 12)
if(pr_p[1] > pr_p[0]):
top_load_array[1][t.length_required[1]] = load_mult * (pr_l[1] - t.rod_weight_in_fluid_total) - t.params['stuffing_box_friction']
elif (pr_p[1] < pr_p[0]):
top_load_array[1][t.length_required[1]] = load_mult * (pr_l[1] - t.rod_weight_in_fluid_total) + t.params['stuffing_box_friction']
else:
top_load_array[1][t.length_required[1]] = load_mult * (pr_l[1] - t.rod_weight_in_fluid_total)
j=1
while j <= tapers_allowed:
count[j] = count[j] + 1
if (count[j] >= t.length_required[j]):
if((j+1) <= t.params['num_tapers']):
for ii in range(2, t.length_required[j+1]+1):
top_pos_array[j+1][ii-1] = top_pos_array[j+1][ii]
top_load_array[j+1][ii-1] = top_load_array[j+1][ii]
top_pos_array[j+1][t.length_required[j+1]] = position_function(j,t)
top_load_array[j+1][t.length_required[j+1]] = load_function(j,t)
else:
if USE_SHIFT:
pmp_p[1] = -12 * (position_function(j,t) + t.stretch[t.params['num_tapers']])
else:
pmp_p[1] = -12 * position_function(j,t)
pmp_l[1] = load_function(j,t) + t.force[t.params['num_tapers']]
pump_pos_array.append(pmp_p[1])
pump_load_array.append(pmp_l[1])
position_load_counter += 1
count[j] = count[j] - 1
tapers_allowed = tapers_allowed + 1
if(tapers_allowed > t.params['num_tapers']):
tapers_allowed = t.params['num_tapers']
j = j+1
return [[pr_p[1], pr_l[1]], [pmp_p[1], pmp_l[1]]]
tapers = Taper(taper_setup)
if __name__ == '__main__':
file_path = fd.askopenfilename()
store_points = False
import csv
with open(file_path, 'r') as csvfile:
data_reader = csv.reader(csvfile)
for row in data_reader:
if (row[0]=="s_pos"):
store_points = False
if store_points:
surface.append([float(row[0]),float(row[1])])
if (row[0]=="d_pos"):
store_points = True
def loop(iterations):
stroke_start_time = time.time()
point_times = [0,0]
for point in range(0,len(surface)):
#print ("calc for", surface[point][0], surface[point][1] )
point_time_delta = point_times[1] - point_times[0]
#print("pt took:", point_time_delta)
point_times[0] = point_times[1]
point_times[1] = time.time()
current = calc(surface[point][0], surface[point][1], tapers)
if ((point_time_delta > 0) and (point_time_delta < 2)):
tapers.set_real_dt(point_time_delta)
time.sleep(tapers.params['dt'])
stroke_end_time = time.time()
stroke_time_delta = stroke_end_time - stroke_start_time
pump_pos_array.append(pump_pos_array[0])
pump_load_array.append(pump_load_array[0])
surface_pos_array.append(surface_pos_array[0])
surface_load_array.append(surface_load_array[0])
last_card = Card(1,surface_pos_array, surface_load_array, pump_pos_array, pump_load_array, tapers, unit_config)
last_card.set_strokes_per_minute((1 / stroke_time_delta) * 60)
last_card.calc_fillage(25,25)
last_card.calc_hp(100)
print("polished_rod_horsepower:", last_card.polished_rod_horsepower)
print("pump_horsepower:", last_card.pump_horsepower)
print("strokes_per_minute:", last_card.strokes_per_minute)
iterations -= 1
if (iterations > 0):
loop(iterations)
if (iterations == 0):
last_card.print_corners()
last_card.write_csv()
last_card.plot()
loop(1)
#pprint(vars(last_card))

183
setupTapers.py Normal file
View File

@@ -0,0 +1,183 @@
import pickle
import math
import traceback
from os import listdir
from os.path import isfile, join
import Tkinter
wt_per_foot = {
'steel': {
# diameter: lbs/ft
2.000: 10.70,
1.750: 8.200,
1.650: 7.000,
1.500: 6.000,
1.375: 5.000,
1.250: 4.172,
1.125: 3.676,
1.000: 2.904,
0.875: 2.224,
0.750: 1.634,
0.625: 1.130,
0.500: 0.720
},
'fiberglass': {
# diameter: lbs/ft
1.250: 1.2879,
1.125: 1.0900,
1.000: 0.8188,
0.875: 0.6108,
0.750: 0.4840
}
}
youngs_modulus = {
'steel': 30.5,
'fiberglass': 7.2
}
configfile = ""
def get_setup():
global youngs_modulus, wt_per_ft, configfile
well_setup = {}
create_new = True
pickled_configs = filter(lambda x: x[-2:] == ".p", [f for f in listdir('wellconfigs') if isfile(join('wellconfigs', f))])
if len(pickled_configs) > 0:
pickled_configs.append("...New file")
master = Tkinter.Tk()
var = Tkinter.StringVar(master)
var.set(pickled_configs[0]) # initial value
w = apply(Tkinter.OptionMenu, (master, var) + tuple(pickled_configs))
w.pack()
def ok():
global configfile
configfile = var.get()
master.quit()
master.destroy()
button = Tkinter.Button(master, text="OK", command=ok)
button.pack()
Tkinter.mainloop()
fpath = 'wellconfigs/' + configfile
print(fpath)
if isfile(fpath):
with open(fpath, 'rb') as well_config_file:
well_setup = pickle.load(well_config_file)
reuse = str(raw_input("Do you want to use the last settings for {}? (y/n): ".format(well_setup['well_name']))).lower()
create_new = (reuse == 'n')
try:
if create_new:
well_setup = {}
well_setup['c'] = [0.0]
well_setup['rod_length_data'] = [0.0]
well_setup['rod_diameter_data'] = [0.0]
well_setup['rod_material'] = ['']
well_setup['rod_youngs_modulus_data'] = [0.0]
well_setup['rod_weight_data'] = [0.0]
ask_num_tapers = int(raw_input("How many tapers to configure (1-10): "))
if (ask_num_tapers > 0) and (ask_num_tapers <= 10):
well_setup['num_tapers'] = ask_num_tapers
for i in range(1, ask_num_tapers + 1):
print("================")
print("== TAPER {} ==".format(i))
print("================")
ask_length = float(raw_input("Enter Taper Length in feet: "))
if ask_length > 0.0:
well_setup['rod_length_data'].append(ask_length)
else:
raise Exception("Invalid length {} for taper {}".format(ask_length, i))
ask_diameter = float(raw_input("Enter Rod Diameter in inches: "))
if ask_diameter > 0.0:
well_setup['rod_diameter_data'].append(ask_diameter)
else:
raise Exception("Invalid diameter {} for taper {}".format(ask_diameter, i))
ask_material = str(raw_input("Enter material type (steel or fiberglass): ")).lower()
if (ask_material == 'fiberglass') or (ask_material == 'steel'):
well_setup['rod_material'].append(ask_material)
else:
raise Exception("Invalid material {} for taper {}".format(ask_material, i))
ask_c = float(raw_input("Enter Damping Factor(0.0 - 1.0): "))
if (ask_c >= 0.0) and (ask_c <= 1.0):
well_setup['c'].append(ask_c)
else:
raise Exception("Invalid Daming Factor {} for taper {}".format(ask_c, i))
for j in range(1, ask_num_tapers + 1):
well_setup['rod_youngs_modulus_data'].append(youngs_modulus[well_setup['rod_material'][j]])
well_setup['rod_weight_data'].append(wt_per_foot[well_setup['rod_material'][i]][well_setup['rod_diameter_data'][j]])
ask_thp = float(raw_input("Enter Tubing Head Pressure in PSI: "))
if ask_length > 0.0:
well_setup['tubing_head_pressure'] = ask_thp
else:
raise Exception("Invalid Tubing Head Pressure: {} PSI".format(ask_length))
ask_fluid_gradient = float(raw_input("Enter Fluid Gradient in PSI/ft: "))
if ask_fluid_gradient > 0.0:
well_setup['fluid_gradient'] = ask_fluid_gradient
else:
raise Exception("Invalid Fluid Gradient: {} PSI/ft".format(ask_fluid_gradient))
ask_sbf = float(raw_input("Enter Stuffing Box Friction in lbs: "))
if ask_sbf > 0.0:
well_setup['stuffing_box_friction'] = ask_sbf
else:
raise Exception("Invalid Stuffing Box Friction: {} PSI/ft".format(ask_sbf))
ask_dt = float(raw_input("Enter delta t in seconds: "))
if ask_dt > 0.0:
well_setup['dt'] = ask_dt
else:
raise Exception("Invalid delta t: {} sec".format(ask_dt))
ask_tubingID = float(raw_input("Enter Tubing ID in inches: "))
if ask_tubingID > 0.0:
well_setup['tubing_id'] = ask_tubingID
else:
raise Exception("Invalid Tubing ID: {} in".format(ask_tubingID))
ask_tubingOD = float(raw_input("Enter Tubing OD in inches: "))
if ask_tubingOD > 0.0:
well_setup['tubing_od'] = ask_tubingOD
else:
raise Exception("Invalid Tubing OD: {} in".format(ask_tubingOD))
ask_TAC = float(raw_input("Enter Tubing Anchor Depth in feet: "))
if ask_TAC > 0.0:
well_setup['anchor_depth'] = ask_TAC
else:
raise Exception("Invalid Tubing Anchor Depth: {} ft".format(ask_TAC))
ask_pump_diameter = float(raw_input("Enter Pump Diameter in inches: "))
if ask_pump_diameter > 0.0:
well_setup['pump_diameter'] = ask_pump_diameter
well_setup['pump_area'] = (well_setup['pump_diameter']**2) * math.pi
else:
raise Exception("Invalid Pump Diameter: {} in".format(ask_pump_diameter))
well_setup['well_name'] = str(raw_input("Enter Well Name: "))
else:
raise Exception("Invalid taper count")
with open('wellconfigs/' + well_setup['well_name'].replace(" ", "") + '.p', 'wb') as well_config_file:
pickle.dump(well_setup, well_config_file)
return well_setup
except Exception as e:
traceback.print_exc()
print e
return False
if __name__ == '__main__':
get_setup()

1
surface_card.json Normal file
View File

@@ -0,0 +1 @@
[[96.237, 20163.0], [94.954, 20122.0], [94.215, 20086.0], [93.467, 20040.0], [92.578, 19987.0], [91.832, 19929.0], [90.908, 19868.0], [90.09, 19805.0], [89.145, 19740.0], [88.213, 19672.0], [87.382, 19601.0], [86.51, 19529.0], [85.792, 19456.0], [84.804, 19397.0], [83.954, 19319.0], [83.058, 19257.0], [82.07, 19195.0], [81.111, 19131.0], [79.967, 19060.0], [79.024, 18980.0], [77.832, 18890.0], [76.766, 18794.0], [75.661, 18694.0], [74.537, 18591.0], [73.411, 18486.0], [72.068, 18378.0], [71.038, 18264.0], [69.634, 18165.0], [68.349, 18017.0], [67.026, 17881.0], [65.708, 17739.0], [64.413, 17595.0], [62.947, 17451.0], [61.692, 17311.0], [60.056, 17175.0], [58.662, 17042.0], [57.076, 16913.0], [55.551, 16786.0], [54.007, 16659.0], [52.492, 16532.0], [51.015, 16403.0], [49.304, 16272.0], [47.644, 16136.0], [45.928, 15992.0], [44.357, 15837.0], [42.736, 15673.0], [41.048, 15504.0], [39.504, 15334.001], [37.731, 15169.999], [36.265, 15014.001], [34.355, 14872.0], [32.688, 14751.0], [30.962, 14671.0], [29.251, 14598.001], [27.666, 14571.0], [25.791, 14574.001], [24.382, 14599.0], [22.643, 14640.0], [21.078, 14691.0], [19.57, 14749.0], [18.089, 14811.0], [16.729, 14865.0], [15.135, 14945.999], [13.937, 15019.0], [12.542, 15097.999], [11.404, 15183.0], [10.212, 15277.0], [9.119, 15380.0], [8.12, 15489.999], [7.121, 15607.0], [6.288, 15728.0], [5.4, 15849.999], [4.654, 15971.0], [3.961, 16068.0], [3.343, 16192.0], [2.838, 16284.0], [2.415, 16347.0], [2.09, 16413.0], [1.846, 16450.0], [1.672, 16469.0], [1.537, 16481.0], [1.441, 16483.0], [1.381, 16481.0], [1.488, 16476.0], [1.612, 16473.0], [1.835, 16469.0], [2.102, 16467.0], [2.512, 16462.0], [2.883, 16458.0], [3.315, 16453.0], [3.808, 16446.0], [4.316, 16438.0], [4.973, 16433.0], [5.54, 16433.0], [6.391, 16440.0], [7.156, 16468.0], [8.009, 16503.0], [8.931, 16575.0], [9.897, 16639.0], [11.031, 16738.0], [11.944, 16811.0], [13.171, 16908.0], [14.28, 16972.0], [15.421, 17044.0], [16.721, 17125.0], [17.889, 17192.0], [19.22, 17248.0], [20.432, 17315.0], [21.853, 17392.0], [23.192, 17446.0], [24.544, 17521.0], [26.013, 17585.0], [27.328, 17650.0], [28.995, 17718.0], [30.292, 17778.0], [31.928, 17857.0], [33.342, 17944.0], [34.936, 18059.0], [36.643, 18171.0], [38.108, 18273.0], [39.958, 18430.0], [41.311, 18553.0], [43.084, 18707.0], [44.599, 18892.0], [46.3, 19047.0], [47.912, 19169.0], [49.415, 19304.0], [51.044, 19447.0], [52.523, 19559.0], [54.304, 19647.0], [55.622, 19766.0], [57.414, 19850.0], [58.858, 19949.0], [60.449, 20047.0], [62.086, 20160.0], [63.562, 20241.0], [65.164, 20356.0], [66.461, 20456.0], [68.089, 20540.0], [69.502, 20645.0], [71.015, 20769.0], [72.48, 20875.0], [73.887, 20977.0], [75.417, 21053.0], [76.705, 21138.0], [78.147, 21178.0], [79.382, 21201.0], [80.704, 21200.0], [81.955, 21178.0], [83.116, 21142.0], [84.558, 21099.0], [85.614, 21052.0], [86.767, 20994.0], [87.773, 20953.0], [88.818, 20903.0], [89.783, 20846.0], [90.683, 20804.0], [91.642, 20745.0], [92.435, 20701.0], [93.347, 20646.0], [94.051, 20589.0], [94.778, 20530.0], [95.418, 20468.0], [96.068, 20394.0], [96.684, 20339.0], [97.189, 20274.0], [97.729, 20215.0], [98.187, 20165.0], [98.624, 20131.0], [98.97, 20114.0], [99.232, 20116.0], [99.499, 20128.0], [99.718, 20150.0], [99.816, 20177.0], [99.889, 20205.0], [99.907, 20234.0], [99.856, 20250.0], [99.682, 20260.0], [99.481, 20260.0], [99.27, 20250.0], [98.926, 20234.0], [98.616, 20216.0], [98.117, 20200.0], [97.676, 20189.0], [97.143, 20184.0], [96.531, 20181.0], [95.914, 20178.0], [96.237, 20163.0], [96.237, 20163.0]]

49
valveCheck.py Normal file
View File

@@ -0,0 +1,49 @@
#!/usr/bin/python
from pycomm.ab_comm.clx import Driver as ClxDriver
c = ClxDriver(True, 'ClxDriver.log')
PLC_IP_ADDRESS = "192.168.1.10"
class PLCException(Exception):
pass
upstroke_target_percent = [20.0, 50.0, 75.0]
downstroke_target_percent = [50.0]
if c.open(PLC_IP_ADDRESS):
# check that well is stopped
pump_run_status = c.read_tag(['Pump.Run'])[0][1]
if pump_run_status == 1:
raise PLCException("Cannot run the valve check while the pump is running. Stop the pump and try again.")
# Set up position targets
stroke_length = float(c.read_tag(['UnitConfig.Total_Stroke_Length'])[0][1])
upstroke_target = map(lamba x: (x/100.0) * stroke_length, upstroke_target_percent)
downstroke_target = map(lamba x: (x/100.0) * stroke_length, downstroke_target_percent)
# Store motor parameters
prev_motor_mode = map(lambda x: {'value':x[1], 'type':x[2]},c.read_tag(['UnitConfig.Speed_Torque_Mode'])[0])[0]
# Ensure drive in speed mode
if prev_motor_mode['value'] != 1:
c.write_tag('Card_Past[1].Data_Read', 1, 'REAL')
# Loop through upstroke position targets
# jog past 0 to within 3 inches of the target position
# let pid take over to hold at target
# once at target, start timer and store surface and downhole load and position
# For downstroke position target
# jog past 0 to within 3 inches of the target position
# let pid take over to hold at target
# once at target, start timer and store surface and downhole load and position
# re-write motor parameters
# do calculations

View File

@@ -0,0 +1,82 @@
(dp0
S'tubing_id'
p1
F2.441
sS'c'
p2
(lp3
F0.0
aF0.08
aF0.08
aF0.08
asS'rod_diameter_data'
p4
(lp5
F0.0
aF1.25
aF1.0
aF1.5
asS'num_tapers'
p6
I3
sS'rod_material'
p7
(lp8
S''
p9
aS'fiberglass'
p10
aS'steel'
p11
aS'steel'
p12
asS'rod_youngs_modulus_data'
p13
(lp14
F0.0
aF7.2
aF30.5
aF30.5
asS'anchor_depth'
p15
F4598.0
sS'tubing_od'
p16
F2.875
sS'dt'
p17
F0.1
sS'rod_weight_data'
p18
(lp19
F0.0
aF4.172
aF2.904
aF6.0
asS'pump_area'
p20
F12.566370614359172
sS'stuffing_box_friction'
p21
F100.0
sS'fluid_gradient'
p22
F0.45
sS'rod_length_data'
p23
(lp24
F0.0
aF2700.0
aF1575.0
aF250.0
asS'well_name'
p25
S'Bean Ranch 341'
p26
sS'tubing_head_pressure'
p27
F50.0
sS'pump_diameter'
p28
F2.0
s.

View File

@@ -0,0 +1,75 @@
(dp0
S'tubing_id'
p1
F1.995
sS'c'
p2
(lp3
F0.0
aF0.08
aF0.08
asS'rod_diameter_data'
p4
(lp5
F0.0
aF0.75
aF1.5
asS'num_tapers'
p6
I2
sS'rod_material'
p7
(lp8
S''
p9
aS'steel'
p10
aS'steel'
p11
asS'rod_youngs_modulus_data'
p12
(lp13
F0.0
aF30.5
aF30.5
asS'anchor_depth'
p14
F8923.0
sS'tubing_od'
p15
F2.375
sS'dt'
p16
F0.06
sS'rod_weight_data'
p17
(lp18
F0.0
aF1.634
aF6.0
asS'pump_area'
p19
F4.908738521234052
sS'stuffing_box_friction'
p20
F100.0
sS'fluid_gradient'
p21
F0.45
sS'rod_length_data'
p22
(lp23
F0.0
aF10095.0
aF300.0
asS'well_name'
p24
S'Casselman 16-8'
p25
sS'tubing_head_pressure'
p26
F150.0
sS'pump_diameter'
p27
F1.25
s.

View File

@@ -0,0 +1,82 @@
(dp0
S'tubing_id'
p1
F2.441
sS'c'
p2
(lp3
F0.0
aF0.08
aF0.08
aF0.08
asS'rod_diameter_data'
p4
(lp5
F0.0
aF1.0
aF0.75
aF1.5
asS'num_tapers'
p6
I3
sS'rod_material'
p7
(lp8
S''
p9
aS'fiberglass'
p10
aS'steel'
p11
aS'steel'
p12
asS'rod_youngs_modulus_data'
p13
(lp14
F0.0
aF7.2
aF30.5
aF30.5
asS'anchor_depth'
p15
F4598.0
sS'tubing_od'
p16
F2.875
sS'dt'
p17
F0.06
sS'rod_weight_data'
p18
(lp19
F0.0
aF2.904
aF1.634
aF6.0
asS'pump_area'
p20
F12.566370614359172
sS'stuffing_box_friction'
p21
F100.0
sS'fluid_gradient'
p22
F0.45
sS'rod_length_data'
p23
(lp24
F0.0
aF4435.0
aF2950.0
aF250.0
asS'well_name'
p25
S'UnivTaylor192UW'
p26
sS'tubing_head_pressure'
p27
F50.0
sS'pump_diameter'
p28
F2.0
s.