Octopus
pes_spm.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
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_spm_oct_m
24 use comm_oct_m
25 use debug_oct_m
27 use global_oct_m
29 use io_oct_m
30 use, intrinsic :: iso_fortran_env
31 use lasers_oct_m
33 use mesh_oct_m
35 use mpi_oct_m
37 use parser_oct_m
41 use unit_oct_m
44
45
46 implicit none
47
48 private
49
50 public :: &
51 pes_spm_t, &
59
60 type pes_spm_t
61 private
62 integer :: nspoints
63 real(real64), allocatable :: rcoords(:,:)
64 real(real64), allocatable :: rcoords_nrm(:,:)
65 complex(real64), allocatable, public :: wf(:,:,:,:,:)
66 real(real64), allocatable :: dq(:,:)
67 real(real64), allocatable :: domega(:)
68 integer :: recipe
69 complex(real64), allocatable :: wfft(:,:,:,:,:)
70 real(real64) :: omegamax
71 real(real64) :: delomega
72 integer :: nomega
73 logical :: onfly
74 integer :: save_iter
75 logical :: sphgrid
76 integer :: nstepsphir, nstepsthetar
77 type(mesh_interpolation_t) :: interp
78 end type pes_spm_t
79
80 integer, parameter :: &
81 M_RAW = 1, &
82 m_phase = 2
83
84contains
85
86 ! ---------------------------------------------------------
87 subroutine pes_spm_init(this, namespace, mesh, st, save_iter)
88 type(pes_spm_t), intent(out) :: this
89 type(namespace_t), intent(in) :: namespace
90 type(mesh_t), intent(in) :: mesh
91 type(states_elec_t), intent(in) :: st
92 integer, intent(in) :: save_iter
93
94 type(block_t) :: blk
95 integer :: stst, stend, kptst, kptend, sdim, mdim
96 integer :: imdim
97 integer :: isp
98 integer :: ith, iph
99 real(real64) :: thetar, phir, radius
100 real(real64) :: xx(mesh%box%dim)
101
102 push_sub(pes_spm_init)
103
104 stst = st%st_start
105 stend = st%st_end
106 kptst = st%d%kpt%start
107 kptend = st%d%kpt%end
108 sdim = st%d%dim
109 mdim = mesh%box%dim
110
111 message(1) = 'Info: Calculating PES using sample point technique.'
112 call messages_info(1, namespace=namespace)
113
114 !%Variable PES_spm_points
115 !%Type block
116 !%Section Time-Dependent::PhotoElectronSpectrum
117 !%Description
118 !% List of points at which to calculate the photoelectron spectrum by the sample point
119 !% method. If no points are given, a spherical grid is generated automatically.
120 !% The exact syntax is:
121 !%
122 !% <tt>%PES_spm_points
123 !% <br>&nbsp;&nbsp;x1 | y1 | z1
124 !% <br>%
125 !% </tt>
126 !%End
127 call messages_obsolete_variable(namespace, 'PhotoElectronSpectrumPoints', 'PES_spm_points')
128 this%sphgrid = .false.
129 if (parse_block(namespace, 'PES_spm_points', blk) < 0) then
130 this%sphgrid = .true.
131 end if
132
133 if (this%sphgrid) then
134 message(1) = 'Info: Using spherical grid.'
135 else
136 message(1) = 'Info: Using sample points from block.'
137 end if
138 call messages_info(1, namespace=namespace)
139
140 !%Variable PES_spm_recipe
141 !%Type integer
142 !%Default phase
143 !%Section Time-Dependent::PhotoElectronSpectrum
144 !%Description
145 !% The type for calculating the photoelectron spectrum in the sample point method.
146 !%Option raw 1
147 !% Calculate the photoelectron spectrum according to A. Pohl, P.-G. Reinhard, and
148 !% E. Suraud, <i>Phys. Rev. Lett.</i> <b>84</b>, 5090 (2000).
149 !%Option phase 2
150 !% Calculate the photoelectron spectrum by including the Volkov phase (approximately), see
151 !% P. M. Dinh, P. Romaniello, P.-G. Reinhard, and E. Suraud, <i>Phys. Rev. A.</i> <b>87</b>, 032514 (2013).
152 !%End
153 call parse_variable(namespace, 'PES_spm_recipe', m_phase, this%recipe)
154 if (.not. varinfo_valid_option('PES_spm_recipe', this%recipe, is_flag = .true.)) then
155 call messages_input_error(namespace, 'PES_spm_recipe')
156 end if
157 call messages_print_var_option("PES_spm_recipe", this%recipe, namespace=namespace)
159 !%Variable PES_spm_OmegaMax
160 !%Type float
161 !%Default 0.0
162 !%Section Time-Dependent::PhotoElectronSpectrum
163 !%Description
164 !% If <tt>PES_spm_OmegaMax > 0</tt>, the photoelectron spectrum is directly calculated during
165 !% time-propagation, evaluated by the PES_spm method. <tt>PES_spm_OmegaMax</tt> is then the maximum frequency
166 !% (approximate kinetic energy) and <tt>PES_spm_DeltaOmega</tt> the spacing in frequency domain of the spectrum.
167 !%End
168 call parse_variable(namespace, 'PES_spm_OmegaMax', units_to_atomic(units_inp%energy, m_zero), this%omegamax)
169 this%onfly = .false.
170 if (this%omegamax > m_zero) then
171 this%onfly = .true.
172 message(1) = 'Info: Calculating PES during time propagation.'
173 call messages_info(1, namespace=namespace)
174 call messages_print_var_value("PES_spm_OmegaMax", this%omegamax, namespace=namespace)
175 end if
176
177 !%Variable PES_spm_DeltaOmega
178 !%Type float
179 !%Section Time-Dependent::PhotoElectronSpectrum
180 !%Description
181 !% The spacing in frequency domain for the photoelectron spectrum (if <tt>PES_spm_OmegaMax > 0</tt>).
182 !% The default is <tt>PES_spm_OmegaMax/500</tt>.
183 !%End
184 call parse_variable(namespace, 'PES_spm_DeltaOmega', units_to_atomic(units_inp%energy, this%omegamax/500_real64), this%delomega)
185 if (this%onfly) then
186 if (this%delomega <= m_zero) call messages_input_error(namespace, 'PES_spm_DeltaOmega')
187 call messages_print_var_value("PES_spm_DeltaOmega", this%delomega, namespace=namespace)
188 end if
189
190 !%Variable PES_spm_StepsThetaR
191 !%Type integer
192 !%Default 45
193 !%Section Time-Dependent::PhotoElectronSpectrum
194 !%Description
195 !% Number of steps in <math>\theta</math> (<math>0 \le \theta \le \pi</math>) for the spherical grid (if no
196 !% <tt>PES_spm_points</tt> are given).
197 !%End
198 call parse_variable(namespace, 'PES_spm_StepsThetaR', 45, this%nstepsthetar)
199 if (this%sphgrid .and. this%nstepsthetar < 0) call messages_input_error(namespace, 'PES_spm_StepsThetaR')
200
201 !%Variable PES_spm_StepsPhiR
202 !%Type integer
203 !%Default 90
204 !%Section Time-Dependent::PhotoElectronSpectrum
205 !%Description
206 !% Number of steps in <math>\phi</math> (<math>0 \le \phi \le 2 \pi</math>) for the spherical grid (if no
207 !% <tt>PES_spm_points</tt> are given).
208 !%End
209 call parse_variable(namespace, 'PES_spm_StepsPhiR', 90, this%nstepsphir)
210 if (this%sphgrid) then
211 if (this%nstepsphir < 0) call messages_input_error(namespace, 'PES_spm_StepsPhiR')
212 if (this%nstepsphir == 0) this%nstepsphir = 1
213 end if
214
215 !%Variable PES_spm_Radius
216 !%Type float
217 !%Section Time-Dependent::PhotoElectronSpectrum
218 !%Description
219 !% The radius of the sphere for the spherical grid (if no <tt>PES_spm_points</tt>
220 !% are given).
221 !%End
222 if (this%sphgrid) then
223 if (parse_is_defined(namespace, 'PES_spm_Radius')) then
224 call parse_variable(namespace, 'PES_spm_Radius', m_zero, radius)
225 if (radius <= m_zero) call messages_input_error(namespace, 'PES_spm_Radius')
226 call messages_print_var_value("PES_spm_Radius", radius, namespace=namespace)
227 else
228 select type (box => mesh%box)
229 type is (box_sphere_t)
230 radius = box%radius
231 type is (box_parallelepiped_t)
232 radius = minval(box%half_length(1:mdim))
233 class default
234 message(1) = "Spherical grid not implemented for this box shape."
235 message(2) = "Specify sample points with block PES_spm_points."
236 call messages_fatal(2, namespace=namespace)
237 end select
238 end if
239 end if
240
241 call mesh_interpolation_init(this%interp, mesh)
242
243 if (.not. this%sphgrid) then
244 this%nspoints = parse_block_n(blk)
245 else
246 ! setting values for spherical grid
247 select case (mdim)
248 case (1)
249 this%nstepsthetar = 0
250 this%nstepsphir = 2
251 this%nspoints = this%nstepsphir
252
253 case (2)
254 this%nstepsthetar = 0
255 this%nspoints = this%nstepsphir
256
257 case (3)
258 if (this%nstepsthetar <= 1) then
259 this%nstepsphir = 1
260 this%nstepsthetar = 1
261 end if
262 this%nspoints = this%nstepsphir * (this%nstepsthetar - 1) + 2
263
264 end select
265
266 if (mdim == 3) call messages_print_var_value("PES_spm_StepsThetaR", this%nstepsthetar, namespace=namespace)
267 call messages_print_var_value("PES_spm_StepsPhiR", this%nstepsphir, namespace=namespace)
268
269 end if
270
271 call messages_print_var_value("Number of sample points", this%nspoints, namespace=namespace)
272
273 safe_allocate(this%rcoords(1:mdim, 1:this%nspoints))
274 safe_allocate(this%rcoords_nrm(1:mdim, 1:this%nspoints))
275
276 if (.not. this%sphgrid) then
277
278 message(1) = 'Info: Reading sample points from input.'
279 call messages_info(1, namespace=namespace)
280
281 ! read points from input file
282 do isp = 1, this%nspoints
283 do imdim = 1, mdim
284 call parse_block_float(blk, isp - 1, imdim - 1, xx(imdim), units_inp%length)
285 end do
286 this%rcoords(:, isp) = xx(:)
287 this%rcoords_nrm(:, isp) = this%rcoords(:, isp) / norm2(this%rcoords(:, isp))
288 end do
289 call parse_block_end(blk)
290
291 else ! this%sphgrid == .true.
292
293 message(1) = 'Info: Initializing spherical grid.'
294 call messages_info(1, namespace=namespace)
295
296 ! initializing spherical grid
297 thetar = m_pi / m_two
298 isp = 0
299 do ith = 0, this%nstepsthetar
300 if (mdim == 3) thetar = ith * m_pi / this%nstepsthetar
301 do iph = 0, this%nstepsphir - 1
302 isp = isp + 1
303 phir = iph * m_two * m_pi / this%nstepsphir
304 this%rcoords_nrm(1, isp) = cos(phir) * sin(thetar)
305 if (mdim >= 2) this%rcoords_nrm(2, isp) = sin(phir) * sin(thetar)
306 if (mdim == 3) this%rcoords_nrm(3, isp) = cos(thetar)
307 this%rcoords(:, isp) = radius * this%rcoords_nrm(:, isp)
308 if (mdim == 3 .and. (ith == 0 .or. ith == this%nstepsthetar)) exit
309 end do
310 end do
311
312 end if
313
314 safe_allocate(this%wf(stst:stend, 1:sdim, kptst:kptend, 1:this%nspoints, 0:save_iter-1))
315
316 if (this%recipe == m_phase) then
317 safe_allocate(this%dq(1:this%nspoints, 0:save_iter-1))
318 safe_allocate(this%domega(0:save_iter-1))
319 this%dq = m_zero
320 this%domega = m_zero
321 end if
322
323 if (this%onfly) then
324 this%nomega = nint(this%omegamax/this%delomega)
325 safe_allocate(this%wfft(stst:stend, 1:sdim, kptst:kptend, 1:this%nspoints, 1:this%nomega))
326 this%wfft = m_z0
327 end if
328
329 this%save_iter = save_iter
330
331 pop_sub(pes_spm_init)
332 end subroutine pes_spm_init
333
334
335 ! ---------------------------------------------------------
336 subroutine pes_spm_end(this)
337 type(pes_spm_t), intent(inout) :: this
338
339 push_sub(pes_spm_end)
340
341 safe_deallocate_a(this%wf)
342 safe_deallocate_a(this%rcoords)
343 safe_deallocate_a(this%rcoords_nrm)
344
345 safe_deallocate_a(this%wfft)
346
347 safe_deallocate_a(this%dq)
348 safe_deallocate_a(this%domega)
349
350 pop_sub(pes_spm_end)
351 end subroutine pes_spm_end
352
353
354 ! ---------------------------------------------------------
355 subroutine pes_spm_calc(this, st, mesh, dt, iter, ext_partners)
356 type(pes_spm_t), intent(inout) :: this
357 type(states_elec_t), intent(in) :: st
358 type(mesh_t), intent(in) :: mesh
359 real(real64), intent(in) :: dt
360 integer, intent(in) :: iter
361 type(partner_list_t),intent(in) :: ext_partners
362
363 integer :: stst, stend, kptst, kptend, sdim, mdim
364 integer :: ist, ik, isdim
365 integer :: itstep
366
367 complex(real64), allocatable :: psistate(:), wfftact(:,:,:,:,:)
368 complex(real64) :: rawfac
369 complex(real64), allocatable :: phasefac(:)
370 integer :: iom
371 real(real64) :: omega
372 complex(real64), allocatable :: interp_values(:)
373
374 push_sub(pes_spm_calc)
375
376 itstep = mod(iter-1, this%save_iter)
377
378 stst = st%st_start
379 stend = st%st_end
380 kptst = st%d%kpt%start
381 kptend = st%d%kpt%end
382 sdim = st%d%dim
383 mdim = mesh%box%dim
384
385 safe_allocate(psistate(1:mesh%np_part))
386 safe_allocate(interp_values(1:this%nspoints))
387
388 if (this%onfly) then
389 safe_allocate(wfftact(1:st%nst, 1:sdim, 1:st%nik, 1:this%nspoints, 1:this%nomega))
390 wfftact = m_z0
391 end if
392
393 if (this%recipe == m_phase) then
394 safe_allocate(phasefac(1:this%nspoints))
395 end if
396
397 ! needed for allreduce, otherwise it will take values from previous cycle
398 this%wf(:,:,:,:,itstep) = m_z0
399
400 do ik = kptst, kptend
401 do ist = stst, stend
402 do isdim = 1, sdim
403 call states_elec_get_state(st, mesh, isdim, ist, ik, psistate(1:mesh%np_part))
404 call mesh_interpolation_evaluate(this%interp, this%nspoints, psistate(1:mesh%np_part), &
405 this%rcoords(1:mdim, 1:this%nspoints), interp_values(1:this%nspoints))
406 this%wf(ist, isdim, ik, :, itstep) = st%occ(ist, ik) * interp_values(:)
407 end do
408 end do
409 end do
410
411 if (this%recipe == m_phase) then
412 call pes_spm_calc_rcphase(this, mesh, iter, dt, ext_partners, itstep)
413 end if
414
415 if (this%onfly) then
416 do iom = 1, this%nomega
417 omega = iom*this%delomega
418 rawfac = exp(m_zi * omega * iter * dt) * dt / (m_two * m_pi)**(mdim/m_two)
419
420 if (this%recipe == m_raw) then
421 wfftact(stst:stend, 1:sdim, kptst:kptend, :, iom) = &
422 rawfac * sqrt(m_two * omega) * this%wf(stst:stend, 1:sdim, kptst:kptend, :, itstep)
423 else
424 phasefac(:) = rawfac * exp(m_zi * (this%domega(itstep) - sqrt(m_two * omega) * this%dq(:, itstep)))
425
426 do ik = kptst, kptend
427 do ist = stst, stend
428 do isdim = 1, sdim
429 wfftact(ist, isdim, ik, :, iom) = phasefac(:) * this%wf(ist, isdim, ik, :, itstep) * sqrt(m_two * omega)
430 end do
431 end do
432 end do
433 end if
434 end do
435
436 this%wfft = this%wfft + wfftact
437 end if
438
439 safe_deallocate_a(psistate)
440 safe_deallocate_a(interp_values)
441 safe_deallocate_a(phasefac)
442
443 safe_deallocate_a(wfftact)
444
445 pop_sub(pes_spm_calc)
446 end subroutine pes_spm_calc
447
449 ! ---------------------------------------------------------
450 subroutine pes_spm_output(this, mesh, st, namespace, iter, dt)
451 type(pes_spm_t), intent(in) :: this
452 class(mesh_t), intent(in) :: mesh
453 type(states_elec_t), intent(in) :: st
454 type(namespace_t), intent(in) :: namespace
455 integer, intent(in) :: iter
456 real(real64), intent(in) :: dt
457
458 integer :: ist, ik, isdim
459 integer :: ii, jj
460 integer :: isp, save_iter, isp_save
461 integer :: iom, ith, iph, iphi, itot
462 real(real64) :: omega, thetar, phir
463 complex(real64) :: vfu
464 real(real64) :: weight
465 real(real64), allocatable :: spctrsum(:,:,:,:), spctrout(:,:)
466 character(len=80) :: filenr
467 integer :: iunitone, iunittwo
468 integer :: stst, stend, kptst, kptend, sdim, mdim
469
470 push_sub(pes_spm_output)
471
472 stst = st%st_start
473 stend = st%st_end
474 kptst = st%d%kpt%start
475 kptend = st%d%kpt%end
476 sdim = st%d%dim
477 mdim = mesh%box%dim
478
479 save_iter = this%save_iter
480
481 if (this%onfly) then
482 safe_allocate(spctrsum(1:st%nst, 1:sdim, 1:st%nik, 1:this%nomega))
483 spctrsum = m_zero
484
485 safe_allocate(spctrout(1:this%nspoints, 1:this%nomega))
486 spctrout = m_zero
487
488 do ik = kptst, kptend
489 do ist = stst, stend
490 do isdim = 1, sdim
491
492 if (this%sphgrid) then
493
494 select case (mdim)
495 case (1)
496 weight = m_half
497
498 do iom = 1, this%nomega
499 spctrsum(ist, isdim, ik, iom) = spctrsum(ist, isdim, ik, iom) + &
500 sum(abs(this%wfft(ist, isdim, ik, :, iom)**m_two),1) * weight
501 end do
502
503 case (2)
504 weight = m_two * m_pi / this%nstepsphir
505
506 do iom = 1, this%nomega
507 do iph = 0, this%nstepsphir - 1
508 spctrsum(ist, isdim, ik, iom) = spctrsum(ist, isdim, ik, iom) + &
509 abs(this%wfft(ist, isdim, ik, iph, iom))**m_two * weight
510 end do
511 end do
512
513 case (3)
514 do iom = 1, this%nomega
515 isp = 0
516
517 do ith = 0, this%nstepsthetar
518 thetar = ith * m_pi / this%nstepsthetar
519
520 if (ith == 0 .or. ith == this%nstepsthetar) then
521 weight = (m_one - cos(m_pi / this%nstepsthetar / m_two)) * m_two * m_pi
522 else
523 weight = abs(cos(thetar - m_pi / this%nstepsthetar / m_two) - &
524 cos(thetar + m_pi / this%nstepsthetar / m_two)) * m_two * m_pi / this%nstepsphir
525 end if
526
527 do iph = 0, this%nstepsphir - 1
528 isp = isp + 1
529 spctrsum(ist, isdim, ik, iom) = spctrsum(ist, isdim, ik, iom) + &
530 abs(this%wfft(ist, isdim, ik, isp, iom))**m_two * weight
531
532 if (ith == 0 .or. ith == this%nstepsthetar) exit
533 end do
534 end do
535 end do
536 end select
537
538 ! distribution
539 spctrout(1:this%nspoints, 1:this%nomega) = spctrout(1:this%nspoints, 1:this%nomega) + &
540 abs(this%wfft(ist, isdim, ik, 1:this%nspoints, 1:this%nomega))**m_two
541
542 end if
543 end do
544 end do
545 end do
546
547 if (st%parallel_in_states .or. st%d%kpt%parallel) then
548 ! total spectrum = sum over all states
549 call comm_allreduce(st%st_kpt_mpi_grp, spctrout)
550
551 ! orbital spectra
552 call comm_allreduce(st%st_kpt_mpi_grp, spctrsum)
553 end if
554
555 ! -----------------------------------------------------------------
556 ! OUTPUT FOR SPHERICAL GRID
557 ! -----------------------------------------------------------------
558 if (this%sphgrid) then
559 iunittwo = io_open('td.general/'//'PES_spm.distribution.out', namespace, action='write', position='rewind')
560 iunitone = io_open('td.general/'//'PES_spm.power.sum', namespace, action='write', position='rewind')
561 write(iunitone, '(a23)') '# omega, total spectrum'
562
563 select case (mdim)
564 case (1)
565 write(iunittwo, '(a40)') '# omega, distribution (left/right point)'
566
567 do iom = 1, this%nomega
568 omega = iom * this%delomega
569 write(iunittwo, '(5(1x,e18.10E3))') omega, spctrout(2, iom), spctrout(1, iom)
570 write(iunitone, '(2(1x,e18.10E3))') omega, sum(sum(sum(spctrsum(:,:,:,iom),1),1),1) * sqrt(m_two * omega)
571 end do
572
573 case (2)
574 write(iunittwo, '(a26)') '# omega, phi, distribution'
575
576 do iom = 1, this%nomega
577 omega = iom * this%delomega
578
579 do iph = 0, this%nstepsphir - 1
580 phir = iph * m_two * m_pi / this%nstepsphir
581 write(iunittwo,'(5(1x,e18.10E3))') omega, phir, spctrout(iph + 1, iom)
582 end do
583 ! just repeat the result for output
584 write(iunittwo,'(5(1x,e18.10E3))') omega, m_two * m_pi, spctrout(1, iom)
585 write(iunittwo, '(1x)', advance='yes')
586
587 write(iunitone, '(2(1x,e18.10E3))', advance='no') omega, sum(sum(sum(spctrsum(:,:,:,iom),1),1),1) * sqrt(m_two * omega)
588
589 do ik = 1, st%nik
590 do ist = 1, st%nst
591 do isdim = 1, st%d%dim
592 write(iunitone, '(1x,e18.10E3)', advance='no') spctrsum(ist, isdim, ik, iom) * sqrt(m_two * omega)
593 end do
594 end do
595 end do
596 write(iunitone, '(1x)', advance='yes')
597
598 end do
599
600 case (3)
601 write(iunittwo, '(a33)') '# omega, theta, phi, distribution'
602
603 do iom = 1, this%nomega
604 omega = iom * this%delomega
605 isp = 0
606
607 do ith = 0, this%nstepsthetar
608 thetar = ith * m_pi / this%nstepsthetar
609
610 do iph = 0, this%nstepsphir - 1
611 isp = isp + 1
612
613 phir = iph * m_two * m_pi / this%nstepsphir
614 if (iph == 0) isp_save = isp
615 write(iunittwo,'(5(1x,e18.10E3))') omega, thetar, phir, spctrout(isp, iom)
616
617 ! just repeat the result for output
618 if (this%nstepsphir > 1 .and. iph == (this%nstepsphir - 1)) then
619 write(iunittwo,'(5(1x,e18.10E3))') omega, thetar, m_two * m_pi, spctrout(isp_save, iom)
620 end if
621
622 ! just repeat the result for output
623 if (ith == 0 .or. ith == this%nstepsthetar) then
624 if (this%nstepsphir > 1) then
625 do iphi = 1, this%nstepsphir
626 phir = iphi * m_two * m_pi / this%nstepsphir
627 write(iunittwo,'(5(1x,e18.10E3))') omega, thetar, phir, spctrout(isp, iom)
628 end do
629 end if
630 exit
631 end if
632 end do
633
634 if (this%nstepsphir > 1 .or. ith == this%nstepsthetar) write(iunittwo, '(1x)', advance='yes')
635 end do
636
637 ! write total and orbital spectra
638 write(iunitone, '(2(1x,e18.10E3))', advance='no') omega, sum(sum(sum(spctrsum(:,:,:,iom),1),1),1) * sqrt(m_two * omega)
639 do ik = 1, st%nik
640 do ist = 1, st%nst
641 do isdim = 1, st%d%dim
642 write(iunitone, '(1x,e18.10E3)', advance='no') spctrsum(ist, isdim, ik, iom) * sqrt(m_two * omega)
643 end do
644 end do
645 end do
646 write(iunitone, '(1x)', advance='yes')
647
648 end do
649 end select
650 call io_close(iunittwo)
651 call io_close(iunitone)
652
653 end if
654 end if
655
656 ! -----------------------------------------------------------------
657 ! DEBUG OUTPUT
658 ! -----------------------------------------------------------------
659 if (.not. this%sphgrid .or. debug%info) then ! too much output for spherical grid
660 if (mpi_grp_is_root(mesh%mpi_grp)) then
661 do ik = kptst, kptend
662 do ist = stst, stend
663 do isdim = 1, sdim
664 itot = ist + (ik-1) * st%nst + (isdim-1) * st%nst*st%d%kpt%nglobal
665 write(*,*) 'TEST', itot
666 write(filenr, '(i10.10)') itot
667
668 iunitone = io_open('td.general/'//'PES_spm.'//trim(filenr)//'.wavefunctions.out', &
669 namespace, action='write', position='append')
670
671 do ii = 1, save_iter - mod(iter, save_iter)
672 jj = iter - save_iter + ii + mod(save_iter - mod(iter, save_iter), save_iter)
673 write(iunitone, '(e17.10)', advance='yes') units_from_atomic(units_inp%time, jj * dt)
674
675 do isp = 1, this%nspoints
676 vfu = units_from_atomic(sqrt(units_out%length**(-3)), this%wf(ist, isdim, ik, isp, ii-1))
677 write(iunitone, '(1x,e18.10E3,1x,e18.10E3)', advance='no') real(vfu, real64) , aimag(vfu)
678 end do
679 write(iunitone, '(1x)', advance='yes')
680 end do
681
682 call io_close(iunitone)
683 end do
684 end do
685 end do
686
687 if (this%onfly) then
688 do ik = kptst, kptend
689 do ist = stst, stend
690 do isdim = 1, sdim
691 itot = ist + (ik-1) * st%nst + (isdim-1) * st%nst*st%d%kpt%nglobal
692 write(filenr, '(i10.10)') itot
693
694 iunitone = io_open('td.general/'//'PES_spm.'//trim(filenr)//'.spectrum.out', &
695 namespace, action='write', position='rewind')
696 write(iunitone, '(a48)') '# frequency, orbital spectrum at sampling points'
697
698 do iom = 1, this%nomega
699 omega = iom*this%delomega
700 write(iunitone, '(e17.10, 1x)', advance='no') omega
701
702 do isp = 1, this%nspoints
703 write(iunitone, '(e17.10, 1x)', advance='no') abs(this%wfft(ist, isdim, ik, isp, iom))**m_two
704 end do
705
706 write(iunitone, '(1x)', advance='yes')
707 end do
708
709 call io_close(iunitone)
710 end do
711 end do
712 end do
713 end if
714 end if
715
716 if (mpi_grp_is_root(mpi_world)) then
717 if (this%recipe == m_phase) then
718 do isp = 1, this%nspoints
719 write(filenr, '(i10.10)') isp
720 iunittwo = io_open('td.general/'//'PES_spm.'//trim(filenr)//'.phase.out', namespace, action='write', position='append')
721
722 do ii = 1, save_iter - mod(iter, save_iter)
723 jj = iter - save_iter + ii + mod(save_iter - mod(iter, save_iter), save_iter)
724
725 write(iunittwo, '(e17.10)', advance='no') units_from_atomic(units_inp%time, jj * dt)
726 write(iunittwo, '(1x,e18.10E3,1x,e18.10E3)', advance='no') this%domega(ii-1), this%dq(isp, ii-1)
727 write(iunittwo, '(1x)', advance='yes')
728 end do
729
730 call io_close(iunittwo)
731 end do
732 end if
733
734 if (this%onfly) then
735 iunitone = io_open('td.general/'//'PES_spm.total.out', namespace, action='write', position='rewind')
736 write(iunitone, '(a46)') '# frequency, total spectrum at sampling points'
737 do iom = 1, this%nomega
738 omega = iom*this%delomega
739
740 write(iunitone, '(e17.10, 1x)', advance='no') omega
741 do isp = 1, this%nspoints
742 write(iunitone, '(e17.10, 1x)', advance='no') spctrout(isp, iom)
743 end do
744
745 write(iunitone, '(1x)', advance='yes')
746 end do
747 call io_close(iunitone)
748 end if
749 end if
750 end if
751
752 safe_deallocate_a(spctrout)
753 safe_deallocate_a(spctrsum)
754
755 pop_sub(pes_spm_output)
756 end subroutine pes_spm_output
757
758 ! ---------------------------------------------------------
759 subroutine pes_spm_init_write(this, mesh, st, namespace)
760 type(pes_spm_t), intent(in) :: this
761 type(mesh_t), intent(in) :: mesh
762 type(states_elec_t), intent(in) :: st
763 type(namespace_t), intent(in) :: namespace
764
765 integer :: ist, ik, isdim
766 integer :: isp
767 real(real64) :: xx(mesh%box%dim)
768 character(len=80) :: filenr
769 integer :: iunit
770
771 push_sub(pes_spm_init_write)
772
773 if (mpi_grp_is_root(mpi_world)) then
774 if (.not. this%sphgrid .or. debug%info) then ! too much output for spherical grid
775 do isp = 1, this%nspoints
776 write(filenr, '(i10.10)') isp
777
778 iunit = io_open('td.general/'//'PES_spm.'//trim(filenr)//'.wavefunctions.out', namespace, action='write')
779 xx(:) = this%rcoords(1:mesh%box%dim, isp)
780 write(iunit,'(a1)') '#'
781 write(iunit, '(a7,f17.6,a1,f17.6,a1,f17.6,5a)') &
782 '# R = (',xx(1),' ,',xx(2),' ,',xx(3), &
783 ' ) [', trim(units_abbrev(units_inp%length)), ']'
784
785 write(iunit,'(a1)') '#'
786 write(iunit, '(a3,14x)', advance='no') '# t'
787 do ik = 1, st%nik
788 do ist = 1, st%nst
789 do isdim = 1, st%d%dim
790 write(iunit, '(3x,a8,i3,a7,i3,a8,i3,3x)', advance='no') &
791 "ik = ", ik, " ist = ", ist, " idim = ", isdim
792 end do
793 end do
794 end do
795 write(iunit, '(1x)', advance='yes')
796
797 call io_close(iunit)
798
799 if (this%recipe == m_phase) then
800 iunit = io_open('td.general/'//'PES_spm.'//trim(filenr)//'.phase.out', namespace, action='write')
801 write(iunit,'(a24)') '# time, dq(t), dOmega(t)'
802 call io_close(iunit)
803 end if
804 end do
805 end if
806 end if
807
808 pop_sub(pes_spm_init_write)
809 end subroutine pes_spm_init_write
810
811 ! ---------------------------------------------------------
812 subroutine pes_spm_dump(restart, this, st, ierr)
813 type(restart_t), intent(in) :: restart
814 type(pes_spm_t), intent(in) :: this
815 type(states_elec_t), intent(in) :: st
816 integer, intent(out) :: ierr
817
818 integer :: err, iunit
819
820 push_sub(pes_spm_dump)
821
822 err = 0
823 ierr = 0
824
825 if (restart_skip(restart)) then
826 pop_sub(pes_spm_dump)
827 return
828 end if
829
830 if (debug%info) then
831 message(1) = "Debug: Writing PES_spm restart."
832 call messages_info(1)
833 end if
834
835 if (this%onfly) then
836 call zrestart_write_binary(restart, 'pesspm', this%nspoints*st%d%dim*st%nst*st%nik*this%nomega, &
837 this%wfft, err)
838 end if
839
840 if (this%recipe == m_phase) then
841 iunit = restart_open(restart, 'rcphase')
842 write(iunit, *) this%domega(:), this%dq(:,:)
843 call restart_close(restart, iunit)
844 end if
845
846 if (err /= 0) ierr = ierr + 1
847
848 if (debug%info) then
849 message(1) = "Debug: Writing PES_spm restart done."
850 call messages_info(1)
851 end if
853 pop_sub(pes_spm_dump)
854 end subroutine pes_spm_dump
855
856 ! ---------------------------------------------------------
857 subroutine pes_spm_load(restart, this, st, ierr)
858 type(restart_t), intent(in) :: restart
859 type(pes_spm_t), intent(inout) :: this
860 type(states_elec_t), intent(inout) :: st
861 integer, intent(out) :: ierr
862
863 integer :: err, iunit
864
865 push_sub(pes_spm_load)
866
867 err = 0
868 ierr = 0
869
870 if (restart_skip(restart)) then
871 ierr = -1
872 pop_sub(pes_spm_load)
873 return
874 end if
875
876 if (debug%info) then
877 message(1) = "Debug: Reading PES_spm restart."
878 call messages_info(1)
879 end if
880
881 if (this%onfly) then
882 call zrestart_read_binary(restart, 'pesspm', this%nspoints*st%d%dim*st%nst*st%nik*this%nomega, &
883 this%wfft, err)
884 end if
885
886 if (this%recipe == m_phase) then
887 iunit = restart_open(restart, 'rcphase')
888 read(iunit, *) this%domega(:), this%dq(:,:)
889 call restart_close(restart, iunit)
890 end if
891
892 if (err /= 0) ierr = ierr + 1
893
894 if (debug%info) then
895 message(1) = "Debug: Reading PES_spm restart done."
896 call messages_info(1)
897 end if
898
899 pop_sub(pes_spm_load)
900 end subroutine pes_spm_load
901
902 ! ---------------------------------------------------------
903 subroutine pes_spm_calc_rcphase(this, mesh, iter, dt, ext_partners, ii)
904 type(pes_spm_t), intent(inout) :: this
905 type(mesh_t), intent(in) :: mesh
906 type(partner_list_t),intent(in) :: ext_partners
907 integer, intent(in) :: iter
908 real(real64), intent(in) :: dt
909 integer, intent(in) :: ii
910
911 integer :: isp
912 integer :: il, iprev
913 real(real64) :: vp(3)
914 real(real64) :: rdota
915 type(lasers_t), pointer :: lasers
916
917 push_sub(pes_spm_calc_rcphase)
918
919 vp = m_zero
920 lasers => list_get_lasers(ext_partners)
921 if(associated(lasers)) then
922 do il = 1, lasers%no_lasers
923 call laser_field(lasers%lasers(il), vp, iter*dt)
924 end do
925 vp = -vp
926 end if
927
928 iprev = ii - 1
929 if (ii == 0) iprev = this%save_iter - 1
930
931 do isp = 1, this%nspoints
932 rdota = dot_product(this%rcoords_nrm(1:mesh%box%dim, isp), vp(1:mesh%box%dim))
933 this%dq(isp, ii) = this%dq(isp, iprev) + rdota * dt / p_c
934 end do
935
936 this%domega(ii) = this%domega(iprev) + dot_product(vp, vp) / (m_two * p_c**m_two) * dt
937
938 pop_sub(pes_spm_calc_rcphase)
939 end subroutine pes_spm_calc_rcphase
940
941end module pes_spm_oct_m
942
943!! Local Variables:
944!! mode: f90
945!! coding: utf-8
946!! End:
Prints out to iunit a message in the form: ["InputVariable" = value] where "InputVariable" is given b...
Definition: messages.F90:180
double exp(double __x) __attribute__((__nothrow__
double sin(double __x) __attribute__((__nothrow__
double cos(double __x) __attribute__((__nothrow__
type(debug_t), save, public debug
Definition: debug.F90:154
type(lasers_t) function, pointer, public list_get_lasers(partners)
real(real64), parameter, public m_two
Definition: global.F90:189
real(real64), parameter, public m_zero
Definition: global.F90:187
real(real64), parameter, public m_pi
some mathematical constants
Definition: global.F90:185
complex(real64), parameter, public m_z0
Definition: global.F90:197
complex(real64), parameter, public m_zi
Definition: global.F90:201
real(real64), parameter, public m_half
Definition: global.F90:193
real(real64), parameter, public p_c
Electron gyromagnetic ratio, see Phys. Rev. Lett. 130, 071801 (2023)
Definition: global.F90:223
real(real64), parameter, public m_one
Definition: global.F90:188
This module defines classes and functions for interaction partners.
Definition: io.F90:114
subroutine, public io_close(iunit, grp)
Definition: io.F90:468
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:395
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:1111
subroutine, public mesh_interpolation_init(this, mesh)
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
subroutine, public messages_obsolete_variable(namespace, name, rep)
Definition: messages.F90:1057
subroutine, public messages_info(no_lines, iunit, verbose_limit, stress, all_nodes, namespace)
Definition: messages.F90:624
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:420
subroutine, public messages_input_error(namespace, var, details, row, column)
Definition: messages.F90:723
logical function mpi_grp_is_root(grp)
Is the current MPI process of grpcomm, root.
Definition: mpi.F90:430
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:266
logical function, public parse_is_defined(namespace, name)
Definition: parser.F90:502
integer function, public parse_block(namespace, name, blk, check_varinfo_)
Definition: parser.F90:618
integer, parameter m_phase
Definition: pes_spm.F90:173
subroutine, public pes_spm_dump(restart, this, st, ierr)
Definition: pes_spm.F90:906
subroutine, public pes_spm_init_write(this, mesh, st, namespace)
Definition: pes_spm.F90:853
subroutine, public pes_spm_output(this, mesh, st, namespace, iter, dt)
Definition: pes_spm.F90:544
subroutine, public pes_spm_calc(this, st, mesh, dt, iter, ext_partners)
Definition: pes_spm.F90:449
subroutine, public pes_spm_init(this, namespace, mesh, st, save_iter)
Definition: pes_spm.F90:181
subroutine, public pes_spm_load(restart, this, st, ierr)
Definition: pes_spm.F90:951
subroutine, public pes_spm_end(this)
Definition: pes_spm.F90:430
subroutine pes_spm_calc_rcphase(this, mesh, iter, dt, ext_partners, ii)
Definition: pes_spm.F90:997
subroutine, public restart_close(restart, iunit)
Close a file previously opened with restart_open.
Definition: restart.F90:950
logical pure function, public restart_skip(restart)
Returns true if the restart information should neither be read nor written. This might happen because...
Definition: restart.F90:967
integer function, public restart_open(restart, filename, status, position, silent)
Open file "filename" found inside the current restart directory. Depending on the type of restart,...
Definition: restart.F90:859
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:132
character(len=20) pure function, public units_abbrev(this)
Definition: unit.F90:223
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:132
Describes mesh distribution to nodes.
Definition: mesh.F90:186
The states_elec_t class contains all electronic wave functions.
int true(void)