aboutsummaryrefslogtreecommitdiff
path: root/Source/WarpX_laser.F90
blob: 76ff0caa67c8ff86d983535fd0885a33a6d52156 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

module warpx_laser_module

  use iso_c_binding
  use amrex_fort_module, only : amrex_real
  use constants, only : clight, pi
  use parser_wrapper, only : parser_evaluate_function

  implicit none

contains

  subroutine warpx_gaussian_laser( np, Xp, Yp, t, &
      wavelength, e_max, waist, duration, t_peak, f, amplitude, &
      zeta, beta, phi2 ) bind(C, name="warpx_gaussian_laser")

    integer(c_long), intent(in) :: np
    real(amrex_real), intent(in)    :: Xp(np),Yp(np)
    real(amrex_real), intent(in)    :: e_max, t, t_peak, wavelength, duration, f, waist
    real(amrex_real), intent(in)    :: zeta, beta, phi2
    real(amrex_real), intent(inout) :: amplitude(np)

    integer(c_long)  :: i
    real(amrex_real) :: k0, oscillation_phase, inv_tau2
    complex*16       :: diffract_factor, exp_argument, prefactor, &
                        inv_complex_waist_2, stretch_factor, &
                        stc_exponent, stcfactor
    complex*16, parameter :: j=cmplx(0., 1.)

    ! This function uses the complex expression of a Gaussian laser
    ! (Including Gouy phase and laser oscillations)

    ! Calculate a few factors which are independent of the macroparticle
    k0 = 2*pi/wavelength
    inv_tau2 = 1. / duration**2
    oscillation_phase = k0 * clight * ( t - t_peak )
    ! The coefficients below contain info about Gouy phase,
    ! laser diffraction, and phase front curvature
    diffract_factor = 1 + j * f * 2./(k0*waist**2)
    inv_complex_waist_2 = 1./( waist**2 * diffract_factor )
    
    ! Time stretching due to STCs and phi2 complex envelope
    ! (1 if zeta=0, beta=0, phi2=0)
    stretch_factor = 1. + \
        4*(zeta + beta*f)**2 * (inv_tau2*inv_complex_waist_2) + \
        2*j*(phi2 - beta**2*k0*f) * inv_tau2
    
    ! Amplitude and monochromatic oscillations
    prefactor = e_max * exp( j * oscillation_phase )

    ! Because diffract_factor is a complex, the code below takes into
    ! account the impact of the dimensionality on both the Gouy phase
    ! and the amplitude of the laser
#if (AMREX_SPACEDIM == 3)
    prefactor = prefactor / diffract_factor
#elif (AMREX_SPACEDIM == 2)
    prefactor = prefactor / sqrt(diffract_factor)
#endif

    ! Loop through the macroparticle to calculate the proper amplitude
    do i = 1, np
      ! Exp argument for the temporal gaussian envelope + STCs
      stc_exponent = 1./stretch_factor * inv_tau2 * \
          (t - t_peak - beta*k0*Xp(i) - 2*j*Xp(i)*( zeta - beta*f ) * \
          inv_complex_waist_2)**2 
      ! stcfactor = everything but complex transverse envelope 
      stcfactor = prefactor * exp( - stc_exponent )
      ! Exp argument for transverse envelope
      exp_argument = - ( Xp(i)*Xp(i) + Yp(i)*Yp(i) ) * inv_complex_waist_2
      ! stcfactor + transverse envelope
      amplitude(i) = DREAL( stcfactor * exp( exp_argument ) )
    enddo

  end subroutine warpx_gaussian_laser

  ! Harris function for the laser temporal profile
  subroutine warpx_harris_laser( np, Xp, Yp, t, &
      wavelength, e_max, waist, duration, f, amplitude ) &
       bind(C, name="warpx_harris_laser")

       integer(c_long), intent(in) :: np
       real(amrex_real), intent(in)    :: Xp(np),Yp(np)
       real(amrex_real), intent(in)    :: e_max, t, wavelength, duration, f, waist
       real(amrex_real), intent(inout) :: amplitude(np)

       integer(c_long)  :: i
       real(amrex_real) :: space_envelope, time_envelope, arg_osc, arg_env
       real(amrex_real) :: omega0, zR, wz, inv_Rz, oscillations, inv_wz_2

    ! This function uses the Harris function as the temporal profile of the pulse
    omega0 = 2*pi*clight/wavelength
    zR = pi * waist**2 / wavelength
    wz = waist * sqrt(1. + f**2/zR**2)
    inv_wz_2 = 1./wz**2
    if (f == 0.) then
      inv_Rz = 0.
    else
      inv_Rz = -f / ( f**2 + zR**2 )
    end if

    arg_env = 2.*pi*t/duration

    ! time envelope is given by the Harris function
    time_envelope = 0.
    if (t < duration) then
      time_envelope = 1./32. * (10. - 15.*cos(arg_env) + 6.*cos(2.*arg_env) - cos(3.*arg_env))
    else
      time_envelope = 0.
    end if

    ! Loop through the macroparticle to calculate the proper amplitude
    do i = 1, np
      space_envelope = exp(- ( Xp(i)*Xp(i) + Yp(i)*Yp(i) ) * inv_wz_2)
      arg_osc = omega0*t - omega0/clight*(Xp(i)*Xp(i) + Yp(i)*Yp(i)) * inv_Rz / 2
      oscillations = cos(arg_osc)
      amplitude(i) = e_max * time_envelope * space_envelope * oscillations
    enddo

  end subroutine warpx_harris_laser

  ! Parse function from the input script for the laser temporal profile
  subroutine parse_function_laser( np, Xp, Yp, t, amplitude, parser_instance_number ) bind(C, name="parse_function_laser")
       integer(c_long), intent(in) :: np
       real(amrex_real), intent(in)    :: Xp(np),Yp(np)
       real(amrex_real), intent(in)    :: t
       real(amrex_real), intent(inout) :: amplitude(np)
       INTEGER, value, INTENT(IN) :: parser_instance_number
       integer(c_long)  :: i
       INTEGER, PARAMETER :: nvar_parser = 3
       REAL(amrex_real) :: list_var(1:nvar_parser)
    ! Loop through the macroparticle to calculate the proper amplitude
    do i = 1, np
      list_var = [Xp(i), Yp(i), t]
      amplitude(i) = parser_evaluate_function(list_var, nvar_parser, parser_instance_number)
    enddo
  end subroutine parse_function_laser

end module warpx_laser_module