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.