Tipo de roca con python

Python Ingenería de yacimientos Petrofísica

Cálculo de radio de garganta poral para agrupar datos petrofísicos en tipo de roca con Python

Rigoberto Chandomi https://www.linkedin.com/in/rigobertochandomi/
2023-12-20

La técnica de Tipo de roca (Rock Typing) es el proceso de dividir la roca del yacimiento en un número específico de grupos en función de los cambios de las propiedades petrofísicas; en este ejemplo utilizamos datos de núcleos, porosidad y permeabilidad del campo Volve. Este proceso se utiliza a menudo en la simulación de yacimientos para agrupar las funciones fluido-roca, la permeabilidad relativa y las curvas de presión capilar.

Existen varios métodos para estimar el tamaño de la garganta de los poros: Pittman, Winland, Kolodzie y Aguile, la mayoría de ellos ajustan el radio de garganta poral a partir del experimento de presión capilar por inyección de mercurio a una cierta saturación de mercurio, utilizando regresión lineal multiple.

En este ejemplo, utilizamos la correlación de Winland para estimar el radio de la garganta de los poros y, a continuación, agrupamos según este parámetro.

\[ log(R35) = 0.588\ log(k) - 0.588\ log(\phi)- 0.966\]

donde:

\(R35 = pore \ throat \ radius \ at \ mercury \ saturation \ of \ 35%, \ microns\)

\(k = air-permeability, \ md\)

\(\phi = porosity, \ fraction\)

Primero cargamos los datos de núcleos por medio de un archivo CSV, en el dataset tenemos 4 columnas: WELL, MD, POROSITY y PERMEABILIDAD, la primera nos indica a que pozo pertenece la muestra, MD es la profundidad desarrollada de la muestra y después tenemos las columnas de porosidad y permeabilidad.

import pandas as pd

data = pd.read_csv('Core_data.csv')
data
       WELL           MD  POROSITY  PERMEABILITY
0    WELL_1  4038.350098     0.201     1973.9240
1    WELL_1  4038.850098     0.203     1158.9270
2    WELL_1  4039.350098     0.207     1935.1169
3    WELL_1  4039.850098     0.206     1003.6810
4    WELL_1  4040.350098     0.190      901.4980
..      ...          ...       ...           ...
401  WELL_2  3918.350098     0.207       31.1830
402  WELL_2  3918.600098     0.198       29.8160
403  WELL_2  3918.850098     0.166        9.8900
404  WELL_2  3919.100098     0.202       31.8940
405  WELL_2  3919.350098     0.150        2.9790

[406 rows x 4 columns]

Usando la ecuación de Winland, se estima el radio de garganta poral (PTS). Para ello cargamos las librerías math y numpy para hacer uso de la función log10()

import math
import numpy as np

data["PTS"] = 10**(0.588*np.log10(data.PERMEABILITY) - 0.864*np.log10(data.POROSITY) - 0.996)

data
       WELL           MD  POROSITY  PERMEABILITY        PTS
0    WELL_1  4038.350098     0.201     1973.9240  34.969780
1    WELL_1  4038.850098     0.203     1158.9270  25.350609
2    WELL_1  4039.350098     0.207     1935.1169  33.696552
3    WELL_1  4039.850098     0.206     1003.6810  23.001544
4    WELL_1  4040.350098     0.190      901.4980  23.156673
..      ...          ...       ...           ...        ...
401  WELL_2  3918.350098     0.207       31.1830   2.974578
402  WELL_2  3918.600098     0.198       29.8160   3.010631
403  WELL_2  3918.850098     0.166        9.8900   1.832323
404  WELL_2  3919.100098     0.202       31.8940   3.078629
405  WELL_2  3919.350098     0.150        2.9790   0.987667

[406 rows x 5 columns]

Una vez que tenemos calculado el radio de garganta poral, se crea una variable categórica usando los siguientes rangos para la subdivisión, para ello usamos la función cut() de Pandas

Pore-throat radius, microns Rock Type
<0.1 Nano
0.1-0.5 Micro
0.5-2 Meso
2-10 Macro
>10 Mega

data["RT"] = pd.cut(data.PTS, bins = [0,0.1,0.5,2,10,10000000], 
                    labels = ["Nano", "Micro", "Meso", "Macro", "Mega"])
data["RT_n"] = pd.cut(data.PTS, bins = [0,0.1,0.5,2,10,10000000], 
                      labels = [1,2,3,4,5])

data
       WELL           MD  POROSITY  PERMEABILITY        PTS     RT RT_n
0    WELL_1  4038.350098     0.201     1973.9240  34.969780   Mega    5
1    WELL_1  4038.850098     0.203     1158.9270  25.350609   Mega    5
2    WELL_1  4039.350098     0.207     1935.1169  33.696552   Mega    5
3    WELL_1  4039.850098     0.206     1003.6810  23.001544   Mega    5
4    WELL_1  4040.350098     0.190      901.4980  23.156673   Mega    5
..      ...          ...       ...           ...        ...    ...  ...
401  WELL_2  3918.350098     0.207       31.1830   2.974578  Macro    4
402  WELL_2  3918.600098     0.198       29.8160   3.010631  Macro    4
403  WELL_2  3918.850098     0.166        9.8900   1.832323   Meso    3
404  WELL_2  3919.100098     0.202       31.8940   3.078629  Macro    4
405  WELL_2  3919.350098     0.150        2.9790   0.987667   Meso    3

[406 rows x 7 columns]
data.to_csv('RT_cores.csv')

Ahora podemos crear un gráfico semilog porosidad contra permeabilidad coloreado por tipo de roca usando la librería matplotlib. Esto nos muestra a que tipo de roca pertenece cada muestra en la cual el tipo de Mega es mejor calidad y el tipo de roca Nano de peor calidad.


import matplotlib.pyplot as plt

plt.scatter(data.POROSITY,data.PERMEABILITY, c = data.RT_n, alpha=0.8);
plt.xlabel('Porosity');
plt.ylabel('Permeability');
plt.yscale('log');
plt.ylim(0.0001,100000);
plt.show();