The fatiando package has been deprecated. Please check out the new tools in the Fatiando a Terra website: www.fatiando.org

Source code for fatiando.gravmag.talwani

"""
Calculate the gravitational attraction of a 2D body with polygonal vertical
cross-section using the formula of Talwani et al. (1959)

Use the :func:`~fatiando.mesher.Polygon` object to create polygons.

.. warning:: the vertices must be given clockwise! If not, the result will have
    an inverted sign.

**Components**

* :func:`~fatiando.gravmag.talwani.gz`

**References**

Talwani, M., J. L. Worzel, and M. Landisman (1959), Rapid Gravity Computations
for Two-Dimensional Bodies with Application to the Mendocino Submarine
Fracture Zone, J. Geophys. Res., 64(1), 49-59, doi:10.1029/JZ064i001p00049.

----

"""
import numpy
from numpy import arctan2, pi, sin, cos, log, tan

from fatiando.constants import G, SI2MGAL


[docs]def gz(xp, zp, polygons, dens=None): """ Calculates the :math:`g_z` gravity acceleration component. .. note:: The coordinate system of the input parameters is z -> **DOWN**. .. note:: All input values in **SI** units(!) and output in **mGal**! Parameters: * xp, zp : arrays The x and z coordinates of the computation points. * polygons : list of :func:`~fatiando.mesher.Polygon` The density model used. Polygons must have the property ``'density'``. Polygons that don't have this property will be ignored in the computations. Elements of *polygons* that are None will also be ignored. * dens : float or None If not None, will use this value instead of the ``'density'`` property of the polygons. Use this, e.g., for sensitivity matrix building. .. note:: The y coordinate of the polygons is used as z! Returns: * gz : array The :math:`g_z` component calculated on the computation points """ if xp.shape != zp.shape: raise ValueError("Input arrays xp and zp must have same shape!") res = numpy.zeros_like(xp) for polygon in polygons: if polygon is None or ('density' not in polygon.props and dens is None): continue if dens is None: density = polygon.props['density'] else: density = dens x = polygon.x z = polygon.y nverts = polygon.nverts for v in xrange(nverts): # Change the coordinates of this vertice xv = x[v] - xp zv = z[v] - zp # The last vertice pairs with the first one if v == nverts - 1: xvp1 = x[0] - xp zvp1 = z[0] - zp else: xvp1 = x[v + 1] - xp zvp1 = z[v + 1] - zp # Temporary fix. The analytical conditions for these limits don't # work. So if the conditions are breached, sum 0.01 meters to the # coodinates and be happy xv[xv == 0.] += 0.01 xv[xv == xvp1] += 0.01 zv[zv[xv == zv] == 0.] += 0.01 zv[zv == zvp1] += 0.01 zvp1[zvp1[xvp1 == zvp1] == 0.] += 0.01 xvp1[xvp1 == 0.] += 0.01 # End of fix phi_v = arctan2(zvp1 - zv, xvp1 - xv) ai = xvp1 + zvp1 * (xvp1 - xv) / (zv - zvp1) theta_v = arctan2(zv, xv) theta_vp1 = arctan2(zvp1, xvp1) theta_v[theta_v < 0] += pi theta_vp1[theta_vp1 < 0] += pi tmp = ai * sin(phi_v) * cos(phi_v) * ( theta_v - theta_vp1 + tan(phi_v) * log( (cos(theta_v) * (tan(theta_v) - tan(phi_v))) / (cos(theta_vp1) * (tan(theta_vp1) - tan(phi_v))))) tmp[theta_v == theta_vp1] = 0. res = res + tmp * density res = res * SI2MGAL * 2.0 * G return res