Source code for choclo.prism._gravity

# Copyright (c) 2022 The Choclo Developers.
# Distributed under the terms of the BSD 3-Clause License.
# SPDX-License-Identifier: BSD-3-Clause
#
# This code is part of the Fatiando a Terra project (https://www.fatiando.org)
#
"""
Gravity forward modelling functions for rectangular prisms
"""
import numpy as np
from numba import jit

from ..constants import GRAVITATIONAL_CONST
from ._kernels import (
    kernel_e,
    kernel_ee,
    kernel_en,
    kernel_eu,
    kernel_n,
    kernel_nn,
    kernel_nu,
    kernel_pot,
    kernel_u,
    kernel_uu,
)
from ._utils import (
    is_point_on_east_face,
    is_point_on_easting_edge,
    is_point_on_north_face,
    is_point_on_northing_edge,
    is_point_on_top_face,
    is_point_on_upward_edge,
)


[docs] @jit(nopython=True) def gravity_pot( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, density, ): r""" Gravitational potential field due to a rectangular prism Returns the gravitational potential field produced by a single rectangular prism on a single computation point. Parameters ---------- easting : float Easting coordinate of the observation point. Must be in meters. northing : float Northing coordinate of the observation point. Must be in meters. upward : float Upward coordinate of the observation point. Must be in meters. prism_west : float The West boundary of the prism. Must be in meters. prism_east : float The East boundary of the prism. Must be in meters. prism_south : float The South boundary of the prism. Must be in meters. prism_north : float The North boundary of the prism. Must be in meters. prism_bottom : float The bottom boundary of the prism. Must be in meters. prism_top : float The top boundary of the prism. Must be in meters. density: float Density of the rectangular prism in kilograms per cubic meter. Returns ------- potential : float Gravitational potential field generated by the rectangular prism on the observation point in :math:`\text{J}/\text{kg}`. Notes ----- Returns the gravitational potential field :math:`V(\mathbf{p})` on the observation point :math:`\mathbf{p} = (x_p, y_p, z_p)` generated by a single rectangular prism defined by its boundaries :math:`x_1, x_2, y_1, y_2, z_1, z_2` and with a density :math:`\rho`: .. math:: V(\mathbf{p}) = G \rho \,\, \Bigg\lvert \Bigg\lvert \Bigg\lvert k_V(x, y, z) \Bigg\rvert_{X_1}^{X_2} \Bigg\rvert_{Y_1}^{Y_2} \Bigg\rvert_{Z_1}^{Z_2} where .. math:: k_V(x, y, z) &= x y \, \operatorname{safe-ln} (z, r) + y z \, \operatorname{safe-ln} (x, r) + z x \, \operatorname{safe-ln} (y, r) \\ - \frac{x^2}{2} &\operatorname{safe-arctan} \left( yz, xr \right) - \frac{y^2}{2} \operatorname{safe-arctan} \left( zx, yr \right) - \frac{z^2}{2} \operatorname{safe-arctan} \left( xy, zr \right), .. math:: r = \sqrt{x^2 + y^2 + z^2}, and .. math:: X_1 = x_1 - x_p \\ X_2 = x_2 - x_p \\ Y_1 = y_1 - y_p \\ Y_2 = y_2 - y_p \\ Z_1 = z_1 - z_p \\ Z_2 = z_2 - z_p are the shifted coordinates of the prism boundaries and :math:`G` is the Universal Gravitational Constant. The :math:`\operatorname{safe-ln}` and :math:`\operatorname{safe-arctan}` functions are defined as follows: .. math:: \operatorname{safe-ln}(x, r) = \begin{cases} 0 & x = 0, r = 0 \\ \ln(x + r) & x \ge 0 \\ \ln((r^2 - x^2) / (r - x)) & x < 0, r \ne -x \\ -\ln(-2 x) & x < 0, r = -x \end{cases} .. math:: \operatorname{safe-arctan} \left( y, x \right) = \begin{cases} \text{arctan}\left( \frac{y}{x} \right) & x \ne 0 \\ \frac{\pi}{2} & x = 0 \quad \text{and} \quad y > 0 \\ -\frac{\pi}{2} & x = 0 \quad \text{and} \quad y < 0 \\ 0 & x = 0 \quad \text{and} \quad y = 0 \\ \end{cases} These were defined after [Fukushima2020]_ and guarantee a good accuracy on any observation point. References ---------- - [Nagy2000]_ - [Nagy2002]_ - [Fukushima2020]_ """ return ( GRAVITATIONAL_CONST * density * _evaluate_kernel( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, kernel_pot, ) )
[docs] @jit(nopython=True) def gravity_e( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, density, ): r""" Easting component of the gravitational acceleration due to a prism Returns the easting component of the gravitational acceleration produced by a single rectangular prism on a single computation point. Parameters ---------- easting : float Easting coordinate of the observation point. Must be in meters. northing : float Northing coordinate of the observation point. Must be in meters. upward : float Upward coordinate of the observation point. Must be in meters. prism_west : float The West boundary of the prism. Must be in meters. prism_east : float The East boundary of the prism. Must be in meters. prism_south : float The South boundary of the prism. Must be in meters. prism_north : float The North boundary of the prism. Must be in meters. prism_bottom : float The bottom boundary of the prism. Must be in meters. prism_top : float The top boundary of the prism. Must be in meters. density: float Density of the rectangular prism in kilograms per cubic meter. Returns ------- g_e : float Easting component of the gravitational acceleration generated by the rectangular prism on the observation point in :math:`\text{m}/\text{s}^2`. Notes ----- Returns the easting component :math:`g_x(\mathbf{p})` of the gravitational acceleration :math:`\mathbf{g}` on the observation point :math:`\mathbf{p} = (x_p, y_p, z_p)` generated by a single rectangular prism defined by its boundaries :math:`x_1, x_2, y_1, y_2, z_1, z_2` and with a density :math:`\rho`: .. math:: g_x(\mathbf{p}) = G \rho \,\, \Bigg\lvert \Bigg\lvert \Bigg\lvert k_x(x, y, z) \Bigg\rvert_{X_1}^{X_2} \Bigg\rvert_{Y_1}^{Y_2} \Bigg\rvert_{Z_1}^{Z_2} where .. math:: k_x(x, y, z) = \left[ y \, \operatorname{safe-ln} (z, r) + z \, \operatorname{safe-ln} (y, r) - x \, \operatorname{safe-arctan} \left( yz, xr \right) \right] .. math:: r = \sqrt{x^2 + y^2 + z^2}, and .. math:: X_1 = x_1 - x_p \\ X_2 = x_2 - x_p \\ Y_1 = y_1 - y_p \\ Y_2 = y_2 - y_p \\ Z_1 = z_1 - z_p \\ Z_2 = z_2 - z_p are the shifted coordinates of the prism boundaries and :math:`G` is the Universal Gravitational Constant. The :math:`\operatorname{safe-ln}` and :math:`\operatorname{safe-arctan}` functions are defined as follows: .. math:: \operatorname{safe-ln}(x, r) = \begin{cases} 0 & x = 0, r = 0 \\ \ln(x + r) & x \ge 0 \\ \ln((r^2 - x^2) / (r - x)) & x < 0, r \ne -x \\ -\ln(-2 x) & x < 0, r = -x \end{cases} .. math:: \operatorname{safe-arctan} \left( y, x \right) = \begin{cases} \text{arctan}\left( \frac{y}{x} \right) & x \ne 0 \\ \frac{\pi}{2} & x = 0 \quad \text{and} \quad y > 0 \\ -\frac{\pi}{2} & x = 0 \quad \text{and} \quad y < 0 \\ 0 & x = 0 \quad \text{and} \quad y = 0 \\ \end{cases} These were defined after [Fukushima2020]_ and guarantee a good accuracy on any observation point. References ---------- - [Nagy2000]_ - [Nagy2002]_ - [Fukushima2020]_ """ return ( GRAVITATIONAL_CONST * density * _evaluate_kernel( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, kernel_e, ) )
[docs] @jit(nopython=True) def gravity_n( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, density, ): r""" Northing component of the gravitational acceleration due to a prism Returns the northing component of the gravitational acceleration produced by a single rectangular prism on a single computation point. Parameters ---------- easting : float Easting coordinate of the observation point. Must be in meters. northing : float Northing coordinate of the observation point. Must be in meters. upward : float Upward coordinate of the observation point. Must be in meters. prism_west : float The West boundary of the prism. Must be in meters. prism_east : float The East boundary of the prism. Must be in meters. prism_south : float The South boundary of the prism. Must be in meters. prism_north : float The North boundary of the prism. Must be in meters. prism_bottom : float The bottom boundary of the prism. Must be in meters. prism_top : float The top boundary of the prism. Must be in meters. density: float Density of the rectangular prism in kilograms per cubic meter. Returns ------- g_n : float Northing component of the gravitational acceleration generated by the rectangular prism on the observation point in :math:`\text{m}/\text{s}^2`. Notes ----- Returns the northing component :math:`g_y(\mathbf{p})` of the gravitational acceleration :math:`\mathbf{g}` on the observation point :math:`\mathbf{p} = (x_p, y_p, z_p)` generated by a single rectangular prism defined by its boundaries :math:`x_1, x_2, y_1, y_2, z_1, z_2` and with a density :math:`\rho`: .. math:: g_y(\mathbf{p}) = G \rho \,\, \Bigg\lvert \Bigg\lvert \Bigg\lvert k_y(x, y, z) \Bigg\rvert_{X_1}^{X_2} \Bigg\rvert_{Y_1}^{Y_2} \Bigg\rvert_{Z_1}^{Z_2} where .. math:: k_y(x, y, z) = \left[ z \, \operatorname{safe-ln} (x, r) + x \, \operatorname{safe-ln} (z, r) - y \, \operatorname{safe-arctan} \left( zx, yr \right) \right] .. math:: r = \sqrt{x^2 + y^2 + z^2}, and .. math:: X_1 = x_1 - x_p \\ X_2 = x_2 - x_p \\ Y_1 = y_1 - y_p \\ Y_2 = y_2 - y_p \\ Z_1 = z_1 - z_p \\ Z_2 = z_2 - z_p are the shifted coordinates of the prism boundaries and :math:`G` is the Universal Gravitational Constant. The :math:`\operatorname{safe-ln}` and :math:`\operatorname{safe-arctan}` functions are defined as follows: .. math:: \operatorname{safe-ln}(x, r) = \begin{cases} 0 & x = 0, r = 0 \\ \ln(x + r) & x \ge 0 \\ \ln((r^2 - x^2) / (r - x)) & x < 0, r \ne -x \\ -\ln(-2 x) & x < 0, r = -x \end{cases} .. math:: \operatorname{safe-arctan} \left( y, x \right) = \begin{cases} \text{arctan}\left( \frac{y}{x} \right) & x \ne 0 \\ \frac{\pi}{2} & x = 0 \quad \text{and} \quad y > 0 \\ -\frac{\pi}{2} & x = 0 \quad \text{and} \quad y < 0 \\ 0 & x = 0 \quad \text{and} \quad y = 0 \\ \end{cases} These were defined after [Fukushima2020]_ and guarantee a good accuracy on any observation point. References ---------- - [Nagy2000]_ - [Nagy2002]_ - [Fukushima2020]_ """ return ( GRAVITATIONAL_CONST * density * _evaluate_kernel( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, kernel_n, ) )
[docs] @jit(nopython=True) def gravity_u( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, density, ): r""" Upward component of the gravitational acceleration due to a prism Returns the upward component of the gravitational acceleration produced by a single rectangular prism on a single computation point. Parameters ---------- easting : float Easting coordinate of the observation point. Must be in meters. northing : float Northing coordinate of the observation point. Must be in meters. upward : float Upward coordinate of the observation point. Must be in meters. prism_west : float The West boundary of the prism. Must be in meters. prism_east : float The East boundary of the prism. Must be in meters. prism_south : float The South boundary of the prism. Must be in meters. prism_north : float The North boundary of the prism. Must be in meters. prism_bottom : float The bottom boundary of the prism. Must be in meters. prism_top : float The top boundary of the prism. Must be in meters. density: float Density of the rectangular prism in kilograms per cubic meter. Returns ------- g_u : float Upward component of the gravitational acceleration generated by the rectangular prism on the observation point in :math:`\text{m}/\text{s}^2`. Notes ----- Returns the upward component :math:`g_z(\mathbf{p})` of the gravitational acceleration :math:`\mathbf{g}` on the observation point :math:`\mathbf{p} = (x_p, y_p, z_p)` generated by a single rectangular prism defined by its boundaries :math:`x_1, x_2, y_1, y_2, z_1, z_2` and with a density :math:`\rho`: .. math:: g_z(\mathbf{p}) = G \rho \,\, \Bigg\lvert \Bigg\lvert \Bigg\lvert k_z(x, y, z) \Bigg\rvert_{X_1}^{X_2} \Bigg\rvert_{Y_1}^{Y_2} \Bigg\rvert_{Z_1}^{Z_2} where .. math:: k_z(x, y, z) = - \left[ x \, \operatorname{safe-ln} (y, r) + y \, \operatorname{safe-ln} (x, r) - z \, \operatorname{safe-arctan} \left( xy, zr \right) \right] .. math:: r = \sqrt{x^2 + y^2 + z^2}, and .. math:: X_1 = x_1 - x_p \\ X_2 = x_2 - x_p \\ Y_1 = y_1 - y_p \\ Y_2 = y_2 - y_p \\ Z_1 = z_1 - z_p \\ Z_2 = z_2 - z_p are the shifted coordinates of the prism boundaries and :math:`G` is the Universal Gravitational Constant. .. important The minus sign in the :math:`k_x(x, y, z)` function is needed to return the **upward** component of the acceleration. [Nagy2000]_ and [Nagy2002]_ equation corresponds to the *downward* coordinate. The :math:`\operatorname{safe-ln}` and :math:`\operatorname{safe-arctan}` functions are defined as follows: .. math:: \operatorname{safe-ln}(x, r) = \begin{cases} 0 & x = 0, r = 0 \\ \ln(x + r) & x \ge 0 \\ \ln((r^2 - x^2) / (r - x)) & x < 0, r \ne -x \\ -\ln(-2 x) & x < 0, r = -x \end{cases} .. math:: \operatorname{safe-arctan} \left( y, x \right) = \begin{cases} \text{arctan}\left( \frac{y}{x} \right) & x \ne 0 \\ \frac{\pi}{2} & x = 0 \quad \text{and} \quad y > 0 \\ -\frac{\pi}{2} & x = 0 \quad \text{and} \quad y < 0 \\ 0 & x = 0 \quad \text{and} \quad y = 0 \\ \end{cases} These were defined after [Fukushima2020]_ and guarantee a good accuracy on any observation point. References ---------- - [Nagy2000]_ - [Nagy2002]_ - [Fukushima2020]_ """ return ( GRAVITATIONAL_CONST * density * _evaluate_kernel( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, kernel_u, ) )
[docs] @jit(nopython=True) def gravity_ee( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, density, ): r""" Easting-easting component of the gravitational tensor due to a prism Returns the easting-easting component of the gravitational tensor produced by a single rectangular prism on a single computation point. Parameters ---------- easting : float Easting coordinate of the observation point. Must be in meters. northing : float Northing coordinate of the observation point. Must be in meters. upward : float Upward coordinate of the observation point. Must be in meters. prism_west : float The West boundary of the prism. Must be in meters. prism_east : float The East boundary of the prism. Must be in meters. prism_south : float The South boundary of the prism. Must be in meters. prism_north : float The North boundary of the prism. Must be in meters. prism_bottom : float The bottom boundary of the prism. Must be in meters. prism_top : float The top boundary of the prism. Must be in meters. density: float Density of the rectangular prism in kilograms per cubic meter. Returns ------- g_ee : float Easting-easting component of the gravitational tensor generated by the rectangular prism on the observation point in :math:`\text{m}/\text{s}^2`. Return ``numpy.nan`` if the observation point falls in a singular point: prism vertices or prism edges perpendicular to the easting direction. Notes ----- Returns the easting-easting component :math:`g_{xx}(\mathbf{p})` of the gravitational tensor :math:`\mathbf{T}` on the observation point :math:`\mathbf{p} = (x_p, y_p, z_p)` generated by a single rectangular prism defined by its boundaries :math:`x_1, x_2, y_1, y_2, z_1, z_2` and with a density :math:`\rho`: .. math:: g_{xx}(\mathbf{p}) = G \rho \,\, \Bigg\lvert \Bigg\lvert \Bigg\lvert k_{xx}(x, y, z) \Bigg\rvert_{X_1}^{X_2} \Bigg\rvert_{Y_1}^{Y_2} \Bigg\rvert_{Z_1}^{Z_2} where .. math:: k_{xx}(x, y, z) = - \operatorname{safe-arctan} \left( yz, xr \right), .. math:: r = \sqrt{x^2 + y^2 + z^2}, and .. math:: X_1 = x_1 - x_p \\ X_2 = x_2 - x_p \\ Y_1 = y_1 - y_p \\ Y_2 = y_2 - y_p \\ Z_1 = z_1 - z_p \\ Z_2 = z_2 - z_p are the shifted coordinates of the prism boundaries and :math:`G` is the Universal Gravitational Constant. The :math:`\operatorname{safe-arctan}` function is defined as follows: .. math:: \operatorname{safe-arctan} \left( y, x \right) = \begin{cases} \text{arctan}\left( \frac{y}{x} \right) & x \ne 0 \\ \frac{\pi}{2} & x = 0 \quad \text{and} \quad y > 0 \\ -\frac{\pi}{2} & x = 0 \quad \text{and} \quad y < 0 \\ 0 & x = 0 \quad \text{and} \quad y = 0 \\ \end{cases} It was defined after [Fukushima2020]_ and guarantee a good accuracy on any observation point. References ---------- - [Nagy2000]_ - [Nagy2002]_ - [Fukushima2020]_ """ # Return nan if the observation point falls on a singular point. # For the g_ee this are edges perpendicular to the easting direction # (parallel to northing and upward) if is_point_on_northing_edge( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, ) or is_point_on_upward_edge( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, ): return np.nan # Evaluate kernel function on each vertex of the prism result = _evaluate_kernel( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, kernel_ee, ) # Add 4 pi if computing on the eastern face to return the limit approaching # from outside (approaching from the east) if is_point_on_east_face( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, ): result += 4 * np.pi return GRAVITATIONAL_CONST * density * result
[docs] @jit(nopython=True) def gravity_nn( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, density, ): r""" Northing-northing component of the gravitational tensor due to a prism Returns the northing-northing component of the gravitational tensor produced by a single rectangular prism on a single computation point. Parameters ---------- easting : float Easting coordinate of the observation point. Must be in meters. northing : float Northing coordinate of the observation point. Must be in meters. upward : float Upward coordinate of the observation point. Must be in meters. prism_west : float The West boundary of the prism. Must be in meters. prism_east : float The East boundary of the prism. Must be in meters. prism_south : float The South boundary of the prism. Must be in meters. prism_north : float The North boundary of the prism. Must be in meters. prism_bottom : float The bottom boundary of the prism. Must be in meters. prism_top : float The top boundary of the prism. Must be in meters. density: float Density of the rectangular prism in kilograms per cubic meter. Returns ------- g_nn : float Northing-northing component of the gravitational tensor generated by the rectangular prism on the observation point in :math:`\text{m}/\text{s}^2`. Return ``numpy.nan`` if the observation point falls in a singular point: prism vertices or prism edges perpendicular to the northing direction. Notes ----- Returns the northing-northing component :math:`g_{yy}(\mathbf{p})` of the gravitational tensor :math:`\mathbf{T}` on the observation point :math:`\mathbf{p} = (x_p, y_p, z_p)` generated by a single rectangular prism defined by its boundaries :math:`x_1, x_2, y_1, y_2, z_1, z_2` and with a density :math:`\rho`: .. math:: g_{yy}(\mathbf{p}) = G \rho \,\, \Bigg\lvert \Bigg\lvert \Bigg\lvert k_{yy}(x, y, z) \Bigg\rvert_{X_1}^{X_2} \Bigg\rvert_{Y_1}^{Y_2} \Bigg\rvert_{Z_1}^{Z_2} where .. math:: k_{yy}(x, y, z) = - \operatorname{safe-arctan} \left( zx, yr \right), .. math:: r = \sqrt{x^2 + y^2 + z^2}, and .. math:: X_1 = x_1 - x_p \\ X_2 = x_2 - x_p \\ Y_1 = y_1 - y_p \\ Y_2 = y_2 - y_p \\ Z_1 = z_1 - z_p \\ Z_2 = z_2 - z_p are the shifted coordinates of the prism boundaries and :math:`G` is the Universal Gravitational Constant. The :math:`\operatorname{safe-arctan}` function is defined as follows: .. math:: \operatorname{safe-arctan} \left( y, x \right) = \begin{cases} \text{arctan}\left( \frac{y}{x} \right) & x \ne 0 \\ \frac{\pi}{2} & x = 0 \quad \text{and} \quad y > 0 \\ -\frac{\pi}{2} & x = 0 \quad \text{and} \quad y < 0 \\ 0 & x = 0 \quad \text{and} \quad y = 0 \\ \end{cases} It was defined after [Fukushima2020]_ and guarantee a good accuracy on any observation point. References ---------- - [Nagy2000]_ - [Nagy2002]_ - [Fukushima2020]_ """ # Return nan if the observation point falls on a singular point. # For the g_nn this are edges perpendicular to the northing direction # (parallel to easting and upward) if is_point_on_easting_edge( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, ) or is_point_on_upward_edge( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, ): return np.nan # Evaluate kernel function on each vertex of the prism result = _evaluate_kernel( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, kernel_nn, ) # Add 4 pi if computing on the northern face to return the limit # approaching from outside (approaching from the north) if is_point_on_north_face( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, ): result += 4 * np.pi return GRAVITATIONAL_CONST * density * result
[docs] @jit(nopython=True) def gravity_uu( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, density, ): r""" Upward-upward component of the gravitational tensor due to a prism Returns the northing-northing component of the gravitational tensor produced by a single rectangular prism on a single computation point. Parameters ---------- easting : float Easting coordinate of the observation point. Must be in meters. northing : float Northing coordinate of the observation point. Must be in meters. upward : float Upward coordinate of the observation point. Must be in meters. prism_west : float The West boundary of the prism. Must be in meters. prism_east : float The East boundary of the prism. Must be in meters. prism_south : float The South boundary of the prism. Must be in meters. prism_north : float The North boundary of the prism. Must be in meters. prism_bottom : float The bottom boundary of the prism. Must be in meters. prism_top : float The top boundary of the prism. Must be in meters. density: float Density of the rectangular prism in kilograms per cubic meter. Returns ------- g_uu : float Upward-upward component of the gravitational tensor generated by the rectangular prism on the observation point in :math:`\text{m}/\text{s}^2`. Return ``numpy.nan`` if the observation point falls in a singular point: prism vertices or prism edges perpendicular to the upward direction. Notes ----- Returns the upward-upward component :math:`g_{zz}(\mathbf{p})` of the gravitational tensor :math:`\mathbf{T}` on the observation point :math:`\mathbf{p} = (x_p, y_p, z_p)` generated by a single rectangular prism defined by its boundaries :math:`x_1, x_2, y_1, y_2, z_1, z_2` and with a density :math:`\rho`: .. math:: g_{zz}(\mathbf{p}) = G \rho \,\, \Bigg\lvert \Bigg\lvert \Bigg\lvert k_{zz}(x, y, z) \Bigg\rvert_{X_1}^{X_2} \Bigg\rvert_{Y_1}^{Y_2} \Bigg\rvert_{Z_1}^{Z_2} where .. math:: k_{zz}(x, y, z) = - \operatorname{safe-arctan} \left( xy, zr \right), .. math:: r = \sqrt{x^2 + y^2 + z^2}, and .. math:: X_1 = x_1 - x_p \\ X_2 = x_2 - x_p \\ Y_1 = y_1 - y_p \\ Y_2 = y_2 - y_p \\ Z_1 = z_1 - z_p \\ Z_2 = z_2 - z_p are the shifted coordinates of the prism boundaries and :math:`G` is the Universal Gravitational Constant. The :math:`\operatorname{safe-arctan}` function is defined as follows: .. math:: \operatorname{safe-arctan} \left( y, x \right) = \begin{cases} \text{arctan}\left( \frac{y}{x} \right) & x \ne 0 \\ \frac{\pi}{2} & x = 0 \quad \text{and} \quad y > 0 \\ -\frac{\pi}{2} & x = 0 \quad \text{and} \quad y < 0 \\ 0 & x = 0 \quad \text{and} \quad y = 0 \\ \end{cases} It was defined after [Fukushima2020]_ and guarantee a good accuracy on any observation point. References ---------- - [Nagy2000]_ - [Nagy2002]_ - [Fukushima2020]_ """ # Return nan if the observation point falls on a singular point. # For the g_uu this are edges perpendicular to the upward direction # (parallel to easting and northing) if is_point_on_easting_edge( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, ) or is_point_on_northing_edge( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, ): return np.nan # Evaluate kernel function on each vertex of the prism result = _evaluate_kernel( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, kernel_uu, ) # Add 4 pi if computing on the top face to return the limit approaching # from outside (approaching from the top) if is_point_on_top_face( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, ): result += 4 * np.pi return GRAVITATIONAL_CONST * density * result
[docs] @jit(nopython=True) def gravity_en( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, density, ): r""" Easting-northing component of the gravitational tensor due to a prism Returns the northing-northing component of the gravitational tensor produced by a single rectangular prism on a single computation point. Parameters ---------- easting : float Easting coordinate of the observation point. Must be in meters. northing : float Northing coordinate of the observation point. Must be in meters. upward : float Upward coordinate of the observation point. Must be in meters. prism_west : float The West boundary of the prism. Must be in meters. prism_east : float The East boundary of the prism. Must be in meters. prism_south : float The South boundary of the prism. Must be in meters. prism_north : float The North boundary of the prism. Must be in meters. prism_bottom : float The bottom boundary of the prism. Must be in meters. prism_top : float The top boundary of the prism. Must be in meters. density: float Density of the rectangular prism in kilograms per cubic meter. Returns ------- g_en : float Easting-northing component of the gravitational tensor generated by the rectangular prism on the observation point in :math:`\text{m}/\text{s}^2`. Return ``numpy.nan`` if the observation point falls in a singular point: prism vertices or prism edges parallel to the upward direction. Notes ----- Returns the easting-northing component :math:`g_{xy}(\mathbf{p})` of the gravitational tensor :math:`\mathbf{T}` on the observation point :math:`\mathbf{p} = (x_p, y_p, z_p)` generated by a single rectangular prism defined by its boundaries :math:`x_1, x_2, y_1, y_2, z_1, z_2` and with a density :math:`\rho`: .. math:: g_{xy}(\mathbf{p}) = G \rho \,\, \Bigg\lvert \Bigg\lvert \Bigg\lvert k_{xy}(x, y, z) \Bigg\rvert_{X_1}^{X_2} \Bigg\rvert_{Y_1}^{Y_2} \Bigg\rvert_{Z_1}^{Z_2} where .. math:: k_{xy}(x, y, z) = \operatorname{safe-ln} \left( z, r \right), .. math:: r = \sqrt{x^2 + y^2 + z^2}, and .. math:: X_1 = x_1 - x_p \\ X_2 = x_2 - x_p \\ Y_1 = y_1 - y_p \\ Y_2 = y_2 - y_p \\ Z_1 = z_1 - z_p \\ Z_2 = z_2 - z_p are the shifted coordinates of the prism boundaries and :math:`G` is the Universal Gravitational Constant. The :math:`\operatorname{safe-ln}` function is defined as follows: .. math:: \operatorname{safe-ln}(x, r) = \begin{cases} 0 & x = 0, r = 0 \\ \ln(x + r) & x \ge 0 \\ \ln((r^2 - x^2) / (r - x)) & x < 0, r \ne -x \\ -\ln(-2 x) & x < 0, r = -x \end{cases} It was defined after [Fukushima2020]_ and guarantee a good accuracy on any observation point. References ---------- - [Nagy2000]_ - [Nagy2002]_ - [Fukushima2020]_ """ # Return nan if the observation point falls on a singular point. # For g_en this are edges parallel to to the upward direction if is_point_on_upward_edge( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, ): return np.nan return ( GRAVITATIONAL_CONST * density * _evaluate_kernel( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, kernel_en, ) )
[docs] @jit(nopython=True) def gravity_eu( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, density, ): r""" Easting-upward component of the gravitational tensor due to a prism Returns the easting-upward component of the gravitational tensor produced by a single rectangular prism on a single computation point. Parameters ---------- easting : float Easting coordinate of the observation point. Must be in meters. northing : float Northing coordinate of the observation point. Must be in meters. upward : float Upward coordinate of the observation point. Must be in meters. prism_west : float The West boundary of the prism. Must be in meters. prism_east : float The East boundary of the prism. Must be in meters. prism_south : float The South boundary of the prism. Must be in meters. prism_north : float The North boundary of the prism. Must be in meters. prism_bottom : float The bottom boundary of the prism. Must be in meters. prism_top : float The top boundary of the prism. Must be in meters. density: float Density of the rectangular prism in kilograms per cubic meter. Returns ------- g_eu : float Easting-upward component of the gravitational tensor generated by the rectangular prism on the observation point in :math:`\text{m}/\text{s}^2`. Return ``numpy.nan`` if the observation point falls in a singular point: prism vertices or prism edges parallel to the northing direction. Notes ----- Returns the easting-upward component :math:`g_{xz}(\mathbf{p})` of the gravitational tensor :math:`\mathbf{T}` on the observation point :math:`\mathbf{p} = (x_p, y_p, z_p)` generated by a single rectangular prism defined by its boundaries :math:`x_1, x_2, y_1, y_2, z_1, z_2` and with a density :math:`\rho`: .. math:: g_{xz}(\mathbf{p}) = G \rho \,\, \Bigg\lvert \Bigg\lvert \Bigg\lvert k_{xz}(x, y, z) \Bigg\rvert_{X_1}^{X_2} \Bigg\rvert_{Y_1}^{Y_2} \Bigg\rvert_{Z_1}^{Z_2} where .. math:: k_{xz}(x, y, z) = \operatorname{safe-ln} \left( y, r \right), .. math:: r = \sqrt{x^2 + y^2 + z^2}, and .. math:: X_1 = x_1 - x_p \\ X_2 = x_2 - x_p \\ Y_1 = y_1 - y_p \\ Y_2 = y_2 - y_p \\ Z_1 = z_1 - z_p \\ Z_2 = z_2 - z_p are the shifted coordinates of the prism boundaries and :math:`G` is the Universal Gravitational Constant. The :math:`\operatorname{safe-ln}` function is defined as follows: .. math:: \operatorname{safe-ln}(x, r) = \begin{cases} 0 & x = 0, r = 0 \\ \ln(x + r) & x \ge 0 \\ \ln((r^2 - x^2) / (r - x)) & x < 0, r \ne -x \\ -\ln(-2 x) & x < 0, r = -x \end{cases} It was defined after [Fukushima2020]_ and guarantee a good accuracy on any observation point. References ---------- - [Nagy2000]_ - [Nagy2002]_ - [Fukushima2020]_ """ # Return nan if the observation point falls on a singular point. # For g_eu this are edges parallel to to the northing direction if is_point_on_northing_edge( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, ): return np.nan return ( GRAVITATIONAL_CONST * density * _evaluate_kernel( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, kernel_eu, ) )
[docs] @jit(nopython=True) def gravity_nu( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, density, ): r""" Northing-upward component of the gravitational tensor due to a prism Returns the northing-upward component of the gravitational tensor produced by a single rectangular prism on a single computation point. Parameters ---------- easting : float Easting coordinate of the observation point. Must be in meters. northing : float Northing coordinate of the observation point. Must be in meters. upward : float Upward coordinate of the observation point. Must be in meters. prism_west : float The West boundary of the prism. Must be in meters. prism_east : float The East boundary of the prism. Must be in meters. prism_south : float The South boundary of the prism. Must be in meters. prism_north : float The North boundary of the prism. Must be in meters. prism_bottom : float The bottom boundary of the prism. Must be in meters. prism_top : float The top boundary of the prism. Must be in meters. density: float Density of the rectangular prism in kilograms per cubic meter. Returns ------- g_nu : float Northing-upward component of the gravitational tensor generated by the rectangular prism on the observation point in :math:`\text{m}/\text{s}^2`. Return ``numpy.nan`` if the observation point falls in a singular point: prism vertices or prism edges parallel to the easting direction. Notes ----- Returns the northing-upward component :math:`g_{yz}(\mathbf{p})` of the gravitational tensor :math:`\mathbf{T}` on the observation point :math:`\mathbf{p} = (x_p, y_p, z_p)` generated by a single rectangular prism defined by its boundaries :math:`x_1, x_2, y_1, y_2, z_1, z_2` and with a density :math:`\rho`: .. math:: g_{yz}(\mathbf{p}) = G \rho \,\, \Bigg\lvert \Bigg\lvert \Bigg\lvert k_{yz}(x, y, z) \Bigg\rvert_{X_1}^{X_2} \Bigg\rvert_{Y_1}^{Y_2} \Bigg\rvert_{Z_1}^{Z_2} where .. math:: k_{yz}(x, y, z) = \operatorname{safe-ln} \left( x, r \right), .. math:: r = \sqrt{x^2 + y^2 + z^2}, and .. math:: X_1 = x_1 - x_p \\ X_2 = x_2 - x_p \\ Y_1 = y_1 - y_p \\ Y_2 = y_2 - y_p \\ Z_1 = z_1 - z_p \\ Z_2 = z_2 - z_p are the shifted coordinates of the prism boundaries and :math:`G` is the Universal Gravitational Constant. The :math:`\operatorname{safe-ln}` function is defined as follows: .. math:: \operatorname{safe-ln}(x, r) = \begin{cases} 0 & x = 0, r = 0 \\ \ln(x + r) & x \ge 0 \\ \ln((r^2 - x^2) / (r - x)) & x < 0, r \ne -x \\ -\ln(-2 x) & x < 0, r = -x \end{cases} It was defined after [Fukushima2020]_ and guarantee a good accuracy on any observation point. References ---------- - [Nagy2000]_ - [Nagy2002]_ - [Fukushima2020]_ """ # Return nan if the observation point falls on a singular point. # For g_nu this are edges parallel to to the easting direction if is_point_on_easting_edge( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, ): return np.nan return ( GRAVITATIONAL_CONST * density * _evaluate_kernel( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, kernel_nu, ) )
@jit(nopython=True) def _evaluate_kernel( easting, northing, upward, prism_west, prism_east, prism_south, prism_north, prism_bottom, prism_top, kernel, ): r""" Evaluate a kernel function on every shifted vertex of a prism Parameters ---------- easting : float Easting coordinate of the observation point. Must be in meters. northing : float Northing coordinate of the observation point. Must be in meters. upward : float Upward coordinate of the observation point. Must be in meters. prism_west : float The West boundary of the prism. Must be in meters. prism_east : float The East boundary of the prism. Must be in meters. prism_south : float The South boundary of the prism. Must be in meters. prism_north : float The North boundary of the prism. Must be in meters. prism_bottom : float The bottom boundary of the prism. Must be in meters. prism_top : float The top boundary of the prism. Must be in meters. kernel : callable Kernel function that will be evaluated on each one of the shifted vertices of the prism. Returns ------- result : float Evaluation of the kernel function on each one of the vertices of the prism. Notes ----- This function evaluates a numerical kernel :math:`k(x, y, z)` on each one of the vertices of the prism: .. math:: v(\mathbf{p}) = \Bigg\lvert \Bigg\lvert \Bigg\lvert k(x, y, z) \Bigg\rvert_{X_1}^{X_2} \Bigg\rvert_{Y_1}^{Y_2} \Bigg\rvert_{Z_1}^{Z_2} where :math:`X_1`, :math:`X_2`, :math:`Y_1`, :math:`Y_2`, :math:`Z_1` and :math:`Z_2` are boundaries of the rectangular prism in the *shifted coordinates* defined by the Cartesian coordinate system with its origin located on the observation point :math:`\mathbf{p}`. References ---------- - [Nagy2000]_ - [Nagy2002]_ """ # Initialize result float to zero result = 0 # Iterate over the vertices of the prism for i in range(2): # Compute shifted easting coordinate if i == 0: shift_east = prism_east - easting else: shift_east = prism_west - easting shift_east_sq = shift_east**2 for j in range(2): # Compute shifted northing coordinate if j == 0: shift_north = prism_north - northing else: shift_north = prism_south - northing shift_north_sq = shift_north**2 for k in range(2): # Compute shifted upward coordinate if k == 0: shift_upward = prism_top - upward else: shift_upward = prism_bottom - upward shift_upward_sq = shift_upward**2 # Compute the radius radius = np.sqrt(shift_east_sq + shift_north_sq + shift_upward_sq) # If i, j or k is 1, the corresponding shifted # coordinate will refer to the lower boundary, # meaning the corresponding term should have a minus # sign. result += (-1) ** (i + j + k) * kernel( shift_east, shift_north, shift_upward, radius ) return result