def test_check_opt(capsys): fhtarg = [filters.kong_61_2007(), 43] qwehtarg = [ np.array(1e-12), np.array(1e-30), np.array(51), np.array(100), np.array(33) ] res = utils.check_opt(None, None, 'fht', fhtarg, 4) assert_allclose(res, (False, True, False)) out, _ = capsys.readouterr() outstr = " Kernel Opt. : None\n Loop over : Freq" assert out[:53] == outstr res = utils.check_opt(None, 'off', 'hqwe', qwehtarg, 4) assert_allclose(res, (False, True, False)) out, _ = capsys.readouterr() outstr = " Kernel Opt. : None\n Loop over : Freq" assert out[:53] == outstr res = utils.check_opt('parallel', 'off', 'fht', [fhtarg[0], 0], 4) if use_vml: assert_allclose(callable(res[0]), True) outstr = " Kernel Opt. : Use parallel\n Loop over : Of" elif not use_ne_eval: assert_allclose(callable(res[0]), False) outstr = "* WARNING :: `numexpr` is not installed, `opt=='parallel'` " else: assert_allclose(callable(res[0]), False) outstr = "* WARNING :: `numexpr` is not installed with VML, `opt=='pa" assert_allclose(res[1:], (False, True)) out, _ = capsys.readouterr() assert out[:59] == outstr res = utils.check_opt('parallel', 'freq', 'hqwe', qwehtarg, 4) if use_vml: assert_allclose(callable(res[0]), True) outstr = " Kernel Opt. : Use parallel\n Loop over : Fr" elif not use_ne_eval: assert_allclose(callable(res[0]), False) outstr = "* WARNING :: `numexpr` is not installed, `opt=='parallel'` " else: assert_allclose(callable(res[0]), False) outstr = "* WARNING :: `numexpr` is not installed with VML, `opt=='pa" assert_allclose(res[1:], (True, False)) out, _ = capsys.readouterr() assert out[:59] == outstr
def test_dlf(): # 10. dlf # DLF is integral of fht and ffht, and therefore tested a lot through # those. Here we just ensure status quo. And if a problem arises in fht or # ffht, it would make it obvious if the problem arises from dlf or not. # Check DLF for Fourier t = DATA['t'][()] for i in [0, 1, 2]: dat = DATA['ffht' + str(i)][()] tres = DATA['tEM' + str(i)][()] finp = dat['fEM'] ftarg = dat['ftarg'] if i > 0: finp /= 2j * np.pi * dat['f'] if i > 1: finp *= -1 if ftarg[1] == 0: finp = finp.reshape(t.size, -1) tEM = transform.dlf(finp, 2 * np.pi * dat['f'], t, ftarg[0], ftarg[1], kind=ftarg[2]) assert_allclose(tEM * 2 / np.pi, tres, rtol=1e-3) # Check DLF for Hankel for ab in [12, 22, 13, 33]: model = utils.check_model([], 10, 2, 2, 5, 1, 10, True, 0) depth, res, aniso, epermH, epermV, mpermH, mpermV, isfullspace = model frequency = utils.check_frequency(1, res, aniso, epermH, epermV, mpermH, mpermV, 0) freq, etaH, etaV, zetaH, zetaV = frequency src = [0, 0, 0] src, nsrc = utils.check_dipole(src, 'src', 0) ab, msrc, mrec = utils.check_ab(ab, 0) ht, htarg = utils.check_hankel('fht', None, 0) options = utils.check_opt(None, None, ht, htarg, 0) use_ne_eval, loop_freq, loop_off = options xdirect = False # Important, as we want to comp. wavenumber-frequency! rec = [np.arange(1, 11) * 500, np.zeros(10), 300] rec, nrec = utils.check_dipole(rec, 'rec', 0) off, angle = utils.get_off_ang(src, rec, nsrc, nrec, 0) lsrc, zsrc = utils.get_layer_nr(src, depth) lrec, zrec = utils.get_layer_nr(rec, depth) fhtfilt = htarg[0] pts_per_dec = htarg[1] # # # 0. No Spline # # # # fht calculation lambd = fhtfilt.base / off[:, None] PJ = kernel.wavenumber(zsrc, zrec, lsrc, lrec, depth, etaH, etaV, zetaH, zetaV, lambd, ab, xdirect, msrc, mrec, use_ne_eval) factAng = kernel.angle_factor(angle, ab, msrc, mrec) # dlf calculation fEM0 = transform.dlf(PJ, lambd, off, fhtfilt, 0, factAng=factAng, ab=ab) # Analytical frequency-domain solution freq1 = kernel.fullspace(off, angle, zsrc, zrec, etaH, etaV, zetaH, zetaV, ab, msrc, mrec) # Compare assert_allclose(np.squeeze(fEM0), np.squeeze(freq1)) # # # 1. Spline; One angle # # # options = utils.check_opt('spline', None, ht, htarg, 0) use_ne_eval, loop_freq, loop_off = options # fht calculation lambd, _ = transform.get_spline_values(fhtfilt, off, pts_per_dec) PJ1 = kernel.wavenumber(zsrc, zrec, lsrc, lrec, depth, etaH, etaV, zetaH, zetaV, lambd, ab, xdirect, msrc, mrec, use_ne_eval) # dlf calculation fEM1 = transform.dlf(PJ1, lambd, off, fhtfilt, pts_per_dec, factAng=factAng, ab=ab) # Compare assert_allclose(np.squeeze(fEM1), np.squeeze(freq1), rtol=1e-4) # # # 2.a Lagged; One angle # # # rec = [np.arange(1, 11) * 500, np.arange(-5, 5) * 0, 300] rec, nrec = utils.check_dipole(rec, 'rec', 0) off, angle = utils.get_off_ang(src, rec, nsrc, nrec, 0) # fht calculation lambd, _ = transform.get_spline_values(fhtfilt, off, -1) PJ2 = kernel.wavenumber(zsrc, zrec, lsrc, lrec, depth, etaH, etaV, zetaH, zetaV, lambd, ab, xdirect, msrc, mrec, use_ne_eval) factAng = kernel.angle_factor(angle, ab, msrc, mrec) # dlf calculation fEM2 = transform.dlf(PJ2, lambd, off, fhtfilt, -1, factAng=factAng, ab=ab) # Analytical frequency-domain solution freq2 = kernel.fullspace(off, angle, zsrc, zrec, etaH, etaV, zetaH, zetaV, ab, msrc, mrec) # Compare assert_allclose(np.squeeze(fEM2), np.squeeze(freq2), rtol=1e-4) # # # 2.b Lagged; Multi angle # # # rec = [np.arange(1, 11) * 500, np.arange(-5, 5) * 200, 300] rec, nrec = utils.check_dipole(rec, 'rec', 0) off, angle = utils.get_off_ang(src, rec, nsrc, nrec, 0) # fht calculation lambd, _ = transform.get_spline_values(fhtfilt, off, -1) PJ2 = kernel.wavenumber(zsrc, zrec, lsrc, lrec, depth, etaH, etaV, zetaH, zetaV, lambd, ab, xdirect, msrc, mrec, use_ne_eval) factAng = kernel.angle_factor(angle, ab, msrc, mrec) # dlf calculation fEM2 = transform.dlf(PJ2, lambd, off, fhtfilt, -1, factAng=factAng, ab=ab) # Analytical frequency-domain solution freq2 = kernel.fullspace(off, angle, zsrc, zrec, etaH, etaV, zetaH, zetaV, ab, msrc, mrec) # Compare assert_allclose(np.squeeze(fEM2), np.squeeze(freq2), rtol=1e-4) # # # 3. Spline; Multi angle # # # lambd, _ = transform.get_spline_values(fhtfilt, off, 10) # fht calculation PJ3 = kernel.wavenumber(zsrc, zrec, lsrc, lrec, depth, etaH, etaV, zetaH, zetaV, lambd, ab, xdirect, msrc, mrec, use_ne_eval) # dlf calculation fEM3 = transform.dlf(PJ3, lambd, off, fhtfilt, 10, factAng=factAng, ab=ab) # Compare assert_allclose(np.squeeze(fEM3), np.squeeze(freq2), rtol=1e-3)
def test_hankel(htype): # 1. fht / 2. hqwe / 3. hquad # Compare wavenumber-domain calculation / FHT with analytical # frequency-domain fullspace solution calc = getattr(transform, htype) model = utils.check_model([], 10, 2, 2, 5, 1, 10, True, 0) depth, res, aniso, epermH, epermV, mpermH, mpermV, isfullspace = model frequency = utils.check_frequency(1, res, aniso, epermH, epermV, mpermH, mpermV, 0) freq, etaH, etaV, zetaH, zetaV = frequency src = [0, 0, 0] src, nsrc = utils.check_dipole(src, 'src', 0) ab, msrc, mrec = utils.check_ab(11, 0) ht, htarg = utils.check_hankel(htype, None, 0) options = utils.check_opt(None, None, htype, htarg, 0) use_ne_eval, loop_freq, loop_off = options xdirect = False # Important, as we want to compare wavenumber-frequency! rec = [np.arange(1, 11) * 500, np.zeros(10), 300] rec, nrec = utils.check_dipole(rec, 'rec', 0) off, angle = utils.get_off_ang(src, rec, nsrc, nrec, 0) lsrc, zsrc = utils.get_layer_nr(src, depth) lrec, zrec = utils.get_layer_nr(rec, depth) # # # 0. No Spline # # # if htype != 'hquad': # hquad is always using spline # Wavenumber solution plus transform wvnr0, _, conv = calc(zsrc, zrec, lsrc, lrec, off, angle, depth, ab, etaH, etaV, zetaH, zetaV, xdirect, htarg, False, msrc, mrec) # Analytical frequency-domain solution freq0 = kernel.fullspace(off, angle, zsrc, zrec, etaH, etaV, zetaH, zetaV, ab, msrc, mrec) # Compare assert_allclose(conv, True) assert_allclose(np.squeeze(wvnr0), np.squeeze(freq0)) # # # 1. Spline; One angle # # # htarg, opt = utils.spline_backwards_hankel(htype, None, 'spline') ht, htarg = utils.check_hankel(htype, htarg, 0) options = utils.check_opt(None, None, htype, htarg, 0) use_ne_eval, loop_freq, loop_off = options if htype == 'hquad': # Lower atol to ensure convergence ht, htarg = utils.check_hankel('quad', [1e-8], 0) # Wavenumber solution plus transform wvnr1, _, conv = calc(zsrc, zrec, lsrc, lrec, off, angle, depth, ab, etaH, etaV, zetaH, zetaV, xdirect, htarg, False, msrc, mrec) # Analytical frequency-domain solution freq1 = kernel.fullspace(off, angle, zsrc, zrec, etaH, etaV, zetaH, zetaV, ab, msrc, mrec) # Compare assert_allclose(conv, True) assert_allclose(np.squeeze(wvnr1), np.squeeze(freq1), rtol=1e-4) # # # 2. Spline; Multi angle # # # rec = [np.arange(1, 11) * 500, np.arange(-5, 5) * 200, 300] rec, nrec = utils.check_dipole(rec, 'rec', 0) off, angle = utils.get_off_ang(src, rec, nsrc, nrec, 0) if htype == 'hqwe': # Put a very low diff_quad, to test it.; lower err ht, htarg = utils.check_hankel( 'qwe', [1e-8, '', '', 200, 80, .1, 1e-6, .1, 1000], 0) # Analytical frequency-domain solution wvnr2, _, conv = calc(zsrc, zrec, lsrc, lrec, off, angle, depth, ab, etaH, etaV, zetaH, zetaV, xdirect, htarg, False, msrc, mrec) # Analytical frequency-domain solution freq2 = kernel.fullspace(off, angle, zsrc, zrec, etaH, etaV, zetaH, zetaV, ab, msrc, mrec) # Compare assert_allclose(conv, True) assert_allclose(np.squeeze(wvnr2), np.squeeze(freq2), rtol=1e-4) # # # 3. Spline; pts_per_dec # # # if htype == 'fht': ht, htarg = utils.check_hankel('fht', ['key_201_2012', 20], 0) elif htype == 'hqwe': ht, htarg = utils.check_hankel('qwe', ['', '', '', 80, 100], 0) if htype != 'hquad': # hquad is always pts_per_dec # Analytical frequency-domain solution wvnr3, _, conv = calc(zsrc, zrec, lsrc, lrec, off, angle, depth, ab, etaH, etaV, zetaH, zetaV, xdirect, htarg, False, msrc, mrec) # Analytical frequency-domain solution freq3 = kernel.fullspace(off, angle, zsrc, zrec, etaH, etaV, zetaH, zetaV, ab, msrc, mrec) # Compare assert_allclose(conv, True) assert_allclose(np.squeeze(wvnr3), np.squeeze(freq3), rtol=1e-4) # # # 4. Spline; Only one offset # # # rec = [5000, 0, 300] rec, nrec = utils.check_dipole(rec, 'rec', 0) off, angle = utils.get_off_ang(src, rec, nsrc, nrec, 0) if htype == 'hqwe': ht, htarg = utils.check_hankel('qwe', ['', '', '', 200, 80], 0) elif htype == 'hquad': ht, htarg = utils.check_hankel('quad', None, 0) # Analytical frequency-domain solution wvnr4, _, conv = calc(zsrc, zrec, lsrc, lrec, off, angle, depth, ab, etaH, etaV, zetaH, zetaV, xdirect, htarg, False, msrc, mrec) # Analytical frequency-domain solution freq4 = kernel.fullspace(off, angle, zsrc, zrec, etaH, etaV, zetaH, zetaV, ab, msrc, mrec) # Compare assert_allclose(conv, True) assert_allclose(np.squeeze(wvnr4), np.squeeze(freq4), rtol=1e-4)
def setup(self, size): # One big, one small model if size == 'Small': # Total size: 5*1*1*1 = 5 off = np.array([500., 1000.]) else: # Total size: 5*100*1*201 = 100'500 off = np.arange(1, 101)*200. # Define survey freq = np.array([1]) lsrc = 1 lrec = 1 angle = np.zeros(off.shape) ab = 11 msrc = False mrec = False if VERSION2: zsrc = 250. zrec = 300. else: zsrc = np.array([250.]) # Not sure if this distinction zrec = np.array([300.]) # is actually needed use_ne_eval = False # Define model depth = np.array([-np.infty, 0, 300, 2000, 2100]) res = np.array([2e14, .3, 1, 50, 1]) aniso = np.ones(res.shape) epermH = np.ones(res.shape) epermV = np.ones(res.shape) mpermH = np.ones(res.shape) mpermV = np.ones(res.shape) # Other parameters xdirect = False verb = 0 # Compute eta, zeta etaH = 1/res + np.outer(2j*np.pi*freq, epermH*epsilon_0) etaV = 1/(res*aniso*aniso) + np.outer(2j*np.pi*freq, epermV*epsilon_0) zetaH = np.outer(2j*np.pi*freq, mpermH*mu_0) zetaV = np.outer(2j*np.pi*freq, mpermV*mu_0) # Collect input self.hankel = {'zsrc': zsrc, 'zrec': zrec, 'lsrc': lsrc, 'lrec': lrec, 'off': off, 'depth': depth, 'ab': ab, 'etaH': etaH, 'etaV': etaV, 'zetaH': zetaH, 'zetaV': zetaV, 'xdirect': xdirect, 'msrc': msrc, 'mrec': mrec} if not VERSION2: self.hankel['use_ne_eval'] = use_ne_eval # Before c73d6647; you had to give `ab` to `check_hankel`; # check_opt didn't exist then. if VERSION2: charg = (verb, ) new_version = True else: try: opt = utils.check_opt(None, None, 'fht', ['', 0], verb) charg = (verb, ) if np.size(opt) == 4: new_version = False else: new_version = True except VariableCatch: new_version = False charg = (ab, verb) # From 9bed72b0 onwards, there is no `use_spline`; `htarg` input # changed (29/04/2018; before v1.4.1). if new_version: if VERSION2: htarg = {'dlf': 'key_201_2009', 'pts_per_dec': -1} else: htarg = ['key_201_2009', -1] else: htarg = ['key_201_2009', None] # HT arguments if VERSION2: dlfargname = 'htarg' qweargname = 'htarg' quadargname = 'htarg' htarg1 = {'dlf': 'key_201_2009', 'pts_per_dec': 0} htarg2 = {'dlf': 'key_201_2009', 'pts_per_dec': 10} name = 'dlf' else: dlfargname = 'fhtarg' qweargname = 'qweargs' quadargname = 'quadargs' htarg1 = ['key_201_2009', 0] htarg2 = ['key_201_2009', 10] name = 'fht' _, fhtarg_st = utils.check_hankel(name, htarg1, *charg) self.fhtarg_st = {dlfargname: fhtarg_st} _, fhtarg_sp = utils.check_hankel(name, htarg2, *charg) self.fhtarg_sp = {dlfargname: fhtarg_sp} _, fhtarg_la = utils.check_hankel(name, htarg, *charg) self.fhtarg_la = {dlfargname: fhtarg_la} # QWE: We lower the requirements here, otherwise it takes too long # ['rtol', 'atol', 'nquad', 'maxint', 'pts_per_dec', 'diff_quad', 'a', # 'b', 'limit'] # Args depend if QUAD included into QWE or not try: if VERSION2: args_sp = {'atol': 1e-6, 'rtol': 1e-10, 'nquad': 51, 'maxint': 100, 'pts_per_dec': 10, 'diff_quad': np.inf} args_st = {'atol': 1e-6, 'rtol': 1e-10, 'nquad': 51, 'maxint': 100, 'pts_per_dec': 0, 'diff_quad': np.inf} else: args_sp = [1e-6, 1e-10, 51, 100, 10, np.inf] args_st = [1e-6, 1e-10, 51, 100, 0, np.inf] _, qwearg_sp = utils.check_hankel('qwe', args_sp, *charg) _, qwearg_st = utils.check_hankel('qwe', args_st, *charg) except VariableCatch: args_sp = [1e-6, 1e-10, 51, 100, 10] args_st = [1e-6, 1e-10, 51, 100, 0] _, qwearg_sp = utils.check_hankel('qwe', args_sp, *charg) _, qwearg_st = utils.check_hankel('qwe', args_st, *charg) self.qwearg_st = {qweargname: qwearg_st} self.qwearg_sp = {qweargname: qwearg_sp} # QUAD: We lower the requirements here, otherwise it takes too long # ['rtol', 'atol', 'limit', 'a', 'b', 'pts_per_dec'] if VERSION2: args = {'atol': 1e-6, 'rtol': 1e-10, 'limit': 100, 'a': 1e-6, 'b': 0.1, 'pts_per_dec': 10} else: args = [1e-6, 1e-10, 100, 1e-6, 0.1, 10] try: # QUAD only included since 6104614e (before v1.3.0) _, quadargs = utils.check_hankel('quad', args, *charg) self.quadargs = {quadargname: quadargs} except VariableCatch: self.quadargs = {} if not new_version and not VERSION2: self.fhtarg_la.update({'use_spline': True}) self.fhtarg_sp.update({'use_spline': True}) self.fhtarg_st.update({'use_spline': False}) self.qwearg_sp.update({'use_spline': True}) self.qwearg_st.update({'use_spline': False}) self.quadargs.update({'use_spline': True}) if VERSION2: self.hankel['ang_fact'] = kernel.angle_factor( angle, ab, msrc, mrec) else: # From bb6447a onwards ht-transforms take `factAng`, not `angle`, # to avoid re-calculation in loops. try: transform.fht(angle=angle, **self.fhtarg_la, **self.hankel) self.hankel['angle'] = angle except VariableCatch: self.hankel['factAng'] = kernel.angle_factor( angle, ab, msrc, mrec) if not VERSION2: # From b6f6872 onwards fht-transforms calculates lambd/int_pts in # model.fem, not in transform.fht, to avoid re-calculation in # loops. try: transform.fht(**self.fhtarg_la, **self.hankel) except VariableCatch: lambd, int_pts = transform.get_spline_values( fhtarg_st[0], off, fhtarg_st[1]) self.fhtarg_st.update({'fhtarg': ( fhtarg_st[0], fhtarg_st[1], lambd, int_pts)}) lambd, int_pts = transform.get_spline_values( fhtarg_la[0], off, fhtarg_la[1]) self.fhtarg_la.update( {'fhtarg': (fhtarg_la[0], fhtarg_la[1], lambd, int_pts)}) lambd, int_pts = transform.get_spline_values( fhtarg_sp[0], off, fhtarg_sp[1]) self.fhtarg_sp.update( {'fhtarg': (fhtarg_sp[0], fhtarg_sp[1], lambd, int_pts)})