# Source code for bruges.rockphysics.moduli

```"""
===================
moduli.py
===================

Converts between various acoustic/eslatic parameters, and provides a way to
calculate all the elastic moduli from Vp, Vs, and rho.

Created June 2014, Matt Hall

Using equations http://www.subsurfwiki.org/wiki/Elastic_modulus
from Mavko, G, T Mukerji and J Dvorkin (2003), The Rock Physics Handbook,
Cambridge University Press.
"""
import numpy as np

[docs]def youngs(vp=None, vs=None, rho=None, mu=None, lam=None, bulk=None, pr=None,
pmod=None):
"""
Computes Young's modulus given either Vp, Vs, and rho, or
any two elastic moduli (e.g. lambda and mu, or bulk and P
moduli). SI units only.

Args:
vp, vs, and rho
or any 2 from lam, mu, bulk, pr, and pmod

Returns:
Young's modulus in pascals, Pa
"""
if (vp is not None) and (vs is not None) and (rho is not None):
return rho * vs**2 * (3.*vp**2 - 4.*vs**2) / (vp**2 - vs**2)

elif (mu is not None) and (lam is not None):
return mu * (3.*lam + 2*mu) / (lam + mu)

elif (bulk is not None) and (lam is not None):
return 9.*bulk * (bulk - lam) / (3.*bulk - lam)

elif (bulk is not None) and (mu is not None):
return 9.*bulk*mu / (3.*bulk + mu)

elif (lam is not None) and (pr is not None):
return lam * (1+pr) * (1 - 2*pr) / pr

elif (pr is not None) and (mu is not None):
return 2. * mu * (1+pr)

elif (pr is not None) and (bulk is not None):
return 3. * bulk * (1 - 2*pr)

else:
return None

[docs]def bulk(vp=None, vs=None, rho=None, mu=None, lam=None, youngs=None, pr=None,
pmod=None):
"""
Computes bulk modulus given either Vp, Vs, and rho, or
any two elastic moduli (e.g. lambda and mu, or Young's
and P moduli). SI units only.

Args:
vp, vs, and rho
or any 2 from lam, mu, youngs, pr, and pmod

Returns:
Bulk modulus in pascals, Pa
"""
if (vp is not None) and (vs is not None) and (rho is not None):
return rho * (vp**2 - (4./3.)*(vs**2))

elif (mu is not None) and (lam is not None):
return lam + 2*mu/3.

elif (mu is not None) and (youngs is not None):
return youngs * mu / (9.*mu - 3.*youngs)

elif (lam is not None) and (pr is not None):
return lam * (1+pr) / 3.*pr

elif (pr is not None) and (mu is not None):
return 2. * mu * (1+pr) / (3. - 6.*pr)

elif (pr is not None) and (youngs is not None):
return youngs / (3. - 6.*pr)

elif (lam is not None) and (youngs is not None):
# Note that this returns a tuple.
x = np.sqrt(9*lam**2 + 2*youngs*lam + youngs**2)

def b(y): return 1/6. * (3*lam + youngs + y)

# Strictly, we should return b(x), b(-x)
# But actually, the answer is:
return b(x)

else:
return None

[docs]def pr(vp=None, vs=None, rho=None, mu=None, lam=None, youngs=None, bulk=None,
pmod=None):
"""
Computes Poisson ratio given either Vp, Vs, and rho, or
any two elastic moduli (e.g. lambda and mu, or Young's
and P moduli). SI units only.

Args:
vp, vs, and rho
or any 2 from lam, mu, youngs, bulk, and pmod

Returns:
Poisson's ratio, dimensionless
"""
if (vp is not None) and (vs is not None):
return (vp**2. - 2.*vs**2) / (2. * (vp**2 - vs**2))

elif (mu is not None) and (lam is not None):
return lam / (2. * (lam+mu))

elif (mu is not None) and (youngs is not None):
return (youngs / (2.*mu)) - 1

elif (lam is not None) and (bulk is not None):
return lam / (3.*bulk - lam)

elif (bulk is not None) and (mu is not None):
return (3.*bulk - 2*mu) / (6.*bulk + 2*mu)

elif (bulk is not None) and (youngs is not None):
return (3.*bulk - youngs) / (6.*bulk)

elif (lam is not None) and (youngs is not None):
# Note that this returns a tuple.
x = np.sqrt(9*lam**2 + 2*youngs*lam + youngs**2)

def b(y): return (1/(4*lam)) * (-1*lam - youngs + y)

# Strictly, we should return b(x), b(-x)
# But actually, the answer is:
return b(x)

else:
return None

[docs]def mu(vp=None, vs=None, rho=None, pr=None, lam=None, youngs=None, bulk=None,
pmod=None):
"""
Computes shear modulus given either Vp, Vs, and rho, or
any two elastic moduli (e.g. lambda and bulk, or Young's
and P moduli). SI units only.

Args:
vp, vs, and rho
or any 2 from lam, bulk, youngs, pr, and pmod

Returns:
Shear modulus in pascals, Pa
"""
if (vs is not None) and (rho is not None):
return rho * vs**2

elif (bulk is not None) and (lam is not None):
return 3. * (bulk - lam) / 2.

elif (bulk is not None) and (youngs is not None):
return 3. * bulk * youngs / (9.*bulk - youngs)

elif (lam is not None) and (pr is not None):
return lam * (1 - 2.*pr) / (2.*pr)

elif (pr is not None) and (youngs is not None):
return youngs / (2. * (1 + pr))

elif (pr is not None) and (bulk is not None):
return 3. * bulk * (1 - 2*pr) / (2. * (1 + pr))

elif (lam is not None) and (youngs is not None):
# Note that this returns a tuple.
x = np.sqrt(9*lam**2 + 2*youngs*lam + youngs**2)

def b(y): return 1/4. * (-3*lam + youngs + y)

# Strictly, we should return b(x), b(-x)
# But actually, the answer is:
return b(x)

else:
return None

[docs]def lam(vp=None, vs=None, rho=None, pr=None,  mu=None, youngs=None, bulk=None,
pmod=None):
"""
Computes lambda given either Vp, Vs, and rho, or
any two elastic moduli (e.g. bulk and mu, or Young's
and P moduli). SI units only.

Args:
vp, vs, and rho
or any 2 from bulk, mu, youngs, pr, and pmod

Returns:
Lambda in pascals, Pa
"""
if (vp is not None) and (vs is not None) and (rho is not None):
return rho * (vp**2 - 2.*vs**2.)

elif (youngs is not None) and (mu is not None):
return mu * (youngs - 2.*mu) / (3.*mu - youngs)

elif (bulk is not None) and (mu is not None):
return bulk - (2.*mu/3.)

elif (bulk is not None) and (youngs is not None):
return 3. * bulk * (3*bulk - youngs) / (9*bulk - youngs)

elif (pr is not None) and (mu is not None):
return 2. * pr * mu / (1 - 2.*pr)

elif (pr is not None) and (youngs is not None):
return pr * youngs / ((1+pr) * (1-2*pr))

elif (pr is not None) and (bulk is not None):
return 3. * bulk * pr / (1+pr)

else:
return None

[docs]def pmod(vp=None, vs=None, rho=None, pr=None, mu=None, lam=None, youngs=None,
bulk=None):
"""
Computes P-wave modulus given either Vp, Vs, and rho, or
any two elastic moduli (e.g. lambda and mu, or Young's
and bulk moduli). SI units only.

Args:
vp, vs, and rho
or any 2 from lam, mu, youngs, pr, and bulk

Returns:
P-wave modulus in pascals, Pa
"""
if (vp is not None) and (rho is not None):
return rho * vp**2

elif (lam is not None) and (mu is not None):
return lam + 2*mu

elif (youngs is not None) and (mu is not None):
return mu * (4.*mu - youngs) / (3.*mu - youngs)

elif (bulk is not None) and (lam is not None):
return 3*bulk - 2.*lam

elif (bulk is not None) and (mu is not None):
return bulk + (4.*mu/3.)

elif (bulk is not None) and (youngs is not None):
return 3. * bulk * (3*bulk + youngs) / (9*bulk - youngs)

elif (lam is not None) and (pr is not None):
return lam * (1 - pr) / pr

elif (pr is not None) and (mu is not None):
return 2. * pr * mu * (1-pr) / (1 - 2.*pr)

elif (pr is not None) and (youngs is not None):
return (1-pr) * youngs / ((1+pr) * (1 - 2.*pr))

elif (pr is not None) and (bulk is not None):
return 3. * bulk * (1-pr) / (1+pr)

elif (lam is not None) and (youngs is not None):
# Note that this returns a tuple.
x = np.sqrt(9*lam**2 + 2*youngs*lam + youngs**2)

def b(y): return 1/2. * (-1*lam + youngs + y)

# Strictly, we should return b(x), b(-x)
# But actually, the answer is:
return b(x)

else:
return None

[docs]def vp(youngs=None, vs=None, rho=None, mu=None, lam=None, bulk=None, pr=None,
pmod=None):
"""
Computes Vp given bulk density and any two elastic moduli
(e.g. lambda and mu, or Young's and P moduli). SI units only.

Args:
Any 2 from lam, mu, youngs, pr, pmod, bulk
Rho

Returns:
Vp in m/s
"""
if (mu is not None) and (lam is not None) and (rho is not None):
return np.sqrt((lam + 2.*mu) / rho)

elif (youngs is not None) and (mu and rho is not None):
return np.sqrt(mu * (youngs - 4.*mu) / (rho * (youngs - 3.*mu)))

elif (youngs is not None) and (pr and rho is not None):
return np.sqrt(youngs * (1 - pr) / (rho * (1+pr) * (1 - 2.*pr)))

elif (bulk is not None) and (lam and rho is not None):
return np.sqrt((9.*bulk - 2.*lam) / rho)

elif (bulk is not None) and (mu is not None and rho is not None):
return np.sqrt((bulk + 4.*mu/3.) / rho)

elif (lam is not None) and (pr and rho is not None):
return np.sqrt(lam * (1. - pr) / (pr*rho))

elif (bulk is not None) and (vs and rho is not None):
return np.sqrt((bulk / rho) + (4/3)*(vs**2))

else:
return None

[docs]def vs(youngs=None, vp=None, rho=None, mu=None, lam=None, bulk=None, pr=None,
pmod=None):
"""
Computes Vs given bulk density and shear modulus. SI units only.

Args:
Mu
Rho

Returns:
Vs in m/s
"""
if (mu is not None) and (rho is not None):
return np.sqrt(mu / rho)

else:
return None

[docs]def moduli_dict(vp, vs, rho):
"""
Computes elastic moduli given Vp, Vs, and rho. SI units only.

Args:
Vp, Vs, and rho

Returns:
A dict of elastic moduli, plus P-wave impedance.
"""
mod = {}

mod['imp'] = vp * rho

mod['mu'] = mu(vs=vs, rho=rho)
mod['pr'] = pr(vp=vp, vs=vs, rho=rho)
mod['lam'] = lam(vp=vp, vs=vs, rho=rho)
mod['bulk'] = bulk(vp=vp, vs=vs, rho=rho)
mod['pmod'] = pmod(vp=vp, rho=rho)
mod['youngs'] = youngs(vp=vp, vs=vs, rho=rho)

return mod
```