Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 11

Deliverables

Control of time-step for receiving data from RTU lies with us


1. Accept static data from user

2. Integrate real time load and position data coming from sensor with our platform.
3. Some dynamic data which is not coming from sensors but needs to be updated from
time to time, the user should be given an option if he wants to use the previous data
or update the data (such as fluid level, tubing pressure, casing pressure, pump intake
pressure, calibration constant).
4. For each stroke (upstroke + downstroke) load and position data, this data is needed
to be scaled to 360 values using interpolation method
5. Creation of surface dyna card with surface load and position data from surface

sensors.
6. Assume a net stroke length which is less than the user provided theoretical SRP

stroke length.
7. Using the surface dynacard to calculate surface parameters such as Maximum

Polished Rod Load, Minimum Polished Rod Load, Polished Rod Horsepower, Average
Upstroke Load, Average Downstroke Load, Actual Counterbalance Effect, Correct
Counterbalance, and Approximate “ideal” Counterbalance.
8. Using surface data to create downhole dynacard by modelling elastic behaviour of
the rod string (modelling wave equation using finite difference method).
9. Find top of stroke from the downhole dynacard by method of position and method of
load.
10. Find transfer point from the downhole dynacard by method of position and method
of load.
11. Find stroke length from the downhole dynacard which is equal to transfer point.
12. Use this stroke length for running an iterative process to find correct net stroke

length by comparing stroke length obtained from downhole dynacard with the
initially assumed net stroke length.
13. Calculating Production Loss due to Slippage.
14. Calculation of damping factor.

15. All the calculated parameters are needed to be visualized in different screens in
form of charts and graphs, the downhole and surface dynacard are also needed to
be displayed.

Step 1:
Input Stroke length (S) and Net stroke length (nS) (assumed fraction of the stroke length)

Check if S ==nS

If True, display Net Stroke Length after Iteration S

clear all
% Stroke Length S (inch)
S = 86.9;
% Assumed Net Stroke length for damping factor calculation nS (fraction of S)
(inch)
nS = 80;
%Iteration for finding net stroke length
for i=1:8
if S == nS
sprintf('Net Stroke Length after Iteration', S)
disp(S)
sprintf('')
else

if False
Step 2:

Collect all the variables (manufactured data, user input data, live data), variable parameters depends
on the availability. Our code can run without them. Fluid level is needed to be collected from any
prior available data.

Initialize the following parameters with default values (will remain same). Young’s Modulus of rod
material (E), Diameter of Rod (Drod), Diameter of Pump (Dpmp), Length of Sucker Rod Assembly till
pump (for untapered String) (L), Strokes per minute (SPM), Fluid Level (Fl), Polished Rod Horsepower
(Hpr), Fluid Specific Gravity (Sg)

%Assumed Calibration Constant (lb/inch)


CC = 10000;
%Young's Modulus (psi)
E = 30.5e6;
% Rod Diameter Drod (inch)
Drod = 0.75;
% Pump Diameter Dpmp (inch)
Dpmp = 1.5;
% Area of pump (inch^2)
A = pi/4*(Drod)^2;
%Average unit weight of rods in air (pounds/feet)
Wr =1.634;
%Tubing Pressure
Pt = 60;
%Casing Pressure
Pc = 0
%Gravitational Constant
Gc = 32.2;
%Density of steel (pounds/ft^3)
Rho = 490;
%Strokes Per minutes (Cycle speed)
SPM = 11;
%Length of Plunger (inch)
Lp = 48;
%Water Cut (percentage)
Wcut = 97;
%Oil API Gravity (degree API)
APIO = 38;
%Fluid Viscosity
Fviscosity = (((100-Wcut)/100)*(141.5/(131.5+APIO)))+(Wcut/100)
%Tubing OD (inch)
ODt = 2.875;
%Tubing ID (inch)
IDt = 2.441;
% Plunger Clearance (fit, tolerance) (inch)
Clearance = 0.003;
% Pump Intake Pressure (psi)
PIP =100;
%Number of rod elements (no of nodes)
M = 100;
%Time step of the dataset (time increment) (s)
DT = 0.02;
% Time period of the stroke T (s)
T = 60/SPM;
% Polished Rod Horsepower Hpr (HP)
Hpr = 8;
% Fluid Specifc Gravity Sg
Sg=0.995;
% Total Length of Rod (ft)
L = 2710;
% Fluid level Fl (ft)
Fl = 2710;
% Net Lift (ft)
Ln= Fl+(Pt/(0.433*Sg))
%Differential fluid load on full plunger area (pounds)
Fo = 0.34*Fl*Dpmp^2*Sg
%Total weight of rod in air (pounds)
W = L*Wr;
%Total Weight of rod in fluids (Buoyant Weight) (pounds)
Wrf = W*(1-(0.128*Sg))
% Calculating Production Rate Q (bbl/d)
Q= 0.1166*SPM*nS*Dpmp^2
% Calculating Hydraulic Horsepower Hh (HP)
Hh = 7.36e-6*Q*Sg*Ln
% Initially Damping Factor will be taken 0.5, after net stroke length is
%calculated iterations will be done to find the correct damping factor
C=0.5;
% Rod element length (ft)
DX=L/(M-1);
%Pressure difference across plunger (psi)
PDpl = 0.433*Sg*L
Calculating Production Loss due to Slippage
%Production loss due to slippage (bpd)
Qs = (453*(1+(0.14*SPM))*Dpmp*PDpl*Clearance^1.52)/(Fviscosity*Lp)
i=1:9
Clearance(i)=Clearance+(i*0.001)
j=1:10
Clearance(j) = horzcat(0.003,Clearance(i))
Qs = (453*(1+(0.14*SPM))*Dpmp*PDpl*Clearance.^1.52)/(Fviscosity*Lp)

Inputting Static Load and Position Data (integrate this data in


real time)
load case1s
plot(X,F,'b')
Calculating Surface Parameters from Surface Data
%Calculation of surface parameters from Surface Data
F1=F/CC;
[Xmin, IXmin] = min(X);
X = circshift(X, 1 - IXmin);
F = circshift(F, 1 - IXmin);
[Xmax, IXmax] = max(X);
Xu = X(1:IXmax);
Xd = [X(IXmax: end); X(1)];
Fu = F(1:IXmax);
Fd = [F1(IXmax: end); F1(1)];
plot(Xd,Fd,'r-')
%Area of surface dynacard A2 (Inch^2)
A2=polyarea(X,F1)
%Area under downstroke curve A1 (Inch^2)
A1 = abs(trapz(Xd,Fd))
%Maximum Deflection D1 (inch)
D1 = max(F1)
%Minimum Deflection D2 (inch)
D2 = min(F1)
%Load at counterbalance line (inch)
D3 =(1.06*(Wrf+0.5*Fo))/CC
%Length of surface card (inch)
L = max(X)-min(X)
%Peak Polished Rod Load (pounds)
PPRL =CC*D1
%Minimum Polished Rod Load (pounds)
MPRL =CC*D2
%Range of Load (pounds)
ROL = CC*(D1-D2)
%Average Upstroke Load (pounds)
AUL = (CC*(A1+A2))/L
%Average Downstroke Load (pounds)
ADL = CC*A1/L
%Approximate "ideal" counterbalance (pound)
AICB = (PPRL+MPRL)/2
%Actual Counterbalance Effect (pound)
ACBE = CC*D3
%Correct Counterbalance (pounds)
CCB = (AUL+ADL)/2
%Polished rod horsepower (friction+useful work) (HP)
PRHP = (CC*S*SPM*A2)/(33000*12*L)
%Ratio of peak and minimum load
LR = MPRL/PPRL;
N=2*length(X)
%Velocity of wave propogation (ft/s)
V = sqrt(144*E*Gc/Rho);
%To establish the stability criteria
Cest = DX/V/DT;
if Cest >= 1
disp(['Attention. Stability Coefficient: ' num2str(Cest) ' >= 1'])
end

Time step is needed to be adjusted from our end to satisfy the stability
coefficient, Cest<=1)

Step 3:
Calculate buoyant weight of the rod
Step 4:
Obtain DDC using evenly time spaced live load and position data from Finite Difference Method

We have Surface Position (X) and Load (F) data which is to be used to find pump position and load
data which is situated below the earth. The pump data travel as wave through the sucker rod which
faces friction, rod movement and elasticity as it moves up and loses energy. Wave equation is used
on the surface data to model those damping and frictional loss to calculate those losses and find the
representative load and position data at the pump level.

WHAT IS ALPHA, A2 and A3


Alpha = (DX/DT^2)*Rho*A/144/Gc;
A1 = Alpha*(1 + C*DT)./(E*A./DX);
A2 = -(Alpha*(2 + C*DT) - 2*E*A./DX)/(E*A./DX);
A3 = Alpha./(E*A./DX);
A4 = -1

U = NaN(M + 1, N);
U(1,:) = repmat(-X'/12, 1, 2);
U(2,:) = repmat(F'*DX/E/A, 1,2) + U(1,:);
% loop for calculating position value at increasing distance from surface,
calculating data at each node, pump is situated at last node
for i = 3:M + 1
U(i,i-1:N-i+2) = A1*U(i-1,i:N-i+3) + A2*U(i-1,i-1:N-i+2) + A3*U(i-1,i-2:N-i+1)
+ A4*U(i-2,i-1:N-i+2);
End
% After position data for last node is calculated, load at pump is calculated
from the position using Hooke’s Law
Fp = (E*A/DX*(U(M+1,:) - U(M,:)))-Wrf;
Xp = -12*(U(M+1,:) - max(U(M+1,:)));
% plot(Up, Fpj,'r.')
plot(Xp, Fp,'r-')
hold off
xlabel('Displacement (in)')
ylabel('Load (lbs)')
title('Surface and Downhole Dynamometer Cards')
legend('Surface', 'Downhole')
Xp=Xp'
Fp=Fp'
nanRows = any(isnan(Fp), 2)#deleting nan values from matrix
badRows = nanRows
Fp(badRows, :) = []
nanRows = any(isnan(Xp), 2)
badRows = nanRows
Xp(badRows, :) = []
k=1:(length(Xp))#find len of Xp after removing nan
plot(k,Xp,'b-')
xlabel('Number of recorded points')
ylabel('Downhole Position (inch)')
title('Position vs Time')
plot(k,Fp,'b-')# do the same with Fp
xlabel('Number of recorded points')
ylabel('Load (lbs)')
title('Load vs Time')
%differentiation of p wrt t (dp/dt) by using central difference
i=2:(length(Xp)-1)
j=1:(length(Xp)-2)
dp(j) = (Xp(i+1)-Xp(i-1))/(2*DT)
dp(k) = horzcat(nan,dp(j),nan)
plot(k,dp(k),'b-')
hold on
Determine TOS by methods of Position
%Finding TOS by finding the point where velocity becomes zero first
(intersection point)
ax=zeros(1,length(Xp))#creating zero valued matrix of size
absDiff = abs(dp(k) - ax);#mod of differnece
[sortedDiffs, indexes] = sort(absDiff);#sorting the absDifference
TOS = Xp(min(k(indexes(1:3))));
tosindex = k(min(indexes(1:3)))
ax = gca;
ax.XAxisLocation = 'origin'
xlabel('Number of recorded points')
ylabel('Velocity (inch/sec)')
title('First derivative of downhole position')
hold off
%differentiation of f wrt t (df/dt) by using central difference
df(j) = (Fp(i+1)-Fp(i-1))/(2*DT)
df(k) = horzcat(nan,df(j),nan)
plot(k,df(k),'b-')
ax = gca;
ax.XAxisLocation = 'origin'
xlabel('Number of recorded points')
ylabel('lbs/sec')
title('First derivative of downhole load')
%Calculating ratio (df/dp)
ratio(k) = df(k)./dp(k)
plot(k,ratio(k),'b-')
xlabel('Number of recorded points')
ylabel('Ratio')
title('df/dp vs Time')
%differention of dp wrt t (d2p/dt2) by using central difference
dp2(j) = (Xp(i+1)+Xp(i-1)-(2*Xp(i)))/(DT^2)
dp2(k) = horzcat(nan,dp2(j),nan)
plot(k,dp2(k),'b-')
ax = gca;
ax.XAxisLocation = 'origin'
xlabel('Number of recorded points')
ylabel('Acceleration (inch/sec2)')
title('Second derivative of downhole position')
Determining TP using method of position

%Pump fillage calculation using method of position


%Determinig TP using method of position
[dp2min, Idp2min] = min(dp2)#
i=tosindex:Idp2min
[TP, ITP] = max(dp2(i))
ITP = ITP+tosindex
TP = Xp(ITP)
fillage = 100*TP/TOS
fprintf('Results from using Method of Position for Pump Fillage')
fprintf('Determined TOS', TOS)
disp(TOS)
fprintf('Determined TP', TP)
disp(TP)
fprintf('Determined Fillage', fillage)
disp(fillage)
%Pump fillage calculation using method of loads
[dfmin, Idfmin] = min(df)
TP1 = Xp(Idfmin)
fillage1 = 100*TP1/TOS
fprintf('Results from using Method of loads for Pump Fillage')
fprintf('Determined TOS', TOS)
disp(TOS)
fprintf('Determined TP', TP1)
disp(TP1)
fprintf('Determined Fillage', fillage1)
disp(fillage1)

Calculating Net Stroke Length from Downhole Dynacard which is equal to


Transfer Point
nS1 = TP1
%Pump fillage calculation using method of ratios
i=tosindex:length(Xp)
[ratiomax, Iratiomax] = max(ratio(i))
Iratiomax= tosindex+Iratiomax
TP = Xp(Iratiomax)
fillage = 100*TP/TOS
fprintf('Results from using Method of ratios for Pump Fillage')
fprintf('Determined TOS', TOS)
disp(TOS)
fprintf('Determined TP', TP)
disp(TP)
fprintf('Determined Fillage', fillage)
disp(fillage)
%Method of areas for pump fillage
Xpmax = max(Xp)
Xpmin = min(Xp)
Fpmax = max(Fp)
Fpmin = min(Fp)
Areaestimated = (Xpmax-Xpmin)*(Fpmax-Fpmin)
Areaactual = polyarea(Xp,Fp)
fillage= (Areaactual/Areaestimated)*100
TP = TOS*(fillage/100)
Comparing assumed net stroke with the calculated net stroke from downhole
dynacard
S=nS
nS = nS1
end
end %Here Iteration for net stroke length ends and we use this stroke length
for calculating damping factor
sprintf('Net Stroke Length after Iteration', TP1)
disp(TP1)
sprintf('Fillage', fillage)
disp(fillage)
Q= 0.1166*SPM*TP1*Dpmp^2
sprintf('Production from Pump B/D', Q)
disp(Q)

Step 5: Calculation of Damping Factor

% Now the fixed net stroke length is calculated, we will now use this net
% stroke length to calculate damping factor. From this damping factor pump we
% will calculate new downhole dynacard. Now we will find pump horsepower from
% the area of the DDC. This pump horsepower is compared with the hydraulic
% horsepower and accordingly adjustments are done to find correct damping
factor
% using iteration
% Calculating production from now fixed net stroke length
Q= 0.1166*SPM*nS*Dpmp^2
%Hydraulic horsepower as calculated from net stroke length
Hh = 7.36e-6*Q*Sg*Fl
%Now damping factor is calculated from the fixed net stroke length, from this
%damping factor DDC will be calculated
C1 = (550*144*Gc*(PRHP-Hh)*(T^2))/((2^0.5*pi)*(Rho*A*L)*nS^2);
%Calculating new DDC from the new damping factor
A1 = Alpha*(1 + C1*DT)./(E*A./DX);
A2 = -(Alpha*(2 + C1*DT) - 2*E*A./DX)/(E*A./DX);
U = NaN(M + 1, N);
U(1,:) = repmat(-X'/12, 1, 2);
U(2,:) = repmat(F'*DX/E/A, 1,2) + U(1,:);
for i = 3:M + 1
U(i,i-1:N-i+2) = A1*U(i-1,i:N-i+3) + A2*U(i-1,i-1:N-i+2) + A3*U(i-1,i-2:N-i+1)
+ A4*U(i-2,i-1:N-i+2);
end
Fp = (E*A/DX*(U(M+1,:) - U(M,:)))-3871;
Xp = -12*(U(M+1,:) - max(U(M+1,:)));
Fp=Fp'
Xp=Xp'
nanRows = any(isnan(Fp), 2)
badRows = nanRows
Fp(badRows, :) = []
nanRows = any(isnan(Xp), 2)
badRows = nanRows
Xp(badRows, :) = []
Hpump=(nS*SPM*polyarea(Xp,Fp))/(33000*12*(max(Xp)-min(Xp)))
for i=1:20
if abs(Hh==Hpump);
sprintf('Final damping factor is', C1)
disp(C1)
else
A1 = Alpha*(1 + C1*DT)./(E*A./DX);
A2 = -(Alpha*(2 + C1*DT) - 2*E*A./DX)/(E*A./DX);
U = NaN(M + 1, N);
U(1,:) = repmat(-X'/12, 1, 2);
U(2,:) = repmat(F'*DX/E/A, 1,2) + U(1,:);
for i = 3:M + 1
U(i,i-1:N-i+2) = A1*U(i-1,i:N-i+3) + A2*U(i-1,i-1:N-i+2) + A3*U(i-1,i-2:N-i+1)
+ A4*U(i-2,i-1:N-i+2);
end
Fp = (E*A/DX*(U(M+1,:) - U(M,:)))-3871;
Xp = -12*(U(M+1,:) - max(U(M+1,:)));
Xp=Xp'
Fp=Fp'
nanRows = any(isnan(Fp), 2)
badRows = nanRows
Fp(badRows, :) = []
nanRows = any(isnan(Xp), 2)
badRows = nanRows
Xp(badRows, :) = []
Hpump=(nS*SPM*polyarea(Xp,Fp))/(33000*12*(max(Xp)-min(Xp)))

C2=C1*(Hpump/Hh)
C1=C2
end
end
if C1>=1
sprintf('Final Damping factor', 0.99)
disp(0.99)
else
sprintf('Final Damping factor', C1)
disp(C1)
end
Hpump=(nS*SPM*polyarea(Xp,Fp))/(33000*12*(max(Xp)-min(Xp)))
%Net Production after consdering Slippage
Qnet = Q-Qs

Plotting Surface Dynacard from Surface Data


plot(X,F,'r-')
hold on
plot(Xp,Fp,'b-')
hold off
xlabel('Displacement (in)')
ylabel('Load (lbs)')
title('Surface and Downhole Dynamometer Cards')
legend('Surface', 'Downhole')
plot(Clearance,Qs,'g-')
xlabel('Clearance (in)')
ylabel('Slippage (bpd)')
title('Clearance vs Slippage')
fprintf('Determined Net Stroke Length', nS)
disp(nS)
fprintf('Determined fillage', fillage1)
disp(fillage1)
fprintf('Determined Production', Q)
disp(Q)
plot(Clearance,Qnet,'b-')
xlabel('Clearance (in)')
ylabel('Net Production based considering slippage')
title('Net Production due to Slippage')
fprintf('Determined PPRL', PPRL)
disp(PPRL)
fprintf('Determined MPRL', MPRL)
disp(MPRL)
fprintf('Determined Polished Rod Horsepower', PRHP)
disp(PRHP)
fprintf('Determined Pump Horsepower', Hpump)
disp(Hpump)
fprintf('Determined Hydraulic Horsepower', Hh)
disp(Hh)
fprintf('Range of Load', ROL)
disp(ROL)
fprintf('Average Upstroke Load', AUL)
disp(AUL)
fprintf('Determined Downstroke Load', ADL)
disp(ADL)
fprintf('Determined Approximate "ideal" counterbalance', AICB)
disp(AICB)
fprintf('Determined Actual Counterbalance Effect', ACBE)
disp(ACBE)
fprintf('Correct Counterbalance', CCB)
disp(CCB)
fprintf('Ratio of peak and minimum load', LR)
disp(LR)
fprintf('Determined Damping Factor', C1)
disp(C1)

You might also like