30 use,
intrinsic :: iso_fortran_env
83 integer,
public,
parameter :: &
92 integer :: field = e_field_none
93 complex(real64),
allocatable :: pol(:)
94 real(real64),
allocatable :: prop(:)
97 real(real64) :: omega =
m_zero
99 real(real64),
allocatable :: v(:)
100 real(real64),
allocatable :: a(:, :)
106 integer,
public :: no_lasers
107 type(laser_t),
allocatable,
public :: lasers(:)
108 character(len=200) :: scalar_pot_expression
109 character(len=200) :: envelope_expression
110 character(len=200) :: phase_expression
112 real(real64),
allocatable :: e(:)
113 real(real64),
allocatable :: b(:)
114 real(real64),
allocatable :: integrated_nondipole_afield(:)
115 real(real64) :: nd_integration_time
116 real(real64) :: nd_integration_step
132 class(lasers_t),
pointer :: this
133 type(namespace_t),
intent(in) :: namespace
139 this%namespace =
namespace_t(
"Lasers", parent=namespace)
141 safe_allocate(this%e(1:3))
142 safe_allocate(this%b(1:3))
150 class(lasers_t),
intent(inout) :: this
153 integer :: il, jj, ierr, k
154 real(real64) :: omega0
155 complex(real64) :: cprop(3)
257 if (
parse_block(this%namespace,
'TDExternalFields', blk) == 0)
then
259 safe_allocate(this%lasers(1:this%no_lasers))
261 do il = 1, this%no_lasers
262 safe_allocate(this%lasers(il)%pol(1:3))
263 this%lasers(il)%pol =
m_z0
267 select case (this%lasers(il)%field)
271 this%lasers(il)%pol =
m_z1
282 this%lasers(il)%omega = omega0
285 call tdf_read(this%lasers(il)%f, this%namespace, trim(this%envelope_expression), ierr)
290 call tdf_read(this%lasers(il)%phi, this%namespace, trim(this%phase_expression), ierr)
292 write(
message(1),
'(3A)')
'Error in the "', trim(this%envelope_expression), &
293 '" field defined in the TDExternalFields block:'
294 write(
message(2),
'(3A)')
'Time-dependent phase function "', trim(this%phase_expression), &
304 safe_allocate(this%lasers(il)%prop(1:
size(cprop)))
305 do k = 1,
size(cprop)
309 if (any(abs(aimag(cprop)) >
m_epsilon))
then
310 write(
message(1),
'(3A)')
'Error in the "', trim(this%envelope_expression), &
311 '" field defined in the TDExternalFields block:'
312 write(
message(2),
'(A)')
'Propagation direction cannot be complex.'
315 this%lasers(il)%prop = real(cprop, real64)
316 if (.not.
allocated(this%integrated_nondipole_afield))
then
317 safe_allocate(this%integrated_nondipole_afield(1:
size(cprop)))
318 this%integrated_nondipole_afield(1:3)=
m_zero
319 this%nd_integration_time=
m_zero
331 call parse_variable(this%namespace,
'NDSFATimeIntegrationStep', 0.01_real64, this%nd_integration_step)
333 if (this%nd_integration_step == 0.01)
then
334 message(1) =
"The default timestep of 0.01 is utilized for the nondipole SFA integration."
335 message(2) =
"Be aware that this should be at least an order of magniude less than the TDtimestep"
349 class(
lasers_t),
intent(inout) :: this
350 class(
mesh_t),
intent(in) :: mesh
351 class(
space_t),
intent(in) :: space
355 integer :: il, ip, idir, idir2
356 real(real64) :: rr, pot_re, pot_im, xx(3)
357 real(real64) :: miller(space%dim,space%dim), miller_red(space%dim,space%dim)
361 do il = 1, this%no_lasers
394 if (
parse_block(this%namespace,
'MillerIndicesBasis', blk2) == 0)
then
395 if(.not. space%is_periodic())
then
396 write(
message(1),
'(a)')
'MillerIndicesBasis can only be used for periodic systems.'
400 do idir = 1, space%dim
401 do idir2 = 1, space%dim
408 this%lasers(il)%pol = matmul(miller, this%lasers(il)%pol)
412 this%lasers(il)%pol(:) = this%lasers(il)%pol(:)/
sqrt(sum(abs(this%lasers(il)%pol(:))**2))
414 select case (this%lasers(il)%field)
416 safe_allocate(this%lasers(il)%v(1:mesh%np_part))
417 this%lasers(il)%v =
m_zero
419 call mesh_r(mesh, ip, rr, coords = xx(1:space%dim))
420 xx(space%dim+1:3) =
m_zero
422 this%lasers(il)%v(ip) = pot_re
428 safe_allocate(this%lasers(il)%a(1:mesh%np_part, 1:3))
429 this%lasers(il)%a =
m_zero
431 xx(1:space%dim) = mesh%x(ip, :)
432 xx(space%dim+1:3) =
m_zero
436 select case (space%dim)
438 this%lasers(il)%a(ip, :) = (/xx(2), -xx(1)/) * sign(
m_one, real(this%lasers(il)%pol(3)))
440 this%lasers(il)%a(ip, :) = (/ xx(2)*real(this%lasers(il)%pol(3)) - xx(3)*real(this%lasers(il)%pol(2)), &
441 xx(3)*real(this%lasers(il)%pol(1)) - xx(1)*real(this%lasers(il)%pol(3)), &
442 xx(1)*real(this%lasers(il)%pol(2)) - xx(2)*real(this%lasers(il)%pol(1)) /)
444 message(1) =
"Magnetic fields only allowed in 2 or 3D."
448 this%lasers(il)%a = -
m_half * this%lasers(il)%a
467 if (kpoints%use_symmetries)
then
470 do il = 1, this%no_lasers
472 message(1) =
"The lasers break (at least) one of the symmetries used to reduce the k-points ."
473 message(2) =
"Set SymmetryBreakDir accordingly to your laser fields."
485 type(
lasers_t),
intent(inout) :: this
496 class(
lasers_t),
intent(inout) :: this
502 safe_deallocate_a(this%e)
503 safe_deallocate_a(this%b)
504 safe_deallocate_a(this%integrated_nondipole_afield)
506 do il = 1, this%no_lasers
507 safe_deallocate_a(this%lasers(il)%pol)
508 call tdf_end(this%lasers(il)%f)
509 call tdf_end(this%lasers(il)%phi)
510 select case (this%lasers(il)%field)
512 safe_deallocate_a(this%lasers(il)%v)
514 safe_deallocate_a(this%lasers(il)%a)
516 safe_deallocate_a(this%lasers(il)%prop)
518 safe_deallocate_a(this%lasers)
526 type(
laser_t),
intent(in) :: laser
537 class(
lasers_t),
intent(in) :: partner
538 class(interaction_surrogate_t),
intent(inout) :: interaction
542 select type (interaction)
543 type is (lorentz_force_t)
546 message(1) =
"Unsupported interaction."
547 call messages_fatal(1, namespace=partner%namespace)
555 class(
lasers_t),
intent(inout) :: this
556 integer,
intent(in) :: iq
564 call messages_not_implemented(
"Laser vector potentials and scalar potentials in multi-system framework", &
565 namespace=this%namespace)
571 do il = 1, this%no_lasers
573 call laser_field(this%lasers(il), this%e, this%quantities(iq)%iteration%value())
579 do il = 1, this%no_lasers
581 call laser_field(this%lasers(il), this%b, this%quantities(iq)%iteration%value())
586 message(1) =
"Incompatible quantity."
587 call messages_fatal(1, namespace=this%namespace)
595 class(
lasers_t),
intent(inout) :: partner
596 class(interaction_surrogate_t),
intent(inout) :: interaction
602 select type (interaction)
603 type is (lorentz_force_t)
604 do ip = 1, interaction%system_np
605 interaction%partner_e_field(:, ip) = partner%e
606 interaction%partner_b_field(:, ip) = partner%b
609 message(1) =
"Unsupported interaction."
610 call messages_fatal(1, namespace=partner%namespace)
617 integer pure elemental function laser_kind(laser)
630 complex(real64) :: pol(3)
642 type(
lasers_t),
intent(in) :: lasers
643 logical :: isnondipole
646 isnondipole = .false.
647 if(
allocated(lasers%integrated_nondipole_afield)) isnondipole = .
true.
655 type(
lasers_t),
intent(inout) :: this
656 real(real64),
intent(in) :: ndfield(:)
657 real(real64),
intent(in) :: nd_integration_time
662 this%integrated_nondipole_afield(1:dim) = ndfield(1:dim)
663 this%nd_integration_time = nd_integration_time
670 type(
laser_t),
intent(in) :: laser
671 type(tdf_t),
intent(inout) :: ff
674 call tdf_copy(ff, laser%f)
683 type(
laser_t),
intent(inout) :: laser
684 type(tdf_t),
intent(inout) :: ff
688 call tdf_end(laser%f)
689 call tdf_copy(laser%f, ff)
698 type(
laser_t),
intent(in) :: laser
699 type(tdf_t),
intent(inout) :: phi
702 call tdf_copy(phi, laser%phi)
711 type(
laser_t),
intent(inout) :: laser
712 type(tdf_t),
intent(inout) :: phi
716 call tdf_end(laser%phi)
717 call tdf_copy(laser%phi, phi)
726 type(
laser_t),
intent(inout) :: laser
730 call tdf_init(laser%phi)
738 type(
laser_t),
intent(inout) :: laser
739 integer,
intent(in) :: ii
740 real(real64),
intent(in) :: xx
743 call tdf_set_numerical(laser%f, ii, xx)
752 type(
laser_t),
intent(inout) :: laser
753 real(real64),
intent(in) :: omega
765 type(
laser_t),
intent(inout) :: laser
766 complex(real64),
intent(in) :: pol(:)
786 type(
laser_t),
intent(inout) :: laser
787 real(real64),
intent(in) :: dt
788 integer,
intent(in) :: max_iter
789 real(real64),
intent(in) :: omegamax
792 real(real64) :: tt, fj, phi
794 push_sub(lasers_to_numerical_all)
796 call tdf_to_numerical(laser%f, max_iter, dt, omegamax)
797 do iter = 1, max_iter + 1
799 fj = tdf(laser%f, iter)
800 phi = tdf(laser%phi, tt)
801 call tdf_set_numerical(laser%f, iter, fj*
cos(laser%omega*tt+phi))
803 call tdf_end(laser%phi)
804 call tdf_init_cw(laser%phi, m_zero, m_zero)
807 pop_sub(lasers_to_numerical_all)
817 type(
laser_t),
intent(inout) :: laser
818 real(real64),
intent(in) :: dt
819 integer,
intent(in) :: max_iter
820 real(real64),
intent(in) :: omegamax
822 push_sub(lasers_to_numerical)
824 call tdf_to_numerical(laser%f, max_iter, dt, omegamax)
825 call tdf_to_numerical(laser%phi, max_iter, dt, omegamax)
827 pop_sub(lasers_to_numerical)
833 type(
laser_t),
intent(in) :: lasers(:)
834 type(namespace_t),
intent(in) :: namespace
835 real(real64),
optional,
intent(in) :: dt
836 integer,
optional,
intent(in) :: max_iter
837 integer,
optional,
intent(in) :: iunit
839 real(real64) :: tt, fluence, max_intensity, intensity, dt_, field(3), up, maxfield,tmp
840 integer :: il, iter, no_l, max_iter_
848 if (
present(dt))
then
851 dt_ = tdf_dt(lasers(il)%f)
853 if (
present(max_iter))
then
856 max_iter_ = tdf_niter(lasers(il)%f)
859 write(message(1),
'(i2,a)') il,
':'
860 select case (lasers(il)%field)
862 message(2) =
' Electric Field.'
864 message(2) =
' Magnetic Field.'
866 message(2) =
' Vector Potential.'
868 message(2) =
' Scalar Potential.'
870 call messages_info(2, iunit=iunit, namespace=namespace)
873 write(message(1),
'(3x,a,3(a1,f7.4,a1,f7.4,a1))')
'Polarization: ', &
874 '(', real(lasers(il)%pol(1), real64),
',', aimag(lasers(il)%pol(1)),
'), ', &
875 '(', real(lasers(il)%pol(2), real64),
',', aimag(lasers(il)%pol(2)),
'), ', &
876 '(', real(lasers(il)%pol(3), real64),
',', aimag(lasers(il)%pol(3)),
')'
877 call messages_info(1, iunit=iunit, namespace=namespace)
880 write(message(1),
'(3x,a,f14.8,3a)')
'Carrier frequency = ', &
881 units_from_atomic(units_out%energy, lasers(il)%omega), &
882 ' [', trim(units_abbrev(units_out%energy)),
']'
883 message(2) =
' Envelope: '
884 call messages_info(2, iunit=iunit, namespace=namespace)
885 call tdf_write(lasers(il)%f, iunit)
887 if (.not. tdf_is_empty(lasers(il)%phi))
then
888 message(1) =
' Phase: '
889 call messages_info(1, iunit=iunit, namespace=namespace)
890 call tdf_write(lasers(il)%phi, iunit)
899 max_intensity = m_zero
901 do iter = 1, max_iter_
904 intensity = 5.4525289841210_real64*sum(field**2)
905 fluence = fluence + intensity
906 if (intensity > max_intensity) max_intensity = intensity
908 tmp = sum(field(:)**2)
909 if (tmp > maxfield) maxfield = tmp
911 fluence = fluence * dt_
913 write(message(1),
'(a,es17.6,3a)')
' Peak intensity = ', max_intensity,
' [a.u]'
914 write(message(2),
'(a,es17.6,3a)')
' = ', &
915 max_intensity * 6.4364086e+15_real64,
' [W/cm^2]'
916 write(message(3),
'(a,es17.6,a)')
' Int. intensity = ', fluence,
' [a.u]'
917 write(message(4),
'(a,es17.6,a)')
' Fluence = ', &
918 fluence / 5.4525289841210_real64 ,
' [a.u]'
919 call messages_info(4, iunit=iunit, namespace=namespace)
921 if (abs(lasers(il)%omega) > m_epsilon)
then
928 up = maxfield/(4*lasers(il)%omega**2)
930 write(message(1),
'(a,es17.6,3a)')
' Ponderomotive energy = ', &
931 units_from_atomic(units_out%energy, up) ,&
932 ' [', trim(units_abbrev(units_out%energy)),
']'
933 call messages_info(1, iunit=iunit, namespace=namespace)
946 type(
laser_t),
intent(in) :: laser
947 class(mesh_t),
intent(in) :: mesh
948 real(real64),
intent(inout) :: pot(:)
949 real(real64),
optional,
intent(in) :: time
951 complex(real64) :: amp
953 real(real64) :: field(3)
957 if (
present(time))
then
958 amp = tdf(laser%f, time) *
exp(m_zi * (laser%omega * time + tdf(laser%phi, time)))
963 select case (laser%field)
965 pot(1:mesh%np) = pot(1:mesh%np) + real(amp, real64) * laser%v(1:mesh%np)
967 field(:) = real(amp * laser%pol(:), real64)
970 pot(ip) = pot(ip) + sum(field(1:mesh%box%dim) * mesh%x(ip, 1:mesh%box%dim))
981 type(
laser_t),
intent(in) :: laser
982 type(mesh_t),
intent(in) :: mesh
983 real(real64),
intent(inout) :: aa(:, :)
984 real(real64),
optional,
intent(in) :: time
991 if (
present(time))
then
992 amp = real(tdf(laser%f, time)*
exp(m_zi*(laser%omega*time + tdf(laser%phi, time))), real64)
993 do idir = 1, mesh%box%dim
995 aa(ip, idir) = aa(ip, idir) + amp*laser%a(ip, idir)
999 do idir = 1, mesh%box%dim
1001 aa(ip, idir) = aa(ip, idir) + laser%a(ip, idir)
1018 type(
laser_t),
intent(in) :: laser
1019 real(real64),
intent(inout) :: field(:)
1020 real(real64),
optional,
intent(in) :: time
1023 complex(real64) :: amp
1029 if (
present(time))
then
1030 amp = tdf(laser%f, time) *
exp(m_zi * (laser%omega * time + tdf(laser%phi, time)))
1038 field(1) = field(1) + real(amp, real64)
1040 field(1:dim) = field(1:dim) + real(amp*laser%pol(1:dim), real64)
1054 real(real64),
intent(out) :: field(:)
1055 real(real64),
intent(in) :: time
1057 real(real64) :: a0(3)
1058 real(real64) :: e0(3)
1065 field(1:dim) = this%integrated_nondipole_afield(1:dim)
1066 if (time - this%nd_integration_time < 0)
then
1069 do iter = 1, nint((time-this%nd_integration_time)/this%nd_integration_step)
1070 do ilaser = 1, this%no_lasers
1072 do jlaser = 1, this%no_lasers
1074 if(
allocated(this%lasers(jlaser)%prop))
then
1077 iter*this%nd_integration_step+this%nd_integration_time)
1079 iter*this%nd_integration_step+this%nd_integration_time, this%nd_integration_step)
1081 field(1:dim) = field(1:dim) - m_one/(p_c) * this%nd_integration_step &
1082 * dot_product(a0,e0) * this%lasers(jlaser)%prop(1:dim)
1094 type(
laser_t),
intent(in) :: laser
1095 real(real64),
intent(out) :: field(:)
1096 real(real64),
intent(in) :: time
1097 real(real64),
intent(in) :: dt
1100 real(real64),
allocatable :: field1(:), field2(:)
1106 select case (laser%field)
1111 safe_allocate(field1(1:dim))
1112 safe_allocate(field2(1:dim))
1117 field = - (field2 - field1) / (m_two * p_c * dt)
1118 safe_deallocate_a(field1)
1119 safe_deallocate_a(field2)
1131 class(partner_list_t),
intent(inout) :: partners
1132 type(namespace_t),
intent(in) :: namespace
1144 if (parse_is_defined(namespace,
'MillerIndicesBasis'))
then
1145 call messages_not_implemented(
"MillerIndicesBasis with load_lasers routine")
1150 do il = 1, lasers%no_lasers
1151 lasers%lasers(il)%pol(:) = lasers%lasers(il)%pol(:)/
sqrt(sum(abs(lasers%lasers(il)%pol(:))**2))
1154 lasers%quantities(e_field)%always_available = .
true.
1155 lasers%quantities(e_field)%updated_on_demand = .
true.
1156 lasers%quantities(e_field)%iteration =
clock_t()
1157 lasers%quantities(b_field)%always_available = .
true.
1158 lasers%quantities(b_field)%updated_on_demand = .
true.
1159 lasers%quantities(b_field)%iteration =
clock_t()
1161 lasers%supported_interactions_as_partner = [lorentz_force]
1163 if (lasers%no_lasers > 0)
then
1164 call partners%add(lasers)
1166 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 lasers_update_quantity(this, iq)
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, 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 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)
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.
type(unit_system_t), public units_inp
the units systems for reading and writing
abstract class for general interaction partners
Describes mesh distribution to nodes.