214 lines
8.1 KiB
Matlab
214 lines
8.1 KiB
Matlab
classdef Well < handle
|
|
properties(Constant)
|
|
%% Constants (SHOULD THESE BE ELSEWHERE?)
|
|
DIRECTION_UNKNOWN=0;
|
|
DIRECTION_UP=1;
|
|
DIRECTION_DOWN=2;
|
|
end
|
|
|
|
properties
|
|
parameters;
|
|
|
|
|
|
%% Instrumentation
|
|
device;
|
|
mux;
|
|
positionSensor;
|
|
loadSensor;
|
|
|
|
%% Current Values
|
|
currentCard=Card(0);
|
|
lastCard=Card(0);
|
|
direction=0;
|
|
lastDirection=0;
|
|
|
|
%% Production Parameters
|
|
kFactor=1.0;
|
|
waterBblRatio=0.90;
|
|
oilBblRatio=0.10;
|
|
gasMcfRatio=5.0;
|
|
end
|
|
|
|
properties(Access=private)
|
|
topPosArray;
|
|
topLoadArray;
|
|
count;
|
|
|
|
end
|
|
|
|
methods
|
|
%% Constructor Function
|
|
function me = Well(dt, rodLengths, rodDiameters, ...
|
|
rodMaterials, rodDampingFactors, tubingHeadPressure, ...
|
|
stuffingBoxFriction, fluidGradient, pumpDiameter, ...
|
|
tubingOuterDiameter, tubingInnerDiameter, tubingAnchorDepth, ...
|
|
structuralRating)
|
|
|
|
me.parameters = wellSetup(dt, rodLengths, rodDiameters, ...
|
|
rodMaterials, rodDampingFactors, tubingHeadPressure, ...
|
|
stuffingBoxFriction, fluidGradient, pumpDiameter, tubingOuterDiameter, ...
|
|
tubingInnerDiameter, tubingAnchorDepth, structuralRating);
|
|
|
|
me.topPosArray = zeros(me.parameters.numTapers+1, 100);
|
|
me.topLoadArray = zeros(me.parameters.numTapers+1, 100);
|
|
me.count = zeros(1, me.parameters.numTapers);
|
|
|
|
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);
|
|
|
|
me.currentCard = Card(0);
|
|
me.lastCard = Card(0);
|
|
end
|
|
|
|
|
|
%% Check if the stroke has ended
|
|
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
|
|
|
|
|
|
%% Evaluation function for simulated position and load points
|
|
function evalSim(me, s_pos, s_load)
|
|
me.positionSensor.read(s_pos);
|
|
me.loadSensor.read(s_load);
|
|
|
|
[pumpPosition, pumpLoad, status, me.topPosArray, ...
|
|
me.topLoadArray, me.count] = pocAlgorithm( ...
|
|
me.positionSensor.lastValue, ...
|
|
me.positionSensor.history(2), ...
|
|
me.loadSensor.lastValue, ...
|
|
me.count, ...
|
|
me.parameters.dt, ...
|
|
me.parameters.a, ...
|
|
me.parameters.rodDampingFactors, ...
|
|
me.parameters.factorArray, ...
|
|
me.parameters.rodLengths, ...
|
|
double(me.parameters.lagIndex), ...
|
|
me.parameters.rodYMs * 10.0^6, ...
|
|
me.parameters.area, ...
|
|
me.parameters.lengthRequired, ...
|
|
me.parameters.centerPoint, ...
|
|
me.parameters.rodWeightFluidTotal, ...
|
|
me.parameters.stuffingBoxFriction, ...
|
|
me.parameters.force, ...
|
|
me.topPosArray, ...
|
|
me.topLoadArray);
|
|
if status == 1
|
|
me.currentCard.push(me.positionSensor.lastValue, ...
|
|
me.loadSensor.lastValue, pumpPosition, pumpLoad);
|
|
end
|
|
|
|
if me.checkEndOfStroke(5) == 1
|
|
me.endOfStroke()
|
|
end
|
|
end
|
|
|
|
%% End of Stroke actions
|
|
function endOfStroke(me)
|
|
me.currentCard.calcStrokeData( ...
|
|
me.parameters.fluidGradient, ...
|
|
me.parameters.rodDepthTotal, ...
|
|
me.parameters.tubingAnchorDepth, ...
|
|
me.parameters.tubingCrossSectionalArea, ...
|
|
me.parameters.pumpArea, ...
|
|
me.parameters.frictionEstimate, ...
|
|
me.parameters.structuralRating, ...
|
|
me.kFactor, ...
|
|
me.waterBblRatio, ...
|
|
me.oilBblRatio, ...
|
|
me.gasMcfRatio);
|
|
|
|
me.lastCard = me.currentCard;
|
|
me.currentCard = Card(me.lastCard.strokeNumber + 1);
|
|
end
|
|
|
|
%% Draws Cards
|
|
% Draws current card and shows last card
|
|
function plotCards(me)
|
|
figure;
|
|
% ax1 = subplot(2,2,1);
|
|
ax1 = subplot(2,1,1);
|
|
hold on;
|
|
plot(me.lastCard.surfacePosition(1:me.lastCard.numPointsUsed), ...
|
|
me.lastCard.surfaceLoad(1:me.lastCard.numPointsUsed), 'r')
|
|
plot(me.lastCard.repSurfacePosition, me.lastCard.repSurfaceLoadTop, 'g');
|
|
plot(me.lastCard.repSurfacePosition, me.lastCard.repSurfaceLoadBottom, 'b');
|
|
title('Last Surface Card')
|
|
hold off;
|
|
|
|
% ax3 = subplot(2,2,3);
|
|
ax3 = subplot(2,1,2);
|
|
hold on;
|
|
plot(me.lastCard.downholePosition(1:me.lastCard.numPointsUsed), ...
|
|
me.lastCard.downholeLoad(1:me.lastCard.numPointsUsed), 'r')
|
|
plot(me.lastCard.topCorner.position, me.lastCard.topCorner.load, ...
|
|
'gd', 'MarkerSize', 15, 'LineWidth', 2);
|
|
plot(me.lastCard.bottomCorner.position, me.lastCard.bottomCorner.load, ...
|
|
'bd', 'MarkerSize', 15, 'LineWidth', 2);
|
|
plot(me.lastCard.repDownholePosition, me.lastCard.repDownholeLoadTop, 'g');
|
|
plot(me.lastCard.repDownholePosition, me.lastCard.repDownholeLoadBottom, 'b');
|
|
title('Last Downhole Card')
|
|
hold off;
|
|
|
|
% 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')
|
|
linkaxes([ax1, ax3], 'x')
|
|
|
|
end
|
|
end
|
|
end |