Introduction - Decline Curve Analysis
Decline curve analysis (DCA) is a graphical procedure used to analyze declining production rates and forecast the future performance of oil and gas wells. Fitting a line through the performance history and assuming this same trend will continue in future forms the basis of the DCA concept.
The underlying premise of decline curve analysis is the expectation that historical trends will continue to hold into the future, given the same conditions.
Typically, decline analysis is conducted on a plot of rate versus time or rate versus cumulative production.
DCA is essentially a curve fitting or trend-line analysis procedure where the coefficients of the various decline curves are parameterized to find the best fit.
We can use non-linear regression to estimate the coefficients. The nls and nlsLM are R function that iteratively try to find the best coefficent values that fit the data. To that extend, lets look at a simple example.
Before we begin, let import the necessary packages - plotly & minpack.lm packages. Let’s also read the production data. For the purpose of this example, I have a csv file that has the data.
library(plotly)
library(minpack.lm)
library(kableExtra)
prod.data <- read.csv("ProductionData.csv")
head(prod.data)
## DAYS RATE
## 1 1 3635
## 2 2 4757
## 3 3 3580
## 4 4 2979
## 5 5 5042
## 6 6 2849
Data Visualization
Let’s visualize the data using plotly package.
# t1 & t2 are lists for fonts that we will use later.
t1 <- list(family = "Arial, sans-serif", size = 13, color = "black")
t2 <- list(family = "Arial, sans-serif", size = 12, color = "black")
fig.1 <- plot_ly(prod.data)
fig.1 <- fig.1 %>% add_trace(x=~prod.data$DAYS,y=prod.data$RATE,type="scatter",
name="Production History",marker = list(color = 'seagreen'))
fig.1 <- fig.1 %>% layout(title="Production Data History",
yaxis = list(title = "Oil Production Rate (bbl/d)",
titlefont=t1,tickfont=t2,
showgrid=F,range=c(0,6500)),
xaxis = list(title = "Production Days (days)",
titlefont=t1,tickfont=t2,
showgrid=F,range=c(0,150)),
legend = list(orientation = 'v',x=0.6,y=0.8),
showlegend=T)
fig.1
## No scatter mode specifed:
## Setting the mode to markers
## Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
## Warning: `arrange_()` is deprecated as of dplyr 0.7.0.
## Please use `arrange()` instead.
## See vignette('programming') for more help
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_warnings()` to see where this warning was generated.
Curve-Fitting
We are using nlsLM function. For a discussion about nls vs nlsLM, see ‘A better ’nls’’.
For this example, I will use the exponential decline curve.
DCA_Exp <- nlsLM(
RATE ~ (qi_est /(1+ d_est*DAYS)),
data = prod.data,
start = list(qi_est= 1,d_est= 10)
)
summary(DCA_Exp) # to view fit.
##
## Formula: RATE ~ (qi_est/(1 + d_est * DAYS))
##
## Parameters:
## Estimate Std. Error t value Pr(>|t|)
## qi_est 4.964e+03 2.231e+02 22.25 <2e-16 ***
## d_est 1.182e-01 9.680e-03 12.22 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 273 on 96 degrees of freedom
##
## Number of iterations to convergence: 24
## Achieved convergence tolerance: 1.49e-08
Let’s have a look at the coefficients that nlsLM estimated.
coefficients(DCA_Exp) %>%
kbl(caption = "Coefficents Estimated for Exponential Decline Curve",digits=2) %>%
kable_paper("hover", full_width = T, position = "center") %>%
row_spec(0,color="black",background = "grey")
x | |
---|---|
qi_est | 4964.15 |
d_est | 0.12 |
Now, finally, let visually review the fit..
prod.data$Predicted_Rate <- fitted(DCA_Exp)
fig.2 <- plot_ly(prod.data)
fig.2 <- fig.2 %>% add_trace(x=~prod.data$DAYS,y=prod.data$RATE,type="scatter",
name="Production History",marker = list(color = 'seagreen'))
fig.2 <- fig.2 %>% add_trace(x=~prod.data$DAYS,y=~prod.data$Predicted_Rate,type="scatter",
mode="lines",name="DCA Prediction",
line=list(width=3,color='red'))
fig.2 <- fig.2 %>% layout(title="Production Data History",
yaxis = list(title = "Oil Production Rate (bbl/d)",
titlefont=t1,tickfont=t2,
showgrid=F,range=c(0,6500)),
xaxis = list(title = "Production Days (days)",
titlefont=t1,tickfont=t2,
showgrid=F,range=c(0,150)),
legend = list(orientation = 'v',x=0.6,y=0.8),
showlegend=T)
fig.2
This technique can be applied to the other decline curves too.