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
30 use, intrinsic :: iso_fortran_env
34 use math_oct_m
35 use mpi_oct_m
36 use mesh_oct_m
39 use parser_oct_m
42 use space_oct_m
45 use unit_oct_m
48
49 implicit none
50
51 private
52 public :: &
53 lasers_t, &
58 laser_t, &
69 laser_kind, &
80
81
82 ! TODO: (Micael, Alex) Issue 836. Remove the following paramaters and use the
83 ! corresponding quantities defined in the multisystem (E_FIELD, B_FIELD, etc)
84 integer, public, parameter :: &
85 E_FIELD_NONE = 0, &
86 e_field_electric = 1, &
87 e_field_magnetic = 2, &
90
91 type laser_t
92 private
93 integer :: field = e_field_none
94 complex(real64), allocatable :: pol(:)
95 real(real64), allocatable :: prop(:)
96 type(tdf_t) :: f
97 type(tdf_t) :: phi
98 real(real64) :: omega = m_zero
99
100 real(real64), allocatable :: v(:)
101 real(real64), allocatable :: a(:, :)
102 end type laser_t
103
104 type, extends(interaction_partner_t) :: lasers_t
105 private
106
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
112
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
118 contains
119 procedure :: init_interaction_as_partner => lasers_init_interaction_as_partner
120 procedure :: update_quantity => lasers_update_quantity
121 procedure :: copy_quantities_to_interaction => lasers_copy_quantities_to_interaction
122 final :: lasers_finalize
123 end type
124
125 interface lasers_t
126 module procedure lasers_constructor
127 end interface lasers_t
128
129
130contains
131
132 function lasers_constructor(namespace) result(this)
133 class(lasers_t), pointer :: this
134 type(namespace_t), intent(in) :: namespace
135
136 push_sub(lasers_constructor)
137
138 safe_allocate(this)
139
140 this%namespace = namespace_t("Lasers", parent=namespace)
141
142 safe_allocate(this%e(1:3))
143 safe_allocate(this%b(1:3))
144 this%e = m_zero
145 this%b = m_zero
146
147 pop_sub(lasers_constructor)
148 end function lasers_constructor
149
150 subroutine lasers_parse_external_fields(this)
151 class(lasers_t), intent(inout) :: this
152
153 type(block_t) :: blk
154 integer :: il, jj, ierr, k
155 real(real64) :: omega0
156 complex(real64) :: cprop(3)
157
159
160 call messages_obsolete_variable(this%namespace, "TDLasers", "TDExternalFields")
161 !%Variable TDExternalFields
162 !%Type block
163 !%Section Time-Dependent
164 !%Description
165 !% The block <tt>TDExternalFields</tt> describes the type and shape of time-dependent
166 !% external perturbations that are applied to the system, in the form
167 !% <math>f(x,y,z) \cos(\omega t + \phi (t)) g(t)</math>, where <math>f(x,y,z)</math> is defined by
168 !% by a field type and polarization or a scalar potential, as below; <math>\omega</math>
169 !% is defined by <tt>omega</tt>; <math>g(t)</math> is defined by
170 !% <tt>envelope_function_name</tt>; and <math>\phi(t)</math> is the (time-dependent) phase from <tt>phase</tt>.
171 !%
172 !% These perturbations are only applied for time-dependent runs. If
173 !% you want the value of the perturbation at time zero to be
174 !% applied for time-independent runs, use <tt>TimeZero = yes</tt>.
175 !%
176 !% Each line of the block describes an external field; this way you can actually have more
177 !% than one laser (<i>e.g.</i> a "pump" and a "probe").
178 !%
179 !% There are two ways to specify <math>f(x,y,z)</math> but both use the same <tt>omega | envelope_function_name [| phase]</tt>
180 !% for the time-dependence.
181 !% The float <tt>omega</tt> will be the carrier frequency of the
182 !% pulse (in energy units). The envelope of the field is a time-dependent function whose definition
183 !% must be given in a <tt>TDFunctions</tt> block. <tt>envelope_function_name</tt> is a string (and therefore
184 !% it must be surrounded by quotation marks) that must match one of the function names
185 !% given in the first column of the <tt>TDFunctions</tt> block.
186 !% <tt>phase</tt> is optional and is taken to be zero if not provided, and is also a string specifying
187 !% a time-dependent function.
188 !%
189 !% (A) type = <tt>electric field, magnetic field, vector_potential</tt>
190 !%
191 !% For these cases, the syntax is:
192 !%
193 !% <tt>%TDExternalFields
194 !% <br>&nbsp;&nbsp; type | nx | ny | nz | omega | envelope_function_name | phase (| px | py | pz )
195 !% <br>%</tt>
196 !%
197 !% The <tt>vector_potential</tt> option (constant in space) permits us to describe
198 !% an electric perturbation in the velocity gauge.
199 !% The three (possibly complex) numbers (<tt>nx</tt>, <tt>ny</tt>, <tt>nz</tt>) mark the polarization
200 !% direction of the field.
201 !% By default, (<tt>nx</tt>, <tt>ny</tt>, <tt>nz</tt>) are defined in Cartesian space.
202 !% However, it is possible for solids to define them using the Miller indices.
203 !% This can be achieved by defining the block <tt>MillerIndicesBasis</tt>. It is also possible to activate
204 !% the nondipole SFA correction by inserting the laser propagation direction px | py | pz as prescribed in
205 !% Phys. Rev. A 101, 043408 (2020).
206 !%
207 !% (B) type = <tt>scalar_potential</tt>
208 !%
209 !% <tt>%TDExternalFields
210 !% <br>&nbsp;&nbsp; scalar_potential | "spatial_expression" | omega | envelope_function_name | phase
211 !% <br>%</tt>
212 !%
213 !% The scalar potential is any expression of the spatial coordinates given by the string
214 !% "spatial_expression", allowing a field beyond the dipole approximation.
215 !%
216 !% For DFTB runs, only fields of type type = <tt>electric field</tt> are allowed for the moment, and the
217 !% <tt>type</tt> keyword is omitted.
218 !%
219 !% A NOTE ON UNITS:
220 !%
221 !% It is very common to describe the strength of a laser field by its intensity, rather
222 !% than using the electric-field amplitude. In atomic units (or, more precisely, in any
223 !% Gaussian system of units), the relationship between instantaneous electric field
224 !% and intensity is:
225 !% <math> I(t) = \frac{c}{8\pi} E^2(t) </math>.
226 !%
227 !% It is common to read intensities in W/cm<math>^2</math>. The dimensions of intensities are
228 !% [W]/(L<math>^2</math>T), where [W] are the dimensions of energy. The relevant conversion factors
229 !% are:
230 !%
231 !% Hartree / (<math>a_0^2</math> atomic_time) = <math>6.4364086 \times 10^{15} \mathrm{W/cm}^2</math>
232 !%
233 !% eV / ( &Aring;<math>^2 (\hbar</math>/eV) ) = <math>2.4341348 \times 10^{12} \mathrm{W/cm}^2</math>
234 !%
235 !% If, in atomic units, we set the electric-field amplitude to <math>E_0</math>,
236 !% then the intensity is:
237 !%
238 !% <math> I_0 = 3.51 \times 10^{16} \mathrm{W/cm}^2 (E_0^2) </math>
239 !%
240 !% If, working with <tt>Units = ev_angstrom</tt>, we set <math>E_0</math>, then the intensity is:
241 !%
242 !% <math> I_0 = 1.327 \times 10^{13} (E_0^2) \mathrm{W/cm}^2 </math>
243 !%
244 !%Option electric_field 1
245 !% The external field is an electric field, the usual case when we want to describe a
246 !% laser in the length gauge.
247 !%Option magnetic_field 2
248 !% The external field is a (homogeneous) time-dependent magnetic field.
249 !%Option vector_potential 3
250 !% The external field is a time-dependent homogeneous vector potential, which may describe
251 !% a laser field in the velocity gauge.
252 !%Option scalar_potential 4
253 !% The external field is an arbitrary scalar potential, which may describe an
254 !% inhomogeneous electrical field.
255 !%End
256
257 this%no_lasers = 0
258 if (parse_block(this%namespace, 'TDExternalFields', blk) == 0) then
259 this%no_lasers = parse_block_n(blk)
260 safe_allocate(this%lasers(1:this%no_lasers))
261
262 do il = 1, this%no_lasers
263 safe_allocate(this%lasers(il)%pol(1:3))
264 this%lasers(il)%pol = m_z0
265
266 call parse_block_integer(blk, il-1, 0, this%lasers(il)%field)
267
268 select case (this%lasers(il)%field)
270 call parse_block_string(blk, il-1, 1, this%scalar_pot_expression)
271 jj = 1
272 this%lasers(il)%pol = m_z1
273 case default
274 call parse_block_cmplx(blk, il-1, 1, this%lasers(il)%pol(1))
275 call parse_block_cmplx(blk, il-1, 2, this%lasers(il)%pol(2))
276 call parse_block_cmplx(blk, il-1, 3, this%lasers(il)%pol(3))
277 jj = 3
278 end select
279
280 call parse_block_float(blk, il-1, jj+1, omega0)
281 omega0 = units_to_atomic(units_inp%energy, omega0)
282
283 this%lasers(il)%omega = omega0
284
285 call parse_block_string(blk, il-1, jj+2, this%envelope_expression)
286 call tdf_read(this%lasers(il)%f, this%namespace, trim(this%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%phase_expression)
291 call tdf_read(this%lasers(il)%phi, this%namespace, trim(this%phase_expression), ierr)
292 if (ierr /= 0) then
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), &
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%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 message(1) = "The lasers break (at least) one of the symmetries used to reduce the k-points ."
383 !%
384 !% <tt>%MillerIndicesBasis
385 !% <br> 0.0 | 0.5 | 0.5
386 !% <br> 0.5 | 0.0 | 0.5
387 !% <br> 0.5 | 0.5 | 0.0
388 !% <br>%</tt>
389 !%
390 !% Indeed, in this case, the reciprocal lattice vectors are (-1, 1, 1), (1, -1, 1),
391 !% and (1, 1, -1) in units of 2*pi/a.
392 !% This directly gives that the [100] direction correspond to the x direction, [111]
393 !% gives the vector (1,1,1), etc.
394 !%
395 !%End
396 if (parse_block(this%namespace, 'MillerIndicesBasis', blk2) == 0) then
397 if(.not. space%is_periodic()) then
398 write(message(1),'(a)') 'MillerIndicesBasis can only be used for periodic systems.'
399 call messages_fatal(1, namespace=this%namespace)
400 end if
401
402 do idir = 1, space%dim
403 do idir2 = 1, space%dim
404 call parse_block_float(blk2, idir-1, idir2-1, miller_red(idir2, idir))
405 end do
406 call kpoints_to_absolute(latt, miller_red(:, idir), miller(:, idir))
407 end do
408
409
410 this%lasers(il)%pol = matmul(miller, this%lasers(il)%pol)
411 call parse_block_end(blk2)
412 end if
413
414 this%lasers(il)%pol(:) = this%lasers(il)%pol(:)/sqrt(sum(abs(this%lasers(il)%pol(:))**2))
415
416 select case (this%lasers(il)%field)
418 safe_allocate(this%lasers(il)%v(1:mesh%np_part))
419 this%lasers(il)%v = m_zero
420 do ip = 1, mesh%np
421 call mesh_r(mesh, ip, rr, coords = xx(1:space%dim))
422 xx(space%dim+1:3) = m_zero
423 call parse_expression(pot_re, pot_im, 3, xx, rr, m_zero, trim(this%scalar_pot_expression))
424 this%lasers(il)%v(ip) = pot_re
425 end do
426
427 case (e_field_magnetic)
428 ! \warning: note that for the moment we are ignoring the possibility of a complex
429 ! polarizability vector for the td magnetic-field case.
430 safe_allocate(this%lasers(il)%a(1:mesh%np_part, 1:3))
431 this%lasers(il)%a = m_zero
432 do ip = 1, mesh%np
433 xx(1:space%dim) = mesh%x(ip, :)
434 xx(space%dim+1:3) = m_zero
435 ! Compute the vector potential from a uniform B field.
436 ! The sign is determined by the relation $\vec{B} = \nabla \times \vec{A}$.
437 ! This leads to $\vec{A} = -\frac{1}{2}\vec{r}\times\vec{B}$.
438 select case (space%dim)
439 case (2)
440 this%lasers(il)%a(ip, :) = (/xx(2), -xx(1)/) * sign(m_one, real(this%lasers(il)%pol(3)))
441 case (3)
442 this%lasers(il)%a(ip, :) = (/ xx(2)*real(this%lasers(il)%pol(3)) - xx(3)*real(this%lasers(il)%pol(2)), &
443 xx(3)*real(this%lasers(il)%pol(1)) - xx(1)*real(this%lasers(il)%pol(3)), &
444 xx(1)*real(this%lasers(il)%pol(2)) - xx(2)*real(this%lasers(il)%pol(1)) /)
445 case default
446 message(1) = "Magnetic fields only allowed in 2 or 3D."
447 call messages_fatal(1, namespace=this%namespace)
448 end select
449 end do
450 this%lasers(il)%a = -m_half * this%lasers(il)%a
451
452 end select
453
454 end do
455
457 end subroutine lasers_generate_potentials
458
459
460 ! ---------------------------------------------------------
461 subroutine lasers_check_symmetries(this, kpoints)
462 type(lasers_t), intent(in) :: this
463 type(kpoints_t), intent(in) :: kpoints
464
465 integer :: iop, il
466
468
469 if (kpoints%use_symmetries) then
470 do iop = 1, symmetries_number(kpoints%symm)
471 if (iop == symmetries_identity_index(kpoints%symm)) cycle
472 do il = 1, this%no_lasers
473 if (.not. symm_op_invariant_cart(kpoints%symm%ops(iop), this%lasers(il)%pol(:), symprec)) then
474 message(1) = "The lasers break (at least) one of the symmetries used to reduce the k-points ."
475 message(2) = "Set SymmetryBreakDir accordingly to your laser fields."
476 call messages_fatal(2, namespace=this%namespace)
477 end if
478 end do
479 end do
480 end if
481
483 end subroutine lasers_check_symmetries
484
485 ! ---------------------------------------------------------
486 subroutine lasers_finalize(this)
487 type(lasers_t), intent(inout) :: this
488
489 push_sub(lasers_finalize)
490
491 call lasers_deallocate(this)
492
493 pop_sub(lasers_finalize)
494 end subroutine lasers_finalize
495
496 ! ---------------------------------------------------------
497 subroutine lasers_deallocate(this)
498 class(lasers_t), intent(inout) :: this
499
500 integer :: il
501
502 push_sub(lasers_deallocate)
503
504 safe_deallocate_a(this%e)
505 safe_deallocate_a(this%b)
506 safe_deallocate_a(this%integrated_nondipole_afield)
507
508 do il = 1, this%no_lasers
509 safe_deallocate_a(this%lasers(il)%pol)
510 call tdf_end(this%lasers(il)%f)
511 call tdf_end(this%lasers(il)%phi)
512 select case (this%lasers(il)%field)
514 safe_deallocate_a(this%lasers(il)%v)
515 case (e_field_magnetic)
516 safe_deallocate_a(this%lasers(il)%a)
517 end select
518 safe_deallocate_a(this%lasers(il)%prop)
519 end do
520 safe_deallocate_a(this%lasers)
521
522 pop_sub(lasers_deallocate)
523 end subroutine lasers_deallocate
524
525
526 ! ---------------------------------------------------------
527 real(real64) function laser_carrier_frequency(laser) result(w0)
528 type(laser_t), intent(in) :: laser
529
531
532 w0 = laser%omega
533
535 end function laser_carrier_frequency
536
537 ! ---------------------------------------------------------
538 subroutine lasers_init_interaction_as_partner(partner, interaction)
539 class(lasers_t), intent(in) :: partner
540 class(interaction_surrogate_t), intent(inout) :: interaction
541
543
544 select type (interaction)
545 type is (lorentz_force_t)
546 ! Nothing to be initialized for the Lorentz force.
547 class default
548 message(1) = "Unsupported interaction."
549 call messages_fatal(1, namespace=partner%namespace)
550 end select
551
555 ! ---------------------------------------------------------
556 subroutine lasers_update_quantity(this, label)
557 class(lasers_t), intent(inout) :: this
558 character(len=*), intent(in) :: label
559
560 type(quantity_t), pointer :: quantity
561 integer :: il
562
563 push_sub(lasers_update_quantity)
564
565 if (any(laser_kind(this%lasers) == e_field_vector_potential) .or. &
566 any(laser_kind(this%lasers) == e_field_scalar_potential)) then
567 call messages_not_implemented("Laser vector potentials and scalar potentials in multi-system framework", &
568 namespace=this%namespace)
569 end if
570
571 quantity => this%quantities%get(label)
572 select case (label)
573 case ("E field")
574 this%e = m_zero
575 do il = 1, this%no_lasers
576 if (laser_kind(this%lasers(il)) == e_field_electric) then
577 call laser_field(this%lasers(il), this%e, quantity%iteration%value())
578 end if
579 end do
580
581 case ("B field")
582 this%b = m_zero
583 do il = 1, this%no_lasers
584 if (laser_kind(this%lasers(il)) == e_field_magnetic) then
585 call laser_field(this%lasers(il), this%b, quantity%iteration%value())
586 end if
587 end do
588
589 case default
590 message(1) = "Incompatible quantity."
591 call messages_fatal(1, namespace=this%namespace)
592 end select
593
595 end subroutine lasers_update_quantity
596
597 ! ---------------------------------------------------------
598 subroutine lasers_copy_quantities_to_interaction(partner, interaction)
599 class(lasers_t), intent(inout) :: partner
600 class(interaction_surrogate_t), intent(inout) :: interaction
601
602 integer :: ip
603
605
606 select type (interaction)
607 type is (lorentz_force_t)
608 do ip = 1, interaction%system_np
609 interaction%partner_e_field(:, ip) = partner%e
610 interaction%partner_b_field(:, ip) = partner%b
611 end do
612 class default
613 message(1) = "Unsupported interaction."
614 call messages_fatal(1, namespace=partner%namespace)
615 end select
616
619
620 ! ---------------------------------------------------------
621 integer pure elemental function laser_kind(laser)
622 type(laser_t), intent(in) :: laser
623
624 ! no push_sub allowed in pure function
625 laser_kind = laser%field
626
627 end function laser_kind
628 ! ---------------------------------------------------------
629
630
631 ! ---------------------------------------------------------
632 function laser_polarization(laser) result(pol)
633 type(laser_t), intent(in) :: laser
634 complex(real64) :: pol(3)
635
636 push_sub(laser_polarization)
637
638 pol = laser%pol
639
640 pop_sub(laser_polarization)
641 end function laser_polarization
642 ! ---------------------------------------------------------
643
645 function lasers_with_nondipole_field(lasers) result(isnondipole)
646 type(lasers_t), intent(in) :: lasers
647 logical :: isnondipole
648
650 isnondipole = .false.
651 if(allocated(lasers%integrated_nondipole_afield)) isnondipole = .true.
653 end function lasers_with_nondipole_field
654 ! ---------------------------------------------------------
655
656
658 subroutine lasers_set_nondipole_parameters(this, ndfield, nd_integration_time)
659 type(lasers_t), intent(inout) :: this
660 real(real64), intent(in) :: ndfield(:)
661 real(real64), intent(in) :: nd_integration_time
662 integer :: dim
663 dim = size(ndfield)
664
666 this%integrated_nondipole_afield(1:dim) = ndfield(1:dim)
667 this%nd_integration_time = nd_integration_time
670
671
672 ! ---------------------------------------------------------
673 subroutine laser_get_f(laser, ff)
674 type(laser_t), intent(in) :: laser
675 type(tdf_t), intent(inout) :: ff
676
677 push_sub(laser_get_f)
678 call tdf_copy(ff, laser%f)
679
680 pop_sub(laser_get_f)
681 end subroutine laser_get_f
682 ! ---------------------------------------------------------
683
684
685 ! ---------------------------------------------------------
686 subroutine laser_set_f(laser, ff)
687 type(laser_t), intent(inout) :: laser
688 type(tdf_t), intent(inout) :: ff
689
690 push_sub(laser_set_f)
692 call tdf_end(laser%f)
693 call tdf_copy(laser%f, ff)
694
695 pop_sub(laser_set_f)
696 end subroutine laser_set_f
697 ! ---------------------------------------------------------
698
699
700 ! ---------------------------------------------------------
701 subroutine laser_get_phi(laser, phi)
702 type(laser_t), intent(in) :: laser
703 type(tdf_t), intent(inout) :: phi
704
705 push_sub(laser_get_phi)
706 call tdf_copy(phi, laser%phi)
707
708 pop_sub(laser_get_phi)
709 end subroutine laser_get_phi
710 ! ---------------------------------------------------------
711
712
713 ! ---------------------------------------------------------
714 subroutine laser_set_phi(laser, phi)
715 type(laser_t), intent(inout) :: laser
716 type(tdf_t), intent(inout) :: phi
717
718 push_sub(laser_set_phi)
719
720 call tdf_end(laser%phi)
721 call tdf_copy(laser%phi, phi)
722
723 pop_sub(laser_set_phi)
724 end subroutine laser_set_phi
725 ! ---------------------------------------------------------
726
727
728 ! ---------------------------------------------------------
729 subroutine laser_set_empty_phi(laser)
730 type(laser_t), intent(inout) :: laser
731
732 push_sub(laser_set_empty_phi)
733
734 call tdf_init(laser%phi)
735
736 pop_sub(laser_set_empty_phi)
737 end subroutine laser_set_empty_phi
738 ! ---------------------------------------------------------
739
740 ! ---------------------------------------------------------
741 subroutine laser_set_f_value(laser, ii, xx)
742 type(laser_t), intent(inout) :: laser
743 integer, intent(in) :: ii
744 real(real64), intent(in) :: xx
745
746 push_sub(laser_set_f_value)
747 call tdf_set_numerical(laser%f, ii, xx)
748
749 pop_sub(laser_set_f_value)
750 end subroutine laser_set_f_value
751 ! ---------------------------------------------------------
752
753
754 ! ---------------------------------------------------------
755 subroutine laser_set_frequency(laser, omega)
756 type(laser_t), intent(inout) :: laser
757 real(real64), intent(in) :: omega
758
759 push_sub(laser_set_frequency)
760 laser%omega = omega
761
762 pop_sub(laser_set_frequency)
763 end subroutine laser_set_frequency
764 ! ---------------------------------------------------------
765
767 ! ---------------------------------------------------------
768 subroutine laser_set_polarization(laser, pol)
769 type(laser_t), intent(inout) :: laser
770 complex(real64), intent(in) :: pol(:)
771
772 push_sub(laser_set_polarization)
773
774 laser%pol = pol
775
777 end subroutine laser_set_polarization
778 ! ---------------------------------------------------------
780
781 ! ---------------------------------------------------------
788 ! ---------------------------------------------------------
789 subroutine laser_to_numerical_all(laser, dt, max_iter, omegamax)
790 type(laser_t), intent(inout) :: laser
791 real(real64), intent(in) :: dt
792 integer, intent(in) :: max_iter
793 real(real64), intent(in) :: omegamax
795 integer :: iter
796 real(real64) :: tt, fj, phi
797
798 push_sub(lasers_to_numerical_all)
799
800 call tdf_to_numerical(laser%f, max_iter, dt, omegamax)
801 do iter = 1, max_iter + 1
802 tt = (iter-1)*dt
803 fj = tdf(laser%f, iter)
804 phi = tdf(laser%phi, tt)
805 call tdf_set_numerical(laser%f, iter, fj*cos(laser%omega*tt+phi))
806 end do
807 call tdf_end(laser%phi)
808 call tdf_init_cw(laser%phi, m_zero, m_zero)
809 laser%omega = m_zero
810
811 pop_sub(lasers_to_numerical_all)
812 end subroutine laser_to_numerical_all
813 ! ---------------------------------------------------------
814
815
816 ! ---------------------------------------------------------
819 ! ---------------------------------------------------------
820 subroutine laser_to_numerical(laser, dt, max_iter, omegamax)
821 type(laser_t), intent(inout) :: laser
822 real(real64), intent(in) :: dt
823 integer, intent(in) :: max_iter
824 real(real64), intent(in) :: omegamax
825
826 push_sub(lasers_to_numerical)
827
828 call tdf_to_numerical(laser%f, max_iter, dt, omegamax)
829 call tdf_to_numerical(laser%phi, max_iter, dt, omegamax)
830
831 pop_sub(lasers_to_numerical)
832 end subroutine laser_to_numerical
833 ! ---------------------------------------------------------
835 ! ---------------------------------------------------------
836 subroutine laser_write_info(lasers, namespace, dt, max_iter, iunit)
837 type(laser_t), intent(in) :: lasers(:)
838 type(namespace_t), intent(in) :: namespace
839 real(real64), optional, intent(in) :: dt
840 integer, optional, intent(in) :: max_iter
841 integer, optional, intent(in) :: iunit
842
843 real(real64) :: tt, fluence, max_intensity, intensity, dt_, field(3), up, maxfield,tmp
844 integer :: il, iter, no_l, max_iter_
845
846 push_sub(laser_write_info)
847
848 no_l = size(lasers)
849
850 do il = 1, no_l
851
852 if (present(dt)) then
853 dt_ = dt
854 else
855 dt_ = tdf_dt(lasers(il)%f)
856 end if
857 if (present(max_iter)) then
858 max_iter_ = max_iter
859 else
860 max_iter_ = tdf_niter(lasers(il)%f)
861 end if
862
863 write(message(1),'(i2,a)') il, ':'
864 select case (lasers(il)%field)
865 case (e_field_electric)
866 message(2) = ' Electric Field.'
867 case (e_field_magnetic)
868 message(2) = ' Magnetic Field.'
870 message(2) = ' Vector Potential.'
872 message(2) = ' Scalar Potential.'
873 end select
874 call messages_info(2, iunit=iunit, namespace=namespace)
875
876 if (lasers(il)%field /= e_field_scalar_potential) then
877 write(message(1),'(3x,a,3(a1,f7.4,a1,f7.4,a1))') 'Polarization: ', &
878 '(', real(lasers(il)%pol(1), real64), ',', aimag(lasers(il)%pol(1)), '), ', &
879 '(', real(lasers(il)%pol(2), real64), ',', aimag(lasers(il)%pol(2)), '), ', &
880 '(', real(lasers(il)%pol(3), real64), ',', aimag(lasers(il)%pol(3)), ')'
881 call messages_info(1, iunit=iunit, namespace=namespace)
882 end if
883
884 write(message(1),'(3x,a,f14.8,3a)') 'Carrier frequency = ', &
885 units_from_atomic(units_out%energy, lasers(il)%omega), &
886 ' [', trim(units_abbrev(units_out%energy)), ']'
887 message(2) = ' Envelope: '
888 call messages_info(2, iunit=iunit, namespace=namespace)
889 call tdf_write(lasers(il)%f, iunit)
890
891 if (.not. tdf_is_empty(lasers(il)%phi)) then
892 message(1) = ' Phase: '
893 call messages_info(1, iunit=iunit, namespace=namespace)
894 call tdf_write(lasers(il)%phi, iunit)
895 end if
896
897 ! 1 atomic unit of intensity = 3.5094448e+16 W / cm^2
898 ! In a Gaussian system of units,
899 ! I(t) = (1/(8\pi)) * c * E(t)^2
900 ! (1/(8\pi)) * c = 5.4525289841210 a.u.
901 if (lasers(il)%field == e_field_electric .or. lasers(il)%field == e_field_vector_potential) then
902 fluence = m_zero
903 max_intensity = m_zero
904 maxfield= m_zero
905 do iter = 1, max_iter_
906 tt = iter * dt_
907 call laser_electric_field(lasers(il), field, tt, dt_)
908 intensity = 5.4525289841210_real64*sum(field**2)
909 fluence = fluence + intensity
910 if (intensity > max_intensity) max_intensity = intensity
911
912 tmp = sum(field(:)**2)
913 if (tmp > maxfield) maxfield = tmp
914 end do
915 fluence = fluence * dt_
916
917 write(message(1),'(a,es17.6,3a)') ' Peak intensity = ', max_intensity, ' [a.u]'
918 write(message(2),'(a,es17.6,3a)') ' = ', &
919 max_intensity * 6.4364086e+15_real64, ' [W/cm^2]'
920 write(message(3),'(a,es17.6,a)') ' Int. intensity = ', fluence, ' [a.u]'
921 write(message(4),'(a,es17.6,a)') ' Fluence = ', &
922 fluence / 5.4525289841210_real64 , ' [a.u]'
923 call messages_info(4, iunit=iunit, namespace=namespace)
924
925 if (abs(lasers(il)%omega) > m_epsilon) then
926 ! Ponderomotive Energy is the cycle-averaged kinetic energy of
927 ! a free electron quivering in the field
928 ! Up = E^2/(4*\omega^2)
930 ! subroutine laser_to_numerical_all sets lasers%omega to zero
931 !
932 up = maxfield/(4*lasers(il)%omega**2)
933
934 write(message(1),'(a,es17.6,3a)') ' Ponderomotive energy = ', &
935 units_from_atomic(units_out%energy, up) ,&
936 ' [', trim(units_abbrev(units_out%energy)), ']'
937 call messages_info(1, iunit=iunit, namespace=namespace)
938 end if
939 end if
940
941 end do
942
943 pop_sub(laser_write_info)
944 end subroutine laser_write_info
945 ! ---------------------------------------------------------
946
947
948 ! ---------------------------------------------------------
949 subroutine laser_potential(laser, mesh, pot, time)
950 type(laser_t), intent(in) :: laser
951 class(mesh_t), intent(in) :: mesh
952 real(real64), intent(inout) :: pot(:)
953 real(real64), optional, intent(in) :: time
954
955 complex(real64) :: amp
956 integer :: ip
957 real(real64) :: field(3)
958
959 push_sub(laser_potential)
960
961 if (present(time)) then
962 amp = tdf(laser%f, time) * exp(m_zi * (laser%omega * time + tdf(laser%phi, time)))
963 else
964 amp = m_z1
965 end if
966
967 select case (laser%field)
969 pot(1:mesh%np) = pot(1:mesh%np) + real(amp, real64) * laser%v(1:mesh%np)
970 case default
971 field(:) = real(amp * laser%pol(:), real64)
972 do ip = 1, mesh%np
973 ! The -1 sign is missing here. Check epot.F90 for the explanation.
974 pot(ip) = pot(ip) + sum(field(1:mesh%box%dim) * mesh%x(ip, 1:mesh%box%dim))
975 end do
976 end select
977
978 pop_sub(laser_potential)
979 end subroutine laser_potential
980 ! ---------------------------------------------------------
981
982
983 ! ---------------------------------------------------------
984 subroutine laser_vector_potential(laser, mesh, aa, time)
985 type(laser_t), intent(in) :: laser
986 type(mesh_t), intent(in) :: mesh
987 real(real64), intent(inout) :: aa(:, :)
988 real(real64), optional, intent(in) :: time
989
990 real(real64) :: amp
991 integer :: ip, idir
992
993 push_sub(laser_vector_potential)
994
995 if (present(time)) then
996 amp = tdf(laser%f, time)*cos((laser%omega*time + tdf(laser%phi, time)))
997 do idir = 1, mesh%box%dim
998 do ip = 1, mesh%np
999 aa(ip, idir) = aa(ip, idir) + amp*laser%a(ip, idir)
1000 end do
1001 end do
1002 else
1003 do idir = 1, mesh%box%dim
1004 do ip = 1, mesh%np
1005 aa(ip, idir) = aa(ip, idir) + laser%a(ip, idir)
1006 end do
1007 end do
1008 end if
1009
1010 pop_sub(laser_vector_potential)
1011 end subroutine laser_vector_potential
1012 ! ---------------------------------------------------------
1013
1014
1015 ! ---------------------------------------------------------
1021 subroutine laser_field(laser, field, time)
1022 type(laser_t), intent(in) :: laser
1023 real(real64), intent(inout) :: field(:)
1024 real(real64), optional, intent(in) :: time
1025
1026 integer :: dim
1027 complex(real64) :: amp
1028
1029 !no PUSH SUB, called too often
1030
1031 dim = size(field)
1032
1033 if (present(time)) then
1034 amp = tdf(laser%f, time) * exp(m_zi * (laser%omega * time + tdf(laser%phi, time)))
1035 else
1036 amp = m_z1
1037 end if
1038 if (laser%field == e_field_scalar_potential) then
1039 ! In this case we will just return the value of the time function. The "field", in fact,
1040 ! should be a function of the position in space (thus, a true "field"), given by the
1041 ! gradient of the scalar potential.
1042 field(1) = field(1) + real(amp, real64)
1043 else
1044 field(1:dim) = field(1:dim) + real(amp*laser%pol(1:dim), real64)
1045 end if
1046 end subroutine laser_field
1047
1048! ---------------------------------------------------------
1056 subroutine lasers_nondipole_laser_field_step(this, field, time)
1057 type(lasers_t), intent(in) :: this
1058 real(real64), intent(out) :: field(:)
1059 real(real64), intent(in) :: time
1060
1061 real(real64) :: a0(3)
1062 real(real64) :: e0(3)
1063 integer :: ilaser
1064 integer :: jlaser
1065 integer :: dim
1066 integer :: iter
1067 dim = size(field)
1068
1069 field(1:dim) = this%integrated_nondipole_afield(1:dim)
1070 if (time - this%nd_integration_time < 0) then
1071 return
1072 endif
1073 do iter = 1, nint((time-this%nd_integration_time)/this%nd_integration_step)
1074 do ilaser = 1, this%no_lasers
1075 if(laser_kind(this%lasers(ilaser)) /= e_field_vector_potential) cycle
1076 do jlaser = 1, this%no_lasers
1077 if(laser_kind(this%lasers(jlaser)) /= e_field_vector_potential) cycle
1078 if(allocated(this%lasers(jlaser)%prop)) then
1079 a0 = m_zero
1080 call laser_field(this%lasers(ilaser), a0, &
1081 iter*this%nd_integration_step+this%nd_integration_time)
1082 call laser_electric_field(this%lasers(jlaser), e0, &
1083 iter*this%nd_integration_step+this%nd_integration_time, this%nd_integration_step)
1084 ! We have front factor q/(mc) with q=-abs(e) =-1 a.u. and m = 1 a.u.
1085 field(1:dim) = field(1:dim) - m_one/(p_c) * this%nd_integration_step &
1086 * dot_product(a0,e0) * this%lasers(jlaser)%prop(1:dim)
1087 end if
1088 end do
1089 end do
1090 end do
1092
1093
1094 ! ---------------------------------------------------------
1097 subroutine laser_electric_field(laser, field, time, dt)
1098 type(laser_t), intent(in) :: laser
1099 real(real64), intent(out) :: field(:)
1100 real(real64), intent(in) :: time
1101 real(real64), intent(in) :: dt
1102
1103 integer :: dim
1104 real(real64), allocatable :: field1(:), field2(:)
1105
1106 !no PUSH SUB, called too often
1107
1108 dim = size(field)
1109
1110 select case (laser%field)
1111 case (e_field_electric)
1112 field = m_zero
1113 call laser_field(laser, field(1:dim), time)
1115 safe_allocate(field1(1:dim))
1116 safe_allocate(field2(1:dim))
1117 field1 = m_zero
1118 field2 = m_zero
1119 call laser_field(laser, field1(1:dim), time - dt)
1120 call laser_field(laser, field2(1:dim), time + dt)
1121 field = - (field2 - field1) / (m_two * p_c * dt)
1122 safe_deallocate_a(field1)
1123 safe_deallocate_a(field2)
1124 case default
1125 field = m_zero
1126 end select
1127
1128 end subroutine laser_electric_field
1129 ! ---------------------------------------------------------
1130
1131 ! ---------------------------------------------------------
1132 ! Loading of the lasers for the multisystem framework
1133 ! Ultimately this should be done in laser_init
1134 subroutine load_lasers(partners, namespace)
1135 class(partner_list_t), intent(inout) :: partners
1136 type(namespace_t), intent(in) :: namespace
1137
1138 class(lasers_t), pointer :: lasers
1139 integer :: il
1140
1141 push_sub(load_lasers)
1142
1143 lasers => lasers_t(namespace)
1144
1145 call lasers_parse_external_fields(lasers)
1146
1147 ! TODO: see how to do this in the multisystem framework
1148 if (parse_is_defined(namespace, 'MillerIndicesBasis')) then
1149 call messages_not_implemented("MillerIndicesBasis with load_lasers routine")
1150 end if
1151
1152 ! This is done normally in lasers_generate_potential, but we cannot call this routine here,
1153 ! so we do it here
1154 do il = 1, lasers%no_lasers
1155 lasers%lasers(il)%pol(:) = lasers%lasers(il)%pol(:)/sqrt(sum(abs(lasers%lasers(il)%pol(:))**2))
1156 end do
1157
1158 call lasers%quantities%add(quantity_t("E field", always_available = .true., updated_on_demand = .true., iteration = clock_t()))
1159 call lasers%quantities%add(quantity_t("B field", always_available = .true., updated_on_demand = .true., iteration = clock_t()))
1160
1161 lasers%supported_interactions_as_partner = [lorentz_force]
1162
1163 if (lasers%no_lasers > 0) then
1164 call partners%add(lasers)
1165 else
1166 safe_deallocate_p(lasers)
1167 end if
1168
1169 pop_sub(load_lasers)
1170 end subroutine load_lasers
1171
1172end module lasers_oct_m
1173
1174!! Local Variables:
1175!! mode: f90
1176!! coding: utf-8
1177!! End:
double exp(double __x) __attribute__((__nothrow__
double sqrt(double __x) __attribute__((__nothrow__
double cos(double __x) __attribute__((__nothrow__
__clock_t clock_t
Definition: metis_f.c:397
real(real64), parameter, public m_zero
Definition: global.F90:188
complex(real64), parameter, public m_z0
Definition: global.F90:198
real(real64), parameter, public m_epsilon
Definition: global.F90:204
complex(real64), parameter, public m_z1
Definition: global.F90:199
real(real64), parameter, public m_half
Definition: global.F90:194
real(real64), parameter, public m_one
Definition: global.F90:189
This module defines classes and functions for interaction partners.
subroutine, public kpoints_to_absolute(latt, kin, kout)
Definition: kpoints.F90:1031
subroutine, public load_lasers(partners, namespace)
Definition: lasers.F90:1228
complex(real64) function, dimension(3), public laser_polarization(laser)
Definition: lasers.F90:726
subroutine, public laser_set_phi(laser, phi)
Definition: lasers.F90:808
subroutine, public lasers_check_symmetries(this, kpoints)
Definition: lasers.F90:555
subroutine lasers_copy_quantities_to_interaction(partner, interaction)
Definition: lasers.F90:692
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:883
subroutine, public laser_vector_potential(laser, mesh, aa, time)
Definition: lasers.F90:1078
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:1150
subroutine, public lasers_parse_external_fields(this)
Definition: lasers.F90:244
subroutine, public lasers_set_nondipole_parameters(this, ndfield, nd_integration_time)
Set parameters for nondipole SFA calculation.
Definition: lasers.F90:752
subroutine lasers_update_quantity(this, label)
Definition: lasers.F90:650
subroutine, public laser_get_f(laser, ff)
Definition: lasers.F90:767
subroutine, public laser_set_f(laser, ff)
Definition: lasers.F90:780
logical function, public lasers_with_nondipole_field(lasers)
Check if a nondipole SFA correction should be computed for the given laser.
Definition: lasers.F90:739
subroutine, public laser_write_info(lasers, namespace, dt, max_iter, iunit)
Definition: lasers.F90:930
subroutine, public laser_set_empty_phi(laser)
Definition: lasers.F90:823
real(real64) function, public laser_carrier_frequency(laser)
Definition: lasers.F90:621
integer, parameter, public e_field_electric
Definition: lasers.F90:177
integer, parameter, public e_field_vector_potential
Definition: lasers.F90:177
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:914
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:1191
subroutine, public lasers_generate_potentials(this, mesh, space, latt)
Definition: lasers.F90:444
subroutine lasers_init_interaction_as_partner(partner, interaction)
Definition: lasers.F90:632
subroutine lasers_finalize(this)
Definition: lasers.F90:580
subroutine, public laser_potential(laser, mesh, pot, time)
Definition: lasers.F90:1043
class(lasers_t) function, pointer lasers_constructor(namespace)
Definition: lasers.F90:226
integer, parameter, public e_field_scalar_potential
Definition: lasers.F90:177
integer pure elemental function, public laser_kind(laser)
Definition: lasers.F90:715
subroutine, public laser_set_frequency(laser, omega)
Definition: lasers.F90:849
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:1115
subroutine, public laser_set_polarization(laser, pol)
Definition: lasers.F90:862
subroutine, public laser_set_f_value(laser, ii, xx)
Definition: lasers.F90:835
subroutine, public laser_get_phi(laser, phi)
Definition: lasers.F90:795
subroutine lasers_deallocate(this)
Definition: lasers.F90:591
integer, parameter, public e_field_magnetic
Definition: lasers.F90:177
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:115
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
pure subroutine, public mesh_r(mesh, ip, rr, origin, coords)
return the distance to the origin for a given grid point
Definition: mesh.F90:336
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:537
subroutine, public messages_obsolete_variable(namespace, name, rep)
Definition: messages.F90:1045
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:414
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:616
integer function, public parse_block(namespace, name, blk, check_varinfo_)
Definition: parser.F90:618
This module defines the quantity_t class and the IDs for quantities, which can be exposed by a system...
Definition: quantity.F90:138
integer pure function, public symmetries_identity_index(this)
Definition: symmetries.F90:586
real(real64), public symprec
Definition: symmetries.F90:169
integer pure function, public symmetries_number(this)
Definition: symmetries.F90:540
subroutine, public tdf_end(f)
Definition: tdfunction.F90:974
subroutine, public tdf_init(f)
Definition: tdfunction.F90:388
subroutine, public tdf_read(f, namespace, function_name, ierr)
This function initializes "f" from the TDFunctions block.
Definition: tdfunction.F90:218
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:132
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.
Definition: mesh.F90:186
int true(void)