1-Introduction
The data collected from wells comes from different scales such as the megascopic and mesoscopic to the microscopic. It is important to appreciate all the scales and the reliability of different datasets because sometimes we make upscaling or downscale.
For example we should make core scale correction to log scale than to reservoir scale.
Let’s load Data.
data = read.csv("karpur.csv")
head(data)
## depth caliper ind.deep ind.med gamma phi.N R.deep R.med SP
## 1 5667.0 8.685 618.005 569.781 98.823 0.410 1.618 1.755 -56.587
## 2 5667.5 8.686 497.547 419.494 90.640 0.307 2.010 2.384 -61.916
## 3 5668.0 8.686 384.935 300.155 78.087 0.203 2.598 3.332 -55.861
## 4 5668.5 8.686 278.324 205.224 66.232 0.119 3.593 4.873 -41.860
## 5 5669.0 8.686 183.743 131.155 59.807 0.069 5.442 7.625 -34.934
## 6 5669.5 8.686 109.512 75.633 57.109 0.048 9.131 13.222 -39.769
## density.corr density phi.core k.core Facies
## 1 -0.033 2.205 33.9000 2442.590 F1
## 2 -0.067 2.040 33.4131 3006.989 F1
## 3 -0.064 1.888 33.1000 3370.000 F1
## 4 -0.053 1.794 34.9000 2270.000 F1
## 5 -0.054 1.758 35.0644 2530.758 F1
## 6 -0.058 1.759 35.3152 2928.314 F1
2-Checking Outliers
Using plot-box, let’s first see if our interesting data contains any outliers:
par(mfrow = c(1,3))
boxplot(data$k.core, xlab = "Kcore", col = 'BLUE', cex = 2)
boxplot(data$phi.core, xlab = "PHIcore", col = 'BROWN', cex = 2)
boxplot(data$phi.N, xlab = "PHI.N", col = 'RED', cex = 2)
Core-Permeability and Log-Porosity both have glaring outliers (outliers shown by circles).
We employ the following to eliminate the outliers from the data:
quartiles1 = quantile(data$k.core, probs=c(.25, .75), na.rm = FALSE)
quartiles2 = quantile(data$phi.N, probs=c(.25, .75), na.rm = FALSE)
IQR1 = IQR(data$k.core)
IQR2 = IQR(data$phi.N)
Lower1 = quartiles1[1] - 1.5*IQR1
Upper1 = quartiles1[2] + 1.5*IQR1
Lower2 = quartiles2[1] - 1.5*IQR2
Upper2 = quartiles2[2] + 1.5*IQR2
sub1 = subset(data, data$k.core > Lower1 & data$k.core < Upper1)
new_data = subset(sub1, data$phi.N > Lower2 & data$phi.N < Upper2)
We calculate first (Q1) and third (Q3) quartiles by using quantile() function. Then, interquartile range (IQR) is found by IQR() function. Then, we calculate Q1 – 1.5IQR to find lower limit for outliers. After that, we calculate Q3 + 1.5IQR to find upper limit for outliers. Then, we use subset() function to eliminate outliers.
Let’s check it again:
par(mfrow = c(1,3))
boxplot(new_data$k.core, xlab = "kcore", col = 'BLUE', cex = 2)
boxplot(new_data$phi.core, xlab = "phi.core", col = 'BROWN', cex = 2)
boxplot(new_data$phi.N, xlab = "phi.N", col = 'RED', cex = 2)
Although there are fewer outliers than previously, we will retain the remainder to ensure that our model is not affected in any way.
3-Checking Normal distribution
define some required data:
kcore= new_data$k.core
phi.N= new_data$phi.N
phi.core= (new_data$phi.core) / 100
check that kcore is normal or not
hist(kcore,breaks = 10)
apply log to obtain normal distribution
hist((log(kcore)),breaks = 10)
4-Correlations between Data
All of the data is now ready for the correlation procedure:
Porosity log data is used to rectify porosity core data.
Finding the relationship between PHICORE and PHI.N using the Linear Regression model Lm()
Also we will plot best straight line between porosity from log and porosity from core
plot(phi.N,phi.core,col = 'black', pch = 16, cex = 1)
mod1=lm(phi.core ~ phi.N )
summary(mod1)
##
## Call:
## lm(formula = phi.core ~ phi.N)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.103280 -0.040444 0.009061 0.039229 0.093787
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.27170 0.01029 26.406 <2e-16 ***
## phi.N -0.04495 0.04096 -1.097 0.273
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.04538 on 642 degrees of freedom
## (47 observations deleted due to missingness)
## Multiple R-squared: 0.001872, Adjusted R-squared: 0.0003175
## F-statistic: 1.204 on 1 and 642 DF, p-value: 0.2729
abline(mod1,col = "red" , lwd = "3")
corrected values of phi core
model_input = data.frame(phi.N)
PhiCoreCorrected = predict(mod1, model_input)
The correction of core permeability by corrected core porosity
Using Linear Regression model Lm() to find the relation between KCORE and PHIcl
KcoreCorrected = lm(log(kcore) ~ PhiCoreCorrected)
summary(KcoreCorrected)
##
## Call:
## lm(formula = log(kcore) ~ PhiCoreCorrected)
##
## Residuals:
## Min 1Q Median 3Q Max
## -7.5710 -0.5593 0.1525 1.0367 2.0153
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -29.244 6.918 -4.227 2.71e-05 ***
## PhiCoreCorrected 138.565 26.547 5.220 2.42e-07 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.322 on 642 degrees of freedom
## (47 observations deleted due to missingness)
## Multiple R-squared: 0.04071, Adjusted R-squared: 0.03922
## F-statistic: 27.25 on 1 and 642 DF, p-value: 2.423e-07
plot the relationship between phi.core_to_log and log(kcore) and plot best straight line between them
plot(PhiCoreCorrected, log(kcore), col = 'black', pch = 16, cex = 1)
abline(KcoreCorrected, col = "red" , lwd = "3")
To get the corrected value of core permeability based on this model:
input_model2 = data.frame(PhiCoreCorrected)
KcoreCorrected = predict(KcoreCorrected, input_model2)
*The Verdict
Since there is a clear nonlinear relationship (small R2) between permeability and porosity, it is not appropriate to model using simple linear regression since permeability depends on a variety of factors, including facies and other variables in addition to porosity.