"""
This module collects some tools to deal with Gaussian pulses.
This class of pulses is described by a sinusoidal function, whose frequency
defines the `energy` :math:`E=\hbar\omega` of the pulse, times a gaussian envelope.
The time-dependent amplitude of the pulse is parametrized as
.. math::
:label: pulseamplitude
{\cal G}(t) = A sin(\omega t)e^{-(t-t_0)^2/2w^2}
where ``A`` is the amplitude of the pulse and the value of :math:`t_0` sets the
position of the maximum of the gaussian envelope. Here :math:`t_0` is expressed
in function of the width parameter as the multiple of the half period of the sine
function nearest to 3w. Due to this choice the maximum of the gaussian profile
matches with the maximum of the sine function. The origin of the time
variable can be set using the :math:`t_{start}` parameter.
The width parameter determines the value of the FWHM of the pulse according to the
relation
.. math::
:label: fwhm_def
FWHM = 2 w \sqrt{2ln(2)}
"""
import numpy as np
from mppi.Utilities import Constants as C
[docs]def gaussianPulse(time, energy = 1.5, amplitude = 1, width = 100, fwhm = None,t_start = 0,
envelope_only = False, THz_pulse = False, change_sign = False, verbose = True):
"""
Build a Gaussian pulse.
Args:
time : the value of the time variable (in fs), it can be a single :py:class:`float`
or an :py:class:`array`
energy (:py:class:`float`) : the energy of the pulse (in eV)
amplitude (:py:class:`float`) : the amplitude of the pulse (it can be a complex number)
width (:py:class:`float`) : the width parameter of the Gaussian (in fs)
fwhm (:py:class:`float`) : if not None set the FWHM of the pulse (in fs). The width
is set to :math:`fwhm/(2\sqrt{2ln(2)})`
t_start (:py:class:`float`) : time shift for the origin of the pulse (in fs)
envelope_only (:py:class:`bool`) : if True the sinusodial oscillating factor
is not considered
THz_pulse (:py:class:`bool`) : if True expresses the energy in meV and the
time variable and the width parameter in ps
change_sign (:py:class:`bool`) : if True change the sign to the envelope function
verbose (:py:class:`bool`) : defines the amount of information provided
on terminal
Returns:
:py:class:`float` or :py:class:`array` (depending on the time provided as input)
with the value of the Gaussian pulse. The pulse can be complex (depending on the
amplitude provided as input)
"""
if not THz_pulse:
h_red = C.Planck_reduced_ev_ps*1e3 # in eV*fs
timeUnit = 'fs'
inverseTimeUnit = 'fs^-1'
if verbose: print('time unit: fs - energy unit: eV')
else:
h_red = C.Planck_reduced_ev_ps*1e3 # in meV*ps
timeUnit = 'ps'
inverseTimeUnit = 'ps^-1'
if verbose: print('time unit: ps - energy unit: meV')
omega = energy/h_red
if fwhm is None:
fwhm = width*(2.*np.sqrt(2.*np.log(2.)))
else:
width = fwhm/(2.*np.sqrt(2.*np.log(2.)))
if verbose :
print('period of the oscillations',2.*np.pi/omega,timeUnit)
print('width of the pulse',width,timeUnit)
print('fwhm of the pulse',fwhm,timeUnit)
t = time-t_start
t0 = np.pi/omega*round(omega/np.pi*3*width)
#t0 = 3.*width
exp_arg = (t-t0)**2/(2.*width**2)
if not change_sign: envelope_sign = 1
else: envelope_sign = -1
pulse = envelope_sign*amplitude*np.exp(-exp_arg)
if not envelope_only:
pulse *= np.sin(omega*t)
return pulse
[docs]def doubleGaussianPulse(time, energy = 1.5, amplitude1 = 1, amplitude2 = 1, width1 = 100, width2 = 100,
fwhm1 = None, fwhm2 = None, t_start1 = 0, t_start2 = 600, envelope_only = False,
THz_pulse = False, change_sign1 = False, change_sign2 = False, verbose = True):
"""
Build a sine oscillating pulse with e double Gaussian envelope.
Args:
time : the value of the time variable (in fs), it can be a single :py:class:`float`
or an :py:class:`array`
energy (:py:class:`float`) : the energy of the pulse (in eV)
amplitude1 (:py:class:`float`) : the amplitude of the first pulse (it can be a complex number)
amplitude2 (:py:class:`float`) : the amplitude of the second pulse (it can be a complex number)
width1 (:py:class:`float`) : the width parameter of the first Gaussian (in fs)
fwhm1 (:py:class:`float`) : if not None set the FWHM of the first pulse (in fs). The width1
is set to :math:`fwhm1/(2\sqrt{2ln(2)})`
width2 (:py:class:`float`) : the width parameter of the second Gaussian (in fs)
fwhm2 (:py:class:`float`) : if not None set the FWHM of the second pulse (in fs). The width2
is set to :math:`fwhm2/(2\sqrt{2ln(2)})`
t_start1 (:py:class:`float`) : time shift for the origin of the first pulse (in fs)
t_start2 (:py:class:`float`) : time shift for the origin of the second pulse (in fs)
envelope_only (:py:class:`bool`) : if True the sinusodial oscillating factor
is not considered
THz_pulse (:py:class:`bool`) : if True expresses the energy in meV and the
time variable and the width parameter in ps
change_sign1 (:py:class:`bool`) : if True change the sign to the first envelope function
change_sign2 (:py:class:`bool`) : if True change the sign to the second envelope function
verbose (:py:class:`bool`) : defines the amount of information provided
on terminal
Returns:
:py:class:`float` or :py:class:`array` (depending on the time provided as input)
with the value of the double Gaussian pulse. The pulse can be complex (depending on the
amplitude provided as input)
"""
if not THz_pulse:
h_red = C.Planck_reduced_ev_ps*1e3 # in eV*fs
timeUnit = 'fs'
inverseTimeUnit = 'fs^-1'
if verbose: print('time unit: fs - energy unit: eV')
else:
h_red = C.Planck_reduced_ev_ps*1e3 # in meV*ps
timeUnit = 'ps'
inverseTimeUnit = 'ps^-1'
if verbose: print('time unit: ps - energy unit: meV')
omega = energy/h_red
if fwhm1 is None:
fwhm1 = width1*(2.*np.sqrt(2.*np.log(2.)))
else:
width1 = fwhm1/(2.*np.sqrt(2.*np.log(2.)))
if fwhm2 is None:
fwhm2 = width2*(2.*np.sqrt(2.*np.log(2.)))
else:
width2 = fwhm2/(2.*np.sqrt(2.*np.log(2.)))
if verbose :
print('period of the oscillations',2.*np.pi/omega,timeUnit)
print('width of the first pulse',width1,timeUnit)
print('fwhm of the first pulse',fwhm1,timeUnit)
print('width of the second pulse',width2,timeUnit)
print('fwhm of the second pulse',fwhm2,timeUnit)
pulse1 = gaussianPulse(time, energy=energy, amplitude=amplitude1,width=width1,
t_start= t_start1,envelope_only=True,THz_pulse=THz_pulse,change_sign=change_sign1,verbose=False)
pulse2 = gaussianPulse(time, energy=energy, amplitude=amplitude2,width=width2,
t_start= t_start2,envelope_only=True,THz_pulse=THz_pulse,change_sign=change_sign2,verbose=False)
doublePulse = pulse1 + pulse2
t = time-t_start1
if not envelope_only:
doublePulse *= np.sin(omega*t)
return doublePulse