def __init__(self, **kwargs): BaseEMSimulation.__init__(self, **kwargs) try: ht, htarg = check_hankel( "fht", [self.hankel_filter, self.hankel_pts_per_dec], 1) self.fhtfilt = htarg[0] # Store filter self.hankel_pts_per_dec = htarg[1] # Store pts_per_dec except ValueError: arg = {} arg["dlf"] = self.hankel_filter if self.hankel_pts_per_dec is not None: arg["pts_per_dec"] = self.hankel_pts_per_dec ht, htarg = check_hankel("dlf", arg, 1) self.fhtfilt = htarg["dlf"] # Store filter self.hankel_pts_per_dec = htarg["pts_per_dec"] # Store pts_per_dec self.hankel_filter = self.fhtfilt.name # Store name self.n_filter = self.fhtfilt.base.size
def __init__(self, mesh, **kwargs): Problem.BaseProblem.__init__(self, mesh, **kwargs) # Check input arguments. If self.hankel_filter is not a valid filter, # it will set it to the default (key_201_2009). ht, htarg = check_hankel('fht', [self.hankel_filter, self.hankel_pts_per_dec], 1) self.fhtfilt = htarg[0] # Store filter self.hankel_filter = self.fhtfilt.name # Store name self.hankel_pts_per_dec = htarg[1] # Store pts_per_dec if self.verbose: print(">> Use "+self.hankel_filter+" filter for Hankel Transform") if self.hankel_pts_per_dec != 0: raise NotImplementedError()
def __init__(self, mesh, **kwargs): Problem.BaseProblem.__init__(self, mesh, **kwargs) # Check input arguments. If self.hankel_filter is not a valid filter, # it will set it to the default (key_201_2009). ht, htarg = check_hankel('dlf', { 'dlf': self.hankel_filter, 'pts_per_dec': 0 }, 1) self.fhtfilt = htarg['dlf'] # Store filter self.hankel_pts_per_dec = htarg['pts_per_dec'] # Store pts_per_dec if self.verbose: print(">> Use " + self.hankel_filter + " filter for Hankel Transform")
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 magnetic_field(self, xyz, field="secondary"): """ Magnetic field due to a magnetic dipole in a layered halfspace at a specific height z Parameters ---------- xyz : numpy.ndarray receiver locations of shape (n_locations, 3). The z component cannot be below the surface (z=0.0). field : ("secondary", "total") Flag for the type of field to return. """ if np.any(xyz[:, 2] < 0.0): raise ValueError("Cannot compute fields below the surface") h = self.location[2] dxyz = xyz - self.location offsets = np.linalg.norm(dxyz[:, :-1], axis=-1) # Comput transform operations # -1 gives lagged convolution in dlf ht, htarg = check_hankel('dlf', { 'dlf': 'key_101_2009', 'pts_per_dec': 0 }, 1) fhtfilt = htarg['dlf'] pts_per_dec = htarg['pts_per_dec'] f = self.frequency n_frequency = len(f) lambd, int_points = get_dlf_points(fhtfilt, offsets, pts_per_dec) thick = self.thickness n_layer = len(thick) + 1 thick, sigma, epsilon, mu = self._get_valid_properties() sigh = sigma_hat( self.frequency[:, None], sigma, epsilon, quasistatic=self.quasistatic ).T # this gets sigh with proper shape (n_layer x n_freq) and fortran ordering. mu = np.tile(mu, (n_frequency, 1)).T # shape(n_layer x n_freq) rTE = rTE_forward(f, lambd.reshape(-1), sigh, mu, thick) rTE = rTE.reshape((n_frequency, *lambd.shape)) # secondary is height of receiver plus height of source rTE *= np.exp(-lambd * (xyz[:, -1] + h)[:, None]) # works for variable xyz because each point has it's own lambdas src_x, src_y, src_z = self.orientation C0x = C0y = C0z = 0.0 C1x = C1y = C1z = 0.0 if src_x != 0.0: C0x += src_x * (dxyz[:, 0]**2 / offsets**2)[:, None] * lambd**2 C1x += src_x * (1 / offsets - 2 * dxyz[:, 0]**2 / offsets**3)[:, None] * lambd C0y += src_x * (dxyz[:, 0] * dxyz[:, 1] / offsets**2)[:, None] * lambd**2 C1y -= src_x * (2 * dxyz[:, 0] * dxyz[:, 1] / offsets**3)[:, None] * lambd # C0z += 0.0 C1z -= (src_x * dxyz[:, 0] / offsets)[:, None] * lambd**2 if src_y != 0.0: C0x += src_y * (dxyz[:, 0] * dxyz[:, 1] / offsets**2)[:, None] * lambd**2 C1x -= src_y * (2 * dxyz[:, 0] * dxyz[:, 1] / offsets**3)[:, None] * lambd C0y += src_y * (dxyz[:, 1]**2 / offsets**2)[:, None] * lambd**2 C1y += src_y * (1 / offsets - 2 * dxyz[:, 1]**2 / offsets**3)[:, None] * lambd # C0z += 0.0 C1z -= (src_y * dxyz[:, 1] / offsets)[:, None] * lambd**2 if src_z != 0.0: # C0x += 0.0 C1x += (src_z * dxyz[:, 0] / offsets)[:, None] * lambd**2 # C0y += 0.0 C1y += (src_z * dxyz[:, 1] / offsets)[:, None] * lambd**2 C0z += src_z * lambd**2 # C1z += 0.0 # Do the hankel transform on each component em_x = ((C0x * rTE) @ fhtfilt.j0 + (C1x * rTE) @ fhtfilt.j1) / offsets em_y = ((C0y * rTE) @ fhtfilt.j0 + (C1y * rTE) @ fhtfilt.j1) / offsets em_z = ((C0z * rTE) @ fhtfilt.j0 + (C1z * rTE) @ fhtfilt.j1) / offsets if field == "total": # add in the primary field r = np.linalg.norm(dxyz, axis=-1) mdotr = src_x * dxyz[:, 0] + src_y * dxyz[:, 1] + src_z * dxyz[:, 2] em_x += 3 * dxyz[:, 0] * mdotr / r**5 - src_x / r**3 em_y += 3 * dxyz[:, 1] * mdotr / r**5 - src_y / r**3 em_z += 3 * dxyz[:, 2] * mdotr / r**5 - src_z / r**3 return self.moment / (4 * np.pi) * np.stack( (em_x, em_y, em_z), axis=-1)
True, 0) depth, res, aniso, epermH, epermV, mpermH, mpermV, isfullspace = model frequency = utils.check_frequency(freq, res, aniso, epermH, epermV, mpermH, mpermV, 0) freq, etaH, etaV, zetaH, zetaV = frequency # src and rec rec = [np.arange(1, 11) * 500, np.arange(1, 11) * 100, 300] src = [[0, -100], [0, -200], 200] src, nsrc = utils.check_dipole(src, 'src', 0) 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) ht, htarg = utils.check_hankel('fht', None, 0) # 1. FULLSPACE inp1 = { 'ab': 12, 'off': off, 'angle': angle, 'zsrc': zsrc, 'zrec': zrec, 'lsrc': lsrc, 'lrec': lrec, 'depth': depth, 'freq': freq, 'etaH': np.ones((3, 3)) * etaH[:, 0], 'etaV': np.ones((3, 3)) * etaV[:, 0], 'zetaH': np.ones((3, 3)) * zetaH[:, 0],
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)})
def test_dlf(): # 10. dlf # DLF is integral of hankel_dlf and fourier_dlf, and therefore tested a lot # through those. Here we just ensure status quo. And if a problem arises in # hankel_dlf or fourier_dlf, 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['fourier_dlf' + 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['pts_per_dec'] == 0: finp = finp.reshape(t.size, -1) tEM = transform.dlf(finp, 2 * np.pi * dat['f'], t, ftarg['dlf'], ftarg['pts_per_dec'], kind=ftarg['kind']) 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, _ = model frequency = utils.check_frequency(1, res, aniso, epermH, epermV, mpermH, mpermV, 0) _, 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('dlf', {}, 0) 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) dlf = htarg['dlf'] pts_per_dec = htarg['pts_per_dec'] # # # 0. No Spline # # # # dlf calculation lambd = dlf.base / off[:, None] PJ = kernel.wavenumber(zsrc, zrec, lsrc, lrec, depth, etaH, etaV, zetaH, zetaV, lambd, ab, xdirect, msrc, mrec) # Angle factor, one example with None instead of 1's. if ab != 13: ang_fact = kernel.angle_factor(angle, ab, msrc, mrec) else: ang_fact = None # dlf calculation fEM0 = transform.dlf(PJ, lambd, off, dlf, 0, ang_fact=ang_fact, 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 # # # # dlf calculation lambd, _ = transform.get_dlf_points(dlf, off, pts_per_dec) PJ1 = kernel.wavenumber(zsrc, zrec, lsrc, lrec, depth, etaH, etaV, zetaH, zetaV, lambd, ab, xdirect, msrc, mrec) # dlf calculation fEM1 = transform.dlf(PJ1, lambd, off, dlf, pts_per_dec, ang_fact=ang_fact, 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) # dlf calculation lambd, _ = transform.get_dlf_points(dlf, off, -1) PJ2 = kernel.wavenumber(zsrc, zrec, lsrc, lrec, depth, etaH, etaV, zetaH, zetaV, lambd, ab, xdirect, msrc, mrec) ang_fact = kernel.angle_factor(angle, ab, msrc, mrec) # dlf calculation fEM2 = transform.dlf(PJ2, lambd, off, dlf, -1, ang_fact=ang_fact, 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) # dlf calculation lambd, _ = transform.get_dlf_points(dlf, off, -1) PJ2 = kernel.wavenumber(zsrc, zrec, lsrc, lrec, depth, etaH, etaV, zetaH, zetaV, lambd, ab, xdirect, msrc, mrec) ang_fact = kernel.angle_factor(angle, ab, msrc, mrec) # dlf calculation fEM2 = transform.dlf(PJ2, lambd, off, dlf, -1, ang_fact=ang_fact, 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_dlf_points(dlf, off, 30) # dlf calculation PJ3 = kernel.wavenumber(zsrc, zrec, lsrc, lrec, depth, etaH, etaV, zetaH, zetaV, lambd, ab, xdirect, msrc, mrec) # dlf calculation fEM3 = transform.dlf(PJ3, lambd, off, dlf, 30, ang_fact=ang_fact, ab=ab) # Compare assert_allclose(np.squeeze(fEM3), np.squeeze(freq2), rtol=1e-3)
SS = np.sin(Bx) * np.tile(g_w, maxint) tEM_iint = iuSpline(np.log(2 * np.pi * freq), fEM.imag) sEM = tEM_iint(np.log(Bx / t[:, None])) * SS fqwe0['sEM'] = sEM fqwe0['intervals'] = intervals # # G -- QWE - HQWE # # # Model 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, nsrc = utils.check_dipole([0, 0, 0], 'src', 0) ab, msrc, mrec = utils.check_ab(11, 0) ht, htarg = utils.check_hankel('qwe', {'pts_per_dec': 80}, 0) 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) # Frequency-domain result freqres = kernel.fullspace(off, angle, zsrc, zrec, etaH, etaV, zetaH, zetaV, ab, msrc, mrec) # The following is a condensed version of transform.hqwe etaH = etaH[0, :] etaV = etaV[0, :] zetaH = zetaH[0, :] zetaV = zetaV[0, :] rtol, atol, nquad, maxint, pts_per_dec, diff_quad, a, b, limit = htarg g_x, g_w = special.p_roots(nquad)
def test_check_hankel(capsys): # # DLF # # # verbose ht, htarg = utils.check_hankel('dlf', {}, 4) out, _ = capsys.readouterr() assert " Hankel : DLF (Fast Hankel Transform)\n > F" in out assert " > DLF type : Standard" in out assert ht == 'dlf' assert htarg['dlf'].name == filters.key_201_2009().name assert htarg['pts_per_dec'] == 0 # provide filter-string and unknown parameter _, htarg = utils.check_hankel('dlf', {'dlf': 'key_201_2009', 'abc': 0}, 1) out, _ = capsys.readouterr() assert htarg['dlf'].name == filters.key_201_2009().name assert htarg['pts_per_dec'] == 0 assert "WARNING :: Unknown htarg {'abc': 0} for method 'dlf'" in out # provide filter-instance _, htarg = utils.check_hankel('dlf', {'dlf': filters.kong_61_2007()}, 0) assert htarg['dlf'].name == filters.kong_61_2007().name assert htarg['pts_per_dec'] == 0 # provide pts_per_dec _, htarg = utils.check_hankel('dlf', {'pts_per_dec': -1}, 3) out, _ = capsys.readouterr() assert " > DLF type : Lagged Convolution" in out assert htarg['dlf'].name == filters.key_201_2009().name assert htarg['pts_per_dec'] == -1 # provide filter-string and pts_per_dec _, htarg = utils.check_hankel('dlf', { 'dlf': 'key_201_2009', 'pts_per_dec': 20 }, 4) out, _ = capsys.readouterr() assert " > DLF type : Splined, 20.0 pts/dec" in out assert htarg['dlf'].name == filters.key_201_2009().name assert htarg['pts_per_dec'] == 20 # Assert it can be called repetitively _, _ = capsys.readouterr() ht, htarg = utils.check_hankel('dlf', {}, 1) _, _ = utils.check_hankel(ht, htarg, 1) out, _ = capsys.readouterr() assert out == "" # # QWE # # # verbose ht, htarg = utils.check_hankel('qwe', {}, 4) out, _ = capsys.readouterr() outstr = " Hankel : Quadrature-with-Extrapolation\n > rtol" assert outstr in out assert ht == 'qwe' assert htarg['rtol'] == 1e-12 assert htarg['atol'] == 1e-30 assert htarg['nquad'] == 51 assert htarg['maxint'] == 100 assert htarg['pts_per_dec'] == 0 assert htarg['diff_quad'] == 100 assert htarg['a'] is None assert htarg['b'] is None assert htarg['limit'] is None # limit _, htarg = utils.check_hankel('qwe', {'limit': 30}, 0) assert htarg['rtol'] == 1e-12 assert htarg['atol'] == 1e-30 assert htarg['nquad'] == 51 assert htarg['maxint'] == 100 assert htarg['pts_per_dec'] == 0 assert htarg['diff_quad'] == 100 assert htarg['a'] is None assert htarg['b'] is None assert htarg['limit'] == 30 # all arguments _, htarg = utils.check_hankel( 'qwe', { 'rtol': 1e-3, 'atol': 1e-4, 'nquad': 31, 'maxint': 20, 'pts_per_dec': 30, 'diff_quad': 200, 'a': 1e-6, 'b': 160, 'limit': 30 }, 3) out, _ = capsys.readouterr() assert " > a (quad): 1e-06" in out assert " > b (quad): 160" in out assert " > limit (quad): 30" in out assert htarg['rtol'] == 1e-3 assert htarg['atol'] == 1e-4 assert htarg['nquad'] == 31 assert htarg['maxint'] == 20 assert htarg['pts_per_dec'] == 30 assert htarg['diff_quad'] == 200 assert htarg['a'] == 1e-6 assert htarg['b'] == 160 assert htarg['limit'] == 30 # Assert it can be called repetitively _, _ = capsys.readouterr() ht, htarg = utils.check_hankel('qwe', {}, 1) _, _ = utils.check_hankel(ht, htarg, 1) out, _ = capsys.readouterr() assert out == "" # # QUAD # # # verbose ht, htarg = utils.check_hankel('quad', {}, 4) out, _ = capsys.readouterr() outstr = " Hankel : Quadrature\n > rtol" assert outstr in out assert ht == 'quad' assert htarg['rtol'] == 1e-12 assert htarg['atol'] == 1e-20 assert htarg['limit'] == 500 assert htarg['a'] == 1e-6 assert htarg['b'] == 0.1 assert htarg['pts_per_dec'] == 40 # pts_per_dec _, htarg = utils.check_hankel('quad', {'pts_per_dec': 100}, 0) assert htarg['rtol'] == 1e-12 assert htarg['atol'] == 1e-20 assert htarg['limit'] == 500 assert htarg['a'] == 1e-6 assert htarg['b'] == 0.1 assert htarg['pts_per_dec'] == 100 # all arguments _, htarg = utils.check_hankel( 'quad', { 'rtol': 1e-3, 'atol': 1e-4, 'limit': 100, 'a': 1e-10, 'b': 200, 'pts_per_dec': 50 }, 0) assert htarg['rtol'] == 1e-3 assert htarg['atol'] == 1e-4 assert htarg['limit'] == 100 assert htarg['a'] == 1e-10 assert htarg['b'] == 200 assert htarg['pts_per_dec'] == 50 # Assert it can be called repetitively _, _ = capsys.readouterr() ht, htarg = utils.check_hankel('quad', {}, 1) _, _ = utils.check_hankel(ht, htarg, 1) out, _ = capsys.readouterr() assert out == "" # wrong ht with pytest.raises(ValueError): utils.check_hankel('doesnotexist', {}, 1) # filter missing attributes with pytest.raises(AttributeError): utils.check_hankel('dlf', {'dlf': 'key_101_CosSin_2012'}, 1)
def test_check_hankel(capsys): # # FHT # # # verbose ht, htarg = utils.check_hankel('fht', None, 4) out, _ = capsys.readouterr() assert " Hankel : DLF (Fast Hankel Transform)\n > F" in out assert " > DLF type : Standard" in out assert ht == 'fht' assert htarg[0].name == filters.key_201_2009().name assert htarg[1] is 0 # [filter str] _, htarg = utils.check_hankel('fht', 'key_201_2009', 0) assert htarg[0].name == filters.key_201_2009().name assert htarg[1] is 0 # [filter inst] _, htarg = utils.check_hankel('fht', filters.kong_61_2007(), 0) assert htarg[0].name == filters.kong_61_2007().name assert htarg[1] is 0 # ['', pts_per_dec] :: list _, htarg = utils.check_hankel('fht', ['', 20], 0) assert htarg[0].name == filters.key_201_2009().name assert htarg[1] == 20 # ['', pts_per_dec] :: dict _, htarg = utils.check_hankel('fht', {'pts_per_dec': -1}, 4) out, _ = capsys.readouterr() assert " > DLF type : Lagged Convolution" in out assert htarg[0].name == filters.key_201_2009().name assert htarg[1] == -1 # [filter str, pts_per_dec] _, htarg = utils.check_hankel('fht', ['key_201_2009', 20], 4) out, _ = capsys.readouterr() assert " > DLF type : Splined, 20 pts/dec" in out assert htarg[0].name == filters.key_201_2009().name assert htarg[1] == 20 # # QWE # # # verbose ht, htarg = utils.check_hankel('qwe', None, 4) out, _ = capsys.readouterr() outstr = " Hankel : Quadrature-with-Extrapolation\n > rtol" assert outstr in out assert ht == 'hqwe' assert_allclose(htarg[:-3], [1e-12, 1e-30, 51, 100, 0, 100]) assert htarg[-3] is None assert htarg[-2] is None assert htarg[-1] is None # only last argument _, htarg = utils.check_hankel('qwe', ['', '', '', '', '', '', '', '', 30], 0) assert_allclose(htarg[:-3], [1e-12, 1e-30, 51, 100, 0, 100]) assert htarg[-3] is None assert htarg[-2] is None assert htarg[-1] == 30 # all arguments _, htarg = utils.check_hankel('qwe', [1e-3, 1e-4, 31, 20, 30, 200, 1e-6, 160, 30], 3) out, _ = capsys.readouterr() assert " > a (quad): 1e-06" in out assert " > b (quad): 160" in out assert " > limit (quad): 30" in out assert_allclose(htarg, [1e-3, 1e-4, 31, 20, 30, 200, 1e-6, 160, 30]) # # QUAD # # # verbose ht, htarg = utils.check_hankel('quad', None, 4) out, _ = capsys.readouterr() outstr = " Hankel : Quadrature\n > rtol" assert outstr in out assert ht == 'hquad' assert_allclose(htarg, [1e-12, 1e-20, 500, 1e-6, 0.1, 40]) # only last argument _, htarg = utils.check_hankel('quad', ['', '', '', '', '', 100], 0) assert_allclose(htarg, [1e-12, 1e-20, 500, 1e-6, 0.1, 100]) # all arguments _, htarg = utils.check_hankel('quad', [1e-3, 1e-4, 100, 1e-10, 200, 50], 0) assert_allclose(htarg, [1e-3, 1e-4, 100, 1e-10, 200, 50]) # wrong ht with pytest.raises(ValueError): utils.check_hankel('doesnotexist', None, 1)
def setup_cache(self): """setup_cache is not parametrized, so we do it manually. """ data = {} for size in self.params[0]: # size tdat = {} # One big, one small model if size == 'Small': freqtime = np.array([2.]) else: freqtime = np.logspace(-1, 1, 11) # Define survey lsrc = 1 lrec = 1 angle = np.array([0]) off = np.array([5000]) 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 verb = 0 loop_freq = True loop_off = False signal = 0 # Get Hankel arguments if VERSION2: ht, htarg = utils.check_hankel( 'dlf', {'pts_per_dec': -1}, verb) else: # `pts_per_dec` changed at 9bed72b0 (29/04/2018; bef. v1.4.1) try: ht, htarg = utils.check_hankel('fht', ['', -1], verb) except VariableCatch: # `check_hankel`-signature changed at c73d6647 try: ht, htarg = utils.check_hankel('fht', None, verb) except VariableCatch: ht, htarg = utils.check_hankel('fht', None, ab, verb) # Get frequency-domain stuff for time-domain computation def get_args(freqtime, ft, ftarg): time, freq, ft, ftarg = utils.check_time( freqtime, signal, ft, ftarg, verb) # 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) # `model.fem`-signature changed on 9bed72b0 # (29/04/2018; bef. v1.4.1) inp = (ab, off, angle, zsrc, zrec, lsrc, lrec, depth, freq, etaH, etaV, zetaH, zetaV, False, False, ht, htarg, msrc, mrec, loop_freq, loop_off) try: if not VERSION2: inp = (*inp[:17], use_ne_eval, *inp[17:]) out = model.fem(*inp) except VariableCatch: out = model.fem(*inp[:17], True, *inp[17:]) # `model.fem` returned in the beginning only fEM; # then (fEM, kcount) and finally (fEM, kcount, conv). if isinstance(out, tuple): fEM = np.squeeze(out[0]) else: fEM = np.squeeze(out) return (fEM, time, freq, ftarg) # Define function name of transform fft_and_ffht = True if VERSION2: name_dlf = 'fourier_dlf' name_fqwe = 'fourier_qwe' name_fftlog = 'fourier_fftlog' name_fft = 'fourier_fft' else: name_fqwe = 'fqwe' name_fftlog = 'fftlog' name_fft = 'fft' # ffht used to be fft until the introduction of fft try: getattr(transform, 'ffht') name_ffht = 'ffht' except VariableCatch: fft_and_ffht = False name_ffht = 'fft' name_dlf = name_ffht # Store functions tdat['fourier_dlf'] = getattr(transform, name_dlf) tdat['fourier_qwe'] = getattr(transform, name_fqwe) tdat['fourier_fftlog'] = getattr(transform, name_fftlog) tdat['fourier_fft'] = getattr(transform, name_fft) # Check default pts_per_dec to see if new or old case if VERSION2: old_case = False else: try: test = utils.check_time(freqtime, signal, 'sin', ['key_201_CosSin_2012', 'test'], 0) old_case = test[3][1] is None except VariableCatch: old_case = True # Get fourier_dlf arguments if old_case and not VERSION2: tdat['dlf_st'] = () # Standard was not possible in old case tdat['dlf_la'] = get_args(freqtime, name_ffht, None) elif VERSION2: tdat['dlf_st'] = get_args( freqtime, 'dlf', {'dlf': 'key_201_CosSin_2012', 'pts_per_dec': 0}) tdat['dlf_la'] = get_args( freqtime, 'dlf', {'dlf': 'key_201_CosSin_2012', 'pts_per_dec': -1}) else: tdat['dlf_st'] = get_args( freqtime, name_ffht, ['key_201_CosSin_2012', 0]) tdat['dlf_la'] = get_args( freqtime, name_ffht, ['key_201_CosSin_2012', -1]) if VERSION2: tdat['dlf_sp'] = get_args( freqtime, 'dlf', {'dlf': 'key_201_CosSin_2012', 'pts_per_dec': 10}) # Get fourier_qwe arguments tdat['qwe'] = get_args(freqtime, 'qwe', {'pts_per_dec': 10}) # Get fourier_fftlog arguments tdat['fftlog'] = get_args(freqtime, 'fftlog', {}) # Get fourier_fft arguments tdat['fft'] = get_args(freqtime, 'fft', {}) else: tdat['dlf_sp'] = get_args( freqtime, name_ffht, ['key_201_CosSin_2012', 10]) # Get fourier_qwe arguments tdat['qwe'] = get_args(freqtime, 'fqwe', ['', '', '', '', 10]) # Get fourier_fftlog arguments tdat['fftlog'] = get_args(freqtime, 'fftlog', None) # Get fourier_fft arguments if fft_and_ffht: tdat['fft'] = get_args(freqtime, 'fft', None) else: tdat['fft'] = () # Will fail data[size] = tdat return data
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)
True, 0) depth, res, aniso, epermH, epermV, mpermH, mpermV, isfullspace = model frequency = utils.check_frequency(freq, res, aniso, epermH, epermV, mpermH, mpermV, 0) freq, etaH, etaV, zetaH, zetaV = frequency # src and rec rec = [np.arange(1, 11)*500, np.arange(1, 11)*100, 300] src = [[0, -100], [0, -200], 200] src, nsrc = utils.check_dipole(src, 'src', 0) 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) ht, htarg = utils.check_hankel('dlf', {}, 0) # 1. FULLSPACE inp1 = {'ab': 12, 'off': off, 'angle': angle, 'zsrc': zsrc, 'zrec': zrec, 'lsrc': lsrc, 'lrec': lrec, 'depth': depth, 'freq': freq, 'etaH': np.ones((3, 3))*etaH[:, 0], 'etaV': np.ones((3, 3))*etaV[:, 0], 'zetaH': np.ones((3, 3))*zetaH[:, 0], 'zetaV': np.ones((3, 3))*zetaV[:, 0],
def test_hankel(htype): # 1. DLF / 2. QWE / 3. QUAD # Compare wavenumber-domain calculation / DLF with analytical # frequency-domain fullspace solution calc = getattr(transform, 'hankel_' + htype) model = utils.check_model([], 10, 2, 2, 5, 1, 10, True, 0) depth, res, aniso, epermH, epermV, mpermH, mpermV, _ = model frequency = utils.check_frequency(1, res, aniso, epermH, epermV, mpermH, mpermV, 0) _, etaH, etaV, zetaH, zetaV = frequency src = [0, 0, 0] src, nsrc = utils.check_dipole(src, 'src', 0) for ab_inp in [11, 12, 13, 33]: ab, msrc, mrec = utils.check_ab(ab_inp, 0) _, htarg = utils.check_hankel(htype, {}, 0) xdirect = False # Important, as we want to compare wavenr-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) ang_fact = kernel.angle_factor(angle, ab, msrc, mrec) lsrc, zsrc = utils.get_layer_nr(src, depth) lrec, zrec = utils.get_layer_nr(rec, depth) # # # 0. No Spline # # # if htype != 'quad': # quad is always using spline # Wavenumber solution plus transform # Adjust htarg for dlf if htype == 'dlf': lambd, int_pts = transform.get_dlf_points( htarg['dlf'], off, htarg['pts_per_dec']) htarg['lambd'] = lambd htarg['int_pts'] = int_pts wvnr0, _, conv = calc(zsrc, zrec, lsrc, lrec, off, ang_fact, depth, ab, etaH, etaV, zetaH, zetaV, xdirect, htarg, 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 = utils.check_hankel(htype, {'pts_per_dec': 80}, 0) if htype == 'quad': # Lower atol to ensure convergence _, htarg = utils.check_hankel('quad', {'rtol': 1e-8}, 0) elif htype == 'dlf': # Adjust htarg for dlf lambd, int_pts = transform.get_dlf_points(htarg['dlf'], off, htarg['pts_per_dec']) htarg['lambd'] = lambd htarg['int_pts'] = int_pts # Wavenumber solution plus transform wvnr1, _, conv = calc(zsrc, zrec, lsrc, lrec, off, ang_fact, depth, ab, etaH, etaV, zetaH, zetaV, xdirect, htarg, msrc, mrec) # Analytical frequency-domain solution freq1 = kernel.fullspace(off, angle, zsrc, zrec, etaH, etaV, zetaH, zetaV, ab, msrc, mrec) # Compare if htype == 'qwe' and ab in [13, 33]: assert_allclose(conv, False) else: 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) ang_fact = kernel.angle_factor(angle, ab, msrc, mrec) if htype == 'qwe': # Put a very low diff_quad, to test it.; lower err _, htarg = utils.check_hankel( 'qwe', { 'rtol': 1e-8, 'maxint': 200, 'pts_per_dec': 80, 'diff_quad': .1, 'a': 1e-6, 'b': .1, 'limit': 1000 }, 0) elif htype == 'dlf': # Adjust htarg for dlf lambd, int_pts = transform.get_dlf_points(htarg['dlf'], off, htarg['pts_per_dec']) htarg['lambd'] = lambd htarg['int_pts'] = int_pts # Analytical frequency-domain solution wvnr2, _, conv = calc(zsrc, zrec, lsrc, lrec, off, ang_fact, depth, ab, etaH, etaV, zetaH, zetaV, xdirect, htarg, 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 == 'dlf': _, htarg = utils.check_hankel('dlf', { 'dlf': 'key_201_2012', 'pts_per_dec': 20 }, 0) lambd, int_pts = transform.get_dlf_points(htarg['dlf'], off, htarg['pts_per_dec']) htarg['lambd'] = lambd htarg['int_pts'] = int_pts elif htype == 'qwe': _, htarg = utils.check_hankel('qwe', { 'maxint': 80, 'pts_per_dec': 100 }, 0) if htype != 'quad': # quad is always pts_per_dec # Analytical frequency-domain solution wvnr3, _, conv = calc(zsrc, zrec, lsrc, lrec, off, ang_fact, depth, ab, etaH, etaV, zetaH, zetaV, xdirect, htarg, 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) ang_fact = kernel.angle_factor(angle, ab, msrc, mrec) if htype == 'qwe': _, htarg = utils.check_hankel('qwe', { 'maxint': 200, 'pts_per_dec': 80 }, 0) elif htype == 'quad': _, htarg = utils.check_hankel('quad', {}, 0) elif htype == 'dlf': lambd, int_pts = transform.get_dlf_points(htarg['dlf'], off, htarg['pts_per_dec']) htarg['lambd'] = lambd htarg['int_pts'] = int_pts # Analytical frequency-domain solution wvnr4, _, conv = calc(zsrc, zrec, lsrc, lrec, off, ang_fact, depth, ab, etaH, etaV, zetaH, zetaV, xdirect, htarg, 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 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, _ = model frequency = utils.check_frequency(1, res, aniso, epermH, epermV, mpermH, mpermV, 0) _, etaH, etaV, zetaH, zetaV = frequency src = [0, 0, 0] src, nsrc = utils.check_dipole(src, 'src', 0) for ab_inp in [11, 12, 13, 33]: ab, msrc, mrec = utils.check_ab(ab_inp, 0) _, htarg = utils.check_hankel(htype, None, 0) xdirect = False # Important, as we want to compare wavenr-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) factAng = kernel.angle_factor(angle, ab, msrc, mrec) 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 # Adjust htarg for fht if htype == 'fht': lambd, int_pts = transform.get_spline_values(htarg[0], off, htarg[1]) htarg = (htarg[0], htarg[1], lambd, int_pts) wvnr0, _, conv = calc(zsrc, zrec, lsrc, lrec, off, factAng, 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, _ = utils.spline_backwards_hankel(htype, None, 'spline') _, htarg = utils.check_hankel(htype, htarg, 0) if htype == 'hquad': # Lower atol to ensure convergence _, htarg = utils.check_hankel('quad', [1e-8], 0) elif htype == 'fht': # Adjust htarg for fht lambd, int_pts = transform.get_spline_values(htarg[0], off, htarg[1]) htarg = (htarg[0], htarg[1], lambd, int_pts) # Wavenumber solution plus transform wvnr1, _, conv = calc(zsrc, zrec, lsrc, lrec, off, factAng, 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 if htype == 'hqwe' and ab in [13, 33]: assert_allclose(conv, False) else: 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) factAng = kernel.angle_factor(angle, ab, msrc, mrec) if htype == 'hqwe': # Put a very low diff_quad, to test it.; lower err _, htarg = utils.check_hankel('qwe', [1e-8, '', '', 200, 80, .1, 1e-6, .1, 1000], 0) elif htype == 'fht': # Adjust htarg for fht lambd, int_pts = transform.get_spline_values(htarg[0], off, htarg[1]) htarg = (htarg[0], htarg[1], lambd, int_pts) # Analytical frequency-domain solution wvnr2, _, conv = calc(zsrc, zrec, lsrc, lrec, off, factAng, 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': _, htarg = utils.check_hankel('fht', ['key_201_2012', 20], 0) lambd, int_pts = transform.get_spline_values(htarg[0], off, htarg[1]) htarg = (htarg[0], htarg[1], lambd, int_pts) elif htype == 'hqwe': _, 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, factAng, 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) factAng = kernel.angle_factor(angle, ab, msrc, mrec) if htype == 'hqwe': _, htarg = utils.check_hankel('qwe', ['', '', '', 200, 80], 0) elif htype == 'hquad': _, htarg = utils.check_hankel('quad', None, 0) elif htype == 'fht': lambd, int_pts = transform.get_spline_values(htarg[0], off, htarg[1]) htarg = (htarg[0], htarg[1], lambd, int_pts) # Analytical frequency-domain solution wvnr4, _, conv = calc(zsrc, zrec, lsrc, lrec, off, factAng, 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)
SS = np.sin(Bx) * np.tile(g_w, maxint) tEM_iint = iuSpline(np.log(2 * np.pi * freq), fEM.imag) sEM = tEM_iint(np.log(Bx / t[:, None])) * SS fqwe0['sEM'] = sEM fqwe0['intervals'] = intervals # # G -- QWE - HQWE # # # Model 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, nsrc = utils.check_dipole([0, 0, 0], 'src', 0) ab, msrc, mrec = utils.check_ab(11, 0) ht, htarg = utils.check_hankel('qwe', None, 0) 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) # Frequency-domain result freqres = kernel.fullspace(off, angle, zsrc, zrec, etaH, etaV, zetaH, zetaV, ab, msrc, mrec) # The following is a condensed version of transform.hqwe etaH = etaH[0, :] etaV = etaV[0, :] zetaH = zetaH[0, :] zetaV = zetaV[0, :] rtol, atol, nquad, maxint, pts_per_dec, diff_quad, a, b, limit = htarg g_x, g_w = special.p_roots(nquad)
def setup_cache(self): """setup_cache is not parametrized, so we do it manually. """ data = {} for size in self.params[0]: # size data[size] = {} # One big, one small model if size == 'Small': # Small; Total size: 5*1*1*1 = 5 x = np.array([500., 1000.]) else: # Big; Total size: 5*100*100*201 = 10'050'000 x = np.arange(1, 101)*200. # Define model parameters freq = np.array([1]) src = [0, 0, 250] rec = [x, np.zeros(x.shape), 300] depth = np.array([-np.infty, 0, 300, 2000, 2100]) res = np.array([2e14, .3, 1, 50, 1]) ab = 11 xdirect = False verb = 0 if not VERSION2: use_ne_eval = False # Checks (since DLF exists the `utils`-checks haven't changed, so # we just use them here. model = utils.check_model(depth, res, None, None, None, None, None, xdirect, verb) depth, res, aniso, epermH, epermV, mpermH, mpermV, _ = model frequency = utils.check_frequency(freq, res, aniso, epermH, epermV, mpermH, mpermV, verb) freq, etaH, etaV, zetaH, zetaV = frequency ab, msrc, mrec = utils.check_ab(ab, verb) src, nsrc = utils.check_dipole(src, 'src', verb) rec, nrec = utils.check_dipole(rec, 'rec', verb) off, angle = utils.get_off_ang(src, rec, nsrc, nrec, verb) lsrc, zsrc = utils.get_layer_nr(src, depth) lrec, zrec = utils.get_layer_nr(rec, depth) for htype in self.params[1]: # htype # pts_per_dec depending on htype if htype == 'Standard': pts_per_dec = 0 elif htype == 'Lagged': pts_per_dec = -1 else: pts_per_dec = 10 # Compute kernels for dlf if VERSION2: # HT arguments _, fhtarg = utils.check_hankel( 'dlf', {'dlf': 'key_201_2009', 'pts_per_dec': pts_per_dec}, 0) inp = (fhtarg['dlf'], off, fhtarg['pts_per_dec']) lambd, _ = transform.get_dlf_points(*inp) else: # HT arguments _, fhtarg = utils.check_hankel( 'fht', ['key_201_2009', pts_per_dec], 0) inp = (fhtarg[0], off, fhtarg[1]) lambd, _ = transform.get_spline_values(*inp) if VERSION2: inp = (zsrc, zrec, lsrc, lrec, depth, etaH, etaV, zetaH, zetaV, lambd, ab, xdirect, msrc, mrec) else: inp = (zsrc, zrec, lsrc, lrec, depth, etaH, etaV, zetaH, zetaV, lambd, ab, xdirect, msrc, mrec, use_ne_eval) PJ = kernel.wavenumber(*inp) factAng = kernel.angle_factor(angle, ab, msrc, mrec) # Signature changed at commit a15af07 (20/05/2018; before # v1.6.2) try: dlf = {'signal': PJ, 'points': lambd, 'out_pts': off, 'ab': ab} if VERSION2: dlf['ang_fact'] = factAng dlf['filt'] = fhtarg['dlf'] dlf['pts_per_dec'] = fhtarg['pts_per_dec'] else: dlf['factAng'] = factAng dlf['filt'] = fhtarg[0] dlf['pts_per_dec'] = fhtarg[1] transform.dlf(**dlf) except VariableCatch: dlf = {'signal': PJ, 'points': lambd, 'out_pts': off, 'targ': fhtarg, 'factAng': factAng} data[size][htype] = dlf return data