30 use,
intrinsic :: iso_fortran_env
84 integer,
public,
parameter :: &
93 integer :: field = e_field_none
94 complex(real64),
allocatable :: pol(:)
95 real(real64),
allocatable :: prop(:)
98 real(real64) :: omega =
m_zero
100 real(real64),
allocatable :: v(:)
101 real(real64),
allocatable :: a(:, :)
107 integer,
public :: no_lasers
108 type(laser_t),
allocatable,
public :: lasers(:)
109 character(len=200) :: scalar_pot_expression
110 character(len=200) :: envelope_expression
111 character(len=200) :: phase_expression
113 real(real64),
allocatable :: e(:)
114 real(real64),
allocatable :: b(:)
115 real(real64),
allocatable :: integrated_nondipole_afield(:)
116 real(real64) :: nd_integration_time
117 real(real64) :: nd_integration_step
133 class(lasers_t),
pointer :: this
134 type(namespace_t),
intent(in) :: namespace
140 this%namespace =
namespace_t(
"Lasers", parent=namespace)
142 safe_allocate(this%e(1:3))
143 safe_allocate(this%b(1:3))
151 class(lasers_t),
intent(inout) :: this
154 integer :: il, jj, ierr, k
155 real(real64) :: omega0
156 complex(real64) :: cprop(3)
258 if (
parse_block(this%namespace,
'TDExternalFields', blk) == 0)
then
260 safe_allocate(this%lasers(1:this%no_lasers))
262 do il = 1, this%no_lasers
263 safe_allocate(this%lasers(il)%pol(1:3))
264 this%lasers(il)%pol =
m_z0
268 select case (this%lasers(il)%field)
272 this%lasers(il)%pol =
m_z1
283 this%lasers(il)%omega = omega0
286 call tdf_read(this%lasers(il)%f, this%namespace, trim(this%envelope_expression), ierr)
291 call tdf_read(this%lasers(il)%phi, this%namespace, trim(this%phase_expression), ierr)
293 write(
message(1),
'(3A)')
'Error in the "', trim(this%envelope_expression), &
294 '" field defined in the TDExternalFields block:'
295 write(
message(2),
'(3A)')
'Time-dependent phase function "', trim(this%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%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, :) = (/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
568 call messages_not_implemented(
"Laser vector potentials and scalar potentials in multi-system framework", &
569 namespace=this%namespace)
572 quantity => this%quantities%get(label)
576 do il = 1, this%no_lasers
578 call laser_field(this%lasers(il), this%e, quantity%iteration%value())
584 do il = 1, this%no_lasers
586 call laser_field(this%lasers(il), this%b, quantity%iteration%value())
591 message(1) =
"Incompatible quantity."
592 call messages_fatal(1, namespace=this%namespace)
600 class(
lasers_t),
intent(inout) :: partner
601 class(interaction_surrogate_t),
intent(inout) :: interaction
607 select type (interaction)
608 type is (lorentz_force_t)
609 do ip = 1, interaction%system_np
610 interaction%partner_e_field(:, ip) = partner%e
611 interaction%partner_b_field(:, ip) = partner%b
614 message(1) =
"Unsupported interaction."
615 call messages_fatal(1, namespace=partner%namespace)
622 integer pure elemental function
laser_kind(laser)
623 type(
laser_t),
intent(in) :: laser
634 type(
laser_t),
intent(in) :: laser
635 complex(real64) :: pol(3)
647 type(
lasers_t),
intent(in) :: lasers
648 logical :: isnondipole
651 isnondipole = .false.
652 if(
allocated(lasers%integrated_nondipole_afield)) isnondipole = .
true.
660 type(
lasers_t),
intent(inout) :: this
661 real(real64),
intent(in) :: ndfield(:)
662 real(real64),
intent(in) :: nd_integration_time
667 this%integrated_nondipole_afield(1:dim) = ndfield(1:dim)
668 this%nd_integration_time = nd_integration_time
675 type(
laser_t),
intent(in) :: laser
676 type(tdf_t),
intent(inout) :: ff
679 call tdf_copy(ff, laser%f)
688 type(
laser_t),
intent(inout) :: laser
689 type(tdf_t),
intent(inout) :: ff
693 call tdf_end(laser%f)
694 call tdf_copy(laser%f, ff)
703 type(
laser_t),
intent(in) :: laser
704 type(tdf_t),
intent(inout) :: phi
707 call tdf_copy(phi, laser%phi)
716 type(
laser_t),
intent(inout) :: laser
717 type(tdf_t),
intent(inout) :: phi
721 call tdf_end(laser%phi)
722 call tdf_copy(laser%phi, phi)
731 type(
laser_t),
intent(inout) :: laser
735 call tdf_init(laser%phi)
743 type(
laser_t),
intent(inout) :: laser
744 integer,
intent(in) :: ii
745 real(real64),
intent(in) :: xx
748 call tdf_set_numerical(laser%f, ii, xx)
757 type(
laser_t),
intent(inout) :: laser
758 real(real64),
intent(in) :: omega
770 type(
laser_t),
intent(inout) :: laser
771 complex(real64),
intent(in) :: pol(:)
791 type(
laser_t),
intent(inout) :: laser
792 real(real64),
intent(in) :: dt
793 integer,
intent(in) :: max_iter
794 real(real64),
intent(in) :: omegamax
797 real(real64) :: tt, fj, phi
799 push_sub(lasers_to_numerical_all)
801 call tdf_to_numerical(laser%f, max_iter, dt, omegamax)
802 do iter = 1, max_iter + 1
804 fj = tdf(laser%f, iter)
805 phi = tdf(laser%phi, tt)
806 call tdf_set_numerical(laser%f, iter, fj*
cos(laser%omega*tt+phi))
808 call tdf_end(laser%phi)
809 call tdf_init_cw(laser%phi, m_zero, m_zero)
812 pop_sub(lasers_to_numerical_all)
822 type(
laser_t),
intent(inout) :: laser
823 real(real64),
intent(in) :: dt
824 integer,
intent(in) :: max_iter
825 real(real64),
intent(in) :: omegamax
827 push_sub(lasers_to_numerical)
829 call tdf_to_numerical(laser%f, max_iter, dt, omegamax)
830 call tdf_to_numerical(laser%phi, max_iter, dt, omegamax)
832 pop_sub(lasers_to_numerical)
838 type(
laser_t),
intent(in) :: lasers(:)
839 type(namespace_t),
intent(in) :: namespace
840 real(real64),
optional,
intent(in) :: dt
841 integer,
optional,
intent(in) :: max_iter
842 integer,
optional,
intent(in) :: iunit
844 real(real64) :: tt, fluence, max_intensity, intensity, dt_, field(3), up, maxfield,tmp
845 integer :: il, iter, no_l, max_iter_
853 if (
present(dt))
then
856 dt_ = tdf_dt(lasers(il)%f)
858 if (
present(max_iter))
then
861 max_iter_ = tdf_niter(lasers(il)%f)
864 write(message(1),
'(i2,a)') il,
':'
865 select case (lasers(il)%field)
867 message(2) =
' Electric Field.'
869 message(2) =
' Magnetic Field.'
871 message(2) =
' Vector Potential.'
873 message(2) =
' Scalar Potential.'
875 call messages_info(2, iunit=iunit, namespace=namespace)
878 write(message(1),
'(3x,a,3(a1,f7.4,a1,f7.4,a1))')
'Polarization: ', &
879 '(', real(lasers(il)%pol(1), real64),
',', aimag(lasers(il)%pol(1)),
'), ', &
880 '(', real(lasers(il)%pol(2), real64),
',', aimag(lasers(il)%pol(2)),
'), ', &
881 '(', real(lasers(il)%pol(3), real64),
',', aimag(lasers(il)%pol(3)),
')'
882 call messages_info(1, iunit=iunit, namespace=namespace)
885 write(message(1),
'(3x,a,f14.8,3a)')
'Carrier frequency = ', &
886 units_from_atomic(units_out%energy, lasers(il)%omega), &
887 ' [', trim(units_abbrev(units_out%energy)),
']'
888 message(2) =
' Envelope: '
889 call messages_info(2, iunit=iunit, namespace=namespace)
890 call tdf_write(lasers(il)%f, iunit)
892 if (.not. tdf_is_empty(lasers(il)%phi))
then
893 message(1) =
' Phase: '
894 call messages_info(1, iunit=iunit, namespace=namespace)
895 call tdf_write(lasers(il)%phi, iunit)
904 max_intensity = m_zero
906 do iter = 1, max_iter_
909 intensity = 5.4525289841210_real64*sum(field**2)
910 fluence = fluence + intensity
911 if (intensity > max_intensity) max_intensity = intensity
913 tmp = sum(field(:)**2)
914 if (tmp > maxfield) maxfield = tmp
916 fluence = fluence * dt_
918 write(message(1),
'(a,es17.6,3a)')
' Peak intensity = ', max_intensity,
' [a.u]'
919 write(message(2),
'(a,es17.6,3a)')
' = ', &
920 max_intensity * 6.4364086e+15_real64,
' [W/cm^2]'
921 write(message(3),
'(a,es17.6,a)')
' Int. intensity = ', fluence,
' [a.u]'
922 write(message(4),
'(a,es17.6,a)')
' Fluence = ', &
923 fluence / 5.4525289841210_real64 ,
' [a.u]'
924 call messages_info(4, iunit=iunit, namespace=namespace)
926 if (abs(lasers(il)%omega) > m_epsilon)
then
933 up = maxfield/(4*lasers(il)%omega**2)
935 write(message(1),
'(a,es17.6,3a)')
' Ponderomotive energy = ', &
936 units_from_atomic(units_out%energy, up) ,&
937 ' [', trim(units_abbrev(units_out%energy)),
']'
938 call messages_info(1, iunit=iunit, namespace=namespace)
951 type(
laser_t),
intent(in) :: laser
952 class(mesh_t),
intent(in) :: mesh
953 real(real64),
intent(inout) :: pot(:)
954 real(real64),
optional,
intent(in) :: time
956 complex(real64) :: amp
958 real(real64) :: field(3)
962 if (
present(time))
then
963 amp = tdf(laser%f, time) *
exp(m_zi * (laser%omega * time + tdf(laser%phi, time)))
968 select case (laser%field)
970 pot(1:mesh%np) = pot(1:mesh%np) + real(amp, real64) * laser%v(1:mesh%np)
972 field(:) = real(amp * laser%pol(:), real64)
975 pot(ip) = pot(ip) + sum(field(1:mesh%box%dim) * mesh%x(ip, 1:mesh%box%dim))
986 type(
laser_t),
intent(in) :: laser
987 type(mesh_t),
intent(in) :: mesh
988 real(real64),
intent(inout) :: aa(:, :)
989 real(real64),
optional,
intent(in) :: time
996 if (
present(time))
then
997 amp = tdf(laser%f, time)*
cos((laser%omega*time + tdf(laser%phi, time)))
998 do idir = 1, mesh%box%dim
1000 aa(ip, idir) = aa(ip, idir) + amp*laser%a(ip, idir)
1004 do idir = 1, mesh%box%dim
1006 aa(ip, idir) = aa(ip, idir) + laser%a(ip, idir)
1023 type(
laser_t),
intent(in) :: laser
1024 real(real64),
intent(inout) :: field(:)
1025 real(real64),
optional,
intent(in) :: time
1028 complex(real64) :: amp
1034 if (
present(time))
then
1035 amp = tdf(laser%f, time) *
exp(m_zi * (laser%omega * time + tdf(laser%phi, time)))
1043 field(1) = field(1) + real(amp, real64)
1045 field(1:dim) = field(1:dim) + real(amp*laser%pol(1:dim), real64)
1059 real(real64),
intent(out) :: field(:)
1060 real(real64),
intent(in) :: time
1062 real(real64) :: a0(3)
1063 real(real64) :: e0(3)
1070 field(1:dim) = this%integrated_nondipole_afield(1:dim)
1071 if (time - this%nd_integration_time < 0)
then
1074 do iter = 1, nint((time-this%nd_integration_time)/this%nd_integration_step)
1075 do ilaser = 1, this%no_lasers
1077 do jlaser = 1, this%no_lasers
1079 if(
allocated(this%lasers(jlaser)%prop))
then
1082 iter*this%nd_integration_step+this%nd_integration_time)
1084 iter*this%nd_integration_step+this%nd_integration_time, this%nd_integration_step)
1086 field(1:dim) = field(1:dim) - m_one/(p_c) * this%nd_integration_step &
1087 * dot_product(a0,e0) * this%lasers(jlaser)%prop(1:dim)
1099 type(
laser_t),
intent(in) :: laser
1100 real(real64),
intent(out) :: field(:)
1101 real(real64),
intent(in) :: time
1102 real(real64),
intent(in) :: dt
1105 real(real64),
allocatable :: field1(:), field2(:)
1111 select case (laser%field)
1116 safe_allocate(field1(1:dim))
1117 safe_allocate(field2(1:dim))
1122 field = - (field2 - field1) / (m_two * p_c * dt)
1123 safe_deallocate_a(field1)
1124 safe_deallocate_a(field2)
1136 class(partner_list_t),
intent(inout) :: partners
1137 type(namespace_t),
intent(in) :: namespace
1149 if (parse_is_defined(namespace,
'MillerIndicesBasis'))
then
1150 call messages_not_implemented(
"MillerIndicesBasis with load_lasers routine")
1155 do il = 1, lasers%no_lasers
1156 lasers%lasers(il)%pol(:) = lasers%lasers(il)%pol(:)/
sqrt(sum(abs(lasers%lasers(il)%pol(:))**2))
1159 call lasers%quantities%add(quantity_t(
"E field", always_available = .
true., updated_on_demand = .
true., iteration =
clock_t()))
1160 call lasers%quantities%add(quantity_t(
"B field", always_available = .
true., updated_on_demand = .
true., iteration =
clock_t()))
1162 lasers%supported_interactions_as_partner = [lorentz_force]
1164 if (lasers%no_lasers > 0)
then
1165 call partners%add(lasers)
1167 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)
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.