commit a1714c722f54e88acb0b6305472a8526ab48ff35 Author: Patrick McDonagh Date: Fri Jul 1 16:43:39 2016 -0500 Initial Commit diff --git a/FiniteDifferences/.idea/.name b/FiniteDifferences/.idea/.name new file mode 100644 index 0000000..4ca51f8 --- /dev/null +++ b/FiniteDifferences/.idea/.name @@ -0,0 +1 @@ +FiniteDifferences \ No newline at end of file diff --git a/FiniteDifferences/.idea/FiniteDifferences.iml b/FiniteDifferences/.idea/FiniteDifferences.iml new file mode 100644 index 0000000..d0876a7 --- /dev/null +++ b/FiniteDifferences/.idea/FiniteDifferences.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/FiniteDifferences/.idea/misc.xml b/FiniteDifferences/.idea/misc.xml new file mode 100644 index 0000000..8f0be67 --- /dev/null +++ b/FiniteDifferences/.idea/misc.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FiniteDifferences/.idea/modules.xml b/FiniteDifferences/.idea/modules.xml new file mode 100644 index 0000000..5e4e018 --- /dev/null +++ b/FiniteDifferences/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/FiniteDifferences/.idea/vcs.xml b/FiniteDifferences/.idea/vcs.xml new file mode 100644 index 0000000..6564d52 --- /dev/null +++ b/FiniteDifferences/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/FiniteDifferences/.idea/workspace.xml b/FiniteDifferences/.idea/workspace.xml new file mode 100644 index 0000000..1a93d56 --- /dev/null +++ b/FiniteDifferences/.idea/workspace.xml @@ -0,0 +1,289 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1434394978091 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FiniteDifferences/FiniteDifferences.py b/FiniteDifferences/FiniteDifferences.py new file mode 100644 index 0000000..a931d65 --- /dev/null +++ b/FiniteDifferences/FiniteDifferences.py @@ -0,0 +1,39 @@ +__author__ = 'patrickjmcd' +import math +import numpy as np +import scipy.interpolate + +# setting up constants +E = 30.5 * 10**6 +A = math.pi/4 * (0.75)**2 +L = 2000 +Gc = 32.2 +Rho = 490 +T = 15 +M = 100 +NT = 360 +C = 0.8 + +F = [4085.7, 3969.1, 3852.4, 3774.7, 3697, 3736, 3814, 3891.9, 3969.7, 4047.7, 4008.9, 3931.1, 3853.3, 3775.6, 3658.9, 3581.2, 3581.3, 3659.3, 3737.3, 3815.2, 3893.1, 3970.9, 4048.9, 4126.8, 4204.7, 4282.6, 4360.5, 4477.3, 4555.3, 4633.2, 4672.1, 4788.9, 4866.8, 4944.7, 5061.4, 5139.4, 5256.2, 5334, 5411.8, 5528.6, 5606.5, 5684.4, 5801.3, 5879.2, 5918.3, 5918.6, 5879.9, 5841.2, 5880.2, 5919.3, 5997.3, 6075.2, 6153.1, 6231, 6308.9, 6386.7, 6503.6, 6581.5, 6659.3, 6776.2, 6854.1, 6932, 6971.1, 6932.5, 6893.7, 6855, 6777.3, 6738.6, 6699.8, 6699.9, 6739.1, 6778.3, 6778.6, 6778.8, 6779.2, 6818.4, 6896.4, 6974.3, 7052.2, 7169, 7285.9, 7441.6, 7597.4, 7675.3, 7792.2, 7986.8, 8103.7, 8220.5, 8337.3, 8454.1, 8571, 8649, 8726.9, 8766, 8688.4, 8610.7, 8533, 8455.3, 8377.6, 8261, 8183.3, 8105.7, 8067, 8067.2, 8106.3, 8145.5, 8145.7, 8145.9, 8107.2, 8068.5, 8029.9, 7991.3, 7991.5, 7991.7, 7992, 7914.4, 7836.8, 7759, 7681.3, 7603.6, 7448.1, 7331.5, 7253.8, 7137.2, 7020.5, 6865, 6670.6, 6515, 6398.4, 6281.8, 6165.2, 6048.6, 5970.9, 5932.2, 5971.3, 6049.2, 6127.2, 6205.1, 6283, 6361.1, 6400.2, 6439.3, 6400.8, 6362.1, 6323.4, 6323.6, 6323.8, 6363.1, 6363.3, 6363.5, 6363.7, 6325.1, 6325.2, 6403.2, 6442.2, 6520.2, 6598.1, 6676, 6754, 6870.8, 6987.6, 7143.4, 7260.2, 7416, 7610.7, 7766.4, 7922.2, 8000.1, 8078, 8078.1, 8039.4, 8000.6, 7922.9, 7845.2, 7767.5, 7689.8, 7651, 7612.3, 7612.5, 7651.7, 7690.7, 7690.9, 7652.4, 7613.8, 7614, 7653.1, 7653.4, 7575.8, 7498, 7420.3, 7342.6, 7226, 7109.4, 6992.7, 6876, 6720.5, 6526.1, 6370.5, 6253.8, 6137.2, 6020.6, 5981.8, 6020.9, 6098.8, 6176.8, 6254.7, 6332.8, 6333, 6294.4, 6294.7, 6295, 6295.2, 6256.6, 6334.6, 6451.5, 6568.3, 6685.1, 6801.9, 6957.7, 7152.3, 7269, 7502.6, 7619.5, 7697.4, 7658.7, 7581, 7503.2, 7425.6, 7425.8, 7464.8, 7426.2, 7387.6, 7387.8, 7310.1, 7193.5, 7037.8, 6687.6, 6843.4, 6687.7, 6532.1, 6415.5, 6298.7, 6182, 6182.2, 6182.5, 6182.8, 6338.6, 6416.4, 6572, 6688.7, 6844.4, 7038.9, 7155.7, 7311.2, 7116.5, 6999.8, 6844.2, 6727.3, 6571.8, 6454.8, 6338, 5987.8, 5832.1, 5676.4, 5442.8, 5326, 5209.2, 5364.7, 5559.1, 5714.7, 5870.2, 5947.8, 5869.7, 5830.6, 5791.5, 5674.6, 5596.7, 5518.8, 5440.7, 5401.6, 5479.2, 5556.8, 5478.7, 5361.9, 5206.1, 5128.3, 5011.5, 4816.9, 4622.3, 4349.8, 4155.1, 3882.6, 3726.9, 3610.1, 3493, 3414.9, 3336.8, 3258.7, 3219.5, 3219.3, 3218.9, 3179.7, 3101.7, 2984.7, 2906.9, 2751, 2595.2, 2517.2, 2400.4, 2322.5, 2322.2, 2438.7, 2555.4, 2672, 2749.7, 2866.3, 2944, 3021.6, 3021.4, 2943.5, 2787.6, 2631.8, 2476.1, 2242.4, 2008.7, 1814.1, 1697.2, 1619.3, 1580, 1579.8, 1579.6, 1579.4, 1579.1, 1656.6, 1695.2, 1811.7, 1928.2, 2122.6, 2278, 2394.6, 2472.2, 2511, 2510.8, 2432.7, 2315.8, 2159.9, 2004, 1926, 1964.6, 2081.1, 2236.5, 2392, 2547.6, 2741.9, 2936.3, 3130.6, 3247.2, 3286, 3324.7, 3402.3, 3402, 3440.6, 3401.3, 3362.1, 3283.9, 3205.9, 3089.1, 3011.1, 2933.2, 2855.3, 2777.3, 2699.4, 2660.3, 2660, 2698.7, 2815.2, 3009.6, 3126.1, 3242.6, 3281.4, 3281.2, 3203.1, 3125.2, 3008.3, 2852.5, 2735.6, 2618.8, 2502, 2385.1, 2268.2, 2190.2, 2151.1, 2111.8, 2111.4, 2111.1, 2188.4, 2266, 2382.5, 2538.1, 2615.8, 2693.5, 2810, 2887.7, 2926.4, 2887.3, 2809.2, 2731.3, 2614.4, 2536.5, 2458.5, 2419.3, 2496.9, 2574.6, 2652.4, 2769, 2924.5, 3080, 3118.8, 3274.4, 3429.9, 3468.7, 3546.4, 3585.1, 3662.7, 3701.3, 3701, 3700.8, 3661.6, 3466.8, 3349.9, 3233.1, 3155.1, 3193.7, 3271.5, 3388.1, 3504.7, 3621.3, 3660.1, 3698.9, 3659.8, 3542.9, 3426.1, 3270.3, 3153.5, 2997.7, 2880.9, 2802.9, 2763.6, 2841.1, 2957.8, 3074.6, 3191.2, 3269, 3346.7, 3346.6, 3346.4 ] + +X = [0.10168, 0.2756, 0.44953, 0.62278, 0.79604, 0.96729, 1.1379, 1.3084, 1.3071, 1.4777, 1.6503, 1.8235, 1.8249, 1.9981, 2.0001, 2.1734, 2.3453, 2.6878, 2.8584, 3.029, 3.1995, 3.1982, 3.3688, 3.5394, 3.7099, 3.7086, 3.8792, 4.0491, 4.2197, 4.3903, 4.3896, 4.5595, 4.5582, 4.7287, 4.7267, 4.8973, 5.0672, 5.0659, 5.0646, 5.0625, 5.2331, 5.4037, 5.5736, 5.7442, 6.0874, 6.4312, 6.7757, 7.1202, 7.2915, 7.6346, 7.8052, 7.9758, 8.1464, 8.145, 8.3156, 8.3143, 8.4842, 8.6548, 8.6534, 8.8233, 8.9939, 9.1645, 9.5077, 9.8522, 10.025, 10.369, 10.543, 10.887, 11.06, 11.232, 11.747, 12.09, 12.606, 12.949, 13.465, 13.98, 14.323, 14.321, 14.492, 14.662, 14.832, 15.001, 15.17, 15.341, 15.511, 15.679, 15.849, 16.019, 16.189, 16.187, 16.529, 16.699, 16.87, 17.213, 17.558, 17.732, 17.905, 18.078, 18.251, 18.425, 18.599, 18.944, 19.288, 19.632, 19.975, 20.318, 20.662, 21.006, 21.351, 21.695, 22.04, 22.556, 22.9, 23.244, 23.588, 23.933, 24.278, 24.451, 24.624, 24.798, 24.972, 25.146, 25.319, 25.493, 25.667, 25.842, 26.017, 26.192, 26.366, 26.54, 26.713, 26.887, 27.061, 27.405, 27.748, 27.919, 28.09, 28.26, 28.431, 28.773, 29.116, 29.459, 29.976, 30.32, 30.665, 31.009, 31.353, 31.868, 32.212, 32.555, 32.899, 33.244, 33.416, 33.758, 33.929, 34.1, 34.271, 34.441, 34.612, 34.782, 34.952, 35.121, 35.291, 35.46, 35.628, 35.798, 35.967, 36.138, 36.308, 36.48, 36.825, 36.997, 37.17, 37.344, 37.517, 37.69, 37.863, 38.207, 38.551, 38.894, 39.065, 39.409, 39.926, 40.442, 40.786, 41.129, 41.473, 41.818, 41.991, 42.165, 42.338, 42.512, 42.686, 42.688, 42.862, 43.036, 43.212, 43.386, 43.388, 43.562, 43.736, 43.909, 44.252, 44.422, 44.593, 44.764, 45.106, 45.45, 45.966, 46.482, 46.826, 47.17, 47.686, 48.029, 48.199, 48.368, 48.366, 48.536, 48.706, 48.874, 48.872, 49.04, 49.21, 49.381, 49.725, 49.898, 49.9, 50.245, 50.589, 50.76, 51.276, 51.621, 51.965, 52.138, 52.312, 52.315, 52.321, 52.49, 52.492, 52.495, 52.669, 52.671, 52.673, 53.017, 53.361, 53.877, 54.046, 54.044, 54.042, 54.04, 54.037, 54.034, 54.032, 53.857, 53.689, 53.691, 53.693, 53.523, 53.698, 53.356, 53.186, 53.192, 53.023, 53.026, 52.858, 52.688, 52.518, 52.343, 52.168, 51.993, 51.819, 51.474, 51.131, 50.788, 50.445, 50.275, 50.104, 49.934, 49.591, 49.248, 48.903, 48.558, 48.215, 48.045, 47.876, 47.877, 47.708, 47.711, 47.542, 47.375, 47.207, 47.039, 46.87, 46.7, 46.186, 45.844, 45.329, 44.987, 44.472, 44.128, 43.612, 43.097, 42.755, 42.413, 42.414, 42.073, 41.732, 41.561, 41.391, 41.221, 40.877, 40.531, 40.357, 40.183, 40.01, 39.836, 39.663, 39.318, 38.974, 38.803, 38.462, 38.293, 38.124, 37.784, 37.444, 37.275, 37.105, 36.935, 36.42, 36.076, 35.732, 35.388, 35.044, 34.527, 34.011, 33.665, 33.319, 32.972, 32.626, 32.452, 32.106, 31.934, 31.59, 31.248, 30.906, 30.565, 30.223, 29.881, 29.365, 29.019, 28.672, 28.498, 28.323, 27.976, 27.801, 27.453, 27.107, 26.935, 26.762, 26.417, 25.901, 25.385, 24.87, 24.355, 23.84, 23.498, 23.328, 23.157, 22.987, 22.816, 22.646, 22.475, 22.132, 21.788, 21.444, 21.098, 20.751, 20.405, 20.059, 19.886, 19.542, 19.2, 19.029, 18.859, 18.518, 18.348, 18.178, 18.009, 17.839, 17.497, 17.326, 16.983, 16.468, 15.78, 15.265, 14.576, 14.23, 13.885, 13.71, 13.537, 13.363, 13.018, 12.844, 12.5, 12.157, 11.814, 11.644, 11.474, 11.303, 10.961, 10.617, 10.272, 10.099, 9.9257, 9.7518, 9.5772, 9.4026, 9.23, 9.0555, 8.8809, 8.7083, 8.535, 8.1905, 7.8453, 7.3289, 6.9851, 6.6412, 6.1262, 5.7857, 5.6158, 5.4458, 5.1034, 4.7588, 4.5856, 4.4117, 4.2377, 4.0638, 3.8912, 3.7186, 3.3755, 3.2056, 3.0357, 2.8664, 2.6965, 2.5273, 2.3573, 2.0149, 1.4998, 0.98267, 0.98067, 0.97866, 0.80474, 0.8034, 0.63014, 0.45822, 0.11439] + +[Xmin, IXmin] = min(X) +X = np.roll(X, 1 - IXmin) +F = np.roll(F, 1 - IXmin) +[Xmax, IXmax] = max(X) + +Xu = X[0:IXmax] +Xd = X[IXmax:len(X)] +Xd.push(X[0]) +Fu = F[0:IXmax] +Fd = F[IXmax:len(X)] +Fd.push(F[0]) + +S = Xmax - Xmin + +Xi = [0.10168, 0.111692778, 0.13196366, 0.162450928, 0.203107855, 0.253882838, 0.314719538, 0.385557016, 0.466329871, 0.556968385, 0.65739866, 0.767542759, 0.887318849, 1.016641341, 1.155421026, 1.303565219, 1.460977889, 1.6275598, 1.80320864, 1.987819156, 2.181283279, 2.383490252, 2.594326755, 2.813677023, 3.041422967, 3.277444288, 3.521618587, 3.773821477, 4.033926687, 4.301806164, 4.577330175, 4.860367396, 5.150785014, 5.448448807, 5.753223235, 6.064971523, 6.383555736, 6.708836859, 7.040674868, 7.378928801, 7.723456822, 8.074116288, 8.430763807, 8.793255299, 9.161446046, 9.53519075, 9.914343578, 10.29875821, 10.6882879, 11.08278548, 11.48210343, 11.88609393, 12.29460886, 12.70749983, 13.12461828, 13.54581543, 13.97094234, 14.39984995, 14.8323891, 15.26841055, 15.70776498, 16.15030306, 16.59587544, 17.04433279, 17.49552579, 17.94930517, 18.40552174, 18.86402637, 19.32467006, 19.78730391, 20.25177917, 20.71794722, 21.18565964, 21.65476819, 22.12512482, 22.59658173, 23.06899135, 23.54220637, 24.01607978, 24.49046486, 24.96521521, 25.44018477, 25.91522788, 26.39019925, 26.864954, 27.33934771, 27.81323643, 28.28647671, 28.75892562, 29.2304408, 29.70088048, 30.17010353, 30.63796946, 31.10433849, 31.5690716, 32.03203051, 32.49307779, 32.95207685, 33.40889204, 33.86338863, 34.31543289, 34.76489217, 35.2116349, 35.65553064, 36.09645018, 36.53426556, 36.96885013, 37.4000786, 37.82782711, 38.25197327, 38.67239623, 39.08897675, 39.50159723, 39.91014179, 40.31449631, 40.71454852, 41.11018804, 41.50130641, 41.88779722, 42.26955608, 42.64648076, 43.01847117, 43.38542946, 43.74726007, 44.10386975, 44.45516765, 44.80106533, 45.14147682, 45.47631866, 45.80550996, 46.12897239, 46.44663024, 46.75841048, 47.06424272, 47.36405929, 47.65779525, 47.94538839, 48.22677923, 48.5019111, 48.77073005, 49.03318493, 49.28922733, 49.53881164, 49.78189496, 50.01843717, 50.24840083, 50.47175123, 50.68845631, 50.8984867, 51.10181559, 51.29841878, 51.48827461, 51.6713639, 51.84766995, 52.01717844, 52.17987741, 52.33575719, 52.48481037, 52.62703172, 52.76241813, 52.89096853, 53.01268389, 53.12756708, 53.23562284, 53.3368577, 53.43127994, 53.51889947, 53.59972779, 53.67377794, 53.74106438, 53.80160294, 53.85541079, 53.90250628, 53.94290897, 53.97663949, 54.00371951, 54.02417164, 54.03801941, 54.04528716, 54.046, 54.04018376, 54.02786489, 54.00907046, 53.98382803, 53.95216567, 53.91411185, 53.86969545, 53.81894562, 53.76189185, 53.69856383, 53.62899145, 53.55320476, 53.47123393, 53.38310922, 53.28886093, 53.1885194, 53.08211497, 52.96967792, 52.85123853, 52.72682697, 52.59647335, 52.46020767, 52.31805981, 52.17005956, 52.01623653, 51.85662026, 51.69124009, 51.52012528, 51.34330491, 51.16080797, 50.97266331, 50.77889967, 50.57954568, 50.37462992, 50.16418087, 49.94822697, 49.72679663, 49.49991826, 49.26762028, 49.02993118, 48.78687952, 48.53849395, 48.2848033, 48.02583657, 47.76162296, 47.49219198, 47.2175734, 46.93779736, 46.65289442, 46.36289555, 46.06783225, 45.76773656, 45.46264114, 45.1525793, 44.8375851, 44.51769336, 44.19293978, 43.86336097, 43.52899451, 43.18987904, 42.84605434, 42.49756136, 42.14444234, 41.78674086, 41.42450191, 41.057772, 40.6865992, 40.31103326, 39.93112565, 39.54692968, 39.15850056, 38.76589551, 38.3691738, 37.96839688, 37.56362844, 37.15493451, 36.74238354, 36.32604648, 35.90599687, 35.48231092, 35.0550676, 34.62434871, 34.19023899, 33.75282616, 33.31220102, 32.8684575, 32.4216928, 31.97200735, 31.51950499, 31.06429294, 30.60648193, 30.14618619, 29.68352357, 29.21861553, 28.7515872, 28.2825674, 27.81168873, 27.33908749, 26.86490378, 26.38928149, 25.91236828, 25.4343156, 24.95527863, 24.47541634, 23.99489139, 23.5138701, 23.03252244, 22.55102193, 22.0695456, 21.58827392, 21.10739066, 20.62708288, 20.14754073, 19.66895741, 19.19152901, 18.71545439, 18.24093498, 17.76817472, 17.2973798, 16.82875854, 16.36252121, 15.89887979, 15.43804781, 14.98024012, 14.52567268, 14.07456235, 13.62712662, 13.18358339, 12.74415076, 12.30904672, 11.87848894, 11.4526945, 11.03187963, 10.61625945, 10.20604771, 9.801456512, 9.402696059, 9.009974389, 8.623497114, 8.243467156, 7.870084499, 7.503545932, 7.144044805, 6.791770785, 6.446909627, 6.109642939, 5.780147969, 5.458597387, 5.145159087, 4.839995992, 4.54326587, 4.255121159, 3.97570881, 3.705170133, 3.443640654, 3.191249996, 2.948121753, 2.714373392, 2.490116162, 2.275455011, 2.070488521, 1.875308851, 1.690001699, 1.514646263, 1.349315229, 1.194074759, 1.048984495, 0.914097574, 0.789460652, 0.675113939, 0.571091244, 0.477420029, 0.394121474, 0.321210542, 0.258696068, 0.206580837, 0.164861684, 0.133529591, 0.112569796, 0.101961904 ] + +Ni = len(Xi) +Xi_new = Xi.push(Xi[0]) +Xi = scipy.interpolate.interp1d(np.linspace(0,1,Ni+1), ) \ No newline at end of file diff --git a/NeuralNetwork/NeuralNetwork.py b/NeuralNetwork/NeuralNetwork.py new file mode 100644 index 0000000..dd6c05b --- /dev/null +++ b/NeuralNetwork/NeuralNetwork.py @@ -0,0 +1,12 @@ + +import numpy as np + +class BackPropagationNetwork: + + # + # Class Members + # + + layerCount = 0 + shape = None + weights = [] diff --git a/WellBore/drawWellBore.py b/WellBore/drawWellBore.py new file mode 100644 index 0000000..3290668 --- /dev/null +++ b/WellBore/drawWellBore.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +""" +Created on Fri Oct 23 18:23:25 2015 + +@author: patrickjmcd +""" + +import csv +import matplotlib.pyplot as plt +from mpl_toolkits.mplot3d import Axes3D + +f = open('melinda254.csv', 'rb') +reader = csv.reader(f) +headers = reader.next() + +csv_data = {} +for h in headers: + csv_data[h] = [] + +for row in reader: + for h,v in zip(headers, row): + csv_data[h].append(float(v)) + +csv_data['Depth'] = map(lambda x: -1*x, csv_data['Depth']) + +fig = plt.figure() +ax = fig.add_subplot(111, projection='3d') +ax.plot(csv_data['Northings'], csv_data['Eastings'], csv_data['Depth']) + +plt.show() \ No newline at end of file diff --git a/WellBore/melinda252.csv b/WellBore/melinda252.csv new file mode 100644 index 0000000..b8aa852 --- /dev/null +++ b/WellBore/melinda252.csv @@ -0,0 +1,171 @@ +Depth,Northings,Eastings +0,0,0 +199.99,0.36,1.44 +399.97,1,4.58 +599.94,1.17,8.05 +799.9,0.99,11.78 +999.87,0.91,15.35 +1199.84,0.71,18.55 +1399.83,0.59,20.76 +1599.83,0.33,21.89 +1703.82,0.15,22.61 +1861.82,0.29,24.11 +1987.81,0.94,25.47 +2114.79,2.26,27.1 +2240.77,3.73,29.15 +2366.74,5.38,31.32 +2492.71,7.24,33.35 +2619.67,9.23,35.43 +2745.64,11.42,37.25 +2871.61,13.58,38.76 +2997.59,15.72,40.3 +3124.55,18.16,41.82 +3250.52,20.9,43.24 +3376.47,23.85,44.41 +3502.43,26.92,45.28 +3629.39,30.16,46.38 +3755.34,33.4,47.75 +3881.3,36.18,48.76 +4007.28,38.65,49.3 +4134.26,41.05,49.7 +4260.23,43.76,50.2 +4387.18,46.93,50.68 +4513.14,50.3,51.17 +4639.08,54.1,51.83 +4765.03,57.46,52.05 +4892.02,58.95,51.49 +5018.02,59.45,51.06 +5144.02,59.69,50.83 +5270.02,59.61,50.63 +5396.02,59.74,50.81 +5523.02,59.87,50.99 +5649.02,60.08,50.95 +5775.02,60,50.79 +5902.01,58.8,50.64 +6027.99,56.5,49.8 +6153.95,53.92,48.64 +6280.94,51.99,48.12 +6406.93,50.48,47.86 +6532.92,49.18,47.64 +6658.92,48.23,47.37 +6784.91,47.27,46.88 +6910.91,46.3,46.38 +7037.9,45.43,46.29 +7163.9,44.74,46.79 +7289.89,44.15,47.97 +7416.88,44.13,49.85 +7542.85,44.8,52.29 +7668.84,44.67,54.43 +7795.82,43.09,55.24 +7921.81,41.74,55.78 +8048.79,40.87,57.57 +8174.76,39.07,59.88 +8301.71,35.89,61.24 +8427.65,32,61.94 +8553.58,27.9,62.22 +8680.5,23.77,60.7 +8806.44,20.4,58.42 +8932.4,17.86,56.51 +8997.38,16.86,55.58 +9049.37,16.16,54.87 +9080.37,15.83,54.44 +9112.36,15.89,53.98 +9143.33,17.22,53.61 +9175.15,20.53,53.63 +9206.75,25.54,54.28 +9237.07,31.89,55.24 +9268.03,39.89,56.43 +9297.61,49.04,57.91 +9327.54,60.22,59.62 +9356.71,73.25,61.28 +9384.13,87.62,62.88 +9411.49,104.11,64.55 +9437.02,121.62,66.06 +9462.11,141.43,67.29 +9485.68,163.05,68.01 +9506.96,185.59,68.22 +9526.98,210.53,67.8 +9543.93,236.44,66.54 +9558.78,264.61,63.57 +9570.95,292.61,58.24 +9581.23,321.96,50.78 +9588.33,351,42.61 +9592.32,380.42,33.75 +9594.42,410.88,24.18 +9595.42,440.42,14.84 +9595.78,470.91,5.14 +9595.89,500.39,-4.47 +9595.89,530.74,-14.6 +9596.06,591.35,-35.17 +9595.67,650.93,-55.63 +9594.91,709.42,-76.17 +9594.64,768.7,-97.51 +9594.92,828.74,-119.66 +9595.14,887.52,-142.34 +9594.7,946.23,-165.17 +9593.65,1005.31,-187.02 +9592.44,1064.88,-207.48 +9591.51,1124.92,-226.53 +9590.5,1186.17,-245.08 +9589.07,1246.38,-263.54 +9587.81,1306.55,-282.17 +9586.66,1366.85,-300.37 +9584.84,1427.19,-318.42 +9582.55,1488.35,-337.12 +9580.74,1548.46,-355.9 +9579.8,1608.79,-374 +9579.09,1669.41,-391.15 +9577.99,1730.02,-408.3 +9576.45,1790.45,-426.03 +9575.28,1851.79,-444.26 +9574.51,1912.27,-461.88 +9573.68,1973.03,-478.51 +9572.62,2035.09,-494.1 +9571.52,2096.32,-508.91 +9571.3,2157.48,-523.99 +9570.64,2218.58,-539.33 +9569.05,2279.44,-555.53 +9567.37,2340.78,-573.7 +9565.28,2400.83,-592.63 +9562.87,2460.69,-612.14 +9561.38,2520.53,-631.76 +9560.72,2580.63,-650.65 +9560.28,2640.81,-669.28 +9560.11,2701.74,-688.84 +9559.67,2761.43,-708.99 +9559.73,2820.98,-729.55 +9560.11,2880.71,-749.59 +9559.02,2940.59,-769.11 +9557.15,3000.57,-788.3 +9556.53,3061.53,-807.76 +9556.7,3121.5,-827.07 +9556.31,3181.42,-846.54 +9555.54,3240.9,-867.26 +9554.77,3299.81,-889.57 +9554.77,3359.4,-912.93 +9555.72,3419.16,-935.81 +9557.04,3478.4,-957.19 +9558.6,3538.77,-978.39 +9559.39,3599.11,-999.7 +9557.57,3658.59,-1020.36 +9553.61,3719.22,-1040.47 +9549.65,3779.2,-1059.32 +9545.97,3840.51,-1077.31 +9542.84,3901.19,-1093.96 +9540.16,3962.94,-1110.57 +9537.57,4023.93,-1126.11 +9534.84,4086.34,-1140.01 +9532.25,4148.07,-1152.34 +9529.8,4210.86,-1164.49 +9526.99,4272.55,-1176.93 +9524.15,4335.04,-1190.44 +9521.89,4396.45,-1204.34 +9520,4458.81,-1218.62 +9518.02,4520.16,-1232.78 +9515.34,4582.31,-1247.82 +9511.6,4644.12,-1263.98 +9506.87,4704.63,-1280.87 +9501.68,4765.81,-1298.93 +9495.92,4825.74,-1317.48 +9491.46,4865.52,-1330.18 +9485.99,4911.86,-1345.15 \ No newline at end of file diff --git a/WellBore/melinda254.csv b/WellBore/melinda254.csv new file mode 100644 index 0000000..b3e461b --- /dev/null +++ b/WellBore/melinda254.csv @@ -0,0 +1,146 @@ +Depth,Northings,Eastings +0,0,0 +100,-0.33,0.25 +199.99,-1.13,0.81 +299.99,-1.54,1.85 +399.98,-2.36,3.04 +499.96,-2.72,4.97 +599.92,-3.1,7.62 +699.9,-4.07,9.54 +799.87,-5.58,11.17 +899.86,-6.56,12.54 +999.84,-7.72,13.71 +1099.83,-8.22,14.72 +1199.83,-9.31,15.06 +1299.82,-10.17,15.48 +1399.82,-11.18,15.39 +1499.81,-11.85,15.78 +1599.81,-12.55,15.48 +1699.8,-13.73,14.9 +1799.79,-14.82,15.3 +1899.79,-15.4,15.58 +1999.79,-15.43,15.33 +2099.79,-15.53,15.45 +2199.79,-15.07,15.33 +2299.79,-14.97,15.09 +2399.79,-15.01,14.63 +2499.78,-14.66,14.02 +2599.78,-14.32,13.1 +2699.77,-13.64,13 +2799.77,-12.66,13.2 +2899.76,-11.51,13.56 +2999.75,-10.25,13.85 +3099.74,-8.86,13.94 +3199.73,-7.79,14.5 +3299.71,-6.14,15.48 +3399.69,-4.48,16.59 +3499.68,-3.17,17.28 +3599.67,-1.65,18.21 +3699.66,-0.81,19 +3799.65,0.48,19.93 +3899.63,2.1,21.01 +3999.61,3.69,22.03 +4099.58,5.73,23.24 +4199.57,6.85,24.03 +4299.56,8.03,25.12 +4399.53,9.69,26.35 +4499.51,11.49,27.75 +4599.46,13.44,30.11 +4699.42,15.77,31.36 +4799.38,17.71,33.42 +4899.35,19.27,35.19 +4999.34,20.08,36.23 +5099.33,20.29,37.52 +5199.33,20.79,38.03 +5299.32,20.65,39.26 +5399.31,20.36,40.74 +5499.3,20.22,41.93 +5599.29,19.77,43.34 +5699.29,19.77,43.98 +5799.29,19.27,44.79 +5899.28,18.55,45.52 +5999.27,17.35,45.75 +6099.26,16.14,45.07 +6199.26,15.87,44.37 +6299.25,15.36,43.82 +6399.25,15.71,43.43 +6499.25,15.58,42.8 +6599.25,15.53,42.19 +6699.24,16.02,41.7 +6799.24,15.89,41.13 +6899.24,15.73,41.17 +6999.24,15.77,41.49 +7099.24,15.64,41.16 +7199.23,15.91,39.87 +7299.21,16.48,38.09 +7399.17,18.79,36.42 +7499.16,20.21,35.78 +7599.15,21,36.6 +7699.11,21.97,38.99 +7799.02,23.9,42.73 +7898.98,25.29,45.16 +7998.97,26.38,45.51 +8098.96,27.58,44.43 +8198.95,28.08,43.25 +8298.93,28.91,41.25 +8398.88,28.64,38.42 +8498.86,28.54,36.05 +8598.83,29.75,34.38 +8698.81,31.31,33.26 +8798.8,32.57,32.61 +8898.8,33.4,31.82 +8998.78,34.4,30.69 +9098.21,43.02,27.53 +9193.48,71.25,18.27 +9280.34,119.49,8.62 +9357.9,179.92,-9.06 +9424.72,249.84,-34.1 +9479.19,330.19,-57.65 +9517.6,418.81,-82.95 +9541.53,512.14,-109.48 +9555.24,606.96,-137.83 +9558.16,703.18,-164.9 +9560.78,798.81,-193.98 +9563.45,893.01,-227.43 +9565.16,988.21,-257.97 +9566.63,1083.65,-287.8 +9567.58,1179.11,-317.56 +9567.8,1274.71,-346.86 +9566.7,1370.83,-374.39 +9564.42,1467.43,-400.17 +9562.05,1564.5,-424.05 +9559.6,1661.42,-448.58 +9557.08,1758.46,-472.59 +9554.28,1855.14,-497.96 +9552.14,1951.81,-523.48 +9551.17,2048.79,-547.83 +9553.1,2145.95,-571.38 +9555.42,2242.89,-595.82 +9556.48,2339.8,-620.47 +9555.22,2436.9,-644.3 +9554.24,2533.89,-668.65 +9552.68,2630.51,-694.34 +9552.9,2726.64,-721.89 +9551.95,2822.73,-749.58 +9549.18,2919.02,-776.39 +9544.82,3015.65,-801.73 +9542.42,3112.25,-827.45 +9543.04,3208.62,-854.15 +9542.04,3305.07,-880.52 +9539.22,3402.13,-904.4 +9539.67,3498.9,-929.58 +9541.02,3595.24,-956.35 +9542.06,3691.21,-984.42 +9542.26,3787.73,-1010.56 +9542.24,3884.89,-1034.22 +9541,3982.12,-1057.55 +9539.24,4079.14,-1081.72 +9537.89,4176.18,-1105.81 +9536.18,4273.1,-1130.37 +9534.93,4369.84,-1155.69 +9534.45,4466.39,-1181.72 +9534.09,4562.03,-1210.85 +9534.13,4656.6,-1243.35 +9533.28,4752.09,-1273.03 +9530.08,4847.78,-1301.88 +9527.2,4919.36,-1324.18 \ No newline at end of file diff --git a/cardAnalysis.py b/cardAnalysis.py new file mode 100644 index 0000000..22ca01d --- /dev/null +++ b/cardAnalysis.py @@ -0,0 +1,442 @@ +# Python program to analyze cards +import matplotlib.pyplot as plt +import numpy as np +import readCardFile as rcf + +# Setup Data +slices = 250 # number of horizontal slices to evaluate +pctTop = 10 # when finding corners, percent below maximum to search +pctBottom = 10 # when finding corners, percent above minimum to search +pumpTapPercent = 35 # percentage of downhole load span to be considered 100% tapping +tubingMovementPctStroke = 25 # percentage of stroke taken up by tubing movement to consider score of 100 + +downhole = rcf.readFile()[1] + +# Mostly Full Card +# downhole = [[64.577, -4503.565], [65.055, -4507.592], [65.432, -4493.037], [65.851, -4599.1], [66.291, -4735.827], [66.561, -4853.273], [66.682, -4899.307], [66.787, -4918.142], [66.89, -4929.726], [67.001, -4983.405], [67.108, -4978.893], [67.128, -4937.433], [67.101, -4955.286], [67.019, -4990.838], [66.86, -5014.888], [66.609, -5034.405], [66.286, -5053.554], [65.872, -5107.013], [65.38, -5126.4], [64.761, -5138.246], [64.073, -5152.267], [63.318, -5237.705], [62.387, -5360.465], [61.333, -5386.295], [60.202, -5427.148], [59.121, -5698.709], [58.068, -5775.45], [56.748, -5961.322], [55.738, -6598.427], [54.947, -7069.938], [54.472, -7458.419], [54.264, -7766.768], [54.231, -7900.823], [54.274, -7919.208], [54.493, -8065.488], [54.798, -8058.136], [54.94, -7923.052], [55.063, -7913.114], [55.224, -7932.654], [55.324, -7964.23], [55.394, -7934.037], [55.398, -7917.927], [55.438, -8037.331], [55.527, -8057.723], [55.46, -7971.96], [55.368, -7845.327], [55.488, -8151.271], [55.302, -8644.739], [54.942, -8993.722], [54.33, -9503.194], [53.228, -9900.778], [51.617, -9812.004], [49.266, -9620.005], [46.471, -9609.26], [43.288, -9329.185], [39.96, -9250.057], [36.341, -9366.431], [32.531, -9379.656], [28.688, -9408.648], [24.829, -9418.401], [20.988, -9513.613], [17.209, -9660.981], [13.48, -9622.327], [9.957, -9654.526], [6.484, -9772.297], [3.101, -9758.53], [-0.097, -9737.41], [-3.072, -9726.858], [-5.92, -9730.714], [-8.554, -9710.393], [-11.079, -9383.728], [-13.231, -9137.783], [-15.146, -8857.06], [-16.522, -8288.292], [-17.249, -7753.214], [-17.524, -6990.508], [-17.425, -6589.685], [-16.774, -6192.202], [-16.215, -5397.993], [-15.67, -4906.086], [-15.105, -4564.741], [-14.478, -4324.163], [-13.793, -4192.837], [-13.014, -4094.249], [-12.14, -3961.145], [-11.155, -3976.249], [-9.957, -4033.805], [-8.689, -4038.992], [-7.438, -4063.336], [-6.192, -3982.634], [-4.922, -3940.978], [-3.642, -3944.722], [-2.381, -3955.24], [-1.204, -4037.927], [-0.213, -4031.55], [0.623, -4048.03], [1.238, -3668.058], [2.166, -3223.797], [3.326, -3193.519], [4.675, -3049.454], [6.405, -2941.393], [8.566, -3218.628], [11.119, -3568.049], [13.674, -3672.504], [16.261, -3844.035], [18.726, -3851.298], [21.175, -3785.033], [23.526, -3837.698], [25.733, -3859.446], [27.746, -3803.885], [29.603, -3773.95], [31.459, -3777.372], [33.243, -3804.467], [34.927, -3828.283], [36.52, -3770.409], [38.017, -3681.814], [39.579, -3626.998], [41.175, -3641.395], [42.788, -3743.97], [44.416, -3937.624], [45.946, -4236.965], [47.175, -4377.768], [48.21, -4438.309], [48.838, -4537.2], [49.129, -4478.764], [49.196, -4308.402], [49.137, -4262.084], [49.143, -4247.508], [49.098, -4114.916], [49.084, -4100.473], [49.072, -4051.415], [49.196, -3999.507], [49.395, -4009.326], [49.634, -4000.167], [49.88, -3973.371], [50.084, -3918.636], [50.357, -3886.275], [50.697, -3936.03], [50.981, -4002.471], [51.209, -4039.17], [51.401, -4074.127], [51.553, -4057.877], [51.723, -4087.47], [52.184, -4223.707], [52.507, -4084.271], [53.238, -3994.224], [54.011, -3849.528], [54.93, -3743.578], [55.856, -3797.639], [56.748, -3817.357], [57.653, -3869.861], [58.552, -3891.538], [59.342, -3931.89], [60.089, -4015.883], [60.804, -4092.087]] + +# Tubing Movement Card +#downhole = [[46.83,-2887.081], [46.892,-2852.452], [46.914,-2878.963], [46.902,-2899.007], [46.927,-2914.736], [47.007,-3009.142], [47.098,-3044.16], [47.092,-2973.454], [47.047,-2927.351], [47.051,-2983.958], [47.026,-3072.558], [46.947,-3099.861], [46.85,-3086.603], [46.764,-3128.667], [46.706,-3222.279], [46.686,-3412.667], [46.643,-3492.5], [46.517,-3486.271], [46.347,-3520.645], [46.154,-3498.79], [45.943,-3570.53], [45.735,-3729.349], [45.457,-3834.83], [45.112,-3882.304], [44.779,-3951.678], [44.53,-4202.284], [44.259,-4344.169], [43.867,-4339.462], [43.489,-4462.086], [43.164,-4546.753], [42.917,-4713.565], [42.674,-4933.95], [42.349,-5087.896], [42.091,-5281.532], [41.858,-5409.675], [41.692,-5623.63], [41.597,-5789.314], [41.413,-5789.535], [41.212,-5854.792], [41.086,-5882.121], [41.039,-6019.487], [41.043,-6218.706], [40.973,-6308.513], [40.906,-6457.92], [40.837,-6594.607], [40.856,-6745.795], [40.883,-6767.062], [40.83,-6794.824], [40.797,-6933.782], [40.778,-6895.658], [40.822,-7034.814], [40.884,-7296.804], [40.818,-7419.478], [40.803,-7614.82], [40.776,-7751.075], [40.777,-8017.832], [40.764,-8241.186], [40.682,-8306.266], [40.554,-8463.126], [40.378,-8506.211], [40.272,-8608.049], [40.154,-8848.913], [39.906,-8996.566], [39.656,-9101.418], [39.305,-9067.18], [38.986,-9168.235], [38.634,-9203.583], [38.111,-9143.733], [37.598,-9187.537], [37.048,-9105.862], [36.496,-9175.496], [35.831,-9297.358], [35.077,-9295.168], [34.328,-9385.535], [33.5,-9417.49], [32.723,-9524.418], [31.903,-9543.187], [30.982,-9451.246], [30.098,-9542.783], [29.151,-9510.178], [28.189,-9502.326], [27.179,-9617.115], [26.052,-9694.688], [24.867,-9766.146], [23.598,-9761.514], [22.288,-9798.367], [20.981,-9780.708], [19.63,-9698.224], [18.306,-9740.019], [16.958,-9686.539], [15.724,-9736.812], [14.441,-9795.19], [13.139,-9681.094], [11.895,-9693.57], [10.726,-9760.314], [9.592,-9739.54], [8.484,-9680.257], [7.457,-9688.138], [6.545,-9698.494], [5.685,-9580.339], [4.955,-9585.38], [4.243,-9641.511], [3.558,-9554.533], [2.959,-9510.332], [2.426,-9502.439], [1.926,-9394.177], [1.461,-9293.815], [1.131,-9240.729], [0.896,-9156.458], [0.718,-9034.355], [0.661,-8899.793], [0.632,-8803.163], [0.698,-8727.494], [0.864,-8618.893], [1.119,-8519.666], [1.39,-8330.483], [1.644,-8299.007], [2,-8344.218], [2.361,-8159.301], [2.726,-8045.124], [3.063,-7967.46], [3.394,-7865.336], [3.799,-7748.28], [4.204,-7632.871], [4.584,-7505.887], [4.938,-7339.214], [5.354,-7351.317], [5.839,-7334.936], [6.263,-7134.111], [6.694,-7091.65], [7.063,-6987.825], [7.409,-6818.716], [7.799,-6755.144], [8.162,-6656.295], [8.528,-6602.11], [8.814,-6468.438], [9.062,-6377.223], [9.418,-6363.788], [9.772,-6233.713], [10.132,-6193.403], [10.371,-6052.44], [10.667,-5807.847], [11.056,-5740.982], [11.428,-5666.741], [11.749,-5544.153], [11.979,-5295.527], [12.207,-5178.551], [12.512,-5210.087], [12.812,-5150.446], [13.077,-5086.271], [13.292,-4886.025], [13.578,-4669.326], [13.871,-4606.906], [14.153,-4517.883], [14.414,-4369.183], [14.606,-4223.626], [14.854,-4204.487], [15.15,-4149.035], [15.382,-3974.269], [15.589,-3955.612], [15.735,-3888.778], [15.942,-3758.221], [16.219,-3730.551], [16.522,-3728.962], [16.78,-3677.023], [17.03,-3605.006], [17.333,-3618.731], [17.723,-3620.313], [18.111,-3588.642], [18.507,-3645.753], [18.835,-3584.838], [19.238,-3480.506], [19.803,-3500.618], [20.429,-3489.421], [21.043,-3439.612], [21.66,-3398.009], [22.274,-3438.254], [22.967,-3438.026], [23.667,-3442.973], [24.367,-3499.912], [25.087,-3420.673], [25.911,-3368.711], [26.764,-3426.286], [27.61,-3468.203], [28.469,-3448.212], [29.316,-3352.306], [30.161,-3336.477], [31.077,-3393.436], [31.987,-3440.532], [32.871,-3491.23], [33.721,-3432.89], [34.593,-3393.32], [35.456,-3425.981], [36.298,-3487.22], [37.115,-3508.692], [37.809,-3375.236], [38.502,-3342.76], [39.256,-3397.23], [39.94,-3387.344], [40.551,-3421.552], [41.078,-3365.214], [41.606,-3300.955], [42.124,-3340.255], [42.598,-3304.887], [43.053,-3276.992], [43.491,-3247.673], [43.861,-3218.775], [44.204,-3199.074], [44.529,-3187.272], [44.818,-3259.493], [45.008,-3241.877], [45.174,-3169.097], [45.358,-3180.797], [45.53,-3152.304], [45.695,-3142.974], [45.835,-3115.725], [45.945,-3071.782], [46.048,-2995.923], [46.18,-2967.381], [46.296,-3044.686], [46.328,-2969.671], [46.374,-2862.842], [46.437,-2863.76], [46.491,-2876.354], [46.561,-2888.627], [46.63,-2893.73], [46.688,-2844.868]] + +# Pumped Off Card +# downhole=[[46.62,-2712.68], [46.602,-2800.402], [46.534,-2764.056], [46.394,-2655.373], [46.263,-2651.785], [46.138,-2755.013], [45.999,-2767.18], [45.847,-2748.438], [45.736,-2776.021], [45.606,-2749.383], [45.465,-2784.358], [45.327,-2888.547], [45.14,-2896.921], [44.948,-2943.494], [44.79,-3047.353], [44.632,-3124.92], [44.491,-3203.635], [44.329,-3212.191], [44.211,-3351.46], [44.126,-3434.87], [43.893,-3402.475], [43.648,-3489.605], [43.373,-3496.714], [43.076,-3609.12], [42.726,-3652.814], [42.381,-3682.839], [42.109,-3868.039], [41.777,-4001.037], [41.381,-4092.478], [40.923,-4032.864], [40.407,-4011.32], [39.87,-4078.828], [39.252,-4021.814], [38.533,-4000.884], [37.709,-4023.979], [36.817,-4012.084], [35.884,-4119.401], [34.922,-4226.103], [33.985,-4364.747], [33.015,-4340.242], [31.772,-4084.583], [30.454,-4186.653], [29.164,-4334.347], [27.943,-4459.974], [26.647,-4724.885], [25.311,-4907.698], [24.035,-5196.977], [22.856,-5536.343], [21.915,-5988.342], [21.099,-6207.023], [20.393,-6277.558], [19.88,-6619.778], [19.636,-6877.075], [19.486,-7004.481], [19.361,-7169.644], [19.309,-7222.818], [19.293,-7321.001], [19.319,-7506.76], [19.38,-7669.473], [19.468,-7688.039], [19.452,-7580.956], [19.539,-7603.85], [19.69,-7499.871], [19.966,-7604.458], [20.234,-7987.768], [20.343,-8046.571], [20.515,-8010.688], [20.819,-8139.062], [21.135,-8352.702], [21.437,-8524.034], [21.635,-8747.591], [21.806,-9045.313], [21.887,-9210.366], [21.91,-9533.773], [21.765,-9970.918], [21.268,-10077.19], [20.656,-10106.954], [19.921,-10233.764], [18.956,-10184.094], [17.902,-10141.401], [16.742,-10103.894], [15.569,-9961.449], [14.364,-9788.658], [13.214,-9741.754], [11.959,-9742.078], [10.664,-9667.238], [9.451,-9661.859], [8.197,-9555.982], [6.951,-9387.272], [5.788,-9378.236], [4.736,-9395.63], [3.779,-9331.787], [2.846,-9178.237], [1.996,-9134.094], [1.157,-9067.718], [0.349,-8902.578], [-0.307,-8899.076], [-0.842,-8825.375], [-1.417,-8495.976], [-1.925,-8406.432], [-2.162,-8415.77], [-2.313,-8165.475], [-2.316,-7971.104], [-2.164,-7774.518], [-1.868,-7469.596], [-1.405,-7125.546], [-0.836,-6804.768], [-0.191,-6500.219], [0.427,-6154.017], [1.025,-5891.592], [1.71,-5692.756], [2.373,-5484.625], [2.975,-5384.557], [3.524,-5202.852], [4.052,-4905.002], [4.605,-4745.705], [5.159,-4676.503], [5.646,-4588.479], [6.087,-4447.826], [6.415,-4363.645], [6.781,-4308.298], [7.208,-4210.163], [7.607,-4341.792], [7.823,-4231.768], [8.1,-4013.293], [8.469,-4037.254], [8.784,-3968.269], [9.05,-3848.801], [9.317,-3704.935], [9.615,-3745.845], [9.999,-3745.517], [10.352,-3575.309], [10.728,-3533.071], [11.123,-3454.092], [11.655,-3307.476], [12.318,-3219.887], [13.053,-3125.011], [13.907,-3064.4], [14.821,-3024.716], [15.774,-3057.919], [16.851,-3077.195], [17.929,-3046.074], [19.11,-3149.958], [20.246,-3187.356], [21.4,-3081.013], [22.649,-3090.806], [23.927,-3123.975], [25.222,-3158.243], [26.47,-3109.859], [27.725,-3131.643], [29.074,-3250.88], [30.339,-3222.404], [31.573,-3276.256], [32.746,-3184.676], [33.961,-3054.106], [35.186,-3105.254], [36.363,-3140.104], [37.512,-3103.287], [38.66,-3028.344], [39.784,-3065.363], [40.878,-3106.046], [41.916,-3093.05], [42.889,-3138.815], [43.748,-3091.373], [44.615,-3086.79], [45.405,-3115.451], [46.112,-3065.278], [46.748,-3048.583], [47.3,-3038.282], [47.785,-3037.967], [48.197,-2976.641], [48.504,-2874.274], [48.737,-2905.508], [48.888,-2892.011], [49.067,-2823.676], [49.241,-2883.689], [49.346,-2879.874], [49.42,-2870.957], [49.467,-2926.496], [49.459,-2906.499]] + +scores = {"fullPump": 0, + "tubingMovement": 0, + "fluidPound": 0, + "gasInterference": 0, + "pumpTappingTop": 0, + "pumpTappingBottom": 0, + "bentBarrel": 0, + "wornPlunger": 0, + "wornStandingBill": 0, + "wornBarrel": 0, + "fluidFriction": 0, + "dragFriction": 0, + "rodPart": 0} + + +def printScores(): + print("Full Pump: {:.5f}".format(scores['fullPump'])) + print("Tubing Movement: {:.5f}".format(scores['tubingMovement'])) + print("Fluid Pound: {:.5f}".format(scores['fluidPound'])) + print("Gas Interference: {:.5f}".format(scores['gasInterference'])) + print("Pump Tapping - Top: {:.5f}".format(scores['pumpTappingTop'])) + print("Pump Tapping - Bottom: {:.5f}".format(scores['pumpTappingBottom'])) + print("Bent Barrel: {:.5f}".format(scores['bentBarrel'])) + print("Worn Plunger: {:.5f}".format(scores['wornPlunger'])) + print("Worn Standing Bill: {:.5f}".format(scores['wornStandingBill'])) + print("Worn Barrel: {:.5f}".format(scores['wornBarrel'])) + print("Fluid Friction: {:.5f}".format(scores['fluidFriction'])) + print("Drag Friction: {:.5f}".format(scores['dragFriction'])) + print("Rod Part: {:.5f}".format(scores['rodPart'])) + + +# helper functions +def __find_incremental_load(target_position, downholeArray, lastResult): + up_point_greater = [0, 0] + up_point_lesser = [0, 0] + down_point_greater = [0, 0] + down_point_lesser = [0, 0] + up_point_found = False + down_point_found = False + for ind in range(1, len(downholeArray)): + # print(downholeArray[i][0]) + if (downholeArray[ind][0] > target_position) and (downholeArray[ind - 1][0] <= target_position): + up_point_greater = [downholeArray[ind][0], downholeArray[ind][1]] + up_point_lesser = [downholeArray[ind - 1][0], downholeArray[ind - 1][1]] + up_point_found = True + if (downholeArray[ind][0] <= target_position) and (downholeArray[ind - 1][0] > target_position): + down_point_greater = [downholeArray[ind][0], downholeArray[ind][1]] + down_point_lesser = [downholeArray[ind - 1][0], downholeArray[ind - 1][1]] + down_point_found = True + if up_point_found & down_point_found: + 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, up_middle, down_middle] + else: + return lastResult + + +def __find_nearest_point_to_load(direction, card_half, target_load, ptArray, minPos, maxPos): + left_ignore = minPos + (minPos + maxPos) * 0.75 + right_ignore = minPos + (minPos + maxPos) * 0.25 + + if direction == "up": + for up_i in range(1, len(ptArray)): + if card_half == "right" and ptArray[up_i][0] >= right_ignore: + if (ptArray[up_i][1] <= target_load) & (ptArray[up_i - 1][1] > target_load): + return [ptArray[up_i][0], ptArray[up_i][1]] + elif card_half == "left" and ptArray[up_i][0] <= left_ignore: + if (ptArray[up_i][1] >= target_load) & (ptArray[up_i - 1][1] < target_load): + return [ptArray[up_i][0], ptArray[up_i][1]] + else: + for down_i in range(len(ptArray) - 1, 1, -1): + if card_half == "right" and ptArray[down_i][0] >= right_ignore: + if (ptArray[down_i][1] >= target_load) & (ptArray[down_i - 1][1] < target_load): + return [ptArray[down_i][0], ptArray[down_i][1]] + elif card_half == "left" and ptArray[down_i][0] <= left_ignore: + if (ptArray[down_i][1] <= target_load) & (ptArray[down_i - 1][1] > target_load): + return [ptArray[down_i][0], ptArray[down_i][1]] + + +def countPointsBetween(posLeft, posRight, dArray): + topPoints = 0 + bottomPoints = 0 + for l in range(1, len(dArray)): + if (dArray[l][0] > posLeft) and (dArray[l][0] <= posRight) and (dArray[l][0] < dArray[l - 1][0]): + topPoints += 1 + if (dArray[l][0] <= posRight) and (dArray[l - 1][0] > posLeft) and (dArray[l][0] > dArray[l - 1][0]): + bottomPoints += 1 + return [topPoints, bottomPoints] + + +def average(lis): + listsum = 0 + for avg_i in range(0, len(lis)): + listsum += lis[avg_i] + listavg = listsum / len(lis) + return listavg + + +def percentDiff(m1, m2): + mean = (m1 + m2) / 2 + dif = (m1 - m2) / mean + if dif < 0: + return -1 * dif + else: + return dif + + +def percentError(actual, expected): + err = (actual - expected) / expected + if err < 0: + return -1 * err + else: + return err + +# find min & max position +minPosition = downhole[0][0] +minPositionPt = [0, 0] +minLoad = downhole[0][1] +maxPosition = downhole[0][0] +maxPositionPt = [0, 0] +maxLoad = downhole[0][1] +for i in range(1, len(downhole)): + if downhole[i][0] < minPosition: + minPosition = downhole[i][0] + minPositionPt = downhole[i] + if downhole[i][0] > maxPosition: + maxPosition = downhole[i][0] + maxPositionPt = downhole[i] + if downhole[i][1] < minLoad: + minLoad = downhole[i][1] + if downhole[i][1] > maxLoad: + maxLoad = downhole[i][1] +downholeLoadSpan = maxLoad - minLoad + +# split cards into equal slices +sliceLength = (maxPosition - minPosition) / (slices + 1) +slicesAll = [] +topSlices = [] +topSlicesChange = [] +bottomSlices = [] +bottomSlicesChange = [] +sliceDelta = [] +sliceDeltaChange = [] +topPointsBetween = [] +bottomPointsBetween = [] +for j in range(0, slices): + targetPosition = j * sliceLength + minPosition + nextTargetPosition = (j + 1) * sliceLength + minPosition + + # measure points in each slice to look for fast/slow parts + ptb = countPointsBetween(targetPosition, nextTargetPosition, downhole) + topPointsBetween.append(ptb[0]) + bottomPointsBetween.append(ptb[1]) + + # interpret mean point of each slice + if j > 0: + sliver = __find_incremental_load(targetPosition, downhole, slicesAll[j - 1]) + else: + sliver = __find_incremental_load(targetPosition, downhole, [0, 0, 0]) + slicesAll.append(sliver) + sliceDelta.append(sliver[0]) + topSlices.append(sliver[1]) + bottomSlices.append(sliver[2]) + +for k in range(1, slices): + topSlicesChange.append(topSlices[k] - topSlices[k - 1]) + bottomSlicesChange.append(bottomSlices[k] - bottomSlices[k - 1]) + sliceDeltaChange.append(sliceDelta[k] - sliceDelta[k - 1]) + +topSlicesAverage = average(topSlices) +bottomSlicesAverage = average(bottomSlices) +sliceDeltaAverage = average(sliceDelta) + +# find Graph Corners +halfLoadLoad = minLoad + downholeLoadSpan / 2 +halfLoad = __find_nearest_point_to_load("up", "left", halfLoadLoad, downhole, minPosition, maxPosition) +if minPosition < halfLoad[0]: + corner_bottomLeft = minPositionPt + corner_topLeft = __find_nearest_point_to_load("up", "left", maxLoad - downholeLoadSpan * (pctTop / 100), downhole, + minPosition, maxPosition) +else: + corner_bottomLeft = __find_nearest_point_to_load("up", "left", minLoad + downholeLoadSpan * (pctBottom / 100), + downhole, minPosition, maxPosition) + corner_topLeft = minPositionPt +corner_topRight = maxPositionPt +corner_fillage = __find_nearest_point_to_load("up", "right", minLoad + downholeLoadSpan * (pctBottom / 100), downhole,minPosition, maxPosition) +corner_fullFillage = [corner_bottomLeft[0] + corner_topRight[0] - corner_topLeft[0], corner_bottomLeft[1]] + +topSlicesAboveAverage = [] +for i in range(0, len(topSlices)): + if topSlices[i] > topSlicesAverage: + topSlicesAboveAverage.append(topSlices[i]) +if len(topSlicesAboveAverage) == 0: + topSlicesAboveAverageAverage = topSlicesAverage +else: + topSlicesAboveAverageAverage = average(topSlicesAboveAverage) +bottomSlicesBelowAverage = [] +for i in range(0, len(bottomSlices)): + if bottomSlices[i] < bottomSlicesAverage: + bottomSlicesBelowAverage.append(bottomSlices[i]) +if len(bottomSlicesBelowAverage) == 0: + bottomSlicesBelowAverageAverage = bottomSlicesAverage +else: + bottomSlicesBelowAverageAverage = average(bottomSlicesBelowAverage) + +# find equation of line between fillage point and the top right +# y=mx+b +incompletionLineM = (bottomSlices[-1] - corner_fillage[1]) / ((maxPosition-2*sliceLength) - corner_fillage[0]) +incompletionLineB = bottomSlices[-1] - incompletionLineM * (maxPosition-2*sliceLength) +def poLine(pos): + return incompletionLineM * pos + incompletionLineB +# find slices in the pump-off part of the card +poSlicesTop = [] +poSlicesBottom = [] +poSlicePos = [] +for i in range(0,len(topSlices)): + poSlicePosTest = i * sliceLength + minPosition + if poSlicePosTest > corner_fillage[0]: + poSlicesBottom.append(bottomSlices[i]) + poSlicesTop.append(topSlices[i]) + poSlicePos.append(poSlicePosTest) + +# get score for each possible condition based on points. points (0-100) should reflect how closesly the pattern fits + +# check Full pump +# ------------------------------------ +scores['fullPump'] = round( + 100 * ((corner_fillage[0] - corner_bottomLeft[0]) / (corner_fullFillage[0] - corner_bottomLeft[0])), 5) +if scores['fullPump'] > 100.0: + scores['fullPump'] = 100.0 + +# topPctError = percentDiff(topSlicesAverage,topSlicesAboveAverageAverage) +# print("topPctError:", topPctError) +# bottomPctError = percentDiff(bottomSlicesAverage,bottomSlicesBelowAverageAverage) +# print('bottomPctError:', bottomPctError) +# scores['fullPump'] = round(100*(percentDiff((topPctError - bottomPctError),0.01)),5) + +# check tubing movement & drag friction +# ------------------------------------ + +leftCornerDiff = corner_topLeft[0] - corner_bottomLeft[0] +if leftCornerDiff > 0: + # indicates tubing movement + scores['dragFriction'] = 0.0 + if leftCornerDiff < (maxPosition - minPosition) * (tubingMovementPctStroke / 100): + scores['tubingMovement'] = round( + 100 * (1 - percentError(leftCornerDiff, (maxPosition - minPosition) * (tubingMovementPctStroke / 100))), 5) + else: + scores['tubingMovement'] = 100.0 +else: + # indicates drag friction + scores["tubingMovement"] = 0.0 + if abs(leftCornerDiff) < (maxPosition - minPosition) * (tubingMovementPctStroke / 100): + scores['dragFriction'] = round(100 * ( + 1 - percentError(abs(leftCornerDiff), (maxPosition - minPosition) * (tubingMovementPctStroke / 100))), 5) + else: + scores['dragFriction'] = 100.0 + +# Check Pump Tapping Top +# ------------------------------------ +if topSlices[len(topSlices) - 1] > topSlicesAboveAverageAverage: + scores['pumpTappingTop'] = 100 * percentDiff(topSlices[len(topSlices) - 1], minLoad + downholeLoadSpan * (pumpTapPercent/100)) +else: + scores['pumpTappingTop'] = 0.0 + +# Check Pump Tapping Bottom +# ------------------------------------ +if bottomSlices[len(bottomSlices) - 1] < bottomSlicesBelowAverageAverage: + scores['pumpTappingBottom'] = 100 * percentDiff(bottomSlices[len(bottomSlices) - 1], minLoad - downholeLoadSpan * (pumpTapPercent/100)) +else: + scores['pumpTappingBottom'] = 0.0 + +# check fluid pound & gas interference +# ------------------------------------ +distFromPOLine = [] +linear = [] +for i in range(0,len(poSlicePos)): + distFromPOLine.append(poSlicesBottom[i] - poLine(poSlicePos[i])) + linear.append(poLine(poSlicePos[i])) + +pRegC = np.polyfit(poSlicePos, poSlicesBottom, 3) +fitPOSlicesBottom = [] +for i in range(0, len(poSlicePos)): + fitPOSlicesBottom.append(pRegC[0] * poSlicePos[i]**3 + pRegC[1] * poSlicePos[i]**2 + pRegC[2] * poSlicePos[i] + pRegC[3]) +gradient1 = np.gradient(fitPOSlicesBottom) +gradient2 = np.gradient(gradient1) + +c2 = np.polyfit(poSlicePos, poSlicesBottom, 2) +c4 = np.polyfit(poSlicePos, poSlicesBottom, 4) +c5 = np.polyfit(poSlicePos, poSlicesBottom, 5) +c6 = np.polyfit(poSlicePos, poSlicesBottom, 6) + +c2g = [] +c4g = [] +c5g = [] +c6g = [] + +for i in range(0, len(poSlicePos)): + ps = poSlicePos[i] + c2g.append(c2[0] * ps**2 + c2[1] * ps + c2[2]) + c4g.append(c4[0] * ps**4 + c4[1] * ps**3 + c4[2] * ps**2 + c4[3] * ps + c4[4]) + c5g.append(c5[0] * ps**5 + c5[1] * ps**4 + c5[2] * ps**3 + c5[3] * ps**2 + c5[4] * ps + c5[5]) + c6g.append(c6[0] * ps**6 + c6[1] * ps**5 + c6[2] * ps**4 + c6[3] * ps**3 + c6[4] * ps**2 + c6[5] * ps + c6[6]) + + +inflectionPoint = [0,0] +for i in range(len(gradient2)-1, 0, -1): + if (gradient2[i-1] < 0) & (gradient2[i] > 0): + inflectionPoint = [poSlicePos[i], poSlicesBottom[i], i] +if inflectionPoint == [0,0]: + inflectionPoint = [poSlicePos[-1], poSlicesBottom[-1], len(poSlicePos)-1] + +inflectionLineM = (inflectionPoint[1] - corner_fillage[1]) / ((inflectionPoint[0]) - corner_fillage[0]) +inflectionLineB = inflectionPoint[1] - inflectionLineM * (inflectionPoint[0]) +def inflectionL(pos): + return inflectionLineM * pos + inflectionLineB + +inflectionLine = [] +for i in range(0,inflectionPoint[2]+1): + inflectionLine.append(inflectionL(poSlicePos[i])) +inflectionError = 0 +for i in range(0,len(inflectionLine)): + inflectionError += (poSlicesBottom[i] - inflectionLine[i]) * sliceLength +inflectionArea = (1/2) * (inflectionPoint[1] - corner_fillage[1]) * (inflectionPoint[0] - corner_fillage[0]) +inflectionGasInterferenceError = 1 - (inflectionError / inflectionArea) + +linearError = 0 +for i in range(0, len(distFromPOLine)): + linearError += distFromPOLine[i] * sliceLength +pumpOffArea = (1/2) * (corner_topRight[1] - corner_fillage[1]) * (corner_topRight[0] - corner_fillage[0]) +gasInterferenceError = 1 - (linearError / pumpOffArea) + +wellFriction = topSlicesAboveAverageAverage - inflectionPoint[1] +fluidLoad = downholeLoadSpan - wellFriction +print("Well Friction:", wellFriction) +print("Fluid Load:", fluidLoad) + +scores['gasInterference'] = inflectionGasInterferenceError * 100 +if scores['gasInterference'] > 100: + scores['gasInterference'] = 100.0 +scores['fluidPound'] = 100 - scores['gasInterference'] + +# check worn plunger +# ------------------------------------ + +# check worn standing bill +# ------------------------------------ + +# check worn barrel +# ------------------------------------ + +# check fluid friction +# ------------------------------------ + +# check rod part +# ------------------------------------ +if downholeLoadSpan < 1000: + scores['rodPart'] = 100 +elif downholeLoadSpan < 1500: + scores['rodPart'] = 75 +elif downholeLoadSpan < 1500: + scores['rodPart'] = 50 +elif downholeLoadSpan < 2000: + scores['rodPart'] = 25 +else: + scores['rodPart'] = 0 + + + + +# compare scores +printScores() +# Plot Card on graph +tpltPos = [] +tpltLod = [] +bpltPos = [] +bpltLod = [] +for i in range(0, len(topSlices)): + tpltLod.append(topSlices[i]) + tpltPos.append(minPosition + sliceLength * i) +for i in range(0, len(bottomSlices)): + bpltLod.append(bottomSlices[i]) + bpltPos.append(minPosition + sliceLength * i) + +fig = plt.figure(figsize=(12, 9)) +fig.canvas.set_window_title('Downhole Card Analysis') + +plt.plot(tpltPos, tpltLod, 'g') # plot top points +plt.plot(bpltPos, bpltLod, 'g') # plot bottom points + +# using linear error +# plt.plot([corner_fillage[0], corner_fillage[0],poSlicePos[-1],corner_fillage[0]],[corner_fillage[1],bottomSlices[-1], bottomSlices[-1],corner_fillage[1]],'y') +# plt.plot(poSlicePos, linear) + +# using inflection point error +plt.plot([corner_fillage[0], corner_fillage[0],inflectionPoint[0],corner_fillage[0]],[corner_fillage[1],inflectionPoint[1], inflectionPoint[1],corner_fillage[1]],'purple') +plt.plot(poSlicePos[0:len(inflectionLine)], inflectionLine, 'red') + +# average load lines +# plt.axhline(y=topSlicesAverage, xmin=0, xmax=1) +# plt.axhline(y=bottomSlicesAverage, xmin=0, xmax=1) +# plt.axhline(y=topSlicesAboveAverageAverage, xmin=0, xmax=1) +# plt.axhline(y=bottomSlicesBelowAverageAverage, xmin=0, xmax=1) + +# curve fit of pump-off +# plt.plot(poSlicePos, c2g, 'orange') +plt.plot(poSlicePos, fitPOSlicesBottom, 'b') +# plt.plot(poSlicePos, c4g, 'red') +# .plot(poSlicePos, c5g, 'brown') +# plt.plot(poSlicePos, c6g, 'purple') + +plt.grid(True) +plt.show() diff --git a/findCorners.py b/findCorners.py new file mode 100644 index 0000000..c43f9e6 --- /dev/null +++ b/findCorners.py @@ -0,0 +1,166 @@ +# Python program to analyze cards +import matplotlib.pyplot as plt +import readCardFile as rcf +import math +import os, sys + +def main(sl = 100): + # Setup Data + slices = int(sl) # number of horizontal slices to evaluate + #downhole = rcf.readFile("{0}/{1}".format(os.getcwd(), "testCard.csv"))[1] # read in CSV file output from POConsole/POCloud + downhole = rcf.readFile()[1] + num_points = len(downhole) + + dh_pos = list(map(lambda x: x[0], downhole)) + dh_pos_max = max(dh_pos) + dh_pos_min = min(dh_pos) + + dh_lod = list(map(lambda x: x[1], downhole)) + dh_lod_max = max(dh_lod) + dh_lod_min = min(dh_lod) + + max_p = (dh_pos_max, dh_lod[dh_pos.index(dh_pos_max)]) + min_p = (dh_pos_min, dh_lod[dh_pos.index(dh_pos_min)]) + + def determine_d_pos(min, max, num_slices): + return (max - min) / num_slices + + d_pos = determine_d_pos(dh_pos_min, dh_pos_max, slices) + + def distribute_positions(min, max, num_slices, dp): + """ distributes positions equally between the max and min values. Returns a list of positions """ + p_targ = [] + + for i in range(0, num_slices): + p_targ.append(min + i * dp) + return p_targ + + position_targets = distribute_positions(dh_pos_min, dh_pos_max, slices, d_pos) + + def lineresolve(x1,x2,y1,y2,targ): + m = ((y2-y1)/(x2-x1)) + b = y1 - m * x1 + return(m * targ + b) + + + def find_top_slices(): + """ finds the top slices of a card. Returns a list of (position,load) tuples""" + t_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) + t_slices.append((targ, fake_load)) + last_pos_index = found_i + break + return t_slices + + top_slices = find_top_slices() + print("== TOP ==") + for i in top_slices: + print("{0} - {1}".format(i[0], i[1])) + + def find_bot_slices(): + """ finds the top slices of a card. Returns a list of (position,load) tuples""" + b_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) + + b_slices.append((targ, fake_load)) + #last_pos_index = found_i + break + return b_slices + + bot_slices = find_bot_slices() + print("== BOTTOM ==") + for i in bot_slices: + print("{0} - {1}".format(i[0], i[1])) + + def distance_to_line(x0,y0): + """ Finds the perpendicular distance from a point to the line between max and min points""" + x1 = min_p[0] + x2 = max_p[0] + # y1 = min_p[1] + # y2 = max_p[1] + y1 = dh_lod_min + y2 = dh_lod_max + + 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 + + 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(distance_to_line(top_slices[i][0], top_slices[i][1])) + except Exception: + print("Error - top_d, index: {0}".format(i)) + + + try: + bot_d.append(distance_to_line(bot_slices[i][0], 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)) + top_corner = top_slices[top_cor_i] + bot_corner = bot_slices[bot_cor_i] + + tubing_movement = top_corner[0] - dh_pos_min + fillage = (bot_corner[0] - dh_pos_min)/(dh_pos_max - (dh_pos_min + tubing_movement)) * 100 + print("=================================================") + print("Tubing Movement: {0} in.".format(round(tubing_movement,3))) + print("Fill Percent: {0}%".format(round(fillage, 3))) + + + #determine difference between gas interference and incomplete fill + po_area = 0.0 + actual_area = 0.0 + bot_last = bot_slices[-1] + gas_line = [] + for i in range(bot_cor_i, len(bot_slices)): + gas_line_load = lineresolve(bot_corner[0], bot_last[0], bot_corner[1], bot_last[1], bot_slices[i][0]) + gas_line.append((bot_slices[i][0], gas_line_load)) + po_area = po_area + (bot_last[0] - gas_line_load) * d_pos + actual_area = actual_area + abs(gas_line_load - bot_slices[i][1]) * d_pos + area_ratio = actual_area / po_area + print ("\nFull Area: {0}\nActual Area: {1}".format(po_area, actual_area)) + print("\nIncomplete Fillage Score:{0}%\nGas Interference Score:{1}%".format(round(area_ratio*100,3), round((1-area_ratio)*100,3))) + + print("=================================================") + + + plt.figure() + plt.subplot(211) + plt.plot(list(map(lambda x: x[0], downhole)), list(map(lambda x: x[1], downhole)) ,'r') + plt.plot(list(map(lambda x: x[0], top_slices)), list(map(lambda x: x[1], top_slices)) ,'b') + plt.plot(list(map(lambda x: x[0], bot_slices)), list(map(lambda x: x[1], bot_slices)) ,'g') + plt.plot(list(map(lambda x: x[0], gas_line)), list(map(lambda x: x[1], gas_line)) ,'m') + + plt.subplot(212) + plt.plot(list(map(lambda x: x[0], top_slices))[1:], top_d ,'r') + plt.plot(list(map(lambda x: x[0], bot_slices))[1:], bot_d ,'y') + #ax2.axvline(x=top_corner[0]) + #ax2.axvline(x=bot_corner[0]) + + plt.grid(True) + plt.show() + +if __name__ == "__main__": + if len(sys.argv) > 1: + main(sys.argv[1]) + else: + main() diff --git a/readCardFile.py b/readCardFile.py new file mode 100644 index 0000000..211ea6c --- /dev/null +++ b/readCardFile.py @@ -0,0 +1,35 @@ +__author__ = 'patrickjmcd' + +import Tkinter as tk +import tkFileDialog as fd + +def readFile(file=None): + surface = [] + downhole = [] + if not file: + tk.Tk().withdraw() + file_path = fd.askopenfilename() + else: + file_path = file + + storeSurface = False + storeDownhole = False + import csv + with open(file_path, 'r') as csvfile: + dataReader = csv.reader(csvfile) + for row in dataReader: + if storeDownhole: + downhole.append((float(row[0]),float(row[1]))) + if row[0]=="d_pos": + storeSurface = False + storeDownhole = True + if storeSurface: + surface.append((float(row[0]),float(row[1]))) + if row[0]=="s_pos": + storeSurface = True + storeDownhole = False + + return [surface, downhole] + +# if __name__ == "__main__": +# readFile() diff --git a/regressionTesting/Example1/2ndOrder.png b/regressionTesting/Example1/2ndOrder.png new file mode 100644 index 0000000..4047003 Binary files /dev/null and b/regressionTesting/Example1/2ndOrder.png differ diff --git a/regressionTesting/Example1/2ndOrder_full.png b/regressionTesting/Example1/2ndOrder_full.png new file mode 100644 index 0000000..1862158 Binary files /dev/null and b/regressionTesting/Example1/2ndOrder_full.png differ diff --git a/regressionTesting/Example1/3rdOrder.png b/regressionTesting/Example1/3rdOrder.png new file mode 100644 index 0000000..df85ea2 Binary files /dev/null and b/regressionTesting/Example1/3rdOrder.png differ diff --git a/regressionTesting/Example1/3rdOrder_full.png b/regressionTesting/Example1/3rdOrder_full.png new file mode 100644 index 0000000..3f1ba9b Binary files /dev/null and b/regressionTesting/Example1/3rdOrder_full.png differ diff --git a/regressionTesting/Example1/4thOrder.png b/regressionTesting/Example1/4thOrder.png new file mode 100644 index 0000000..86ed09a Binary files /dev/null and b/regressionTesting/Example1/4thOrder.png differ diff --git a/regressionTesting/Example1/4thOrder_full.png b/regressionTesting/Example1/4thOrder_full.png new file mode 100644 index 0000000..be42f68 Binary files /dev/null and b/regressionTesting/Example1/4thOrder_full.png differ diff --git a/regressionTesting/Example1/5thOrder.png b/regressionTesting/Example1/5thOrder.png new file mode 100644 index 0000000..342b05e Binary files /dev/null and b/regressionTesting/Example1/5thOrder.png differ diff --git a/regressionTesting/Example1/5thOrder_full.png b/regressionTesting/Example1/5thOrder_full.png new file mode 100644 index 0000000..c242dc5 Binary files /dev/null and b/regressionTesting/Example1/5thOrder_full.png differ diff --git a/regressionTesting/Example1/6thOrder.png b/regressionTesting/Example1/6thOrder.png new file mode 100644 index 0000000..4681c65 Binary files /dev/null and b/regressionTesting/Example1/6thOrder.png differ diff --git a/regressionTesting/Example1/6thOrder_full.png b/regressionTesting/Example1/6thOrder_full.png new file mode 100644 index 0000000..9ff8f62 Binary files /dev/null and b/regressionTesting/Example1/6thOrder_full.png differ diff --git a/regressionTesting/Example2/2ndOrder.png b/regressionTesting/Example2/2ndOrder.png new file mode 100644 index 0000000..0aa389f Binary files /dev/null and b/regressionTesting/Example2/2ndOrder.png differ diff --git a/regressionTesting/Example2/2ndOrder_full.png b/regressionTesting/Example2/2ndOrder_full.png new file mode 100644 index 0000000..8e7cf44 Binary files /dev/null and b/regressionTesting/Example2/2ndOrder_full.png differ diff --git a/regressionTesting/Example2/3rdOrder.png b/regressionTesting/Example2/3rdOrder.png new file mode 100644 index 0000000..a5a40d3 Binary files /dev/null and b/regressionTesting/Example2/3rdOrder.png differ diff --git a/regressionTesting/Example2/3rdOrder_full.png b/regressionTesting/Example2/3rdOrder_full.png new file mode 100644 index 0000000..41da4bf Binary files /dev/null and b/regressionTesting/Example2/3rdOrder_full.png differ diff --git a/regressionTesting/Example2/4thOrder.png b/regressionTesting/Example2/4thOrder.png new file mode 100644 index 0000000..88e0d25 Binary files /dev/null and b/regressionTesting/Example2/4thOrder.png differ diff --git a/regressionTesting/Example2/4thOrder_full.png b/regressionTesting/Example2/4thOrder_full.png new file mode 100644 index 0000000..b1bd2dc Binary files /dev/null and b/regressionTesting/Example2/4thOrder_full.png differ diff --git a/regressionTesting/Example2/5thOrder.png b/regressionTesting/Example2/5thOrder.png new file mode 100644 index 0000000..5af3e9c Binary files /dev/null and b/regressionTesting/Example2/5thOrder.png differ diff --git a/regressionTesting/Example2/5thOrder_full.png b/regressionTesting/Example2/5thOrder_full.png new file mode 100644 index 0000000..b807f5e Binary files /dev/null and b/regressionTesting/Example2/5thOrder_full.png differ diff --git a/regressionTesting/Example2/6thOrder.png b/regressionTesting/Example2/6thOrder.png new file mode 100644 index 0000000..ad37340 Binary files /dev/null and b/regressionTesting/Example2/6thOrder.png differ diff --git a/regressionTesting/Example2/6thOrder_full.png b/regressionTesting/Example2/6thOrder_full.png new file mode 100644 index 0000000..fb5d029 Binary files /dev/null and b/regressionTesting/Example2/6thOrder_full.png differ diff --git a/testCard.csv b/testCard.csv new file mode 100644 index 0000000..cc597f9 --- /dev/null +++ b/testCard.csv @@ -0,0 +1,227 @@ +"localtime","2015-11-04 12:15:09.439141" +"utctime","2015-11-04 18:15:09.439141" +"Card_ID","6372" +"Num_Tapers","3" +"Num_Points","99" +"Card_Type","0" +"Well_Name","Denise1601" +"Tubing_Head_Pressure","50.0" +"Fluid_Gradient","0.44999998807907104" +"Stuffing_Box_Friction","100.0" +"dt","0.07500000298023224" +"Downhole_Max_Load","-526.87939453125" +"Downhole_Min_Load","-7897.5439453125" +"Downhole_Max_Position","60.587005615234375" +"Downhole_Min_Position","-24.125038146972656" +"Downhole_Gross_Stroke","84.71204376220703" +"Downhole_Adjusted_Gross_Stroke","84.7914047241211" +"Downhole_Net_Stroke","55.0130615234375" +"Downhole_Fluid_Load","4686.138671875" +"Surface_Max_Load","19870.0" +"Surface_Min_Load","14372.0" +"Surface_Max_Position","102.35242462158203" +"Surface_Min_Position","-0.04880121350288391" +"Tubing_Movement","-0.07936454564332962" +"Surface_Stroke_Length","102.4012222290039" +"Fillage_Percent","64.3893814086914" +"Polished_Rod_HP","3.1364829540252686" +"Pump_HP","2.222397804260254" +"SPM","8.080738067626953" +"Fluid_Above_Pump","6301.8017578125" +"Stroke_Production","0.02783350832760334" +"s_pos","s_load" +"93.398","17086.0" +"91.515","17048.0" +"89.589","16972.0" +"87.589","16841.0" +"85.512","16707.0" +"83.053","16561.0" +"80.681","16466.0" +"78.327","16409.0" +"75.429","16390.0" +"72.627","16374.001" +"70.131","16332.0" +"66.977","16227.0" +"63.972","16076.0" +"61.077","15845.0" +"57.669","15613.0" +"54.186","15379.0" +"50.876","15128.0" +"47.587","14885.0" +"44.252","14653.0" +"40.975","14337.0" +"37.813","14001.0" +"34.284","13556.0" +"30.98","13136.0" +"27.847","12673.999" +"24.425","12333.0" +"21.17","12051.0" +"18.27","11903.0" +"15.414","11819.0" +"12.557","11795.0" +"10.132","11799.0" +"7.927","11820.0" +"5.754","11865.999" +"4.089","11937.999" +"2.545","12075.0" +"1.339","12260.0" +"0.472","12556.0" +"-0.074","12889.0" +"-0.368","13345.999" +"-0.25","13801.0" +"-0.049","14372.0" +"0.426","14897.0" +"1.341","15501.0" +"2.357","16015.0" +"3.497","16577.0" +"5.109","17047.0" +"6.8","17569.0" +"8.502","18011.0" +"10.679","18480.0" +"12.965","18832.0" +"15.086","19136.0" +"17.612","19302.0" +"20.242","19378.0" +"22.824","19364.0" +"25.506","19282.0" +"28.503","19190.0" +"31.475","19116.0" +"33.923","19127.0" +"36.863","19247.0" +"39.621","19427.0" +"41.982","19650.0" +"44.881","19800.0" +"47.613","19870.0" +"50.177","19835.0" +"52.751","19720.0" +"55.53","19604.0" +"58.111","19511.0" +"60.527","19486.0" +"63.239","19514.0" +"65.704","19561.0" +"68.063","19602.0" +"70.593","19597.0" +"73.05","19517.0" +"75.196","19378.0" +"77.563","19163.0" +"79.977","18972.0" +"82.256","18803.0" +"84.429","18727.0" +"86.889","18717.0" +"89.117","18746.0" +"91.097","18771.0" +"93.252","18745.0" +"95.093","18637.0" +"96.677","18484.0" +"98.182","18282.0" +"99.385","18119.0" +"100.338","17983.0" +"101.113","17919.0" +"101.72","17908.0" +"102.111","17931.0" +"102.352","17957.0" +"102.351","17941.0" +"101.965","17849.0" +"101.524","17704.0" +"100.899","17496.0" +"100.143","17314.0" +"99.199","17151.0" +"98.041","17066.0" +"d_pos","d_load" +"60.986","-1421.341" +"61.18","-1630.285" +"61.098","-1723.069" +"60.894","-1816.997" +"60.518","-1893.947" +"59.96","-1743.353" +"59.262","-1684.411" +"58.597","-1797.25" +"57.767","-1847.692" +"56.769","-2028.492" +"55.666","-2365.939" +"54.4","-2577.627" +"52.854","-2681.227" +"51.205","-2890.279" +"49.477","-2904.455" +"47.627","-2769.189" +"45.85","-3007.649" +"44.143","-3272.492" +"42.433","-3451.081" +"40.817","-4005.708" +"39.223","-4469.438" +"37.615","-4626.933" +"36.149","-5001.764" +"34.751","-5299.257" +"33.517","-5367.123" +"32.486","-5578.117" +"31.658","-5912.868" +"31.018","-6186.276" +"30.5","-6477.536" +"29.881","-6812.0" +"29.256","-6948.168" +"28.537","-6880.609" +"27.816","-6962.176" +"27.003","-7007.687" +"26.076","-6916.81" +"25.058","-7059.85" +"23.881","-7302.985" +"22.482","-7429.931" +"20.864","-7667.682" +"18.99","-7897.544" +"16.687","-7720.645" +"14.287","-7572.63" +"11.679","-7466.455" +"8.855","-7031.728" +"5.906","-6759.008" +"2.991","-6597.28" +"-0.217","-6196.185" +"-3.22","-6081.894" +"-6.359","-5920.985" +"-9.479","-5484.665" +"-12.556","-5238.389" +"-15.253","-5103.293" +"-17.768","-4894.909" +"-19.836","-4836.033" +"-21.658","-4788.491" +"-22.939","-4528.13" +"-23.794","-4188.902" +"-24.125","-3951.927" +"-23.994","-3569.314" +"-23.434","-3062.452" +"-22.585","-2650.886" +"-21.336","-2287.333" +"-19.872","-1719.896" +"-18.173","-1279.187" +"-16.214","-1101.919" +"-14.06","-748.781" +"-11.811","-526.879" +"-9.409","-646.94" +"-6.948","-617.908" +"-4.416","-720.337" +"-1.873","-1075.932" +"0.549","-1190.441" +"2.945","-1081.959" +"5.33","-1000.862" +"7.835","-898.726" +"10.543","-717.542" +"13.399","-720.939" +"16.366","-904.753" +"19.423","-969.946" +"22.449","-1055.779" +"25.41","-1216.705" +"28.249","-1172.759" +"31.03","-1007.448" +"33.73","-931.535" +"36.425","-849.579" +"39.053","-669.859" +"41.666","-690.598" +"44.192","-843.798" +"46.608","-885.599" +"48.878","-1064.131" +"50.934","-1207.103" +"52.612","-991.171" +"54.205","-885.51" +"55.582","-811.091" +"56.797","-643.467" +"57.951","-725.744" +"58.99","-867.17" diff --git a/upstrokeDownstroke.py b/upstrokeDownstroke.py new file mode 100644 index 0000000..5c6b188 --- /dev/null +++ b/upstrokeDownstroke.py @@ -0,0 +1,35 @@ +import readCardFile as rcf +import matplotlib.pyplot as plt + +downhole = rcf.readFile()[1] + +upstroke = [] +downstroke = [] +mUp = False + +for i in range (2,len(downhole)-1): + if downhole[i][0] > downhole[i-1][0]: + upstroke.append(downhole[i]) + mUp = True + elif downhole[i][0] < downhole[i-1][0]: + downstroke.append(downhole[i]) + mUp = False + else: + if mUp: + upstroke.append(downhole[i]) + else: + downstroke.append(downhole[i]) + + +p,l = zip(*downhole) +uP, uL = zip(*upstroke) +dP,dL = zip(*downstroke) + + +fig = plt.figure(figsize=(12, 9)) +fig.canvas.set_window_title('Downhole Card Analysis') +plt.plot(p,l,'g') +plt.plot(uP, uL, 'b') +plt.plot(dP, dL, 'r') +plt.grid(True) +plt.show() diff --git a/wellInflow.py b/wellInflow.py new file mode 100644 index 0000000..807e535 --- /dev/null +++ b/wellInflow.py @@ -0,0 +1,21 @@ +'''Well Inflow Calculator''' +import math + +def annulusCrossSectionalArea(id, od): + '''Calculates cross-sectional area of an annulus''' + return math.pi/4*(math.pow(od,2)-math.pow(id,2)) + +bblPerIn3 = 0.00010307 + +casingID = 5.0 +tubingOD = 2.375 + +dailyProduction = 13.36 #BBL +fluidLevelChange = -23.0 #ft +fluidLevelChangeInches = fluidLevelChange * 12.0 +casingAnnulusArea = annulusCrossSectionalArea(tubingOD, casingID) + +wellInflowBBL = fluidLevelChangeInches * casingAnnulusArea * bblPerIn3 + dailyProduction +print ("Inflow:",wellInflowBBL, "BBL") +wellInflowRate = wellInflowBBL / 24.0 +print ("Inflow Rate:", wellInflowRate, "BBL/HR") diff --git a/wholeCardRegression.py b/wholeCardRegression.py new file mode 100644 index 0000000..9503111 --- /dev/null +++ b/wholeCardRegression.py @@ -0,0 +1,165 @@ +# Python program to analyze cards +import matplotlib.pyplot as plt +import numpy as np +import readCardFile as rcf +import math + +# Setup Data +slices = 250 # number of horizontal slices to evaluate +regN = 10 # regression level + +downhole = rcf.readFile()[1] # read in CSV file output from POConsole/POCloud + +# helper functions +def __find_incremental_load(target_position, downholeArray, lastResult): + up_point_greater = [0, 0] + up_point_lesser = [0, 0] + down_point_greater = [0, 0] + down_point_lesser = [0, 0] + up_point_found = False + down_point_found = False + for ind in range(1, len(downholeArray)): + # print(downholeArray[i][0]) + if (downholeArray[ind][0] > target_position) and (downholeArray[ind - 1][0] <= target_position): + up_point_greater = [downholeArray[ind][0], downholeArray[ind][1]] + up_point_lesser = [downholeArray[ind - 1][0], downholeArray[ind - 1][1]] + up_point_found = True + if (downholeArray[ind][0] <= target_position) and (downholeArray[ind - 1][0] > target_position): + down_point_greater = [downholeArray[ind][0], downholeArray[ind][1]] + down_point_lesser = [downholeArray[ind - 1][0], downholeArray[ind - 1][1]] + down_point_found = True + if up_point_found & down_point_found: + 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, up_middle, down_middle] + else: + return lastResult + +def findLine(x1,y1,x2,y2): # finds the slope and intercept of a line between two points + m = (y2-y1)/(x2-x1) + b = y1 - m*x1 + return(m,b) + +def vectorDist(x1,y1,x2,y2): + return math.sqrt((x2-x1)**2 + (y2-y1)**2) + +def perpDist(x,y,m,b): + # line as mx+b + return abs(m*x + (-1) * y + b) / math.sqrt( m**2 + (-1)**2) + + +# find min & max position +minPosition = min(downhole, key = lambda x:x[0]) +minLoad = min(downhole, key = lambda x:x[1]) +maxPosition = max(downhole, key = lambda x:x[0]) +maxLoad = max(downhole, key = lambda x:x[1]) +downholeLoadSpan = maxLoad[1] - minLoad[1] + +# split cards into equal slices +sliceLength = (maxPosition[0] - minPosition[0]) / (slices + 1) +slicesAll = [] +topSlices = [] +bottomSlices = [] +sliceDelta = [] +posSlices = [] +for j in range(0, slices): + targetPosition = j * sliceLength + minPosition[0] + nextTargetPosition = (j + 1) * sliceLength + minPosition[0] + + # interpret mean point of each slice + if j > 0: + sliver = __find_incremental_load(targetPosition, downhole, slicesAll[j - 1]) + else: + sliver = __find_incremental_load(targetPosition, downhole, [0, 0, 0]) + slicesAll.append(sliver) + sliceDelta.append(sliver[0]) + topSlices.append(sliver[1]) + bottomSlices.append(sliver[2]) + posSlices.append(targetPosition) + + + +topC = np.polyfit(posSlices, topSlices, regN) +botC = np.polyfit(posSlices, bottomSlices, regN) + +topReg = [] +botReg = [] + +for i in range(0,len(posSlices)): + x = posSlices[i] + tr = 0 + br = 0 + for j in range(0,regN+1): + tr += topC[j] * x**(regN-j) + br += botC[j] * x**(regN-j) + topReg.append(tr) + botReg.append(br) + +p,l = zip(*downhole) + +(tm,tb) = findLine(posSlices[0], topSlices[0], posSlices[-1], topSlices[-1]) +(bm,bb) = findLine(posSlices[0], bottomSlices[0], posSlices[-1], bottomSlices[-1]) + +#(tm,tb) = findLine(minPosition[0], minPosition[1], maxPosition[0], maxPosition[1]) +#(bm,bb) = findLine(minPosition[0], minPosition[1], maxPosition[0], maxPosition[1]) + +linePos = np.linspace(posSlices[0], posSlices[-1], len(posSlices)) + + + +topDist = [] +bottomDist = [] +tLine = [] +bLine = [] +corner_topLeft = (0, 0) +corner_fillage = (0, 0) +maxTopDist = 0.0 +maxBotDist = 0.0 +for i in range(0, len(posSlices)): + tLineY = linePos[i] * tm + tb + #td = vectorDist(posSlices[i], topSlices[i], linePos[i], tLineY) + td = perpDist(posSlices[i], topSlices[i], tm, tb) + topDist.append(td) + tLine.append(tLineY) + if td > maxTopDist: + maxTopDist = td + corner_topLeft = (posSlices[i], topSlices[i]) + tLine.append(tLineY) + + bLineY = linePos[i] * bm + bb + #bd = vectorDist(posSlices[i], bottomSlices[i], linePos[i], bLineY) + bd = perpDist(posSlices[i], bottomSlices[i], bm, bb) + bLine.append(bLineY) + bottomDist.append(bd) + if bd > maxBotDist: + maxBotDist = bd + corner_fillage = (posSlices[i], bottomSlices[i]) + +fillPercent = (corner_fillage[0] - minPosition[0])/(maxPosition[0] - corner_topLeft[0]) * 100 +print("Fill:", fillPercent) + + +fig = plt.figure(figsize=(12, 9)) +fig.canvas.set_window_title('Downhole Card Analysis') + +# plt.plot(p, l, 'g') # plot actual card +plt.plot(posSlices, topSlices, 'r') # plot bottom points +plt.plot(posSlices, bottomSlices, 'r') # plot bottom points + +# plt.plot(posSlices, topReg, 'b') +# plt.plot(posSlices, botReg, 'b') +# plt.plot(posSlices, topDist, 'y') +# plt.plot(posSlices, bottomDist, 'g') +plt.axvline(x=corner_topLeft[0]) +plt.axvline(x=corner_fillage[0]) +# plt.plot(linePos, tLine, 'orange') +# plt.plot(linePos, bLine, 'purple') + +plt.grid(True) +plt.show()