Octopus
lasers.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
2!! Copyright (C) 2021 N. Tancogne-Dejean
3!!
4!! This program is free software; you can redistribute it and/or modify
5!! it under the terms of the GNU General Public License as published by
6!! the Free Software Foundation; either version 2, or (at your option)
7!! any later version.
8!!
9!! This program is distributed in the hope that it will be useful,
10!! but WITHOUT ANY WARRANTY; without even the implied warranty of
11!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12!! GNU General Public License for more details.
13!!
14!! You should have received a copy of the GNU General Public License
15!! along with this program; if not, write to the Free Software
16!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17!! 02110-1301, USA.
18!!
19
20#include "global.h"
21
22module lasers_oct_m
23 use clock_oct_m
24 use debug_oct_m
26 use global_oct_m
31 use, intrinsic :: iso_fortran_env
35 use math_oct_m
36 use mpi_oct_m
37 use mesh_oct_m
40 use parser_oct_m
43 use space_oct_m
46 use unit_oct_m
49
50 implicit none
51
52 private
53 public :: &
54 lasers_t, &
59 laser_t, &
70 laser_kind, &
81
82
83 ! TODO: (Micael, Alex) Issue 836. Remove the following paramaters and use the
84 ! corresponding quantities defined in the multisystem (E_FIELD, B_FIELD, etc)
85 integer, public, parameter :: &
86 E_FIELD_NONE = 0, &
87 e_field_electric = 1, &
88 e_field_magnetic = 2, &
91
92 type laser_t
93 private
94 integer :: field = e_field_none
95 complex(real64), allocatable :: pol(:)
96 real(real64), allocatable :: prop(:)
97 type(tdf_t) :: f
98 type(tdf_t) :: phi
99 real(real64) :: omega = m_zero
100
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
106 end type laser_t
107
108 type, extends(interaction_partner_t) :: lasers_t
109 private
110
111 integer, public :: no_lasers
112 type(laser_t), allocatable, public :: lasers(:)
113
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
119 contains
120 procedure :: init_interaction_as_partner => lasers_init_interaction_as_partner
121 procedure :: update_quantity => lasers_update_quantity
122 procedure :: copy_quantities_to_interaction => lasers_copy_quantities_to_interaction
123 final :: lasers_finalize
124 end type
125
126 interface lasers_t
127 module procedure lasers_constructor
128 end interface lasers_t
129
130
131contains
132
133 function lasers_constructor(namespace) result(this)
134 class(lasers_t), pointer :: this
135 type(namespace_t), intent(in) :: namespace
136
137 push_sub(lasers_constructor)
138
139 safe_allocate(this)
140
141 this%namespace = namespace_t("Lasers", parent=namespace)
142
143 safe_allocate(this%e(1:3))
144 safe_allocate(this%b(1:3))
145 this%e = m_zero
146 this%b = m_zero
147
148 pop_sub(lasers_constructor)
149 end function lasers_constructor
150
151 subroutine lasers_parse_external_fields(this)
152 class(lasers_t), intent(inout) :: this
153
154 type(block_t) :: blk
155 integer :: il, jj, ierr, k
156 real(real64) :: omega0
157 complex(real64) :: cprop(3)
158
160
161 call messages_obsolete_variable(this%namespace, "TDLasers", "TDExternalFields")
162 !%Variable TDExternalFields
163 !%Type block
164 !%Section Time-Dependent
165 !%Description
166 !% The block <tt>TDExternalFields</tt> describes the type and shape of time-dependent
167 !% external perturbations that are applied to the system, in the form
168 !% <math>f(x,y,z) \cos(\omega t + \phi (t)) g(t)</math>, where <math>f(x,y,z)</math> is defined by
169 !% by a field type and polarization or a scalar potential, as below; <math>\omega</math>
170 !% is defined by <tt>omega</tt>; <math>g(t)</math> is defined by
171 !% <tt>envelope_function_name</tt>; and <math>\phi(t)</math> is the (time-dependent) phase from <tt>phase</tt>.
172 !%
173 !% These perturbations are only applied for time-dependent runs. If
174 !% you want the value of the perturbation at time zero to be
175 !% applied for time-independent runs, use <tt>TimeZero = yes</tt>.
176 !%
177 !% Each line of the block describes an external field; this way you can actually have more
178 !% than one laser (<i>e.g.</i> a "pump" and a "probe").
179 !%
180 !% There are two ways to specify <math>f(x,y,z)</math> but both use the same <tt>omega | envelope_function_name [| phase]</tt>
181 !% for the time-dependence.
182 !% The float <tt>omega</tt> will be the carrier frequency of the
183 !% pulse (in energy units). The envelope of the field is a time-dependent function whose definition
184 !% must be given in a <tt>TDFunctions</tt> block. <tt>envelope_function_name</tt> is a string (and therefore
185 !% it must be surrounded by quotation marks) that must match one of the function names
186 !% given in the first column of the <tt>TDFunctions</tt> block.
187 !% <tt>phase</tt> is optional and is taken to be zero if not provided, and is also a string specifying
188 !% a time-dependent function.
189 !%
190 !% (A) type = <tt>electric field, magnetic field, vector_potential</tt>
191 !%
192 !% For these cases, the syntax is:
193 !%
194 !% <tt>%TDExternalFields
195 !% <br>&nbsp;&nbsp; type | nx | ny | nz | omega | envelope_function_name | phase (| px | py | pz )
196 !% <br>%</tt>
197 !%
198 !% The <tt>vector_potential</tt> option (constant in space) permits us to describe
199 !% an electric perturbation in the velocity gauge.
200 !% The three (possibly complex) numbers (<tt>nx</tt>, <tt>ny</tt>, <tt>nz</tt>) mark the polarization
201 !% direction of the field.
202 !% By default, (<tt>nx</tt>, <tt>ny</tt>, <tt>nz</tt>) are defined in Cartesian space.
203 !% However, it is possible for solids to define them using the Miller indices.
204 !% This can be achieved by defining the block <tt>MillerIndicesBasis</tt>. It is also possible to activate
205 !% the nondipole SFA correction by inserting the laser propagation direction px | py | pz as prescribed in
206 !% Phys. Rev. A 101, 043408 (2020).
207 !%
208 !% (B) type = <tt>scalar_potential</tt>
209 !%
210 !% <tt>%TDExternalFields
211 !% <br>&nbsp;&nbsp; scalar_potential | "spatial_expression" | omega | envelope_function_name | phase
212 !% <br>%</tt>
213 !%
214 !% The scalar potential is any expression of the spatial coordinates given by the string
215 !% "spatial_expression", allowing a field beyond the dipole approximation.
216 !%
217 !% For DFTB runs, only fields of type type = <tt>electric field</tt> are allowed for the moment, and the
218 !% <tt>type</tt> keyword is omitted.
219 !%
220 !% A NOTE ON UNITS:
221 !%
222 !% It is very common to describe the strength of a laser field by its intensity, rather
223 !% than using the electric-field amplitude. In atomic units (or, more precisely, in any
224 !% Gaussian system of units), the relationship between instantaneous electric field
225 !% and intensity is:
226 !% <math> I(t) = \frac{c}{8\pi} E^2(t) </math>.
227 !%
228 !% It is common to read intensities in W/cm<math>^2</math>. The dimensions of intensities are
229 !% [W]/(L<math>^2</math>T), where [W] are the dimensions of energy. The relevant conversion factors
230 !% are:
231 !%
232 !% Hartree / (<math>a_0^2</math> atomic_time) = <math>6.4364086 \times 10^{15} \mathrm{W/cm}^2</math>
233 !%
234 !% eV / ( &Aring;<math>^2 (\hbar</math>/eV) ) = <math>2.4341348 \times 10^{12} \mathrm{W/cm}^2</math>
235 !%
236 !% If, in atomic units, we set the electric-field amplitude to <math>E_0</math>,
237 !% then the intensity is:
238 !%
239 !% <math> I_0 = 3.51 \times 10^{16} \mathrm{W/cm}^2 (E_0^2) </math>
240 !%
241 !% If, working with <tt>Units = ev_angstrom</tt>, we set <math>E_0</math>, then the intensity is:
242 !%
243 !% <math> I_0 = 1.327 \times 10^{13} (E_0^2) \mathrm{W/cm}^2 </math>
244 !%
245 !%Option electric_field 1
246 !% The external field is an electric field, the usual case when we want to describe a
247 !% laser in the length gauge.
248 !%Option magnetic_field 2
249 !% The external field is a (homogeneous) time-dependent magnetic field.
250 !%Option vector_potential 3
251 !% The external field is a time-dependent homogeneous vector potential, which may describe
252 !% a laser field in the velocity gauge.
253 !%Option scalar_potential 4
254 !% The external field is an arbitrary scalar potential, which may describe an
255 !% inhomogeneous electrical field.
256 !%End
257
258 this%no_lasers = 0
259 if (parse_block(this%namespace, 'TDExternalFields', blk) == 0) then
260 this%no_lasers = parse_block_n(blk)
261 safe_allocate(this%lasers(1:this%no_lasers))
262
263 do il = 1, this%no_lasers
264 safe_allocate(this%lasers(il)%pol(1:3))
265 this%lasers(il)%pol = m_z0
266
267 call parse_block_integer(blk, il-1, 0, this%lasers(il)%field)
268
269 select case (this%lasers(il)%field)
271 call parse_block_string(blk, il-1, 1, this%lasers(il)%scalar_pot_expression)
272 jj = 1
273 this%lasers(il)%pol = m_z1
274 case default
275 call parse_block_cmplx(blk, il-1, 1, this%lasers(il)%pol(1))
276 call parse_block_cmplx(blk, il-1, 2, this%lasers(il)%pol(2))
277 call parse_block_cmplx(blk, il-1, 3, this%lasers(il)%pol(3))
278 jj = 3
279 end select
280
281 call parse_block_float(blk, il-1, jj+1, omega0)
282
283 this%lasers(il)%omega = omega0
284
285 call parse_block_string(blk, il-1, jj+2, this%lasers(il)%envelope_expression)
286 call tdf_read(this%lasers(il)%f, this%namespace, trim(this%lasers(il)%envelope_expression), ierr)
287
288 ! Check if there is a phase.
289 if (parse_block_cols(blk, il-1) > jj+3) then
290 call parse_block_string(blk, il-1, jj+3, this%lasers(il)%phase_expression)
291 call tdf_read(this%lasers(il)%phi, this%namespace, trim(this%lasers(il)%phase_expression), ierr)
292 if (ierr /= 0) then
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), &
296 '" not found.'
297 call messages_warning(2, namespace=this%namespace)
298 end if
299 else
300 call tdf_init(this%lasers(il)%phi)
301 end if
302
303 ! Check if there is nondipoole fields to activate the nondipole SFA formalism of Phys. Rev. A 101, 043408 (2020)
304 if (parse_block_cols(blk, il-1) > jj+4) then
305 safe_allocate(this%lasers(il)%prop(1:size(cprop)))
306 do k = 1, size(cprop)
307 call parse_block_cmplx(blk, il-1, jj+size(cprop)+k, cprop(k))
308
309 end do
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.'
314 call messages_fatal(2, namespace=this%namespace)
315 end if
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
321 !%Variable NDSFATimeIntegrationStep
322 !%Type float
323 !%Default 0.01
324 !%Section Hamiltonian
325 !%Description
326 !% Timestep for the integration of the NDSFA first order
327 !% response numerically as prescribed in Phys. Rev. A 101, 043408 (2020).
328 !% Typically needs to be an order of magniude less than
329 !% the TDtimestep. However, for writing "laser" the TDtimestep
330 !% is used instead.
331 !%End
332 call parse_variable(this%namespace, 'NDSFATimeIntegrationStep', 0.01_real64, this%nd_integration_step)
333
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"
337 call messages_info(2, namespace=this%namespace)
338 end if
339 end if
340 end if
341
342 end do
343
344 call parse_block_end(blk)
345 end if
346
348 end subroutine lasers_parse_external_fields
349
350 subroutine lasers_generate_potentials(this, mesh, space, latt)
351 class(lasers_t), intent(inout) :: this
352 class(mesh_t), intent(in) :: mesh
353 class(space_t), intent(in) :: space
354 type(lattice_vectors_t), intent(in) :: latt
355
356 type(block_t) :: blk2
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)
360
362
363 do il = 1, this%no_lasers
364 ! For periodic systems, we might want to define the polarization direction in
365 ! terms of Miller indices
366 ! In this case, the use must provide the coordinates of the X, Y, and Z high symmetry points
367 ! such that the code applying a laser along say the [100] direction converts it to
368 ! the proper coordinates in Cartesian space.
369 ! This is usefull for arbitrarily rotated crystals.
370
371 !%Variable MillerIndicesBasis
372 !%Type block
373 !%Section Time-Dependent
374 !%Description
375 !% When this block is given, the polarisation of the TDExternalFields is
376 !% understood to be defined in terms of Miller indices.
377 !% This block define the corresponding basis, by defining the reduced coordinates
378 !% of the X, Y, and Z high symmetry points, such that the code can do the corresponding
379 !% transformation.
380 !%
381 !% For example, in an FCC crystal with the conventional primitive cell,
382 !% the following input allows to define the polarization in terms
383 !% message(1) = "The lasers break (at least) one of the symmetries used to reduce the k-points ."
384 !%
385 !% <tt>%MillerIndicesBasis
386 !% <br> 0.0 | 0.5 | 0.5
387 !% <br> 0.5 | 0.0 | 0.5
388 !% <br> 0.5 | 0.5 | 0.0
389 !% <br>%</tt>
390 !%
391 !% Indeed, in this case, the reciprocal lattice vectors are (-1, 1, 1), (1, -1, 1),
392 !% and (1, 1, -1) in units of 2*pi/a.
393 !% This directly gives that the [100] direction correspond to the x direction, [111]
394 !% gives the vector (1,1,1), etc.
395 !%
396 !%End
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.'
400 call messages_fatal(1, namespace=this%namespace)
401 end if
402
403 do idir = 1, space%dim
404 do idir2 = 1, space%dim
405 call parse_block_float(blk2, idir-1, idir2-1, miller_red(idir2, idir))
406 end do
407 call kpoints_to_absolute(latt, miller_red(:, idir), miller(:, idir))
408 end do
409
410
411 this%lasers(il)%pol = matmul(miller, this%lasers(il)%pol)
412 call parse_block_end(blk2)
413 end if
414
415 this%lasers(il)%pol(:) = this%lasers(il)%pol(:)/sqrt(sum(abs(this%lasers(il)%pol(:))**2))
416
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
421 do ip = 1, mesh%np
422 call mesh_r(mesh, ip, rr, coords = xx(1:space%dim))
423 xx(space%dim+1:3) = m_zero
424 call parse_expression(pot_re, pot_im, 3, xx, rr, m_zero, trim(this%lasers(il)%scalar_pot_expression))
425 this%lasers(il)%v(ip) = pot_re
426 end do
427
428 case (e_field_magnetic)
429 ! \warning: note that for the moment we are ignoring the possibility of a complex
430 ! polarizability vector for the td magnetic-field case.
431 safe_allocate(this%lasers(il)%a(1:mesh%np_part, 1:3))
432 this%lasers(il)%a = m_zero
433 do ip = 1, mesh%np
434 xx(1:space%dim) = mesh%x(:, ip)
435 xx(space%dim+1:3) = m_zero
436 ! Compute the vector potential from a uniform B field.
437 ! The sign is determined by the relation $\vec{B} = \nabla \times \vec{A}$.
438 ! This leads to $\vec{A} = -\frac{1}{2}\vec{r}\times\vec{B}$.
439 select case (space%dim)
440 case (2)
441 this%lasers(il)%a(ip, 1:2) = (/xx(2), -xx(1)/) * sign(m_one, real(this%lasers(il)%pol(3)))
442 case (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)) /)
446 case default
447 message(1) = "Magnetic fields only allowed in 2 or 3D."
448 call messages_fatal(1, namespace=this%namespace)
449 end select
450 end do
451 this%lasers(il)%a = -m_half * this%lasers(il)%a
452
453 end select
454
455 end do
456
458 end subroutine lasers_generate_potentials
459
460
461 ! ---------------------------------------------------------
462 subroutine lasers_check_symmetries(this, kpoints)
463 type(lasers_t), intent(in) :: this
464 type(kpoints_t), intent(in) :: kpoints
465
466 integer :: iop, il
467
469
470 if (kpoints%use_symmetries) then
471 do iop = 1, symmetries_number(kpoints%symm)
472 if (iop == symmetries_identity_index(kpoints%symm)) cycle
473 do il = 1, this%no_lasers
474 if (.not. symm_op_invariant_cart(kpoints%symm%ops(iop), this%lasers(il)%pol(:), symprec)) then
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."
477 call messages_fatal(2, namespace=this%namespace)
478 end if
479 end do
480 end do
481 end if
482
484 end subroutine lasers_check_symmetries
485
486 ! ---------------------------------------------------------
487 subroutine lasers_finalize(this)
488 type(lasers_t), intent(inout) :: this
489
490 push_sub(lasers_finalize)
491
492 call lasers_deallocate(this)
493
494 pop_sub(lasers_finalize)
495 end subroutine lasers_finalize
496
497 ! ---------------------------------------------------------
498 subroutine lasers_deallocate(this)
499 class(lasers_t), intent(inout) :: this
500
501 integer :: il
502
503 push_sub(lasers_deallocate)
504
505 safe_deallocate_a(this%e)
506 safe_deallocate_a(this%b)
507 safe_deallocate_a(this%integrated_nondipole_afield)
508
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)
516 case (e_field_magnetic)
517 safe_deallocate_a(this%lasers(il)%a)
518 end select
519 safe_deallocate_a(this%lasers(il)%prop)
520 end do
521 safe_deallocate_a(this%lasers)
522
523 pop_sub(lasers_deallocate)
524 end subroutine lasers_deallocate
525
526
527 ! ---------------------------------------------------------
528 real(real64) function laser_carrier_frequency(laser) result(w0)
529 type(laser_t), intent(in) :: laser
530
532
533 w0 = laser%omega
534
536 end function laser_carrier_frequency
537
538 ! ---------------------------------------------------------
539 subroutine lasers_init_interaction_as_partner(partner, interaction)
540 class(lasers_t), intent(in) :: partner
541 class(interaction_surrogate_t), intent(inout) :: interaction
542
544
545 select type (interaction)
546 type is (lorentz_force_t)
547 ! Nothing to be initialized for the Lorentz force.
548 class default
549 message(1) = "Unsupported interaction."
550 call messages_fatal(1, namespace=partner%namespace)
551 end select
552
555
556 ! ---------------------------------------------------------
557 subroutine lasers_update_quantity(this, label)
558 class(lasers_t), intent(inout) :: this
559 character(len=*), intent(in) :: label
560
561 type(quantity_t), pointer :: quantity
562 integer :: il
563
564 push_sub(lasers_update_quantity)
565
566 if (allocated(this%lasers)) then
567 if (any(laser_kind(this%lasers) == e_field_vector_potential) .or. &
568 any(laser_kind(this%lasers) == e_field_scalar_potential)) then
569 call messages_not_implemented("Laser vector potentials and scalar potentials in multi-system framework", &
570 namespace=this%namespace)
571 end if
572 end if
573
574 quantity => this%quantities%get(label)
575 select case (label)
576 case ("E field")
577 this%e = m_zero
578 do il = 1, this%no_lasers
579 if (laser_kind(this%lasers(il)) == e_field_electric) then
580 call laser_field(this%lasers(il), this%e, quantity%iteration%value())
581 end if
582 end do
583
584 case ("B field")
585 this%b = m_zero
586 do il = 1, this%no_lasers
587 if (laser_kind(this%lasers(il)) == e_field_magnetic) then
588 call laser_field(this%lasers(il), this%b, quantity%iteration%value())
589 end if
590 end do
591
592 case default
593 message(1) = "Incompatible quantity."
594 call messages_fatal(1, namespace=this%namespace)
595 end select
596
598 end subroutine lasers_update_quantity
599
600 ! ---------------------------------------------------------
601 subroutine lasers_copy_quantities_to_interaction(partner, interaction)
602 class(lasers_t), intent(inout) :: partner
603 class(interaction_surrogate_t), intent(inout) :: interaction
604
605 integer :: ip
606
608
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
614 end do
615 class default
616 message(1) = "Unsupported interaction."
617 call messages_fatal(1, namespace=partner%namespace)
618 end select
619
622
623 ! ---------------------------------------------------------
624 integer pure elemental function laser_kind(laser)
625 type(laser_t), intent(in) :: laser
626
627 ! no push_sub allowed in pure function
628 laser_kind = laser%field
629
630 end function laser_kind
631 ! ---------------------------------------------------------
632
633
634 ! ---------------------------------------------------------
635 function laser_polarization(laser) result(pol)
636 type(laser_t), intent(in) :: laser
637 complex(real64) :: pol(3)
638
639 push_sub(laser_polarization)
640
641 pol = laser%pol
642
643 pop_sub(laser_polarization)
644 end function laser_polarization
645 ! ---------------------------------------------------------
646
648 function lasers_with_nondipole_field(lasers) result(isnondipole)
649 type(lasers_t), intent(in) :: lasers
650 logical :: isnondipole
651
653 isnondipole = .false.
654 if(allocated(lasers%integrated_nondipole_afield)) isnondipole = .true.
656 end function lasers_with_nondipole_field
657 ! ---------------------------------------------------------
658
659
661 subroutine lasers_set_nondipole_parameters(this, ndfield, nd_integration_time)
662 type(lasers_t), intent(inout) :: this
663 real(real64), intent(in) :: ndfield(:)
664 real(real64), intent(in) :: nd_integration_time
665 integer :: dim
666 dim = size(ndfield)
667
669
670 this%integrated_nondipole_afield(1:dim) = ndfield(1:dim)
671 this%nd_integration_time = nd_integration_time
672
675
676
677 ! ---------------------------------------------------------
678 subroutine laser_get_f(laser, ff)
679 type(laser_t), intent(in) :: laser
680 type(tdf_t), intent(inout) :: ff
681
682 push_sub(laser_get_f)
683 call tdf_copy(ff, laser%f)
684
685 pop_sub(laser_get_f)
686 end subroutine laser_get_f
687 ! ---------------------------------------------------------
688
689
690 ! ---------------------------------------------------------
691 subroutine laser_set_f(laser, ff)
692 type(laser_t), intent(inout) :: laser
693 type(tdf_t), intent(inout) :: ff
694
695 push_sub(laser_set_f)
697 call tdf_end(laser%f)
698 call tdf_copy(laser%f, ff)
699
700 pop_sub(laser_set_f)
701 end subroutine laser_set_f
702 ! ---------------------------------------------------------
703
704
705 ! ---------------------------------------------------------
706 subroutine laser_get_phi(laser, phi)
707 type(laser_t), intent(in) :: laser
708 type(tdf_t), intent(inout) :: phi
709
710 push_sub(laser_get_phi)
711 call tdf_copy(phi, laser%phi)
712
713 pop_sub(laser_get_phi)
714 end subroutine laser_get_phi
715 ! ---------------------------------------------------------
716
717
718 ! ---------------------------------------------------------
719 subroutine laser_set_phi(laser, phi)
720 type(laser_t), intent(inout) :: laser
721 type(tdf_t), intent(inout) :: phi
722
723 push_sub(laser_set_phi)
724
725 call tdf_end(laser%phi)
726 call tdf_copy(laser%phi, phi)
727
728 pop_sub(laser_set_phi)
729 end subroutine laser_set_phi
730 ! ---------------------------------------------------------
731
732
733 ! ---------------------------------------------------------
734 subroutine laser_set_empty_phi(laser)
735 type(laser_t), intent(inout) :: laser
736
737 push_sub(laser_set_empty_phi)
738
739 call tdf_init(laser%phi)
740
741 pop_sub(laser_set_empty_phi)
742 end subroutine laser_set_empty_phi
743 ! ---------------------------------------------------------
744
745 ! ---------------------------------------------------------
746 subroutine laser_set_f_value(laser, ii, xx)
747 type(laser_t), intent(inout) :: laser
748 integer, intent(in) :: ii
749 real(real64), intent(in) :: xx
750
751 push_sub(laser_set_f_value)
752 call tdf_set_numerical(laser%f, ii, xx)
753
754 pop_sub(laser_set_f_value)
755 end subroutine laser_set_f_value
756 ! ---------------------------------------------------------
757
758
759 ! ---------------------------------------------------------
760 subroutine laser_set_frequency(laser, omega)
761 type(laser_t), intent(inout) :: laser
762 real(real64), intent(in) :: omega
763
764 push_sub(laser_set_frequency)
765 laser%omega = omega
766
767 pop_sub(laser_set_frequency)
768 end subroutine laser_set_frequency
769 ! ---------------------------------------------------------
770
771
772 ! ---------------------------------------------------------
773 subroutine laser_set_polarization(laser, pol)
774 type(laser_t), intent(inout) :: laser
775 complex(real64), intent(in) :: pol(:)
776
777 push_sub(laser_set_polarization)
778
779 laser%pol = pol
780
782 end subroutine laser_set_polarization
783 ! ---------------------------------------------------------
784
785
786 ! ---------------------------------------------------------
793 ! ---------------------------------------------------------
794 subroutine laser_to_numerical_all(laser, dt, max_iter, omegamax)
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
799
800 integer :: iter
801 real(real64) :: tt, fj, phi
802
803 push_sub(lasers_to_numerical_all)
804
805 call tdf_to_numerical(laser%f, max_iter, dt, omegamax)
806 do iter = 1, max_iter + 1
807 tt = (iter-1)*dt
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))
811 end do
812 call tdf_end(laser%phi)
813 call tdf_init_cw(laser%phi, m_zero, m_zero)
814 laser%omega = m_zero
815
816 pop_sub(lasers_to_numerical_all)
817 end subroutine laser_to_numerical_all
818 ! ---------------------------------------------------------
819
820
821 ! ---------------------------------------------------------
824 ! ---------------------------------------------------------
825 subroutine laser_to_numerical(laser, dt, max_iter, omegamax)
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
830
831 push_sub(lasers_to_numerical)
832
833 call tdf_to_numerical(laser%f, max_iter, dt, omegamax)
834 call tdf_to_numerical(laser%phi, max_iter, dt, omegamax)
835
836 pop_sub(lasers_to_numerical)
837 end subroutine laser_to_numerical
838 ! ---------------------------------------------------------
839
840 ! ---------------------------------------------------------
841 subroutine laser_write_info(lasers, namespace, dt, max_iter, iunit)
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
847
848 real(real64) :: tt, fluence, max_intensity, intensity, dt_, field(3), up, maxfield,tmp
849 integer :: il, iter, no_l, max_iter_
850
851 push_sub(laser_write_info)
852
853 no_l = size(lasers)
854
855 do il = 1, no_l
856
857 if (present(dt)) then
858 dt_ = dt
859 else
860 dt_ = tdf_dt(lasers(il)%f)
861 end if
862 if (present(max_iter)) then
863 max_iter_ = max_iter
864 else
865 max_iter_ = tdf_niter(lasers(il)%f)
866 end if
867
868 write(message(1),'(i2,a)') il, ':'
869 select case (lasers(il)%field)
870 case (e_field_electric)
871 message(2) = ' Electric Field.'
872 case (e_field_magnetic)
873 message(2) = ' Magnetic Field.'
875 message(2) = ' Vector Potential.'
877 message(2) = ' Scalar Potential.'
878 end select
879 call messages_info(2, iunit=iunit, namespace=namespace)
880
881 if (lasers(il)%field /= e_field_scalar_potential) then
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)
887 end if
888
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)
895
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)
900 end if
901
902 ! 1 atomic unit of intensity = 3.5094448e+16 W / cm^2
903 ! In a Gaussian system of units,
904 ! I(t) = (1/(8\pi)) * c * E(t)^2
905 ! (1/(8\pi)) * c = 5.4525289841210 a.u.
906 if (lasers(il)%field == e_field_electric .or. lasers(il)%field == e_field_vector_potential) then
907 fluence = m_zero
908 max_intensity = m_zero
909 maxfield= m_zero
910 do iter = 1, max_iter_
911 tt = iter * dt_
912 call laser_electric_field(lasers(il), field, tt, dt_)
913 intensity = 5.4525289841210_real64*sum(field**2)
914 fluence = fluence + intensity
915 if (intensity > max_intensity) max_intensity = intensity
916
917 tmp = sum(field(:)**2)
918 if (tmp > maxfield) maxfield = tmp
919 end do
920 fluence = fluence * dt_
921
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)
929
930 if (abs(lasers(il)%omega) > m_epsilon) then
931 ! Ponderomotive Energy is the cycle-averaged kinetic energy of
932 ! a free electron quivering in the field
933 ! Up = E^2/(4*\omega^2)
934 !
935 ! subroutine laser_to_numerical_all sets lasers%omega to zero
937 up = maxfield/(4*lasers(il)%omega**2)
938
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)
943 end if
944 end if
945
946 end do
947
948 pop_sub(laser_write_info)
949 end subroutine laser_write_info
950 ! ---------------------------------------------------------
951
952
953 ! ---------------------------------------------------------
954 subroutine laser_potential(laser, mesh, pot, time)
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
959
960 complex(real64) :: amp
961 integer :: ip
962 real(real64) :: field(3)
963
964 push_sub(laser_potential)
965
966 if (present(time)) then
967 amp = tdf(laser%f, time) * exp(m_zi * (laser%omega * time + tdf(laser%phi, time)))
968 else
969 amp = m_z1
970 end if
971
972 select case (laser%field)
974 call lalg_axpy(mesh%np, real(amp, real64), laser%v, pot)
975 case default
976 field(:) = real(amp * laser%pol(:), real64)
977 do ip = 1, mesh%np
978 ! The -1 sign is missing here. Check epot.F90 for the explanation.
979 pot(ip) = pot(ip) + sum(field(1:mesh%box%dim) * mesh%x(1:mesh%box%dim, ip))
980 end do
981 end select
982
983 pop_sub(laser_potential)
984 end subroutine laser_potential
985 ! ---------------------------------------------------------
986
987
988 ! ---------------------------------------------------------
989 subroutine laser_vector_potential(laser, mesh, aa, time)
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
994
995 real(real64) :: amp
996 integer :: ip, idir
997
998 push_sub(laser_vector_potential)
999
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
1003 do ip = 1, mesh%np
1004 aa(ip, idir) = aa(ip, idir) + amp*laser%a(ip, idir)
1005 end do
1006 end do
1007 else
1008 do idir = 1, mesh%box%dim
1009 do ip = 1, mesh%np
1010 aa(ip, idir) = aa(ip, idir) + laser%a(ip, idir)
1011 end do
1012 end do
1013 end if
1014
1015 pop_sub(laser_vector_potential)
1016 end subroutine laser_vector_potential
1017 ! ---------------------------------------------------------
1018
1019
1020 ! ---------------------------------------------------------
1026 subroutine laser_field(laser, field, time)
1027 type(laser_t), intent(in) :: laser
1028 real(real64), intent(inout) :: field(:)
1029 real(real64), optional, intent(in) :: time
1030
1031 integer :: dim
1032 complex(real64) :: amp
1033
1034 !no PUSH SUB, called too often
1035
1036 dim = size(field)
1037
1038 if (present(time)) then
1039 amp = tdf(laser%f, time) * exp(m_zi * (laser%omega * time + tdf(laser%phi, time)))
1040 else
1041 amp = m_z1
1042 end if
1043 if (laser%field == e_field_scalar_potential) then
1044 ! In this case we will just return the value of the time function. The "field", in fact,
1045 ! should be a function of the position in space (thus, a true "field"), given by the
1046 ! gradient of the scalar potential.
1047 field(1) = field(1) + real(amp, real64)
1048 else
1049 field(1:dim) = field(1:dim) + real(amp*laser%pol(1:dim), real64)
1050 end if
1051 end subroutine laser_field
1052
1053! ---------------------------------------------------------
1061 subroutine lasers_nondipole_laser_field_step(this, field, time)
1062 type(lasers_t), intent(in) :: this
1063 real(real64), intent(out) :: field(:)
1064 real(real64), intent(in) :: time
1065
1066 real(real64) :: a0(3)
1067 real(real64) :: e0(3)
1068 integer :: ilaser
1069 integer :: jlaser
1070 integer :: dim
1071 integer :: iter
1072 dim = size(field)
1073
1074 field(1:dim) = this%integrated_nondipole_afield(1:dim)
1075 if (time - this%nd_integration_time < 0) then
1076 return
1077 endif
1078 do iter = 1, nint((time-this%nd_integration_time)/this%nd_integration_step)
1079 do ilaser = 1, this%no_lasers
1080 if(laser_kind(this%lasers(ilaser)) /= e_field_vector_potential) cycle
1081 do jlaser = 1, this%no_lasers
1082 if(laser_kind(this%lasers(jlaser)) /= e_field_vector_potential) cycle
1083 if(allocated(this%lasers(jlaser)%prop)) then
1084 a0 = m_zero
1085 call laser_field(this%lasers(ilaser), a0, &
1086 iter*this%nd_integration_step+this%nd_integration_time)
1087 call laser_electric_field(this%lasers(jlaser), e0, &
1088 iter*this%nd_integration_step+this%nd_integration_time, this%nd_integration_step)
1089 ! We have front factor q/(mc) with q=-abs(e) =-1 a.u. and m = 1 a.u.
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)
1092 end if
1093 end do
1094 end do
1095 end do
1097
1098
1099 ! ---------------------------------------------------------
1102 subroutine laser_electric_field(laser, field, time, dt)
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
1107
1108 integer :: dim
1109 real(real64), allocatable :: field1(:), field2(:)
1110
1111 !no PUSH SUB, called too often
1112
1113 dim = size(field)
1114
1115 select case (laser%field)
1116 case (e_field_electric)
1117 field = m_zero
1118 call laser_field(laser, field(1:dim), time)
1120 safe_allocate(field1(1:dim))
1121 safe_allocate(field2(1:dim))
1122 field1 = m_zero
1123 field2 = m_zero
1124 call laser_field(laser, field1(1:dim), time - dt)
1125 call laser_field(laser, field2(1:dim), time + dt)
1126 field = - (field2 - field1) / (m_two * p_c * dt)
1127 safe_deallocate_a(field1)
1128 safe_deallocate_a(field2)
1129 case default
1130 field = m_zero
1131 end select
1132
1133 end subroutine laser_electric_field
1134 ! ---------------------------------------------------------
1135
1136 ! ---------------------------------------------------------
1137 ! Loading of the lasers for the multisystem framework
1138 ! Ultimately this should be done in laser_init
1139 subroutine load_lasers(partners, namespace)
1140 class(partner_list_t), intent(inout) :: partners
1141 type(namespace_t), intent(in) :: namespace
1142
1143 class(lasers_t), pointer :: lasers
1144 integer :: il
1145
1146 push_sub(load_lasers)
1147
1148 lasers => lasers_t(namespace)
1149
1150 call lasers_parse_external_fields(lasers)
1151
1152 ! TODO: see how to do this in the multisystem framework
1153 if (parse_is_defined(namespace, 'MillerIndicesBasis')) then
1154 call messages_not_implemented("MillerIndicesBasis with load_lasers routine")
1155 end if
1157 ! This is done normally in lasers_generate_potential, but we cannot call this routine here,
1158 ! so we do it here
1159 do il = 1, lasers%no_lasers
1160 lasers%lasers(il)%pol(:) = lasers%lasers(il)%pol(:)/sqrt(sum(abs(lasers%lasers(il)%pol(:))**2))
1161 end do
1162
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()))
1165
1166 lasers%supported_interactions_as_partner = [lorentz_force]
1167
1168 if (lasers%no_lasers > 0) then
1169 call partners%add(lasers)
1170 else
1171 safe_deallocate_p(lasers)
1172 end if
1173
1174 pop_sub(load_lasers)
1175 end subroutine load_lasers
1176
1177end module lasers_oct_m
1178
1179!! Local Variables:
1180!! mode: f90
1181!! coding: utf-8
1182!! End:
double exp(double __x) __attribute__((__nothrow__
double sqrt(double __x) __attribute__((__nothrow__
double cos(double __x) __attribute__((__nothrow__
real(real64), parameter, public m_zero
Definition: global.F90:200
complex(real64), parameter, public m_z0
Definition: global.F90:210
real(real64), parameter, public m_epsilon
Definition: global.F90:216
complex(real64), parameter, public m_z1
Definition: global.F90:211
real(real64), parameter, public m_half
Definition: global.F90:206
real(real64), parameter, public m_one
Definition: global.F90:201
This module defines classes and functions for interaction partners.
subroutine, public kpoints_to_absolute(latt, kin, kout)
Definition: kpoints.F90:1137
subroutine, public load_lasers(partners, namespace)
Definition: lasers.F90:1235
complex(real64) function, dimension(3), public laser_polarization(laser)
Definition: lasers.F90:731
subroutine, public laser_set_phi(laser, phi)
Definition: lasers.F90:815
subroutine, public lasers_check_symmetries(this, kpoints)
Definition: lasers.F90:558
subroutine lasers_copy_quantities_to_interaction(partner, interaction)
Definition: lasers.F90:697
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....
Definition: lasers.F90:890
subroutine, public laser_vector_potential(laser, mesh, aa, time)
Definition: lasers.F90:1085
subroutine, public lasers_nondipole_laser_field_step(this, field, time)
Retrieves the NDSFA vector_potential correction. The nondipole field is obtained for consecutive time...
Definition: lasers.F90:1157
subroutine, public lasers_parse_external_fields(this)
Definition: lasers.F90:247
subroutine, public lasers_set_nondipole_parameters(this, ndfield, nd_integration_time)
Set parameters for nondipole SFA calculation.
Definition: lasers.F90:757
subroutine lasers_update_quantity(this, label)
Definition: lasers.F90:653
subroutine, public laser_get_f(laser, ff)
Definition: lasers.F90:774
subroutine, public laser_set_f(laser, ff)
Definition: lasers.F90:787
logical function, public lasers_with_nondipole_field(lasers)
Check if a nondipole SFA correction should be computed for the given laser.
Definition: lasers.F90:744
subroutine, public laser_write_info(lasers, namespace, dt, max_iter, iunit)
Definition: lasers.F90:937
subroutine, public laser_set_empty_phi(laser)
Definition: lasers.F90:830
real(real64) function, public laser_carrier_frequency(laser)
Definition: lasers.F90:624
integer, parameter, public e_field_electric
Definition: lasers.F90:180
integer, parameter, public e_field_vector_potential
Definition: lasers.F90:180
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....
Definition: lasers.F90:921
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...
Definition: lasers.F90:1198
subroutine, public lasers_generate_potentials(this, mesh, space, latt)
Definition: lasers.F90:446
subroutine lasers_init_interaction_as_partner(partner, interaction)
Definition: lasers.F90:635
subroutine lasers_finalize(this)
Definition: lasers.F90:583
subroutine, public laser_potential(laser, mesh, pot, time)
Definition: lasers.F90:1050
class(lasers_t) function, pointer lasers_constructor(namespace)
Definition: lasers.F90:229
integer, parameter, public e_field_scalar_potential
Definition: lasers.F90:180
integer pure elemental function, public laser_kind(laser)
Definition: lasers.F90:720
subroutine, public laser_set_frequency(laser, omega)
Definition: lasers.F90:856
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...
Definition: lasers.F90:1122
subroutine, public laser_set_polarization(laser, pol)
Definition: lasers.F90:869
subroutine, public laser_set_f_value(laser, ii, xx)
Definition: lasers.F90:842
subroutine, public laser_get_phi(laser, phi)
Definition: lasers.F90:802
subroutine lasers_deallocate(this)
Definition: lasers.F90:594
integer, parameter, public e_field_magnetic
Definition: lasers.F90:180
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:117
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
pure subroutine, public mesh_r(mesh, ip, rr, origin, coords)
return the distance to the origin for a given grid point
Definition: mesh.F90:343
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:525
subroutine, public messages_obsolete_variable(namespace, name, rep)
Definition: messages.F90:1000
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:410
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
subroutine, public parse_block_string(blk, l, c, res, convert_to_c)
Definition: parser.F90:818
integer function, public parse_block(namespace, name, blk, check_varinfo_)
Definition: parser.F90:623
This module defines the quantity_t class and the IDs for quantities, which can be exposed by a system...
Definition: quantity.F90:140
integer pure function, public symmetries_identity_index(this)
Definition: symmetries.F90:615
real(real64), public symprec
Definition: symmetries.F90:173
integer pure function, public symmetries_number(this)
Definition: symmetries.F90:569
subroutine, public tdf_end(f)
Definition: tdfunction.F90:982
subroutine, public tdf_init(f)
Definition: tdfunction.F90:390
subroutine, public tdf_read(f, namespace, function_name, ierr)
This function initializes "f" from the TDFunctions block.
Definition: tdfunction.F90:220
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:134
This module defines the unit system, used for input and output.
__clock_t clock_t
Definition: recipes.c:399
abstract class for general interaction partners
Describes mesh distribution to nodes.
Definition: mesh.F90:187
int true(void)