Able to run simulations of cards
This commit is contained in:
@@ -13,6 +13,7 @@ classdef AnalogInput < handle
|
|||||||
|
|
||||||
properties(Access=private)
|
properties(Access=private)
|
||||||
m,b;
|
m,b;
|
||||||
|
histi;
|
||||||
end
|
end
|
||||||
|
|
||||||
methods
|
methods
|
||||||
@@ -23,17 +24,23 @@ classdef AnalogInput < handle
|
|||||||
obj.rawMax = double(rawMax);
|
obj.rawMax = double(rawMax);
|
||||||
obj.euMin = double(euMin);
|
obj.euMin = double(euMin);
|
||||||
obj.euMax = double(euMax);
|
obj.euMax = double(euMax);
|
||||||
|
obj.histi = 0;
|
||||||
|
|
||||||
obj.m = (obj.euMax - obj.euMin) / (obj.rawMax - obj.rawMin);
|
obj.m = (obj.euMax - obj.euMin) / (obj.rawMax - obj.rawMin);
|
||||||
obj.b = obj.euMax - obj.m * (obj.rawMax);
|
obj.b = obj.euMax - obj.m * (obj.rawMax);
|
||||||
end
|
end
|
||||||
|
|
||||||
function value = setValue(obj, inValue)
|
function value = setValue(obj, inValue)
|
||||||
|
obj.histi = obj.histi + 1;
|
||||||
obj.rawValue = inValue;
|
obj.rawValue = inValue;
|
||||||
value = obj.m * inValue + obj.b;
|
value = obj.m * inValue + obj.b;
|
||||||
obj.lastValue = value;
|
obj.lastValue = value;
|
||||||
obj.lastStored = now;
|
obj.lastStored = now;
|
||||||
obj.history = [value, obj.history(1:end-1)];
|
|
||||||
|
% Store value in history array
|
||||||
|
histTemp = obj.history(1:end-1);
|
||||||
|
obj.history(2:end) = histTemp;
|
||||||
|
obj.history(1) = value;
|
||||||
end
|
end
|
||||||
|
|
||||||
function value = read(obj)
|
function value = read(obj)
|
||||||
@@ -47,15 +54,12 @@ classdef AnalogInput < handle
|
|||||||
end
|
end
|
||||||
|
|
||||||
if (obj.badReads > 10)
|
if (obj.badReads > 10)
|
||||||
"Bad Reads"
|
|
||||||
obj.badReads
|
|
||||||
pause(0.010);
|
pause(0.010);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function value = readSim(obj, simRaw)
|
function value = readSim(obj, simRaw)
|
||||||
value = obj.m * simRaw + obj.b;
|
value = obj.m * simRaw + obj.b;
|
||||||
obj.lastValue = pv;
|
|
||||||
obj.lastValue = value;
|
obj.lastValue = value;
|
||||||
obj.lastStored = now;
|
obj.lastStored = now;
|
||||||
obj.history = [value, obj.history(1:end-1)];
|
obj.history = [value, obj.history(1:end-1)];
|
||||||
|
|||||||
50
AnalogInputSim.m
Normal file
50
AnalogInputSim.m
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
classdef AnalogInputSim < handle
|
||||||
|
properties
|
||||||
|
mux;
|
||||||
|
channel;
|
||||||
|
rawValue;
|
||||||
|
lastValue;
|
||||||
|
lastStored=0;
|
||||||
|
rawMax,rawMin,euMax,euMin;
|
||||||
|
history=zeros(1, 100, 'double');
|
||||||
|
badReads=0;
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
properties(Access=private)
|
||||||
|
m,b;
|
||||||
|
end
|
||||||
|
|
||||||
|
methods
|
||||||
|
function obj = AnalogInputSim(mux, channel, rawMin, rawMax, euMin, euMax)
|
||||||
|
obj.mux = mux;
|
||||||
|
obj.channel = channel;
|
||||||
|
obj.rawMin = double(rawMin);
|
||||||
|
obj.rawMax = double(rawMax);
|
||||||
|
obj.euMin = double(euMin);
|
||||||
|
obj.euMax = double(euMax);
|
||||||
|
|
||||||
|
obj.m = (obj.euMax - obj.euMin) / (obj.rawMax - obj.rawMin);
|
||||||
|
obj.b = obj.euMax - obj.m * (obj.rawMax);
|
||||||
|
end
|
||||||
|
|
||||||
|
function value = setValue(obj, inValue)
|
||||||
|
obj.rawValue = inValue;
|
||||||
|
value = obj.m * inValue + obj.b;
|
||||||
|
obj.lastValue = value;
|
||||||
|
obj.lastStored = now;
|
||||||
|
obj.history = [value, obj.history(1:end-1)];
|
||||||
|
end
|
||||||
|
|
||||||
|
function value = read(obj, simRaw)
|
||||||
|
value = obj.m * simRaw + obj.b;
|
||||||
|
obj.lastValue = value;
|
||||||
|
obj.lastStored = now;
|
||||||
|
|
||||||
|
% Store value in history array
|
||||||
|
histTemp = obj.history(1:end-1);
|
||||||
|
obj.history(2:end) = histTemp;
|
||||||
|
obj.history(1) = value;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
55
Card.m
55
Card.m
@@ -65,7 +65,7 @@ classdef Card < handle
|
|||||||
anchorDepth, tubingCSA, pumpArea, frictionEstimate, ...
|
anchorDepth, tubingCSA, pumpArea, frictionEstimate, ...
|
||||||
structuralRating, kFactor, waterBBLRatio, oilBBLRatio, ...
|
structuralRating, kFactor, waterBBLRatio, oilBBLRatio, ...
|
||||||
gasMCFRatio)
|
gasMCFRatio)
|
||||||
calculateSPM();
|
obj.calculateSPM();
|
||||||
obj.surfacePositionMax = obj.positionMax(obj.surfacePosition, obj.surfaceLoad, obj.numPointsUsed);
|
obj.surfacePositionMax = obj.positionMax(obj.surfacePosition, obj.surfaceLoad, obj.numPointsUsed);
|
||||||
obj.surfaceLoadMax = obj.loadMax(obj.surfacePosition, obj.surfaceLoad, obj.numPointsUsed);
|
obj.surfaceLoadMax = obj.loadMax(obj.surfacePosition, obj.surfaceLoad, obj.numPointsUsed);
|
||||||
obj.surfacePositionMin = obj.positionMin(obj.surfacePosition, obj.surfaceLoad, obj.numPointsUsed);
|
obj.surfacePositionMin = obj.positionMin(obj.surfacePosition, obj.surfaceLoad, obj.numPointsUsed);
|
||||||
@@ -96,21 +96,21 @@ classdef Card < handle
|
|||||||
dhLoadAtTargetTop = 0.0;
|
dhLoadAtTargetTop = 0.0;
|
||||||
dhLoadAtTargetBottom = 0.0;
|
dhLoadAtTargetBottom = 0.0;
|
||||||
|
|
||||||
for j = 1:obj.numPointsUsed
|
for j = 1:obj.numPointsUsed-1
|
||||||
if (obj.downholePosition(j) <= dhPosTarget && obj.downholePosition(j+1) > dhPosTarget)
|
if (obj.downholePosition(j) <= dhPosTarget && obj.downholePosition(j+1) > dhPosTarget)
|
||||||
dhLoadAtTargetTop = lineResolve(obj.downholePosition(j), obj.downholePosition(j+1), obj.downholeLoad(j), obj.downholeLoad(j+1), dhPosTarget);
|
dhLoadAtTargetTop = obj.lineResolve(obj.downholePosition(j), obj.downholePosition(j+1), obj.downholeLoad(j), obj.downholeLoad(j+1), dhPosTarget);
|
||||||
end
|
end
|
||||||
|
|
||||||
if (obj.downholePosition(j) > dhPosTarget && obj.downholePosition(j+1) >= dhPosTarget)
|
if (obj.downholePosition(j) > dhPosTarget && obj.downholePosition(j+1) >= dhPosTarget)
|
||||||
dhLoadAtTargetBottom = lineResolve(obj.downholePosition(j), obj.downholePosition(j+1), obj.downholeLoad(j), obj.downholeLoad(j+1), dhPosTarget);
|
dhLoadAtTargetBottom = obj.lineResolve(obj.downholePosition(j), obj.downholePosition(j+1), obj.downholeLoad(j), obj.downholeLoad(j+1), dhPosTarget);
|
||||||
end
|
end
|
||||||
|
|
||||||
if (obj.surfacePosition(j) <= suPosTarget && obj.surfacePosition(j+1) > suPosTarget)
|
if (obj.surfacePosition(j) <= suPosTarget && obj.surfacePosition(j+1) > suPosTarget)
|
||||||
suLoadAtTargetTop = lineResolve(obj.surfacePosition(j), obj.surfacePosition(j+1), obj.surfaceLoad(j), obj.surfaceLoad(j+1), suPosTarget);
|
suLoadAtTargetTop = obj.lineResolve(obj.surfacePosition(j), obj.surfacePosition(j+1), obj.surfaceLoad(j), obj.surfaceLoad(j+1), suPosTarget);
|
||||||
end
|
end
|
||||||
|
|
||||||
if (obj.surfacePosition(j) > suPosTarget && obj.surfacePosition(j+1) >= suPosTarget)
|
if (obj.surfacePosition(j) > suPosTarget && obj.surfacePosition(j+1) >= suPosTarget)
|
||||||
suLoadAtTargetBottom = lineResolve(obj.surfacePosition(j), obj.surfacePosition(j+1), obj.surfaceLoad(j), obj.surfaceLoad(j+1), suPosTarget);
|
suLoadAtTargetBottom = obj.lineResolve(obj.surfacePosition(j), obj.surfacePosition(j+1), obj.surfaceLoad(j), obj.surfaceLoad(j+1), suPosTarget);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -135,11 +135,11 @@ classdef Card < handle
|
|||||||
obj.downholeNetStrokeLength = obj.bottomCorner.position - obj.downholePositionMin.position;
|
obj.downholeNetStrokeLength = obj.bottomCorner.position - obj.downholePositionMin.position;
|
||||||
obj.fillageCalculated = (obj.downholeNetStrokeLength / obj.downholeAdjustedGrossStrokeLength) * 100.0;
|
obj.fillageCalculated = (obj.downholeNetStrokeLength / obj.downholeAdjustedGrossStrokeLength) * 100.0;
|
||||||
obj.fillageEstimated =(obj.downholeNetStrokeLength / obj.downholeGrossStrokeLength) * 100.0;
|
obj.fillageEstimated =(obj.downholeNetStrokeLength / obj.downholeGrossStrokeLength) * 100.0;
|
||||||
obj.fluidBBLMoved = obj.downholeNetStrokeLength * pumpArea * 0.00010307;
|
obj.fluidBblMoved = obj.downholeNetStrokeLength * pumpArea * 0.00010307;
|
||||||
obj.fluidBBLMovedAdjusted = obj.fluidBBLMoved * kFactor;
|
obj.fluidBblMovedAdjusted = obj.fluidBblMoved * kFactor;
|
||||||
obj.oilBBLMoved = obj.fluidBBLMoved * oilBBLRatio;
|
obj.oilBblMoved = obj.fluidBblMoved * oilBBLRatio;
|
||||||
obj.waterBBLMoved = obj.fluidBBLMoved * waterBBLRatio;
|
obj.waterBblMoved = obj.fluidBblMoved * waterBBLRatio;
|
||||||
obj.gasMCFMoved = obj.fluidBBLMoved * gasMCFRatio;
|
obj.gasMcfMoved = obj.fluidBblMoved * gasMCFRatio;
|
||||||
|
|
||||||
|
|
||||||
if (obj.fillageEstimated > 100)
|
if (obj.fillageEstimated > 100)
|
||||||
@@ -169,7 +169,7 @@ classdef Card < handle
|
|||||||
obj.strokeSpeed = 60000.0 / (now - obj.strokeStartTime);
|
obj.strokeSpeed = 60000.0 / (now - obj.strokeStartTime);
|
||||||
end
|
end
|
||||||
|
|
||||||
function dist = distanceToLine(pos, load)
|
function dist = distanceToLine(obj, pos, load)
|
||||||
% Finds the distance between a point and a line between the
|
% Finds the distance between a point and a line between the
|
||||||
% Max Position at Max Load and Min Position at Min Load
|
% Max Position at Max Load and Min Position at Min Load
|
||||||
x1 = obj.downholePositionMin.position;
|
x1 = obj.downholePositionMin.position;
|
||||||
@@ -180,6 +180,27 @@ classdef Card < handle
|
|||||||
dist = abs((y2-y1)* pos - (x2-x1)* load + x2*y1 - y2*x1) / sqrt(power(y2-y1, 2) + power(x2-x1,2));
|
dist = abs((y2-y1)* pos - (x2-x1)* load + x2*y1 - y2*x1) / sqrt(power(y2-y1, 2) + power(x2-x1,2));
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function plot(obj)
|
||||||
|
ax1 = subplot(2,1,1);
|
||||||
|
plot(obj.surfacePosition(1:obj.numPointsUsed), obj.surfaceLoad(1:obj.numPointsUsed))
|
||||||
|
title('Surface Card')
|
||||||
|
|
||||||
|
ax2 = subplot(2,1,2);
|
||||||
|
plot(obj.downholePosition(1:obj.numPointsUsed),obj.downholeLoad(1:obj.numPointsUsed), 'r')
|
||||||
|
title('Downhole Card')
|
||||||
|
|
||||||
|
linkaxes([ax1, ax2], 'x')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
methods(Static)
|
||||||
|
function yTest = lineResolve(x1, x2, y1, y2, xTest)
|
||||||
|
% Uses the standard line equation to find the y value given x
|
||||||
|
line_m = (y2 - y1) / (x2 - x1);
|
||||||
|
line_b = y1 - line_m * x1;
|
||||||
|
yTest = line_m * xTest + line_b;
|
||||||
|
end
|
||||||
|
|
||||||
function foundPoint = positionMax(positionArr, loadArr, arrSize)
|
function foundPoint = positionMax(positionArr, loadArr, arrSize)
|
||||||
maxPos = positionArr(1);
|
maxPos = positionArr(1);
|
||||||
loadAtMaxP = -inf;
|
loadAtMaxP = -inf;
|
||||||
@@ -228,16 +249,6 @@ classdef Card < handle
|
|||||||
end
|
end
|
||||||
foundPoint = LPPair(posAtMinL, minLoad);
|
foundPoint = LPPair(posAtMinL, minLoad);
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
methods(Static)
|
|
||||||
function yTest = lineResolve(x1, x2, y1, y2, xTest)
|
|
||||||
% Uses the standard line equation to find the y value given x
|
|
||||||
line_m = (y2 - y1) / (x2 - x1);
|
|
||||||
line_b = y1 - line_m * x1;
|
|
||||||
yTest = line_m * xTest + line_b;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
21
MuxSetupSim.m
Normal file
21
MuxSetupSim.m
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
classdef MuxSetupSim < handle
|
||||||
|
properties(Access=private)
|
||||||
|
mux1Pin=5;
|
||||||
|
mux2Pin=6;
|
||||||
|
mux3Pin=13;
|
||||||
|
digInPin=19;
|
||||||
|
anOutTriggerPin=23;
|
||||||
|
dev;
|
||||||
|
end
|
||||||
|
|
||||||
|
properties
|
||||||
|
setup=[0 0 0; 1 0 0; 0 1 0; 1 1 0; 0 0 1; 1 0 1; 0 1 1; 1 1 1];
|
||||||
|
spiDevice;
|
||||||
|
end
|
||||||
|
|
||||||
|
methods
|
||||||
|
function obj = MuxSetupSim(dev)
|
||||||
|
obj.dev = dev;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
176
Well.m
176
Well.m
@@ -3,27 +3,49 @@ classdef Well < handle
|
|||||||
% Constants (SHOULD THESE BE ELSEWHERE?)
|
% Constants (SHOULD THESE BE ELSEWHERE?)
|
||||||
YM_STEEL=30.5;
|
YM_STEEL=30.5;
|
||||||
YM_FIBERGLASS=7.2;
|
YM_FIBERGLASS=7.2;
|
||||||
|
|
||||||
|
DIRECTION_UNKNOWN=0;
|
||||||
|
DIRECTION_UP=1;
|
||||||
|
DIRECTION_DOWN=2;
|
||||||
end
|
end
|
||||||
|
|
||||||
properties
|
properties
|
||||||
wellName;
|
wellName;
|
||||||
|
|
||||||
|
% Instrumentation
|
||||||
|
device;
|
||||||
|
mux;
|
||||||
|
positionSensor;
|
||||||
|
loadSensor;
|
||||||
|
|
||||||
% Current Values
|
% Current Values
|
||||||
currentSurfacePosition,currentSurfaceLoad;
|
currentSurfacePosition,currentSurfaceLoad;
|
||||||
currentDownholePosition,currentDownholeLoad;
|
currentDownholePosition,currentDownholeLoad;
|
||||||
|
currentCard=Card(0);
|
||||||
currentCard=Card(0);
|
lastCard=Card(0);
|
||||||
|
direction=0;
|
||||||
|
lastDirection=0;
|
||||||
|
|
||||||
% User Inputs
|
% User Inputs
|
||||||
dt = 0.03333333;
|
dt = 1.0 / 30.0;
|
||||||
tubingHeadPressure = 40.0;
|
tubingHeadPressure = 40.0;
|
||||||
fluidGradient = 0.45;
|
fluidGradient = 0.45;
|
||||||
stuffingBoxFriction = 100.0;
|
stuffingBoxFriction = 100.0;
|
||||||
numTapers = 3;
|
numTapers = 3;
|
||||||
tubingAnchorDepth = 0.0;
|
tubingAnchorDepth = 0.0;
|
||||||
pumpDiameter = 2.5;
|
pumpDiameter = 2.5;
|
||||||
|
pumpArea;
|
||||||
tubingInnerDiameter = 1.995;
|
tubingInnerDiameter = 1.995;
|
||||||
tubingOuterDiameter = 2.375;
|
tubingOuterDiameter = 2.375;
|
||||||
|
tubingCrossSectionalArea;
|
||||||
structuralRating = 320000;
|
structuralRating = 320000;
|
||||||
|
frictionEstimate;
|
||||||
|
|
||||||
|
% Production Parameters
|
||||||
|
kFactor=1.0;
|
||||||
|
waterBblRatio=0.90;
|
||||||
|
oilBblRatio=0.10;
|
||||||
|
gasMcfRatio=5.0;
|
||||||
|
|
||||||
% Rod String Inputs
|
% Rod String Inputs
|
||||||
c;
|
c;
|
||||||
@@ -31,7 +53,6 @@ classdef Well < handle
|
|||||||
rodDiameter;
|
rodDiameter;
|
||||||
rodYM;
|
rodYM;
|
||||||
rodWeightPerFoot;
|
rodWeightPerFoot;
|
||||||
|
|
||||||
|
|
||||||
% Calculated Taper Parameters
|
% Calculated Taper Parameters
|
||||||
a;
|
a;
|
||||||
@@ -47,16 +68,17 @@ classdef Well < handle
|
|||||||
centerPoint;
|
centerPoint;
|
||||||
count;
|
count;
|
||||||
|
|
||||||
topPosArray;
|
|
||||||
topLoadArray;
|
|
||||||
|
|
||||||
buoyantForceTotal = 0.0;
|
buoyantForceTotal = 0.0;
|
||||||
rodDepthTotal = 0.0;
|
rodDepthTotal = 0.0;
|
||||||
rodWeightAirTotal = 0.0;
|
rodWeightAirTotal = 0.0;
|
||||||
rodWeightFluidTotal = 0.0;
|
rodWeightFluidTotal = 0.0;
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
properties(Access=private)
|
||||||
|
topPosArray;
|
||||||
|
topLoadArray;
|
||||||
|
|
||||||
% cross-function variables for position and load
|
% cross-function variables for position and load
|
||||||
% POSITION MUST ALWAYS BE CALLED FIRST.
|
% POSITION MUST ALWAYS BE CALLED FIRST.
|
||||||
loadBefore = 0.0;
|
loadBefore = 0.0;
|
||||||
@@ -64,13 +86,10 @@ classdef Well < handle
|
|||||||
loadBefore3 = 0.0;
|
loadBefore3 = 0.0;
|
||||||
loadAfter3 = 0.0;
|
loadAfter3 = 0.0;
|
||||||
tempLoadValue = 0.0;
|
tempLoadValue = 0.0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
methods
|
methods
|
||||||
function me = Well(name)
|
function me = Well(name, sim)
|
||||||
me.wellName = name;
|
me.wellName = name;
|
||||||
|
|
||||||
me.c = [0.8 0.8 0.8];
|
me.c = [0.8 0.8 0.8];
|
||||||
@@ -97,10 +116,27 @@ classdef Well < handle
|
|||||||
me.topPosArray = zeros(10, 250,'double');
|
me.topPosArray = zeros(10, 250,'double');
|
||||||
me.topLoadArray = zeros(10, 250, 'double');
|
me.topLoadArray = zeros(10, 250, 'double');
|
||||||
|
|
||||||
me.taperSetup();
|
if logical(sim)
|
||||||
|
me.device = 0;
|
||||||
|
me.mux = MuxSetupSim(me.device);
|
||||||
|
me.positionSensor = AnalogInputSim(me.mux, 1, 0.0, 65535.0, 0.0, 65535.0);
|
||||||
|
me.loadSensor = AnalogInputSim(me.mux, 2, 0.0, 65535.0, 0.0, 65535.0);
|
||||||
|
else
|
||||||
|
me.device = raspi('10.0.0.106', 'pi', 'HenryPump@1903');
|
||||||
|
me.mux = MuxSetupSim(me.device);
|
||||||
|
me.positionSensor = AnalogInput(mux, 1, 0.0, 65535.0, 0.0, 140.0);
|
||||||
|
me.loadSensor = AnalogInput(mux, 2, 0.0, 65535.0, 0.0, 50000.0);
|
||||||
|
end
|
||||||
|
|
||||||
|
me.wellSetup();
|
||||||
end
|
end
|
||||||
|
|
||||||
function taperSetup(me)
|
function wellSetup(me)
|
||||||
|
me.tubingCrossSectionalArea = (pi / 4) * ...
|
||||||
|
(power(me.tubingOuterDiameter, 2) - ...
|
||||||
|
power(me.tubingInnerDiameter,2));
|
||||||
|
me.pumpArea = power(me.pumpDiameter, 2) * pi;
|
||||||
|
|
||||||
for i = 1:me.numTapers
|
for i = 1:me.numTapers
|
||||||
me.area(i) = pi / 4 * power(me.rodDiameter(i), 2);
|
me.area(i) = pi / 4 * power(me.rodDiameter(i), 2);
|
||||||
end
|
end
|
||||||
@@ -153,6 +189,8 @@ classdef Well < handle
|
|||||||
me.centerPoint(i) = me.lagIndex(i) + 2;
|
me.centerPoint(i) = me.lagIndex(i) + 2;
|
||||||
me.lengthRequired(i) = 2 * (me.lagIndex(i) + 1) + 1;
|
me.lengthRequired(i) = 2 * (me.lagIndex(i) + 1) + 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
me.frictionEstimate = me.rodDepthTotal * 0.10;
|
||||||
end
|
end
|
||||||
|
|
||||||
function pumpPosition = position(me, i)
|
function pumpPosition = position(me, i)
|
||||||
@@ -174,7 +212,7 @@ classdef Well < handle
|
|||||||
me.loadAfter3 = 0.0;
|
me.loadAfter3 = 0.0;
|
||||||
|
|
||||||
pumpPosition = exp(ci * lengthi / (2.0 * ai)) * (me.topPosArray(i, iAfter) + ...
|
pumpPosition = exp(ci * lengthi / (2.0 * ai)) * (me.topPosArray(i, iAfter) + ...
|
||||||
factori * me.topPosArray(i, iAfter+1));
|
factori * (me.topPosArray(i, iAfter+1) - me.topPosArray(i, iAfter)));
|
||||||
|
|
||||||
pumpPosition = pumpPosition + exp(-ci * lengthi / (2.0 * ai)) * ...
|
pumpPosition = pumpPosition + exp(-ci * lengthi / (2.0 * ai)) * ...
|
||||||
(me.topPosArray(i,iBefore) + factori * (me.topPosArray(i,iBefore-1) - ...
|
(me.topPosArray(i,iBefore) + factori * (me.topPosArray(i,iBefore-1) - ...
|
||||||
@@ -271,6 +309,8 @@ classdef Well < handle
|
|||||||
|
|
||||||
function [pumpPosition, pumpLoad, status] = calc(me, polishedRodPosition, lastPolishedRodPosition,...
|
function [pumpPosition, pumpLoad, status] = calc(me, polishedRodPosition, lastPolishedRodPosition,...
|
||||||
polishedRodLoad)
|
polishedRodLoad)
|
||||||
|
me.currentSurfacePosition = polishedRodPosition;
|
||||||
|
me.currentSurfaceLoad = polishedRodLoad;
|
||||||
pumpPosition = -1.0;
|
pumpPosition = -1.0;
|
||||||
pumpLoad = -1.0;
|
pumpLoad = -1.0;
|
||||||
status = -1;
|
status = -1;
|
||||||
@@ -312,7 +352,9 @@ classdef Well < handle
|
|||||||
me.topLoadArray(tap+1, me.lengthRequired(tap+1)) = pumpLoad;
|
me.topLoadArray(tap+1, me.lengthRequired(tap+1)) = pumpLoad;
|
||||||
else
|
else
|
||||||
pumpPosition = -12.0 * me.position(tap); % + me.stretch(me.numTapers);
|
pumpPosition = -12.0 * me.position(tap); % + me.stretch(me.numTapers);
|
||||||
|
me.currentDownholePosition = pumpPosition;
|
||||||
pumpLoad = me.load(tap) + me.force(me.numTapers);
|
pumpLoad = me.load(tap) + me.force(me.numTapers);
|
||||||
|
me.currentDownholeLoad = pumpLoad;
|
||||||
status = 1;
|
status = 1;
|
||||||
end
|
end
|
||||||
me.count(tap) = me.count(tap) - 1;
|
me.count(tap) = me.count(tap) - 1;
|
||||||
@@ -324,6 +366,108 @@ classdef Well < handle
|
|||||||
tap = tap + 1;
|
tap = tap + 1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function directionChanged = checkEndOfStroke(me, numConsecutivePoints)
|
||||||
|
directionChanged = 0;
|
||||||
|
tempDirection = me.DIRECTION_UNKNOWN;
|
||||||
|
startDirection = me.DIRECTION_UNKNOWN;
|
||||||
|
consecutivePointsAllSameDirection = 1;
|
||||||
|
|
||||||
|
if me.positionSensor.history(1) > me.positionSensor.history(2)
|
||||||
|
tempDirection = me.DIRECTION_UP;
|
||||||
|
startDirection = me.DIRECTION_UP;
|
||||||
|
elseif me.positionSensor.history(1) < me.positionSensor.history(2)
|
||||||
|
tempDirection = me.DIRECTION_DOWN;
|
||||||
|
startDirection = me.DIRECTION_DOWN;
|
||||||
|
end
|
||||||
|
|
||||||
|
if startDirection == me.DIRECTION_UP
|
||||||
|
|
||||||
|
for i = 1:numConsecutivePoints
|
||||||
|
if me.positionSensor.history(i) <= me.positionSensor.history(i+1)
|
||||||
|
consecutivePointsAllSameDirection = 0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if consecutivePointsAllSameDirection == 1
|
||||||
|
tempDirection = me.DIRECTION_UP;
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif startDirection == me.DIRECTION_DOWN
|
||||||
|
|
||||||
|
for i = 1:numConsecutivePoints
|
||||||
|
if me.positionSensor.history(i) >= me.positionSensor.history(i+1)
|
||||||
|
consecutivePointsAllSameDirection = 0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if consecutivePointsAllSameDirection == 1
|
||||||
|
tempDirection = me.DIRECTION_DOWN;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if tempDirection ~= me.lastDirection
|
||||||
|
if (tempDirection == me.DIRECTION_UP) && ...
|
||||||
|
(me.currentCard.numPointsUsed > 1)
|
||||||
|
directionChanged = 1;
|
||||||
|
end
|
||||||
|
me.lastDirection = tempDirection;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function evalSim(me, s_pos, s_load)
|
||||||
|
me.positionSensor.read(s_pos);
|
||||||
|
me.loadSensor.read(s_load);
|
||||||
|
|
||||||
|
[d_pos, d_load, d_status] = me.calc(me.positionSensor.lastValue, ...
|
||||||
|
me.positionSensor.history(2), me.loadSensor.lastValue);
|
||||||
|
if d_status == 1
|
||||||
|
me.currentCard.push(me.positionSensor.lastValue, ...
|
||||||
|
me.loadSensor.lastValue, d_pos, d_load);
|
||||||
|
end
|
||||||
|
|
||||||
|
if me.checkEndOfStroke(5) == 1
|
||||||
|
me.endOfStroke()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function endOfStroke(me)
|
||||||
|
me.currentCard.calcStrokeData(100, me.fluidGradient, me.rodDepthTotal, ...
|
||||||
|
me.tubingAnchorDepth, me.tubingCrossSectionalArea, ...
|
||||||
|
me.pumpArea, me.frictionEstimate, ...
|
||||||
|
me.structuralRating, me.kFactor, me.waterBblRatio, me.oilBblRatio, ...
|
||||||
|
me.gasMcfRatio);
|
||||||
|
me.plotCards()
|
||||||
|
|
||||||
|
me.lastCard = me.currentCard();
|
||||||
|
me.currentCard = Card(me.lastCard.strokeNumber + 1);
|
||||||
|
end
|
||||||
|
|
||||||
|
function plotCards(me)
|
||||||
|
ax1 = subplot(2,2,1);
|
||||||
|
plot(me.lastCard.surfacePosition(1:me.lastCard.numPointsUsed), ...
|
||||||
|
me.lastCard.surfaceLoad(1:me.lastCard.numPointsUsed))
|
||||||
|
title('Last Surface Card')
|
||||||
|
|
||||||
|
ax3 = subplot(2,2,3);
|
||||||
|
plot(me.lastCard.downholePosition(1:me.lastCard.numPointsUsed), ...
|
||||||
|
me.lastCard.downholeLoad(1:me.lastCard.numPointsUsed), 'r')
|
||||||
|
title('Last Downhole Card')
|
||||||
|
|
||||||
|
ax2 = subplot(2,2,2);
|
||||||
|
plot(me.currentCard.surfacePosition(1:me.currentCard.numPointsUsed), ...
|
||||||
|
me.currentCard.surfaceLoad(1:me.currentCard.numPointsUsed))
|
||||||
|
title('Current Surface Card')
|
||||||
|
|
||||||
|
ax4 = subplot(2,2,4);
|
||||||
|
plot(me.currentCard.downholePosition(1:me.currentCard.numPointsUsed), ...
|
||||||
|
me.currentCard.downholeLoad(1:me.currentCard.numPointsUsed), 'r')
|
||||||
|
title('Current Downhole Card')
|
||||||
|
|
||||||
|
linkaxes([ax1, ax2, ax3, ax4], 'x')
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
methods(Static)
|
methods(Static)
|
||||||
|
|||||||
18
test.m
18
test.m
@@ -1,10 +1,16 @@
|
|||||||
|
|
||||||
malletData = csvread('mallet.csv');
|
malletData = csvread('mallet.csv');
|
||||||
mallet = Well("Mallet");
|
mallet = Well("Mallet", true(1));
|
||||||
for i = 2:size(malletData,1)
|
figure;
|
||||||
[dhPos, dhLoad, status] = mallet.calc(malletData(i,1), malletData(i-1,1), malletData(i,2));
|
for loops = 1:6
|
||||||
if status == 1
|
for i = 2:size(malletData,1)
|
||||||
mallet.currentCard.push(malletData(i,1), malletData(i,2), dhPos, dhLoad);
|
mallet.evalSim(malletData(i,1), malletData(i,2));
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
figure;plot(mallet.currentCard.downholePosition,mallet.currentCard.downholeLoad)
|
|
||||||
|
% mallet.currentCard.calcStrokeData(100, mallet.fluidGradient, mallet.rodDepthTotal, ...
|
||||||
|
% mallet.tubingAnchorDepth, mallet.tubingCrossSectionalArea, ...
|
||||||
|
% mallet.pumpArea, mallet.frictionEstimate, ...
|
||||||
|
% mallet.structuralRating, mallet.kFactor, mallet.waterBblRatio, mallet.oilBblRatio, ...
|
||||||
|
% mallet.gasMcfRatio)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user