31 use,
intrinsic :: iso_fortran_env
85 integer,
public,
parameter :: &
94 integer :: field = e_field_none
95 complex(real64),
allocatable :: pol(:)
96 real(real64),
allocatable :: prop(:)
99 real(real64) :: omega =
m_zero
101 real(real64),
allocatable :: v(:)
102 real(real64),
allocatable :: a(:, :)
103 character(len=200) :: scalar_pot_expression
104 character(len=200) :: phase_expression
105 character(len=200) :: envelope_expression
111 integer,
public :: no_lasers
112 type(laser_t),
allocatable,
public :: lasers(:)
114 real(real64),
allocatable :: e(:)
115 real(real64),
allocatable :: b(:)
116 real(real64),
allocatable :: integrated_nondipole_afield(:)
117 real(real64) :: nd_integration_time
118 real(real64) :: nd_integration_step
134 class(lasers_t),
pointer :: this
135 type(namespace_t),
intent(in) :: namespace
141 this%namespace =
namespace_t(
"Lasers", parent=namespace)
143 safe_allocate(this%e(1:3))
144 safe_allocate(this%b(1:3))
152 class(lasers_t),
intent(inout) :: this
155 integer :: il, jj, ierr, k
156 real(real64) :: omega0
157 complex(real64) :: cprop(3)
259 if (
parse_block(this%namespace,
'TDExternalFields', blk) == 0)
then
261 safe_allocate(this%lasers(1:this%no_lasers))
263 do il = 1, this%no_lasers
264 safe_allocate(this%lasers(il)%pol(1:3))
265 this%lasers(il)%pol =
m_z0
269 select case (this%lasers(il)%field)
273 this%lasers(il)%pol =
m_z1
283 this%lasers(il)%omega = omega0
286 call tdf_read(this%lasers(il)%f, this%namespace, trim(this%lasers(il)%envelope_expression), ierr)
291 call tdf_read(this%lasers(il)%phi, this%namespace, trim(this%lasers(il)%phase_expression), ierr)
293 write(
message(1),
'(3A)')
'Error in the "', trim(this%lasers(il)%envelope_expression), &
294 '" field defined in the TDExternalFields block:'
295 write(
message(2),
'(3A)')
'Time-dependent phase function "', trim(this%lasers(il)%phase_expression), &
305 safe_allocate(this%lasers(il)%prop(1:
size(cprop)))
306 do k = 1,
size(cprop)
310 if (any(abs(aimag(cprop)) >
m_epsilon))
then
311 write(
message(1),
'(3A)')
'Error in the "', trim(this%lasers(il)%envelope_expression), &
312 '" field defined in the TDExternalFields block:'
313 write(
message(2),
'(A)')
'Propagation direction cannot be complex.'
316 this%lasers(il)%prop(:) = real(cprop(:), real64)
317 if (.not.
allocated(this%integrated_nondipole_afield))
then
318 safe_allocate(this%integrated_nondipole_afield(1:
size(cprop)))
319 this%integrated_nondipole_afield(1:3)=
m_zero
320 this%nd_integration_time=
m_zero
332 call parse_variable(this%namespace,
'NDSFATimeIntegrationStep', 0.01_real64, this%nd_integration_step)
334 if (
is_close(this%nd_integration_step, 0.01_real64))
then
335 message(1) =
"The default timestep of 0.01 is utilized for the nondipole SFA integration."
336 message(2) =
"Be aware that this should be at least an order of magniude less than the TDtimestep"
351 class(
lasers_t),
intent(inout) :: this
352 class(
mesh_t),
intent(in) :: mesh
353 class(
space_t),
intent(in) :: space
357 integer :: il, ip, idir, idir2
358 real(real64) :: rr, pot_re, pot_im, xx(3)
359 real(real64) :: miller(space%dim,space%dim), miller_red(space%dim,space%dim)
363 do il = 1, this%no_lasers
397 if (
parse_block(this%namespace,
'MillerIndicesBasis', blk2) == 0)
then
398 if(.not. space%is_periodic())
then
399 write(
message(1),
'(a)')
'MillerIndicesBasis can only be used for periodic systems.'
403 do idir = 1, space%dim
404 do idir2 = 1, space%dim
411 this%lasers(il)%pol = matmul(miller, this%lasers(il)%pol)
415 this%lasers(il)%pol(:) = this%lasers(il)%pol(:)/
sqrt(sum(abs(this%lasers(il)%pol(:))**2))
417 select case (this%lasers(il)%field)
419 safe_allocate(this%lasers(il)%v(1:mesh%np_part))
420 this%lasers(il)%v =
m_zero
422 call mesh_r(mesh, ip, rr, coords = xx(1:space%dim))
423 xx(space%dim+1:3) =
m_zero
425 this%lasers(il)%v(ip) = pot_re
431 safe_allocate(this%lasers(il)%a(1:mesh%np_part, 1:3))
432 this%lasers(il)%a =
m_zero
434 xx(1:space%dim) = mesh%x(:, ip)
435 xx(space%dim+1:3) =
m_zero
439 select case (space%dim)
441 this%lasers(il)%a(ip, 1:2) = (/xx(2), -xx(1)/) * sign(
m_one, real(this%lasers(il)%pol(3)))
443 this%lasers(il)%a(ip, :) = (/ xx(2)*real(this%lasers(il)%pol(3)) - xx(3)*real(this%lasers(il)%pol(2)), &
444 xx(3)*real(this%lasers(il)%pol(1)) - xx(1)*real(this%lasers(il)%pol(3)), &
445 xx(1)*real(this%lasers(il)%pol(2)) - xx(2)*real(this%lasers(il)%pol(1)) /)
447 message(1) =
"Magnetic fields only allowed in 2 or 3D."
451 this%lasers(il)%a = -
m_half * this%lasers(il)%a
470 if (kpoints%use_symmetries)
then
473 do il = 1, this%no_lasers
475 message(1) =
"The lasers break (at least) one of the symmetries used to reduce the k-points ."
476 message(2) =
"Set SymmetryBreakDir accordingly to your laser fields."
488 type(
lasers_t),
intent(inout) :: this
499 class(
lasers_t),
intent(inout) :: this
505 safe_deallocate_a(this%e)
506 safe_deallocate_a(this%b)
507 safe_deallocate_a(this%integrated_nondipole_afield)
509 do il = 1, this%no_lasers
510 safe_deallocate_a(this%lasers(il)%pol)
511 call tdf_end(this%lasers(il)%f)
512 call tdf_end(this%lasers(il)%phi)
513 select case (this%lasers(il)%field)
515 safe_deallocate_a(this%lasers(il)%v)
517 safe_deallocate_a(this%lasers(il)%a)
519 safe_deallocate_a(this%lasers(il)%prop)
521 safe_deallocate_a(this%lasers)
529 type(
laser_t),
intent(in) :: laser
540 class(
lasers_t),
intent(in) :: partner
541 class(interaction_surrogate_t),
intent(inout) :: interaction
545 select type (interaction)
546 type is (lorentz_force_t)
549 message(1) =
"Unsupported interaction."
550 call messages_fatal(1, namespace=partner%namespace)
558 class(
lasers_t),
intent(inout) :: this
559 character(len=*),
intent(in) :: label
561 type(quantity_t),
pointer :: quantity
566 if (
allocated(this%lasers))
then
569 call messages_not_implemented(
"Laser vector potentials and scalar potentials in multi-system framework", &
570 namespace=this%namespace)
574 quantity => this%quantities%get(label)
578 do il = 1, this%no_lasers
580 call laser_field(this%lasers(il), this%e, quantity%iteration%value())
586 do il = 1, this%no_lasers
588 call laser_field(this%lasers(il), this%b, quantity%iteration%value())
593 message(1) =
"Incompatible quantity."
594 call messages_fatal(1, namespace=this%namespace)
602 class(
lasers_t),
intent(inout) :: partner
603 class(interaction_surrogate_t),
intent(inout) :: interaction
609 select type (interaction)
610 type is (lorentz_force_t)
611 do ip = 1, interaction%system_np
612 interaction%partner_e_field(:, ip) = partner%e
613 interaction%partner_b_field(:, ip) = partner%b
616 message(1) =
"Unsupported interaction."
617 call messages_fatal(1, namespace=partner%namespace)
624 integer pure elemental function
laser_kind(laser)
625 type(
laser_t),
intent(in) :: laser
636 type(
laser_t),
intent(in) :: laser
637 complex(real64) :: pol(3)
649 type(
lasers_t),
intent(in) :: lasers
650 logical :: isnondipole
653 isnondipole = .false.
654 if(
allocated(lasers%integrated_nondipole_afield)) isnondipole = .
true.
662 type(
lasers_t),
intent(inout) :: this
663 real(real64),
intent(in) :: ndfield(:)
664 real(real64),
intent(in) :: nd_integration_time
670 this%integrated_nondipole_afield(1:dim) = ndfield(1:dim)
671 this%nd_integration_time = nd_integration_time
679 type(
laser_t),
intent(in) :: laser
680 type(tdf_t),
intent(inout) :: ff
683 call tdf_copy(ff, laser%f)
692 type(
laser_t),
intent(inout) :: laser
693 type(tdf_t),
intent(inout) :: ff
697 call tdf_end(laser%f)
698 call tdf_copy(laser%f, ff)
707 type(
laser_t),
intent(in) :: laser
708 type(tdf_t),
intent(inout) :: phi
711 call tdf_copy(phi, laser%phi)
720 type(
laser_t),
intent(inout) :: laser
721 type(tdf_t),
intent(inout) :: phi
725 call tdf_end(laser%phi)
726 call tdf_copy(laser%phi, phi)
735 type(
laser_t),
intent(inout) :: laser
739 call tdf_init(laser%phi)
747 type(
laser_t),
intent(inout) :: laser
748 integer,
intent(in) :: ii
749 real(real64),
intent(in) :: xx
752 call tdf_set_numerical(laser%f, ii, xx)
761 type(
laser_t),
intent(inout) :: laser
762 real(real64),
intent(in) :: omega
774 type(
laser_t),
intent(inout) :: laser
775 complex(real64),
intent(in) :: pol(:)
795 type(
laser_t),
intent(inout) :: laser
796 real(real64),
intent(in) :: dt
797 integer,
intent(in) :: max_iter
798 real(real64),
intent(in) :: omegamax
801 real(real64) :: tt, fj, phi
803 push_sub(lasers_to_numerical_all)
805 call tdf_to_numerical(laser%f, max_iter, dt, omegamax)
806 do iter = 1, max_iter + 1
808 fj = tdf(laser%f, iter)
809 phi = tdf(laser%phi, tt)
810 call tdf_set_numerical(laser%f, iter, fj*
cos(laser%omega*tt+phi))
812 call tdf_end(laser%phi)
813 call tdf_init_cw(laser%phi, m_zero, m_zero)
816 pop_sub(lasers_to_numerical_all)
826 type(
laser_t),
intent(inout) :: laser
827 real(real64),
intent(in) :: dt
828 integer,
intent(in) :: max_iter
829 real(real64),
intent(in) :: omegamax
831 push_sub(lasers_to_numerical)
833 call tdf_to_numerical(laser%f, max_iter, dt, omegamax)
834 call tdf_to_numerical(laser%phi, max_iter, dt, omegamax)
836 pop_sub(lasers_to_numerical)
842 type(
laser_t),
intent(in) :: lasers(:)
843 type(namespace_t),
intent(in) :: namespace
844 real(real64),
optional,
intent(in) :: dt
845 integer,
optional,
intent(in) :: max_iter
846 integer,
optional,
intent(in) :: iunit
848 real(real64) :: tt, fluence, max_intensity, intensity, dt_, field(3), up, maxfield,tmp
849 integer :: il, iter, no_l, max_iter_
857 if (
present(dt))
then
860 dt_ = tdf_dt(lasers(il)%f)
862 if (
present(max_iter))
then
865 max_iter_ = tdf_niter(lasers(il)%f)
868 write(message(1),
'(i2,a)') il,
':'
869 select case (lasers(il)%field)
871 message(2) =
' Electric Field.'
873 message(2) =
' Magnetic Field.'
875 message(2) =
' Vector Potential.'
877 message(2) =
' Scalar Potential.'
879 call messages_info(2, iunit=iunit, namespace=namespace)
882 write(message(1),
'(3x,a,3(a1,f7.4,a1,f7.4,a1))')
'Polarization: ', &
883 '(', real(lasers(il)%pol(1), real64),
',', aimag(lasers(il)%pol(1)),
'), ', &
884 '(', real(lasers(il)%pol(2), real64),
',', aimag(lasers(il)%pol(2)),
'), ', &
885 '(', real(lasers(il)%pol(3), real64),
',', aimag(lasers(il)%pol(3)),
')'
886 call messages_info(1, iunit=iunit, namespace=namespace)
889 write(message(1),
'(3x,a,f14.8,3a)')
'Carrier frequency = ', &
890 units_from_atomic(units_out%energy, lasers(il)%omega), &
891 ' [', trim(units_abbrev(units_out%energy)),
']'
892 message(2) =
' Envelope: '
893 call messages_info(2, iunit=iunit, namespace=namespace)
894 call tdf_write(lasers(il)%f, iunit)
896 if (.not. tdf_is_empty(lasers(il)%phi))
then
897 message(1) =
' Phase: '
898 call messages_info(1, iunit=iunit, namespace=namespace)
899 call tdf_write(lasers(il)%phi, iunit)
908 max_intensity = m_zero
910 do iter = 1, max_iter_
913 intensity = 5.4525289841210_real64*sum(field**2)
914 fluence = fluence + intensity
915 if (intensity > max_intensity) max_intensity = intensity
917 tmp = sum(field(:)**2)
918 if (tmp > maxfield) maxfield = tmp
920 fluence = fluence * dt_
922 write(message(1),
'(a,es17.6,3a)')
' Peak intensity = ', max_intensity,
' [a.u]'
923 write(message(2),
'(a,es17.6,3a)')
' = ', &
924 max_intensity * 6.4364086e+15_real64,
' [W/cm^2]'
925 write(message(3),
'(a,es17.6,a)')
' Int. intensity = ', fluence,
' [a.u]'
926 write(message(4),
'(a,es17.6,a)')
' Fluence = ', &
927 fluence / 5.4525289841210_real64 ,
' [a.u]'
928 call messages_info(4, iunit=iunit, namespace=namespace)
930 if (abs(lasers(il)%omega) > m_epsilon)
then
937 up = maxfield/(4*lasers(il)%omega**2)
939 write(message(1),
'(a,es17.6,3a)')
' Ponderomotive energy = ', &
940 units_from_atomic(units_out%energy, up) ,&
941 ' [', trim(units_abbrev(units_out%energy)),
']'
942 call messages_info(1, iunit=iunit, namespace=namespace)
955 type(
laser_t),
intent(in) :: laser
956 class(mesh_t),
intent(in) :: mesh
957 real(real64),
intent(inout) :: pot(:)
958 real(real64),
optional,
intent(in) :: time
960 complex(real64) :: amp
962 real(real64) :: field(3)
966 if (
present(time))
then
967 amp = tdf(laser%f, time) *
exp(m_zi * (laser%omega * time + tdf(laser%phi, time)))
972 select case (laser%field)
974 call lalg_axpy(mesh%np, real(amp, real64), laser%v, pot)
976 field(:) = real(amp * laser%pol(:), real64)
979 pot(ip) = pot(ip) + sum(field(1:mesh%box%dim) * mesh%x(1:mesh%box%dim, ip))
990 type(
laser_t),
intent(in) :: laser
991 type(mesh_t),
intent(in) :: mesh
992 real(real64),
intent(inout) :: aa(:, :)
993 real(real64),
optional,
intent(in) :: time
1000 if (
present(time))
then
1001 amp = tdf(laser%f, time)*
cos((laser%omega*time + tdf(laser%phi, time)))
1002 do idir = 1, mesh%box%dim
1004 aa(ip, idir) = aa(ip, idir) + amp*laser%a(ip, idir)
1008 do idir = 1, mesh%box%dim
1010 aa(ip, idir) = aa(ip, idir) + laser%a(ip, idir)
1027 type(
laser_t),
intent(in) :: laser
1028 real(real64),
intent(inout) :: field(:)
1029 real(real64),
optional,
intent(in) :: time
1032 complex(real64) :: amp
1038 if (
present(time))
then
1039 amp = tdf(laser%f, time) *
exp(m_zi * (laser%omega * time + tdf(laser%phi, time)))
1047 field(1) = field(1) + real(amp, real64)
1049 field(1:dim) = field(1:dim) + real(amp*laser%pol(1:dim), real64)
1063 real(real64),
intent(out) :: field(:)
1064 real(real64),
intent(in) :: time
1066 real(real64) :: a0(3)
1067 real(real64) :: e0(3)
1074 field(1:dim) = this%integrated_nondipole_afield(1:dim)
1075 if (time - this%nd_integration_time < 0)
then
1078 do iter = 1, nint((time-this%nd_integration_time)/this%nd_integration_step)
1079 do ilaser = 1, this%no_lasers
1081 do jlaser = 1, this%no_lasers
1083 if(
allocated(this%lasers(jlaser)%prop))
then
1086 iter*this%nd_integration_step+this%nd_integration_time)
1088 iter*this%nd_integration_step+this%nd_integration_time, this%nd_integration_step)
1090 field(1:dim) = field(1:dim) - m_one/(p_c) * this%nd_integration_step &
1091 * dot_product(a0,e0) * this%lasers(jlaser)%prop(1:dim)
1103 type(
laser_t),
intent(in) :: laser
1104 real(real64),
intent(out) :: field(:)
1105 real(real64),
intent(in) :: time
1106 real(real64),
intent(in) :: dt
1109 real(real64),
allocatable :: field1(:), field2(:)
1115 select case (laser%field)
1120 safe_allocate(field1(1:dim))
1121 safe_allocate(field2(1:dim))
1126 field = - (field2 - field1) / (m_two * p_c * dt)
1127 safe_deallocate_a(field1)
1128 safe_deallocate_a(field2)
1140 class(partner_list_t),
intent(inout) :: partners
1141 type(namespace_t),
intent(in) :: namespace
1153 if (parse_is_defined(namespace,
'MillerIndicesBasis'))
then
1154 call messages_not_implemented(
"MillerIndicesBasis with load_lasers routine")
1159 do il = 1, lasers%no_lasers
1160 lasers%lasers(il)%pol(:) = lasers%lasers(il)%pol(:)/
sqrt(sum(abs(lasers%lasers(il)%pol(:))**2))
1163 call lasers%quantities%add(quantity_t(
"E field", always_available = .
true., updated_on_demand = .
true., iteration =
clock_t()))
1164 call lasers%quantities%add(quantity_t(
"B field", always_available = .
true., updated_on_demand = .
true., iteration =
clock_t()))
1166 lasers%supported_interactions_as_partner = [lorentz_force]
1168 if (lasers%no_lasers > 0)
then
1169 call partners%add(lasers)
1171 safe_deallocate_p(lasers)
double exp(double __x) __attribute__((__nothrow__
double sqrt(double __x) __attribute__((__nothrow__
double cos(double __x) __attribute__((__nothrow__
real(real64), parameter, public m_zero
complex(real64), parameter, public m_z0
real(real64), parameter, public m_epsilon
complex(real64), parameter, public m_z1
real(real64), parameter, public m_half
real(real64), parameter, public m_one
This module defines classes and functions for interaction partners.
subroutine, public kpoints_to_absolute(latt, kin, kout)
subroutine, public load_lasers(partners, namespace)
complex(real64) function, dimension(3), public laser_polarization(laser)
subroutine, public laser_set_phi(laser, phi)
subroutine, public lasers_check_symmetries(this, kpoints)
subroutine lasers_copy_quantities_to_interaction(partner, interaction)
subroutine, public laser_to_numerical_all(laser, dt, max_iter, omegamax)
The td functions that describe the laser field are transformed to a "numerical" representation (i....
subroutine, public laser_vector_potential(laser, mesh, aa, time)
subroutine, public lasers_nondipole_laser_field_step(this, field, time)
Retrieves the NDSFA vector_potential correction. The nondipole field is obtained for consecutive time...
subroutine, public lasers_parse_external_fields(this)
subroutine, public lasers_set_nondipole_parameters(this, ndfield, nd_integration_time)
Set parameters for nondipole SFA calculation.
subroutine lasers_update_quantity(this, label)
subroutine, public laser_get_f(laser, ff)
subroutine, public laser_set_f(laser, ff)
logical function, public lasers_with_nondipole_field(lasers)
Check if a nondipole SFA correction should be computed for the given laser.
subroutine, public laser_write_info(lasers, namespace, dt, max_iter, iunit)
subroutine, public laser_set_empty_phi(laser)
real(real64) function, public laser_carrier_frequency(laser)
integer, parameter, public e_field_electric
integer, parameter, public e_field_vector_potential
subroutine, public laser_to_numerical(laser, dt, max_iter, omegamax)
The td functions that describe the laser field are transformed to a "numerical" representation (i....
subroutine, public laser_electric_field(laser, field, time, dt)
Returns a vector with the electric field, no matter whether the laser is described directly as an ele...
subroutine, public lasers_generate_potentials(this, mesh, space, latt)
subroutine lasers_init_interaction_as_partner(partner, interaction)
subroutine lasers_finalize(this)
subroutine, public laser_potential(laser, mesh, pot, time)
class(lasers_t) function, pointer lasers_constructor(namespace)
integer, parameter, public e_field_scalar_potential
integer pure elemental function, public laser_kind(laser)
subroutine, public laser_set_frequency(laser, omega)
subroutine, public laser_field(laser, field, time)
Retrieves the value of either the electric or the magnetic field. If the laser is given by a scalar p...
subroutine, public laser_set_polarization(laser, pol)
subroutine, public laser_set_f_value(laser, ii, xx)
subroutine, public laser_get_phi(laser, phi)
subroutine lasers_deallocate(this)
integer, parameter, public e_field_magnetic
This module is intended to contain "only mathematical" functions and procedures.
This module defines the meshes, which are used in Octopus.
pure subroutine, public mesh_r(mesh, ip, rr, origin, coords)
return the distance to the origin for a given grid point
subroutine, public messages_warning(no_lines, all_nodes, namespace)
subroutine, public messages_obsolete_variable(namespace, name, rep)
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
subroutine, public parse_block_string(blk, l, c, res, convert_to_c)
integer function, public parse_block(namespace, name, blk, check_varinfo_)
This module defines the quantity_t class and the IDs for quantities, which can be exposed by a system...
integer pure function, public symmetries_identity_index(this)
real(real64), public symprec
integer pure function, public symmetries_number(this)
subroutine, public tdf_end(f)
subroutine, public tdf_init(f)
subroutine, public tdf_read(f, namespace, function_name, ierr)
This function initializes "f" from the TDFunctions block.
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
This module defines the unit system, used for input and output.
abstract class for general interaction partners
Describes mesh distribution to nodes.