def test_hankel(self, capsys): # Compare Hankel transforms inp = { 'depth': [-20, 100], 'res': [1e20, 5, 100], 'freqtime': [1.34, 23, 31], 'src': [0, 0, 0, 0, 90], 'rec': [[200, 300, 400], [3000, 4000, 5000], 120, 90, 0] } fht = bipole(ht='fht', verb=3, **inp) out, _ = capsys.readouterr() assert "Hankel : Fast Hankel Transform" in out qwe = bipole(ht='qwe', verb=3, **inp) out, _ = capsys.readouterr() assert "Hankel : Quadrature-with-Extrapolation" in out assert_allclose(fht, qwe, equal_nan=True) quad = bipole(ht='quad', htarg=['', '', '', '', 1, 1000], verb=3, **inp) out, _ = capsys.readouterr() assert "Hankel : Quadrature" in out assert_allclose(fht, quad, equal_nan=True)
def test_optimization(self, capsys): # Compare optimization options: None, parallel, spline inp = { 'depth': [0, 500], 'res': [10, 3, 50], 'freqtime': [1, 2, 3], 'rec': [[6000, 7000, 8000], [200, 200, 200], 300, 0, 0], 'src': [0, 0, 0, 0, 0] } non = bipole(opt=None, verb=3, **inp) out, _ = capsys.readouterr() assert "Kernel Opt. : None" in out par = bipole(opt='parallel', verb=3, **inp) out, _ = capsys.readouterr() if use_ne_eval and use_vml: assert "Kernel Opt. : Use parallel" in out else: assert "Kernel Opt. : None" in out assert_allclose(non, par, equal_nan=True) spl = bipole(opt='spline', verb=3, **inp) out, _ = capsys.readouterr() assert "> DLF type : Lagged Convolution" in out assert_allclose(non, spl, 1e-3, 1e-22, True)
def test_fourier(self, capsys): # Compare Fourier transforms inp = {'depth': [0, 300], 'res': [1e12, 1/3, 5], 'freqtime': np.logspace(-1.5, 1, 20), 'signal': 0, 'rec': [2000, 300, 280, 0, 0], 'src': [0, 0, 250, 0, 0]} ftl = bipole(ft='fftlog', verb=3, **inp) out, _ = capsys.readouterr() assert "Fourier : FFTLog" in out qwe = bipole(ft='qwe', ftarg={'pts_per_dec': 30}, verb=3, **inp) out, _ = capsys.readouterr() assert "Fourier : Quadrature-with-Extrapolation" in out assert_allclose(qwe, ftl, 1e-2, equal_nan=True) dlf = bipole(ft='dlf', verb=3, **inp) out, _ = capsys.readouterr() assert "Fourier : DLF (Sine-Filter)" in out assert_allclose(dlf, ftl, 1e-2, equal_nan=True) # FFT: We keep the error-check very low, otherwise we would have to # calculate too many frequencies. fft = bipole( ft='fft', ftarg={'dfreq': 0.002, 'nfreq': 2**13, 'ntot': 2**16}, verb=3, **inp) out, _ = capsys.readouterr() assert "Fourier : Fast Fourier Transform FFT" in out assert_allclose(fft, ftl, 1e-1, 1e-13, equal_nan=True)
def calc_cl_time(time, filter_name='key201'): # emulatte emsrc = fwd.transmitter(emsrc_name, time, current=1, radius=radius, turns=1) model.locate(emsrc, sc, rc) tEMF, time_thz = model.emulate(hankel_filter=filter_name, td_transform='DLAG', time_diff=False, ignore_displacement_current=True) thz_emu = tEMF['h_z'].real tEMF_dt, time_thzdt = model.emulate(hankel_filter=filter_name, td_transform='DLAG', time_diff=True, ignore_displacement_current=True) thzdt_emu = tEMF_dt['h_z'].real # empymod eperm = [0, 0] # Reduce early time numerical noise (diffusive approx for air) thz_emp = empymod.bipole(signal=-1, freqtime=time_thz, epermH=eperm, **inp) # スイッチオン応答(微分なし) thzdt_emp = empymod.bipole(signal=0, freqtime=time_thzdt, epermH=eperm, **inp) # インパルス応答 (微分あり) # 解析解 thz_ana = cl.td_hz(time_thz) thzdt_ana = cl.td_dhzdt(time_thzdt) return [thz_emu, thz_emp, thz_ana], time_thz, [thzdt_emu, thzdt_emp, thzdt_ana], time_thzdt
def test_combinations2(self): # Additional to test_combinations: different src- and rec- # bipoles at the same time inp = {'depth': [0.75, 500], 'res': [20, 5, 11], 'freqtime': [1.05, 3.76], 'verb': 0} # Source bipoles and equivalent dipoles srcbip = [[-1, -1], [1, 1], [0, -1], [0, 1], [100, 200], [100, 200]] srcdip1 = [0, 0, 100, 0, 0] srcdip2 = [0, 0, 200, 45, 0] # Receiver bipoles and equivalent dipoles recbip = [[7999, 7999], [8001, 8001], [0, 0], [0, 0], [200, 300], [200, 300]] recdip1 = [8000, 0, 200, 0, 0] recdip2 = [8000, 0, 300, 0, 0] # 1. calculate all bipoles at once bip = bipole(srcbip, recbip, **inp) # 2. calculate each dipole separate dip1 = bipole(srcdip1, recdip1, **inp) dip2 = bipole(srcdip1, recdip2, **inp) dip3 = bipole(srcdip2, recdip1, **inp) dip4 = bipole(srcdip2, recdip2, **inp) # 3. compare assert_allclose(bip[:, 0, 0], dip1) assert_allclose(bip[:, 1, 0], dip2) assert_allclose(bip[:, 0, 1], dip3) assert_allclose(bip[:, 1, 1], dip4)
def test_dipole(): # As this is a subset of bipole, just run two tests to ensure # it is equivalent to bipole. # 1. Frequency src = [5000, 1000, -200] rec = [0, 0, 1200] model = {'depth': [100, 1000], 'res': [2, 0.3, 100], 'aniso': [2, .5, 2]} f = 0.01 # v dipole : ab = 26 # \> bipole : src-dip = 90, rec-azimuth=90, msrc=True dip_res = dipole(src, rec, freqtime=f, ab=26, verb=0, **model) bip_res = bipole([src[0], src[1], src[2], 0, 90], [rec[0], rec[1], rec[2], 90, 0], msrc=True, freqtime=f, verb=0, **model) assert_allclose(dip_res, bip_res) # 2. Time t = 1 dip_res = dipole(src, rec, freqtime=t, signal=1, ab=62, verb=0, **model) bip_res = bipole([src[0], src[1], src[2], 0, 90], [rec[0], rec[1], rec[2], 90, 0], msrc=True, freqtime=t, signal=1, verb=0, **model) assert_allclose(dip_res, bip_res)
def test_dipole(): # As this is a subset of bipole, just run two tests to ensure # it is equivalent to bipole. # 1. Frequency src = [5000, 1000, -200] rec = [0, 0, 1200] model = {'depth': [100, 1000], 'res': [2, 0.3, 100], 'aniso': [2, .5, 2]} f = 0.01 # v dipole : ab = 26 # \> bipole : src-dip = 90, rec-azimuth=90, msrc=True dip_res = dipole(src, rec, freqtime=f, ab=26, verb=0, **model) bip_res = bipole([src[0], src[1], src[2], 0, 90], [rec[0], rec[1], rec[2], 90, 0], msrc=True, freqtime=f, verb=0, **model) assert_allclose(dip_res, bip_res) # 2. Time t = 1 dip_res = dipole(src, rec, freqtime=t, signal=1, ab=62, verb=0, **model) bip_res = bipole([src[0], src[1], src[2], 0, 90], [rec[0], rec[1], rec[2], 90, 0], msrc=True, freqtime=t, signal=1, verb=0, **model) assert_allclose(dip_res, bip_res) # 3. Check user-hook for eta/zeta def func_eta(inp, pdict): # Dummy function to check if it works. etaH = pdict['etaH'].real*inp['fact'] + 1j*pdict['etaH'].imag etaV = pdict['etaV'].real*inp['fact'] + 1j*pdict['etaV'].imag return etaH, etaV def func_zeta(inp, pdict): # Dummy function to check if it works. etaH = pdict['zetaH']/inp['fact'] etaV = pdict['zetaV']/inp['fact'] return etaH, etaV model = {'src': [0, 0, 500], 'rec': [500, 0, 600], 'depth': [0, 550], 'freqtime': [0.1, 1, 10]} res = np.array([2, 10, 5]) fact = np.array([2, 2, 2]) eta = {'res': fact*res, 'fact': fact, 'func_eta': func_eta} zeta = {'res': res, 'fact': fact, 'func_zeta': func_zeta} # Frequency domain standard = dipole(res=res, **model) outeta = dipole(res=eta, **model) assert_allclose(standard, outeta) outzeta = dipole(res=zeta, mpermH=fact, mpermV=fact, **model) assert_allclose(standard, outzeta) # Time domain standard = dipole(res=res, signal=0, **model) outeta = dipole(res=eta, signal=0, **model) assert_allclose(standard, outeta) outzeta = dipole(res=zeta, signal=0, mpermH=fact, mpermV=fact, **model) assert_allclose(standard, outzeta)
def test_halfspace(): # 7. halfspace # Compare all to maintain status quo. hs = DATAEMPYMOD['hs'][()] hsres = DATAEMPYMOD['hsres'][()] hsbp = DATAEMPYMOD['hsbp'][()] for key in hs: # Get halfspace hs_res = kernel.halfspace(**hs[key]) # Check # rtol decreased in June '22 - suddenly failed; why? # # (Potentially as SciPy changed mu_0 to inexact, # https://github.com/scipy/scipy/issues/11341). assert_allclose(hs_res, hsres[key], rtol=5e-5) # Additional checks - Time full = kernel.halfspace(**hs['21']) # Check halfspace = sum of split hs['21']['solution'] = 'dsplit' direct, reflect, air = kernel.halfspace(**hs['21']) assert_allclose(full, direct + reflect + air) # Check fullspace = bipole-solution hsbp['21']['xdirect'] = True hsbp['21']['depth'] = [] hsbp['21']['res'] = hsbp['21']['res'][1] hsbp['21']['aniso'] = hsbp['21']['aniso'][1] hsbp['21']['ft'] = 'dlf' hs_res = bipole(**hsbp['21']) assert_allclose(direct, hs_res, rtol=1e-2) # Additional checks - Frequency hs['11']['solution'] = 'dfs' full = kernel.halfspace(**hs['11']) # Check halfspace = sum of split hs['11']['solution'] = 'dsplit' direct, _, _ = kernel.halfspace(**hs['11']) assert_allclose(full, direct) # Check sums of dtetm = dsplit hs['11']['solution'] = 'dsplit' direct, reflect, air = kernel.halfspace(**hs['11']) hs['11']['solution'] = 'dtetm' dTE, dTM, rTE, rTM, air2 = kernel.halfspace(**hs['11']) assert_allclose(direct, dTE + dTM) assert_allclose(reflect, rTE + rTM) assert_allclose(air, air2) # Check fullspace = bipole-solution hsbp['11']['xdirect'] = True hsbp['11']['depth'] = [] hsbp['11']['res'] = hsbp['11']['res'][1] hsbp['11']['aniso'] = hsbp['11']['aniso'][1] hs_res = bipole(**hsbp['11']) assert_allclose(direct, hs_res, atol=1e-2)
def test_halfspace(): # 7. halfspace # Compare all to maintain status quo. hs = DATAEMPYMOD['hs'][()] hsres = DATAEMPYMOD['hsres'][()] hsbp = DATAEMPYMOD['hsbp'][()] for key in hs: # Get halfspace hs_res = kernel.halfspace(**hs[key]) # Check assert_allclose(hs_res, hsres[key]) # Additional checks - Time full = kernel.halfspace(**hs['21']) # Check halfspace = sum of split hs['21']['solution'] = 'dsplit' direct, reflect, air = kernel.halfspace(**hs['21']) assert_allclose(full, direct + reflect + air) # Check fullspace = bipole-solution hsbp['21']['xdirect'] = True hsbp['21']['depth'] = [] hsbp['21']['res'] = hsbp['21']['res'][1] hsbp['21']['aniso'] = hsbp['21']['aniso'][1] hsbp['21']['ft'] = 'sin' hs_res = bipole(**hsbp['21']) assert_allclose(direct, hs_res, rtol=1e-2) # Additional checks - Frequency hs['11']['solution'] = 'dfs' full = kernel.halfspace(**hs['11']) # Check halfspace = sum of split hs['11']['solution'] = 'dsplit' direct, _, _ = kernel.halfspace(**hs['11']) assert_allclose(full, direct) # Check sums of dtetm = dsplit hs['11']['solution'] = 'dsplit' direct, reflect, air = kernel.halfspace(**hs['11']) hs['11']['solution'] = 'dtetm' dTE, dTM, rTE, rTM, air2 = kernel.halfspace(**hs['11']) assert_allclose(direct, dTE + dTM) assert_allclose(reflect, rTE + rTM) assert_allclose(air, air2) # Check fullspace = bipole-solution hsbp['11']['xdirect'] = True hsbp['11']['depth'] = [] hsbp['11']['res'] = hsbp['11']['res'][1] hsbp['11']['aniso'] = hsbp['11']['aniso'][1] hs_res = bipole(**hsbp['11']) assert_allclose(direct, hs_res, atol=1e-2)
def test_dipole_bipole(self): # Compare a dipole to a bipole # Checking intpts, strength, reciprocity inp = {'depth': [0, 250], 'res': [1e20, 0.3, 5], 'freqtime': 1} rec = [8000, 200, 300, 0, 0] bip1 = bipole([-25, 25, -25, 25, 100, 170.7107], rec, srcpts=1, strength=33, **inp) bip2 = bipole(rec, [-25, 25, -25, 25, 100, 170.7107], recpts=5, strength=33, **inp) dip = bipole([0, 0, 135.3553, 45, 45], [8000, 200, 300, 0, 0], **inp) # r = 100; sI = 33 => 3300 assert_allclose(bip1, dip*3300, 1e-5) # bipole as dipole assert_allclose(bip2, dip*3300, 1e-2) # bipole, src/rec switched.
def test_shape(self): inp = {'depth': [], 'res': 1.0, 'freqtime': (1.0, 2.0), 'verb': 1} a = bipole(src=[0, 10, 1, 0, 90], rec=[10, 10, 10, 11, 1], **inp) b = bipole(src=[-50, 0, 1, 10, 90], rec=[10, 10, 10, 11, 1], **inp) c = bipole(src=[0, 10, 1, 0, 90], rec=[20, 10, 10, 11, 0], **inp) d = bipole(src=[-50, 0, 1, 10, 90], rec=[20, 10, 10, 11, 0], **inp) # Several sources, several receivers out = bipole(src=[[0, -50], [10, 0], 1, [0, 10], 90], rec=[[10, 20], [10, 10], 10, 11, [1, 0]], **inp) assert_allclose(out[:, 0, 0], a) assert_allclose(out[:, 0, 1], b) assert_allclose(out[:, 1, 0], c) assert_allclose(out[:, 1, 1], d) # One source, one receiver out = bipole(src=[-50, 0, 1, 10, 90], rec=[10, 10, 10, 11, 1], **inp) assert_allclose(out, b) # Several sources, one receiver out = bipole(src=[[0, -50], [10, 0], 1, [0, 10], 90], rec=[10, 10, 10, 11, 1], **inp) assert_allclose(out[:, 0], a) assert_allclose(out[:, 1], b) # One sources, several receivers out = bipole(src=[-50, 0, 1, 10, 90], rec=[[10, 20], [10, 10], 10, 11, [1, 0]], **inp) assert_allclose(out[:, 0], b) assert_allclose(out[:, 1], d)
def test_src_rec_definitions(self): inp = {'depth': [0, -250], 'res': [1e20, 0.3, 5], 'freqtime': 1.23456} src1 = [[0, 0], [20, 0], [0, 0], [0, 20], -200, -200] src2 = [[10, 0], [0, 10], -200, [0, 90], [0, 0]] rec1 = [[1000, 0, 1000], [1200, 0, 1200], [0, 1000, 1000], [0, 1200, 1200], -250, -250] rec2 = [[1100, 0, 1100], [0, 1100, 1100], -250, [0, 90, 45], [0, 0, 0]] bip1 = bipole(src1, rec1, **inp) # [x1, x2, y1, y2, z1, z2] bip2 = bipole(src2, rec2, **inp) # [x, y, z, azimuth, dip] assert_allclose(bip1[:, :], bip2[:, :])
def test_bipole(self, capsys): # 1. Compare to bipole in the frequency domain, to ensure it is the # same. # Survey parameters. depth = [0, 200] res = [2e14, 100, 200] freq = np.logspace(-4, 4, 101) # 1.a: msrc-mrec; nrec==nrecz, nsrc!=nsrcz. rec = [100, 0, 0, 23, -50] src = [[0, 0, 0], [0, 0, 0], 0, 45, 33] loo = loop(src, rec, depth, res, freq) bip = bipole(src, rec, depth, res, freq, msrc=True, mrec=True) bip *= 2j*np.pi*freq[:, None]*4e-7*np.pi assert_allclose(bip, loo, rtol=1e-4, atol=1e-18) # 1.b: msrc-erec; nrec!=nrecz, nsrc!=nsrcz. rec = [[100, 200, 300], [-10, 0, 10], 0, 23, -50] src = [[0, 0, 0], [0, 0, 0], 0, 45, 33] loo = loop(src, rec, depth, res, freq, mrec=False, strength=np.pi) bip = bipole(src, rec, depth, res, freq, msrc=True, mrec=False, strength=np.pi)*2j*np.pi*freq[:, None, None]*4e-7*np.pi assert_allclose(bip, loo, rtol=1e-4, atol=1e-18) # 1.c: msrc-looprec; nrec==nrecz, nsrc!=nsrcz. rec = [[100, 100, 100], [0, 0, 0], [-10, 0, 10], 23, -50] src = [[0, 0, 0], [0, 0, 0], 0, 45, 33] loo = loop(src, rec, depth, res, freq, mrec='loop') bip = bipole(src, rec, depth, res, freq, msrc=True, mrec=True) bip *= (2j*np.pi*freq[:, None, None]*4e-7*np.pi)**2 assert_allclose(bip, loo, rtol=1e-4, atol=1e-18) # 1.d: msrc-loopre; nrec!=nrecz, nsrc==nsrcz. _, _ = capsys.readouterr() # Empty it rec = [[100, 100, 100], [0, 0, 0], 0, 23, -50] src = [[0, 0, 0], [0, 0, 0], [-10, 0, 10], 45, 33] mpermH = [1, 1, 1] mpermV = [1.5, 2, 1] loo = loop(src, rec, depth, res, freq, mrec='loop', mpermH=mpermH, mpermV=mpermV) out, _ = capsys.readouterr() bip = bipole(src, rec, depth, res, freq, msrc=True, mrec=True, mpermH=mpermH, mpermV=mpermV) bip *= (2j*np.pi*freq[:, None, None]*4e-7*np.pi)**2 assert_allclose(bip, loo, rtol=1e-4, atol=1e-18) assert '* WARNING :: `mpermH != mpermV` at source level, ' in out assert '* WARNING :: `mpermH != mpermV` at receiver level, ' in out
def test_status_quo(self): # Comparison to self, to ensure nothing changed. # 4 bipole-bipole cases in EE, ME, EM, MM, all different values for i in ['1', '2', '3', '4']: res = DATAEMPYMOD['out'+i][()] tEM = bipole(**res['inp']) assert_allclose(tEM, res['EM'], rtol=5e-5) # 5e-5 shouldn't be...
def test_emmod(self): # Comparison to EMmod (Hunziker et al., 2015) # Comparison f = [0.013, 1.25, 130] Hz.; 11 models, 34 ab's, f altern. dat = EMMOD['res'][()] for _, val in dat.items(): res = bipole(**val[0]) assert_allclose(res, val[1], 3e-2, 1e-17, True)
def test_hankel(self, capsys): # Compare Hankel transforms inp = { 'depth': [-20, 100], 'res': [1e20, 5, 100], 'freqtime': [1.34, 23, 31], 'src': [0, 0, 0, 0, 90], 'rec': [[200, 300, 400], [3000, 4000, 5000], 120, 90, 0] } dlf = bipole(ht='dlf', htarg={'pts_per_dec': 0}, verb=3, **inp) out, _ = capsys.readouterr() assert "Hankel : DLF (Fast Hankel Transform)" in out assert " > DLF type : Standard" in out assert "Loop over : None" in out dlf2 = bipole(ht='dlf', htarg={'pts_per_dec': -1}, verb=3, **inp) out, _ = capsys.readouterr() assert "Hankel : DLF (Fast Hankel Transform)" in out assert " > DLF type : Lagged Convolution" in out assert "Loop over : Frequencies" in out assert_allclose(dlf, dlf2, rtol=1e-4) dlf3 = bipole(ht='dlf', htarg={'pts_per_dec': 40}, verb=3, **inp) out, _ = capsys.readouterr() assert "Hankel : DLF (Fast Hankel Transform)" in out assert " > DLF type : Splined, 40.0 pts/dec" in out assert "Loop over : Frequencies" in out assert_allclose(dlf, dlf3, rtol=1e-3) qwe = bipole(ht='qwe', htarg={'pts_per_dec': 0}, verb=3, **inp) out, _ = capsys.readouterr() assert "Hankel : Quadrature-with-Extrapolation" in out assert_allclose(dlf, qwe, equal_nan=True) quad = bipole(ht='quad', htarg={ 'b': 1, 'pts_per_dec': 1000 }, verb=3, **inp) out, _ = capsys.readouterr() assert "Hankel : Quadrature" in out assert_allclose(dlf, quad, equal_nan=True)
def test_cole_cole(self): # Just compare to bipole. def func_eta(inp, pdict): # Dummy function to check if it works. etaH = pdict['etaH'].real * inp['fact'] + 1j * pdict['etaH'].imag etaV = pdict['etaV'].real * inp['fact'] + 1j * pdict['etaV'].imag return etaH, etaV def func_zeta(inp, pdict): # Dummy function to check if it works. etaH = pdict['zetaH'] / inp['fact'] etaV = pdict['zetaV'] / inp['fact'] return etaH, etaV freq = 1. model = { 'src': [0, 0, 500, 0, 0], 'rec': [500, 0, 600, 0, 0], 'depth': [0, 550], 'freqtime': freq } res = np.array([2, 10, 5]) fact = np.array([2, 2, 2]) eta = {'res': fact * res, 'fact': fact, 'func_eta': func_eta} zeta = {'res': res, 'fact': fact, 'func_zeta': func_zeta} # Frequency domain etabip = bipole(res=eta, msrc=True, mrec=True, **model) etabip *= 2j * np.pi * freq * 4e-7 * np.pi etaloo = loop(res=eta, **model) assert_allclose(etabip, etaloo) zetabip = bipole(res=zeta, mpermH=fact, mpermV=fact, msrc=True, mrec=True, **model) zetabip *= 2j * np.pi * freq * 4e-7 * np.pi zetaloo = loop(res=zeta, mpermH=fact, mpermV=fact, **model) assert_allclose(zetabip, zetaloo)
def test_loop(self, capsys): # Compare loop options: None, 'off', 'freq' inp = {'depth': [0, 500], 'res': [10, 3, 50], 'freqtime': [1, 2, 3], 'rec': [[6000, 7000, 8000], [200, 200, 200], 300, 0, 0], 'src': [0, 0, 0, 0, 0]} non = bipole(loop=None, verb=3, **inp) out, _ = capsys.readouterr() assert "Loop over : None (all vectorized)" in out lpo = bipole(loop='off', verb=3, **inp) out, _ = capsys.readouterr() assert "Loop over : Offsets" in out assert_allclose(non, lpo, equal_nan=True) lfr = bipole(loop='freq', verb=3, **inp) out, _ = capsys.readouterr() assert "Loop over : Frequencies" in out assert_allclose(non, lfr, equal_nan=True)
def comp_appres(depth, res, a, n, srcpts=1, recpts=1, verb=1): """Return apparent resistivity for dipole-dipole DC measurement rho_a = V/I pi a n (n+1) (n+2). Returns die apparent resistivity due to: - Electric source, inline (y = 0 m). - Source of 1 A strength. - Source and receiver are located at the air-interface. - Source is centered at x = 0 m. Note: DC response can be obtained by either t->infinity s or f->0 Hz. f = 0 Hz is much faster, as there is no Fourier transform involved and only a single frequency has to be computed. By default, the minimum frequency in empymod is 1e-20 Hz. The difference between the signals for 1e-20 Hz and 0 Hz is very small. For more explanation regarding input parameters see `empymod.model`. Parameters ---------- depth : Absolute depths of layer interfaces, without air-interface. res : Resistivities of the layers, one more than depths (lower HS). a : Dipole length. n : Separation factors. srcpts, recpts : If < 3, bipoles are approximated as dipoles. verb : Verbosity. Returns ------- rho_a : Apparent resistivity. AB2 : Src/rec-midpoints """ # Get offsets between src-midpoint and rec-midpoint, AB AB = (n + 1) * a # Collect model, putting source and receiver slightly (1e-3 m) into the # ground. model = { 'src': [-a / 2, a / 2, 0, 0, 1e-3, 1e-3], 'rec': [AB - a / 2, AB + a / 2, AB * 0, AB * 0, 1e-3, 1e-3], 'depth': np.r_[0, np.array(depth, ndmin=1)], 'freqtime': 1e-20, # Smaller f would be set to 1e-20 be empymod. 'verb': verb, # Setting it to 1e-20 avoids warning-message. 'res': np.r_[2e14, np.array(res, ndmin=1)], 'strength': 1, # So it is NOT normalized to 1 m src/rec. 'htarg': { 'pts_per_dec': -1 }, } return np.real( empymod.bipole(**model)) * np.pi * a * n * (n + 1) * (n + 2), AB / 2
def test_fullspace(self): # Comparison to analytical fullspace solution fs = DATAEMPYMOD['fs'][()] fsbp = DATAEMPYMOD['fsbp'][()] for key in fs: # Get fullspace fs_res = fullspace(**fs[key]) # Get bipole bip_res = bipole(**fsbp[key]) # Check assert_allclose(fs_res, bip_res)
def test_multisrc_multirec(self): # Check that a multi-source, multi-receiver results in the same as if # calculated on their own. # General model parameters model = { 'depth': [0, 1000], 'res': [2e14, 0.3, 1], 'freqtime': 1, 'verb': 0 } # Multi-src (0) and single sources (1), (2) src0 = [[0, 100], [50, 200], [0, 10], [200, -30], [950, 930], [955, 900]] src1 = [0, 50, 0, 200, 950, 955] src2 = [100, 200, 10, -30, 930, 900] # Multi-rec (0) and single receivers (1), (2) rec0 = [[4000, 5000], [4100, 5200], [0, 100], [100, 250], [950, 990], [990, 1000]] rec1 = [4000, 4100, 0, 100, 950, 990] rec2 = [5000, 5200, 100, 250, 990, 1000] # Calculate the multi-src/multi-rec result out0f = bipole(src=src0, rec=rec0, signal=None, **model) out0t = bipole(src=src0, rec=rec0, signal=0, **model) # Calculate the single-src/single-rec correspondents out1f = np.zeros((2, 2), dtype=np.complex128) out1t = np.zeros((2, 2)) for i, rec in enumerate([rec1, rec2]): for ii, src in enumerate([src1, src2]): out1f[i, ii] = bipole(src=src, rec=rec, signal=None, **model) out1t[i, ii] = bipole(src=src, rec=rec, signal=0, **model) # Check them assert_allclose(out0f, out1f) assert_allclose(out0t, out1t)
def test_optimizaton(self, capsys): # Compare optimization options: None, parallel, spline inp = { 'depth': [0, 500], 'res': [10, 3, 50], 'freqtime': [1, 2, 3], 'rec': [[6000, 7000, 8000], [200, 200, 200], 300, 0, 0], 'src': [0, 0, 0, 0, 0] } non = bipole(opt=None, verb=3, **inp) out, _ = capsys.readouterr() assert "Hankel Opt. : None" in out par = bipole(opt='parallel', verb=3, **inp) out, _ = capsys.readouterr() assert "Hankel Opt. : Use parallel" in out assert_allclose(non, par, equal_nan=True) spl = bipole(opt='spline', verb=3, **inp) out, _ = capsys.readouterr() assert "Hankel Opt. : Use spline" in out assert_allclose(non, spl, 1e-3, 1e-22, True)
def test_halfspace(self): # Comparison to analytical halfspace solution hs = DATAEMPYMOD['hs'][()] hsbp = DATAEMPYMOD['hsbp'][()] for key in hs: # Get halfspace hs_res = halfspace(**hs[key]) # Get bipole bip_res = bipole(**hsbp[key]) # Check if key in ['12', '13', '21', '22', '23', '31']: # t-domain ex. rtol = 1e-2 else: rtol = 1e-7 assert_allclose(hs_res, bip_res, rtol=rtol)
def calc_cl_freq(freq, filter_name='key201'): # emulatte emsrc = fwd.transmitter(emsrc_name, freq, current=1, radius=radius, turns=1) model.locate(emsrc, sc, rc) fEMF = model.emulate(hankel_filter=filter_name) fhz_emu = fEMF['h_z'] # empymod fhz_emp = empymod.bipole(freqtime=freq, **inp) # 解析解 fhz_ana = cl.fd_hz(freq) return [fhz_emu, fhz_emp, fhz_ana], freq
def test_VEB_Ez(self): print('VEB_Ez and VED_Ez agree with bipole') x1 = 0 y1 = 0 casing_length1 = 1500 num_segments1 = 300 x2 = 2000 y2 = 1000 casing_length2 = 1600 num_segments2 = 200 segment_length1 = casing_length1 / num_segments1 segment_length2 = casing_length2 / num_segments2 zi = 52.5 zj = 1352.5 segment_length = 5 zj1 = zj - segment_length / 2 zj2 = zj + segment_length / 2 epm_veb = bipole( src=[x2, x2, y2, y2, zj - segment_length2, zj + segment_length2], rec=[x1, x1, y1, y1, zi, zi + .01], depth=[0], res=[3e14, 1 / con], freqtime=freq, verb=0) chs_veb = chs.VEB_Ez(x1, y1, zi, xp=x2, yp=y2, zp1=zj - segment_length2 / 2, zp2=zj + segment_length2 / 2, conductivity=con, frequency=freq) chs_ved = chs.VED_Ez(x1, y1, zi, xp=x2, yp=y2, zp=zj, conductivity=con, frequency=freq) self.assertTrue(np.isclose(epm_veb, chs_ved, rtol=1e-3, atol=1e-20)) self.assertTrue( np.isclose(epm_veb * segment_length2, chs_veb, rtol=1e-3, atol=1e-20))
def get_xyz(src, rec, depth, res, freq, srcpts): ex = bipole(src, crec(rec, 0, 0), depth, res, freq, srcpts=srcpts, mrec=False, verb=0) ey = bipole(src, crec(rec, 90, 0), depth, res, freq, srcpts=srcpts, mrec=False, verb=0) ez = bipole(src, crec(rec, 0, 90), depth, res, freq, srcpts=srcpts, mrec=False, verb=0) mx = bipole(src, crec(rec, 0, 0), depth, res, freq, srcpts=srcpts, mrec=True, verb=0) my = bipole(src, crec(rec, 90, 0), depth, res, freq, srcpts=srcpts, mrec=True, verb=0) mz = bipole(src, crec(rec, 0, 90), depth, res, freq, srcpts=srcpts, mrec=True, verb=0) return ex, ey, ez, mx, my, mz
def get_xyz(src, rec, depth, res, freq, aniso, strength, srcpts, msrc): ex = bipole(src, crec(rec, 0, 0), depth, res, freq, aniso=aniso, msrc=msrc, mrec=False, strength=strength, srcpts=srcpts, verb=0) ey = bipole(src, crec(rec, 90, 0), depth, res, freq, aniso=aniso, msrc=msrc, mrec=False, strength=strength, srcpts=srcpts, verb=0) ez = bipole(src, crec(rec, 0, 90), depth, res, freq, aniso=aniso, msrc=msrc, mrec=False, strength=strength, srcpts=srcpts, verb=0) mx = bipole(src, crec(rec, 0, 0), depth, res, freq, aniso=aniso, msrc=msrc, mrec=True, strength=strength, srcpts=srcpts, verb=0) my = bipole(src, crec(rec, 90, 0), depth, res, freq, aniso=aniso, msrc=msrc, mrec=True, strength=strength, srcpts=srcpts, verb=0) mz = bipole(src, crec(rec, 0, 90), depth, res, freq, aniso=aniso, msrc=msrc, mrec=True, strength=strength, srcpts=srcpts, verb=0) return ex, ey, ez, mx, my, mz
def test_cole_cole(self): # Check user-hook for eta/zeta def func_eta(inp, pdict): # Dummy function to check if it works. etaH = pdict['etaH'].real * inp['fact'] + 1j * pdict['etaH'].imag etaV = pdict['etaV'].real * inp['fact'] + 1j * pdict['etaV'].imag return etaH, etaV def func_zeta(inp, pdict): # Dummy function to check if it works. etaH = pdict['zetaH'] / inp['fact'] etaV = pdict['zetaV'] / inp['fact'] return etaH, etaV model = { 'src': [0, 0, 500, 0, 0], 'rec': [500, 0, 600, 0, 0], 'depth': [0, 550], 'freqtime': [0.1, 1, 10] } res = np.array([2, 10, 5]) fact = np.array([2, 2, 2]) eta = {'res': fact * res, 'fact': fact, 'func_eta': func_eta} zeta = {'res': res, 'fact': fact, 'func_zeta': func_zeta} # Frequency domain standard = bipole(res=res, **model) outeta = bipole(res=eta, **model) assert_allclose(standard, outeta) outzeta = bipole(res=zeta, mpermH=fact, mpermV=fact, **model) assert_allclose(standard, outzeta) # Time domain standard = bipole(res=res, signal=0, **model) outeta = bipole(res=eta, signal=0, **model) assert_allclose(standard, outeta) outzeta = bipole(res=zeta, signal=0, mpermH=fact, mpermV=fact, **model) assert_allclose(standard, outzeta)
def wire_e_field_casing_halfspace(tx_path_x, tx_path_y, rx_ex_locations, rx_ey_locations, frequency, background_conductivity=0.18, casing_location=[0,0], casing_length=1365, casing_conductivity=1.0e7, outer_radius=0.1095, inner_radius=0.1095-0.0134, num_segments=280, wire_current=1, srcpts=1): ''' Compute EM field at rx_locations due to a wire in the presence of a steel casing Parameters ---------- tx_path_x : list Source coordinates in x (m) tx_path_y : list Source coordinates in y (m) rx_ex_locations, rx_ey_locations : list of lists Ex and Ex receiver coordinates (m): empymod format [x1,x2,y1,y2,z1,z2] z1 and z2 can be scalars even when x and y variables are lists casing_location : list NOT YET IMPLEMENTED: casing assumed to be at 0,0 casing well head location, as [x,y] ''' # TODO: set well location as origin # TODO: compute magnetic field too # TODO: allow multiple frequencies # discretizations # need wire segment lengths dlx = np.diff(tx_path_x) dly = np.diff(tx_path_y) all_segment_lengths = np.sqrt(dlx**2+dly**2) # is segment length zero? nonzero_length = np.append(all_segment_lengths>0,True) # remove 0 length segments lx = tx_path_x[nonzero_length] ly = tx_path_y[nonzero_length] segment_lengths = all_segment_lengths[all_segment_lengths>0] # casing discretization dz = casing_length/num_segments zs = dz*(np.arange(num_segments)+0.5) # compute casing currents # make an argument dictionary for MoM functions casing_args = {'wire_path_x':lx, 'wire_path_y':ly, 'wire_current':wire_current, 'frequency':frequency, 'background_conductivity':background_conductivity, 'casing_conductivity':casing_conductivity, 'casing_length':casing_length, 'outer_radius':outer_radius, 'inner_radius':inner_radius, 'num_segments':num_segments} # form A A = form_A(**casing_args) # form b b = form_b(**casing_args) # solve for casing currents j_casing = np.linalg.solve(A,b) casing_area = np.pi*(outer_radius**2-inner_radius**2) i_casing = j_casing*casing_area casing_moment = i_casing*dz # convert inputs to empymod format empy_wire_args = {'src':[lx[:-1],lx[1:],ly[:-1],ly[1:],1e-2,1e-2], 'rec':rx_ex_locations, 'depth':[0], 'res':[1e20,1/background_conductivity], 'freqtime':frequency, 'srcpts':srcpts, 'verb':0, 'epermH':[0,1], 'epermV':[0,1]} rx_locations_ex_average = [(rx_ex_locations[0]+rx_ex_locations[1])/2, (rx_ex_locations[2]+rx_ex_locations[3])/2, (rx_ex_locations[4]+rx_ex_locations[5])/2] rx_locations_ey_average = [(rx_ey_locations[0]+rx_ey_locations[1])/2, (rx_ey_locations[2]+rx_ey_locations[3])/2, (rx_ey_locations[4]+rx_ey_locations[5])/2] empy_casing_args = {'src':[0,0,zs], 'rec':rx_locations_ex_average, 'depth':[0], 'res':[1e20,1/background_conductivity], 'freqtime':frequency, 'ab':13, 'verb':0, 'epermH':[0,1], 'epermV':[0,1]} # compute field due to wire wire_moment = segment_lengths*wire_current all_field_x_wire = bipole(**empy_wire_args) field_x_wire = np.dot(all_field_x_wire,wire_moment) empy_wire_args['rec'] = rx_ey_locations all_field_y_wire = bipole(**empy_wire_args) field_y_wire = np.dot(all_field_y_wire,wire_moment) # compute field due to casing field_x_casing = 1j*np.zeros(len(rx_ex_locations[0])) field_y_casing = 1j*np.zeros(len(rx_ey_locations[0])) for iz in range(len(zs)): empy_casing_args['src'] = [0,0,zs[iz]] # x empy_casing_args['rec'] = rx_locations_ex_average empy_casing_args['ab'] = 13 field_x_casing += casing_moment[iz]*dipole(**empy_casing_args) # y empy_casing_args['rec'] = rx_locations_ey_average empy_casing_args['ab'] = 23 field_y_casing += casing_moment[iz]*dipole(**empy_casing_args) # sum all fields field_x = field_x_casing + field_x_wire field_y = field_y_casing + field_y_wire return(field_x,field_y,field_x_wire,field_y_wire,field_x_casing,field_y_casing)
res = [2e14, 100] strength = area / (radius / 2) mrec = True # Computation inp = { 'src': src, 'rec': rec, 'depth': depth, 'res': res, 'freqtime': freq, 'strength': strength, 'mrec': mrec, 'verb': 1 } fhz_num = empymod.bipole(**inp) # Figure plt.figure(figsize=(5, 5)) plt.plot(freq, fhz_num.real, 'C0-', label='Real') plt.plot(freq, -fhz_num.real, 'C0--') plt.plot(freq, fhz_num.imag, 'C1-', label='Imaginary') plt.plot(freq, -fhz_num.imag, 'C1--') plt.xscale('log') plt.yscale('log') plt.xlim([1e-1, 1e6]) plt.ylim([1e-8, 1e-1]) plt.xlabel('frequency (Hz)')