Exemplo n.º 1
0
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.])
Exemplo n.º 2
0
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