320 lines
11 KiB
Matlab
320 lines
11 KiB
Matlab
simWell()
|
|
|
|
function simWell
|
|
wellName = "Mallet";
|
|
|
|
% Current Values
|
|
currentSurfacePosition = 0.0;
|
|
currentSurfaceLoad = 0.0;
|
|
currentDownholePosition = 0.0;
|
|
currentDownholeLoad = 0.0;
|
|
|
|
currentCard=Card(0);
|
|
|
|
% Constants
|
|
YM_STEEL=30.5;
|
|
YM_FIBERGLASS=7.2;
|
|
|
|
% User Inputs
|
|
dt = 0.03333333;
|
|
tubingHeadPressure = 40.0;
|
|
fluidGradient = 0.45;
|
|
stuffingBoxFriction = 100.0;
|
|
numTapers = 3;
|
|
tubingAnchorDepth = 0.0;
|
|
pumpDiameter = 2.5;
|
|
tubingInnerDiameter = 1.995;
|
|
tubingOuterDiameter = 2.375;
|
|
structuralRating = 320000;
|
|
|
|
% Rod String Inputs
|
|
c = [0.08 0.08 0.08];
|
|
rodLength = [1475.0 1525.0 2000.0];
|
|
rodDiameter = [1.0 0.875 0.750];
|
|
rodYM = [YM_STEEL YM_STEEL YM_STEEL];
|
|
rodWeightPerFoot = [Well.lookupRodWeightPerFoot(YM_STEEL, rodDiameter(1)) ...
|
|
Well.lookupRodWeightPerFoot(YM_STEEL, rodDiameter(2)) ...
|
|
Well.lookupRodWeightPerFoot(YM_STEEL, rodDiameter(3))];
|
|
|
|
% Calculated Taper Parameters
|
|
% Initialize
|
|
a = zeros(1, numTapers, 'double');
|
|
area = zeros(1, numTapers+1, 'double');
|
|
pressure = zeros(1, numTapers, 'double');
|
|
stretch = zeros(1, numTapers, 'double');
|
|
force = zeros(1, numTapers, 'double');
|
|
alpha = zeros(1, numTapers, 'double');
|
|
xOverA = zeros(1, numTapers, 'double');
|
|
factorArray = zeros(1, numTapers, 'double');
|
|
lagIndex = zeros(1, numTapers, 'uint8');
|
|
lengthRequired = zeros(1, numTapers, 'uint8');
|
|
centerPoint = zeros(1, numTapers, 'uint8');
|
|
count = zeros(1, numTapers, 'uint8');
|
|
|
|
buoyantForceTotal = 0.0;
|
|
rodDepthTotal = 0.0;
|
|
rodWeightAirTotal = 0.0;
|
|
rodWeightFluidTotal = 0.0;
|
|
|
|
topPosArray = zeros(10, 250,'double');
|
|
topLoadArray = zeros(10, 250, 'double');
|
|
|
|
% cross-function variables for position and load
|
|
% POSITION MUST ALWAYS BE CALLED FIRST.
|
|
loadBefore = 0.0;
|
|
loadAfter = 0.0;
|
|
loadBefore3 = 0.0;
|
|
loadAfter3 = 0.0;
|
|
tempLoadValue = 0.0;
|
|
|
|
for i = 1:numTapers
|
|
area(i) = pi / 4 * rodDiameter(i) ^ 2;
|
|
end
|
|
|
|
for i = 1:numTapers
|
|
a(i) = 1000.0 * sqrt(32.3 * rodYM(i) / rodWeightPerFoot(i));
|
|
|
|
% if i > 1
|
|
% rodDepth(i) = rodDepth(i-1) + rodLength(i);
|
|
% else
|
|
% rodDepth(i) = 0.0;
|
|
% end
|
|
rodDepthTotal = rodDepthTotal + rodLength(i);
|
|
|
|
if i > 1
|
|
pressure(i) = pressure(i - 1) + fluidGradient * rodLength(i);
|
|
else
|
|
pressure(i) = tubingHeadPressure + fluidGradient * rodLength(i);
|
|
end
|
|
|
|
% buoyantForce(i) = pressure(i) * (area(i+1) - area(i));
|
|
buoyantForceTotal = buoyantForceTotal + pressure(i) * (area(i+1) - area(i));
|
|
|
|
% rodWeightAir(i) = rodWeightPerFoot(i) * rodLength(i);
|
|
rodWeightAirTotal = rodWeightAirTotal + rodWeightPerFoot(i) * rodLength(i);
|
|
|
|
% rodWeightFluid(i) = rodWeightAir(i) + buoyantForce(i);
|
|
rodWeightFluidTotal = rodWeightFluidTotal + buoyantForceTotal;
|
|
end
|
|
|
|
for j = 1:numTapers
|
|
weightData = 0.0;
|
|
annularForceData = 0.0;
|
|
|
|
for i = j+1:numTapers
|
|
weightData = weightData + rodWeightPerFoot(i) * rodLength(i);
|
|
end
|
|
|
|
for i = j:numTapers-1
|
|
annularForceData = annularForceData + pressure(i) * (area(i) - area(i+1));
|
|
end
|
|
|
|
force(j) = (-area(numTapers) * pressure(numTapers)) + weightData - annularForceData;
|
|
alpha(j) = (force(j) + rodWeightPerFoot(j) * rodLength(j)) / (rodYM(j) * power(10, 6) * area(j));
|
|
|
|
if j > 1
|
|
stretch(j) = stretch(j - 1) + alpha(j) * rodLength(j) - ...
|
|
(rodWeightPerFoot(j) * power(rodLength(j), 2)) / ...
|
|
(2 * rodYM(j) * power(10, 6) * area(j));
|
|
else
|
|
stretch(j) = 0.0 + alpha(j) * rodLength(j) - ...
|
|
(rodWeightPerFoot(j) * power(rodLength(j), 2)) / ...
|
|
(2 * rodYM(j) * power(10, 6) * area(j));
|
|
end
|
|
end
|
|
|
|
for i = 1:numTapers
|
|
xOverA(i) = rodLength(i) / a(i);
|
|
lagIndex(i) = floor(rodLength(i) / (a(i) * dt));
|
|
factorArray(i) = (xOverA(i) - double(lagIndex(i)) * dt) / dt;
|
|
centerPoint(i) = lagIndex(i) + 2;
|
|
lengthRequired(i) = 2 * (lagIndex(i) + 1) + 1;
|
|
end
|
|
|
|
m = csvread('Mallet No Tag.csv');
|
|
for i = 2:size(m,1)
|
|
[dhPos, dhLoad, status] = calc(m(i,1), m(i-1,1), m(i,2));
|
|
if status == 1
|
|
currentCard.push(m(i,1), m(i,2), dhPos, dhLoad);
|
|
end
|
|
end
|
|
% currentCard.surfacePosition
|
|
% scatter(currentCard.surfacePosition, currentCard.surfaceLoad)
|
|
scatter(currentCard.downholePosition, currentCard.downholeLoad)
|
|
|
|
|
|
|
|
|
|
|
|
% FUNCTION DECLARATIONS
|
|
|
|
function pumpPosition = position(i)
|
|
% Position Function
|
|
ai = a(i);
|
|
ci = c(i);
|
|
factori = factorArray(i);
|
|
lengthi = rodLength(i);
|
|
lagi = double(lagIndex(i));
|
|
yi = rodYM(i) * power(10, 6);
|
|
areai = area(i);
|
|
centeri = centerPoint(i);
|
|
iBefore = centeri - lagIndex(i);
|
|
iAfter = centeri + lagIndex(i);
|
|
|
|
pumpPosition = exp(ci * lengthi / (2 * ai)) * (topPosArray(i, iAfter) + ...
|
|
factori * topPosArray(i, iAfter+1));
|
|
|
|
pumpPosition = pumpPosition + exp(ci * lengthi / (2 * ai)) * ...
|
|
(topPosArray(i,iBefore-1) -topPosArray(i, iBefore));
|
|
|
|
pumpPosition = 0.5 * pumpPosition;
|
|
insideIntegral = 0.0;
|
|
|
|
for jj = 1:2*lagi-1
|
|
insideIntegral = insideIntegral + dt / (yi * areai) * ...
|
|
(exp((-ci * (lagi - jj) *dt) / 2) * ...
|
|
topLoadArray(i, iBefore + jj));
|
|
end
|
|
|
|
insideIntegral = insideIntegral + 0.5 * dt /(yi * areai) * ...
|
|
(exp((-ci * lagi * dt) / 2) * topLoadArray(i, iBefore) + ...
|
|
exp((-ci * -lagi * dt) / 2) * topLoadArray(i, iAfter));
|
|
|
|
loadBefore = exp((-ci * lagi * dt) / 2) * topLoadArray(i, iBefore) + ...
|
|
factori * (exp((-ci * (lagi + 1) * dt) / 2) * topLoadArray(i, iBefore-1) - ...
|
|
exp((-ci * lagi * dt) / 2) * topLoadArray(i, iBefore));
|
|
|
|
loadAfter = exp((-ci * -lagi * dt) / 2) * topLoadArray(i, iAfter) + ...
|
|
factori * (exp((-ci * (-lagi - 1) * dt) / 2) * topLoadArray(i, iAfter+1) - ...
|
|
exp((-ci * -lagi * dt) / 2) * topLoadArray(i,iAfter));
|
|
|
|
insideIntegral = insideIntegral + 0.5 * factori * dt / (yi * areai) * ...
|
|
(loadBefore + exp((-ci * lagi * dt) / 2) * topLoadArray(i, iBefore));
|
|
|
|
insideIntegral = insideIntegral + 0.5 * factori * dt / (yi * areai) * ...
|
|
(loadAfter + exp((-ci * -lagi * dt) / 2) * topLoadArray(i, iAfter));
|
|
|
|
insideIntegral = 0.5 * ai * insideIntegral;
|
|
pumpPosition = pumpPosition + insideIntegral;
|
|
|
|
insideIntegral = 0.0;
|
|
|
|
for jj = 1:2*lagi-1
|
|
insideIntegral = insideIntegral + dt * (exp((-ci * (lagi - jj) * dt) / 2) * ...
|
|
topPosArray(i, iBefore+jj));
|
|
end
|
|
|
|
insideIntegral = insideIntegral + 0.5 * dt * (exp((-ci * lagi * dt) / 2) * ...
|
|
topPosArray(i, iBefore) + exp((-ci * -lagi * dt) / 2) * ...
|
|
topPosArray(i, iAfter));
|
|
|
|
loadBefore3 = exp((-ci * lagi * dt) / 2) * topPosArray(i, iBefore) + ...
|
|
factori * (exp((-ci * (lagi+1) * dt) / 2) * topPosArray(i, iBefore-1) - ...
|
|
exp((-ci * lagi * dt) / 2) * topPosArray(i, iBefore));
|
|
|
|
loadAfter3 = exp((-ci * -lagi * dt) / 2) * topPosArray(i, iAfter) + ...
|
|
factori * (exp((-ci * (-lagi-1) * dt) / 2) * topPosArray(i, iAfter+1) - ...
|
|
exp((-ci * -lagi * dt) / 2) * topPosArray(i, iAfter));
|
|
|
|
insideIntegral = insideIntegral + 0.5 * factori * dt * (loadBefore3 + ...
|
|
exp((-ci * lagi * dt) / 2) * topPosArray(i, iBefore));
|
|
|
|
insideIntegral = insideIntegral + 0.5 * factori * dt * (loadAfter3 + ...
|
|
exp((-ci * -lagi * dt) / 2) * topPosArray(i, iAfter));
|
|
|
|
insideIntegral = -(ci * lengthi / 4) * 0.5 * (ci / (2 * ai)) * insideIntegral;
|
|
tempLoadValue = insideIntegral / lengthi;
|
|
pumpPosition = pumpPosition + insideIntegral;
|
|
end
|
|
|
|
function pumpLoad = load(i)
|
|
% Load Function
|
|
ai = a(i);
|
|
ci = c(i);
|
|
factori = factorArray(i);
|
|
lengthi = rodLength(i);
|
|
lagi = lagIndex(i);
|
|
yi = rodYM(i) * power(10, 6);
|
|
areai = area(i);
|
|
centeri = centerPoint(i);
|
|
iBefore = centeri - lagi;
|
|
iAfter = centeri + lagi;
|
|
|
|
pumpLoad = 0.5 * (ai / (yi * areai)) * (1 / ai) * (loadBefore + loadAfter);
|
|
tempResult = yi * areai * pumpLoad;
|
|
pumpLoad = pumpLoad - (ci * lengthi / 4) * (0.5 * (ci / (2 * ai))) * (1 / ai) * ...
|
|
(loadBefore3 + loadAfter3);
|
|
|
|
ptAfter = (topPosArray(i, iAfter+1) - topPosArray(i, iAfter-1)) / (2 * dt);
|
|
ptBefore = (topPosArray(i, iBefore+1) - topPosArray(i, iBefore-1)) / (2 * dt);
|
|
firstPart = (exp((ci * lengthi) / (2 * ai)) * ptAfter - exp((-ci * lengthi) / ...
|
|
(2 * ai)) * ptBefore) / (2 * ai);
|
|
|
|
firstPart = firstPart + (ci * exp((ci * lengthi) / (2 * ai)) * ...
|
|
topPosArray(i, iAfter) - ci * exp((-ci * lengthi) / (2 * ai)) * ...
|
|
topPosArray(i, iBefore)) / (4 * ai);
|
|
|
|
pumpLoad = yi * areai * (firstPart + pumpLoad); % + tempLoadValue ?
|
|
end
|
|
|
|
function [pumpPosition, pumpLoad, status] = calc(polishedRodPosition, lastPolishedRodPosition,...
|
|
polishedRodLoad)
|
|
pumpPosition = -1.0;
|
|
pumpLoad = -1.0;
|
|
status = -1;
|
|
loadMult = 1.0;
|
|
tapersAllowed = 1;
|
|
|
|
for ii = 2:lengthRequired(1)
|
|
topPosArray(1, ii-1) = topPosArray(1, ii);
|
|
topLoadArray(1, ii-1) = topLoadArray(1, ii);
|
|
topPosArray(1, lengthRequired(1)) = - polishedRodPosition / 12;
|
|
|
|
if polishedRodPosition > lastPolishedRodPosition
|
|
topLoadArray(1, lengthRequired(1)) = loadMult * ...
|
|
(polishedRodLoad - rodWeightFluidTotal) - stuffingBoxFriction;
|
|
elseif polishedRodPosition > lastPolishedRodPosition
|
|
topLoadArray(1, lengthRequired(1)) = loadMult * ...
|
|
(polishedRodLoad - rodWeightFLuidTotal) + stuffingBoxFriction;
|
|
else
|
|
topLoadArray(1, lengthRequired(1)) = loadMult * (polishedRodLoad - rodWeightFluidTotal);
|
|
end
|
|
end
|
|
|
|
tap=1;
|
|
while tap <= tapersAllowed
|
|
count(tap) = count(tap) + 1;
|
|
if count(tap) >= lengthRequired(tap)
|
|
if tap+1 <= numTapers
|
|
% working our way down to the bottom of the well
|
|
for pti = 2:lengthRequired(tap+1)
|
|
topPosArray(tap+1, pti-1) = topPosArray(tap+1, pti);
|
|
topLoadArray(tap+1, pti-1) = topLoadArray(tap+1, pti);
|
|
end
|
|
pumpPosition = position(tap);
|
|
pumpLoad = load(tap);
|
|
status = 0;
|
|
topPosArray(tap+1, lengthRequired(tap+1)) = pumpPosition;
|
|
topLoadArray(tap+1, lengthRequired(tap+1)) = pumpLoad;
|
|
else
|
|
pumpPosition = -12 * (position(tap) + stretch(numTapers));
|
|
pumpLoad = load(tap) + force(numTapers);
|
|
status = 1;
|
|
end
|
|
count(tap) = count(tap) - 1;
|
|
tapersAllowed = tapersAllowed + 1;
|
|
if tapersAllowed > numTapers
|
|
tapersAllowed = numTapers;
|
|
end
|
|
end
|
|
tap = tap + 1;
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|