Beispiel #1
0
def setup():
    global model, xp, yp, zp, inc, dec
    inc, dec = -30, 50
    reg_field = np.array(utils.dircos(inc, dec))
    model = [
        Prism(100, 300, -100, 100, 0, 400,
              {'density':1., 'magnetization':2}),
        Prism(-300, -100, -100, 100, 0, 200,
            {'density':2., 'magnetization':utils.dircos(25, -10)})]
    tmp = np.linspace(-500, 500, 50)
    xp, yp = [i.ravel() for i in np.meshgrid(tmp, tmp)]
    zp = -1*np.ones_like(xp)
Beispiel #2
0
 def sensitivity(self, grid):
     x, y, z = self.x, self.y, self.z
     inc, dec = self.inc, self.dec
     mag = utils.dircos(self.sinc, self.sdec)
     sens = numpy.empty((self.size, len(grid)), dtype=float)
     for i, s in enumerate(grid):
         sens[:,i] = kernel.tf(x, y, z, [s], inc, dec, pmag=mag)
     return sens
Beispiel #3
0
def setup():
    global model, xp, yp, zp, inc, dec
    inc, dec = -30, 50
    reg_field = np.array(utils.dircos(inc, dec))
    model = [
        Prism(100, 300, -100, 100, 0, 400, {
            'density': 1.,
            'magnetization': 2
        }),
        Prism(-300, -100, -100, 100, 0, 200, {
            'density': 2.,
            'magnetization': utils.dircos(25, -10)
        })
    ]
    tmp = np.linspace(-500, 500, 50)
    xp, yp = [i.ravel() for i in np.meshgrid(tmp, tmp)]
    zp = -1 * np.ones_like(xp)
Beispiel #4
0
 def sensitivity(self, grid):
     x, y, z = self.x, self.y, self.z
     inc, dec = self.inc, self.dec
     mag = utils.dircos(self.sinc, self.sdec)
     sens = numpy.empty((self.size, len(grid)), dtype=float)
     for i, s in enumerate(grid):
         sens[:, i] = kernel.tf(x, y, z, [s], inc, dec, pmag=mag)
     return sens
Beispiel #5
0
def setup():
    global model, xp, yp, zp, inc, dec
    inc, dec = -30, 50
    reg_field = np.array(utils.dircos(inc, dec))
    model = [
        Sphere(500, 0, 1000, 1000,
               {'density': -1., 'magnetization': utils.ang2vec(-2, inc, dec)}),
        Sphere(-1000, 0, 700, 700,
               {'density': 2., 'magnetization': utils.ang2vec(5, 25, -10)})]
    xp, yp, zp = gridder.regular([-2000, 2000, -2000, 2000], (50, 50), z=-1)
def setup():
    global model, xp, yp, zp, inc, dec
    inc, dec = -30, 50
    reg_field = np.array(utils.dircos(inc, dec))
    model = [
        Sphere(500, 0, 1000, 1000,
               {'density': -1., 'magnetization': utils.ang2vec(-2, inc, dec)}),
        Sphere(-1000, 0, 700, 700,
               {'density': 2., 'magnetization': utils.ang2vec(5, 25, -10)})]
    xp, yp, zp = gridder.regular([-2000, 2000, -2000, 2000], (50, 50), z=-1)
def test_dircos2():
    '''
    This test is pretty similar to the other dircos test. We set two pair of values, one for inclination and the other one for declination. Both values are compare by using the dircos funtion.
    '''

    set1 = numpy.random.normal(loc=45., scale=40., size=200)
    set2 = numpy.random.normal(loc=45., scale=40., size=200)
    dircos_auxiliars = dircos(set1, set2)
    dircos_fatiando = utils.dircos(set1, set2)
    assert_almost_equal(dircos_auxiliars, dircos_fatiando, decimal=8)
def test_dircos1():
    '''
    This test compares the dircos function created and the dircos function from Fatiando a Terra.
    We use 50 and 50 degrees for inclination and declination values.
    '''

    dircos_auxiliars = dircos(50., 50.)
    dircos_fatiando = utils.dircos(50., 50.)

    assert_almost_equal(dircos_auxiliars, dircos_fatiando, decimal=8)
def setup():
    global model, xp, yp, zp, inc, dec, prismmodel
    inc, dec = -30, 50
    mag = utils.dircos(25, -10)
    props1 = {'density':2., 'magnetization':mag}
    props2 = {'density':3., 'magnetization':1}
    model = [PolygonalPrism([
                 [100, -100],
                 [100, 100],
                 [-100, 100],
                 [-100, -100]], 100, 300, props1),
             PolygonalPrism([
                 [400, -100],
                 [600, -100],
                 [600, 100],
                 [400, 100]], 100, 300, props2)]
    prismmodel = [Prism(-100, 100, -100, 100, 100, 300, props1),
                  Prism(400, 600, -100, 100, 100, 300, props2)]
    tmp = np.linspace(-500, 1000, 50)
    xp, yp = [i.ravel() for i in np.meshgrid(tmp, tmp)]
    zp = -1*np.ones_like(xp)
def setup():
    global model, xp, yp, zp, inc, dec, prismmodel
    inc, dec = -30, 50
    mag = utils.dircos(25, -10)
    props1 = {'density': 2., 'magnetization': mag}
    props2 = {'density': 3., 'magnetization': 1}
    model = [PolygonalPrism([
                                [100, -100],
                                [100, 100],
                                [-100, 100],
                                [-100, -100]], 100, 300, props1),
             PolygonalPrism([
                                [400, -100],
                                [600, -100],
                                [600, 100],
                                [400, 100]], 100, 300, props2)]
    prismmodel = [Prism(-100, 100, -100, 100, 100, 300, props1),
                  Prism(400, 600, -100, 100, 100, 300, props2)]
    tmp = np.linspace(-500, 1000, 50)
    xp, yp = [i.ravel() for i in np.meshgrid(tmp, tmp)]
    zp = -1 * np.ones_like(xp)
Beispiel #11
0
def tf(xp, yp, zp, prisms, inc, dec, pmag=None):
    """
    Calculate the total-field anomaly of polygonal prisms.

    .. note:: The coordinate system of the input parameters is to be x -> North,
        y -> East and z -> Down.

    .. note:: Input units are SI. Output is in nT

    Parameters:

    * xp, yp, zp : arrays
        Arrays with the x, y, and z coordinates of the computation points.
    * prisms : list of :class:`fatiando.mesher.PolygonalPrism`
        The model used to calculate the total field anomaly.
        Prisms without the physical property ``'magnetization'`` will
        be ignored.
    * inc : float
        The inclination of the regional field (in degrees)
    * dec : float
        The declination of the regional field (in degrees)
    * pmag : [mx, my, mz] or None
        A magnetization vector. If not None, will use this value instead of the
        ``'magnetization'`` property of the prisms. Use this, e.g., for
        sensitivity matrix building.

    Returns:

    * res : array
        The field calculated on xp, yp, zp

    """
    if xp.shape != yp.shape != zp.shape:
        raise ValueError("Input arrays xp, yp, and zp must have same shape!")
    # Calculate the 3 components of the unit vector in the direction of the
    # regional field
    fx, fy, fz = utils.dircos(inc, dec)
    if pmag is not None:
        if isinstance(pmag, float) or isinstance(pmag, int):
            pintensity = pmag
            pmx, pmy, pmz = fx, fy, fz
        else:
            pintensity = numpy.linalg.norm(pmag)
            pmx, pmy, pmz = numpy.array(pmag) / pintensity
    res = numpy.zeros(len(xp), dtype='f')
    for prism in prisms:
        if prism is None or ('magnetization' not in prism.props
                             and pmag is None):
            continue
        if pmag is None:
            mag = prism.props['magnetization']
            if isinstance(mag, float) or isinstance(mag, int):
                intensity = mag
                mx, my, mz = fx, fy, fz
            else:
                intensity = numpy.linalg.norm(mag)
                mx, my, mz = numpy.array(mag) / intensity
        else:
            intensity = pintensity
            mx, my, mz = pmx, pmy, pmz
        nverts = prism.nverts
        x, y = prism.x, prism.y
        z1, z2 = prism.z1, prism.z2
        # Now calculate the total field anomaly
        Z1 = z1 - zp
        Z2 = z2 - zp
        for k in range(nverts):
            X1 = x[k] - xp
            Y1 = y[k] - yp
            X2 = x[(k + 1) % nverts] - xp
            Y2 = y[(k + 1) % nverts] - yp
            v1 = _integral_v1(X1, X2, Y1, Y2, Z1, Z2)
            v2 = _integral_v2(X1, X2, Y1, Y2, Z1, Z2)
            v3 = _integral_v3(X1, X2, Y1, Y2, Z1, Z2)
            v4 = _integral_v4(X1, X2, Y1, Y2, Z1, Z2)
            v5 = _integral_v5(X1, X2, Y1, Y2, Z1, Z2)
            v6 = _integral_v6(X1, X2, Y1, Y2, Z1, Z2)
            res += intensity * (
                mx * (v1 * fx + v2 * fy + v3 * fz)
                + my * (v2 * fx + v4 * fy + v5 * fz)
                + mz * (v3 * fx + v5 * fy + v6 * fz))
    res *= CM * T2NT
    return res
Beispiel #12
0
def tf(xp, yp, zp, prisms, inc, dec, pmag=None):
    """
    Calculate the total-field anomaly of prisms.

    .. note:: Input units are SI. Output is in nT

    .. note:: The coordinate system of the input parameters is to be x -> North,
        y -> East and z -> Down.

    Parameters:

    * xp, yp, zp : arrays
        Arrays with the x, y, and z coordinates of the computation points.
    * prisms : list of :class:`~fatiando.mesher.Prism`
        The model used to calculate the total field anomaly.
        Prisms without the physical property ``'magnetization'`` will
        be ignored. *prisms* can also be a :class:`~fatiando.mesher.PrismMesh`.
    * inc : float
        The inclination of the regional field (in degrees)
    * dec : float
        The declination of the regional field (in degrees)
    * pmag : [mx, my, mz] or None
        A magnetization vector. If not None, will use this value instead of the
        ``'magnetization'`` property of the prisms. Use this, e.g., for
        sensitivity matrix building.

    Returns:

    * res : array
        The field calculated on xp, yp, zp

    """
    if xp.shape != yp.shape != zp.shape:
        raise ValueError("Input arrays xp, yp, and zp must have same shape!")
    kernel = ''.join([
        'res + ((-1.)**(i + j))*intensity*(',
        '0.5*(my*fz + mz*fy)*log((r - x)/(r + x))',
        ' + 0.5*(mx*fz + mz*fx)*log((r - y)/(r + y))',
        ' - (mx*fy + my*fx)*log(r + z)',
        ' - mx*fx*arctan2(xy, x_sqr + zr + z_sqr)',
        ' - my*fy*arctan2(xy, r_sqr + zr - x_sqr)', ' + mz*fz*arctan2(xy, zr))'
    ])
    res = numpy.zeros_like(xp)
    # Calculate the 3 components of the unit vector in the direction of the
    # regional field
    fx, fy, fz = utils.dircos(inc, dec)
    if pmag is not None:
        if isinstance(pmag, float) or isinstance(pmag, int):
            pintensity = pmag
            pmx, pmy, pmz = fx, fy, fz
        else:
            pintensity = numpy.linalg.norm(pmag)
            pmx, pmy, pmz = numpy.array(pmag) / pintensity
    for prism in prisms:
        if (prism is None
                or ('magnetization' not in prism.props and pmag is None)):
            continue
        if pmag is None:
            mag = prism.props['magnetization']
            if isinstance(mag, float) or isinstance(mag, int):
                intensity = mag
                mx, my, mz = fx, fy, fz
            else:
                intensity = numpy.linalg.norm(mag)
                mx, my, mz = numpy.array(mag) / intensity
        else:
            intensity = pintensity
            mx, my, mz = pmx, pmy, pmz
        # First thing to do is make the computation point P the origin of the
        # coordinate system
        x1, x2, y1, y2, z1, z2 = prism.get_bounds()
        xs = [evaluate('x2 - xp'), evaluate('x1 - xp')]
        ys = [evaluate('y2 - yp'), evaluate('y1 - yp')]
        zs = [evaluate('z2 - zp'), evaluate('z1 - zp')]
        # Now calculate the total field anomaly
        for k in range(2):
            intensity *= -1
            z = zs[k]
            z_sqr = evaluate('z**2')
            for j in range(2):
                y = ys[j]
                y_sqr = evaluate('y**2')
                for i in range(2):
                    x = xs[i]
                    x_sqr = evaluate('x**2')
                    xy = evaluate('x*y')
                    r_sqr = evaluate('x_sqr + y_sqr + z_sqr')
                    r = evaluate('sqrt(r_sqr)')
                    zr = evaluate('z*r')
                    res = evaluate(kernel)
    res *= CM * T2NT
    return res
Beispiel #13
0
def tf(xp, yp, zp, spheres, inc, dec, pmag=None):
    """
    Calculate the total-field anomaly of spheres.

    .. note:: Input units are SI. Output is in nT

    Parameters:

    * xp, yp, zp : arrays
        The x, y, and z coordinates where the anomaly will be calculated
    * spheres : list of :class:`fatiando.mesher.Sphere`
        The spheres. Spheres must have the physical property
        ``'magnetization'``. Spheres without ``'magnetization'`` will be
        ignored.
    * inc : float
        The inclination of the regional field (in degrees)
    * dec : float
        The declination of the regional field (in degrees)
    * pmag : [mx, my, mz] or None
        A magnetization vector. If not None, will use this value instead of the
        ``'magnetization'`` property of the spheres. Use this, e.g., for
        sensitivity matrix building.

    Returns:

    * tf : array
        The total-field anomaly

    """
    if xp.shape != yp.shape != zp.shape:
        raise ValueError("Input arrays xp, yp, and zp must have same shape!")
    tf = numpy.zeros_like(xp)
    # Calculate the 3 components of the unit vector in the direction of the
    # regional field
    fx, fy, fz = utils.dircos(inc, dec)
    if pmag is not None:
        if isinstance(pmag, float) or isinstance(pmag, int):
            pintensity = pmag
            pmx, pmy, pmz = fx, fy, fz
        else:
            pintensity = numpy.linalg.norm(pmag)
            pmx, pmy, pmz = numpy.array(pmag) / pintensity
    for sphere in spheres:
        if sphere is None or ('magnetization' not in sphere.props
                              and pmag is None):
            continue
        radius = sphere.radius
        # Get the intensity and unit vector from the magnetization
        if pmag is None:
            mag = sphere.props['magnetization']
            if isinstance(mag, float) or isinstance(mag, int):
                intensity = mag
                mx, my, mz = fx, fy, fz
            else:
                intensity = numpy.linalg.norm(mag)
                mx, my, mz = numpy.array(mag) / intensity
        else:
            intensity = pintensity
            mx, my, mz = pmx, pmy, pmz
        # First thing to do is make the computation point P the origin of the
        # coordinate system
        x = sphere.x - xp
        y = sphere.y - yp
        z = sphere.z - zp
        # Calculate the 3 components of B
        dotprod = mx * x + my * y + mz * z
        r_sqr = x ** 2 + y ** 2 + z ** 2
        r5 = r_sqr ** (2.5)
        moment = intensity * (4. * numpy.pi * (radius ** 3) / 3.)
        bx = moment * (3 * dotprod * x - r_sqr * mx) / r5
        by = moment * (3 * dotprod * y - r_sqr * my) / r5
        bz = moment * (3 * dotprod * z - r_sqr * mz) / r5
        tf += (fx * bx + fy * by + fz * bz)
    tf *= CM * T2NT
    return tf
Beispiel #14
0
def tf(xp, yp, zp, prisms, inc, dec, pmag=None):
    """
    Calculate the total-field anomaly of prisms.

    .. note:: Input units are SI. Output is in nT

    .. note:: The coordinate system of the input parameters is to be x -> North,
        y -> East and z -> Down.

    Parameters:

    * xp, yp, zp : arrays
        Arrays with the x, y, and z coordinates of the computation points.
    * prisms : list of :class:`~fatiando.mesher.Prism`
        The model used to calculate the total field anomaly.
        Prisms without the physical property ``'magnetization'`` will
        be ignored. *prisms* can also be a :class:`~fatiando.mesher.PrismMesh`.
    * inc : float
        The inclination of the regional field (in degrees)
    * dec : float
        The declination of the regional field (in degrees)
    * pmag : [mx, my, mz] or None
        A magnetization vector. If not None, will use this value instead of the
        ``'magnetization'`` property of the prisms. Use this, e.g., for
        sensitivity matrix building.

    Returns:

    * res : array
        The field calculated on xp, yp, zp

    """
    if xp.shape != yp.shape != zp.shape:
        raise ValueError("Input arrays xp, yp, and zp must have same shape!")
    res = numpy.zeros_like(xp)
    # Calculate the 3 components of the unit vector in the direction of the
    # regional field
    fx, fy, fz = utils.dircos(inc, dec)
    if pmag is not None:
        if isinstance(pmag, float) or isinstance(pmag, int):
            pintensity = pmag
            pmx, pmy, pmz = fx, fy, fz
        else:
            pintensity = numpy.linalg.norm(pmag)
            pmx, pmy, pmz = numpy.array(pmag) / pintensity
    for prism in prisms:
        if prism is None or ('magnetization' not in prism.props
                             and pmag is None):
            continue
        if pmag is None:
            mag = prism.props['magnetization']
            if isinstance(mag, float) or isinstance(mag, int):
                intensity = mag
                mx, my, mz = fx, fy, fz
            else:
                intensity = numpy.linalg.norm(mag)
                mx, my, mz = numpy.array(mag) / intensity
        else:
            intensity = pintensity
            mx, my, mz = pmx, pmy, pmz
        # First thing to do is make the computation point P the origin of the
        # coordinate system
        x = [prism.x2 - xp, prism.x1 - xp]
        y = [prism.y2 - yp, prism.y1 - yp]
        z = [prism.z2 - zp, prism.z1 - zp]
        # Now calculate the total field anomaly
        for k in range(2):
            intensity *= -1
            z_sqr = z[k] ** 2
            for j in range(2):
                y_sqr = y[j] ** 2
                for i in range(2):
                    x_sqr = x[i] ** 2
                    xy = x[i] * y[j]
                    r_sqr = x_sqr + y_sqr + z_sqr
                    r = sqrt(r_sqr)
                    zr = z[k] * r
                    res += ((-1.) ** (i + j)) * intensity * (
                        0.5 * (my * fz + mz * fy) * log((r - x[i]) / (r + x[i]))
                        + 0.5 * (mx * fz + mz * fx) * log((r - y[j]) / (r + y[j]))
                        - (mx * fy + my * fx) * log(r + z[k])
                        - mx * fx * arctan2(xy, x_sqr + zr + z_sqr)
                        - my * fy * arctan2(xy, r_sqr + zr - x_sqr)
                        + mz * fz * arctan2(xy, zr))
    res *= CM * T2NT
    return res
Beispiel #15
0
def tf(xp, yp, zp, spheres, inc, dec):
    """
    Calculate the total-field anomaly of spheres.

    .. note:: Input units are SI. Output is in nT

    Parameters:

    * xp, yp, zp : arrays
        The x, y, and z coordinates where the anomaly will be calculated
    * spheres : list of :class:`fatiando.mesher.Sphere`
        The spheres. Spheres must have the properties ``'magnetization'``,
        ``'inclination'`` and ``'declination'``. If ``'inclination'`` and
        ``'declination'`` are not present, will use the values of *inc* and
        *dec* instead. Those without ``'magnetization'`` will be ignored.
    * inc : float
        The inclination of the regional field (in degrees)
    * dec : float
        The declination of the regional field (in degrees)

    Returns:

    * tf : array
        The total-field anomaly

    """
    if xp.shape != yp.shape != zp.shape:
        raise ValueError("Input arrays xp, yp, and zp must have same shape!")
    tf = numpy.zeros_like(xp)
    # Calculate the 3 components of the unit vector in the direction of the
    # regional field
    fx, fy, fz = utils.dircos(inc, dec)
    for sphere in spheres:
        if sphere is None or "magnetization" not in sphere.props:
            continue
        radius = sphere.radius
        mag = sphere.props["magnetization"]
        # Get the 3 components of the unit vector in the direction of the
        # magnetization from the inclination and declination
        if "inclination" in sphere.props and "declination" in sphere.props:
            inclination = sphere.props["inclination"]
            declination = sphere.props["declination"]
            mx, my, mz = utils.dircos(inclination, declination)
        # If not given, use in the direction of the regional field
        else:
            mx, my, mz = fx, fy, fz
        # First thing to do is make the computation point P the origin of the
        # coordinate system
        x = sphere.x - xp
        y = sphere.y - yp
        z = sphere.z - zp
        # Calculate the 3 components of B
        dotprod = mx * x + my * y + mz * z
        r_sqr = x ** 2 + y ** 2 + z ** 2
        r5 = r_sqr ** (2.5)
        moment = mag * (4.0 * numpy.pi * (radius ** 3) / 3.0)
        bx = moment * (3 * dotprod * x - r_sqr * mx) / r5
        by = moment * (3 * dotprod * y - r_sqr * my) / r5
        bz = moment * (3 * dotprod * z - r_sqr * mz) / r5
        tf = tf + (fx * bx + fy * by + fz * bz)
    tf *= CM * T2NT
    return tf
Beispiel #16
0
def tf(xp, yp, zp, prisms, inc, dec, pmag=None, pinc=None, pdec=None):
    """
    Calculate the total-field anomaly of prisms.

    .. note:: Input units are SI. Output is in nT

    .. note:: The coordinate system of the input parameters is to be x -> North,
        y -> East and z -> Down.

    Parameters:

    * xp, yp, zp : arrays
        Arrays with the x, y, and z coordinates of the computation points.
    * prisms : list of :class:`~fatiando.mesher.Prism`
        The model used to calculate the total field anomaly.
        Prisms must have the physical property ``'magnetization'`` will be
        ignored. If the physical properties ``'inclination'`` and
        ``'declination'`` are not present, will use the values of *inc* and
        *dec* instead (regional field).
        *prisms* can also be a :class:`~fatiando.mesher.PrismMesh`.
    * inc : float
        The inclination of the regional field (in degrees)
    * dec : float
        The declination of the regional field (in degrees)
    * pmag : float or None
        If not None, will use this value instead of the ``'magnetization'``
        property of the prisms. Use this, e.g., for sensitivity matrix building.
    * pinc : float or None
        If not None, will use this value instead of the ``'inclination'``
        property of the prisms. Use this, e.g., for sensitivity matrix building.
    * pdec : float or None
        If not None, will use this value instead of the ``'declination'``
        property of the prisms. Use this, e.g., for sensitivity matrix building.

    Returns:

    * res : array
        The field calculated on xp, yp, zp

    """
    if xp.shape != yp.shape != zp.shape:
        raise ValueError("Input arrays xp, yp, and zp must have same shape!")
    kernel = ''.join([
        'res + ((-1.)**(i + j))*magnetization*(',
        '0.5*(my*fz + mz*fy)*log((r - x)/(r + x))',
        ' + 0.5*(mx*fz + mz*fx)*log((r - y)/(r + y))',
        ' - (mx*fy + my*fx)*log(r + z)',
        ' - mx*fx*arctan2(xy, x_sqr + zr + z_sqr)',
        ' - my*fy*arctan2(xy, r_sqr + zr - x_sqr)',
        ' + mz*fz*arctan2(xy, zr))'])
    res = numpy.zeros_like(xp)
    # Calculate the 3 components of the unit vector in the direction of the
    # regional field
    fx, fy, fz = utils.dircos(inc, dec)
    for prism in prisms:
        if (prism is None or
            ('magnetization' not in prism.props and pmag is None)):
            continue
        if pmag is None:
            magnetization = prism.props['magnetization']
        else:
            magnetization = pmag
        # Get the 3 components of the unit vector in the direction of the
        # magnetization from the inclination and declination
        # 1) given by the function
        if pinc is not None and pdec is not None:
            mx, my, mz = utils.dircos(pinc, pdec)
        # 2) given by the prism
        elif 'inclination' in prism.props and 'declination' in prism.props:
            mx, my, mz = utils.dircos(prism.props['inclination'],
                                      prism.props['declination'])
        # 3) Use in the direction of the regional field
        else:
            mx, my, mz = fx, fy, fz
        # First thing to do is make the computation point P the origin of the
        # coordinate system
        x1, x2, y1, y2, z1, z2 = prism.get_bounds()
        xs = [evaluate('x2 - xp'), evaluate('x1 - xp')]
        ys = [evaluate('y2 - yp'), evaluate('y1 - yp')]
        zs = [evaluate('z2 - zp'), evaluate('z1 - zp')]
        # Now calculate the total field anomaly
        for k in range(2):
            magnetization *= -1
            z = zs[k]
            z_sqr = evaluate('z**2')
            for j in range(2):
                y = ys[j]
                y_sqr = evaluate('y**2')
                for i in range(2):
                    x = xs[i]
                    x_sqr = evaluate('x**2')
                    xy = evaluate('x*y')
                    r_sqr = evaluate('x_sqr + y_sqr + z_sqr')
                    r = evaluate('sqrt(r_sqr)')
                    zr = evaluate('z*r')
                    res = evaluate(kernel)
    res *= CM*T2NT
    return res
Beispiel #17
0
def tf(xp, yp, zp, prisms, inc, dec):
    """
    Calculate the total-field anomaly of polygonal prisms.

    .. note:: The coordinate system of the input parameters is to be x -> North,
        y -> East and z -> Down.

    .. note:: Input units are SI. Output is in nT

    Parameters:

    * xp, yp, zp : arrays
        Arrays with the x, y, and z coordinates of the computation points.
    * prisms : list of :class:`fatiando.mesher.PolygonalPrism`
        The model used to calculate the total field anomaly.
        Prisms must have the physical property ``'magnetization'`` will be
        ignored. If the physical properties ``'inclination'`` and
        ``'declination'`` are not present, will use the values of *inc* and
        *dec* instead (regional field).
    * inc : float
        The inclination of the regional field (in degrees)
    * dec : float
        The declination of the regional field (in degrees)

    Returns:

    * res : array
        The field calculated on xp, yp, zp

    """
    if xp.shape != yp.shape != zp.shape:
        raise ValueError("Input arrays xp, yp, and zp must have same shape!")
    # Calculate the 3 components of the unit vector in the direction of the
    # regional field
    fx, fy, fz = utils.dircos(inc, dec)
    res = numpy.zeros(len(xp), dtype="f")
    for prism in prisms:
        if prism is None or "magnetization" not in prism.props:
            continue
        magnetization = prism.props["magnetization"]
        nverts = prism.nverts
        x, y = prism.x, prism.y
        z1, z2 = prism.z1, prism.z2
        # Get the 3 components of the unit vector in the direction of the
        # magnetization from the inclination and declination
        # 1) given by the prism
        if "inclination" in prism.props and "declination" in prism.props:
            mx, my, mz = utils.dircos(prism.props["inclination"], prism.props["declination"])
        # 2) Use in the direction of the regional field
        else:
            mx, my, mz = fx, fy, fz
        # Now calculate the total field anomaly
        Z1 = z1 - zp
        Z2 = z2 - zp
        for k in range(nverts):
            X1 = x[k] - xp
            Y1 = y[k] - yp
            X2 = x[(k + 1) % nverts] - xp
            Y2 = y[(k + 1) % nverts] - yp
            v1 = _integral_v1(X1, X2, Y1, Y2, Z1, Z2)
            v2 = _integral_v2(X1, X2, Y1, Y2, Z1, Z2)
            v3 = _integral_v3(X1, X2, Y1, Y2, Z1, Z2)
            v4 = _integral_v4(X1, X2, Y1, Y2, Z1, Z2)
            v5 = _integral_v5(X1, X2, Y1, Y2, Z1, Z2)
            v6 = _integral_v6(X1, X2, Y1, Y2, Z1, Z2)
            res += magnetization * (
                mx * (v1 * fx + v2 * fy + v3 * fz)
                + my * (v2 * fx + v4 * fy + v5 * fz)
                + mz * (v3 * fx + v5 * fy + v6 * fz)
            )
    res *= CM * T2NT
    return res
Beispiel #18
0
def tf(xp, yp, zp, ellipsoids, F, inc, dec, demag=True, pmag=None):
    r"""
    The total-field anomaly produced by oblate ellipsoids.

    .. math::

        \Delta T = |\mathbf{T}| - |\mathbf{F}|,

    where :math:`\mathbf{T}` is the measured field and :math:`\mathbf{F}` is
    the local-geomagnetic field.

    The anomaly of a homogeneous ellipsoid can be calculated as:

    .. math::

        \Delta T \approx \hat{\mathbf{F}}\cdot\mathbf{B}.

    where :math:`\mathbf{B}` is the magnetic induction produced by the
    ellipsoid.

    This code follows the approach presented by Emerson et al. (1985).

    The coordinate system of the input parameters is x -> North, y -> East and
    z -> Down.

    Input units should be SI. Output is in nT.

    Parameters:

    * xp, yp, zp : arrays
        The x, y, and z coordinates where the anomaly will be calculated.
    * ellipsoids : list of :class:`mesher.OblateEllipsoid`
        The ellipsoids. Ellipsoids must have the physical properties
        ``'principal susceptibilities'`` and ``'susceptibility angles'``
        as prerequisite to calculate the self-demagnetization.
        Ellipsoids that are ``None`` will be ignored.
    * F, inc, dec : floats
       The intensity (in nT), inclination and declination (in degrees) of
       the local-geomagnetic field.
    * demag : boolean
        If True, will include the self-demagnetization.
    * pmag : [mx, my, mz] or None
        A magnetization vector. If not None, will use this value instead
        of calculating the magnetization of the ellipsoid. Use this, e.g.,
        for sensitivity matrix building.

    Returns:

    * tf : array
        The total-field anomaly

    References:

    Emerson, D. W., Clark, D., and Saul, S.: Magnetic exploration models
    incorporating remanence, demagnetization and anisotropy: HP 41C handheld
    computer algorithms, Exploration Geophysics, 16, 1-122, 1985.

    """
    fx, fy, fz = utils.dircos(inc, dec)
    Bx = bx(xp, yp, zp, ellipsoids, F, inc, dec, demag, pmag)
    By = by(xp, yp, zp, ellipsoids, F, inc, dec, demag, pmag)
    Bz = bz(xp, yp, zp, ellipsoids, F, inc, dec, demag, pmag)

    return fx * Bx + fy * By + fz * Bz
Beispiel #19
0
def tf(xp, yp, zp, prisms, inc, dec, pmag=None):
    """
    Calculate the total-field anomaly of polygonal prisms.

    .. note:: The coordinate system of the input parameters is to be x -> North,
        y -> East and z -> Down.

    .. note:: Input units are SI. Output is in nT

    Parameters:

    * xp, yp, zp : arrays
        Arrays with the x, y, and z coordinates of the computation points.
    * prisms : list of :class:`fatiando.mesher.PolygonalPrism`
        The model used to calculate the total field anomaly.
        Prisms without the physical property ``'magnetization'`` will
        be ignored.
    * inc : float
        The inclination of the regional field (in degrees)
    * dec : float
        The declination of the regional field (in degrees)
    * pmag : [mx, my, mz] or None
        A magnetization vector. If not None, will use this value instead of the
        ``'magnetization'`` property of the prisms. Use this, e.g., for
        sensitivity matrix building.

    Returns:

    * res : array
        The field calculated on xp, yp, zp

    """
    if xp.shape != yp.shape != zp.shape:
        raise ValueError("Input arrays xp, yp, and zp must have same shape!")
    # Calculate the 3 components of the unit vector in the direction of the
    # regional field
    fx, fy, fz = utils.dircos(inc, dec)
    if pmag is not None:
        if isinstance(pmag, float) or isinstance(pmag, int):
            pintensity = pmag
            pmx, pmy, pmz = fx, fy, fz
        else:
            pintensity = numpy.linalg.norm(pmag)
            pmx, pmy, pmz = numpy.array(pmag) / pintensity
    res = numpy.zeros(len(xp), dtype='f')
    for prism in prisms:
        if prism is None or ('magnetization' not in prism.props
                             and pmag is None):
            continue
        if pmag is None:
            mag = prism.props['magnetization']
            if isinstance(mag, float) or isinstance(mag, int):
                intensity = mag
                mx, my, mz = fx, fy, fz
            else:
                intensity = numpy.linalg.norm(mag)
                mx, my, mz = numpy.array(mag) / intensity
        else:
            intensity = pintensity
            mx, my, mz = pmx, pmy, pmz
        nverts = prism.nverts
        x, y = prism.x, prism.y
        z1, z2 = prism.z1, prism.z2
        # Now calculate the total field anomaly
        Z1 = z1 - zp
        Z2 = z2 - zp
        for k in range(nverts):
            X1 = x[k] - xp
            Y1 = y[k] - yp
            X2 = x[(k + 1) % nverts] - xp
            Y2 = y[(k + 1) % nverts] - yp
            v1 = _integral_v1(X1, X2, Y1, Y2, Z1, Z2)
            v2 = _integral_v2(X1, X2, Y1, Y2, Z1, Z2)
            v3 = _integral_v3(X1, X2, Y1, Y2, Z1, Z2)
            v4 = _integral_v4(X1, X2, Y1, Y2, Z1, Z2)
            v5 = _integral_v5(X1, X2, Y1, Y2, Z1, Z2)
            v6 = _integral_v6(X1, X2, Y1, Y2, Z1, Z2)
            res += intensity * (mx * (v1 * fx + v2 * fy + v3 * fz) + my *
                                (v2 * fx + v4 * fy + v5 * fz) + mz *
                                (v3 * fx + v5 * fy + v6 * fz))
    res *= CM * T2NT
    return res
Beispiel #20
0
def tf(xp, yp, zp, prisms, inc, dec, pmag=None, pinc=None, pdec=None):
    """
    Calculate the total-field anomaly of prisms.

    .. note:: Input units are SI. Output is in nT

    .. note:: The coordinate system of the input parameters is to be x -> North,
        y -> East and z -> Down.

    Parameters:

    * xp, yp, zp : arrays
        Arrays with the x, y, and z coordinates of the computation points.
    * prisms : list of :class:`~fatiando.mesher.Prism`
        The model used to calculate the total field anomaly.
        Prisms must have the physical property ``'magnetization'`` will be
        ignored. If the physical properties ``'inclination'`` and
        ``'declination'`` are not present, will use the values of *inc* and
        *dec* instead (regional field).
        *prisms* can also be a :class:`~fatiando.mesher.PrismMesh`.
    * inc : float
        The inclination of the regional field (in degrees)
    * dec : float
        The declination of the regional field (in degrees)
    * pmag : float or None
        If not None, will use this value instead of the ``'magnetization'``
        property of the prisms. Use this, e.g., for sensitivity matrix building.
    * pinc : float or None
        If not None, will use this value instead of the ``'inclination'``
        property of the prisms. Use this, e.g., for sensitivity matrix building.
    * pdec : float or None
        If not None, will use this value instead of the ``'declination'``
        property of the prisms. Use this, e.g., for sensitivity matrix building.

    Returns:

    * res : array
        The field calculated on xp, yp, zp

    """
    if xp.shape != yp.shape != zp.shape:
        raise ValueError("Input arrays xp, yp, and zp must have same shape!")
    res = numpy.zeros_like(xp)
    # Calculate the 3 components of the unit vector in the direction of the
    # regional field
    fx, fy, fz = utils.dircos(inc, dec)
    for prism in prisms:
        if prism is None or ('magnetization' not in prism.props
                              and pmag is None):
            continue
        if pmag is None:
            magnetization = prism.props['magnetization']
        else:
            magnetization = pmag
        # First thing to do is make the computation point P the origin of the
        # coordinate system
        x = [prism.x2 - xp, prism.x1 - xp]
        y = [prism.y2 - yp, prism.y1 - yp]
        z = [prism.z2 - zp, prism.z1 - zp]
        # Get the 3 components of the unit vector in the direction of the
        # magnetization from the inclination and declination
        # 1) given by the function
        if pinc is not None and pdec is not None:
            mx, my, mz = utils.dircos(pinc, pdec)
        # 2) given by the prism
        elif 'inclination' in prism.props and 'declination' in prism.props:
            mx, my, mz = utils.dircos(prism.props['inclination'],
                                      prism.props['declination'])
        # 3) Use in the direction of the regional field
        else:
            mx, my, mz = fx, fy, fz
        # Now calculate the total field anomaly
        for k in range(2):
            magnetization *= -1
            z_sqr = z[k]**2
            for j in range(2):
                y_sqr = y[j]**2
                for i in range(2):
                    x_sqr = x[i]**2
                    xy = x[i]*y[j]
                    r_sqr = x_sqr + y_sqr + z_sqr
                    r = sqrt(r_sqr)
                    zr = z[k]*r
                    res += ((-1.)**(i + j))*magnetization*(
                          0.5*(my*fz + mz*fy)*log((r - x[i])/(r + x[i]))
                        + 0.5*(mx*fz + mz*fx)*log((r - y[j])/(r + y[j]))
                        - (mx*fy + my*fx)*log(r + z[k])
                        - mx*fx*arctan2(xy, x_sqr + zr + z_sqr)
                        - my*fy*arctan2(xy, r_sqr + zr - x_sqr)
                        + mz*fz*arctan2(xy, zr))
    res *= CM*T2NT
    return res
Beispiel #21
0
def tf(xp, yp, zp, prisms, inc, dec, pmag=None):
    """
    Calculate the total-field anomaly of prisms.

    .. note:: Input units are SI. Output is in nT

    .. note:: The coordinate system of the input parameters is to be x -> North,
        y -> East and z -> Down.

    Parameters:

    * xp, yp, zp : arrays
        Arrays with the x, y, and z coordinates of the computation points.
    * prisms : list of :class:`~fatiando.mesher.Prism`
        The model used to calculate the total field anomaly.
        Prisms without the physical property ``'magnetization'`` will
        be ignored. *prisms* can also be a :class:`~fatiando.mesher.PrismMesh`.
    * inc : float
        The inclination of the regional field (in degrees)
    * dec : float
        The declination of the regional field (in degrees)
    * pmag : [mx, my, mz] or None
        A magnetization vector. If not None, will use this value instead of the
        ``'magnetization'`` property of the prisms. Use this, e.g., for
        sensitivity matrix building.

    Returns:

    * res : array
        The field calculated on xp, yp, zp

    """
    if xp.shape != yp.shape != zp.shape:
        raise ValueError("Input arrays xp, yp, and zp must have same shape!")
    res = numpy.zeros_like(xp)
    # Calculate the 3 components of the unit vector in the direction of the
    # regional field
    fx, fy, fz = utils.dircos(inc, dec)
    if pmag is not None:
        if isinstance(pmag, float) or isinstance(pmag, int):
            pintensity = pmag
            pmx, pmy, pmz = fx, fy, fz
        else:
            pintensity = numpy.linalg.norm(pmag)
            pmx, pmy, pmz = numpy.array(pmag)/pintensity
    for prism in prisms:
        if prism is None or ('magnetization' not in prism.props
                              and pmag is None):
            continue
        if pmag is None:
            mag = prism.props['magnetization']
            if isinstance(mag, float) or isinstance(mag, int):
                intensity = mag
                mx, my, mz = fx, fy, fz
            else:
                intensity = numpy.linalg.norm(mag)
                mx, my, mz = numpy.array(mag)/intensity
        else:
            intensity = pintensity
            mx, my, mz = pmx, pmy, pmz
        # First thing to do is make the computation point P the origin of the
        # coordinate system
        x = [prism.x2 - xp, prism.x1 - xp]
        y = [prism.y2 - yp, prism.y1 - yp]
        z = [prism.z2 - zp, prism.z1 - zp]
        # Now calculate the total field anomaly
        for k in range(2):
            intensity *= -1
            z_sqr = z[k]**2
            for j in range(2):
                y_sqr = y[j]**2
                for i in range(2):
                    x_sqr = x[i]**2
                    xy = x[i]*y[j]
                    r_sqr = x_sqr + y_sqr + z_sqr
                    r = sqrt(r_sqr)
                    zr = z[k]*r
                    res += ((-1.)**(i + j))*intensity*(
                          0.5*(my*fz + mz*fy)*log((r - x[i])/(r + x[i]))
                        + 0.5*(mx*fz + mz*fx)*log((r - y[j])/(r + y[j]))
                        - (mx*fy + my*fx)*log(r + z[k])
                        - mx*fx*arctan2(xy, x_sqr + zr + z_sqr)
                        - my*fy*arctan2(xy, r_sqr + zr - x_sqr)
                        + mz*fz*arctan2(xy, zr))
    res *= CM*T2NT
    return res