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 character(len=200) :: scalar_pot_expression
103 character(len=200) :: phase_expression
104 character(len=200) :: envelope_expression
105 end type laser_t
106
107 type, extends(interaction_partner_t) :: lasers_t
108 private
109
110 integer, public :: no_lasers
111 type(laser_t), allocatable, public :: lasers(:)
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%lasers(il)%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%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 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%lasers(il)%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, 1:2) = (/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 (allocated(this%lasers)) then
566 if (any(laser_kind(this%lasers) == e_field_vector_potential) .or. &
567 any(laser_kind(this%lasers) == e_field_scalar_potential)) then
568 call messages_not_implemented("Laser vector potentials and scalar potentials in multi-system framework", &
569 namespace=this%namespace)
570 end if
571 end if
572
573 quantity => this%quantities%get(label)
574 select case (label)
575 case ("E field")
576 this%e = m_zero
577 do il = 1, this%no_lasers
578 if (laser_kind(this%lasers(il)) == e_field_electric) then
579 call laser_field(this%lasers(il), this%e, quantity%iteration%value())
580 end if
581 end do
582
583 case ("B field")
584 this%b = m_zero
585 do il = 1, this%no_lasers
586 if (laser_kind(this%lasers(il)) == e_field_magnetic) then
587 call laser_field(this%lasers(il), this%b, quantity%iteration%value())
588 end if
589 end do
591 case default
592 message(1) = "Incompatible quantity."
593 call messages_fatal(1, namespace=this%namespace)
594 end select
595
597 end subroutine lasers_update_quantity
598
599 ! ---------------------------------------------------------
600 subroutine lasers_copy_quantities_to_interaction(partner, interaction)
601 class(lasers_t), intent(inout) :: partner
602 class(interaction_surrogate_t), intent(inout) :: interaction
603
604 integer :: ip
605
607
608 select type (interaction)
609 type is (lorentz_force_t)
610 do ip = 1, interaction%system_np
611 interaction%partner_e_field(:, ip) = partner%e
612 interaction%partner_b_field(:, ip) = partner%b
613 end do
614 class default
615 message(1) = "Unsupported interaction."
616 call messages_fatal(1, namespace=partner%namespace)
617 end select
618
621
622 ! ---------------------------------------------------------
623 integer pure elemental function laser_kind(laser)
624 type(laser_t), intent(in) :: laser
625
626 ! no push_sub allowed in pure function
627 laser_kind = laser%field
628
629 end function laser_kind
630 ! ---------------------------------------------------------
632
633 ! ---------------------------------------------------------
634 function laser_polarization(laser) result(pol)
635 type(laser_t), intent(in) :: laser
636 complex(real64) :: pol(3)
637
638 push_sub(laser_polarization)
639
640 pol = laser%pol
641
642 pop_sub(laser_polarization)
643 end function laser_polarization
644 ! ---------------------------------------------------------
645
647 function lasers_with_nondipole_field(lasers) result(isnondipole)
648 type(lasers_t), intent(in) :: lasers
649 logical :: isnondipole
650
652 isnondipole = .false.
653 if(allocated(lasers%integrated_nondipole_afield)) isnondipole = .true.
655 end function lasers_with_nondipole_field
656 ! ---------------------------------------------------------
657
658
660 subroutine lasers_set_nondipole_parameters(this, ndfield, nd_integration_time)
661 type(lasers_t), intent(inout) :: this
662 real(real64), intent(in) :: ndfield(:)
663 real(real64), intent(in) :: nd_integration_time
664 integer :: dim
665 dim = size(ndfield)
666
668
669 this%integrated_nondipole_afield(1:dim) = ndfield(1:dim)
670 this%nd_integration_time = nd_integration_time
671
674
675
676 ! ---------------------------------------------------------
677 subroutine laser_get_f(laser, ff)
678 type(laser_t), intent(in) :: laser
679 type(tdf_t), intent(inout) :: ff
680
681 push_sub(laser_get_f)
682 call tdf_copy(ff, laser%f)
683
684 pop_sub(laser_get_f)
685 end subroutine laser_get_f
686 ! ---------------------------------------------------------
687
688
689 ! ---------------------------------------------------------
690 subroutine laser_set_f(laser, ff)
691 type(laser_t), intent(inout) :: laser
692 type(tdf_t), intent(inout) :: ff
694 push_sub(laser_set_f)
695
696 call tdf_end(laser%f)
697 call tdf_copy(laser%f, ff)
698
699 pop_sub(laser_set_f)
700 end subroutine laser_set_f
701 ! ---------------------------------------------------------
702
703
704 ! ---------------------------------------------------------
705 subroutine laser_get_phi(laser, phi)
706 type(laser_t), intent(in) :: laser
707 type(tdf_t), intent(inout) :: phi
708
709 push_sub(laser_get_phi)
710 call tdf_copy(phi, laser%phi)
711
712 pop_sub(laser_get_phi)
713 end subroutine laser_get_phi
714 ! ---------------------------------------------------------
715
717 ! ---------------------------------------------------------
718 subroutine laser_set_phi(laser, phi)
719 type(laser_t), intent(inout) :: laser
720 type(tdf_t), intent(inout) :: phi
721
722 push_sub(laser_set_phi)
723
724 call tdf_end(laser%phi)
725 call tdf_copy(laser%phi, phi)
726
728 end subroutine laser_set_phi
729 ! ---------------------------------------------------------
730
731
732 ! ---------------------------------------------------------
733 subroutine laser_set_empty_phi(laser)
734 type(laser_t), intent(inout) :: laser
735
736 push_sub(laser_set_empty_phi)
737
738 call tdf_init(laser%phi)
739
741 end subroutine laser_set_empty_phi
742 ! ---------------------------------------------------------
743
744 ! ---------------------------------------------------------
745 subroutine laser_set_f_value(laser, ii, xx)
746 type(laser_t), intent(inout) :: laser
747 integer, intent(in) :: ii
748 real(real64), intent(in) :: xx
749
750 push_sub(laser_set_f_value)
751 call tdf_set_numerical(laser%f, ii, xx)
752
754 end subroutine laser_set_f_value
755 ! ---------------------------------------------------------
756
757
758 ! ---------------------------------------------------------
759 subroutine laser_set_frequency(laser, omega)
760 type(laser_t), intent(inout) :: laser
761 real(real64), intent(in) :: omega
762
763 push_sub(laser_set_frequency)
764 laser%omega = omega
765
766 pop_sub(laser_set_frequency)
767 end subroutine laser_set_frequency
768 ! ---------------------------------------------------------
769
771 ! ---------------------------------------------------------
772 subroutine laser_set_polarization(laser, pol)
773 type(laser_t), intent(inout) :: laser
774 complex(real64), intent(in) :: pol(:)
775
776 push_sub(laser_set_polarization)
777
778 laser%pol = pol
779
781 end subroutine laser_set_polarization
782 ! ---------------------------------------------------------
784
785 ! ---------------------------------------------------------
792 ! ---------------------------------------------------------
793 subroutine laser_to_numerical_all(laser, dt, max_iter, omegamax)
794 type(laser_t), intent(inout) :: laser
795 real(real64), intent(in) :: dt
796 integer, intent(in) :: max_iter
797 real(real64), intent(in) :: omegamax
799 integer :: iter
800 real(real64) :: tt, fj, phi
801
802 push_sub(lasers_to_numerical_all)
803
804 call tdf_to_numerical(laser%f, max_iter, dt, omegamax)
805 do iter = 1, max_iter + 1
806 tt = (iter-1)*dt
807 fj = tdf(laser%f, iter)
808 phi = tdf(laser%phi, tt)
809 call tdf_set_numerical(laser%f, iter, fj*cos(laser%omega*tt+phi))
810 end do
811 call tdf_end(laser%phi)
812 call tdf_init_cw(laser%phi, m_zero, m_zero)
813 laser%omega = m_zero
814
815 pop_sub(lasers_to_numerical_all)
816 end subroutine laser_to_numerical_all
817 ! ---------------------------------------------------------
818
819
820 ! ---------------------------------------------------------
823 ! ---------------------------------------------------------
824 subroutine laser_to_numerical(laser, dt, max_iter, omegamax)
825 type(laser_t), intent(inout) :: laser
826 real(real64), intent(in) :: dt
827 integer, intent(in) :: max_iter
828 real(real64), intent(in) :: omegamax
829
830 push_sub(lasers_to_numerical)
831
832 call tdf_to_numerical(laser%f, max_iter, dt, omegamax)
833 call tdf_to_numerical(laser%phi, max_iter, dt, omegamax)
834
835 pop_sub(lasers_to_numerical)
836 end subroutine laser_to_numerical
837 ! ---------------------------------------------------------
839 ! ---------------------------------------------------------
840 subroutine laser_write_info(lasers, namespace, dt, max_iter, iunit)
841 type(laser_t), intent(in) :: lasers(:)
842 type(namespace_t), intent(in) :: namespace
843 real(real64), optional, intent(in) :: dt
844 integer, optional, intent(in) :: max_iter
845 integer, optional, intent(in) :: iunit
846
847 real(real64) :: tt, fluence, max_intensity, intensity, dt_, field(3), up, maxfield,tmp
848 integer :: il, iter, no_l, max_iter_
849
850 push_sub(laser_write_info)
851
852 no_l = size(lasers)
853
854 do il = 1, no_l
855
856 if (present(dt)) then
857 dt_ = dt
858 else
859 dt_ = tdf_dt(lasers(il)%f)
860 end if
861 if (present(max_iter)) then
862 max_iter_ = max_iter
863 else
864 max_iter_ = tdf_niter(lasers(il)%f)
865 end if
866
867 write(message(1),'(i2,a)') il, ':'
868 select case (lasers(il)%field)
869 case (e_field_electric)
870 message(2) = ' Electric Field.'
871 case (e_field_magnetic)
872 message(2) = ' Magnetic Field.'
874 message(2) = ' Vector Potential.'
876 message(2) = ' Scalar Potential.'
877 end select
878 call messages_info(2, iunit=iunit, namespace=namespace)
879
880 if (lasers(il)%field /= e_field_scalar_potential) then
881 write(message(1),'(3x,a,3(a1,f7.4,a1,f7.4,a1))') 'Polarization: ', &
882 '(', real(lasers(il)%pol(1), real64), ',', aimag(lasers(il)%pol(1)), '), ', &
883 '(', real(lasers(il)%pol(2), real64), ',', aimag(lasers(il)%pol(2)), '), ', &
884 '(', real(lasers(il)%pol(3), real64), ',', aimag(lasers(il)%pol(3)), ')'
885 call messages_info(1, iunit=iunit, namespace=namespace)
886 end if
887
888 write(message(1),'(3x,a,f14.8,3a)') 'Carrier frequency = ', &
889 units_from_atomic(units_out%energy, lasers(il)%omega), &
890 ' [', trim(units_abbrev(units_out%energy)), ']'
891 message(2) = ' Envelope: '
892 call messages_info(2, iunit=iunit, namespace=namespace)
893 call tdf_write(lasers(il)%f, iunit)
894
895 if (.not. tdf_is_empty(lasers(il)%phi)) then
896 message(1) = ' Phase: '
897 call messages_info(1, iunit=iunit, namespace=namespace)
898 call tdf_write(lasers(il)%phi, iunit)
899 end if
900
901 ! 1 atomic unit of intensity = 3.5094448e+16 W / cm^2
902 ! In a Gaussian system of units,
903 ! I(t) = (1/(8\pi)) * c * E(t)^2
904 ! (1/(8\pi)) * c = 5.4525289841210 a.u.
905 if (lasers(il)%field == e_field_electric .or. lasers(il)%field == e_field_vector_potential) then
906 fluence = m_zero
907 max_intensity = m_zero
908 maxfield= m_zero
909 do iter = 1, max_iter_
910 tt = iter * dt_
911 call laser_electric_field(lasers(il), field, tt, dt_)
912 intensity = 5.4525289841210_real64*sum(field**2)
913 fluence = fluence + intensity
914 if (intensity > max_intensity) max_intensity = intensity
915
916 tmp = sum(field(:)**2)
917 if (tmp > maxfield) maxfield = tmp
918 end do
919 fluence = fluence * dt_
920
921 write(message(1),'(a,es17.6,3a)') ' Peak intensity = ', max_intensity, ' [a.u]'
922 write(message(2),'(a,es17.6,3a)') ' = ', &
923 max_intensity * 6.4364086e+15_real64, ' [W/cm^2]'
924 write(message(3),'(a,es17.6,a)') ' Int. intensity = ', fluence, ' [a.u]'
925 write(message(4),'(a,es17.6,a)') ' Fluence = ', &
926 fluence / 5.4525289841210_real64 , ' [a.u]'
927 call messages_info(4, iunit=iunit, namespace=namespace)
928
929 if (abs(lasers(il)%omega) > m_epsilon) then
930 ! Ponderomotive Energy is the cycle-averaged kinetic energy of
931 ! a free electron quivering in the field
932 ! Up = E^2/(4*\omega^2)
934 ! subroutine laser_to_numerical_all sets lasers%omega to zero
935 !
936 up = maxfield/(4*lasers(il)%omega**2)
937
938 write(message(1),'(a,es17.6,3a)') ' Ponderomotive energy = ', &
939 units_from_atomic(units_out%energy, up) ,&
940 ' [', trim(units_abbrev(units_out%energy)), ']'
941 call messages_info(1, iunit=iunit, namespace=namespace)
942 end if
943 end if
944
945 end do
946
947 pop_sub(laser_write_info)
948 end subroutine laser_write_info
949 ! ---------------------------------------------------------
950
951
952 ! ---------------------------------------------------------
953 subroutine laser_potential(laser, mesh, pot, time)
954 type(laser_t), intent(in) :: laser
955 class(mesh_t), intent(in) :: mesh
956 real(real64), intent(inout) :: pot(:)
957 real(real64), optional, intent(in) :: time
958
959 complex(real64) :: amp
960 integer :: ip
961 real(real64) :: field(3)
962
963 push_sub(laser_potential)
964
965 if (present(time)) then
966 amp = tdf(laser%f, time) * exp(m_zi * (laser%omega * time + tdf(laser%phi, time)))
967 else
968 amp = m_z1
969 end if
970
971 select case (laser%field)
973 pot(1:mesh%np) = pot(1:mesh%np) + real(amp, real64) * laser%v(1:mesh%np)
974 case default
975 field(:) = real(amp * laser%pol(:), real64)
976 do ip = 1, mesh%np
977 ! The -1 sign is missing here. Check epot.F90 for the explanation.
978 pot(ip) = pot(ip) + sum(field(1:mesh%box%dim) * mesh%x(ip, 1:mesh%box%dim))
979 end do
980 end select
981
982 pop_sub(laser_potential)
983 end subroutine laser_potential
984 ! ---------------------------------------------------------
985
986
987 ! ---------------------------------------------------------
988 subroutine laser_vector_potential(laser, mesh, aa, time)
989 type(laser_t), intent(in) :: laser
990 type(mesh_t), intent(in) :: mesh
991 real(real64), intent(inout) :: aa(:, :)
992 real(real64), optional, intent(in) :: time
993
994 real(real64) :: amp
995 integer :: ip, idir
996
997 push_sub(laser_vector_potential)
998
999 if (present(time)) then
1000 amp = tdf(laser%f, time)*cos((laser%omega*time + tdf(laser%phi, time)))
1001 do idir = 1, mesh%box%dim
1002 do ip = 1, mesh%np
1003 aa(ip, idir) = aa(ip, idir) + amp*laser%a(ip, idir)
1004 end do
1005 end do
1006 else
1007 do idir = 1, mesh%box%dim
1008 do ip = 1, mesh%np
1009 aa(ip, idir) = aa(ip, idir) + laser%a(ip, idir)
1010 end do
1011 end do
1012 end if
1013
1014 pop_sub(laser_vector_potential)
1015 end subroutine laser_vector_potential
1016 ! ---------------------------------------------------------
1017
1018
1019 ! ---------------------------------------------------------
1025 subroutine laser_field(laser, field, time)
1026 type(laser_t), intent(in) :: laser
1027 real(real64), intent(inout) :: field(:)
1028 real(real64), optional, intent(in) :: time
1029
1030 integer :: dim
1031 complex(real64) :: amp
1032
1033 !no PUSH SUB, called too often
1034
1035 dim = size(field)
1036
1037 if (present(time)) then
1038 amp = tdf(laser%f, time) * exp(m_zi * (laser%omega * time + tdf(laser%phi, time)))
1039 else
1040 amp = m_z1
1041 end if
1042 if (laser%field == e_field_scalar_potential) then
1043 ! In this case we will just return the value of the time function. The "field", in fact,
1044 ! should be a function of the position in space (thus, a true "field"), given by the
1045 ! gradient of the scalar potential.
1046 field(1) = field(1) + real(amp, real64)
1047 else
1048 field(1:dim) = field(1:dim) + real(amp*laser%pol(1:dim), real64)
1049 end if
1050 end subroutine laser_field
1051
1052! ---------------------------------------------------------
1060 subroutine lasers_nondipole_laser_field_step(this, field, time)
1061 type(lasers_t), intent(in) :: this
1062 real(real64), intent(out) :: field(:)
1063 real(real64), intent(in) :: time
1064
1065 real(real64) :: a0(3)
1066 real(real64) :: e0(3)
1067 integer :: ilaser
1068 integer :: jlaser
1069 integer :: dim
1070 integer :: iter
1071 dim = size(field)
1072
1073 field(1:dim) = this%integrated_nondipole_afield(1:dim)
1074 if (time - this%nd_integration_time < 0) then
1075 return
1076 endif
1077 do iter = 1, nint((time-this%nd_integration_time)/this%nd_integration_step)
1078 do ilaser = 1, this%no_lasers
1079 if(laser_kind(this%lasers(ilaser)) /= e_field_vector_potential) cycle
1080 do jlaser = 1, this%no_lasers
1081 if(laser_kind(this%lasers(jlaser)) /= e_field_vector_potential) cycle
1082 if(allocated(this%lasers(jlaser)%prop)) then
1083 a0 = m_zero
1084 call laser_field(this%lasers(ilaser), a0, &
1085 iter*this%nd_integration_step+this%nd_integration_time)
1086 call laser_electric_field(this%lasers(jlaser), e0, &
1087 iter*this%nd_integration_step+this%nd_integration_time, this%nd_integration_step)
1088 ! We have front factor q/(mc) with q=-abs(e) =-1 a.u. and m = 1 a.u.
1089 field(1:dim) = field(1:dim) - m_one/(p_c) * this%nd_integration_step &
1090 * dot_product(a0,e0) * this%lasers(jlaser)%prop(1:dim)
1091 end if
1092 end do
1093 end do
1094 end do
1096
1097
1098 ! ---------------------------------------------------------
1101 subroutine laser_electric_field(laser, field, time, dt)
1102 type(laser_t), intent(in) :: laser
1103 real(real64), intent(out) :: field(:)
1104 real(real64), intent(in) :: time
1105 real(real64), intent(in) :: dt
1106
1107 integer :: dim
1108 real(real64), allocatable :: field1(:), field2(:)
1109
1110 !no PUSH SUB, called too often
1111
1112 dim = size(field)
1113
1114 select case (laser%field)
1115 case (e_field_electric)
1116 field = m_zero
1117 call laser_field(laser, field(1:dim), time)
1119 safe_allocate(field1(1:dim))
1120 safe_allocate(field2(1:dim))
1121 field1 = m_zero
1122 field2 = m_zero
1123 call laser_field(laser, field1(1:dim), time - dt)
1124 call laser_field(laser, field2(1:dim), time + dt)
1125 field = - (field2 - field1) / (m_two * p_c * dt)
1126 safe_deallocate_a(field1)
1127 safe_deallocate_a(field2)
1128 case default
1129 field = m_zero
1130 end select
1131
1132 end subroutine laser_electric_field
1133 ! ---------------------------------------------------------
1134
1135 ! ---------------------------------------------------------
1136 ! Loading of the lasers for the multisystem framework
1137 ! Ultimately this should be done in laser_init
1138 subroutine load_lasers(partners, namespace)
1139 class(partner_list_t), intent(inout) :: partners
1140 type(namespace_t), intent(in) :: namespace
1141
1142 class(lasers_t), pointer :: lasers
1143 integer :: il
1144
1145 push_sub(load_lasers)
1146
1147 lasers => lasers_t(namespace)
1148
1149 call lasers_parse_external_fields(lasers)
1150
1151 ! TODO: see how to do this in the multisystem framework
1152 if (parse_is_defined(namespace, 'MillerIndicesBasis')) then
1153 call messages_not_implemented("MillerIndicesBasis with load_lasers routine")
1154 end if
1155
1156 ! This is done normally in lasers_generate_potential, but we cannot call this routine here,
1157 ! so we do it here
1158 do il = 1, lasers%no_lasers
1159 lasers%lasers(il)%pol(:) = lasers%lasers(il)%pol(:)/sqrt(sum(abs(lasers%lasers(il)%pol(:))**2))
1160 end do
1161
1162 call lasers%quantities%add(quantity_t("E field", always_available = .true., updated_on_demand = .true., iteration = clock_t()))
1163 call lasers%quantities%add(quantity_t("B field", always_available = .true., updated_on_demand = .true., iteration = clock_t()))
1164
1165 lasers%supported_interactions_as_partner = [lorentz_force]
1166
1167 if (lasers%no_lasers > 0) then
1168 call partners%add(lasers)
1169 else
1170 safe_deallocate_p(lasers)
1171 end if
1172
1173 pop_sub(load_lasers)
1174 end subroutine load_lasers
1175
1176end module lasers_oct_m
1177
1178!! Local Variables:
1179!! mode: f90
1180!! coding: utf-8
1181!! 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: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:1232
complex(real64) function, dimension(3), public laser_polarization(laser)
Definition: lasers.F90:728
subroutine, public laser_set_phi(laser, phi)
Definition: lasers.F90:812
subroutine, public lasers_check_symmetries(this, kpoints)
Definition: lasers.F90:555
subroutine lasers_copy_quantities_to_interaction(partner, interaction)
Definition: lasers.F90:694
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:887
subroutine, public laser_vector_potential(laser, mesh, aa, time)
Definition: lasers.F90:1082
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:1154
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:754
subroutine lasers_update_quantity(this, label)
Definition: lasers.F90:650
subroutine, public laser_get_f(laser, ff)
Definition: lasers.F90:771
subroutine, public laser_set_f(laser, ff)
Definition: lasers.F90:784
logical function, public lasers_with_nondipole_field(lasers)
Check if a nondipole SFA correction should be computed for the given laser.
Definition: lasers.F90:741
subroutine, public laser_write_info(lasers, namespace, dt, max_iter, iunit)
Definition: lasers.F90:934
subroutine, public laser_set_empty_phi(laser)
Definition: lasers.F90:827
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:918
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:1195
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:1047
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:717
subroutine, public laser_set_frequency(laser, omega)
Definition: lasers.F90:853
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:1119
subroutine, public laser_set_polarization(laser, pol)
Definition: lasers.F90:866
subroutine, public laser_set_f_value(laser, ii, xx)
Definition: lasers.F90:839
subroutine, public laser_get_phi(laser, phi)
Definition: lasers.F90:799
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:538
subroutine, public messages_obsolete_variable(namespace, name, rep)
Definition: messages.F90:1046
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:161
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:415
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:617
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:589
real(real64), public symprec
Definition: symmetries.F90:169
integer pure function, public symmetries_number(this)
Definition: symmetries.F90:543
subroutine, public tdf_end(f)
Definition: tdfunction.F90:980
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
__clock_t clock_t
Definition: recipes.c:399
abstract class for general interaction partners
Describes mesh distribution to nodes.
Definition: mesh.F90:186
int true(void)