Octopus
em_resp.F90
Go to the documentation of this file.
1!! Copyright (C) 2004-2012 Xavier Andrade, Eugene S. Kadantsev (ekadants@mjs1.phy.queensu.ca), David Strubbe
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 em_resp_oct_m
23 use box_oct_m
24 use debug_oct_m
27 use forces_oct_m
28 use global_oct_m
29 use grid_oct_m
32 use io_oct_m
33 use ions_oct_m
34 use, intrinsic :: iso_fortran_env
35 use kdotp_oct_m
39 use loct_oct_m
40 use mesh_oct_m
43 use mpi_oct_m
47 use output_oct_m
48 use parser_oct_m
49 use pcm_oct_m
57 use smear_oct_m
58 use sort_oct_m
59 use space_oct_m
65 use string_oct_m
66 use unit_oct_m
68 use utils_oct_m
69 use v_ks_oct_m
70 use xc_oct_m
71
72 implicit none
73
74 private
75
76 public :: &
79
80 integer, parameter :: &
81 PERTURBATION_ELECTRIC = 1, &
84
85
86 type em_resp_t
87 private
88 class(perturbation_t), pointer :: perturbation
89
90 integer :: nsigma
92 integer :: nfactor
95 integer :: nomega
96
97 real(real64) :: eta
98 real(real64) :: freq_factor(3)
99 real(real64), allocatable :: omega(:)
100 type(lr_t), allocatable :: lr(:,:,:)
101 complex(real64), allocatable :: alpha_k(:, :, :, :)
103 complex(real64), allocatable :: alpha_be_k(:, :, :, :)
105 logical :: calc_hyperpol
106 complex(real64) :: alpha(3, 3, 3)
107 complex(real64) :: alpha_be(3, 3, 3)
108 complex(real64) :: alpha0(3, 3, 3)
110 complex(real64) :: alpha_be0(3, 3, 3)
112 complex(real64) :: beta (3, 3, 3)
113
114 complex(real64) :: chi_para(3, 3)
115 complex(real64) :: chi_dia (3, 3)
116 complex(real64) :: magn(3)
117
118 logical :: ok(1:3)
119 logical :: force_no_kdotp
120
121 logical :: calc_rotatory
122 logical :: calc_Born
123 type(Born_charges_t) :: Born_charges(3)
124 logical :: occ_response
125 logical :: wfns_from_scratch
126 logical :: calc_magnetooptics
127 logical :: magnetooptics_nohvar
129 logical :: kpt_output
131 logical :: lrc_kernel
132
133 end type em_resp_t
134
135contains
136
137 ! ---------------------------------------------------------
138 subroutine em_resp_run(system, from_scratch)
139 class(*), intent(inout) :: system
140 logical, intent(in) :: from_scratch
141
142 push_sub(em_resp_run)
143
144 select type (system)
145 class is (multisystem_basic_t)
146 message(1) = "CalculationMode = em_resp not implemented for multi-system calculations"
147 call messages_fatal(1, namespace=system%namespace)
148 type is (electrons_t)
149 call em_resp_run_legacy(system, from_scratch)
150 end select
151
152 pop_sub(em_resp_run)
153 end subroutine em_resp_run
154
155 ! ---------------------------------------------------------
156 subroutine em_resp_run_legacy(sys, fromScratch)
157 type(electrons_t), intent(inout) :: sys
158 logical, intent(in) :: fromScratch
159
160 type(em_resp_t) :: em_vars
161 type(sternheimer_t) :: sh, sh_kdotp, sh2, sh_kmo, sh_mo
162 type(lr_t) :: kdotp_lr(sys%space%dim, 1)
163 type(lr_t), allocatable :: kdotp_em_lr2(:, :, :, :)
164 type(lr_t), allocatable :: b_lr(:, :)
165 type(lr_t), allocatable :: kb_lr(:, :, :), k2_lr(:, :, :)
166 type(lr_t), allocatable :: ke_lr(:, :, :, :)
167 class(perturbation_t), pointer :: pert_kdotp, pert2_none, pert_b
168
169 integer :: sigma, idir, idir2, ierr, iomega, ifactor
170 integer :: ierr_e(3), ierr_e2(3), nfactor_ke
171 character(len=100) :: str_tmp
172 logical :: complex_response, have_to_calculate, use_kdotp, opp_freq, &
173 exact_freq(3), complex_wfs, allocate_rho_em, allocate_rho_mo
174 logical :: magnetic_pert
176 real(real64) :: last_omega, frequency, dfrequency_eta
177 real(real64), allocatable :: dl_eig(:,:,:)
178 complex(real64) :: zfrequency_eta, lrc_coef(sys%space%dim, sys%space%dim)
179 type(restart_t) :: gs_restart, kdotp_restart
180
182
183 if (sys%hm%pcm%run_pcm) then
184 call messages_not_implemented("PCM for CalculationMode /= gs or td", namespace=sys%namespace)
185 end if
186
187 if (sys%kpoints%use_symmetries) then
188 call messages_experimental("em_resp with k-points symmetries", namespace=sys%namespace)
189 end if
191 if (sys%kpoints%reduced%npoints /= sys%kpoints%full%npoints) then
192 call messages_experimental('em_resp with reduced k-grid', namespace=sys%namespace)
193 end if
197 select type(ptr=>em_vars%perturbation)
199 if (any(abs(em_vars%omega(1:em_vars%nomega)) > m_epsilon)) then
200 call messages_not_implemented('Dynamical magnetic response', namespace=sys%namespace)
201 end if
202 end select
204 em_vars%lrc_kernel = .false.
205 if (abs(sys%ks%xc%lrc%alpha) > m_epsilon) em_vars%lrc_kernel = .true.
206
207 complex_wfs = states_are_complex(sys%st)
208 complex_response = (em_vars%eta > m_epsilon) .or. states_are_complex(sys%st)
209 call gs_restart%init(sys%namespace, restart_gs, restart_type_load, sys%mc, ierr, mesh=sys%gr, exact=.true.)
210 if (ierr == 0) then
211 call states_elec_look_and_load(gs_restart, sys%namespace, sys%space, sys%st, sys%gr, sys%kpoints, &
212 is_complex = complex_response)
213 call gs_restart%end()
214 else
215 message(1) = "Previous gs calculation is required."
216 call messages_fatal(1, namespace=sys%namespace)
217 end if
219 ! Use of ForceComplex will make this true after states_elec_look_and_load even if it was not before.
220 ! Otherwise, this line is a tautology.
221 complex_response = states_are_complex(sys%st)
223 if (states_are_real(sys%st)) then
224 message(1) = 'Info: Using real wavefunctions.'
225 else
226 message(1) = 'Info: Using complex wavefunctions.'
227 end if
228 call messages_info(1, namespace=sys%namespace)
229
230 ! setup Hamiltonian
231 message(1) = 'Info: Setting up Hamiltonian for linear response'
232 call messages_info(1, namespace=sys%namespace)
233 call v_ks_h_setup(sys%namespace, sys%space, sys%gr, sys%ions, sys%ext_partners, sys%st, sys%ks, sys%hm)
234
235 use_kdotp = sys%space%is_periodic() .and. .not. em_vars%force_no_kdotp
236
237 if (use_kdotp .and. .not. smear_is_semiconducting(sys%st%smear)) then
238 ! there needs to be a gap.
239 message(1) = "em_resp with kdotp can only be used with semiconducting smearing"
240 call messages_fatal(1, namespace=sys%namespace)
241 end if
242
243 ! read kdotp wavefunctions if necessary
244 if (use_kdotp) then
245 message(1) = "Reading kdotp wavefunctions for periodic directions."
246 call messages_info(1, namespace=sys%namespace)
247
248 call kdotp_restart%init(sys%namespace, restart_kdotp, restart_type_load, sys%mc, ierr, mesh=sys%gr)
249 if (ierr /= 0) then
250 message(1) = "Unable to read kdotp wavefunctions."
251 message(2) = "Previous kdotp calculation required."
252 call messages_fatal(2, namespace=sys%namespace)
253 end if
254
255 do idir = 1, sys%space%periodic_dim
256 call lr_init(kdotp_lr(idir, 1))
257 call lr_allocate(kdotp_lr(idir, 1), sys%st, sys%gr, allocate_rho = .false.)
258
259 ! load wavefunctions
260 str_tmp = kdotp_wfs_tag(idir)
261 ! 1 is the sigma index which is used in em_resp
262 call kdotp_restart%open_dir(wfs_tag_sigma(sys%namespace, str_tmp, 1), ierr)
263 if (ierr == 0) then
264 call states_elec_load(kdotp_restart, sys%namespace, sys%space, sys%st, sys%gr, sys%kpoints, ierr, &
265 lr=kdotp_lr(idir, 1))
266 end if
267 call kdotp_restart%close_dir()
268
269 if (ierr /= 0) then
270 message(1) = "Could not load kdotp wavefunctions from '"//trim(wfs_tag_sigma(sys%namespace, str_tmp, 1))//"'"
271 message(2) = "Previous kdotp calculation required."
272 call messages_fatal(2, namespace=sys%namespace)
273 end if
274 end do
275
276 call kdotp_restart%end()
277 end if
278
279 em_vars%nfactor = 1
280 if (em_vars%calc_hyperpol) em_vars%nfactor = 3
281
282 ! in effect, nsigma = 1 only if hyperpol not being calculated, and the only frequency is zero
283 if (em_vars%calc_hyperpol .or. any(abs(em_vars%omega(1:em_vars%nomega)) > m_epsilon)) then
284 em_vars%nsigma = 2
285 ! positive and negative values of the frequency must be considered
286 else
287 em_vars%nsigma = 1
288 ! only considering positive values
289 end if
290
291 if (em_vars%calc_hyperpol .and. use_kdotp) then
292 pert_kdotp => perturbation_kdotp_t(sys%namespace, sys%ions)
293 pert2_none => perturbation_none_t(sys%namespace)
294 call messages_experimental("Second-order Sternheimer equation", namespace=sys%namespace)
295 call pert2_none%setup_dir(1) ! direction is irrelevant
296 safe_allocate(kdotp_em_lr2(1:sys%space%periodic_dim, 1:sys%space%dim, 1:em_vars%nsigma, 1:em_vars%nfactor))
297 do ifactor = 1, em_vars%nfactor
298 do sigma = 1, em_vars%nsigma
299 do idir = 1, sys%space%periodic_dim
300 do idir2 = 1, sys%space%dim
301 call lr_init(kdotp_em_lr2(idir, idir2, sigma, ifactor))
302 call lr_allocate(kdotp_em_lr2(idir, idir2, sigma, ifactor), sys%st, sys%gr, allocate_rho = .false.)
303 end do
304 end do
305 end do
306 end do
307 call sternheimer_init(sh2, sys%namespace, sys%space, sys%gr, sys%st, sys%hm, sys%ks, sys%mc, &
308 complex_response, set_ham_var = 0, set_last_occ_response = .false.)
309 call sternheimer_init(sh_kdotp, sys%namespace, sys%space, sys%gr, sys%st, sys%hm, sys%ks, sys%mc, &
310 complex_response, set_ham_var = 0, set_last_occ_response = .true.)
311 em_vars%occ_response = .true.
312 safe_allocate(dl_eig(1:sys%st%nst, 1:sys%st%nik, 1:sys%space%periodic_dim))
313 end if
314
315 ! Hyperpolarizability requires full corrections to wavefunctions (with projections on occupied states).
316 ! Magnetooptics is implemented only for projections of corrections to wavefunctions on unoccupied states.
317 if (em_vars%calc_magnetooptics) then
318 if (em_vars%calc_hyperpol .and. use_kdotp) then
319 message(1) = "Hyperpolarizability and magnetooptics with kdotp are not compatible."
320 message(2) = "Only calculation of hyperpolarizability will be performed."
321 call messages_warning(2, namespace=sys%namespace)
322 em_vars%calc_magnetooptics = .false.
323 else
324 em_vars%nfactor = 2
325 em_vars%freq_factor(1) = m_one
326 em_vars%freq_factor(2) = -m_one
327 end if
328 end if
329
330 magnetic_pert = .false.
331 select type(ptr => em_vars%perturbation)
333 em_vars%nsigma = 1
334 if (use_kdotp) call messages_experimental("Magnetic perturbation for periodic systems", namespace=sys%namespace)
335 magnetic_pert = .true.
336 end select
337
338 if (em_vars%calc_magnetooptics .or. magnetic_pert) then
339 em_vars%occ_response = .false.
340
341 if (use_kdotp) then
342 pert2_none => perturbation_none_t(sys%namespace)
343 call pert2_none%setup_dir(1)
344
345 safe_allocate(k2_lr(1:sys%space%dim, 1:sys%space%dim, 1))
346 safe_allocate(kb_lr(1:sys%space%dim, 1:sys%space%dim, 1))
347 do idir = 1, sys%space%dim
348 do idir2 = 1, sys%space%dim
349 call lr_init(kb_lr(idir, idir2, 1))
350 call lr_allocate(kb_lr(idir, idir2, 1), sys%st, sys%gr, allocate_rho = .false.)
351 if (idir2 <= idir) then
352 call lr_init(k2_lr(idir, idir2, 1))
353 call lr_allocate(k2_lr(idir, idir2, 1), sys%st, sys%gr, allocate_rho = .false.)
354 end if
355 end do
356 end do
357
358 if (sys%space%periodic_dim < sys%space%dim) then
359 if (magnetic_pert) then
360 message(1) = "All directions should be periodic for magnetic perturbations with kdotp."
361 else
362 message(1) = "All directions should be periodic for magnetooptics with kdotp."
363 end if
364 call messages_fatal(1, namespace=sys%namespace)
365 end if
366 if (.not. complex_response) then
367 do idir = 1, sys%space%dim
368 call dlr_orth_response(sys%gr, sys%st, kdotp_lr(idir, 1), m_zero)
369 end do
370 else
371 do idir = 1, sys%space%dim
372 call zlr_orth_response(sys%gr, sys%st, kdotp_lr(idir, 1), m_z0)
373 end do
374 end if
375 call sternheimer_init(sh_kmo, sys%namespace, sys%space, sys%gr, sys%st, sys%hm, sys%ks, sys%mc, &
376 complex_response, set_ham_var = 0, set_last_occ_response = em_vars%occ_response)
377 end if
378 end if
379
380 safe_allocate(em_vars%lr(1:sys%space%dim, 1:em_vars%nsigma, 1:em_vars%nfactor))
381 do ifactor = 1, em_vars%nfactor
382 call born_charges_init(em_vars%Born_charges(ifactor), sys%namespace, sys%ions%natoms, &
383 sys%st%val_charge, sys%st%qtot, sys%space%dim)
384 end do
385
386 if (magnetic_pert .and. sys%st%d%nspin == 1 .and. states_are_real(sys%st)) then
387 ! first-order response is zero if there is time-reversal symmetry. F Mauri and SG Louie, PRL 76, 4246 (1996)
388 call sternheimer_init(sh, sys%namespace, sys%space, sys%gr, sys%st, sys%hm, sys%ks, sys%mc, &
389 complex_response, set_ham_var = 0, set_last_occ_response = em_vars%occ_response)
390 ! set HamiltonianVariation to V_ext_only, in magnetic case
391 else
392 call sternheimer_init(sh, sys%namespace, sys%space, sys%gr, sys%st, sys%hm, sys%ks, sys%mc, &
393 complex_response, set_last_occ_response = em_vars%occ_response)
394 ! otherwise, use default, which is hartree + fxc
395 end if
396
397 if (em_vars%lrc_kernel .and. (.not. sh%add_hartree()) &
398 .and. (.not. sh%add_fxc())) then
399 message(1) = "Only the G = G'= 0 term of the LRC kernel is taken into account."
400 call messages_warning(1, namespace=sys%namespace)
401 end if
402
403
404 if (mpi_world%is_root()) then
405 call info()
406 call io_mkdir(em_resp_dir, sys%namespace) ! output
407 end if
408
409 allocate_rho_em = sh%add_fxc() .or. sh%add_hartree()
410 do ifactor = 1, em_vars%nfactor
411 do idir = 1, sys%space%dim
412 do sigma = 1, em_vars%nsigma
413 call lr_init(em_vars%lr(idir, sigma, ifactor))
414 call lr_allocate(em_vars%lr(idir, sigma, ifactor), sys%st, sys%gr, allocate_rho = allocate_rho_em)
415 end do
416 end do
417 end do
418
419 select type(ptr=> em_vars%perturbation)
421 !Do nothing
422 class default
423 em_vars%kpt_output = .false.
424 end select
425 if (.not. use_kdotp .or. sys%st%nik == 1) em_vars%kpt_output = .false.
426
427 if (em_vars%kpt_output) then
428 safe_allocate(em_vars%alpha_k(1:sys%space%dim, 1:sys%space%dim, 1:em_vars%nfactor, 1:sys%st%nik))
429 end if
430
431 if (em_vars%calc_magnetooptics) then
432 if (em_vars%magnetooptics_nohvar) then
433 call sternheimer_init(sh_mo, sys%namespace, sys%space, sys%gr, sys%st, sys%hm, sys%ks, sys%mc, &
434 complex_response, set_ham_var = 0, set_last_occ_response = em_vars%occ_response)
435 else
436 call sternheimer_init(sh_mo, sys%namespace, sys%space, sys%gr, sys%st, sys%hm, sys%ks, sys%mc, &
437 complex_response, set_last_occ_response = em_vars%occ_response)
438 call sternheimer_build_kxc(sh_mo, sys%namespace, sys%gr, sys%st, sys%ks%xc)
439 end if
440 call messages_experimental("Magneto-optical response", namespace=sys%namespace)
441 allocate_rho_mo = sh_mo%add_fxc() .or. sh_mo%add_hartree()
442 safe_allocate(b_lr(1:sys%space%dim, 1))
443 do idir = 1, sys%space%dim
444 call lr_init(b_lr(idir, 1))
445 call lr_allocate(b_lr(idir, 1), sys%st, sys%gr, allocate_rho = allocate_rho_mo)
446 end do
447
448 if (use_kdotp) then
449 if (em_vars%kpt_output) then
450 safe_allocate(em_vars%alpha_be_k(1:sys%space%dim, 1:sys%space%dim, 1:sys%space%dim, 1:sys%st%nik))
451 end if
452 nfactor_ke = 1
453 if (sys%kpoints%use_time_reversal .and. sys%kpoints%full%npoints > 1) nfactor_ke = em_vars%nfactor
454 safe_allocate(ke_lr(1:sys%space%dim, 1:sys%space%dim, 1:em_vars%nsigma, 1:nfactor_ke))
455 do idir = 1, sys%space%dim
456 do idir2 = 1, sys%space%dim
457 do sigma = 1, em_vars%nsigma
458 do ifactor = 1, nfactor_ke
459 call lr_init(ke_lr(idir, idir2, sigma, ifactor))
460 call lr_allocate(ke_lr(idir, idir2, sigma, ifactor), sys%st, sys%gr, allocate_rho = .false.)
461 end do
462 end do
463 end do
464 end do
465 else
466 pert_b => perturbation_magnetic_t(sys%namespace, sys%ions)
467 end if
468 end if
469
470
471 last_omega = m_huge
472 do iomega = 1, em_vars%nomega
473
474 em_vars%ok(1:3) = .true.
475
476 do ifactor = 1, em_vars%nfactor
477 frequency = em_vars%freq_factor(ifactor)*em_vars%omega(iomega)
478 zfrequency_eta = cmplx(frequency, em_vars%eta, real64)
479 if (em_vars%calc_magnetooptics .and. ifactor == 2) zfrequency_eta = frequency - m_zi * em_vars%eta
480 dfrequency_eta = real(zfrequency_eta, real64)
481
482 if (abs(frequency) < m_epsilon .and. em_vars%calc_magnetooptics .and. use_kdotp) then
483 message(1) = "Magnetooptical response with kdotp requires non-zero frequency."
484 call messages_warning(1, namespace=sys%namespace)
485 end if
486
487 ierr = 0
488 ierr_e(:) = 0
489 ierr_e2(:) = 0
490
491 have_to_calculate = .true.
492 opp_freq = .false.
493
494 ! if this frequency is zero and this is not the first
495 ! iteration we do not have to do anything
496 if (iomega > 1 .and. abs(em_vars%freq_factor(ifactor)) <= m_epsilon) have_to_calculate = .false.
497
498 if (ifactor > 1 .and. (.not. em_vars%calc_magnetooptics)) then
499
500 ! if this frequency is the same as the previous one, just copy it
501 if (have_to_calculate .and. abs(em_vars%freq_factor(ifactor - 1) * em_vars%omega(iomega) &
502 - frequency) < m_epsilon) then
503
504 do idir = 1, sys%space%dim
505 call lr_copy(sys%st, sys%gr, em_vars%lr(idir, 1, ifactor - 1), em_vars%lr(idir, 1, ifactor))
506 call lr_copy(sys%st, sys%gr, em_vars%lr(idir, 2, ifactor - 1), em_vars%lr(idir, 2, ifactor))
507
508 if (em_vars%calc_hyperpol .and. use_kdotp) then
509 do idir2 = 1, sys%space%periodic_dim
510 call lr_copy(sys%st, sys%gr, kdotp_em_lr2(idir, idir2, 1, ifactor - 1), &
511 kdotp_em_lr2(idir, idir2, 1, ifactor))
512 call lr_copy(sys%st, sys%gr, kdotp_em_lr2(idir, idir2, 2, ifactor - 1), &
513 kdotp_em_lr2(idir, idir2, 2, ifactor))
514 end do
515 end if
516 end do
517
518 have_to_calculate = .false.
519
520 end if
521
522 ! if this frequency is minus the previous one, copy it inverted
523 if (have_to_calculate .and. abs(em_vars%freq_factor(ifactor - 1) * em_vars%omega(iomega) &
524 + frequency) < m_epsilon) then
525
526 do idir = 1, sys%space%dim
527 call lr_copy(sys%st, sys%gr, em_vars%lr(idir, 1, ifactor - 1), em_vars%lr(idir, 2, ifactor))
528 call lr_copy(sys%st, sys%gr, em_vars%lr(idir, 2, ifactor - 1), em_vars%lr(idir, 1, ifactor))
529
530 if (em_vars%calc_hyperpol .and. use_kdotp) then
531 do idir2 = 1, sys%space%periodic_dim
532 call lr_copy(sys%st, sys%gr, kdotp_em_lr2(idir, idir2, 1, ifactor - 1), &
533 kdotp_em_lr2(idir, idir2, 2, ifactor))
534 call lr_copy(sys%st, sys%gr, kdotp_em_lr2(idir, idir2, 2, ifactor - 1), &
535 kdotp_em_lr2(idir, idir2, 1, ifactor))
536 end do
537 end if
538 end do
539
540 have_to_calculate = .false.
541
542 end if
543
544 end if
545
546 if (iomega > 1 .and. ifactor == 1 .and. (.not. em_vars%calc_magnetooptics)) then
547
548 ! if this frequency is the same as the previous one, just copy it
549 if (have_to_calculate .and. abs(frequency - last_omega) < m_epsilon) then
550
551 do idir = 1, sys%space%dim
552 call lr_copy(sys%st, sys%gr, em_vars%lr(idir, 1, em_vars%nfactor), em_vars%lr(idir, 1, 1))
553 call lr_copy(sys%st, sys%gr, em_vars%lr(idir, 2, em_vars%nfactor), em_vars%lr(idir, 2, 1))
554
555 if (em_vars%calc_hyperpol .and. use_kdotp) then
556 do idir2 = 1, sys%space%periodic_dim
557 call lr_copy(sys%st, sys%gr, kdotp_em_lr2(idir, idir2, 1, em_vars%nfactor), &
558 kdotp_em_lr2(idir, idir2, 1, 1))
559 call lr_copy(sys%st, sys%gr, kdotp_em_lr2(idir, idir2, 2, em_vars%nfactor), &
560 kdotp_em_lr2(idir, idir2, 2, 1))
561 end do
562 end if
563 end do
564
565 have_to_calculate = .false.
566
567 end if
568
569 ! if this frequency is minus the previous one, copy it inverted
570 if (have_to_calculate .and. abs(frequency + last_omega) < m_epsilon) then
571
572 do idir = 1, sys%space%dim
573 call lr_copy(sys%st, sys%gr, em_vars%lr(idir, 1, em_vars%nfactor), em_vars%lr(idir, 2, 1))
574 call lr_copy(sys%st, sys%gr, em_vars%lr(idir, 2, em_vars%nfactor), em_vars%lr(idir, 1, 1))
575
576 if (em_vars%calc_hyperpol .and. use_kdotp) then
577 do idir2 = 1, sys%space%periodic_dim
578 call lr_copy(sys%st, sys%gr, kdotp_em_lr2(idir, idir2, 1, em_vars%nfactor), &
579 kdotp_em_lr2(idir, idir2, 2, 1))
580 call lr_copy(sys%st, sys%gr, kdotp_em_lr2(idir, idir2, 2, em_vars%nfactor), &
581 kdotp_em_lr2(idir, idir2, 1, 1))
582 end do
583 end if
584 end do
585
586 have_to_calculate = .false.
587
588 end if
589
590 end if
591
592 if (have_to_calculate) then
593
594 exact_freq(:) = .false.
595
596 if (states_are_real(sys%st)) then
597 call drun_sternheimer(em_vars, sys%namespace, sys%space, sys%gr, sys%kpoints, sys%st, sys%hm, sys%mc, &
598 sys%ions)
599 else
600 call zrun_sternheimer(em_vars, sys%namespace, sys%space, sys%gr, sys%kpoints, sys%st, sys%hm, sys%mc, &
601 sys%ions)
602 end if
603
604 end if ! have_to_calculate
605
606 if (.not. have_to_calculate) cycle
607
608 if (states_are_real(sys%st)) then
609 call dcalc_properties_linear(em_vars, sys%namespace, sys%space, sys%gr, sys%kpoints, sys%st, sys%hm, sys%ks%xc, &
610 sys%ions, sys%outp)
611 else
612 call zcalc_properties_linear(em_vars, sys%namespace, sys%space, sys%gr, sys%kpoints, sys%st, sys%hm, sys%ks%xc, &
613 sys%ions, sys%outp)
614 end if
615
616 end do ! ifactor
617
618 if (states_are_real(sys%st)) then
619 call dcalc_properties_nonlinear(em_vars, sys%namespace, sys%space, sys%gr, sys%st, sys%hm, sys%ks%xc)
620 else
621 call zcalc_properties_nonlinear(em_vars, sys%namespace, sys%space, sys%gr, sys%st, sys%hm, sys%ks%xc)
622 end if
623
624 last_omega = em_vars%freq_factor(em_vars%nfactor) * em_vars%omega(iomega)
625
626 end do ! iomega
627
628 do idir = 1, sys%space%dim
629 do sigma = 1, em_vars%nsigma
630 do ifactor = 1, em_vars%nfactor
631 call lr_dealloc(em_vars%lr(idir, sigma, ifactor))
632 end do
633 end do
634 end do
635
636 call sternheimer_end(sh)
637 deallocate(em_vars%perturbation)
638
639 if (use_kdotp) then
640 do idir = 1, sys%space%periodic_dim
641 call lr_dealloc(kdotp_lr(idir, 1))
642 end do
643 end if
644
645 if (em_vars%calc_hyperpol .and. use_kdotp) then
646 call sternheimer_end(sh_kdotp)
647 call sternheimer_end(sh2)
648 safe_deallocate_p(pert_kdotp)
649 safe_deallocate_p(pert2_none)
650 do idir = 1, sys%space%periodic_dim
651 do idir2 = 1, sys%space%periodic_dim
652 do sigma = 1, em_vars%nsigma
653 do ifactor = 1, em_vars%nfactor
654 call lr_dealloc(kdotp_em_lr2(idir, idir2, sigma, ifactor))
655 end do
656 end do
657 end do
658 end do
659 safe_deallocate_a(kdotp_em_lr2)
660 safe_deallocate_a(dl_eig)
661 end if
662
663 if (em_vars%kpt_output) then
664 safe_deallocate_a(em_vars%alpha_k)
665 end if
666
667 if (em_vars%calc_magnetooptics .or. magnetic_pert) then
668 if (use_kdotp) then
669 safe_deallocate_p(pert2_none)
670 call sternheimer_end(sh_kmo)
671 do idir = 1, sys%space%dim
672 do idir2 = 1, sys%space%dim
673 call lr_dealloc(kb_lr(idir, idir2, 1))
674 if (idir2 <= idir) call lr_dealloc(k2_lr(idir, idir2, 1))
675 end do
676 end do
677 safe_deallocate_a(k2_lr)
678 safe_deallocate_a(kb_lr)
679 end if
680 end if
681
682 if (em_vars%calc_magnetooptics) then
683 if (.not. em_vars%magnetooptics_nohvar) call sternheimer_unset_kxc(sh_mo)
684 call sternheimer_end(sh_mo)
685 do idir = 1, sys%space%dim
686 call lr_dealloc(b_lr(idir, 1))
687 end do
688 safe_deallocate_a(b_lr)
689
690 if (use_kdotp) then
691 do idir = 1, sys%space%dim
692 do idir2 = 1, sys%space%dim
693 do sigma = 1, em_vars%nsigma
694 do ifactor = 1, nfactor_ke
695 call lr_dealloc(ke_lr(idir, idir2, sigma, ifactor))
696 end do
697 end do
698 end do
699 end do
700 safe_deallocate_a(ke_lr)
701 if (em_vars%kpt_output) then
702 safe_deallocate_a(em_vars%alpha_be_k)
703 end if
704 else
705 safe_deallocate_p(pert_b)
706 end if
707 end if
708
709 safe_deallocate_a(em_vars%omega)
710 safe_deallocate_a(em_vars%lr)
711 do ifactor = 1, em_vars%nfactor
712 call born_charges_end(em_vars%Born_charges(ifactor))
713 end do
714 call states_elec_deallocate_wfns(sys%st)
715
716 pop_sub(em_resp_run_legacy)
717 contains
718
719 ! ---------------------------------------------------------
720 subroutine parse_input()
721
722 type(block_t) :: blk
723 integer :: nrow, irow, nfreqs_in_row, ifreq, istep, perturb_type
724 real(real64) :: omega_ini, omega_fin, domega
725 logical :: freq_sort
726
728
729 call messages_obsolete_variable(sys%namespace, 'PolFreqs ', 'EMFreqs ')
730 call messages_obsolete_variable(sys%namespace, 'PolHyper ', 'EMHyperpol ')
731 call messages_obsolete_variable(sys%namespace, 'PolEta ', 'EMEta ')
732 call messages_obsolete_variable(sys%namespace, 'PolHamiltonianVariation', 'HamiltonianVariation')
733
734 !%Variable EMFreqs
735 !%Type block
736 !%Section Linear Response::Polarizabilities
737 !%Description
738 !% This block defines for which frequencies the polarizabilities
739 !% will be calculated. If it is not present, the static (<math>\omega = 0</math>) response
740 !% is calculated.
741 !%
742 !% Each row of the block indicates a sequence of frequency values, the
743 !% first column is an integer that indicates the number of steps, the
744 !% second number is the initial frequency, and the third number the final
745 !% frequency. If the first number is one, then only the initial value is
746 !% considered. The block can have any number of rows. Consider the next example:
747 !%
748 !% <tt>%EMFreqs
749 !% <br>31 | 0.0 | 1.0
750 !% <br> 1 | 0.32
751 !% <br>%</tt>
752 !%
753 !%End
754
755 if (parse_block(sys%namespace, 'EMFreqs', blk) == 0) then
756
757 nrow = parse_block_n(blk)
758 em_vars%nomega = 0
759
760 !count the number of frequencies
761 do irow = 0, nrow-1
762 call parse_block_integer(blk, irow, 0, nfreqs_in_row)
763 if (nfreqs_in_row < 1) then
764 message(1) = "EMFreqs: invalid number of frequencies."
765 call messages_fatal(1, namespace=sys%namespace)
766 end if
767 em_vars%nomega = em_vars%nomega + nfreqs_in_row
768 end do
769
770 safe_allocate(em_vars%omega(1:em_vars%nomega))
771
772 !read frequencies
773 ifreq = 1
774 do irow = 0, nrow-1
775 call parse_block_integer(blk, irow, 0, nfreqs_in_row)
776 call parse_block_float(blk, irow, 1, omega_ini)
777 if (nfreqs_in_row > 1) then
778 call parse_block_float(blk, irow, 2, omega_fin)
779 domega = (omega_fin - omega_ini)/(nfreqs_in_row - m_one)
780 do istep = 0, nfreqs_in_row-1
781 em_vars%omega(ifreq + istep) = omega_ini + domega*istep
782 end do
783 ifreq = ifreq + nfreqs_in_row
784 else
785 em_vars%omega(ifreq) = omega_ini
786 ifreq = ifreq + 1
787 end if
788 end do
789
790 call parse_block_end(blk)
791
792 !%Variable EMFreqsSort
793 !%Type logical
794 !%Default true
795 !%Section Linear Response::Polarizabilities
796 !%Description
797 !% If true, the frequencies specified by the <tt>EMFreqs</tt> block are sorted, so that
798 !% they are calculated in increasing order. Can be set to false to use the order as stated,
799 !% in case this makes better use of available restart information.
800 !%End
801 call parse_variable(sys%namespace, 'EMFreqsSort', .true., freq_sort)
802
803 if (freq_sort) call sort(em_vars%omega)
804
805 else
806 !there is no frequency block, we calculate response for w = 0.0
807 em_vars%nomega = 1
808 safe_allocate(em_vars%omega(1:em_vars%nomega))
809 em_vars%omega(1) = m_zero
810 end if
811
812 !%Variable EMEta
813 !%Type float
814 !%Default 0.0
815 !%Section Linear Response::Polarizabilities
816 !%Description
817 !% The imaginary part of the frequency, effectively a Lorentzian broadening
818 !% for peaks in the spectrum. It can help convergence of the SCF cycle for the
819 !% Sternheimer equation when on a resonance, and it can be used as a positive
820 !% infinitesimal to get the imaginary parts of response functions at poles.
821 !% In units of energy. Cannot be negative.
822 !%End
823
824 call parse_variable(sys%namespace, 'EMEta', m_zero, em_vars%eta, units_inp%energy)
825 if (em_vars%eta < -m_epsilon) then
826 message(1) = "EMEta cannot be negative."
827 call messages_fatal(1, namespace=sys%namespace)
828 end if
829
830 ! reset the values of these variables
831 em_vars%calc_hyperpol = .false.
832 em_vars%freq_factor(1:3) = m_one
833 em_vars%calc_magnetooptics = .false.
834 em_vars%magnetooptics_nohvar = .true.
835 em_vars%kpt_output = .false.
836
837 !%Variable EMPerturbationType
838 !%Type integer
839 !%Default electric
840 !%Section Linear Response::Polarizabilities
841 !%Description
842 !% Which perturbation to consider for electromagnetic linear response.
843 !%Option electric 1
844 !% Electric perturbation used to calculate electric polarizabilities
845 !% and hyperpolarizabilities.
846 !%Option magnetic 2
847 !% Magnetic perturbation used to calculate magnetic susceptibilities.
848 !%Option none 0
849 !% Zero perturbation, for use in testing.
850 !%End
851 call parse_variable(sys%namespace, 'EMPerturbationType', perturbation_electric, perturb_type)
852 call messages_print_var_option('EMPerturbationType', perturb_type, namespace=sys%namespace)
853
854 select case(perturb_type)
855 case(perturbation_electric)
856 em_vars%perturbation => perturbation_electric_t(sys%namespace)
858 em_vars%perturbation => perturbation_magnetic_t(sys%namespace, sys%ions)
860 em_vars%perturbation => perturbation_none_t(sys%namespace)
861 case default
862 assert(.false.)
863 end select
864
865 select type(ptr=>em_vars%perturbation)
867 !%Variable EMCalcRotatoryResponse
868 !%Type logical
869 !%Default false
870 !%Section Linear Response::Polarizabilities
871 !%Description
872 !% Calculate circular-dichroism spectrum from electric perturbation,
873 !% and write to file <tt>rotatory_strength</tt>.
874 !%End
875
876 call parse_variable(sys%namespace, 'EMCalcRotatoryResponse', .false., em_vars%calc_rotatory)
877
878 !%Variable EMHyperpol
879 !%Type block
880 !%Section Linear Response::Polarizabilities
881 !%Description
882 !% This block describes the multiples of the frequency used for
883 !% the dynamic hyperpolarizability. The results are written to the
884 !% file <tt>beta</tt> in the directory for the first multiple.
885 !% There must be three factors, summing to zero: <math>\omega_1 + \omega_2 + \omega_3 = 0</math>.
886 !% For example, for second-harmonic generation, you could use
887 !% <tt>1 | 1 | -2</tt>.
888 !%End
889
890 if (parse_block(sys%namespace, 'EMHyperpol', blk) == 0) then
891 call parse_block_float(blk, 0, 0, em_vars%freq_factor(1))
892 call parse_block_float(blk, 0, 1, em_vars%freq_factor(2))
893 call parse_block_float(blk, 0, 2, em_vars%freq_factor(3))
894
895 call parse_block_end(blk)
896
897 if (abs(sum(em_vars%freq_factor(1:3))) > m_epsilon) then
898 message(1) = "Frequency factors specified by EMHyperpol must sum to zero."
899 call messages_fatal(1, namespace=sys%namespace)
900 end if
901
902 em_vars%calc_hyperpol = .true.
903 end if
904
905 !%Variable EMCalcMagnetooptics
906 !%Type logical
907 !%Default false
908 !%Section Linear Response::Polarizabilities
909 !%Description
910 !% Calculate magneto-optical response.
911 !%End
912 call parse_variable(sys%namespace, 'EMCalcMagnetooptics', .false., em_vars%calc_magnetooptics)
913
914 !%Variable EMMagnetoopticsNoHVar
915 !%Type logical
916 !%Default true
917 !%Section Linear Response::Polarizabilities
918 !%Description
919 !% Exclude corrections to the exchange-correlation and Hartree terms
920 !% from consideration of perturbations induced by a magnetic field
921 !%End
922 call parse_variable(sys%namespace, 'EMMagnetoopticsNoHVar', .true., em_vars%magnetooptics_nohvar)
923
924 !%Variable EMKPointOutput
925 !%Type logical
926 !%Default false
927 !%Section Linear Response::Polarizabilities
928 !%Description
929 !% Give in the output contributions of different k-points to the dielectric constant.
930 !% Can be also used for magneto-optical effects.
931 !%End
932
933 call parse_variable(sys%namespace, 'EMKPointOutput', .false., em_vars%kpt_output)
934
935 end select
936
937 !%Variable EMForceNoKdotP
938 !%Type logical
939 !%Default false
940 !%Section Linear Response::Polarizabilities
941 !%Description
942 !% If the system is periodic, by default wavefunctions from a previous <tt>kdotp</tt> run will
943 !% be read, to be used in the formulas for the polarizability and
944 !% hyperpolarizability in the quantum theory of polarization. For testing purposes,
945 !% you can set this variable to true to disregard the <tt>kdotp</tt> run, and use the formulas
946 !% for the finite system. This variable has no effect for a finite system.
947 !%End
948
949 call parse_variable(sys%namespace, 'EMForceNoKdotP', .false., em_vars%force_no_kdotp)
950
951 !%Variable EMCalcBornCharges
952 !%Type logical
953 !%Default false
954 !%Section Linear Response::Polarizabilities
955 !%Description
956 !% Calculate linear-response Born effective charges from electric perturbation (experimental).
957 !%End
958
959 call parse_variable(sys%namespace, 'EMCalcBornCharges', .false., em_vars%calc_Born)
960 if (em_vars%calc_Born) call messages_experimental("Calculation of Born effective charges", namespace=sys%namespace)
961
962 !%Variable EMOccupiedResponse
963 !%Type logical
964 !%Default false
965 !%Section Linear Response::Polarizabilities
966 !%Description
967 !% Solve for full response without projector into unoccupied subspace.
968 !% Not possible if there are partial occupations.
969 !% When <tt>EMHyperpol</tt> is set for a periodic system, this variable is ignored and
970 !% the full response is always calculated.
971 !%End
972
973 call parse_variable(sys%namespace, 'EMOccupiedResponse', .false., em_vars%occ_response)
974 if (em_vars%occ_response .and. .not. (smear_is_semiconducting(sys%st%smear) .or. sys%st%smear%method == smear_fixed_occ)) then
975 message(1) = "EMOccupiedResponse cannot be used if there are partial occupations."
976 call messages_fatal(1, namespace=sys%namespace)
977 end if
978
979 !%Variable EMWavefunctionsFromScratch
980 !%Type logical
981 !%Default false
982 !%Section Linear Response::Polarizabilities
983 !%Description
984 !% Do not use saved linear-response wavefunctions from a previous run as starting guess.
985 !% Instead initialize to zero as in <tt>FromScratch</tt>, but restart densities will still
986 !% be used. Restart wavefunctions from a very different frequency can hinder convergence.
987 !%End
988
989 call parse_variable(sys%namespace, 'EMWavefunctionsFromScratch', .false., em_vars%wfns_from_scratch)
990
992
993 end subroutine parse_input
994
995
996 ! ---------------------------------------------------------
997 subroutine info()
998
999 push_sub(em_resp_run_legacy.info)
1000
1001 call em_vars%perturbation%info()
1002 select type(ptr=>em_vars%perturbation)
1004 if (em_vars%calc_hyperpol) then
1005 call messages_print_with_emphasis(msg='Linear-Response First-Order Hyperpolarizabilities', namespace=sys%namespace)
1006 else
1007 call messages_print_with_emphasis(msg='Linear-Response Polarizabilities', namespace=sys%namespace)
1008 end if
1009 class default
1010 call messages_print_with_emphasis(msg='Magnetic Susceptibilities', namespace=sys%namespace)
1011 end select
1012
1013 if (states_are_real(sys%st)) then
1014 message(1) = 'Wavefunctions type: Real'
1015 else
1016 message(1) = 'Wavefunctions type: Complex'
1017 end if
1018 call messages_info(1, namespace=sys%namespace)
1019
1020 write(message(1),'(a,i3,a)') 'Calculating response for ', em_vars%nomega, ' frequencies.'
1021 call messages_info(1, namespace=sys%namespace)
1022
1023 call messages_print_with_emphasis(namespace=sys%namespace)
1024
1025 pop_sub(em_resp_run_legacy.info)
1026
1027 end subroutine info
1028
1029! Note: unlike the typical usage, here the templates make 'internal procedures'
1030#include "undef.F90"
1031#include "real.F90"
1032#include "em_resp_inc.F90"
1033
1034#include "undef.F90"
1035#include "complex.F90"
1036#include "em_resp_inc.F90"
1037
1038#include "undef.F90"
1039 end subroutine em_resp_run_legacy
1040
1041
1042 ! ---------------------------------------------------------
1043 subroutine em_resp_output(st, namespace, space, gr, hm, ions, outp, sh, em_vars, iomega, ifactor)
1044 type(states_elec_t), intent(inout) :: st
1045 type(namespace_t), intent(in) :: namespace
1046 class(space_t), intent(in) :: space
1047 type(grid_t), intent(in) :: gr
1048 type(hamiltonian_elec_t), intent(inout) :: hm
1049 type(ions_t), intent(in) :: ions
1050 type(output_t), intent(in) :: outp
1051 type(sternheimer_t), intent(in) :: sh
1052 type(em_resp_t), intent(inout) :: em_vars
1053 integer, intent(in) :: iomega
1054 integer, intent(in) :: ifactor
1055
1056 integer :: iunit, idir
1057 character(len=80) :: dirname, str_tmp
1058 logical :: use_kdotp
1059 complex(real64) :: epsilon(space%dim, space%dim)
1060
1061 push_sub(em_resp_output)
1062
1063 use_kdotp = space%is_periodic() .and. .not. em_vars%force_no_kdotp
1064
1065 str_tmp = freq2str(units_from_atomic(units_out%energy, em_vars%freq_factor(ifactor)*em_vars%omega(iomega)))
1066 if (em_vars%calc_magnetooptics) str_tmp = freq2str(units_from_atomic(units_out%energy, em_vars%omega(iomega)))
1067 write(dirname, '(a, a)') em_resp_dir//'freq_', trim(str_tmp)
1068 call io_mkdir(trim(dirname), namespace)
1069
1070 if (sh%has_photons .and. mpi_world%is_root()) then
1071 iunit = io_open(trim(dirname)//'/photon_coord_q', namespace, action='write')
1072 write(iunit, '(a)') 'Photon coordinate Q [', trim(units_abbrev(units_out%energy)), ']'
1073 write(iunit, '(a)') ' Re Im'
1074 do idir = 1, space%dim
1075 write(iunit, '(f20.6,f20.6)') units_from_atomic(units_out%energy, sum(real(sh%zphoton_coord_q(:, idir)))), &
1076 units_from_atomic(units_out%energy, sum(aimag(sh%zphoton_coord_q(:, idir))))
1077 end do
1078 call io_close(iunit)
1079 end if
1080
1081 call write_eta()
1082
1083 select type(ptr=>em_vars%perturbation)
1085 if ((.not. em_vars%calc_magnetooptics) .or. ifactor == 1) then
1086 call out_polarizability()
1087 if (em_vars%calc_Born) then
1088 call born_output_charges(em_vars%born_charges(ifactor), ions%atom, ions%charge, ions%natoms, &
1089 namespace, space%dim, dirname, write_real = em_vars%eta < m_epsilon)
1090 end if
1091
1092 if (space%periodic_dim == space%dim) then
1094 end if
1095
1096 if ((.not. space%is_periodic() .or. em_vars%force_no_kdotp) .and. em_vars%calc_rotatory) then
1098 end if
1099
1100 else
1101 call out_magnetooptics()
1102 if (iomega == 1) call out_susceptibility()
1103 end if
1104
1106 call out_susceptibility()
1107 end select
1108
1110
1111 pop_sub(em_resp_output)
1112
1113 contains
1114
1115
1116 subroutine write_eta()
1117 if (.not. mpi_world%is_root()) return ! only first node outputs
1118
1119 push_sub(em_resp_output.write_eta)
1120
1121 iunit = io_open(trim(dirname)//'/eta', namespace, action='write')
1122
1123 write(iunit, '(3a)') 'Imaginary part of frequency [', trim(units_abbrev(units_out%energy)), ']'
1124 write(iunit, '(f20.6)') units_from_atomic(units_out%energy, em_vars%eta)
1125
1126 call io_close(iunit)
1127
1128 pop_sub(em_resp_output.write_eta)
1129 end subroutine write_eta
1130
1131
1132 ! ---------------------------------------------------------
1134 subroutine cross_section_header(out_file)
1135 integer, intent(in) :: out_file
1136
1137 character(len=80) :: header_string
1138 integer :: ii, idir, kdir
1139
1140 if (.not. mpi_world%is_root()) return ! only first node outputs
1141
1143
1144 !this header is the same as spectrum.F90
1145 write(out_file, '(a1, a20)', advance = 'no') '#', str_center("Energy", 20)
1146 write(out_file, '(a20)', advance = 'no') str_center("(1/3)*Tr[sigma]", 20)
1147 write(out_file, '(a20)', advance = 'no') str_center("Anisotropy[sigma]", 20)
1148
1149 do idir = 1, space%dim
1150 do kdir = 1, space%dim
1151 write(header_string,'(a6,i1,a1,i1,a1)') 'sigma(', idir, ',', kdir, ')'
1152 write(out_file, '(a20)', advance = 'no') str_center(trim(header_string), 20)
1153 end do
1154 end do
1155
1156 write(out_file, *)
1157 write(out_file, '(a1,a20)', advance = 'no') '#', str_center('['//trim(units_abbrev(units_out%energy)) // ']', 20)
1158 do ii = 1, 2 + space%dim**2
1159 write(out_file, '(a20)', advance = 'no') str_center('['//trim(units_abbrev(units_out%length**2)) // ']', 20)
1160 end do
1161 write(out_file,*)
1162
1164 end subroutine cross_section_header
1165
1166
1167 ! ---------------------------------------------------------
1168 subroutine out_polarizability()
1169 real(real64) :: cross(space%dim, space%dim), crossp(space%dim, space%dim)
1170 real(real64) :: cross_sum, crossp_sum, anisotropy
1171 integer :: idir, idir2
1172
1173 if (.not. mpi_world%is_root()) return ! only first node outputs
1174
1176
1177 iunit = io_open(trim(dirname)//'/alpha', namespace, action='write')
1178
1179 if (.not. em_vars%ok(ifactor)) write(iunit, '(a)') "# WARNING: not converged"
1180
1181 write(iunit, '(3a)') '# Polarizability tensor [', trim(units_abbrev(units_out%polarizability)), ']'
1182 call output_tensor(real(em_vars%alpha(:, :, ifactor), real64), space%dim, units_out%polarizability, iunit=iunit)
1183
1184 call io_close(iunit)
1185
1186 ! CROSS SECTION (THE IMAGINARY PART OF POLARIZABILITY)
1187 if (em_vars%eta > m_epsilon) then
1188 cross(1:space%dim, 1:space%dim) = aimag(em_vars%alpha(1:space%dim, 1:space%dim, ifactor)) * &
1189 em_vars%freq_factor(ifactor) * em_vars%omega(iomega) * (m_four * m_pi / p_c)
1190
1191 do idir = 1, space%dim
1192 do idir2 = 1, space%dim
1193 cross(idir, idir2) = units_from_atomic(units_out%length**2, cross(idir, idir2))
1194 end do
1195 end do
1196
1197 iunit = io_open(trim(dirname)//'/cross_section', namespace, action='write')
1198 if (.not. em_vars%ok(ifactor)) write(iunit, '(a)') "# WARNING: not converged"
1199
1200 crossp(1:space%dim, 1:space%dim) = matmul(cross(1:space%dim, 1:space%dim), cross(1:space%dim, 1:space%dim))
1201
1202 cross_sum = m_zero
1203 crossp_sum = m_zero
1204 do idir = 1, space%dim
1205 cross_sum = cross_sum + cross(idir, idir)
1206 crossp_sum = crossp_sum + crossp(idir, idir)
1207 end do
1208
1209 anisotropy = crossp_sum - m_third * cross_sum**2
1210
1211 call cross_section_header(iunit)
1212 write(iunit,'(3e20.8)', advance = 'no') &
1213 units_from_atomic(units_out%energy, em_vars%freq_factor(ifactor)*em_vars%omega(iomega)), &
1214 cross_sum * m_third, sqrt(max(anisotropy, m_zero))
1215 do idir = 1, space%dim
1216 do idir2 = 1, space%dim
1217 write(iunit,'(e20.8)', advance = 'no') cross(idir, idir2)
1218 end do
1219 end do
1220 write(iunit,'(a)', advance = 'yes')
1221
1222 call io_close(iunit)
1223 end if
1224
1226 end subroutine out_polarizability
1227
1228
1229 ! ---------------------------------------------------------
1231 subroutine out_dielectric_constant()
1232 integer :: idir, idir1, ik
1233 character(len=80) :: header_string
1234 complex(real64), allocatable :: epsilon_k(:, :, :)
1235
1236 if (.not. mpi_world%is_root()) return ! only first node outputs
1237
1239
1240 iunit = io_open(trim(dirname)//'/epsilon', namespace, action='write')
1241 if (.not. em_vars%ok(ifactor)) write(iunit, '(a)') "# WARNING: not converged"
1242
1243 epsilon(1:space%dim, 1:space%dim) = &
1244 4 * m_pi * em_vars%alpha(1:space%dim, 1:space%dim, ifactor) / ions%latt%rcell_volume
1245 do idir = 1, space%dim
1246 epsilon(idir, idir) = epsilon(idir, idir) + m_one
1247 end do
1248
1249 write(iunit, '(a)') '# Real part of dielectric constant'
1250 call output_tensor(real(epsilon(1:space%dim, 1:space%dim), real64), space%dim, unit_one, iunit=iunit)
1251 write(iunit, '(a)')
1252 write(iunit, '(a)') '# Imaginary part of dielectric constant'
1253 call output_tensor(aimag(epsilon(1:space%dim, 1:space%dim)), space%dim, unit_one, iunit=iunit)
1254
1255 if (em_vars%lrc_kernel) then
1256 write(iunit, '(a)')
1257 write(iunit, '(a)') '# Without G = G'' = 0 term of the LRC kernel'
1258
1259 epsilon(1:space%dim, 1:space%dim) = &
1260 4 * m_pi * em_vars%alpha0(1:space%dim, 1:space%dim, ifactor) / ions%latt%rcell_volume
1261 do idir = 1, space%dim
1262 epsilon(idir, idir) = epsilon(idir, idir) + m_one
1263 end do
1264
1265 write(iunit, '(a)') '# Real part of dielectric constant'
1266 call output_tensor(real(epsilon(1:space%dim, 1:space%dim), real64), space%dim, unit_one, iunit=iunit)
1267 write(iunit, '(a)')
1268 write(iunit, '(a)') '# Imaginary part of dielectric constant'
1269 call output_tensor(aimag(epsilon(1:space%dim, 1:space%dim)), space%dim, unit_one, iunit=iunit)
1270 end if
1271
1272 call io_close(iunit)
1273
1274 if (em_vars%kpt_output) then
1275 safe_allocate(epsilon_k(1:space%dim, 1:space%dim, 1:hm%kpoints%reduced%npoints))
1276 do ik = 1, hm%kpoints%reduced%npoints
1277 do idir = 1, space%dim
1278 do idir1 = 1, space%dim
1279 epsilon_k(idir, idir1, ik) = m_four * m_pi * em_vars%alpha_k(idir, idir1, ifactor, ik) / ions%latt%rcell_volume
1280 end do
1281 end do
1282 end do
1283 iunit = io_open(trim(dirname)//'/epsilon_k_re', namespace, action='write')
1284
1285 write(iunit, '(a)') '# Real part of dielectric constant'
1286 write(iunit, '(a10)', advance = 'no') '# index '
1287 write(iunit, '(a20)', advance = 'no') str_center("weight", 20)
1288 write(iunit, '(a20)', advance = 'no') str_center("kx", 20)
1289 write(iunit, '(a20)', advance = 'no') str_center("ky", 20)
1290 write(iunit, '(a20)', advance = 'no') str_center("kz", 20)
1291
1292 do idir = 1, space%dim
1293 do idir1 = 1, space%dim
1294 write(header_string,'(a7,i1,a1,i1,a1)') 'Re eps(', idir, ',', idir1, ')'
1295 write(iunit, '(a20)', advance = 'no') str_center(trim(header_string), 20)
1296 end do
1297 end do
1298 write(iunit, *)
1299
1300 do ik = 1, hm%kpoints%reduced%npoints
1301 write(iunit, '(i8)', advance = 'no') ik
1302 write(iunit, '(e20.8)', advance = 'no') hm%kpoints%reduced%weight(ik)
1303 do idir = 1, space%dim
1304 write(iunit, '(e20.8)', advance = 'no') hm%kpoints%reduced%red_point(idir, ik)
1305 end do
1306 do idir = 1, space%dim
1307 do idir1 = 1, space%dim
1308 write(iunit, '(e20.8)', advance = 'no') real(epsilon_k(idir, idir1, ik), real64)
1309 end do
1310 end do
1311 write(iunit, *)
1312 end do
1313 call io_close(iunit)
1314
1315 iunit = io_open(trim(dirname)//'/epsilon_k_im', namespace, action='write')
1316
1317 write(iunit, '(a)') '# Imaginary part of dielectric constant'
1318 write(iunit, '(a10)', advance = 'no') '# index '
1319 write(iunit, '(a20)', advance = 'no') str_center("weight", 20)
1320 write(iunit, '(a20)', advance = 'no') str_center("kx", 20)
1321 write(iunit, '(a20)', advance = 'no') str_center("ky", 20)
1322 write(iunit, '(a20)', advance = 'no') str_center("kz", 20)
1323
1324 do idir = 1, space%dim
1325 do idir1 = 1, space%dim
1326 write(header_string,'(a7,i1,a1,i1,a1)') 'Im eps(', idir, ',', idir1,')'
1327 write(iunit, '(a20)', advance = 'no') str_center(trim(header_string), 20)
1328 end do
1329 end do
1330 write(iunit, *)
1331
1332 do ik = 1, hm%kpoints%reduced%npoints
1333 write(iunit, '(i8)', advance = 'no') ik
1334 write(iunit, '(e20.8)', advance = 'no') hm%kpoints%reduced%weight(ik)
1335 do idir = 1, space%dim
1336 write(iunit, '(e20.8)', advance = 'no') hm%kpoints%reduced%red_point(idir, ik)
1337 end do
1338 do idir = 1, space%dim
1339 do idir1 = 1, space%dim
1340 write(iunit, '(e20.8)', advance = 'no') aimag(epsilon_k(idir, idir1, ik))
1341 end do
1342 end do
1343 write(iunit, *)
1344 end do
1345 call io_close(iunit)
1346 safe_deallocate_a(epsilon_k)
1347 end if
1348
1350 end subroutine out_dielectric_constant
1351
1352
1353 ! ---------------------------------------------------------
1354 subroutine out_susceptibility()
1355
1356 character(len=80) :: dirname1
1357
1358 if (.not. mpi_world%is_root()) return ! only first node outputs
1359
1361
1362 select type(ptr=>em_vars%perturbation)
1364 write(dirname1, '(a)') em_resp_dir//'freq_0.0000'
1365 call io_mkdir(trim(dirname1), namespace)
1366 iunit = io_open(trim(dirname1)//'/susceptibility', namespace, action='write')
1367 class default
1368 iunit = io_open(trim(dirname)//'/susceptibility', namespace, action='write')
1369 end select
1370
1371 if (.not. em_vars%ok(ifactor)) write(iunit, '(a)') "# WARNING: not converged"
1372
1373 ! There is no separation into the diamagnetic and paramagnetic terms in the expression
1374 ! for periodic systems
1375 if (.not. use_kdotp) then
1376 write(iunit, '(2a)') '# Paramagnetic contribution to the susceptibility tensor [ppm a.u.]'
1377 call output_tensor(real(em_vars%chi_para(:, :), real64), space%dim, unit_ppm, iunit=iunit)
1378 write(iunit, '(1x)')
1379
1380 write(iunit, '(2a)') '# Diamagnetic contribution to the susceptibility tensor [ppm a.u.]'
1381 call output_tensor(real(em_vars%chi_dia(:, :), real64), space%dim, unit_ppm, iunit=iunit)
1382 write(iunit, '(1x)')
1383 end if
1384
1385 write(iunit, '(2a)') '# Total susceptibility tensor [ppm a.u.]'
1386 call output_tensor(real(em_vars%chi_para(:, :) + em_vars%chi_dia(:,:), real64) , &
1387 space%dim, unit_ppm, iunit=iunit)
1388 write(iunit, '(1x)')
1389
1390 write(iunit, '(a)') hyphens
1391
1392 if (.not. use_kdotp) then
1393 write(iunit, '(2a)') '# Paramagnetic contribution to the susceptibility tensor [ppm cgs / mol]'
1394 call output_tensor(real(em_vars%chi_para(:, :), real64), space%dim, unit_susc_ppm_cgs, iunit=iunit)
1395 write(iunit, '(1x)')
1396
1397 write(iunit, '(2a)') '# Diamagnetic contribution to the susceptibility tensor [ppm cgs / mol]'
1398 call output_tensor(real(em_vars%chi_dia(:, :), real64), space%dim, unit_susc_ppm_cgs, iunit=iunit)
1399 write(iunit, '(1x)')
1400 end if
1401
1402 write(iunit, '(2a)') '# Total susceptibility tensor [ppm cgs / mol]'
1403 call output_tensor(real(em_vars%chi_para(:, :) + em_vars%chi_dia(:,:), real64), &
1404 space%dim, unit_susc_ppm_cgs, iunit=iunit)
1405 write(iunit, '(1x)')
1406
1407 if (use_kdotp) then
1408 write(iunit, '(a)') hyphens
1409 write(iunit, '(1a)') '# Magnetization [ppm a.u.]'
1410 write(iunit, '(3f20.8)') units_from_atomic(unit_ppm, real(em_vars%magn(1), real64)), &
1411 units_from_atomic(unit_ppm, real(em_vars%magn(2), real64)), &
1412 units_from_atomic(unit_ppm, real(em_vars%magn(3), real64))
1413 end if
1414
1415 call io_close(iunit)
1417 end subroutine out_susceptibility
1418
1419
1420 ! ---------------------------------------------------------
1421 subroutine out_wfn_and_densities()
1422 integer :: idir, isigma
1423
1425
1426 do idir = 1, space%dim
1427 if (states_are_complex(st)) then
1428
1429 if (space%dim == 3 .and. outp%what(option__output__elf)) then
1430 if (em_vars%nsigma == 1) then
1431 call zlr_calc_elf(st, space, gr, hm%kpoints, em_vars%lr(idir, 1, ifactor))
1432 else
1433 call zlr_calc_elf(st, space, gr, hm%kpoints, em_vars%lr(idir, 1, ifactor), em_vars%lr(idir, 2, ifactor))
1434 end if
1435 end if
1436 do isigma = 1, em_vars%nsigma
1437 call zoutput_lr(outp, namespace, space, dirname, st, gr, em_vars%lr(idir, isigma, ifactor), idir, isigma, ions, &
1438 units_out%force)
1439 end do
1440 else
1441
1442 if (space%dim == 3 .and. outp%what(option__output__elf)) then
1443 if (em_vars%nsigma == 1) then
1444 call dlr_calc_elf(st, space, gr, hm%kpoints, em_vars%lr(idir, 1, ifactor))
1445 else
1446 call dlr_calc_elf(st, space, gr, hm%kpoints, em_vars%lr(idir, 1, ifactor), em_vars%lr(idir, 2, ifactor))
1447 end if
1448 end if
1449
1450 do isigma = 1, em_vars%nsigma
1451 call doutput_lr(outp, namespace, space, dirname, st, gr, em_vars%lr(idir, isigma, ifactor), idir, isigma, ions, &
1452 units_out%force)
1453 end do
1454
1455 end if
1456 end do
1457
1459
1460 end subroutine out_wfn_and_densities
1461
1462
1463 ! ---------------------------------------------------------
1466 subroutine out_circular_dichroism()
1467
1468 type(perturbation_magnetic_t), pointer :: angular_momentum
1469 integer :: idir
1470 real(real64) :: ff
1471 complex(real64) :: dic
1472 complex(real64), allocatable :: psi(:, :, :, :)
1473
1475
1476 if (states_are_complex(st) .and. em_vars%nsigma == 2) then
1477
1478 message(1) = "Info: Calculating rotatory response."
1479 call messages_info(1, namespace=namespace)
1480
1481 angular_momentum => perturbation_magnetic_t(namespace, ions)
1482
1483 safe_allocate(psi(1:gr%np_part, 1:st%d%dim, st%st_start:st%st_end, st%d%kpt%start:st%d%kpt%end))
1484
1485 call states_elec_get_state(st, gr, psi)
1486
1487 dic = m_zero
1488 do idir = 1, space%dim
1489 call angular_momentum%setup_dir(idir)
1490 dic = dic &
1491 + angular_momentum%zexpectation_value(namespace, space, gr, hm, st, psi, &
1492 em_vars%lr(idir, 1, ifactor)%zdl_psi) &
1493 + angular_momentum%zexpectation_value(namespace, space, gr, hm, st, &
1494 em_vars%lr(idir, 2, ifactor)%zdl_psi, psi)
1495 end do
1496
1497 safe_deallocate_a(psi)
1498
1499 safe_deallocate_p(angular_momentum)
1500
1501 dic = dic*m_zi*m_half
1502
1503 if (mpi_world%is_root()) then ! only first node outputs
1504
1505 iunit = io_open(trim(dirname)//'/rotatory_strength', namespace, action='write')
1506
1507 ! print header
1508 write(iunit, '(a1,a20,a20,a20)') '#', str_center("Energy", 20), str_center("R", 20), str_center("Re[beta]", 20)
1509 write(iunit, '(a1,a20,a20,a20)') '#', str_center('['//trim(units_abbrev(units_out%energy)) // ']', 20), &
1510 str_center('['//trim(units_abbrev(units_out%length**3)) //']', 20), &
1511 str_center('['//trim(units_abbrev(units_out%length**4)) //']', 20)
1512
1513 ff = m_zero
1514 if (abs(em_vars%omega(iomega)) > m_epsilon) ff = real(dic, real64) /(m_three*em_vars%omega(iomega))
1515
1516 write(iunit, '(3e20.8)') units_from_atomic(units_out%energy, em_vars%omega(iomega)), &
1517 units_from_atomic(units_out%length**3, aimag(dic)/(p_c*m_pi)), units_from_atomic(units_out%length**4, ff)
1518
1519 call io_close(iunit)
1520 end if
1521 end if
1522
1524
1525 end subroutine out_circular_dichroism
1526
1527 ! ---------------------------------------------------------
1528 subroutine out_magnetooptics
1529 integer :: idir, ik
1530 complex(real64) :: epsilon_m(4), diff(4), eps_mk(space%dim)
1531
1532 if (.not. mpi_world%is_root()) return ! only first node outputs
1533
1535
1536 ! This code assumes 3D
1537 assert(space%dim == 3)
1538
1539 diff(:) = m_zero
1540 do idir = 1, space%dim
1541 diff(idir) = m_half * (em_vars%alpha_be(magn_dir(idir, 1), magn_dir(idir, 2), idir) - &
1542 em_vars%alpha_be(magn_dir(idir, 2), magn_dir(idir, 1), idir))
1543 end do
1544 diff(4) = (diff(1) + diff(2) + diff(3)) / m_three
1545
1546 iunit = io_open(trim(dirname)//'/alpha_mo', namespace, action='write')
1547
1548 if (.not. em_vars%ok(ifactor)) write(iunit, '(a)') "# WARNING: not converged"
1549
1550 write(iunit, '(a1, a25)', advance = 'no') '#', str_center(" ", 25)
1551 write(iunit, '(a20)', advance = 'no') str_center(" yz,x = -zy,x", 20)
1552 write(iunit, '(a20)', advance = 'no') str_center(" zx,y = -xz,y", 20)
1553 write(iunit, '(a20)', advance = 'no') str_center(" xy,z = -yx,z", 20)
1554 write(iunit, '(a20)', advance = 'no') str_center(" Average", 20)
1555 write(iunit, *)
1556
1557 write(iunit, '(a25)', advance = 'no') str_center("Re alpha [a.u.]", 25)
1558 do idir = 1, space%dim + 1
1559 write(iunit, '(e20.8)', advance = 'no') real(diff(idir), real64)
1560 end do
1561 write(iunit, *)
1562
1563 write(iunit, '(a25)', advance = 'no') str_center("Im alpha [a.u.]", 25)
1564 do idir = 1, space%dim + 1
1565 write(iunit, '(e20.8)', advance = 'no') aimag(diff(idir))
1566 end do
1567 write(iunit, *)
1568
1569 if (space%is_periodic()) then
1570 ! This code assumes 3D periodic
1571 assert(space%periodic_dim == 3)
1572
1573 do idir = 1, space%dim
1574 epsilon_m(idir) = 4 * m_pi * diff(idir) / ions%latt%rcell_volume
1575 end do
1576 epsilon_m(4) = 4 * m_pi * diff(4) / ions%latt%rcell_volume
1577
1578 write(iunit, '(a25)', advance = 'no') str_center("Re epsilon (B = 1 a.u.)", 25)
1579 do idir = 1, space%dim + 1
1580 write(iunit, '(e20.8)', advance = 'no') real(epsilon_m(idir), real64)
1581 end do
1582 write(iunit, *)
1583
1584 write(iunit, '(a25)', advance = 'no') str_center("Im epsilon (B = 1 a.u.)", 25)
1585 do idir = 1, space%dim + 1
1586 write(iunit, '(e20.8)', advance = 'no') aimag(epsilon_m(idir))
1587 end do
1588 write(iunit, *)
1589
1590 if (em_vars%lrc_kernel) then
1591 write(iunit, '(a)')
1592 write(iunit, '(a)') '# Without the G = G'' = 0 term of the LRC kernel'
1593
1594 diff(:) = m_zero
1595 epsilon_m(:) = m_zero
1596 do idir = 1, space%dim
1597 diff(idir) = m_half * (em_vars%alpha_be0(magn_dir(idir, 1), magn_dir(idir, 2), idir) - &
1598 em_vars%alpha_be0(magn_dir(idir, 2), magn_dir(idir, 1), idir))
1599
1600 epsilon_m(idir) = 4 * m_pi * diff(idir) / ions%latt%rcell_volume
1601 end do
1602 diff(4) = (diff(1) + diff(2) + diff(3)) / m_three
1603 epsilon_m(4) = 4 * m_pi * diff(4) / ions%latt%rcell_volume
1604
1605 write(iunit, '(a1, a25)', advance = 'no') '#', str_center(" ", 25)
1606 write(iunit, '(a20)', advance = 'no') str_center(" yz,x = -zy,x", 20)
1607 write(iunit, '(a20)', advance = 'no') str_center(" zx,y = -xz,y", 20)
1608 write(iunit, '(a20)', advance = 'no') str_center(" xy,z = -yx,z", 20)
1609 write(iunit, '(a20)', advance = 'no') str_center(" Average", 20)
1610 write(iunit, *)
1611
1612 write(iunit, '(a25)', advance = 'no') str_center("Re alpha [a.u.]", 25)
1613 do idir = 1, space%dim + 1
1614 write(iunit, '(e20.8)', advance = 'no') real(diff(idir), real64)
1615 end do
1616 write(iunit, *)
1617
1618 write(iunit, '(a25)', advance = 'no') str_center("Im alpha [a.u.]", 25)
1619 do idir = 1, space%dim + 1
1620 write(iunit, '(e20.8)', advance = 'no') aimag(diff(idir))
1621 end do
1622 write(iunit, *)
1623
1624 write(iunit, '(a25)', advance = 'no') str_center("Re epsilon (B = 1 a.u.)", 25)
1625 do idir = 1, space%dim + 1
1626 write(iunit, '(e20.8)', advance = 'no') real(epsilon_m(idir), real64)
1627 end do
1628 write(iunit, *)
1629
1630 write(iunit, '(a25)', advance = 'no') str_center("Im epsilon (B = 1 a.u.)", 25)
1631 do idir = 1, space%dim + 1
1632 write(iunit, '(e20.8)', advance = 'no') aimag(epsilon_m(idir))
1633 end do
1634 write(iunit, *)
1635 end if
1636 end if
1637 call io_close(iunit)
1638
1639 if (space%is_periodic() .and. em_vars%kpt_output) then
1640 iunit = io_open(trim(dirname)//'/epsilon_mo_k', namespace, action='write')
1641
1642 write(iunit, '(a)') '# Contribution to dielectric tensor for B = 1 a.u.'
1643 write(iunit, '(a10)', advance = 'no') '# index '
1644 write(iunit, '(a20)', advance = 'no') str_center("weight", 20)
1645 write(iunit, '(a20)', advance = 'no') str_center("kx", 20)
1646 write(iunit, '(a20)', advance = 'no') str_center("ky", 20)
1647 write(iunit, '(a20)', advance = 'no') str_center("kz", 20)
1648 write(iunit, '(a20)', advance = 'no') str_center("Re eps_yz,x", 20)
1649 write(iunit, '(a20)', advance = 'no') str_center("Re eps_zx,y", 20)
1650 write(iunit, '(a20)', advance = 'no') str_center("Re eps_xy,z", 20)
1651 write(iunit, '(a20)', advance = 'no') str_center("Im eps_yz,x", 20)
1652 write(iunit, '(a20)', advance = 'no') str_center("Im eps_zx,y", 20)
1653 write(iunit, '(a20)', advance = 'no') str_center("Im eps_xy,z", 20)
1654 write(iunit, *)
1655
1656 do ik = 1, hm%kpoints%reduced%npoints
1657 write(iunit, '(i8)', advance = 'no') ik
1658 write(iunit, '(e20.8)', advance = 'no') hm%kpoints%reduced%weight(ik)
1659 do idir = 1, space%dim
1660 eps_mk(idir) = m_two * m_pi * (em_vars%alpha_be_k(magn_dir(idir, 1), magn_dir(idir, 2), idir, ik) - &
1661 em_vars%alpha_be_k(magn_dir(idir, 2), magn_dir(idir, 1), idir, ik)) / ions%latt%rcell_volume
1662 end do
1663
1664 do idir = 1, space%dim
1665 write(iunit, '(e20.8)', advance = 'no') hm%kpoints%reduced%red_point(idir, ik)
1666 end do
1667 do idir = 1, space%dim
1668 write(iunit, '(e20.8)', advance = 'no') real(eps_mk(idir), real64)
1669 end do
1670 do idir = 1, space%dim
1671 write(iunit, '(e20.8)', advance = 'no') aimag(eps_mk(idir))
1672 end do
1673 write(iunit, *)
1674 end do
1675 call io_close(iunit)
1676 end if
1677
1679 end subroutine out_magnetooptics
1680
1681 end subroutine em_resp_output
1682
1683 ! ---------------------------------------------------------
1687 subroutine out_hyperpolarizability(box, beta, freq_factor, converged, dirname, namespace)
1688 class(box_t), intent(in) :: box
1689 complex(real64), intent(in) :: beta(:, :, :)
1690 real(real64), intent(in) :: freq_factor(:)
1691 logical, intent(in) :: converged
1692 character(len=*), intent(in) :: dirname
1693 type(namespace_t), intent(in) :: namespace
1694
1695 complex(real64) :: bpar(1:box%dim), bper(1:box%dim), bk(1:box%dim)
1696 complex(real64) :: HRS_VV, HRS_HV
1697 integer :: ii, jj, kk, iunit
1698
1699 if (.not. mpi_world%is_root()) return ! only first node outputs
1700
1701 push_sub(out_hyperpolarizability)
1702
1703 ! Output first hyperpolarizability (beta)
1704 iunit = io_open(trim(dirname)//'/beta', namespace, action='write')
1705
1706 if (.not. converged) write(iunit, '(a)') "# WARNING: not converged"
1707
1708 write(iunit, '(a,3(f4.1,a),2a)', advance='no') 'First hyperpolarizability tensor: beta(', &
1709 freq_factor(1), ', ', freq_factor(2), ', ', freq_factor(3), ') [', &
1710 trim(units_abbrev(units_out%hyperpolarizability)), ']'
1711
1712 write(iunit, '()')
1713
1714 do ii = 1, box%dim
1715 do jj = 1, box%dim
1716 do kk = 1, box%dim
1717 write(iunit,'(a,e20.8,e20.8)') 'beta '// &
1718 index2axis(ii)//index2axis(jj)//index2axis(kk)//' ', &
1719 units_from_atomic(units_out%hyperpolarizability, real( beta(ii, jj, kk), real64)) , &
1720 units_from_atomic(units_out%hyperpolarizability, aimag(beta(ii, jj, kk)))
1721 end do
1722 end do
1723 end do
1724
1725 if (box%dim == 3) then
1726 bpar = m_zero
1727 bper = m_zero
1728
1729 do ii = 1, box%dim
1730 do jj = 1, box%dim
1731 bpar(ii) = bpar(ii) + beta(ii, jj, jj) + beta(jj, ii, jj) + beta(jj, jj, ii)
1732 bper(ii) = bper(ii) + m_two*beta(ii, jj, jj) - m_three*beta(jj, ii, jj) + m_two*beta(jj, jj, ii)
1733 end do
1734 end do
1735
1736 write(iunit, '()')
1737
1738 bpar = bpar / m_five
1739 bper = bper / m_five
1740 bk(1:box%dim) = m_three*m_half*(bpar(1:box%dim) - bper(1:box%dim))
1741
1742 do ii = 1, box%dim
1743 write(iunit, '(a, 2e20.8)') 'beta // '//index2axis(ii), &
1744 units_from_atomic(units_out%hyperpolarizability, real(bpar(ii), real64)), &
1745 units_from_atomic(units_out%hyperpolarizability, aimag(bpar(ii)))
1746 end do
1747
1748 write(iunit, '()')
1749
1750 do ii = 1, box%dim
1751 write(iunit, '(a, 2e20.8)') 'beta _L '//index2axis(ii), &
1752 units_from_atomic(units_out%hyperpolarizability, real(bper(ii), real64)), &
1753 units_from_atomic(units_out%hyperpolarizability, aimag(bper(ii)))
1754 end do
1755
1756 write(iunit, '()')
1757
1758 do ii = 1, box%dim
1759 write(iunit, '(a, 2e20.8)') 'beta k '//index2axis(ii), &
1760 units_from_atomic(units_out%hyperpolarizability, real(bk(ii), real64)), &
1761 units_from_atomic(units_out%hyperpolarizability, aimag(bk(ii)))
1762 end do
1763
1764 call calc_beta_hrs(box, beta, hrs_vv, hrs_hv)
1765
1766 write(iunit, '()')
1767 write(iunit, '(a)') 'beta for liquid- or gas-phase hyper-Rayleigh scattering:'
1768 write(iunit, '(a, 2e20.8)') 'VV polarization ', &
1769 units_from_atomic(units_out%hyperpolarizability, real(sqrt(hrs_vv), real64)), &
1770 units_from_atomic(units_out%hyperpolarizability, aimag(sqrt(hrs_vv)))
1771 write(iunit, '(a, 2e20.8)') 'HV polarization ', &
1772 units_from_atomic(units_out%hyperpolarizability, real(sqrt(hrs_hv), real64)), &
1773 units_from_atomic(units_out%hyperpolarizability, aimag(sqrt(hrs_hv)))
1774 end if
1775
1776 call io_close(iunit)
1778
1779 contains
1780
1781 ! ---------------------------------------------------------
1786 subroutine calc_beta_hrs(box, beta, HRS_VV, HRS_HV)
1787 class(box_t), intent(in) :: box
1788 complex(real64), intent(in) :: beta(:, :, :)
1789 complex(real64), intent(out) :: HRS_VV, HRS_HV
1790
1791 complex(real64) :: HRS_A, HRS_B, HRS_C, HRS_D, HRS_E
1792 complex(real64) :: HRS_B1, HRS_B2, HRS_C1, HRS_C2, HRS_C3, HRS_D1, HRS_D2, HRS_D3, HRS_E1, HRS_E2
1793 integer :: ii, jj
1794
1796
1797 ! first calculate VV (vertical-vertical) polarization, FFF in Decius et al.
1798 hrs_a = m_zero
1799 do ii = 1, box%dim
1800 hrs_a = hrs_a + beta(ii,ii,ii)**2
1801 end do
1802
1803 hrs_b = m_zero
1804 hrs_c = m_zero
1805 do ii = 1, box%dim
1806 do jj = 1, box%dim
1807 if (ii /= jj) then
1808 hrs_b = hrs_b + beta(ii,ii,ii) * (beta(ii,jj,jj) + beta(jj,ii,jj) + beta(jj,jj,ii))
1809 hrs_c = hrs_c + (beta(ii,ii,jj) + beta(ii,jj,ii) + beta(jj,ii,ii))**2
1810 end if
1811 end do
1812 end do
1813
1814 hrs_d = (beta(1,1,2) + beta(1,2,1) + beta(2,1,1)) * (beta(2,3,3) + beta(3,2,3) + beta(3,3,2)) &
1815 + (beta(2,2,3) + beta(2,3,2) + beta(3,2,2)) * (beta(3,1,1) + beta(1,3,1) + beta(1,1,3)) &
1816 + (beta(3,3,1) + beta(3,1,3) + beta(1,3,3)) * (beta(1,2,2) + beta(2,1,2) + beta(2,2,1))
1817
1818 hrs_e = (beta(1,2,3) + beta(1,3,2) + beta(2,1,3) + beta(2,3,1) + beta(3,1,2) + beta(3,2,1))**2
1819
1820 hrs_vv = (m_one / 7.0_real64) * hrs_a &
1821 + (m_two / 35.0_real64) * hrs_b &
1822 + (m_one / 35.0_real64) * hrs_c &
1823 + (m_two / 105.0_real64) * hrs_d &
1824 + (m_one / 105.0_real64) * hrs_e
1825
1826 ! now calculate HV (horizontal-vertical) polarization, FGG in Decius et al.
1827 hrs_b1 = m_zero
1828 hrs_b2 = m_zero
1829 hrs_c1 = m_zero
1830 hrs_c2 = m_zero
1831 hrs_c3 = m_zero
1832 do ii = 1, box%dim
1833 do jj = 1, box%dim
1834 if (ii /= jj) then
1835 hrs_b1 = hrs_b1 + beta(ii,ii,ii) * beta(ii,jj,jj)
1836 hrs_b2 = hrs_b2 + beta(ii,ii,ii) * (beta(jj,ii,jj) + beta(jj,jj,ii))
1837 hrs_c1 = hrs_c1 + (beta(ii,ii,jj) + beta(ii,jj,ii))**2
1838 hrs_c2 = hrs_c2 + beta(jj,ii,ii) * (beta(ii,ii,jj) + beta(ii,jj,ii))
1839 hrs_c3 = hrs_c3 + beta(jj,ii,ii)**2
1840 end if
1841 end do
1842 end do
1843
1844 hrs_d1 = (beta(1,1,2) + beta(1,2,1) + beta(2,1,1)) * (beta(3,2,3) + beta(3,3,2)) &
1845 + (beta(2,2,3) + beta(2,3,2) + beta(3,2,2)) * (beta(1,3,1) + beta(1,1,3)) &
1846 + (beta(3,3,1) + beta(3,1,3) + beta(1,3,3)) * (beta(2,1,2) + beta(2,2,1))
1847 hrs_d2 = (beta(1,1,2) + beta(1,2,1)) * beta(2,3,3) &
1848 + (beta(2,2,3) + beta(2,3,2)) * beta(3,1,1) &
1849 + (beta(3,3,1) + beta(3,1,3)) * beta(1,2,2)
1850 hrs_d3 = beta(2,1,1) * beta(2,3,3) &
1851 + beta(3,2,2) * beta(3,1,1) &
1852 + beta(1,3,3) * beta(1,2,2)
1853
1854 hrs_e1 = (beta(1,2,3) + beta(1,3,2))**2 &
1855 + (beta(2,1,3) + beta(2,3,1))**2 &
1856 + (beta(3,1,2) + beta(3,2,1))**2
1857
1858 hrs_e2 = (beta(1,2,3) + beta(1,3,2)) * (beta(2,1,3) + beta(2,3,1)) &
1859 + (beta(2,1,3) + beta(2,3,1)) * (beta(3,1,2) + beta(3,2,1)) &
1860 + (beta(3,1,2) + beta(3,2,1)) * (beta(1,2,3) + beta(1,3,2))
1861
1862 hrs_hv = (m_one / 35.0_real64) * hrs_a &
1863 + (m_four / 105.0_real64) * hrs_b1 &
1864 - (m_one / 35.0_real64) * hrs_b2 &
1865 + (m_two / 105.0_real64) * hrs_c1 &
1866 - (m_one / 35.0_real64) * hrs_c2 &
1867 + (m_three / 35.0_real64) * hrs_c3 &
1868 - (m_one / 105.0_real64) * hrs_d1 &
1869 - (m_one / 105.0_real64) * hrs_d2 &
1870 + (m_two / 35.0_real64) * hrs_d3 &
1871 + (m_one / 35.0_real64) * hrs_e1 &
1872 - (m_one / 105.0_real64) * hrs_e2
1873
1875 end subroutine calc_beta_hrs
1876
1877 end subroutine out_hyperpolarizability
1878
1879end module em_resp_oct_m
1880
1881!! Local Variables:
1882!! mode: f90
1883!! coding: utf-8
1884!! End:
subroutine out_dielectric_constant()
epsilon = 1 + 4 * pi * alpha/volume
Definition: em_resp.F90:2812
subroutine write_eta()
Definition: em_resp.F90:2697
subroutine calc_beta_hrs(box, beta, HRS_VV, HRS_HV)
calculate hyper-Rayleigh scattering hyperpolarizabilities SJ Cyvin, JE Rauch, and JC Decius,...
Definition: em_resp.F90:3367
subroutine out_circular_dichroism()
See D Varsano, LA Espinosa Leal, Xavier Andrade, MAL Marques, Rosa di Felice, Angel Rubio,...
Definition: em_resp.F90:3047
subroutine out_magnetooptics
Definition: em_resp.F90:3109
subroutine out_susceptibility()
Definition: em_resp.F90:2935
subroutine info()
Definition: em_resp.F90:1093
subroutine dcalc_properties_linear(em_vars, namespace, space, gr, kpoints, st, hm, xc, ions, outp)
Definition: em_resp.F90:1694
subroutine out_wfn_and_densities()
Definition: em_resp.F90:3002
subroutine drun_sternheimer(em_vars, namespace, space, gr, kpoints, st, hm, mc, ions)
Definition: em_resp.F90:1193
subroutine out_polarizability()
Definition: em_resp.F90:2749
subroutine dcalc_properties_nonlinear(em_vars, namespace, space, gr, st, hm, xc)
Definition: em_resp.F90:1823
subroutine zrun_sternheimer(em_vars, namespace, space, gr, kpoints, st, hm, mc, ions)
Definition: em_resp.F90:1928
subroutine parse_input()
Definition: em_resp.F90:816
subroutine cross_section_header(out_file)
Note: this should be in spectrum.F90.
Definition: em_resp.F90:2715
subroutine zcalc_properties_nonlinear(em_vars, namespace, space, gr, st, hm, xc)
Definition: em_resp.F90:2558
subroutine zcalc_properties_linear(em_vars, namespace, space, gr, kpoints, st, hm, xc, ions, outp)
Definition: em_resp.F90:2429
This is the common interface to a sorting routine. It performs the shell algorithm,...
Definition: sort.F90:151
subroutine, public born_charges_end(this)
subroutine, public born_output_charges(this, atom, charge, natoms, namespace, dim, dirname, write_real)
subroutine, public born_charges_init(this, namespace, natoms, val_charge, qtot, dim)
integer pure function, public magn_dir(dir, ind)
subroutine, public dlr_calc_elf(st, space, gr, kpoints, lr, lr_m)
subroutine, public zlr_calc_elf(st, space, gr, kpoints, lr, lr_m)
character(len=12) function, public freq2str(freq)
integer, parameter perturbation_magnetic
Definition: em_resp.F90:175
subroutine em_resp_run_legacy(sys, fromScratch)
Definition: em_resp.F90:252
subroutine, public out_hyperpolarizability(box, beta, freq_factor, converged, dirname, namespace)
Ref: David M Bishop, Rev Mod Phys 62, 343 (1990) beta generalized to lack of Kleinman symmetry.
Definition: em_resp.F90:3268
subroutine, public em_resp_run(system, from_scratch)
Definition: em_resp.F90:234
subroutine em_resp_output(st, namespace, space, gr, hm, ions, outp, sh, em_vars, iomega, ifactor)
Definition: em_resp.F90:2624
integer, parameter perturbation_none
Definition: em_resp.F90:175
real(real64), parameter, public m_two
Definition: global.F90:193
real(real64), parameter, public m_huge
Definition: global.F90:209
real(real64), parameter, public m_zero
Definition: global.F90:191
real(real64), parameter, public m_four
Definition: global.F90:195
real(real64), parameter, public m_third
Definition: global.F90:198
real(real64), parameter, public m_pi
some mathematical constants
Definition: global.F90:189
complex(real64), parameter, public m_z0
Definition: global.F90:201
complex(real64), parameter, public m_zi
Definition: global.F90:205
real(real64), parameter, public m_epsilon
Definition: global.F90:207
character(len= *), parameter, public em_resp_dir
Definition: global.F90:267
real(real64), parameter, public m_half
Definition: global.F90:197
real(real64), parameter, public p_c
Electron gyromagnetic ratio, see Phys. Rev. Lett. 130, 071801 (2023)
Definition: global.F90:229
real(real64), parameter, public m_one
Definition: global.F90:192
real(real64), parameter, public m_three
Definition: global.F90:194
real(real64), parameter, public m_five
Definition: global.F90:196
This module implements the underlying real-space grid.
Definition: grid.F90:119
Definition: io.F90:116
subroutine, public io_close(iunit, grp)
Definition: io.F90:466
subroutine, public io_mkdir(fname, namespace, parents)
Definition: io.F90:360
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:401
character(len=100) function, public kdotp_wfs_tag(dir, dir2)
Definition: kdotp_calc.F90:154
subroutine, public zlr_orth_response(mesh, st, lr, omega)
subroutine, public lr_copy(st, mesh, src, dest)
subroutine, public lr_allocate(lr, st, mesh, allocate_rho)
subroutine, public lr_init(lr)
subroutine, public lr_dealloc(lr)
subroutine, public dlr_orth_response(mesh, st, lr, omega)
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
subroutine, public messages_print_with_emphasis(msg, iunit, namespace)
Definition: messages.F90:898
subroutine, public messages_not_implemented(feature, namespace)
Definition: messages.F90:1091
character(len=512), private msg
Definition: messages.F90:167
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:525
subroutine, public messages_obsolete_variable(namespace, name, rep)
Definition: messages.F90:1023
character(len=68), parameter, public hyphens
Definition: messages.F90:163
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_experimental(name, namespace)
Definition: messages.F90:1063
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:272
This module handles the communicators for the various parallelization strategies.
Definition: multicomm.F90:147
This module implements the basic mulsisystem class, a container system for other systems.
this module contains the low-level part of the output system
Definition: output_low.F90:117
this module contains the output system
Definition: output.F90:117
subroutine, public zoutput_lr(outp, namespace, space, dir, st, mesh, lr, idir, isigma, ions, pert_unit)
Definition: output.F90:1825
subroutine, public doutput_lr(outp, namespace, space, dir, st, mesh, lr, idir, isigma, ions, pert_unit)
Definition: output.F90:2094
integer function, public parse_block(namespace, name, blk, check_varinfo_)
Definition: parser.F90:615
integer, parameter, public restart_kdotp
Definition: restart.F90:156
integer, parameter, public restart_gs
Definition: restart.F90:156
integer, parameter, public restart_type_load
Definition: restart.F90:183
integer, parameter, public smear_fixed_occ
Definition: smear.F90:173
logical pure function, public smear_is_semiconducting(this)
Definition: smear.F90:838
This module is intended to contain "only mathematical" functions and procedures.
Definition: sort.F90:119
pure logical function, public states_are_complex(st)
pure logical function, public states_are_real(st)
This module handles spin dimensions of the states and the k-point distribution.
subroutine, public states_elec_deallocate_wfns(st)
Deallocates the KS wavefunctions defined within a states_elec_t structure.
This module handles reading and writing restart information for the states_elec_t.
subroutine, public states_elec_look_and_load(restart, namespace, space, st, mesh, kpoints, is_complex, packed)
subroutine, public states_elec_load(restart, namespace, space, st, mesh, kpoints, ierr, iter, lr, lowest_missing, label, verbose, skip)
returns in ierr: <0 => Fatal error, or nothing read =0 => read all wavefunctions >0 => could only rea...
character(len=100) function, public wfs_tag_sigma(namespace, base_name, isigma)
subroutine, public sternheimer_unset_kxc(this)
subroutine, public sternheimer_end(this)
subroutine, public sternheimer_build_kxc(this, namespace, mesh, st, xc)
subroutine, public sternheimer_init(this, namespace, space, gr, st, hm, ks, mc, wfs_are_cplx, set_ham_var, set_occ_response, set_last_occ_response, occ_response_by_sternheimer)
character(len=80) function, public str_center(s_in, l_in)
puts space around string, so that it is centered
Definition: string.F90:199
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_t), public unit_ppm
Parts per million.
type(unit_system_t), public units_out
type(unit_t), public unit_susc_ppm_cgs
Some magnetic stuff.
type(unit_system_t), public units_inp
the units systems for reading and writing
type(unit_t), public unit_one
some special units required for particular quantities
This module is intended to contain simple general-purpose utility functions and procedures.
Definition: utils.F90:120
subroutine, public output_tensor(tensor, ndim, unit, write_average, iunit, namespace)
Definition: utils.F90:245
character pure function, public index2axis(idir)
Definition: utils.F90:205
subroutine, public v_ks_h_setup(namespace, space, gr, ions, ext_partners, st, ks, hm, calc_eigenval, calc_current)
Definition: v_ks.F90:695
Definition: xc.F90:116
class to tell whether a point is inside or outside
Definition: box.F90:143
Class describing the electron system.
Definition: electrons.F90:220
Description of the grid, containing information on derivatives, stencil, and symmetries.
Definition: grid.F90:171
Container class for lists of system_oct_m::system_t.
output handler class
Definition: output_low.F90:166
The states_elec_t class contains all electronic wave functions.
int true(void)