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_propagation(sys, t_final): """ Run tests for the specified propagators and plot the probability density of the time dependent propagation :param sys: class that propagates """ iterations = 748 steps = int(np.ceil(t_final / sys.dt / iterations)) # display the propagator plt.imshow( [np.abs(sys.propagate(steps))**2 for _ in range(iterations)], origin='lower', norm=LogNorm(vmin=1e-12, vmax=0.1), aspect=0.4, # image aspect ratio extent=[sys.x.min(), sys.x.max(), 0., sys.t]) plt.xlabel('coordinate $x$ (a.u.)') plt.ylabel('time $t$ (a.u.)') plt.colorbar()
def test_propagation(sys): """ Run tests for the specified propagators and plot the probability density of the time dependent propagation :param sys: class that propagates """ # Set the ground state wavefunction as the initial condition sys.get_stationary_states(1) sys.set_wavefunction(sys.stationary_states[0]) iterations = 748 steps = int(round(sys.t_final / sys.dt / iterations)) # display the propagator plt.imshow( [np.abs(sys.propagate(steps))**2 for _ in xrange(iterations)], origin='lower', norm=LogNorm(vmin=1e-12, vmax=0.1), aspect=0.4, # image aspect ratio extent=[sys.X.min(), sys.X.max(), 0., sys.t]) plt.xlabel('coordinate $x$ (a.u.)') plt.ylabel('time $t$ (a.u.)') plt.colorbar()
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