  Archie S_wa (Python 3.x)   Algorithm for computing apparent water saturation (S_wa) from effective (open) porosity Phi_e, formation water resistivity R_w and true formation resistivity R_t. The Archie Law is empirical. Any reliable computation should be based on Special Core Analysis. Formation water samples (for example, with MDT) should be also considered. $S_{\mathit{wa}}=\left[\frac{AR_w}{\phi _e^mR_t}\right]^{\frac 1 n}$   Download source code: Archie_Equation.py   import numpy as np def Archie_Swa( Phi_e, V_sh, R_t, R_w, A=1, m=2, n=2, formula=None, shale_cutoff=0.9, mcor=0, verbose=False): """ Solves Archie equation for apparent water saturation Phi_e - array-like, effective (connected) porosity, in v/v V_sh - total shale volume, in v/v R_t - array-like, true formation restistivity, environmentally corrected, Ohm m R_w - formation water restistivity, downhole conditions, Ohm m A = 1 - tortuosity exponent m = 2 - default cementation exponent, in carbonates n = 2 - default saturation exponent, in carbonates formula - None or one of the pre-sets: Archie carbonates: A = 1.00 M = 2.00 N = 2.00 Humble: A = 0.62 M = 2.15 N = 2.00 (for clean sandstones) Tixier: A = 0.81 M = 2.00 N = 2.00 (for clean sandstones) Average sands: A = 1.45 M = 1.54 N = 2.00 Shaly sands: A = 1.65 M = 1.33 N = 2.00 Calcareous sands: A = 1.45 M = 1.70 N = 2.00 Carbonates: A = 0.85 M = 2.14 N = 2.00 Pliocene sands: A = 2.45 M = 1.08 N = 2.00 (based on South California) Miocene sands: A = 1.97 M = 1.29 N = 2.00 (based on Louisiana and Texas) Clean granular: A = 1.00 M = 2.05 - PHIe N = 2.00 shale_cutoff - simple limit for NTG computation, in v/v; to ignore - set to > 1.0 mcor = 0 - m-factor correction, based on porosity verbose - print intermediate results returns: Apparent water saturation S_wa as an array, in v/v """ formulas = { "Archie carbonates": (1.00, 2.00, 2.00, 0), "Humble": (0.62, 2.15, 2.00, 0), "Tixier": (0.81, 2.00, 2.00, 0), "Average sands": (1.45, 1.54, 2.00, 0), "Shaly sands": (1.65, 1.33, 2.00, 0), "Calcareous sands": (1.45, 1.70, 2.00, 0), "Carbonates": (0.85, 2.14, 2.00, 0), "Pliocene sands": (2.45, 1.08, 2.00, 0), "Miocene sands": (1.97, 1.29, 2.00, 0), "Clean granular": (1.00, 2.05, 2.00, -1)} porosity = np.array(Phi_e) l = len(porosity) shale = np.array(V_sh) if len(shale) != l: shale = np.ones(l) * shale resistivity = np.array(R_t) if len(resistivity) != l: resistivity = np.ones(l) * resistivity water = np.array(R_w) if len(water) != l: water = np.ones(l) * water if formula is not None: A, m, n, mcor = formulas[formula] if verbose: print("Values from {:s} applied".format( formula)) if verbose: print("A={:.2f}, m={:.2f}, n={:.2f}," " mcor={:.2f}".format( A, m, n, mcor)) porosity = np.clip( porosity, 0, 1) porosity = np.clip(porosity ** (m + mcor*porosity), 0.0001, 1) S_wa = np.clip( A * water / resistivity / porosity, 0, 1) S_wa **= 1 / n for i, s in enumerate(shale): if s > shale_cutoff: S_wa[i] = 1.0 return S_wa if __name__ == "__main__": print("Archie carbonates (default):") print("Phi_e=0.33, V_sh=0.2, R_t = 20 Ohmm, R_w = 0.9 Ohmm, S_wa={:0.3f}".format( Archie_Swa( [0.33], [0.2], , [0.9], verbose=True))) print("Phi_e=0.33, V_sh=0.2, R_t = 20 Ohmm, R_w = 0.9 Ohmm, S_wa={:0.3f}".format( Archie_Swa( [0.33], [0.2], , [0.9], formula="Humble", verbose=True))) print("Phi_e=0.33, V_sh=0.2, R_t = 20 Ohmm, R_w = 0.9 Ohmm, S_wa={:0.3f}".format( Archie_Swa( [0.33], [0.2], , [0.9], formula="Average sands", verbose=True))) print("Phi_e=0.33, V_sh=0.2, R_t = 20 Ohmm, R_w = 0.9 Ohmm, S_wa={:0.3f}".format( Archie_Swa( [0.33], [0.2], , [0.9], formula="Clean granular", verbose=True))) print("Phi_e=-0.01, V_sh=0.2, R_t = 20 Ohmm, R_w = 0.9 Ohmm, S_wa={:0.3f}".format( Archie_Swa( [-0.01], [0.2], , [0.9], formula="Clean granular", verbose=True))) print("Phi_e=0.33, V_sh=0.92, R_t = 20 Ohmm, R_w = 0.9 Ohmm, S_wa={:0.3f}".format( Archie_Swa( [0.33], [0.92], , [0.9], formula="Clean granular", verbose=True))) (C) M.Yakimov, 2006 