def plot_spectrum(sys): """ Plot the High Harmonic Generation spectrum """ # Power spectrum emitted is calculated using the Larmor formula # (https://en.wikipedia.org/wiki/Larmor_formula) # which says that the power emitted is proportional to the square of the acceleration # i.e., the RHS of the second Ehrenfest theorem N = len(sys.P_average_RHS) k = np.arange(N) # frequency range omegas = (k - N / 2) * np.pi / (0.5 * sys.t) # spectra of the spectrum = np.abs( # used windows fourier transform to calculate the spectra # rhttp://docs.scipy.org/doc/scipy/reference/tutorial/fftpack.html fftpack.fft((-1)**k * blackman(N) * sys.P_average_RHS))**2 spectrum /= spectrum.max() plt.semilogy(omegas / sys.omega_laser, spectrum) plt.ylabel('spectrum (arbitrary units)') plt.xlabel('frequency / $\\omega_L$') plt.xlim([0, 45.]) plt.ylim([1e-15, 1.])
def test_Ehrenfest2(sys): """ Test the second Ehenfest theorem for the specified quantum system """ times = sys.dt * np.arange(len(sys.P_average)) dP_dt = np.gradient(sys.P_average, sys.dt) print("%.2e" % np.linalg.norm(dP_dt - sys.P_average_RHS)) plt.plot(times, dP_dt, '-r', label='$d\\langle\\hat{p}\\rangle / dt$') plt.plot(times, sys.P_average_RHS, '--b', label='$\\langle -U\'(\\hat{x})\\rangle$') plt.legend() plt.ylabel('force') plt.xlabel('time $t$ (a.u.)')
def test_Ehrenfest1(sys): """ Test the first Ehenfest theorem for the specified quantum system """ times = sys.dt * np.arange(len(sys.x_average)) dx_dt = np.gradient(sys.x_average, sys.dt) print("{:.2e}".format(np.linalg.norm(dx_dt - sys.x_average_rhs))) plt.plot(times, dx_dt, '-r', label='$d\\langle\\hat{x}\\rangle / dt$') plt.plot(times, sys.x_average_rhs, '--b', label='$\\langle\\hat{p}\\rangle$') plt.legend() plt.ylabel('momentum') plt.xlabel('time $t$ (a.u.)')
def frft(x, alpha): """ Implementation of the Fractional Fourier Transform (FRFT) :param x: array of data to be transformed :param alpha: parameter of FRFT :return: FRFT(x) """ k = np.arange(x.size) y = np.hstack([ x * np.exp(-np.pi * 1j * k**2 * alpha), np.zeros(x.size, dtype=np.complex) ]) z = np.hstack([ np.exp(np.pi * 1j * k**2 * alpha), np.exp(np.pi * 1j * (k - x.size)**2 * alpha) ]) G = fftpack.ifft(fftpack.fft(y, overwrite_x=True) * fftpack.fft(z, overwrite_x=True), overwrite_x=True) return np.exp(-np.pi * 1j * k**2 * alpha) * G[:x.size]
def get_hhg_spectrum(F, omega_0=0.06, omega_1=0.12, omega_2=0.18, data=np.zeros(10), get_omega=False, test_mode=False): """ Evaluate the HHG spectrum :param F: the amplitude of the laser field strength :param get_omega: boolean flag whether to return the omegas :param coords: tuple of data to be encoded into laser :return: """ #################################################################################################################### # # Define parameters of an atom (a single-electron model of Ar) in the external laser field # #################################################################################################################### # laser field frequency omega_laser = omega_0 omegas = np.linspace(omega_1, omega_2, len(data)) # the final time of propagation (= 8 periods of laser oscillations) t_final = 12 * 2. * np.pi / omega_laser # the amplitude of grid x_amplitude = 300. # the time step dt = 0.05 @njit def laser(t): """ The strength of the laser field. Always add an envelop to the laser field to avoid all sorts of artifacts. We use a sin**2 envelope, which resembles the Blackman filter """ # laser = 2*np.sin(omega_laser * t) laser = np.sin(omega_laser * t) for freq, dat in zip(omegas, data): laser += dat * np.sin(freq * t) laser *= F * np.sin(np.pi * t / t_final)**2 return laser @njit def v(x, t=0.): """ Potential energy. Define the potential energy as a sum of the soft core Columb potential and the laser field interaction in the dipole approximation. """ return -1. / np.sqrt(x**2 + 2.37) + x * laser(t) @njit def diff_v(x, t=0.): """ the derivative of the potential energy """ return x * (x**2 + 2.37)**(-1.5) + laser(t) @njit def k(p, t=0.): """ Non-relativistic kinetic energy """ return 0.5 * p**2 @njit def diff_k(p, t=0.): """ the derivative of the kinetic energy for Ehrenfest theorem evaluation """ return p @njit def abs_boundary(x): """ Absorbing boundary similar to the Blackman filter """ return np.sin(0.5 * np.pi * (x + x_amplitude) / x_amplitude)**(0.05 * dt) sys_params = dict( dt=dt, x_grid_dim=2 * 1024, x_amplitude=x_amplitude, k=k, diff_k=diff_k, v=v, diff_v=diff_v, abs_boundary=abs_boundary, ) #################################################################################################################### # # propagate # #################################################################################################################### sys = ImgTimePropagation(**sys_params) # Set the ground state wavefunction as the initial condition sys.get_stationary_states(1) sys.set_wavefunction(sys.stationary_states[0]) if test_mode: plt.title("No absorbing boundary, $|\\Psi(x, t)|^2$") test_propagation(sys, t_final) plt.show() plt.subplot(121) print("\nError in the first Ehrenfest relation: ") test_Ehrenfest1(sys) plt.subplot(122) print("\nError in the second Ehrenfest relation: ") test_Ehrenfest2(sys) plt.show() else: steps = int(np.ceil(t_final / sys.dt)) sys.propagate(steps) print("F = {} Completed!".format(F)) #################################################################################################################### # # Evaluate the spectrum # #################################################################################################################### # N = len(sys.x_average) # k = np.arange(N) # # # frequency range # omega = (k - N / 2) * np.pi / (0.5 * sys.t) # # # spectra of the # spectrum = np.abs( # # used windows fourier transform to calculate the spectra # # rhttp://docs.scipy.org/doc/scipy/reference/tutorial/fftpack.html # fftpack.fft((-1) ** k * blackman(N) * sys.x_average) # ) ** 2 # spectrum /= spectrum.max() N = len(sys.p_average_rhs) k = np.arange(N) # generate the desired momentum grid omega_amplitude = 2. domega = 2. * omega_amplitude / N omega = (k - N / 2) * domega delta = sys.dt * domega / (2. * np.pi) spectrum = np.abs( frft( blackman(N) * sys.p_average_rhs * np.exp(np.pi * 1j * k * N * delta), delta))**2 spectrum /= spectrum.max() return (spectrum, omega / omega_laser) if get_omega else spectrum