rp.py

Equation definitions and derivations using SymPy.


Requires Python packages/modules:

class gme.core.rp.RpMixin

Define ray vector and normal-slowness covector equations.

Basic \(\mathbf{r}\) and \(\mathbf{\tilde{p}}\) equations supplement to equation definition class.

define_p_eqns()None

Define normal slowness \(p\) and derive related equations.

p_covec_eqn

\(\mathbf{\widetilde{p}} := [p_x, p_z]\)

Type

Equality

px_p_beta_eqn

\(p_x = p \sin\beta\)

Type

Equality

pz_p_beta_eqn

\(p_z = p \cos\beta\)

Type

Equality

p_norm_pxpz_eqn

\(p = \sqrt{p_x^2+p_z^2}\)

Type

Equality

tanbeta_pxpz_eqn

\(\tan\beta = -\dfrac{p_x}{p_z}\)

Type

Equality

sinbeta_pxpz_eqn

\(\sin\beta = \dfrac{p_x}{\sqrt{p_x^2+p_z^2}}\)

Type

Equality

cosbeta_pxpz_eqn

\(\cos\beta = \dfrac{-p_z}{\sqrt{p_x^2+p_z^2}}\)

Type

Equality

pz_px_tanbeta_eqn

\(p_z = -\dfrac{p_x}{\tan\beta}\)

Type

Equality

px_pz_tanbeta_eqn

\(p_x = -{p_z}{\tan\beta}\)

Type

Equality

p_pz_cosbeta_eqn

\(p = -\dfrac{p_z}{\cos\beta}\)

Type

Equality

define_r_eqns()None

Define equations for ray position \(\vec{r}\).

rx_r_alpha_eqn

\(r^x = r\cos\alpha\)

Type

Equality

rz_r_alpha_eqn

\(r^z = r\sin\alpha\)

Type

Equality

Code

"""
Equation definitions and derivations using :mod:`SymPy <sympy>`.

---------------------------------------------------------------------

Requires Python packages/modules:
  -  :mod:`SymPy <sympy>`
  -  `GMPLib`_
  -  `GME`_

.. _GMPLib: https://github.com/geomorphysics/GMPLib
.. _GME: https://github.com/geomorphysics/GME
.. _Matrix:
    https://docs.sympy.org/latest/modules/matrices/immutablematrices.html

---------------------------------------------------------------------
"""
# Disable these pylint errors because it doesn't understand SymPy syntax
#   - notably minus signs in equations flag an error
# pylint: disable=invalid-unary-operand-type, not-callable

# Library
import warnings
import logging

# from typing import Dict, Type, Optional  # , Tuple, Eq, List

# SymPy
from sympy import Eq, sqrt, simplify, solve, Matrix, sin, cos, trigsimp

# GMPLib
from gmplib.utils import e2d

# GME
from gme.core.symbols import p, r, rx, rz, px, pz, pcovec, alpha, beta

warnings.filterwarnings("ignore")

__all__ = ["RpMixin"]


class RpMixin:
    r"""
    Define ray vector and normal-slowness covector equations.

    Basic :math:`\mathbf{r}` and :math:`\mathbf{\tilde{p}}`
    equations supplement to equation definition class.
    """

    # Definitions
    p_covec_eqn: Eq
    px_p_beta_eqn: Eq
    pz_p_beta_eqn: Eq
    p_norm_pxpz_eqn: Eq
    tanbeta_pxpz_eqn: Eq
    sinbeta_pxpz_eqn: Eq
    cosbeta_pxpz_eqn: Eq
    pz_px_tanbeta_eqn: Eq
    px_pz_tanbeta_eqn: Eq
    p_pz_cosbeta_eqn: Eq
    rx_r_alpha_eqn: Eq
    rz_r_alpha_eqn: Eq

    def define_p_eqns(self) -> None:
        r"""
        Define normal slowness :math:`p` and derive related equations.

        Attributes:
            p_covec_eqn (:class:`~sympy.core.relational.Equality`):
                :math:`\mathbf{\widetilde{p}} := [p_x, p_z]`
            px_p_beta_eqn (:class:`~sympy.core.relational.Equality`):
                :math:`p_x = p \sin\beta`
            pz_p_beta_eqn (:class:`~sympy.core.relational.Equality`):
                :math:`p_z = p \cos\beta`
            p_norm_pxpz_eqn (:class:`~sympy.core.relational.Equality`):
                :math:`p = \sqrt{p_x^2+p_z^2}`
            tanbeta_pxpz_eqn (:class:`~sympy.core.relational.Equality`):
                :math:`\tan\beta = -\dfrac{p_x}{p_z}`
            sinbeta_pxpz_eqn (:class:`~sympy.core.relational.Equality`):
                :math:`\sin\beta = \dfrac{p_x}{\sqrt{p_x^2+p_z^2}}`
            cosbeta_pxpz_eqn (:class:`~sympy.core.relational.Equality`):
                :math:`\cos\beta = \dfrac{-p_z}{\sqrt{p_x^2+p_z^2}}`
            pz_px_tanbeta_eqn (:class:`~sympy.core.relational.Equality`):
                :math:`p_z = -\dfrac{p_x}{\tan\beta}`
            px_pz_tanbeta_eqn (:class:`~sympy.core.relational.Equality`):
                :math:`p_x = -{p_z}{\tan\beta}`
            p_pz_cosbeta_eqn (:class:`~sympy.core.relational.Equality`):
                :math:`p = -\dfrac{p_z}{\cos\beta}`
        """
        logging.info("gme.core.rp.define_p_eqns")
        self.p_covec_eqn = Eq(pcovec, Matrix([px, pz]).T)
        self.px_p_beta_eqn = Eq(px, p * sin(beta))
        self.pz_p_beta_eqn = Eq(pz, -p * cos(beta))
        self.p_norm_pxpz_eqn = Eq(
            trigsimp(
                sqrt(self.px_p_beta_eqn.rhs ** 2 + self.pz_p_beta_eqn.rhs ** 2)
            ),
            (sqrt(self.px_p_beta_eqn.lhs ** 2 + self.pz_p_beta_eqn.lhs ** 2)),
        )
        self.tanbeta_pxpz_eqn = Eq(
            simplify(-self.px_p_beta_eqn.rhs / self.pz_p_beta_eqn.rhs),
            -self.px_p_beta_eqn.lhs / self.pz_p_beta_eqn.lhs,
        )
        self.sinbeta_pxpz_eqn = Eq(
            sin(beta),
            solve(self.px_p_beta_eqn, sin(beta))[0].subs(
                e2d(self.p_norm_pxpz_eqn)
            ),
        )
        self.cosbeta_pxpz_eqn = Eq(
            cos(beta),
            solve(self.pz_p_beta_eqn, cos(beta))[0].subs(
                e2d(self.p_norm_pxpz_eqn)
            ),
        )
        self.pz_px_tanbeta_eqn = Eq(pz, solve(self.tanbeta_pxpz_eqn, pz)[0])
        self.px_pz_tanbeta_eqn = Eq(px, solve(self.tanbeta_pxpz_eqn, px)[0])
        self.p_pz_cosbeta_eqn = Eq(p, solve(self.pz_p_beta_eqn, p)[0])

    def define_r_eqns(self) -> None:
        r"""
        Define equations for ray position :math:`\vec{r}`.

        Attributes:
            rx_r_alpha_eqn (:class:`~sympy.core.relational.Equality`):
                :math:`r^x = r\cos\alpha`
            rz_r_alpha_eqn (:class:`~sympy.core.relational.Equality`):
                :math:`r^z = r\sin\alpha`
        """
        logging.info("gme.core.rp.define_r_eqns")
        self.rx_r_alpha_eqn = Eq(rx, r * cos(alpha))
        self.rz_r_alpha_eqn = Eq(rz, r * sin(alpha))


#