Source code for rockphypy.Fluid

import scipy.special as sp
import numpy as np
from rockphypy.utils import utils
#from utils import *


[docs]class Fluid: """ Fluid subsitution approaches and models describing velocity dispersion and attenuation due to the fluid effect. """
[docs] @staticmethod def Brie(Kw, Kgas, Sw, e): """Brie empirical fluid mixing law Parameters ---------- Kw : float bulk modulus of fluid phase Kgas : float bulk modulus of gas phase Sw : float or array water saturation e : int Brie component Returns ------- float or array Kf: effective fluid propertie """ Kf= (Kw-Kgas)*Sw**e+Kgas return Kf
[docs] @staticmethod def Biot(Kdry,Gdry,K0,Kfl,rho0,rhofl,eta,phi,kapa,a,alpha,freq): """ Compute Biot dispersion and velocity attenuation Parameters ---------- Kdry : float or array-like dry frame bulk modulus Gdry : float or array-like dry frame shear modulus K0 : float bulk modulus of mineral material making up rock Kfl : float effective bulk modulus of pore fluid rho0 : float grain density rhofl : float pore fluid density eta : float η is the viscosity of the pore fluid phi : float porosity kapa : float absolute permeability of the rock a : float pore-size parameter. Stoll (1974) found that values between 1/6 and 1/7 of the mean grain diameter alpha : float tortuosity parameter, always greater than or equal to 1. freq : float or array-like frequency range, e.g 10^-3 to 10^3 Hz Returns ------- float or array-like Vp_fast, fast P-wave velocities at all frequencies,km/s Vp_slow, slow P-wave velocities at all frequencies,km/s Vs, S-wave velocities,km/s QP1_inv, fast P-wave attenuation QP2_inv, slow P-wave attenuation Qs_inv, S-wave attenuation """ rho=(1-phi)*rho0+phi*rhofl # bulk density # poroelastic coefficients D = K0*(1+phi*(K0/Kfl-1)) M = K0**2/(D-Kdry) C = (K0-Kdry)*K0/(D-Kdry) H = Kdry+4*Gdry/3+(K0-Kdry)**2/(D-Kdry) # angular frequency of the plane wave, ω is the angular frequency of the plane wave. w = 2*np.pi*freq # viscodynamic operator zeta = np.sqrt(w*a**2*rhofl/eta) T = np.zeros(zeta.size, dtype=complex) # asymptotic values for very high and very low frequencies # high frequency limit, T->(1+i)/sqrt(2) T[zeta<=1e3]=np.exp(1j*3*np.pi/4)*sp.jv(1,zeta[zeta<=1e3]*np.exp(-1j*np.pi/4) )/sp.jv(0, zeta[zeta<=1e3]*np.exp(-1j*np.pi/4) ) T[zeta>1e3]=(1+1j)/np.sqrt(2) # low frequency limit F->1 F = 1/4 * (zeta*T/(1+2*1j*T/zeta)) F[zeta<1e-1]=1 q = alpha*rhofl/phi - 1j*eta*F/(w*kapa) # a,b,c terms of the root Ta = (C**2-M*H) Tb = H*q+M*rho-2*C*rhofl Tc = rhofl**2-rho*q # slowness squared P1_slowness2= (-Tb+np.sqrt(Tb**2-4*Ta*Tc) )/(2*Ta) P2_slowness2= (-Tb-np.sqrt(Tb**2-4*Ta*Tc) )/(2*Ta) S_slowness2= (rho*q-rhofl**2)/(Gdry*q) # velocities and attenuations Vp_fast = 1/ np.sqrt(P1_slowness2).real Vp_slow = 1/ np.sqrt(P2_slowness2).real Vs = 1/ np.sqrt(S_slowness2).real QP1_inv= (1/P1_slowness2).imag/(1/P1_slowness2).real QP2_inv= (1/P2_slowness2).imag/(1/P2_slowness2).real Qs_inv = (1/S_slowness2).imag/(1/S_slowness2).real return Vp_fast,Vp_slow,Vs,QP1_inv,QP2_inv,Qs_inv
[docs] @staticmethod def Biot_HF(Kdry,Gdry,K0,Kfl,rho0,rhofl,phi,alpha): """Biot high-frequency limiting velocities in the notation of Johnson and Plona (1982) Parameters ---------- Kdry : float or array-like dry frame bulk modulus Gdry : float or array-like dry frame shear modulus K0 : float bulk modulus of mineral material making up rock Kfl : float effective bulk modulus of pore fluid rho0 : float grain density rhofl : float pore fluid density phi : float porosity alpha : float tortuosity parameter, always greater than or equal to 1. Returns ------- float or array-like Vp_fast,Vp_slow,Vs: high-frequency limiting velocities,km/s """ rho=(1-phi)*rho0+phi*rhofl # bulk density rho12=(1-alpha)*phi*rhofl rho22=alpha*phi*rhofl rho11=(1-phi)*rho0-(1-alpha)*phi*rhofl # repetative terms T1=1-phi-Kdry/K0 T2= phi*K0/Kfl R=phi**2*K0/(T1+T2) Q=(T1*phi*K0/(T1+T2)) P=((1-phi)*T1*K0+T2*Kdry)/(T1+T2) + 4*Gdry/3 Delta= P*rho22+R*rho11-2*Q*rho12 T3= rho11*rho22-rho12**2 T4=P*R-Q**2 Vp_fast= np.sqrt( (Delta+np.sqrt(Delta**2-4*T3*T4))/(2*T3)) Vp_slow= np.sqrt( (Delta-np.sqrt(Delta**2-4*T3*T4))/(2*T3)) Vs=np.sqrt(Gdry/(rho-phi*rhofl*alpha**-1)) return Vp_fast,Vp_slow,Vs
[docs] @staticmethod def Geertsma_Smit_HF(Kdry,Gdry,K0,Kfl,rho0,rhofl,phi,alpha): """Approximation of Biot high-frequency limit of the fast P-wave velocity given by Geertsma and Smit (1961), This form predicts velocities that are too high (by about 3%–6%) compared with the actual high-frequency limit. Parameters ---------- Kdry : float or array-like dry frame bulk modulus Gdry : float or array-like dry frame shear modulus K0 : float bulk modulus of mineral material making up rock Kfl : float effective bulk modulus of pore fluid rho0 : float grain density rhofl : float pore fluid density phi : float porosity alpha : float tortuosity parameter, always greater than or equal to 1. Returns ------- float or array-like Vp_fast,Vs: high-frequency limiting velocities, km/s """ rho=(1-phi)*rho0+phi*rhofl # bulk density rho_biot= rho0*(1-phi)+phi*rhofl*(1-alpha**-1) Hdry= Kdry+4*Gdry/3 T1=phi*rho/(rhofl*alpha) alpha_biot= 1-Kdry/K0 Vp_fast=np.sqrt( 1/rho_biot*(Hdry+(T1+alpha_biot*(alpha_biot-2*phi/alpha))/((alpha_biot-phi)/K0+phi/Kfl ))) Vs=np.sqrt(Gdry/rho_biot) return Vp_fast,Vs
[docs] @staticmethod def Geertsma_Smit_LF(Vp0,Vpinf, freq,phi, rhofl, kapa, eta): """Low and middle-frequency approximations of Biot wave given by Geertsma and Smit (1961). Noticed that mathematically this approximation is valid at moderate-to-low seismic frequencies, i.e. f<fc Parameters ---------- Vp0 : float Biot−Gassmann low-frequency limiting P-wave velocity, km/s or m/s Vpinf : float Biot highfrequency limiting P-wave velocity, km/s or m/s freq : float or array-like frequency phi : float porosity rhofl : float fluid density kapa : float absolute permeability of the rock. eta : float viscosity of the pore fluid Returns ------- float or array-like Vp: frequency-dependent P-wave velocity of saturated rock """ # Biot reference frequency fc = phi*eta/(2*np.pi*rhofl*kapa) # if freq >=fc: # print('ATTENTION, the input frequency is higher than the reference frequency, the approximation might not be valid!') a = (fc/freq)**2 Vp= np.sqrt((Vpinf**4+Vp0**4*a)/(Vpinf**2+Vp0**2*a)) return Vp
[docs] @staticmethod def Gassmann(K_dry,G_dry,K_mat,Kf,phi): """Computes saturated elastic moduli of rock via Gassmann equation given dry-rock moduli. Parameters ---------- K_dry : float or array-like dry frame bulk modulus G_dry : float or array-like dry frame shear modulus K_mat : float matrix bulk modulus Kf : float fluid bulk modulus phi : float or array-like porosity Returns ------- float or array-like K_sat, G_sat: fluid saturated elastic moduli """ A=(1-K_dry/K_mat)**2 B=phi/Kf+(1-phi)/K_mat-K_dry/(K_mat**2) K_sat=K_dry+A/B G_sat = G_dry # At low frequencies, Gassmann’s relations predict no change in the shear modulus between dry and saturated patches return K_sat,G_sat
[docs] @staticmethod def Gassmann_sub(phi, K0, Ksat1,Kfl1,Kfl2): """Fluid subsititution using Gassmann equation, thr rock is initially saturated with a fluid, compute the saturated moduli for tge rock saturated with a different fluid Parameters ---------- phi : float or array-like porosity K0 : float mineral modulus Ksat1 : float or array-like original bulk modulus of rock saturated with fluid of bulk modulus Kfl1 Kfl1 : float original saturant Kfl2 : float new saturant Returns ------- float or array-like Ksat2: new satuarted bulk modulus of the rock """ a=Ksat1/(K0-Ksat1)-Kfl1/(phi*(K0-Kfl1))+Kfl2/(phi*(K0-Kfl2)) Ksat2= a*K0/(1+a) return Ksat2
[docs] @staticmethod def vels(K_dry,G_dry,K0,D0,Kf,Df,phi): """Computes Vp,Vs and densities of saturated rock using Gassmann relations from elastic moduli of rock. See also `Gassmann_vels`. Parameters ---------- K_dry : float dry frame bulk modulus G_dry : float dry frame shear modulus K0 : float mineral matrix bulk modulus D0 : float mineral matrix density Kf : float fluid bulk modulus Df : float fluid density in g/cm3 phi : float or array porosity Returns ------- float or array Vp, Vs, rho """ #D0=Dsh*vsh+Dqz*(1-vsh)#### rho = D0*(1-phi)+Df*phi K,_= Fluid.Gassmann(K_dry,G_dry,K0,Kf,phi) Vp = np.sqrt((K+4./3*G_dry)/rho)*1e3 Vs = np.sqrt(G_dry/rho)*1e3 return Vp, Vs, rho
[docs] @staticmethod def Gassmann_vels(Vp1,Vs1,rho1,rhofl1,Kfl1,rhofl2,Kfl2,K0,phi): """Gassmann fluid substituion with velocities Parameters ---------- Vp1 : float or array-like saturated P velocity of rock with fluid 1 Vs1 : float or array-like saturated S velocity of rock with fluid 1 rho1 : float bulk density of saturated rock with fluid 1 rhofl1 : float density of fluid 1 Kfl1 : float bulk modulus of fluid 1 rhofl2 : float density of fluid 2 Kfl2 : float bulk modulus of fluid 2 K0 : float mineral bulk modulus phi : float or array-like porosity Returns ------- float or array-like Vp2, Vs2: velocities of rock saturated with fluid 2 """ rho2=rho1 - phi*rhofl1 +phi*rhofl2 # density update G1=rho1*Vs1**2 Ksat1=rho1*Vp1**2-(4/3)*G1 k2= Fluid.Gassmann_sub(phi, K0, Ksat1,Kfl1,Kfl2) G2=G1 Vp2=np.sqrt((k2+(4/3)*G2)/rho2) Vs2=np.sqrt(G2/rho2) return Vp2, Vs2
[docs] @staticmethod def Gassmann_approx(Msat1,M0,Mfl1,phi,Mfl2): """Perform gassmann fluid subsititution using p wave modulus only Parameters ---------- Msat1 : float or array-like in situ saturated p wave modulus from well log data M0 : float p wave modulus of mineral Mfl1 : float p wave modulus of in situ fluid phi : float porosity Mfl2 : float p wave modulus of new fluid for susbtitution Returns ------- float or array-like Msat2: p wave modulus of rock fully saturated with new fluid """ x=Msat1/(M0-Msat1) -Mfl1/(phi*(M0-Mfl1)) +Mfl2/(phi*(M0-Mfl2)) Msat2=x*M0/(1+x) return Msat2
[docs] @staticmethod def Brown_Korringa_dry2sat(Sdry,K0,G0,Kfl,phi): """Compute fluid saturated compliances from dry compliance for anisotropic rock using Brown and Korringa (1975). See eq. 32 in the paper. Parameters ---------- Sdry : 2d array comliance matrix of the dry rock K0 : float Isotropic mineral bulk modulus G0 : float Isotropic mineral shear modulus Kfl : float Isotropic fluid bulk modulus phi : float porosity Returns ------- 2d array Ssat (6x6 matrix): Saturated compliance of anisotropic rock """ # Compressibilities of the fluid, mineral, and dry rock, sum over repeted index, e,g, β0 =s0[ααγγ] beta0 = 1/K0 betadry = np.sum(Sdry[0:3,0:3]) betafl =1/Kfl # Isotropic mineral compliance tensor C = utils.write_iso(K0,G0) S0 = np.linalg.inv(C) # nominator Sprime = np.sum(Sdry[0:3,:],axis=0) - np.sum(S0[0:3,:],axis=0) Sprime = Sprime.reshape((1,6)) # denominator denom = (betafl-beta0)*phi+(betadry-beta0) Ssat=Sdry-np.dot(Sprime.T,Sprime)/denom return Ssat
[docs] @staticmethod def Brown_Korringa_sat2dry(Ssat,K0,G0,Kfl,phi): """Compute dry compliance from fluid saturated compliances for arbitrarily anisotropic rock using Brown and Korringa (1975). See eq. 32 in the paper. Parameters ---------- Ssat : 2d array comliance matrix (6x6) of the saturated rock K0 : float Isotropic mineral bulk modulus G0 : float Isotropic mineral shear modulus Kfl : float Isotropic fluid bulk modulus phi : float porosity Returns ------- 2d array Sdry (6x6 matrix): Dry compliance of anisotropic rock """ # Compressibilities of the fluid, mineral, and dry rock, sum over repeted index, e,g, β0 =s0[ααγγ] beta0 = 1/K0 betasat = np.sum(Ssat[0:3,0:3]) betafl =1/Kfl # Isotropic mineral compliance tensor C = utils.write_iso(K0,G0) S0 = np.linalg.inv(C) # nominator Sprime = np.sum(Ssat[0:3,:],axis=0) - np.sum(S0[0:3,:],axis=0) Sprime = Sprime.reshape((1,6)) # denominator denom = (betafl-beta0)*phi-(betasat-beta0) Sdry=Ssat + np.dot(Sprime.T,Sprime)/denom return Sdry
[docs] @staticmethod def Brown_Korringa_sub(Csat,K0,G0,Kfl1,Kfl2,phi): """Fluid substitution in arbitrarily anisotropic rock using Brown and Korringa (1975). the rock is originally saturated by fluid 1. After fluid subsititution, the rock is finally saturated by fluid 2. Parameters ---------- Csat : 6x6 matrix comliance matrix of the saturated rock K0 : float Isotropic mineral bulk modulus G0 : float Isotropic mineral shear modulus Kfl1 : float bulk modulus of the original fluid Kfl2 : float bulk modulus of the final fluid phi : float porosity Returns ------- 2d array Csat2, Ssat2 (6x6 matrix): Dry stiffness and compliance matrix of anisotropic rock saturated with new fluid """ Ssat = np.linalg.inv(Csat) Sdry = Fluid.Brown_Korringa_sat2dry(Ssat,K0,G0,Kfl1,phi) Ssat2 = Fluid.Brown_Korringa_dry2sat(Sdry,K0,G0,Kfl2,phi) Csat2 = np.linalg.inv(Ssat2) return Csat2, Ssat2
[docs] @staticmethod def Mavko_Jizba(Vp_hs, Vs_hs,Vpdry, Vsdry, K0, rhodry, rhofl,Kfl, phi): """Predicting the very high-frequency moduli and velocities of saturated rocks from dry rock properties using the Squirt flow model derived by Mavko and Jizba (1991). Parameters ---------- Vp_hs : float P wave velocity of the dry rock measured at very high effective pressure in the unit of m/s Vs_hs : float S wave velocity of the dry rock measured at very high effective pressure in the unit of m/s Vpdry : array P wave velocity of the dry rock measured at different effective pressure in the unit of m/s Vsdry : array S wave velocity of the dry rock measured at different effective pressure in the unit of m/s K0 : float mineral bulk moduli rhodry : float bulk density of the dry rock rhofl : float bulk density of the pore fluid Kfl : float bulk moduli of the pore fluid phi : float porosity Returns ------- float or array-like Kuf_sat (float):GPa, predicted high frequency bulk moduli of saturated rock Guf_sat (array): GPa, predicted high frequency shear moduli of saturated rock at different pressure Vp_hf (array): m/s, predicted high frequency P wave velocities of saturated rock Vs_hf (array): m/s, predicted high frequency S wave velocities of saturated rock """ # dry rock moduli with pressure Kdry,Gdry = utils.M_from_V(rhodry, Vpdry,Vsdry) # dry moduli dry rock at high high effective pressure, crack free high pressure moduli Khs, Ghs = utils.M_from_V(rhodry, Vp_hs,Vs_hs) # high-frequency “wet-frame moduli Kuf= Khs # ignore the a first order correction for the difference in fluid and mineral compressibilities. # high-frequency saturated moduli Kuf_sat,_ = Fluid.Gassmann(Kuf,1,K0,Kfl,phi) Guf_sat_inv = 1/Gdry - 4/15*(1/Kdry-1/Kuf) Guf_sat = 1/Guf_sat_inv # predicted high frequency velocities rho_sat=rhodry+phi*rhofl # saturated bulk density Vp_hf,Vs_hf = utils.V(Kuf_sat, Guf_sat, rho_sat) return Kuf_sat,Guf_sat,Vp_hf,Vs_hf
[docs] @staticmethod def Squirt_anisotropic(Sdry, Sdry_hp): """Predict wet unrelaxed frame compliances at very high frequency from dry frame compliances for transversely isotropic rocks using theoretical formula derived by Mukerji and Mavko, (1994) Parameters ---------- Sdry : list or array dry rock compliances [S11 S12 S13 S33 S44] Sdry_hp : array dry rock compliances at very high effective stress [S11 S12 S13 S33 S44] Returns ------- array The wet-frame compliances [S11 S12 S13 S33 S44] """ Sdry=np.asanyarray(Sdry) Sdry_hp=np.asanyarray(Sdry_hp) # delta_Sdry_ijkl DSdry=Sdry-Sdry_hp # delta_Sdry_aabb DSdry_aabb= 2*DSdry[0]+2*DSdry[1]+4*DSdry[2]+DSdry[3] #2*(dss(:,1)+dss(:,2)+2*dss(:,3))+dss(:,4); # Delta S_tilde D_Sdry= DSdry/DSdry_aabb # delta_Sdry_abab= 2S11+S33+4S44+2S66 D_Sdry_abab=2*D_Sdry[0]+D_Sdry[3]+4*D_Sdry[4]+4*(D_Sdry[0]-D_Sdry[1]) alpha=0.25*(D_Sdry_abab-1) #the elements of Gijkl T = 1-4*alpha G11=D_Sdry[0]-4*alpha/T*(D_Sdry[1]+D_Sdry[2]) G12=D_Sdry[1]/T G13=D_Sdry[2]/T G33=D_Sdry[3]-8*alpha*D_Sdry[2]/T G44=D_Sdry[4]/T-(D_Sdry[0]+D_Sdry[2])/(4*T)+(G11+G33)/4 # G66=2*(G11-G12) G=np.array([G11,G12,G13,G33,G44]) # The wet-frame compliance S_wet= Sdry-DSdry_aabb*G return S_wet
[docs] @staticmethod def White_Dutta_Ode(Kdry, Gdry, K0, phi, rho0, rhofl1,rhofl2, Kfl1, Kfl2,eta1,eta2,kapa,a,sg,freq ): """Dispersion and Attenuation of partial saturation using White and Dutta–Odé Model. Parameters ---------- Kdry : float bulk modulus of the dry rock Gdry : float shear modulus of the dry rock K0 : float Isotropic mineral bulk modulus phi : float porosity rho0 : float mineral density rhofl1 : float density of the fluid opcupying the central sphere rhofl2 : float density of the fluid opcupying the outer sphere Kfl1 : float bulk modulus of the fluid opcupying the central sphere Kfl2 : float bulk modulus of the fluid opcupying the outer sphere eta1 : float viscousity of the fluid opcupying the central sphere eta2 : float viscousity of the fluid opcupying the outer sphere kapa : float absolute permeability of the rock a : float radius of central sphere , sg=a3/b3 sg : float saturation of fluid opcupying the central sphere freq : float or array-like frequencies Returns ------- float, array-like Vp (m/s): P wave velocity km/s a_w: attenuation coefficient K_star: complex bulk modulus """ omega= 2*np.pi*freq #sg=a3/b3, outer radius b b= a/sg**(1/3) # The saturated bulk and shear moduli, Kj and μj of region j K1,_=Fluid.Gassmann(Kdry,0,K0,Kfl1,phi) K2,_=Fluid.Gassmann(Kdry,0,K0,Kfl2,phi) G1=Gdry G2=G1 # R1=(K1-Kdry)/(1-Kdry/K0) * (3*K2+4*G2)/(K2*(3*K1+4*G2)+4*G2*(K1-K2)*sg ) R2=(K2-Kdry)/(1-Kdry/K0) * (3*K1+4*G1)/(K2*(3*K1+4*G2)+4*G2*(K1-K2)*sg ) KA1=(phi/Kfl1+(1-phi)/K0-Kdry/K0**2)**-1 KA2=(phi/Kfl2+(1-phi)/K0-Kdry/K0**2)**-1 KE1=(1-Kfl1*(1-K1/K0)*(1-Kdry/K0)/(phi*K1*(1-Kfl1/K0)))*KA1 KE2=(1-Kfl2*(1-K2/K0)*(1-Kdry/K0)/(phi*K2*(1-Kfl2/K0)))*KA2 alpha1=(1j*omega*eta1/(kapa*KE1))**(1/2) alpha2=(1j*omega*eta2/(kapa*KE2))**(1/2) Z1=eta1*a/kapa *(1-np.exp(-2*alpha1*a))/((alpha1*a-1)+(alpha1*a+1)*np.exp(-2*alpha1*a) ) Z2=-eta2*a/kapa *( (alpha2*b+1) +(alpha2*b-1)*np.exp(2*alpha2*(b-a) ) )/( (alpha2*b+1)* (alpha2*a-1)- (alpha2*b-1)*(alpha2*a+1)*np.exp(2*alpha2*(b-a)) ) Q1= (1-Kdry/K0)*KA1/K1 Q2= (1-Kdry/K0)*KA2/K2 W=3*a**2*(R1-R2)*(-Q1+Q2)/ (b**3*1j*omega*(Z1+Z2) ) Kinf= (K2*(3*K1+4*G2)+4*G2*(K1-K2)*sg)/((3*K1+4*G2)-3*(K1-K2)*sg) Klowf = (K2*(K1-Kdry)+sg*Kdry*(K2-K1))/((K1-Kdry)+sg*(K2-K1)) K_star = Kinf/(1-Kinf*W) # when the central sphere is saturated with a very compressible gas K_star_gas= Kinf/(1+3*a**2*R2*Q2*Kinf/(b**3*1j*omega*Z2) ) # P wave modulus and density M= K_star+4*Gdry/3 rho = (1-phi)*rho0+phi*sg*rhofl1+phi*(1-sg)*rhofl2 # phase angle theta= np.arctan(M.imag/M.real) # velocity and attenuation coefficient, see 3.8.56 in RPH Vp = np.sqrt(np.abs(M)/rho) * 1/np.cos(theta/2) a_w= omega/Vp *np.tan(theta/2) return Vp,a_w, K_star