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)
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
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)
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
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)
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
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
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
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
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
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
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
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
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
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
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