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