Ecuación de balance de materia: ejemplo 1, parte 1

Ejemplo de cálculo usando la ecuación de balance de materia con un modelo sin capa de gas ni acuífero. Método de Diagnóstico de Havlena-Odeh y Gráfico de Campbell

Author
Published

March 30, 2025

Un yacimiento con una presión inicial de 5200 psi y temperatura de 123 °F tiene las siguientes propiedades:

Porosidad = 0.2

\(S_{wc} = 0.15\)

\(c_f = 3.50 \times 10^{-6} \text{ psi}^{-1}\)

\(c_w = 7.00 \times 10^{-6} \text{ psi}^{-1}\)

API = 30°

GOR = 800 scf/stb

\(g_g = 0.8\)

📌 Carga de Datos de Producción y Propiedades de Fluidos

Ver código
import pandas as pd

# Cargar datos del archivo CSV
file_path = "MB_ex.csv"
df = pd.read_csv(file_path)
print(df)
          Date     Pavg     Np     Gp     Bo     Rs     Bg     Rp
0   01/01/2003  5200.00   0.00   0.00  1.376  0.800  0.545  0.800
1   02/04/2003  3940.89   3.89   3.11  1.389  0.800  0.613  0.800
2   02/07/2003  3512.38   6.07   4.85  1.364  0.747  0.651  0.800
3   01/10/2003  3322.18   7.74   6.17  1.336  0.696  0.673  0.798
4   31/12/2003  3178.82   9.22   7.51  1.316  0.658  0.692  0.814
5   31/03/2004  3058.58  10.57   8.98  1.299  0.627  0.709  0.850
6   30/06/2004  2952.10  11.79  10.63  1.285  0.600  0.727  0.901
7   29/09/2004  2854.95  12.90  12.47  1.272  0.576  0.745  0.966
8   29/12/2004  2764.87  13.91  14.50  1.261  0.554  0.763  1.042
9   30/03/2005  2680.77  14.83  16.70  1.250  0.533  0.781  1.126
10  29/06/2005  2602.16  15.65  19.04  1.241  0.515  0.800  1.216
11  28/09/2005  2528.94  16.39  21.47  1.232  0.497  0.820  1.310
12  28/12/2005  2461.18  17.05  23.94  1.224  0.482  0.839  1.404
13  29/03/2006  2399.03  17.62  26.40  1.216  0.467  0.858  1.498
14  28/06/2006  2342.59  18.13  28.79  1.210  0.455  0.877  1.588
15  27/09/2006  2291.91  18.56  31.07  1.204  0.443  0.895  1.674
16  27/12/2006  2246.93  18.94  33.20  1.199  0.433  0.912  1.753
17  28/03/2007  2207.46  19.26  35.14  1.195  0.424  0.928  1.825
18  27/06/2007  2173.21  19.53  36.89  1.191  0.417  0.943  1.889
19  26/09/2007  2143.79  19.76  38.44  1.188  0.410  0.956  1.945
20  26/12/2007  2118.77  19.95  39.79  1.185  0.405  0.967  1.994
21  26/03/2008  2097.66  20.11  40.95  1.183  0.400  0.977  2.037
22  25/06/2008  2080.00  20.24  41.94  1.181  0.397  0.986  2.072
23  24/09/2008  2065.32  20.35  42.77  1.179  0.393  0.993  2.102
24  24/12/2008  2053.19  20.43  43.47  1.178  0.391  0.999  2.127
25  25/03/2009  2043.21  20.51  44.05  1.177  0.389  1.004  2.148
26  24/06/2009  2035.03  20.56  44.52  1.176  0.387  1.008  2.165
27  23/09/2009  2028.36  20.61  44.91  1.176  0.385  1.012  2.179
28  23/12/2009  2022.92  20.65  45.23  1.175  0.384  1.015  2.190
29  24/03/2010  2018.51  20.68  45.50  1.174  0.383  1.017  2.200
30  23/06/2010  2014.94  20.71  45.80  1.174  0.383  1.019  2.212
Ver código

# Unidades del CSV: Np en MMSTB, Gp en miles de MMscf (10^9 scf),
# Rs y Rp en Mscf/STB, Bg en RB/Mscf. M=10^3 y MM=10^6.
# Por eso (Rp-Rs)*Bg es RB/STB y F resulta en MMRB.
# Rp es Gp/Np acumulados, no el GOR instantáneo.
# Las columnas Rp, Rs y Bg se conservan con el redondeo publicado.

📌 Ecuaciones del Balance de Materia

Las siguientes ecuaciones permiten crear los gráficos de diagnóstico de Campbell y Havlena-Odeh. En este ejemplo se supone \(m=0\), sin acuífero, sin inyección y sin producción de agua reportada. En el caso general, \(F\) incluye además \(W_p B_w\). Aquí \(W_e\), cuando se menciona, se expresa en RB (ya a condiciones de yacimiento).

\[ F = NE_t \]

Donde:

\[ F = N_p(B_o+(R_p-R_s)B_g) \]

Y:

\[ E_t = B_{oi} \left[ \frac{(B_o - B_{oi}) + (R_{si} - R_s)B_g}{B_{oi}} + m \left( \frac{B_g}{B_{gi}} -1 \right) + (1 + m) \left( \frac{c_w S_{wc} + c_f}{1 - S_{wc}} \Delta p \right) \right] \]

Reordenando la ecuación:

\[ \frac{F}{E_t} = N \]

En el caso del gráfico de Campbell, el yacimiento es volumétrico, por lo que:

\[ W_e = 0 \]

En esta variante del gráfico, el eje horizontal es la producción acumulada \(N_p\) y el vertical es \(F/E_t\). Para un modelo volumétrico consistente, \(F/E_t\) se aproxima a una horizontal igual a \(N\). El manual de MBAL usa también \(F\) como eje horizontal. No se trata del término independiente de una regresión de \(N_p\).

📌 Reorganización de la Ecuación de Havlena-Odeh

En los métodos de diagnóstico de Havlena-Odeh, la ecuación (1) se reorganiza de la siguiente forma:

\[ F - W_e = N E_t \]

Por lo tanto, un gráfico de ( (F - W_e) ) contra ( E_t ) producirá una línea recta que pasa por el origen, cuya pendiente representa el petróleo original en sitio ( N ).

📌 Cálculo de ( F ) y ( E_t ) en Python

Ver código
import numpy as np

# Si el archivo fue cargado correctamente
# Extraer columnas relevantes
Np = df["Np"]  # Producción acumulada de petróleo (MMSTB)
Bo = df["Bo"]  # Factor de volumen de formación del petróleo
Bg = df["Bg"]  # Factor de volumen de formación del gas
Rp = df["Rp"]  # Razón gas-petróleo acumulada (Mscf/STB)
Rs = df["Rs"]  # Razón gas disuelto
Pavg = df["Pavg"]  # Presión promedio del yacimiento (psia)

#Parámetros iniciales
Sw = 0.15
cf = 0.0000035
cw = 0.000007
Boi = Bo.iloc[0]  # Bo inicial
Rsi = Rs.iloc[0]  # Rs inicial
Pi = Pavg.iloc[0]  # Presión inicial

# Cálculo de F y Et
F = Np * (Bo + (Rp - Rs) * Bg)
Et = Boi*(((Bo-Boi)+(Rsi-Rs)*Bg)/Boi+(Pi-Pavg)*(cw*Sw+cf)/(1-Sw))

# Agregar los resultados al dataframe
df["F"] = F
df["Et"] = Et
df["F_Et"] = F / Et.where(Et > 0)  # Excluir 0/0 del estado inicial

# Mostrar los resultados calculados
print(df)
          Date     Pavg     Np     Gp  ...     Rp          F        Et        F_Et
0   01/01/2003  5200.00   0.00   0.00  ...  0.800   0.000000  0.000000         NaN
1   02/04/2003  3940.89   3.89   3.11  ...  0.800   5.403210  0.022274  242.577499
2   02/07/2003  3512.38   6.07   4.85  ...  0.800   8.488913  0.034933  243.002685
3   01/10/2003  3322.18   7.74   6.17  ...  0.798  10.871960  0.043823  248.085957
4   31/12/2003  3178.82   9.22   7.51  ...  0.814  13.128837  0.053151  247.008781
5   31/03/2004  3058.58  10.57   8.98  ...  0.850  15.401621  0.061430  250.718461
6   30/06/2004  2952.10  11.79  10.63  ...  0.901  17.730120  0.070957  249.870497
7   29/09/2004  2854.95  12.90  12.47  ...  0.966  20.156895  0.080153  251.480826
8   29/12/2004  2764.87  13.91  14.50  ...  1.042  22.719815  0.090634  250.675660
9   30/03/2005  2680.77  14.83  16.70  ...  1.126  25.405762  0.101083  251.336258
10  29/06/2005  2602.16  15.65  19.04  ...  1.216  28.198170  0.112135  251.466778
11  28/09/2005  2528.94  16.39  21.47  ...  1.310  31.119037  0.124134  250.688901
12  28/12/2005  2461.18  17.05  23.94  ...  1.404  34.058364  0.134975  252.330566
13  29/03/2006  2399.03  17.62  26.40  ...  1.498  37.012537  0.146345  252.912964
14  28/06/2006  2342.59  18.13  28.79  ...  1.588  39.952011  0.157612  253.483834
15  27/09/2006  2291.91  18.56  31.07  ...  1.674  42.794627  0.168935  253.320130
16  27/12/2006  2246.93  18.94  33.20  ...  1.753  45.509790  0.179455  253.599625
17  28/03/2007  2207.46  19.26  35.14  ...  1.825  48.056165  0.189970  252.967137
18  27/06/2007  2173.21  19.53  36.89  ...  1.889  50.369745  0.198463  253.798830
19  26/09/2007  2143.79  19.76  38.44  ...  1.945  52.471890  0.207351  253.058334
20  26/12/2007  2118.77  19.95  39.79  ...  1.994  54.295182  0.213660  254.119244
21  26/03/2008  2097.66  20.11  40.95  ...  2.037  55.953038  0.220651  253.581919
22  25/06/2008  2080.00  20.24  41.94  ...  2.072  57.330812  0.225339  254.420487
23  24/09/2008  2065.32  20.35  42.77  ...  2.102  58.527353  0.230240  254.201557
24  24/12/2008  2053.19  20.43  43.47  ...  2.127  59.497554  0.233769  254.513983
25  25/03/2009  2043.21  20.51  44.05  ...  2.148  60.361668  0.236896  254.802610
26  24/06/2009  2035.03  20.56  44.52  ...  2.165  61.026685  0.239616  254.685297
27  23/09/2009  2028.36  20.61  44.91  ...  2.179  61.655392  0.243341  253.370152
28  23/12/2009  2022.92  20.65  45.23  ...  2.190  62.117058  0.244641  253.910812
29  24/03/2010  2018.51  20.68  45.50  ...  2.200  62.492665  0.245523  254.529036
30  23/06/2010  2014.94  20.71  45.80  ...  2.212  62.911823  0.246383  255.341546

[31 rows x 11 columns]

📊 Gráfico de Campbell

El gráfico de Campbell permite evaluar si \(F/E_t\) se mantiene aproximadamente constante. Con este CSV, los valores están entre 242.6 y 255.3 MMSTB. La referencia de 250 MMSTB ayuda a comparar; no es una estimación única obtenida de una intersección.

Ver código
import matplotlib.pyplot as plt

# Gráfico de Np vs F_ET
plt.figure(figsize=(8,5))
plt.scatter(df["Np"], df["F_Et"], color='blue', label="Datos")

# Calcular la regresión lineal solo con datos limpios
df_clean = df.dropna(subset=["F_Et"])
coeficientes = np.polyfit(df_clean["Np"], df_clean["F_Et"], 1)  # Ajuste lineal (grado 1)
polinomio = np.poly1d(coeficientes)  # Crear función polinómica

# Evaluar la línea de ajuste en los valores de Np limpios
ajuste_y = polinomio(df_clean["Np"])

# Graficar la línea de ajuste
plt.plot(df_clean["Np"], ajuste_y, 'r--', label=f"Ajuste lineal: y = {coeficientes[0]:.2f}x + {coeficientes[1]:.2f}")

# Agregar línea horizontal en y=250 (similar a geom_hline)
plt.axhline(y=250, color='black', linestyle='-', linewidth=1)

# Agregar texto en (x=2, y=270) (similar a geom_text)
plt.text(5, 270, "N = 250 MMSTB", fontsize=12, color="black")

plt.xlabel("Np acumulado (MMSTB)")
plt.ylabel("F/Et (MMSTB)")
plt.ylim(-0, 400)
(0.0, 400.0)
Ver código
plt.title("Gráfico de Campbell ")
plt.legend()
plt.grid()
plt.show()

📊 Gráfico de Havlena-Odeh

El ajuste físico se hace por el origen, porque \(F=NE_t\). Con el CSV publicado y mínimos cuadrados no ponderados se obtiene N ≈ 253.76 MMSTB. Un ajuste con intercepto libre produce otra pendiente y sirve para explorar desviaciones, pero no es el mismo ajuste.

Ver código
# Gráfico de Et vs F
plt.figure(figsize=(8,5))
plt.scatter(df["Et"], df["F"], color='blue', label="Datos")

# Ajuste por el origen: N = sum(Et*F) / sum(Et^2)
mask = (df["Et"] > 0) & np.isfinite(df["F"])
x = df.loc[mask, "Et"]
y = df.loc[mask, "F"]
N_ajustado = np.dot(x, y) / np.dot(x, x)
x_linea = np.array([0, x.max()])
plt.plot(x_linea, N_ajustado*x_linea, 'r--',
         label=f"Origen fijo: N = {N_ajustado:.2f} MMSTB")

plt.xlabel("Et (RB/STB)")
plt.ylabel("F (MMRB)")
plt.ylim(-0, 70)
(0.0, 70.0)
Ver código
plt.title("Havlena–Odeh")
plt.legend()
plt.grid()
plt.show()

📈 Interpretación de los Gráficos

  1. Una relación aproximadamente lineal y coherente con el origen es compatible con el modelo volumétrico supuesto.
  2. Las desviaciones pueden sugerir entrada de agua, pero también errores de presión promedio, PVT, producción o un modelo incompleto. Una curva por sí sola no identifica el mecanismo.
  3. La pendiente del ajuste por el origen estima el petróleo original en sitio, N. No representa reservas recuperables.

La presión utilizada es la presión promedio del yacimiento, no la presión de fondo fluyente de un pozo. Las propiedades PVT y las unidades deben corresponder a cada registro de presión.

Referencias

  • Dake, L.P. Fundamentals of Reservoir Engineering, capítulo 3, ecuaciones 3.8–3.12.
  • Ahmed, T. (2019). Reservoir Engineering Handbook, 5.ª ed., capítulo 11.
  • Petroleum Experts. MBAL Help, febrero de 2016, sección 2.16.2.1.6.