Octopus
phonons_lr.F90
Go to the documentation of this file.
1!! Copyright (C) 2007-2012 Xavier Andrade, 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
23 use debug_oct_m
24 use epot_oct_m
25 use forces_oct_m
26 use global_oct_m
27 use grid_oct_m
29 use io_oct_m
31 use ions_oct_m
32 use, intrinsic :: iso_fortran_env
33 use kdotp_oct_m
38 use math_oct_m
39 use mesh_oct_m
42 use mpi_oct_m
45 use parser_oct_m
49 use smear_oct_m
50 use space_oct_m
58 use unit_oct_m
60 use utils_oct_m
62 use v_ks_oct_m
63
64 implicit none
65
66 private
67 public :: &
73
74contains
75
76 ! ---------------------------------------------------------
77 subroutine phonons_lr_run(system, from_scratch)
78 class(*), intent(inout) :: system
79 logical, intent(in) :: from_scratch
80
81 push_sub(phonons_lr_run)
82
83 select type (system)
84 class is (multisystem_basic_t)
85 message(1) = "CalculationMode = vib_modes not implemented for multi-system calculations"
86 call messages_fatal(1, namespace=system%namespace)
87 type is (electrons_t)
88 call phonons_lr_run_legacy(system, from_scratch)
89 end select
90
91 pop_sub(phonons_lr_run)
92 end subroutine phonons_lr_run
93
94 ! ---------------------------------------------------------
95 subroutine phonons_lr_run_legacy(sys, fromscratch)
96 type(electrons_t), target, intent(inout) :: sys
97 logical, intent(in) :: fromscratch
98
99 type(sternheimer_t) :: sh
100 type(lr_t) :: lr(1:1), kdotp_lr(sys%space%dim)
101 type(vibrations_t) :: vib
102 class(perturbation_ionic_t), pointer :: pert
103
104 type(ions_t), pointer :: ions
105 type(states_elec_t), pointer :: st
106 type(grid_t), pointer :: gr
107
108 integer :: natoms, ndim, iatom, idir, jatom, jdir, imat, jmat, iunit_restart, ierr, start_mode, ispin
109 complex(real64), allocatable :: force_deriv(:,:)
110 real(real64), allocatable :: grad_rho_core(:,:), drho_core(:,:), dvxc_bare(:,:,:)
111 real(real64), allocatable :: ddrho_tot(:,:), ddvxc_resp(:,:,:)
112 complex(real64), allocatable :: zdrho_tot(:,:), zdvxc_resp(:,:,:)
113 character(len=80) :: str_tmp
114 character(len=300) :: line(1)
115 type(born_charges_t) :: born
116 logical :: normal_mode_wfs, do_infrared, symmetrize
117 type(restart_t) :: restart_load, restart_dump, kdotp_restart, gs_restart
118
119 push_sub(phonons_lr_run_legacy)
120
121 !some shortcuts
122
123 ions => sys%ions
124 st => sys%st
125 gr => sys%gr
126
127 if (sys%hm%pcm%run_pcm) then
128 call messages_not_implemented("PCM for CalculationMode /= gs or td", namespace=sys%namespace)
129 end if
130
131 if (sys%space%is_periodic()) then
132 call messages_not_implemented('linear-response vib_modes for periodic systems', namespace=sys%namespace)
133 end if
134
135 !%Variable CalcNormalModeWfs
136 !%Type logical
137 !%Default false
138 !%Section Linear Response::Vibrational Modes
139 !%Description
140 !% If set to true, the response wavefunctions for each normal mode will be calculated
141 !% and written in directory <tt>restart/vib_modes/phn_nm_wfs_XXXXX</tt>.
142 !% This part is time-consuming and not parallel, but not needed for most purposes.
143 !%End
144 call parse_variable(sys%namespace, 'CalcNormalModeWfs', .false., normal_mode_wfs)
145
146 !%Variable CalcInfrared
147 !%Type logical
148 !%Default true
149 !%Section Linear Response::Vibrational Modes
150 !%Description
151 !% If set to true, infrared intensities (and born charges) will be calculated
152 !% and written in <tt>vib_modes/infrared</tt>.
153 !%End
154 call parse_variable(sys%namespace, 'CalcInfrared', .true., do_infrared)
155
156 !%Variable SymmetrizeDynamicalMatrix
157 !%Type logical
158 !%Default true
159 !%Section Linear Response::Vibrational Modes
160 !%Description
161 !% If set to true, all entries of the dynamical matrix will be calculated and then
162 !% the matrix will be symmetrized to enforce <math>D_{ij} = D_{ji}</math>. If set to false,
163 !% only the upper half of the matrix will be calculated.
164 !%End
165 call parse_variable(sys%namespace, 'SymmetrizeDynamicalMatrix', .true., symmetrize)
166
167 ! replaced by properly saving and reading the dynamical matrix
168 call messages_obsolete_variable(sys%namespace, 'UseRestartDontSolve')
169
170 natoms = ions%natoms
171 ndim = sys%space%dim
173 call gs_restart%init(sys%namespace, restart_gs, restart_type_load, sys%mc, ierr, mesh=gr, exact=.true.)
174 if (ierr == 0) then
175 call states_elec_look_and_load(gs_restart, sys%namespace, sys%space, st, sys%gr, sys%kpoints, st%restart_fixed_occ)
176 call gs_restart%end()
177 else
178 message(1) = "Previous gs calculation is required."
179 call messages_fatal(1, namespace=sys%namespace)
180 end if
181
182 ! read kdotp wavefunctions if necessary (for IR intensities)
183 if (sys%space%is_periodic() .and. do_infrared) then
184 message(1) = "Reading kdotp wavefunctions for periodic directions."
185 call messages_info(1, namespace=sys%namespace)
186
187 call kdotp_restart%init(sys%namespace, restart_kdotp, restart_type_load, sys%mc, ierr, mesh=gr)
188 if (ierr /= 0) then
189 message(1) = "Unable to read kdotp wavefunctions."
190 message(2) = "Previous kdotp calculation required."
191 call messages_fatal(2, namespace=sys%namespace)
192 end if
193
194 do idir = 1, sys%space%periodic_dim
195 call lr_init(kdotp_lr(idir))
196 call lr_allocate(kdotp_lr(idir), sys%st, sys%gr)
197
198 ! load wavefunctions
199 str_tmp = trim(kdotp_wfs_tag(idir))
200 call kdotp_restart%open_dir(wfs_tag_sigma(sys%namespace, str_tmp, 1), ierr)
201 if (ierr == 0) then
202 call states_elec_load(kdotp_restart, sys%namespace, sys%space, sys%st, sys%gr, sys%kpoints, &
203 sys%st%restart_fixed_occ, ierr=ierr, lr=kdotp_lr(idir))
204 end if
205 call kdotp_restart%close_dir()
206
207 if (ierr /= 0) then
208 message(1) = "Unable to read kdotp wavefunctions from '"//trim(wfs_tag_sigma(sys%namespace, str_tmp, 1))//"'."
209 message(2) = "Previous kdotp calculation required."
210 call messages_fatal(2, namespace=sys%namespace)
211 end if
212 end do
213 call kdotp_restart%end()
214 end if
215
216 message(1) = 'Info: Setting up Hamiltonian for linear response.'
217 call messages_info(1, namespace=sys%namespace)
218
219 call v_ks_h_setup(sys%namespace, sys%space, sys%gr, sys%ions, sys%ext_partners, sys%st, sys%ks, sys%hm)
220 call sternheimer_init(sh, sys%namespace, sys%space, sys%gr, sys%st, sys%hm, sys%ks, sys%mc, &
221 wfs_are_cplx = states_are_complex(st))
222
223 if (sys%hm%ep%nlcc .and. .not. sh%add_fxc()) then
224 message(1) = "Linear-response vib_modes with non-linear core corrections requires the xc kernel."
225 message(2) = "HamiltonianVariation must include V_xc."
226 call messages_fatal(2, namespace=sys%namespace)
227 end if
228
229 call vibrations_init(vib, ions%space, ions%natoms, ions%mass, "lr", sys%namespace)
230
231 call epot_precalc_local_potential(sys%hm%ep, sys%namespace, sys%gr, sys%ions)
232
233 if (do_infrared) then
234 call born_charges_init(born, sys%namespace, ions%natoms, st%val_charge, st%qtot, ndim)
235 end if
236
237 call lr_init(lr(1))
238 call lr_allocate(lr(1), st, gr)
239
240 call restart_dump%init(sys%namespace, restart_vib_modes, restart_type_dump, sys%mc, ierr, mesh=gr)
241 call restart_load%init(sys%namespace, restart_vib_modes, restart_type_load, sys%mc, ierr, mesh=gr)
242
243 !CALCULATE
244
245 ! the ionic contribution, see second term in Eq. 85 in Baroni et al. RMP, 73, 515 (2001)
247
248 ! Compute the -<phi0 | v2 | phi0> term
249 if (states_are_real(st)) then
250 call dionic_pert_matrix_elements_2(sys%gr, sys%namespace, sys%space, sys%ions, sys%hm, 1, st, vib, vib%dyn_matrix)
251 else
252 call zionic_pert_matrix_elements_2(sys%gr, sys%namespace, sys%space, sys%ions, sys%hm, 1, st, vib, vib%dyn_matrix)
253 end if
254
255 if (fromscratch) then
256 start_mode = 1
257 else
258 call phonons_load(restart_load, vib, start_mode)
259 end if
260
261 ! Delete, if fromScratch, or trying to open it failed and there is something wrong with it.
262 if (start_mode == 1) call restart_dump%rm('restart')
263
264 ! Output the first start_mode-1 modes
265 do imat = 1, start_mode - 1
266 call vibrations_out_dyn_matrix_row(vib, imat)
267 end do
268
269
270 ! The remaining term is <\psi_1 | v^{(1)} | \psi_0> + <\psi_0 | v^{(1)} | \psi_1>
271 ! We first get \psi_1 from Sternheimer, and then compute the term using X(forces_derivative)
272 ! Note that in order to avoid getting v^{(1)}, we perform an integration by part in this routine
273 pert => perturbation_ionic_t(sys%namespace, ions)
274
275 if (sys%hm%ep%nlcc) then
276 safe_allocate(grad_rho_core(1:gr%np, 1:ndim))
277 safe_allocate(drho_core(1:gr%np, 1:st%d%nspin))
278 safe_allocate(dvxc_bare(1:gr%np, 1:st%d%nspin, 1:1))
279 if (states_are_real(st)) then
280 safe_allocate(ddrho_tot(1:gr%np, 1:st%d%nspin))
281 safe_allocate(ddvxc_resp(1:gr%np, 1:st%d%nspin, 1:1))
282 else
283 safe_allocate(zdrho_tot(1:gr%np, 1:st%d%nspin))
284 safe_allocate(zdvxc_resp(1:gr%np, 1:st%d%nspin, 1:1))
285 end if
286 end if
287
288 do imat = start_mode, vib%num_modes
289 iatom = vibrations_get_atom(vib, imat)
290 idir = vibrations_get_dir(vib, imat)
291
292 write(message(1),'(a,i5,a,a1,a)') &
293 "Calculating response to displacement of atom ", iatom, " in ", index2axis(idir), "-direction."
294 call messages_info(1, namespace=sys%namespace)
295
296 ! the converged wfns for the previous mode are probably not a good starting point
297 call lr_zero(lr(1), st)
298
299 if (.not. fromscratch) then
300 message(1) = "Loading restart wavefunctions for linear response."
301 call messages_info(1, namespace=sys%namespace)
302 call restart_load%open_dir(wfs_tag_sigma(sys%namespace, phn_wfs_tag(iatom, idir), 1), ierr)
303 if (ierr == 0) then
304 call states_elec_load(restart_load, sys%namespace, sys%space, st, sys%gr, sys%kpoints, &
305 sys%st%restart_fixed_occ, ierr=ierr, lr = lr(1))
306 end if
307 if (ierr /= 0) then
308 message(1) = "Unable to read response wavefunctions from '"//&
309 trim(wfs_tag_sigma(sys%namespace, phn_wfs_tag(iatom, idir), 1))//"'."
310 call messages_warning(1, namespace=sys%namespace)
311 end if
312 call restart_load%close_dir()
313 end if
314
315 call pert%setup_atom(iatom)
316 call pert%setup_dir(idir)
317
318 if (sys%hm%ep%nlcc) then
319 ! The bare perturbation includes the xc response to the rigid displacement of the core density:
320 ! d rho_core / d R_{iatom, idir} = -d_idir rho_core, spread over the spin channels
321 call species_get_nlcc_grad_bare(ions%atom(iatom)%species, ions%space, ions%latt, ions%pos(:, iatom), &
322 gr, grad_rho_core)
323 do ispin = 1, st%d%nspin
324 drho_core(1:gr%np, ispin) = -grad_rho_core(1:gr%np, idir) / st%d%spin_channels
325 end do
326 call dsternheimer_calc_hvar(sh, sys%namespace, gr, sys%hm, lr, 1, dvxc_bare, &
327 lr_rho = drho_core, exclude_hartree = .true.)
328 call pert%set_nlcc_response(dvxc_bare(:, :, 1))
329 end if
330
331 ! We now solve the Sternheimber equation in order to get the first-order change in the wavefunction
332 ! This is then used to get the force derivatives
333 safe_allocate(force_deriv(1:ndim, 1:natoms))
334 if (states_are_real(st)) then
335
336 call dsternheimer_solve(sh, sys%namespace, sys%space, sys%gr, sys%kpoints, sys%st, sys%hm, sys%mc, &
337 lr, 1, m_zero, pert, restart_dump, phn_rho_tag(iatom, idir), phn_wfs_tag(iatom, idir))
338
339 if (sys%hm%ep%nlcc) then
340 ! the NLCC term of the force derivatives needs the xc response to the
341 ! composite (valence + core) response density
342 ddrho_tot(1:gr%np, 1:st%d%nspin) = lr(1)%ddl_rho(1:gr%np, 1:st%d%nspin) + drho_core(1:gr%np, 1:st%d%nspin)
343 call dsternheimer_calc_hvar(sh, sys%namespace, gr, sys%hm, lr, 1, ddvxc_resp, &
344 lr_rho = ddrho_tot, exclude_hartree = .true.)
345 call dforces_derivative(gr, sys%namespace, sys%space, ions, sys%hm%ep, st, sys%kpoints, lr(1), lr(1), force_deriv, &
346 sys%hm%lda_u_level, vxc_response = ddvxc_resp(:, :, 1))
347 else
348 call dforces_derivative(gr, sys%namespace, sys%space, ions, sys%hm%ep, st, sys%kpoints, lr(1), lr(1), force_deriv, &
349 sys%hm%lda_u_level)
350 end if
351
352 else
353
354 call zsternheimer_solve(sh, sys%namespace, sys%space, sys%gr, sys%kpoints, sys%st, sys%hm, sys%mc, &
355 lr, 1, m_z0, pert, restart_dump, phn_rho_tag(iatom, idir), phn_wfs_tag(iatom, idir))
356
357 if (sys%hm%ep%nlcc) then
358 zdrho_tot(1:gr%np, 1:st%d%nspin) = lr(1)%zdl_rho(1:gr%np, 1:st%d%nspin) + drho_core(1:gr%np, 1:st%d%nspin)
359 call zsternheimer_calc_hvar(sh, sys%namespace, gr, sys%hm, lr, 1, zdvxc_resp, &
360 lr_rho = zdrho_tot, exclude_hartree = .true.)
361 call zforces_derivative(gr, sys%namespace, sys%space, ions, sys%hm%ep, st, sys%kpoints, lr(1), lr(1), force_deriv, &
362 sys%hm%lda_u_level, vxc_response = zdvxc_resp(:, :, 1))
363 else
364 call zforces_derivative(gr, sys%namespace, sys%space, ions, sys%hm%ep, st, sys%kpoints, lr(1), lr(1), force_deriv, &
365 sys%hm%lda_u_level)
366 end if
367
368 end if
369
370 do jmat = 1, vib%num_modes
371 if (.not. symmetrize .and. jmat < imat) then
372 vib%dyn_matrix(jmat, imat) = vib%dyn_matrix(imat, jmat)
373 cycle
374 end if
375
376 jatom = vibrations_get_atom(vib, jmat)
377 jdir = vibrations_get_dir(vib, jmat)
378
379 vib%dyn_matrix(jmat, imat) = vib%dyn_matrix(jmat, imat) + real(force_deriv(jdir, jatom), real64)
380 vib%dyn_matrix(jmat, imat) = vib%dyn_matrix(jmat, imat) * vibrations_norm_factor(vib, iatom, jatom)
381 end do
382 safe_deallocate_a(force_deriv)
383
384 call vibrations_out_dyn_matrix_row(vib, imat)
385
386 if (do_infrared) then
387 if (states_are_real(st)) then
388 call dphonons_lr_infrared(gr, ions, st, lr(1), kdotp_lr, imat, iatom, idir, vib%infrared)
389 else
390 call zphonons_lr_infrared(gr, ions, st, lr(1), kdotp_lr, imat, iatom, idir, vib%infrared)
391 end if
392 end if
393
394 iunit_restart = restart_dump%open('restart', position='append')
395 ! open and close makes sure output is not buffered
396 do jmat = 1, vib%num_modes
397 write(line(1), *) jmat, imat, vib%dyn_matrix(jmat, imat)
398 call restart_dump%write(iunit_restart, line, 1, ierr)
399 if (ierr /= 0) then
400 message(1) = "Could not write restart information."
401 call messages_warning(1, namespace=sys%namespace)
402 end if
403 end do
404 write(line(1), *) imat, (vib%infrared(imat, idir), idir = 1, ndim)
405 call restart_dump%write(iunit_restart, line, 1, ierr)
406 if (ierr /= 0) then
407 message(1) = "Could not write restart information."
408 call messages_warning(1, namespace=sys%namespace)
409 end if
410 call restart_dump%close(iunit_restart)
411
412 message(1) = ""
413 call messages_info(1, namespace=sys%namespace)
414 end do
415
416 safe_deallocate_p(pert)
417
418 safe_deallocate_a(grad_rho_core)
419 safe_deallocate_a(drho_core)
420 safe_deallocate_a(dvxc_bare)
421 safe_deallocate_a(ddrho_tot)
422 safe_deallocate_a(ddvxc_resp)
423 safe_deallocate_a(zdrho_tot)
424 safe_deallocate_a(zdvxc_resp)
425
426 if (symmetrize) call vibrations_symmetrize_dyn_matrix(vib)
428 call vibrations_output(vib)
429 call axsf_mode_output(vib, ions, gr, sys%namespace)
430
431 if (do_infrared) then
432 if (sys%space%is_periodic() .and. .not. smear_is_semiconducting(st%smear)) then
433 message(1) = "Cannot calculate infrared intensities for periodic system with smearing (i.e. without a gap)."
434 call messages_info(1, namespace=sys%namespace)
435 else
436 call born_from_infrared(vib, born)
437 call born_output_charges(born, ions%atom, ions%charge, ions%natoms, sys%namespace, &
438 ndim, vib_modes_dir, write_real = .true.)
439 call calc_infrared()
440 end if
441
442 call born_charges_end(born)
443 end if
444
445 if (normal_mode_wfs) then
446 message(1) = "Calculating response wavefunctions for normal modes."
447 call messages_info(1, namespace=sys%namespace)
448 if (states_are_real(st)) then
449 call dphonons_lr_wavefunctions(lr(1), sys%namespace, sys%space, st, sys%gr, sys%kpoints, vib, restart_load, &
450 restart_dump)
451 else
452 call zphonons_lr_wavefunctions(lr(1), sys%namespace, sys%space, st, sys%gr, sys%kpoints, vib, restart_load, &
453 restart_dump)
454 end if
455 end if
456
457 !DESTRUCT
458
459 call lr_dealloc(lr(1))
460 call vibrations_end(vib)
461 call sternheimer_end(sh)
463 if (sys%space%is_periodic() .and. do_infrared) then
464 do idir = 1, sys%space%periodic_dim
465 call lr_dealloc(kdotp_lr(idir))
466 end do
467 end if
468 call restart_load%end()
469 call restart_dump%end()
470
471 pop_sub(phonons_lr_run_legacy)
472
473 contains
474
475 ! ---------------------------------------------------------
481 subroutine build_ionic_dyn_matrix()
482 real(real64) :: term, weight, xi(1:ndim), dx(1:ndim), r2
483
485
486 assert(.not. ions%space%is_periodic())
487
488 vib%dyn_matrix(:,:) = m_zero
489
490 do iatom = 1, natoms
491 xi = ions%pos(:, iatom)
492
493 do jatom = 1, natoms
494 if(iatom == jatom) cycle
495
496 dx = xi - ions%pos(:, jatom)
497 r2 = dot_product(dx, dx)
498
499 weight = ions%charge(iatom) * ions%charge(jatom) /(sqrt(r2)**3)
500
501 do idir = 1, ndim
502 do jdir = 1, ndim
503
504 term = weight * (ddelta(idir, jdir) - m_three*dx(idir)*dx(jdir)/r2)
505
506 ! The force is given by F_I = Z_I \sum_K Z_K (R_I-R_K)/|R_I-R_K|^3
507 ! There is therefore a diagonal term from the case J=I, with the sum over K
508 vib%dyn_matrix(vibrations_get_index(vib, iatom, jdir), vibrations_get_index(vib, iatom, idir)) = &
509 vib%dyn_matrix(vibrations_get_index(vib, iatom, jdir), vibrations_get_index(vib, iatom, idir)) + term
510
511 vib%dyn_matrix(vibrations_get_index(vib, jatom, jdir), vibrations_get_index(vib, iatom, idir)) = &
512 vib%dyn_matrix(vibrations_get_index(vib, jatom, jdir), vibrations_get_index(vib, iatom, idir)) - term
513 end do
514 end do
515 end do
516 end do
517
519 end subroutine build_ionic_dyn_matrix
520
521 ! ---------------------------------------------------------
523 subroutine calc_infrared()
524
525 integer :: iunit_ir
526 real(real64) :: lir(1:sys%space%dim+1)
527
529
530 iunit_ir = io_open(vib_modes_dir//'infrared', sys%namespace, action='write')
531
532 ! dP/dQ over a dimensionless normal-mode eigenvector is a charge, so the columns
533 ! below are in units of the elementary charge and do not depend on UnitsOutput.
534 write(iunit_ir, '(a)', advance = 'no') '# freq ['//trim(units_abbrev(unit_invcm))//']'
535 do idir = 1, ndim
536 write(iunit_ir, '(a14)', advance = 'no') '<' // index2axis(idir) // '> [e]'
537 end do
538 write(iunit_ir, '(a14)') 'average [e]'
539
540 do iatom = 1, natoms
541 do idir = 1, ndim
542
543 imat = vibrations_get_index(vib, iatom, idir)
544
545 write(iunit_ir, '(f17.8)', advance = 'no') units_from_atomic(unit_invcm, vib%freq(imat))
546 do jdir = 1, ndim
547 lir(jdir) = dot_product(vib%infrared(:, jdir), vib%normal_mode(:, imat))
548 write(iunit_ir, '(f14.5)', advance = 'no') units_from_atomic(unit_one, lir(jdir))
549 end do
550
551 lir(ndim+1) = norm2(lir(1:ndim))/sqrt(real(ndim, real64) )
552 write(iunit_ir, '(f17.8)') units_from_atomic(unit_one, lir(ndim + 1))
553 end do
554 end do
555
556 call io_close(iunit_ir)
558 end subroutine calc_infrared
559
560 end subroutine phonons_lr_run_legacy
561
562
563 ! ---------------------------------------------------------
564 subroutine born_from_infrared(vib, born)
565 type(vibrations_t), intent(in) :: vib
566 type(born_charges_t), intent(inout) :: born
567
568 integer :: imat, idir, iatom
569
570 push_sub(born_from_infrared)
571
572 do imat = 1, vib%num_modes
573 idir = vibrations_get_dir(vib, imat)
574 iatom = vibrations_get_atom(vib, imat)
575 born%charge(1:vib%ndim, idir, iatom) = -vib%infrared(imat, 1:vib%ndim)
576 end do
577
578 pop_sub(born_from_infrared)
579 end subroutine born_from_infrared
580
581
582 ! ---------------------------------------------------------
583 character(len=100) function phn_rho_tag(iatom, dir) result(str)
584 integer, intent(in) :: iatom, dir
585
586 push_sub(phn_rho_tag)
587
588 write(str, '(a,i4.4,a,i1)') 'phn_rho_', iatom, '_', dir
589
590 pop_sub(phn_rho_tag)
591
592 end function phn_rho_tag
593
594
595 ! ---------------------------------------------------------
596 character(len=100) function phn_wfs_tag(iatom, dir) result(str)
597 integer, intent(in) :: iatom, dir
598
599 push_sub(phn_wfs_tag)
600
601 write(str, '(a,i4.4,a,a)') "phn_wfs_", iatom, "_", index2axis(dir)
602
603 pop_sub(phn_wfs_tag)
604
605 end function phn_wfs_tag
606
607
608 ! ---------------------------------------------------------
609 character(len=100) function phn_nm_wfs_tag(inm) result(str)
610 integer, intent(in) :: inm
611
612 push_sub(phn_nm_wfs_tag)
613
614 write(str, '(a,i5.5)') "phn_nm_wfs_", inm
615
616 pop_sub(phn_nm_wfs_tag)
617
618 end function phn_nm_wfs_tag
619
620
621 ! ---------------------------------------------------------
623 subroutine axsf_mode_output(this, ions, mesh, namespace)
624 type(vibrations_t), intent(in) :: this
625 type(ions_t), intent(in) :: ions
626 class(mesh_t), intent(in) :: mesh
627 type(namespace_t), intent(in) :: namespace
628
629 integer :: iunit, iatom, idir, imat, jmat
630 real(real64), allocatable :: forces(:,:)
631 character(len=2) :: suffix
632
633 if (.not. mpi_world%is_root()) return
634
635 push_sub(axsf_mode_output)
636
637 ! for some reason, direct usage of this%suffix gives an odd result
638 suffix = vibrations_get_suffix(this)
639 iunit = io_open(vib_modes_dir//'normal_modes_'//suffix//'.axsf', namespace, action='write')
640
641 write(iunit, '(a,i6)') 'ANIMSTEPS ', this%num_modes
642 safe_allocate(forces(1:ions%space%dim, 1:ions%natoms))
643 do imat = 1, this%num_modes
644 do jmat = 1, this%num_modes
645 iatom = vibrations_get_atom(this, jmat)
646 idir = vibrations_get_dir(this, jmat)
647 forces(idir, iatom) = this%normal_mode(jmat, imat)
648 end do
649 call write_xsf_geometry(iunit, ions%space, ions%latt, ions%pos, ions%atom, mesh, forces = forces, index = imat)
650 end do
651 safe_deallocate_a(forces)
652 call io_close(iunit)
653
654 pop_sub(axsf_mode_output)
655 end subroutine axsf_mode_output
656
657 ! ---------------------------------------------------------
659 subroutine phonons_load(restart, vib, start_mode)
660 type(restart_t), intent(in) :: restart
661 type(vibrations_t), intent(inout) :: vib
662 integer, intent(out) :: start_mode
663
664 integer :: iunit, ierr, imode, jmode, imode_read, jmode_read
665 character(len=120) :: line(1)
666
667 push_sub(phonons_load)
668
669 iunit = restart%open('restart')
670 if (iunit /= -1) then
671 imode_loop: do imode = 1, vib%num_modes
672 do jmode = 1, vib%num_modes
673 call restart%read(iunit, line, 1, ierr)
674 if (ierr /= 0) exit imode_loop
675 read(line(1), fmt=*, iostat=ierr) jmode_read, imode_read, vib%dyn_matrix(jmode, imode)
676 if (imode_read /= imode) then
677 write(message(1),'(a,i9,a,i9)') "Corruption of restart data: row ", imode, " is labeled as ", imode_read
679 end if
680 if (jmode_read /= jmode) then
681 write(message(1),'(a,i9,a,i9)') "Corruption of restart data: column ", jmode, " is labeled as ", jmode_read
682 call messages_fatal(1)
683 end if
684 end do
685
686 call restart%read(iunit, line, 1, ierr)
687 if (ierr /= 0) exit
688
689 start_mode = imode + 1
690
691 read(line(1), fmt=*, iostat=ierr) imode_read, vib%infrared(imode, 1:vib%ndim)
692 if (imode_read /= imode) then
693 write(message(1),'(a,i9,a,i9)') "Corruption of restart data: infrared row ", imode, " is labeled as ", imode_read
694 call messages_fatal(1)
695 end if
696 end do imode_loop
697
698 write(message(1),'(a,i9,a,i9)') 'Info: Read saved dynamical-matrix rows for ', &
699 start_mode - 1, ' modes out of ', vib%num_modes
700 call messages_info(1)
701
702 call restart%close(iunit)
703 else
704 start_mode = 1
705
706 message(1) = "Could not open restart file 'restart'. Starting from scratch."
707 call messages_warning(1)
708 end if
709
710 pop_sub(phonons_load)
711 end subroutine phonons_load
712
713#include "complex.F90"
714#include "phonons_lr_inc.F90"
715
716#include "undef.F90"
717
718#include "real.F90"
719#include "phonons_lr_inc.F90"
720
721end module phonons_lr_oct_m
722
723!! Local Variables:
724!! mode: f90
725!! coding: utf-8
726!! End:
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)
subroutine, public epot_precalc_local_potential(ep, namespace, gr, ions)
Definition: epot.F90:666
subroutine, public dforces_derivative(gr, namespace, space, ions, ep, st, kpoints, lr, lr2, force_deriv, lda_u_level, vxc_response)
Computes the derivative of the ionic forces with respect to the strength of an external perturbation...
Definition: forces.F90:1276
subroutine, public zforces_derivative(gr, namespace, space, ions, ep, st, kpoints, lr, lr2, force_deriv, lda_u_level, vxc_response)
Computes the derivative of the ionic forces with respect to the strength of an external perturbation...
Definition: forces.F90:1954
real(real64), parameter, public m_zero
Definition: global.F90:200
character(len= *), parameter, public vib_modes_dir
Definition: global.F90:284
complex(real64), parameter, public m_z0
Definition: global.F90:210
real(real64), parameter, public m_three
Definition: global.F90:203
This module implements the underlying real-space grid.
Definition: grid.F90:119
subroutine, public write_xsf_geometry(iunit, space, latt, pos, atoms, mesh, forces, index)
for format specification see: http:
Definition: io.F90:116
subroutine, public io_close(iunit, grp)
Definition: io.F90:467
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:402
character(len=100) function, public kdotp_wfs_tag(dir, dir2)
Definition: kdotp_calc.F90:154
subroutine, public lr_zero(lr, st)
subroutine, public lr_allocate(lr, st, mesh, allocate_rho)
subroutine, public lr_init(lr)
subroutine, public lr_dealloc(lr)
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:117
real(real64) pure function, public ddelta(i, j)
Definition: math.F90:611
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_not_implemented(feature, namespace)
Definition: messages.F90:1068
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:525
subroutine, public messages_obsolete_variable(namespace, name, rep)
Definition: messages.F90:1000
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:410
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:276
This module implements the basic mulsisystem class, a container system for other systems.
subroutine, public zionic_pert_matrix_elements_2(gr, namespace, space, ions, hm, ik, st, vib, matrix)
Computes the second order term.
subroutine, public dionic_pert_matrix_elements_2(gr, namespace, space, ions, hm, ik, st, vib, matrix)
Computes the second order term.
subroutine dphonons_lr_infrared(mesh, ions, st, lr, kdotp_lr, imat, iatom, idir, infrared)
subroutine zphonons_lr_wavefunctions(lr, namespace, space, st, mesh, kpoints, vib, restart_load, restart_dump)
calculate the wavefunction associated with each normal mode
Definition: phonons_lr.F90:896
subroutine, public phonons_lr_run(system, from_scratch)
Definition: phonons_lr.F90:173
subroutine zphonons_lr_infrared(mesh, ions, st, lr, kdotp_lr, imat, iatom, idir, infrared)
Definition: phonons_lr.F90:852
subroutine born_from_infrared(vib, born)
Definition: phonons_lr.F90:660
character(len=100) function, public phn_nm_wfs_tag(inm)
Definition: phonons_lr.F90:705
subroutine phonons_load(restart, vib, start_mode)
Load restart information for a linear-response phonon calculation.
Definition: phonons_lr.F90:755
subroutine dphonons_lr_wavefunctions(lr, namespace, space, st, mesh, kpoints, vib, restart_load, restart_dump)
calculate the wavefunction associated with each normal mode
subroutine phonons_lr_run_legacy(sys, fromscratch)
Definition: phonons_lr.F90:191
subroutine, public axsf_mode_output(this, ions, mesh, namespace)
output eigenvectors as animated XSF file, one per frame, displacements as forces
Definition: phonons_lr.F90:719
character(len=100) function, public phn_rho_tag(iatom, dir)
Definition: phonons_lr.F90:679
character(len=100) function, public phn_wfs_tag(iatom, dir)
Definition: phonons_lr.F90:692
integer, parameter, public restart_kdotp
Definition: restart.F90:156
integer, parameter, public restart_gs
Definition: restart.F90:156
integer, parameter, public restart_type_dump
Definition: restart.F90:184
integer, parameter, public restart_vib_modes
Definition: restart.F90:156
integer, parameter, public restart_type_load
Definition: restart.F90:184
logical pure function, public smear_is_semiconducting(this)
Definition: smear.F90:1042
subroutine, public species_get_nlcc_grad_bare(species, space, latt, pos, mesh, grad_rho_core)
Returns the bare analytic gradient of the NLCC core density.
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, fixed_occ, is_complex, packed)
subroutine, public states_elec_load(restart, namespace, space, st, mesh, kpoints, fixed_occ, 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...
subroutine, public zsternheimer_calc_hvar(this, namespace, gr, hm, lr, nsigma, hvar, idir, lr_rho, exclude_hartree)
Computes the first-order variation of the Kohn-Sham potential from the stored xc kernel,...
subroutine, public dsternheimer_solve(this, namespace, space, gr, kpoints, st, hm, mc, lr, nsigma, omega, perturbation, restart, rho_tag, wfs_tag, idir, have_restart_rho, have_exact_freq)
This routine calculates the first-order variations of the wavefunctions for an applied perturbation.
subroutine, public dsternheimer_calc_hvar(this, namespace, gr, hm, lr, nsigma, hvar, idir, lr_rho, exclude_hartree)
Computes the first-order variation of the Kohn-Sham potential from the stored xc kernel,...
character(len=100) function, public wfs_tag_sigma(namespace, base_name, isigma)
subroutine, public zsternheimer_solve(this, namespace, space, gr, kpoints, st, hm, mc, lr, nsigma, omega, perturbation, restart, rho_tag, wfs_tag, idir, have_restart_rho, have_exact_freq)
This routine calculates the first-order variations of the wavefunctions for an applied perturbation.
subroutine, public sternheimer_end(this)
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)
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_invcm
For vibrational frequencies.
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
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:665
character(len=2) pure function, public vibrations_get_suffix(this)
Definition: vibrations.F90:223
real(real64) pure function, public vibrations_norm_factor(this, iatom, jatom)
Definition: vibrations.F90:262
subroutine, public vibrations_diag_dyn_matrix(this)
Diagonalize the dynamical matrix.
Definition: vibrations.F90:321
subroutine, public vibrations_out_dyn_matrix_row(this, imat)
Outputs one row of the dynamical matrix.
Definition: vibrations.F90:274
subroutine, public vibrations_init(this, space, natoms, mass, suffix, namespace)
Definition: vibrations.F90:169
integer pure function, public vibrations_get_dir(this, index)
Definition: vibrations.F90:374
subroutine, public vibrations_symmetrize_dyn_matrix(this)
Symmetrize the dynamical matric, which is real symmetric matrix.
Definition: vibrations.F90:232
integer pure function, public vibrations_get_index(this, iatom, idim)
Definition: vibrations.F90:355
subroutine, public vibrations_output(this)
Outputs the eigenvectors and eigenenergies of the dynamical matrix.
Definition: vibrations.F90:384
subroutine, public vibrations_end(this)
Definition: vibrations.F90:208
integer pure function, public vibrations_get_atom(this, index)
Definition: vibrations.F90:365
subroutine calc_infrared()
calculate infrared intensities
Definition: phonons_lr.F90:619
subroutine build_ionic_dyn_matrix()
Computes the ionic contribution to the dynamical matrix.
Definition: phonons_lr.F90:577
Class describing the electron system.
Definition: electrons.F90:222
Describes mesh distribution to nodes.
Definition: mesh.F90:187
Container class for lists of system_oct_m::system_t.
int true(void)