def test_tesseroid_vs_spherical_shell(): "gravmag.tesseroid equal analytical solution of spherical shell to 0.1%" density = 1000. top = 1000 bottom = 0 model = TesseroidMesh((0, 360, -90, 90, top, bottom), (1, 6, 12)) model.addprop('density', density*np.ones(model.size)) h = 10000 lon, lat, height = gridder.regular((0, model.dims[0], 0, model.dims[1]), (10, 10), z=h) funcs = ['potential', 'gx', 'gy', 'gz', 'gxx', 'gxy', 'gxz', 'gyy', 'gyz', 'gzz'] shellvalues = calc_shell_effect(h, top, bottom, density) for f in funcs: shell = shellvalues[f] tess = getattr(tesseroid, f)(lon, lat, height, model) diff = np.abs(shell - tess) # gz gy and the off-diagonal gradients should be zero so I can't # calculate a relative error (in %). # To do that, I'll use the gz and gzz shell values to calculate the # percentage. if f in 'gx gy'.split(): shell = shellvalues['gz'] elif f in 'gxy gxz gyz'.split(): shell = shellvalues['gzz'] diff = 100*diff/np.abs(shell) assert diff.max() < 0.1, "diff > 0.1% for {}: {}".format( f, diff.max())
def test_numba_vs_python(): "gravmag.tesseroid numba and pure python implementations give same result" model = TesseroidMesh((0, 1, 0, 2, 1000, 0), (2, 2, 1)) model.addprop('density', -200*np.ones(model.size)) lon, lat, height = gridder.regular((0, 1, 0, 2), (20, 20), z=250e3) for f in 'potential gx gy gz gxx gxy gxz gyy gyz gzz'.split(): func = getattr(tesseroid, f) py = func(lon, lat, height, model, engine='numpy') nb = func(lon, lat, height, model, engine='numba') assert_allclose(nb, py, err_msg="Mismatch for {}".format(f))
def test_numba_vs_python(): "gravmag.tesseroid numba and pure python implementations give same result" model = TesseroidMesh((0, 1, 0, 2, 1000, 0), (2, 2, 1)) model.addprop('density', -200 * np.ones(model.size)) lon, lat, height = gridder.regular((0, 1, 0, 2), (20, 20), z=250e3) for f in 'potential gx gy gz gxx gxy gxz gyy gyz gzz'.split(): func = getattr(tesseroid, f) py = func(lon, lat, height, model, engine='numpy') nb = func(lon, lat, height, model, engine='numba') assert_allclose(nb, py, err_msg="Mismatch for {}".format(f))
def test_serial_vs_parallel(): "gravmag.tesseroid serial and parallel execution give same result" model = TesseroidMesh((-1, 1.5, -2, 2, 0, -10e3), (3, 2, 1)) model.addprop('density', 500*np.ones(model.size)) lon, lat, height = gridder.regular((-1, 1.5, -2, 2), (15, 21), z=150e3) njobs = 3 for f in 'potential gx gy gz gxx gxy gxz gyy gyz gzz'.split(): func = getattr(tesseroid, f) serial = func(lon, lat, height, model, njobs=1) parallel = func(lon, lat, height, model, njobs=njobs) assert_allclose(serial, parallel, err_msg="Mismatch for {}".format(f))
def test_thick_shell(): def density_linear(height): r = height + MEAN_EARTH_RADIUS return a * r + b # Spherical shell model with a Tesseroid Mesh top, bottom = 0, -35000 density_1, density_2 = 2670, 3300 a = -(density_2 - density_1) / abs(bottom) b = (density_2 - density_1) / abs(bottom) * MEAN_EARTH_RADIUS + 2670 model = TesseroidMesh((0, 360, -90, 90, top, bottom), (1, 6, 12)) model.addprop("density", [density_linear for i in range(model.size)]) # Computation grids shape = (10, 10) grids = { "pole": gridder.regular((89, 90, 0, 1), shape, z=2e3), "equator": gridder.regular((0, 1, 0, 1), shape, z=2e3), "260km": gridder.regular((89, 90, 0, 1), shape, z=260e3), "30deg": gridder.regular((60, 90, 0, 30), shape, z=2e3) } fields = 'potential gx gy gz gxx gxy gxz gyy gyz gzz'.split() for field in fields: for grid in grids.keys(): msg = "Failed linear density test for thick shell while \ computing {} on {} grid".format(field, grid) lats, lons, heights = grids[grid] analytical = shell_linear_density(heights[0], top, bottom, a, b) result = getattr(tesseroid, field)(lons, lats, heights, model) diff = np.abs(result - analytical[field]) # gz gy and the off-diagonal gradients should be zero so I can't # calculate a relative error (in %). # To do that, I'll use the gz and gzz shell values to calculate the # percentage. if field in 'potential gz gxx gyy gzz'.split(): diff /= np.abs(analytical[field]) elif field in 'gx gy'.split(): diff /= np.abs(analytical['gz']) elif field in "gxy gxz gyz".split(): diff /= np.abs(analytical['gzz']) diff = 100 * np.max(diff) assert diff < 1e-1, msg
def test_thick_shell(): def density_exponential(height): r = height + MEAN_EARTH_RADIUS return a * np.exp(-(r - deltah) / b) + c # Spherical shell model with a Tesseroid Mesh top, bottom = 0, -35000 density_1, density_2 = 2670, 3300 b = 850. a = (density_2 - density_1) / (np.exp((abs(top - bottom)) / b) - 1) c = density_1 - a deltah = MEAN_EARTH_RADIUS model = TesseroidMesh((0, 360, -90, 90, top, bottom), (1, 6, 12)) model.addprop("density", [density_exponential for i in range(model.size)]) # Computation grids shape = (10, 10) grid = gridder.regular((60, 90, 0, 30), shape, z=2e3) fields = 'potential gx gy gz gxx gxy gxz gyy gyz gzz'.split() for field in fields: msg = "Failed linear density test for thin shell while \ computing {} on {} grid".format(field, grid) lats, lons, heights = grid[:] analytical = shell_exponential_density(heights[0], top, bottom, a, b, c, deltah) result = getattr(tesseroid, field)(lons, lats, heights, model) diff = np.abs(result - analytical[field]) # gz gy and the off-diagonal gradients should be zero so I can't # calculate a relative error (in %). # To do that, I'll use the gz and gzz shell values to calculate the # percentage. if field in 'potential gz gxx gyy gzz'.split(): diff /= np.abs(analytical[field]) elif field in 'gx gy'.split(): diff /= np.abs(analytical['gz']) elif field in "gxy gxz gyz".split(): diff /= np.abs(analytical['gzz']) diff = 100 * np.max(diff) assert diff < 1e-1, msg