def _efieldn_koelbig(x, y, sig_x, sig_y): '''The charge-normalised electric field components of a two-dimensional Gaussian charge distribution according to M. Bassetti and G. A. Erskine in CERN-ISR-TH/80-06. Return (E_x / Q, E_y / Q). Assumes sig_x > sig_y and mean_x == 0 as well as mean_y == 0. For convergence reasons of the erfc, use only x > 0 and y > 0. Uses CERN library from K. Koelbig. ''' # timing was ~3.35ms for same situation as _efieldn_mit if not pm._errf: raise ImportError('errfff cannot be imported for using ' + 'TransverseSpaceCharge._efield_koelbig .' + 'Did you call make (or f2py general/errfff.f)?') sig_sqrt = TransverseGaussianSpaceCharge._sig_sqrt(sig_x, sig_y) w1re, w1im = pm._errf(x / sig_sqrt, y / sig_sqrt) ex = pm.exp(-x * x / (2 * sig_x * sig_x) + -y * y / (2 * sig_y * sig_y)) w2re, w2im = pm._errf(x * sig_y / (sig_x * sig_sqrt), y * sig_x / (sig_y * sig_sqrt)) pref = 1. / (2 * epsilon_0 * np.sqrt(pi) * sig_sqrt) return pref * (w1im - ex * w2im), pref * (w1re - ex * w2re)
def _efieldn_mit(x, y, sig_x, sig_y): '''The charge-normalised electric field components of a two-dimensional Gaussian charge distribution according to M. Bassetti and G. A. Erskine in CERN-ISR-TH/80-06. Return (E_x / Q, E_y / Q). Assumes sig_x > sig_y and mean_x == 0 as well as mean_y == 0. For convergence reasons of the erfc, use only x > 0 and y > 0. Uses FADDEEVA C++ implementation from MIT (via SciPy >= 0.13.0). ''' # timing was ~0.522 ms for: # x = np.arange(-1e-5, 1e-5, 1e-8) # y = np.empty(len(x)) # sig_x = 1.2e-6 # sig_y = 1e-6 sig_sqrt = TransverseGaussianSpaceCharge._sig_sqrt(sig_x, sig_y) w1re, w1im = pm.wofz(x / sig_sqrt, y / sig_sqrt) ex = pm.exp(-x * x / (2 * sig_x * sig_x) + -y * y / (2 * sig_y * sig_y)) w2re, w2im = pm.wofz(x * sig_y / (sig_x * sig_sqrt), y * sig_x / (sig_y * sig_sqrt)) denom = 2. * epsilon_0 * np.sqrt(pi) * sig_sqrt return (w1im - ex * w2im) / denom, (w1re - ex * w2re) / denom
def _efieldn_round(x, y, sig_r): '''Return (E_x / Q, E_y / Q) for a round distribution with sigma_x == sigma_y == sig_r . ''' r2 = x * x + y * y amplitude = (1 - pm.exp(-r2 / (2 * sig_r * sig_r))) / (2 * pi * epsilon_0 * r2) return x * amplitude, y * amplitude
def _efieldn_mitmod(x, y, sig_x, sig_y): '''The charge-normalised electric field components of a two-dimensional Gaussian charge distribution according to M. Bassetti and G. A. Erskine in CERN-ISR-TH/80-06. Return (E_x / Q, E_y / Q). Assumes sig_x > sig_y and mean_x == 0 as well as mean_y == 0. For convergence reasons of the erfc, use only x > 0 and y > 0. Uses erfc C++ implementation from MIT (via SciPy >= 0.13.0) and calculates wofz (FADDEEVA function) explicitely. ''' # timing was ~1.01ms for same situation as _efieldn_mit sig_sqrt = _sig_sqrt(sig_x, sig_y) w1 = pm._errfadd((x + 1j * y) / sig_sqrt) ex = pm.exp(-x * x / (2 * sig_x * sig_x) + -y * y / (2 * sig_y * sig_y)) w2 = pm._errfadd(x * sig_y / (sig_x * sig_sqrt) + y * sig_x / (sig_y * sig_sqrt) * 1j) val = (w1 - ex * w2) / (2 * epsilon_0 * np.sqrt(pi) * sig_sqrt) return val.imag, val.real