Octopus
pes_mask.F90
Go to the documentation of this file.
1!! Copyright (C) 2006-2011 U. De Giovannini, M. Marques
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
21module pes_mask_oct_m
23 use box_oct_m
26 use comm_oct_m
28 use cube_oct_m
29 use debug_oct_m
33 use fft_oct_m
35 use global_oct_m
37 use grid_oct_m
41 use io_oct_m
42 use ions_oct_m
44 use lasers_oct_m
45 use loct_oct_m
46 use math_oct_m
48 use mesh_oct_m
50 use mpi_oct_m
52#if defined(HAVE_NETCDF)
53 use netcdf
54#endif
56 use parser_oct_m
58 use qshep_oct_m
60 use space_oct_m
61 use sort_oct_m
63 use string_oct_m
64 use unit_oct_m
67 use vtk_oct_m
69
70 implicit none
71
72 private
73
74 public :: &
75 pes_mask_t, &
96
97
98 type pes_mask_t
99 private
100 complex(real64), allocatable, public :: k(:,:,:,:,:,:)
101 ! !< mask%k(ll(1),ll(2),ll(3),st%d%dim, st%nst, st%nik)
102
103 ! mesh- and cube-related stuff
104 integer :: np
106 integer :: ll(3)
107 integer :: fs_n_global(1:3)
108 integer :: fs_n(1:3)
109 integer :: fs_istart(1:3)
110
111 real(real64) :: spacing(3)
112
113 type(mesh_t), pointer, public :: mesh => null()
114 type(cube_t) :: cube
115
116 real(real64), allocatable, public :: vec_pot(:,:)
117
118 real(real64), allocatable, public :: Mk(:,:,:)
119 type(cube_function_t) :: cM
120 real(real64), allocatable, public :: mask_R(:)
121 integer :: shape
122 real(real64), allocatable :: ufn(:)
123 logical :: user_def
124
125 real(real64), allocatable, public :: Lk(:,:)
126
127 real(real64) :: enlarge(3)
128 real(real64) :: enlarge_2p(3)
129
130 real(real64) :: start_time
131 real(real64) :: energyMax
132 real(real64) :: energyStep
133
134 integer :: sw_evolve
135 logical :: back_action
136 logical :: add_psia
137 logical :: filter_k
138
139 integer :: mode
140 integer :: pw_map_how
141
142 type(fft_t) :: fft
143
144 type(mesh_cube_parallel_map_t) :: mesh_cube_map
145
146
147 end type pes_mask_t
148
149
150 integer, public, parameter :: &
151 PES_MASK_MODE_MASK = 1, &
154
155 integer, parameter :: &
156 PW_MAP_FFT = 3, & !< FFT - normally from fftw3
157 pw_map_nfft = 5, &
158 pw_map_pfft = 6, &
159 pw_map_pnfft = 7
160
161 integer, parameter :: &
162 M_SIN2 = 1, &
163 m_step = 2, &
164 m_erf = 3
165
166 integer, parameter :: &
167 IN = 1, &
168 out = 2
169
170 integer, public, parameter :: &
171 INTEGRATE_NONE = -1, &
172 integrate_phi = 1, &
173 integrate_theta = 2, &
174 integrate_r = 3, &
175 integrate_kx = 4, &
176 integrate_ky = 5, &
177 integrate_kz = 6
178
179
180contains
181
182
183 ! ---------------------------------------------------------
184 subroutine pes_mask_init(mask, namespace, space, mesh, box, st, ext_partners, abs_boundaries, max_iter,dt)
185 type(pes_mask_t), intent(out) :: mask
186 type(namespace_t), intent(in) :: namespace
187 class(space_t), intent(in) :: space
188 type(mesh_t), target, intent(in) :: mesh
189 class(box_t), intent(in) :: box
190 type(states_elec_t), intent(in) :: st
191 type(partner_list_t), intent(in) :: ext_partners
192 type(absorbing_boundaries_t), intent(in) :: abs_boundaries
193 integer, intent(in) :: max_iter
194 real(real64), intent(in) :: dt
196 type(block_t) :: blk
197
198 integer :: il, it, ll(3)
199 real(real64) :: field(3)
200 real(real64) :: deltae, maxe, pcutoff, tmp
201 integer :: defaultmask,k1,k2,st1,st2
202 integer :: cols_pesmask_block, idim, ip
204 real(real64) :: xx(space%dim), r
205 real(real64) :: ufn_re, ufn_im
206 character(len=1024) :: user_def_expr
207 type(lasers_t), pointer :: lasers
210
211 mask%mesh => mesh
212
213 if (space%is_periodic()) then
214 call messages_experimental("PES_mask with periodic dimensions", namespace=namespace)
215 end if
218 write(message(1),'(a,i1,a)') 'Info: Calculating PES using mask technique.'
219 call messages_info(1, namespace=namespace)
221
222 select type (box => box)
223 type is (box_sphere_t)
224 class default
225 if (.not. space%is_periodic()) then
226 message(1) = 'PhotoElectronSpectrum = pes_mask usually requires BoxShape = sphere.'
227 message(2) = 'Unless you know what you are doing modify this parameter and rerun.'
228 call messages_warning(2, namespace=namespace)
229 end if
230 end select
232 if (abs_boundaries%abtype /= not_absorbing) then
233 message(1) = 'PhotoElectronSpectrum = pes_mask already contains absorbing boundaries.'
234 message(2) = 'Set AbsorbingBoundaries = no and rerun.'
235 call messages_fatal(2, namespace=namespace)
236 end if
238
239!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
240!! Calculation mode
241!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
242
243 !%Variable PESMaskMode
244 !%Type integer
245 !%Default mask_mode
246 !%Section Time-Dependent::PhotoElectronSpectrum
247 !%Description
248 !% PES calculation mode.
249 !%Option mask_mode 1
250 !% Mask method.
251 !%Option fullmask_mode 2
252 !% Full mask method. This includes a back action of the momentum-space states on the
253 !% interaction region. This enables electrons to come back from the continuum.
254 !%Option passive_mode 3
255 !% Passive analysis of the wf. Simply analyze the plane-wave components of the
256 !% wavefunctions on the region <i>r</i> > <i>R1</i>. This mode employs a step masking function by default.
257 !%End
258 call parse_variable(namespace, 'PESMaskMode', pes_mask_mode_mask, mask%mode)
259 if (.not. varinfo_valid_option('PESMaskMode', mask%mode)) call messages_input_error(namespace, 'PESMaskMode')
260 call messages_print_var_option("PESMaskMode", mask%mode, namespace=namespace)
262 select case (mask%mode)
264 defaultmask = m_step
265 mask%back_action = .false.
266
268 defaultmask = m_sin2
269 mask%back_action = .true.
270 mask%mode = pes_mask_mode_mask
271 case default
272 defaultmask = m_sin2
273 mask%back_action = .false.
274 end select
275
276
277 !%Variable PESMaskStartTime
278 !%Type float
279 !%Default -1.0
280 !%Section Time-Dependent::PhotoElectronSpectrum
281 !%Description
282 !% The time photoelectrons start to be recorded. In pump-probe simulations, this allows
283 !% getting rid of an unwanted ionization signal coming from the pump.
284 !% NOTE: This will enforce the mask boundary conditions for all times.
285 !%End
286 call parse_variable(namespace, 'PESMaskStartTime', -m_one, mask%start_time, unit = units_inp%time)
287
288 !%Variable PESMaskPlaneWaveProjection
289 !%Type integer
290 !%Default fft_map
291 !%Section Time-Dependent::PhotoElectronSpectrum
292 !%Description
293 !% With the mask method, wavefunctions in the continuum are treated as plane waves.
294 !% This variable sets how to calculate the plane-wave projection in the buffer
295 !% region. We perform discrete Fourier transforms (DFT) in order to approximate
296 !% a continuous Fourier transform. The major drawback of this approach is the built-in
297 !% periodic boundary condition of DFT. Choosing an appropriate plane-wave projection
298 !% for a given simulation in addition to <tt>PESMaskEnlargeFactor</tt> and
299 !% <tt>PESMask2PEnlargeFactor</tt>will help to converge the results.
300 !%
301 !% NOTE: depending on the value of <tt>PESMaskMode</tt> <tt>PESMaskPlaneWaveProjection</tt>,
302 !% may affect not only performance but also the time evolution of the density.
303 !%Option fft_out 2
304 !% FFT filtered in order to keep only outgoing waves. 1D only.
305 !%Option fft_map 3
306 !% FFT transform.
307 !%Option nfft_map 5
308 !% Non-equispaced FFT map.
309 !%Option pfft_map 6
310 !% Use PFFT library.
311 !%Option pnfft_map 7
312 !% Use PNFFT library.
313 !%End
314 call parse_variable(namespace, 'PESMaskPlaneWaveProjection', pw_map_fft, mask%pw_map_how)
315
316 if (.not. varinfo_valid_option('PESMaskPlaneWaveProjection', mask%pw_map_how)) then
317 call messages_input_error(namespace, 'PESMaskPlaneWaveProjection')
318 end if
319
320 call messages_print_var_option("PESMaskPlaneWaveProjection", mask%pw_map_how, namespace=namespace)
321
322 if (mask%pw_map_how == pw_map_pfft .and. (.not. mask%mesh%parallel_in_domains)) then
323 message(1)= "Trying to use PESMaskPlaneWaveProjection = pfft_map with no domain parallelization."
324 message(2)= "Projection method changed to more efficient fft_map."
325 call messages_warning(2, namespace=namespace)
326 mask%pw_map_how = pw_map_fft
327 end if
328
329 if (mask%pw_map_how == pw_map_pnfft .and. (.not. mask%mesh%parallel_in_domains)) then
330 message(1)= "Trying to use PESMaskPlaneWaveProjection = pnfft_map with no domain parallelization."
331 message(2)= "Projection method changed to more efficient nfft_map."
332 call messages_warning(2, namespace=namespace)
333 mask%pw_map_how = pw_map_nfft
334 end if
335
336#if !defined(HAVE_NFFT)
337 if (mask%pw_map_how == pw_map_nfft) then
338 message(1) = "PESMaskPlaneWaveProjection = nfft_map requires NFFT but that library was not linked."
339 call messages_fatal(1, namespace=namespace)
340 end if
341#endif
342
343#if !defined(HAVE_PFFT)
344 if (mask%pw_map_how == pw_map_pfft) then
345 message(1) = "PESMaskPlaneWaveProjection = pfft_map requires PFFT but that library was not linked."
346 call messages_fatal(1, namespace=namespace)
347 end if
348#endif
349
350#if !defined(HAVE_PNFFT)
351 if (mask%pw_map_how == pw_map_pnfft) then
352 message(1) = "PESMaskPlaneWaveProjection = pnfft_map requires PNFFT but that library was not linked."
353 call messages_fatal(1, namespace=namespace)
354 end if
355#endif
356
357
358 !%Variable PESMaskEnlargeFactor
359 !%Type float
360 !%Default 1
361 !%Section Time-Dependent::PhotoElectronSpectrum
362 !%Description
363 !% Mask box enlargement level. Enlarges the mask bounding box by a <tt>PESMaskEnlargeFactor</tt>.
364 !% This helps to avoid wavefunction wrapping at the boundaries.
365 !%End
366
367 mask%enlarge = m_one
368 call parse_variable(namespace, 'PESMaskEnlargeFactor', m_one, mask%enlarge(1))
369
370 if (.not. is_close(mask%enlarge(1), m_one)) then
371
372 mask%enlarge(space%periodic_dim + 1:space%dim) = mask%enlarge(1)
373 mask%enlarge(1:space%periodic_dim) = m_one
374
375 if (space%is_periodic()) then
376 call messages_print_var_value("PESMaskEnlargeFactor", mask%enlarge(1:space%dim), namespace=namespace)
377 else
378 call messages_print_var_value("PESMaskEnlargeFactor", mask%enlarge(1), namespace=namespace)
379 end if
380
381 end if
382 if (mask%enlarge(1) < m_one) then
383 message(1) = "PESMaskEnlargeFactor must be bigger than one."
384 call messages_fatal(1, namespace=namespace)
385 end if
386
387 call messages_obsolete_variable(namespace, 'PESMaskEnlargeLev', 'PESMaskEnlargeFactor')
388
389 !%Variable PESMask2PEnlargeFactor
390 !%Type float
391 !%Default 1.0
392 !%Section Time-Dependent::PhotoElectronSpectrum
393 !%Description
394 !% Mask two points enlargement factor. Enlarges the mask box by adding two
395 !% points at the edges of the box in each direction (x,y,z) at a distance
396 !% L=Lb*<tt>PESMask2PEnlargeFactor</tt> where <i>Lb</i> is the box size.
397 !% This allows to run simulations with an additional void space at a price of
398 !% adding few points. The Fourier space associated with the new box is restricted
399 !% by the same factor.
400 !%
401 !% Note: needs <tt> PESMaskPlaneWaveProjection = nfft_map or pnfft_map </tt>.
402 !%End
403
404 mask%enlarge_2p = m_one
405 call parse_variable(namespace, 'PESMask2PEnlargeFactor', m_one, mask%enlarge_2p(1))
406
407
408 if (.not. is_close(mask%enlarge_2p(1), m_one)) then
409
410 mask%enlarge_2p(space%periodic_dim + 1:space%dim) = mask%enlarge_2p(1)
411 mask%enlarge_2p(1:space%periodic_dim) = m_one
412
413 if (space%is_periodic()) then
414 call messages_print_var_value("PESMask2PEnlargeFactor", mask%enlarge_2p(1:space%dim), namespace=namespace)
415 else
416 call messages_print_var_value("PESMask2PEnlargeFactor", mask%enlarge_2p(1), namespace=namespace)
417 end if
418
419 if (mask%pw_map_how /= pw_map_nfft .and. mask%pw_map_how /= pw_map_pnfft) then
420 message(1) = "PESMask2PEnlargeFactor requires PESMaskPlaneWaveProjection = nfft_map"
421 message(2) = "or pnfft_map in order to run properly."
422 call messages_warning(2, namespace=namespace)
423 end if
424 end if
425
426 if (mask%enlarge_2p(1) < m_one) then
427 message(1) = "PESMask2PEnlargeFactor must be bigger than one."
428 call messages_fatal(1, namespace=namespace)
429 end if
430
431 call messages_obsolete_variable(namespace, 'PESMaskNFFTEnlargeLev', 'PESMask2PEnlargeFactor')
432
433
434 mask%ll = 1
435 mask%spacing = -m_one
436
437 mask%spacing(1:space%dim) = mesh%spacing(1:space%dim)
438 mask%ll(1:space%dim) = mesh%idx%ll(1:space%dim)
439
440 !Enlarge the cube region
441 mask%ll(1:space%dim) = int(mask%ll(1:space%dim) * mask%enlarge(1:space%dim))
442
443 mask%np = mesh%np_part ! the mask is local
444
445 select case (mask%pw_map_how)
446
447 case (pw_map_pfft)
448 assert(mask%mesh%parallel_in_domains)
449 call cube_init(mask%cube, mask%ll, namespace, space, &
450 mesh%spacing, mesh%coord_system, &
451 fft_type = fft_complex, fft_library = fftlib_pfft, nn_out = ll, &
452 mpi_grp = mask%mesh%mpi_grp, need_partition=.true.)
453 call cube_init_cube_map(mask%cube, mesh)
454
455
456! mask%ll(1) = mask%cube%fs_n(3)
457! mask%ll(2) = mask%cube%fs_n(1)
458! mask%ll(3) = mask%cube%fs_n(2)
459! Note: even if tempting, setting
460! mask%ll(1:3) = mask%cube%fs_n(1:3)
461! results in the wrong index mapping! (1->3, 2->1, 3->2)
462! Well.. very much against intuition it turns out to be
463 mask%ll(1:3) = mask%cube%rs_n(1:3)
464
465 mask%fft = mask%cube%fft
466 if (mask%mesh%parallel_in_domains .and. mask%cube%parallel_in_domains) then
467 call mesh_cube_parallel_map_init(mask%mesh_cube_map, mask%mesh, mask%cube)
468 end if
469
470 case (pw_map_fft)
471 call cube_init(mask%cube, mask%ll, namespace, space, &
472 mesh%spacing, mesh%coord_system, &
473 fft_type = fft_complex, fft_library = fftlib_fftw, &
474 nn_out = ll)
475 call cube_init_cube_map(mask%cube, mesh)
476 mask%ll = ll
477 mask%fft = mask%cube%fft
478
479
480 case (pw_map_nfft)
481
482 !NFFT initialization
483 ! we just add 2 points for the enlarged region
484 if (.not. is_close(mask%enlarge_2p(1), m_one)) mask%ll(1:space%dim) = mask%ll(1:space%dim) + 2
485
486 call cube_init(mask%cube, mask%ll, namespace, space, &
487 mesh%spacing, mesh%coord_system, &
488 fft_type = fft_complex, fft_library = fftlib_nfft, &
489 nn_out = ll, tp_enlarge = mask%enlarge_2p)
490 call cube_init_cube_map(mask%cube, mesh)
491
492 mask%ll = ll
493 mask%fft = mask%cube%fft
494
495
496 case (pw_map_pnfft)
497
498 if (.not. is_close(mask%enlarge_2p(1), m_one)) mask%ll(1:space%dim) = mask%ll(1:space%dim) + 2
499
500 call cube_init(mask%cube, mask%ll, namespace, space, &
501 mask%mesh%spacing, mask%mesh%coord_system, &
502 fft_type = fft_complex, fft_library = fftlib_pnfft, &
503 nn_out = ll, tp_enlarge = mask%enlarge_2p, &
504 mpi_grp = mask%mesh%mpi_grp, need_partition=.true.)
505 call cube_init_cube_map(mask%cube, mesh)
506
507 mask%ll(1:3) = mask%cube%fs_n(1:3)
508
509 mask%fft = mask%cube%fft
510 if (mask%mesh%parallel_in_domains .and. mask%cube%parallel_in_domains) then
511 call mesh_cube_parallel_map_init(mask%mesh_cube_map, mask%mesh, mask%cube)
512 end if
513
514 case default
515 !Program should die before coming here
516 write(message(1),'(a)') "PESMaskPlaneWaveProjection unrecognized option."
517 call messages_fatal(1, namespace=namespace)
518
519 end select
520
521 !Indices
522
523 if (mask%pw_map_how == pw_map_pfft) then
524 mask%fs_istart = mask%cube%rs_istart
525 mask%fs_n = mask%cube%rs_n
526 mask%fs_n_global = mask%cube%rs_n_global
527 else
528 mask%fs_istart = mask%cube%fs_istart
529 mask%fs_n = mask%cube%fs_n
530 mask%fs_n_global = mask%cube%fs_n_global
531 end if
532
533 !Allocations
534 call zcube_function_alloc_rs(mask%cube, mask%cM, force_alloc = .true.)
535
536 safe_allocate(mask%Lk(1:maxval(mask%fs_n_global(:)),1:3))
537 mask%Lk(:,:) = m_zero
538
539 st1 = st%st_start
540 st2 = st%st_end
541 k1 = st%d%kpt%start
542 k2 = st%d%kpt%end
543 safe_allocate(mask%k(1:mask%ll(1),1:mask%ll(2),1:mask%ll(3),1:st%d%dim,st1:st2,k1:k2))
544 mask%k = m_z0
545
546
547 ! generate the map between mesh and cube
548 call pes_mask_generate_lk(mask) ! generate the physical momentum vector
549
550
551
552!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
553!! Mask Function options
554!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
555
556 safe_allocate(mask%mask_R(1:2))
557
558 !%Variable PESMaskShape
559 !%Type integer
560 !%Default m_sin2
561 !%Section Time-Dependent::PhotoElectronSpectrum
562 !%Description
563 !% The mask function shape.
564 !%Option m_sin2 1
565 !% sin2 mask.
566 !%Option m_step 2
567 !%step function.
568 !%Option m_erf 3
569 !%Error function. Not Implemented.
570 !%End
571 call parse_variable(namespace, 'PESMaskShape', defaultmask, mask%shape)
572 if (.not. varinfo_valid_option('PESMaskShape', mask%shape)) call messages_input_error(namespace, 'PESMaskShape')
573 call messages_print_var_option("PESMaskShape", mask%shape, namespace=namespace)
574
575 !%Variable PESMaskSize
576 !%Type block
577 !%Section Time-Dependent::PhotoElectronSpectrum
578 !%Description
579 !% Set the size of the mask function.
580 !% Here you can set the inner (R1) and outer (R2) radius by setting
581 !% the block as follows:
582 !%
583 !% <tt>%PESMaskSize
584 !% <br>&nbsp;&nbsp; R1 | R2 | "user-defined"
585 !% <br>%</tt>
586 !%
587 !% The optional 3rd column is a user-defined expression for the mask
588 !% function. For example, <i>r</i> creates a spherical mask (which is the
589 !% default for <tt>BoxShape = sphere</tt>). Note, values R2 larger than
590 !% the box size may lead in this case to unexpected reflection
591 !% behaviours.
592 !%End
593 cols_pesmask_block = 0
594 if (parse_block(namespace, 'PESMaskSize', blk) == 0) then
595 cols_pesmask_block = parse_block_cols(blk, 0)
596 end if
597
598 mask%user_def = .false.
599
600 select case (cols_pesmask_block)
601 case (0)
602 select type (box => box)
603 type is (box_sphere_t)
604 mask%mask_R(1) = box%radius/m_two
605 mask%mask_R(2) = box%radius
606 message(1) = "Input: PESMaskSize R(1) and R(2) not specified. Using default values for spherical mask."
607 type is (box_parallelepiped_t)
608 mask%mask_R(1) = box%half_length(1)/m_two
609 mask%mask_R(2) = box%half_length(1)
610 message(1) = "Input: PESMaskSize R(1) and R(2) not specified. Using default values for cubic mask."
611 end select
612 call messages_info(1, namespace=namespace)
613 case (1)
614 call parse_block_float(blk, 0, 0, mask%mask_R(1), units_inp%length)
615 select type (box => box)
616 type is (box_sphere_t)
617 mask%mask_R(2) = box%radius
618 message(1) = "Input: PESMaskSize R(2) not specified. Using default value for spherical mask."
619 type is (box_parallelepiped_t)
620 mask%mask_R(2) = box%half_length(1)
621 message(1) = "Input: PESMaskSize R(2) not specified. Using default value for cubic mask."
622 end select
623 call messages_info(1, namespace=namespace)
624 case (2)
625 call parse_block_float(blk, 0, 0, mask%mask_R(1), units_inp%length)
626 call parse_block_float(blk, 0, 1, mask%mask_R(2), units_inp%length)
627
628 select type (box => box)
629 type is (box_sphere_t)
630 if (mask%mask_R(2) > box%radius) mask%mask_R(2) = box%radius
631 message(1) = "Info: using spherical mask."
632 type is (box_parallelepiped_t)
633 if (mask%mask_R(2) > box%half_length(1)) mask%mask_R(2) = box%half_length(1)
634 message(1) = "Info: using cubic mask."
635 end select
636 call messages_info(1, namespace=namespace)
637
638 case (3)
639 mask%user_def = .true.
640 safe_allocate(mask%ufn(1:mask%np))
641 mask%ufn = m_zero
642 call parse_block_float(blk, 0, 0, mask%mask_R(1), units_inp%length)
643 call parse_block_float(blk, 0, 1, mask%mask_R(2), units_inp%length)
644 call parse_block_string(blk, 0, 2, user_def_expr)
645 do ip = 1, mask%np
646 xx(1:space%dim) = mesh%x(1:space%dim, ip)
647 r = units_from_atomic(units_inp%length, norm2(xx(1:space%dim)))
648 do idim = 1, space%dim
649 xx(idim) = units_from_atomic(units_inp%length, xx(idim))
650 end do
651 call parse_expression(ufn_re, ufn_im, space%dim, xx, r, m_zero, user_def_expr)
652 mask%ufn(ip) = ufn_re
653 end do
654 message(1) = "Input: using user-defined mask function from expression:"
655 write(message(2),'(a,a)') ' R = ', trim(user_def_expr)
656 call messages_info(2, namespace=namespace)
657 end select
658
659 call parse_block_end(blk)
660
661 write(message(1),'(a,es10.3,3a)') &
662 " R1 = ", units_from_atomic(units_inp%length, mask%mask_R(1)),&
663 ' [', trim(units_abbrev(units_inp%length)), ']'
664 write(message(2),'(a,es10.3,3a)') &
665 " R2 = ", units_from_atomic(units_inp%length, mask%mask_R(2)),&
666 ' [', trim(units_abbrev(units_inp%length)), ']'
667 call messages_info(2, namespace=namespace)
668
669
670 call pes_mask_generate_mask(mask, namespace, mesh)
671
672 !%Variable PESMaskFilterCutOff
673 !%Type float
674 !%Default -1
675 !%Section Time-Dependent::PhotoElectronSpectrum
676 !%Description
677 !% In calculation with <tt>PESMaskMode = fullmask_mode</tt> and NFFT, spurious frequencies
678 !% may lead to numerical instability of the algorithm. This option gives the possibility
679 !% to filter out the unwanted components by setting an energy cut-off.
680 !% If <tt>PESMaskFilterCutOff = -1</tt> no filter is applied.
681 !%End
682 call parse_variable(namespace, 'PESMaskFilterCutOff', -m_one, pcutoff, unit = units_inp%energy)
683
684 mask%filter_k = .false.
685
686 if (pcutoff > m_zero) then
687 call messages_print_var_value("PESMaskFilterCutOff", pcutoff, unit = units_out%energy, namespace=namespace)
688 mask%filter_k = .true.
689
690 safe_allocate(mask%Mk(1:mask%ll(1),1:mask%ll(2),1:mask%ll(3)))
691
692 call pes_mask_generate_filter(mask,pcutoff)
693 end if
694
695!! Output
696
697 !%Variable PESMaskIncludePsiA
698 !%Type logical
699 !%Default false
700 !%Section Time-Dependent::PhotoElectronSpectrum
701 !%Description
702 !% Add the contribution of <math>\Psi_A</math> in the mask region to the photo-electron spectrum.
703 !% Literally adds the Fourier components of:
704 !% <math>\Theta(r-R1) \Psi_A(r)</math>
705 !% with <math>\Theta</math> being the Heaviside step function.
706 !% With this option PES will contain all the contributions starting from the inner
707 !% radius <math>R1</math>. Use this option to improve convergence with respect to the box size
708 !% and total simulation time.
709 !% Note: Carefully choose <math>R1</math> in order to avoid contributions from returning electrons.
710 !%End
711 call parse_variable(namespace, 'PESMaskIncludePsiA', .false., mask%add_psia)
712 if (mask%add_psia) then
713 message(1)= "Input: Include contribution from Psi_A."
714 call messages_info(1, namespace=namespace)
715 end if
716
717
718 !%Variable PESMaskSpectEnergyMax
719 !%Type float
720 !%Default maxval(mask%Lk)<math>^2/2</math>
721 !%Section Time-Dependent::PhotoElectronSpectrum
722 !%Description
723 !% The maximum energy for the PES spectrum.
724 !%End
725 maxe = m_epsilon
726 do idim = 1, space%dim
727 tmp = maxval(mask%Lk(1:mask%ll(idim),1:space%dim))**2/m_two
728 if (tmp > maxe) maxe = tmp
729 end do
730 call parse_variable(namespace, 'PESMaskSpectEnergyMax', maxe, mask%energyMax, unit = units_inp%energy)
731 call messages_print_var_value("PESMaskSpectEnergyMax", mask%energyMax, unit = units_out%energy, namespace=namespace)
732
733 !%Variable PESMaskSpectEnergyStep
734 !%Type float
735 !%Section Time-Dependent::PhotoElectronSpectrum
736 !%Description
737 !% The PES spectrum energy step.
738 !%End
739 deltae = minval(mask%Lk(2,1:space%dim) - mask%Lk(1,1:space%dim))**2/m_two
740 call parse_variable(namespace, 'PESMaskSpectEnergyStep', deltae, mask%energyStep, unit = units_inp%energy)
741 call messages_print_var_value("PESMaskSpectEnergyStep", mask%energyStep, unit = units_out%energy, namespace=namespace)
742
743
744!! Set external fields
745
746 safe_allocate(mask%vec_pot(0:max_iter,1:3))
747 mask%vec_pot=m_zero
748
749 lasers => list_get_lasers(ext_partners)
750 if(associated(lasers)) then
751 do il = 1, lasers%no_lasers
752 select case (laser_kind(lasers%lasers(il)))
754 do it = 1, max_iter
755 field=m_zero
756 call laser_field(lasers%lasers(il), field, it*dt)
757 ! We must sum with a -1 sign to account for the
758 ! electron charge.
759 mask%vec_pot(it,:)= mask%vec_pot(it,:) - field(:)
760 end do
761
762 case default
763 write(message(1),'(a)') 'PESMask should work only with TDExternalFields = vector_potential.'
764 write(message(2),'(a)') 'Unless PESMaskMode = passive_mode the results are likely to be wrong. '
765 call messages_warning(2, namespace=namespace)
766
767 end select
768 end do
769 end if
770
771
772
773 ! Compensate the sign for the forward <-> backward FT inversion
774 ! used with NFFT. See pes_mask_X_to_K comment for more info
775 if (mask%pw_map_how == pw_map_pnfft .or. &
776 mask%pw_map_how == pw_map_nfft) mask%Lk = - mask%Lk
777
778
779 pop_sub(pes_mask_init)
780 end subroutine pes_mask_init
781
782
783 ! ---------------------------------------------------------
784 subroutine pes_mask_end(mask)
785 type(pes_mask_t), intent(inout) :: mask
786
787 push_sub(pes_mask_end)
788
789 safe_deallocate_a(mask%k)
790
791 safe_deallocate_a(mask%vec_pot)
792 safe_deallocate_a(mask%mask_R)
793 safe_deallocate_a(mask%Lk)
794
795
796 if (mask%filter_k) then
797 safe_deallocate_a(mask%Mk)
798 end if
799
800 if (mask%mesh%parallel_in_domains .and. mask%cube%parallel_in_domains) then
801 call mesh_cube_parallel_map_end(mask%mesh_cube_map)
802 end if
803
804 call zcube_function_free_rs(mask%cube, mask%cM)
805 call cube_end(mask%cube)
806
807 if (mask%user_def) then
808 safe_deallocate_a(mask%ufn)
809 end if
810
811 pop_sub(pes_mask_end)
812 end subroutine pes_mask_end
813
814
815 ! --------------------------------------------------------
816 subroutine pes_mask_generate_lk(mask)
817 type(pes_mask_t), intent(inout) :: mask
818
819 integer :: ii, dim
820
821 push_sub(pes_mask_generate_lk)
822
823 dim = mask%mesh%box%dim
824
825 do ii = 1, maxval(mask%ll(:))
826 mask%Lk(ii,1:dim)= matmul(mask%cube%latt%klattice_primitive(1:dim,1:dim), mask%cube%Lfs(ii,1:dim))
827 end do
828
829 pop_sub(pes_mask_generate_lk)
830 end subroutine pes_mask_generate_lk
831
832 ! ======================================
834 ! ======================================
835 subroutine pes_mask_generate_filter(mask,cutOff)
836 type(pes_mask_t), intent(inout) :: mask
837 real(real64), intent(in) ::cutoff
838
839
840 integer :: kx,ky,kz, power
841 real(real64) :: kk(3), ee, emax
842
844
845 mask%Mk = m_zero
846
847 emax = maxval(mask%Lk(:,:))**2 / m_two
848
849 power = 8
850
851 do kx = 1, mask%ll(1)
852 kk(1) = mask%Lk(kx,1)
853 do ky = 1, mask%ll(2)
854 kk(2) = mask%Lk(ky,2)
855 do kz = 1, mask%ll(3)
856 kk(3) = mask%Lk(kz,3)
857
858 ee = sum(kk(1:mask%mesh%box%dim)**2) / m_two
859
860 if (ee > cutoff .and. ee < emax) then
861 mask%Mk(kx,ky,kz) = m_one * sin((emax-ee) * m_pi / (m_two * (cutoff)))**power
862 else
863 if (ee <= cutoff) mask%Mk(kx,ky,kz) = m_one
864 end if
865
866 end do
867 end do
868 end do
869
870
872 end subroutine pes_mask_generate_filter
873
874
875 ! --------------------------------------------------------
878 ! ---------------------------------------------------------
879 subroutine pes_mask_generate_mask(mask, namespace, mesh)
880 type(pes_mask_t), intent(inout) :: mask
881 type(namespace_t), intent(in) :: namespace
882 type(mesh_t), intent(in) :: mesh
883
884 push_sub(pes_mask_generate_mask)
885
886 call pes_mask_generate_mask_function(mask, namespace, mesh, mask%shape, mask%mask_R)
887
889
890 end subroutine pes_mask_generate_mask
891
892 ! --------------------------------------------------------
895 ! ---------------------------------------------------------
896 subroutine pes_mask_generate_mask_function(mask, namespace, mesh, shape, R, mask_sq)
897 type(pes_mask_t), intent(inout) :: mask
898 type(namespace_t), intent(in) :: namespace
899 type(mesh_t), intent(in) :: mesh
900 integer, intent(in) :: shape
901 real(real64), intent(in) :: r(2)
902 real(real64), optional, intent(out) :: mask_sq(:,:,:)
903
904 integer :: ip, dir
905 real(real64) :: width
906 real(real64) :: xx(1:mesh%box%dim), rr, dd, ddv(1:mesh%box%dim), tmp(1:mesh%box%dim)
907 complex(real64), allocatable :: mask_fn(:)
908
910
911 assert(mask%cM%batch_size == 1)
912
913 ! generate the mask function on the mesh
914 safe_allocate(mask_fn(1:mask%np))
915
916 mask_fn = m_zero
917 width = r(2) - r(1)
918 xx = m_zero
919
920 select case (shape)
921 case (m_sin2)
922 do ip = 1, mask%np
923 call mesh_r(mesh, ip, rr, coords=xx)
924
925 if (mask%user_def) then
926 dd = mask%ufn(ip) - r(1)
927 if (dd > m_zero) then
928 if (mask%ufn(ip) < r(2)) then
929 mask_fn(ip) = m_one * sin(dd * m_pi / (m_two * (width)))**2
930 else
931 mask_fn(ip) = m_one
932 end if
933 end if
934
935 else ! mask%user_def == .false.
936
937 select type (box => mesh%box)
938 type is (box_sphere_t)
939 dd = rr - r(1)
940 if (dd > m_zero) then
941 if (dd < width) then
942 mask_fn(ip) = m_one * sin(dd * m_pi / (m_two * (width)))**2
943 else
944 mask_fn(ip) = m_one
945 end if
946 end if
947
948 type is (box_parallelepiped_t)
949
950 ! We are filling from the center opposite to the spherical case
951 tmp = m_one
952 mask_fn(ip) = m_one
953 ddv = abs(xx) - r(1)
954 do dir=1, mesh%box%dim
955 if (ddv(dir) > m_zero) then
956 if (ddv(dir) < width) then
957 tmp(dir) = m_one - sin(ddv(dir) * m_pi / (m_two * width))**2
958 else
959 tmp(dir) = m_zero
960 end if
961 end if
962 mask_fn(ip) = mask_fn(ip) * tmp(dir)
963 end do
964 mask_fn(ip) = m_one - mask_fn(ip)
965
966 end select
967 end if
968 end do
969
970 case (m_step)
971 do ip = 1, mask%np
972 call mesh_r(mesh, ip, rr, coords=xx)
973 dd = rr - r(1)
974 if (dd > m_zero) then
975 if (dd < width) then
976 mask_fn(ip) = m_one
977 else
978 mask_fn(ip) = m_zero
979 end if
980 end if
981 end do
982
983 case (m_erf)
984
985 case default
986 message(1)="PhotoElectronSpectrum = pes_mask. Unrecognized mask type."
987 call messages_fatal(1, namespace=namespace)
988 end select
989
990 mask_fn(:) = m_one - mask_fn(:)
991 call pes_mask_mesh_to_cube(mask, mask_fn, mask%cM)
992
993 if (present(mask_sq)) mask_sq = real(mask%cM%zRS(1, :, :, :), real64)
994
995 safe_deallocate_a(mask_fn)
996
998
1000
1001
1002 ! --------------------------------------------------------
1003 subroutine pes_mask_apply_mask(mask, st)
1004 type(states_elec_t), intent(inout) :: st
1005 type(pes_mask_t), intent(in) :: mask
1006
1007 integer :: ik, ist, idim, ip
1008 complex(real64), allocatable :: mmask(:), psi(:)
1009
1010 push_sub(pes_mask_apply_mask)
1011 safe_allocate(mmask(1:mask%mesh%np))
1012 safe_allocate(psi(1:mask%mesh%np))
1013
1014 call pes_mask_cube_to_mesh(mask, mask%cM, mmask)
1015
1016 do ik = st%d%kpt%start, st%d%kpt%end
1017 do ist = st%st_start, st%st_end
1018 do idim = 1, st%d%dim
1019 call states_elec_get_state(st, mask%mesh, idim, ist, ik, psi)
1020 !$omp parallel do
1021 do ip = 1, mask%mesh%np
1022 psi(ip) = psi(ip) * mmask(ip)
1023 end do
1024 !$omp end parallel do
1025 call states_elec_set_state(st, mask%mesh, idim, ist, ik, psi)
1026 end do
1027 end do
1028 end do
1029
1030 safe_deallocate_a(mmask)
1031
1032 pop_sub(pes_mask_apply_mask)
1033 end subroutine pes_mask_apply_mask
1034
1035
1036
1037
1038
1039
1040 ! ---------------------------------------------------------
1052 ! ---------------------------------------------------------
1053 subroutine pes_mask_volkov_time_evolution_wf(mask, space, mesh, kpoints, dt, iter, wf, ikpoint)
1054 type(pes_mask_t), intent(in) :: mask
1055 class(space_t), intent(in) :: space
1056 type(mesh_t), intent(in) :: mesh
1057 type(kpoints_t), intent(in) :: kpoints
1058 real(real64), intent(in) :: dt
1059 integer, intent(in) :: iter
1060 complex(real64), intent(inout) :: wf(:,:,:)
1061 integer, intent(in) :: ikpoint
1062
1063 integer :: ix, iy, iz
1064 real(real64) :: vec
1065 real(real64) :: kk(1:3), kpoint(1:3)
1066
1068
1069 kpoint = m_zero
1070 if (space%is_periodic()) then
1071 kpoint(1:mesh%box%dim) = kpoints%get_point(ikpoint)
1072 end if
1073
1074 do ix = 1, mask%ll(1)
1075 kk(1) = mask%Lk(ix + mask%fs_istart(1) - 1, 1)
1076 do iy = 1, mask%ll(2)
1077 kk(2) = mask%Lk(iy + mask%fs_istart(2) - 1, 2)
1078 do iz = 1, mask%ll(3)
1079 kk(3) = mask%Lk(iz + mask%fs_istart(3) - 1, 3)
1080 ! The k-points have the same sign as the vector potential consistently
1081 ! with what is done to generate the phase (hm%phase) in hamiltonian_elec_update()
1082 vec = sum(( kk(1:mesh%box%dim) &
1083 - kpoint(1:mesh%box%dim) &
1084 - mask%vec_pot(iter,1:mesh%box%dim)/p_c)**2) / m_two
1085 wf(ix, iy, iz) = wf(ix, iy, iz) * exp(-m_zi * dt * vec)
1086 end do
1087 end do
1088 end do
1089
1090
1091! do ix = 1, mask%ll(1)
1092! KK(1) = mask%Lk(ix + mask%fs_istart(1) - 1)
1093! do iy = 1, mask%ll(2)
1094! KK(2) = mask%Lk(iy + mask%fs_istart(2) - 1)
1095! do iz = 1, mask%ll(3)
1096! KK(3) = mask%Lk(iz + mask%fs_istart(3) - 1)
1097! vec = sum(( KK(1:mesh%box%dim) - mask%vec_pot(iter,1:mesh%box%dim)/P_C)**2) / M_TWO
1098! wf(ix, iy, iz) = wf(ix, iy, iz) * exp(-M_zI * dt * vec)
1099! end do
1100! end do
1101! end do
1102
1105
1106
1107
1108
1109 !---------------------------------------------------------
1111 !---------------------------------------------------------
1112 subroutine pes_mask_x_to_k(mask, wfin, wfout)
1113 type(pes_mask_t), intent(in) :: mask
1114 complex(real64), intent(inout) :: wfin(:,:,:)
1115 complex(real64), intent(out) :: wfout(:,:,:)
1116
1117 type(cube_function_t) :: cf_tmp
1118 real(real64) :: norm
1119
1120 call profiling_in("PESMASK_X_to_K")
1121
1122 push_sub(pes_mask_x_to_k)
1123
1124 assert(cf_tmp%batch_size == 1)
1125
1126 wfout=m_z0
1127
1128 select case (mask%pw_map_how)
1129
1130 case (pw_map_fft)
1131 call zfft_forward(mask%cube%fft, wfin, wfout)
1132
1133 case (pw_map_nfft)
1134 ! By definition NFFT forward transform generates a function defined on an
1135 ! unstructured grid from its Fourier components (defined on a cubic equispaced grid).
1136 ! This is not what we want since for us it is the real-space grid the one that can be
1137 ! unstructured.
1138 ! In order to preserve the possibility to have an unstructured rs-grid we use the
1139 ! backward transform and flip the sign of all the momenta (Lk = -Lk).
1140 call zfft_backward(mask%cube%fft, wfin, wfout, norm)
1141 wfout = wfout * norm
1142
1143 case (pw_map_pfft)
1144 call zcube_function_alloc_rs(mask%cube, cf_tmp)
1145 call cube_function_alloc_fs(mask%cube, cf_tmp)
1146 cf_tmp%zRs(1, :, :, :) = wfin
1147 call zfft_forward(mask%cube%fft, cf_tmp%zRs, cf_tmp%fs)
1148 wfout = cf_tmp%fs(1, :, :, :)
1149 call zcube_function_free_rs(mask%cube, cf_tmp)
1150 call cube_function_free_fs(mask%cube, cf_tmp)
1151
1152 case (pw_map_pnfft)
1153 call zfft_backward(mask%cube%fft, wfin, wfout, norm)
1154 wfout = wfout * norm
1155
1156 case default
1157
1158 end select
1159
1160 pop_sub(pes_mask_x_to_k)
1161 call profiling_out("PESMASK_X_to_K")
1162
1163 end subroutine pes_mask_x_to_k
1164
1165 ! ------------------------------------------------
1166 subroutine pes_mask_k_to_x(mask, wfin, wfout)
1167 type(pes_mask_t), intent(in) :: mask
1168 complex(real64), intent(inout) :: wfin(:,:,:)
1169 complex(real64), intent(out) :: wfout(:,:,:)
1170
1171 type(cube_function_t) :: cf_tmp
1172 real(real64) :: norm
1173
1174 call profiling_in("PESMASK_K_toX")
1175
1176 push_sub(pes_mask_k_to_x)
1177
1178 assert(cf_tmp%batch_size == 1)
1179
1180 wfout=m_z0
1181
1182 select case (mask%pw_map_how)
1183
1184 case (pw_map_fft)
1185 call zfft_backward(mask%cube%fft, wfin, wfout)
1186
1187 case (pw_map_nfft)
1188 call zfft_forward(mask%cube%fft, wfin, wfout, norm)
1189 wfout = wfout / norm
1190
1191 case (pw_map_pfft)
1192 call zcube_function_alloc_rs(mask%cube, cf_tmp)
1193 call cube_function_alloc_fs(mask%cube, cf_tmp)
1194 cf_tmp%fs(1, :, :, :) = wfin
1195 call zfft_backward(mask%cube%fft, cf_tmp%fs, cf_tmp%zRs)
1196 wfout = cf_tmp%zRs(1, :, :, :)
1197 call zcube_function_free_rs(mask%cube, cf_tmp)
1198 call cube_function_free_fs(mask%cube, cf_tmp)
1199
1200 case (pw_map_pnfft)
1201 call zfft_forward(mask%cube%fft, wfin, wfout, norm)
1202 wfout = wfout / norm
1203
1204 case default
1205
1206 end select
1208 pop_sub(pes_mask_k_to_x)
1209
1210 call profiling_out("PESMASK_K_toX")
1211
1212 end subroutine pes_mask_k_to_x
1213
1214 !---------------------------------------------------------
1215 subroutine pes_mask_mesh_to_cube(mask, mf, cf)
1216 type(pes_mask_t), intent(in) :: mask
1217 complex(real64), contiguous, intent(in) :: mf(:)
1218 type(cube_function_t), intent(inout) :: cf
1219
1220 push_sub(pes_mask_mesh_to_cube)
1221
1222 if (mask%cube%parallel_in_domains) then
1223 call zmesh_to_cube_parallel(mask%mesh, mf, mask%cube, cf, mask%mesh_cube_map)
1224 else
1225 call zmesh_to_cube(mask%mesh, mf, mask%cube, cf)
1226 end if
1227
1228 pop_sub(pes_mask_mesh_to_cube)
1229 end subroutine pes_mask_mesh_to_cube
1230
1231
1232 !---------------------------------------------------------
1233 subroutine pes_mask_cube_to_mesh(mask, cf, mf)
1234 type(pes_mask_t), intent(in) :: mask
1235 complex(real64), contiguous, intent(out):: mf(:)
1236 type(cube_function_t), intent(in) :: cf
1237
1238 push_sub(pes_mask_cube_to_mesh)
1239
1240 if (mask%cube%parallel_in_domains) then
1241 call zcube_to_mesh_parallel(mask%cube, cf, mask%mesh, mf, mask%mesh_cube_map)
1242 else
1243 call zcube_to_mesh(mask%cube, cf, mask%mesh, mf)
1244 end if
1245
1246 pop_sub(pes_mask_cube_to_mesh)
1247 end subroutine pes_mask_cube_to_mesh
1248
1249
1250 !---------------------------------------------------------
1251 !
1252 ! Performs all the dirty work
1253 !
1254 !---------------------------------------------------------
1255 subroutine pes_mask_calc(mask, namespace, space, mesh, st, kpoints, dt, iter)
1256 type(pes_mask_t), intent(inout) :: mask
1257 type(namespace_t), intent(in) :: namespace
1258 class(space_t), intent(in) :: space
1259 type(mesh_t), intent(in) :: mesh
1260 type(states_elec_t), intent(inout) :: st
1261 type(kpoints_t), intent(in) :: kpoints
1262 real(real64), intent(in) :: dt
1263 integer, intent(in) :: iter
1264
1265 integer :: idim, ist, ik
1266 type(cube_function_t):: cf1, cf2
1267 complex(real64), allocatable :: mf(:), psi(:)
1268
1269 real(real64) :: time
1270
1271
1272 call profiling_in("PESMASK_calc")
1273
1274 push_sub(pes_mask_calc)
1275
1276 time = iter *dt
1277
1278 if (time > mask%start_time) then ! record photoelectrons only after mask%start_time
1279
1280 call zcube_function_alloc_rs(mask%cube, cf1, force_alloc = .true.)
1281 call cube_function_alloc_fs(mask%cube, cf1, force_alloc = .true.)
1282 call zcube_function_alloc_rs(mask%cube, cf2, force_alloc = .true.)
1283 call cube_function_alloc_fs(mask%cube, cf2, force_alloc = .true.)
1284
1285 select case (mask%mode)
1286 case (pes_mask_mode_mask)
1287 if (mask%back_action .eqv. .true.) then
1288 safe_allocate(mf(1:mask%mesh%np_part))
1289 end if
1290 end select
1291
1292 safe_allocate(psi(1:mask%mesh%np_part))
1293
1294 do ik = st%d%kpt%start, st%d%kpt%end
1295 do ist = st%st_start, st%st_end
1296 do idim = 1, st%d%dim
1297
1298 call states_elec_get_state(st, mask%mesh, idim, ist, ik, psi)
1299
1300 cf1%zRs = m_z0
1301 cf2%zRS= m_z0
1302 cf1%Fs = m_z0
1303 cf2%Fs = m_z0
1304
1305 call pes_mask_mesh_to_cube(mask, psi, cf1)
1306
1307 select case (mask%mode)
1308 !-----------------------------------------
1309 ! Mask Method
1310 !----------------------------------------
1311 case (pes_mask_mode_mask)
1312
1313 cf1%zRs = (m_one - mask%cM%zRs) * cf1%zRs ! cf1 =(1-M)*\Psi_A(x,t2)
1314 call pes_mask_x_to_k(mask, cf1%zRs(1, :, :, :), cf2%Fs(1, :, :, :)) ! cf2 = \tilde{\Psi}_A(k,t2)
1315
1316 if (mask%filter_k) then ! apply a filter to the Fourier transform to remove unwanted energies
1317 assert(allocated(mask%Mk))
1318 cf2%Fs(1, :, :, :) = cf2%Fs(1, :, :, :) * mask%Mk
1319 end if
1320
1321 cf1%Fs(1, :,:,:) = mask%k(:,:,:, idim, ist, ik) ! cf1 = \Psi_B(k,t1)
1322 mask%k(:,:,:, idim, ist, ik) = cf2%Fs(1, :,:,:) ! mask%k = \tilde{\Psi}_A(k,t2)
1323 ! cf1 = \tilde{\Psi}_B(k,t2)
1324 call pes_mask_volkov_time_evolution_wf(mask, space, mesh, kpoints, dt,iter-1, cf1%Fs(1, :, :, :), &
1325 st%d%get_kpoint_index(ik))
1326
1327 ! mask%k = \tilde{\Psi}_A(k,t2) + \tilde{\Psi}_B(k,t2)
1328 mask%k(:,:,:, idim, ist, ik) = mask%k(:,:,:, idim, ist, ik) + cf1%Fs(1, :,:,:)
1329
1330 if (mask%back_action .eqv. .true.) then
1331 ! Apply Back-action to wavefunction in A
1332 call pes_mask_k_to_x(mask, cf1%Fs(1, :, :, :), cf2%zRs(1, :, :, :)) ! cf2 = \Psi_B(x,t2)
1333 call pes_mask_cube_to_mesh(mask, cf2, mf)
1334 call lalg_axpy(mask%mesh%np, m_one, mf, psi)
1335 call states_elec_set_state(st, mask%mesh, idim, ist, ik, psi)
1336
1337 ! Apply correction to wavefunction in B
1338 cf2%zRs= (mask%cM%zRs) * cf2%zRs ! cf2 = M*\Psi_B(x,t1)
1339 call pes_mask_x_to_k(mask, cf2%zRs(1, :, :, :), cf1%Fs(1, :, :, :))
1340
1341 mask%k(:,:,:, idim, ist, ik) = mask%k(:,:,:, idim, ist, ik) - cf1%Fs(1, :, :, :)
1342 end if
1343
1344 !-----------------------------------------
1345 ! Passive Mask method
1346 !----------------------------------------
1348 cf1%zRs = (m_one-mask%cM%zRs) * cf1%zRs
1349 call pes_mask_x_to_k(mask, cf1%zRs(1, :, :, :), cf2%Fs(1, :, :, :))
1350 mask%k(:,:,:, idim, ist, ik) = cf2%Fs(1, :,:,:)
1351
1352 case default
1353 !Program should die before coming here
1354 write(message(1),'(a)') "PhotoElectroSpectrum = pes_mask. Unrecognized calculation mode."
1355 call messages_fatal(1, namespace=namespace)
1356
1357 end select
1358
1359 end do
1360 end do
1361 end do
1362
1363 safe_deallocate_a(psi)
1364
1365 call zcube_function_free_rs(mask%cube, cf1)
1366 call cube_function_free_fs(mask%cube, cf1)
1367 call zcube_function_free_rs(mask%cube, cf2)
1368 call cube_function_free_fs(mask%cube, cf2)
1369
1370 select case (mask%mode)
1371 case (pes_mask_mode_mask)
1372 if (mask%back_action .eqv. .true.) then
1373 safe_deallocate_a(mf)
1374 end if
1375 end select
1376
1377 end if ! time > mask%start_time
1378
1379 if (mask%mode == pes_mask_mode_mask) call pes_mask_apply_mask(mask, st) !apply the mask to all the KS orbitals
1380
1381 pop_sub(pes_mask_calc)
1382
1383 call profiling_out("PESMASK_calc")
1384 end subroutine pes_mask_calc
1385
1386#include "pes_mask_out_inc.F90"
1387
1388end module pes_mask_oct_m
1389
1390!! Local Variables:
1391!! mode: f90
1392!! coding: utf-8
1393!! End:
constant times a vector plus a vector
Definition: lalg_basic.F90:173
Prints out to iunit a message in the form: ["InputVariable" = value] where "InputVariable" is given b...
Definition: messages.F90:182
double exp(double __x) __attribute__((__nothrow__
double sin(double __x) __attribute__((__nothrow__
integer, parameter, public not_absorbing
subroutine, public zcube_to_mesh_parallel(cube, cf, mesh, mf, map)
subroutine, public zmesh_to_cube_parallel(mesh, mf, cube, cf, map)
The next two subroutines convert a function between the normal mesh and the cube in parallel.
subroutine, public zcube_function_free_rs(cube, cf)
Deallocates the real space grid.
subroutine, public zcube_function_alloc_rs(cube, cf, in_device, force_alloc)
Allocates locally the real space grid, if PFFT library is not used. Otherwise, it assigns the PFFT re...
subroutine, public cube_end(cube)
Definition: cube.F90:400
subroutine, public cube_init(cube, nn, namespace, space, spacing, coord_system, fft_type, fft_library, dont_optimize, nn_out, mpi_grp, need_partition, tp_enlarge, blocksize, batch_size, batch_axis)
Definition: cube.F90:208
subroutine, public cube_init_cube_map(cube, mesh)
Definition: cube.F90:838
This module implements a calculator for the density and defines related functions.
Definition: density.F90:122
type(lasers_t) function, pointer, public list_get_lasers(partners)
Fast Fourier Transform module. This module provides a single interface that works with different FFT ...
Definition: fft.F90:120
integer, parameter, public fft_complex
Definition: fft.F90:174
integer, parameter, public fftlib_nfft
Definition: fft.F90:179
integer, parameter, public fftlib_pnfft
Definition: fft.F90:179
integer, parameter, public fftlib_pfft
Definition: fft.F90:179
integer, parameter, public fftlib_fftw
Definition: fft.F90:179
subroutine, public cube_function_free_fs(cube, cf)
Deallocates the Fourier space grid.
subroutine, public cube_function_alloc_fs(cube, cf, force_alloc)
Allocates locally the Fourier space grid, if PFFT library is not used. Otherwise, it assigns the PFFT...
real(real64), parameter, public m_two
Definition: global.F90:202
real(real64), parameter, public m_zero
Definition: global.F90:200
real(real64), parameter, public m_pi
some mathematical constants
Definition: global.F90:198
complex(real64), parameter, public m_z0
Definition: global.F90:210
complex(real64), parameter, public m_zi
Definition: global.F90:214
real(real64), parameter, public m_epsilon
Definition: global.F90:216
real(real64), parameter, public p_c
Electron gyromagnetic ratio, see Phys. Rev. Lett. 130, 071801 (2023)
Definition: global.F90:242
real(real64), parameter, public m_one
Definition: global.F90:201
This module implements the underlying real-space grid.
Definition: grid.F90:119
This module defines classes and functions for interaction partners.
Definition: io.F90:116
integer, parameter, public e_field_vector_potential
Definition: lasers.F90:180
integer pure elemental function, public laser_kind(laser)
Definition: lasers.F90:720
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
System information (time, memory, sysname)
Definition: loct.F90:117
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:117
subroutine, public mesh_cube_parallel_map_end(this)
subroutine, public mesh_cube_parallel_map_init(this, mesh, cube)
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:342
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_input_error(namespace, var, details, row, column)
Definition: messages.F90:691
subroutine, public messages_experimental(name, namespace)
Definition: messages.F90:1040
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
this module contains the low-level part of the output system
Definition: output_low.F90:117
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
subroutine, public pes_mask_calc(mask, namespace, space, mesh, st, kpoints, dt, iter)
Definition: pes_mask.F90:1351
integer, parameter, public pes_mask_mode_backaction
Definition: pes_mask.F90:245
integer, parameter, public integrate_r
Definition: pes_mask.F90:265
subroutine, public pes_mask_dump(mask, namespace, restart, st, ierr)
Definition: pes_mask.F90:3581
subroutine, public pes_mask_output_full_mapm(pesK, file, namespace, space, Lk, ll, how, mesh, pmesh)
Definition: pes_mask.F90:2258
subroutine pes_mask_volkov_time_evolution_wf(mask, space, mesh, kpoints, dt, iter, wf, ikpoint)
Propagate in time a wavefunction in momentum space with the Volkov Hamiltonian.
Definition: pes_mask.F90:1149
integer, parameter pw_map_pnfft
use PNFFT
Definition: pes_mask.F90:250
subroutine, public pes_mask_cube_to_mesh(mask, cf, mf)
Definition: pes_mask.F90:1329
subroutine, public pes_mask_output_full_mapm_cut(pesK, file, namespace, ll, dim, pol, dir, integrate, pos, Lk, pmesh)
Definition: pes_mask.F90:2377
subroutine, public pes_mask_output(mask, gr, st, outp, namespace, space, file, ions, iter)
This routine is the main routine dedicated to the output of PES data.
Definition: pes_mask.F90:3348
integer, parameter pw_map_nfft
non-equispaced fft (NFFT)
Definition: pes_mask.F90:250
subroutine pes_mask_apply_mask(mask, st)
Definition: pes_mask.F90:1099
integer, parameter, public integrate_kx
Definition: pes_mask.F90:265
subroutine, public pes_mask_init(mask, namespace, space, mesh, box, st, ext_partners, abs_boundaries, max_iter, dt)
Definition: pes_mask.F90:280
subroutine, public pes_mask_pmesh(namespace, dim, kpoints, ll, LG, pmesh, idxZero, krng, Lp)
Definition: pes_mask.F90:1540
subroutine, public pes_mask_generate_mask_function(mask, namespace, mesh, shape, R, mask_sq)
Generate the mask function on the cubic mesh containing the simulation box.
Definition: pes_mask.F90:992
subroutine pes_mask_generate_mask(mask, namespace, mesh)
Generate the mask function on the cubic mesh containing the simulation box.
Definition: pes_mask.F90:975
subroutine, public pes_mask_output_power_totalm(pesK, file, namespace, Lk, ll, dim, Emax, Estep, interpolate)
Definition: pes_mask.F90:3154
integer, parameter, public integrate_phi
Definition: pes_mask.F90:265
subroutine pes_mask_generate_filter(mask, cutOff)
Generate the momentum-space filter.
Definition: pes_mask.F90:931
subroutine, public pes_mask_output_ar_spherical_cut_m(pesK, file, namespace, Lk, ll, dim, dir, Emin, Emax, Estep)
Definition: pes_mask.F90:2883
subroutine, public pes_mask_load(mask, namespace, restart, st, ierr)
Definition: pes_mask.F90:3672
subroutine, public pes_mask_mesh_to_cube(mask, mf, cf)
Definition: pes_mask.F90:1311
subroutine, public pes_mask_x_to_k(mask, wfin, wfout)
Project the wavefunction on plane waves.
Definition: pes_mask.F90:1208
integer, parameter, public pes_mask_mode_passive
Definition: pes_mask.F90:245
integer, parameter m_step
Definition: pes_mask.F90:256
subroutine pes_mask_generate_lk(mask)
Definition: pes_mask.F90:912
integer, parameter, public integrate_theta
Definition: pes_mask.F90:265
subroutine, public pes_mask_output_ar_plane_m(pesK, file, namespace, Lk, ll, dim, dir, Emax, Estep)
Definition: pes_mask.F90:2753
integer, parameter pw_map_pfft
use PFFT
Definition: pes_mask.F90:250
integer, parameter out
Definition: pes_mask.F90:261
subroutine, public pes_mask_map_from_states(restart, st, ll, pesK, krng, Lp, istin)
Definition: pes_mask.F90:1780
subroutine, public pes_mask_end(mask)
Definition: pes_mask.F90:880
integer, parameter, public integrate_ky
Definition: pes_mask.F90:265
integer, parameter m_erf
Definition: pes_mask.F90:256
subroutine, public pes_mask_k_to_x(mask, wfin, wfout)
Definition: pes_mask.F90:1262
integer, parameter, public integrate_kz
Definition: pes_mask.F90:265
subroutine, public pes_mask_read_info(dir, namespace, dim, Emax, Estep, ll, Lk, RR)
Read pes info.
Definition: pes_mask.F90:3477
subroutine, public pes_mask_output_ar_polar_m(pesK, file, namespace, Lk, ll, dim, dir, Emax, Estep)
Definition: pes_mask.F90:2634
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:631
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:554
This module is intended to contain "only mathematical" functions and procedures.
Definition: sort.F90:119
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:134
character(len=20) pure function, public units_abbrev(this)
Definition: unit.F90:225
This module defines the unit system, used for input and output.
type(unit_system_t), public units_out
type(unit_system_t), public units_inp
the units systems for reading and writing
Class implementing a parallelepiped box. Currently this is restricted to a rectangular cuboid (all th...
Class implementing a spherical box.
Definition: box_sphere.F90:134
Describes mesh distribution to nodes.
Definition: mesh.F90:187
The states_elec_t class contains all electronic wave functions.
int true(void)