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 if (sys%kpoints%use_symmetries) then
136 call messages_experimental("CalculationMode = vib_modes with k-points symmetries", namespace=sys%namespace)
137 end if
138
139 if (sys%kpoints%reduced%npoints /= sys%kpoints%full%npoints) then
140 call messages_experimental("CalculationMode = vib_modes with reduced k-grid", namespace=sys%namespace)
141 end if
142
143 !%Variable CalcNormalModeWfs
144 !%Type logical
145 !%Default false
146 !%Section Linear Response::Vibrational Modes
147 !%Description
148 !% If set to true, the response wavefunctions for each normal mode will be calculated
149 !% and written in directory <tt>restart/vib_modes/phn_nm_wfs_XXXXX</tt>.
150 !% This part is time-consuming and not parallel, but not needed for most purposes.
151 !%End
152 call parse_variable(sys%namespace, 'CalcNormalModeWfs', .false., normal_mode_wfs)
153
154 !%Variable CalcInfrared
155 !%Type logical
156 !%Default true
157 !%Section Linear Response::Vibrational Modes
158 !%Description
159 !% If set to true, infrared intensities (and born charges) will be calculated
160 !% and written in <tt>vib_modes/infrared</tt>.
161 !%End
162 call parse_variable(sys%namespace, 'CalcInfrared', .true., do_infrared)
163
164 !%Variable SymmetrizeDynamicalMatrix
165 !%Type logical
166 !%Default true
167 !%Section Linear Response::Vibrational Modes
168 !%Description
169 !% If set to true, all entries of the dynamical matrix will be calculated and then
170 !% the matrix will be symmetrized to enforce <math>D_{ij} = D_{ji}</math>. If set to false,
171 !% only the upper half of the matrix will be calculated.
172 !%End
173 call parse_variable(sys%namespace, 'SymmetrizeDynamicalMatrix', .true., symmetrize)
174
175 ! replaced by properly saving and reading the dynamical matrix
176 call messages_obsolete_variable(sys%namespace, 'UseRestartDontSolve')
177
178 natoms = ions%natoms
179 ndim = sys%space%dim
180
181 call gs_restart%init(sys%namespace, restart_gs, restart_type_load, sys%mc, ierr, mesh=gr, exact=.true.)
182 if (ierr == 0) then
183 call states_elec_look_and_load(gs_restart, sys%namespace, sys%space, st, sys%gr, sys%kpoints, st%restart_fixed_occ)
184 call gs_restart%end()
185 else
186 message(1) = "Previous gs calculation is required."
187 call messages_fatal(1, namespace=sys%namespace)
188 end if
189
190 ! read kdotp wavefunctions if necessary (for IR intensities)
191 if (sys%space%is_periodic() .and. do_infrared) then
192 message(1) = "Reading kdotp wavefunctions for periodic directions."
193 call messages_info(1, namespace=sys%namespace)
194
195 call kdotp_restart%init(sys%namespace, restart_kdotp, restart_type_load, sys%mc, ierr, mesh=gr)
196 if (ierr /= 0) then
197 message(1) = "Unable to read kdotp wavefunctions."
198 message(2) = "Previous kdotp calculation required."
199 call messages_fatal(2, namespace=sys%namespace)
200 end if
201
202 do idir = 1, sys%space%periodic_dim
203 call lr_init(kdotp_lr(idir))
204 call lr_allocate(kdotp_lr(idir), sys%st, sys%gr)
205
206 ! load wavefunctions
207 str_tmp = trim(kdotp_wfs_tag(idir))
208 call kdotp_restart%open_dir(wfs_tag_sigma(sys%namespace, str_tmp, 1), ierr)
209 if (ierr == 0) then
210 call states_elec_load(kdotp_restart, sys%namespace, sys%space, sys%st, sys%gr, sys%kpoints, &
211 sys%st%restart_fixed_occ, ierr=ierr, lr=kdotp_lr(idir))
212 end if
213 call kdotp_restart%close_dir()
214
215 if (ierr /= 0) then
216 message(1) = "Unable to read kdotp wavefunctions from '"//trim(wfs_tag_sigma(sys%namespace, str_tmp, 1))//"'."
217 message(2) = "Previous kdotp calculation required."
218 call messages_fatal(2, namespace=sys%namespace)
219 end if
220 end do
221 call kdotp_restart%end()
222 end if
223
224 message(1) = 'Info: Setting up Hamiltonian for linear response.'
225 call messages_info(1, namespace=sys%namespace)
226
227 call v_ks_h_setup(sys%namespace, sys%space, sys%gr, sys%ions, sys%ext_partners, sys%st, sys%ks, sys%hm)
228 call sternheimer_init(sh, sys%namespace, sys%space, sys%gr, sys%st, sys%hm, sys%ks, sys%mc, &
229 wfs_are_cplx = states_are_complex(st))
230
231 if (sys%hm%ep%nlcc .and. .not. sh%add_fxc()) then
232 message(1) = "Linear-response vib_modes with non-linear core corrections requires the xc kernel."
233 message(2) = "HamiltonianVariation must include V_xc."
234 call messages_fatal(2, namespace=sys%namespace)
235 end if
236
237 call vibrations_init(vib, ions%space, ions%natoms, ions%mass, "lr", sys%namespace)
238
239 call epot_precalc_local_potential(sys%hm%ep, sys%namespace, sys%gr, sys%ions)
240
241 if (do_infrared) then
242 call born_charges_init(born, sys%namespace, ions%natoms, st%val_charge, st%qtot, ndim)
243 end if
244
245 call lr_init(lr(1))
246 call lr_allocate(lr(1), st, gr)
247
248 call restart_dump%init(sys%namespace, restart_vib_modes, restart_type_dump, sys%mc, ierr, mesh=gr)
249 call restart_load%init(sys%namespace, restart_vib_modes, restart_type_load, sys%mc, ierr, mesh=gr)
250
251 !CALCULATE
252
253 ! the ionic contribution, see second term in Eq. 85 in Baroni et al. RMP, 73, 515 (2001)
255
256 ! Compute the -<phi0 | v2 | phi0> term
257 if (states_are_real(st)) then
258 call dionic_pert_matrix_elements_2(sys%gr, sys%namespace, sys%space, sys%ions, sys%hm, 1, st, vib, vib%dyn_matrix)
259 else
260 call zionic_pert_matrix_elements_2(sys%gr, sys%namespace, sys%space, sys%ions, sys%hm, 1, st, vib, vib%dyn_matrix)
261 end if
262
263 if (fromscratch) then
264 start_mode = 1
265 else
266 call phonons_load(restart_load, vib, start_mode)
267 end if
268
269 ! Delete, if fromScratch, or trying to open it failed and there is something wrong with it.
270 if (start_mode == 1) call restart_dump%rm('restart')
271
272 ! Output the first start_mode-1 modes
273 do imat = 1, start_mode - 1
274 call vibrations_out_dyn_matrix_row(vib, imat)
275 end do
276
277
278 ! The remaining term is <\psi_1 | v^{(1)} | \psi_0> + <\psi_0 | v^{(1)} | \psi_1>
279 ! We first get \psi_1 from Sternheimer, and then compute the term using X(forces_derivative)
280 ! Note that in order to avoid getting v^{(1)}, we perform an integration by part in this routine
281 pert => perturbation_ionic_t(sys%namespace, ions)
282
283 if (sys%hm%ep%nlcc) then
284 safe_allocate(grad_rho_core(1:gr%np, 1:ndim))
285 safe_allocate(drho_core(1:gr%np, 1:st%d%nspin))
286 safe_allocate(dvxc_bare(1:gr%np, 1:st%d%nspin, 1:1))
287 if (states_are_real(st)) then
288 safe_allocate(ddrho_tot(1:gr%np, 1:st%d%nspin))
289 safe_allocate(ddvxc_resp(1:gr%np, 1:st%d%nspin, 1:1))
290 else
291 safe_allocate(zdrho_tot(1:gr%np, 1:st%d%nspin))
292 safe_allocate(zdvxc_resp(1:gr%np, 1:st%d%nspin, 1:1))
293 end if
294 end if
295
296 do imat = start_mode, vib%num_modes
297 iatom = vibrations_get_atom(vib, imat)
298 idir = vibrations_get_dir(vib, imat)
299
300 write(message(1),'(a,i5,a,a1,a)') &
301 "Calculating response to displacement of atom ", iatom, " in ", index2axis(idir), "-direction."
302 call messages_info(1, namespace=sys%namespace)
303
304 ! the converged wfns for the previous mode are probably not a good starting point
305 call lr_zero(lr(1), st)
306
307 if (.not. fromscratch) then
308 message(1) = "Loading restart wavefunctions for linear response."
309 call messages_info(1, namespace=sys%namespace)
310 call restart_load%open_dir(wfs_tag_sigma(sys%namespace, phn_wfs_tag(iatom, idir), 1), ierr)
311 if (ierr == 0) then
312 call states_elec_load(restart_load, sys%namespace, sys%space, st, sys%gr, sys%kpoints, &
313 sys%st%restart_fixed_occ, ierr=ierr, lr = lr(1))
314 end if
315 if (ierr /= 0) then
316 message(1) = "Unable to read response wavefunctions from '"//&
317 trim(wfs_tag_sigma(sys%namespace, phn_wfs_tag(iatom, idir), 1))//"'."
318 call messages_warning(1, namespace=sys%namespace)
319 end if
320 call restart_load%close_dir()
321 end if
322
323 call pert%setup_atom(iatom)
324 call pert%setup_dir(idir)
325
326 if (sys%hm%ep%nlcc) then
327 ! The bare perturbation includes the xc response to the rigid displacement of the core density:
328 ! d rho_core / d R_{iatom, idir} = -d_idir rho_core, spread over the spin channels
329 call species_get_nlcc_grad_bare(ions%atom(iatom)%species, ions%space, ions%latt, ions%pos(:, iatom), &
330 gr, grad_rho_core)
331 do ispin = 1, st%d%nspin
332 drho_core(1:gr%np, ispin) = -grad_rho_core(1:gr%np, idir) / st%d%spin_channels
333 end do
334 call dsternheimer_calc_hvar(sh, sys%namespace, gr, sys%hm, lr, 1, dvxc_bare, &
335 lr_rho = drho_core, exclude_hartree = .true.)
336 call pert%set_nlcc_response(dvxc_bare(:, :, 1))
337 end if
338
339 ! We now solve the Sternheimber equation in order to get the first-order change in the wavefunction
340 ! This is then used to get the force derivatives
341 safe_allocate(force_deriv(1:ndim, 1:natoms))
342 if (states_are_real(st)) then
343
344 call dsternheimer_solve(sh, sys%namespace, sys%space, sys%gr, sys%kpoints, sys%st, sys%hm, sys%mc, &
345 lr, 1, m_zero, pert, restart_dump, phn_rho_tag(iatom, idir), phn_wfs_tag(iatom, idir))
346
347 if (sys%hm%ep%nlcc) then
348 ! the NLCC term of the force derivatives needs the xc response to the
349 ! composite (valence + core) response density
350 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)
351 call dsternheimer_calc_hvar(sh, sys%namespace, gr, sys%hm, lr, 1, ddvxc_resp, &
352 lr_rho = ddrho_tot, exclude_hartree = .true.)
353 call dforces_derivative(gr, sys%namespace, sys%space, ions, sys%hm%ep, st, sys%kpoints, lr(1), lr(1), force_deriv, &
354 sys%hm%lda_u_level, vxc_response = ddvxc_resp(:, :, 1))
355 else
356 call dforces_derivative(gr, sys%namespace, sys%space, ions, sys%hm%ep, st, sys%kpoints, lr(1), lr(1), force_deriv, &
357 sys%hm%lda_u_level)
358 end if
359
360 else
361
362 call zsternheimer_solve(sh, sys%namespace, sys%space, sys%gr, sys%kpoints, sys%st, sys%hm, sys%mc, &
363 lr, 1, m_z0, pert, restart_dump, phn_rho_tag(iatom, idir), phn_wfs_tag(iatom, idir))
364
365 if (sys%hm%ep%nlcc) then
366 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)
367 call zsternheimer_calc_hvar(sh, sys%namespace, gr, sys%hm, lr, 1, zdvxc_resp, &
368 lr_rho = zdrho_tot, exclude_hartree = .true.)
369 call zforces_derivative(gr, sys%namespace, sys%space, ions, sys%hm%ep, st, sys%kpoints, lr(1), lr(1), force_deriv, &
370 sys%hm%lda_u_level, vxc_response = zdvxc_resp(:, :, 1))
371 else
372 call zforces_derivative(gr, sys%namespace, sys%space, ions, sys%hm%ep, st, sys%kpoints, lr(1), lr(1), force_deriv, &
373 sys%hm%lda_u_level)
374 end if
375
376 end if
377
378 do jmat = 1, vib%num_modes
379 if (.not. symmetrize .and. jmat < imat) then
380 vib%dyn_matrix(jmat, imat) = vib%dyn_matrix(imat, jmat)
381 cycle
382 end if
383
384 jatom = vibrations_get_atom(vib, jmat)
385 jdir = vibrations_get_dir(vib, jmat)
386
387 vib%dyn_matrix(jmat, imat) = vib%dyn_matrix(jmat, imat) + real(force_deriv(jdir, jatom), real64)
388 vib%dyn_matrix(jmat, imat) = vib%dyn_matrix(jmat, imat) * vibrations_norm_factor(vib, iatom, jatom)
389 end do
390 safe_deallocate_a(force_deriv)
391
392 call vibrations_out_dyn_matrix_row(vib, imat)
393
394 if (do_infrared) then
395 if (states_are_real(st)) then
396 call dphonons_lr_infrared(gr, ions, st, lr(1), kdotp_lr, imat, iatom, idir, vib%infrared)
397 else
398 call zphonons_lr_infrared(gr, ions, st, lr(1), kdotp_lr, imat, iatom, idir, vib%infrared)
399 end if
400 end if
401
402 iunit_restart = restart_dump%open('restart', position='append')
403 ! open and close makes sure output is not buffered
404 do jmat = 1, vib%num_modes
405 write(line(1), *) jmat, imat, vib%dyn_matrix(jmat, imat)
406 call restart_dump%write(iunit_restart, line, 1, ierr)
407 if (ierr /= 0) then
408 message(1) = "Could not write restart information."
409 call messages_warning(1, namespace=sys%namespace)
410 end if
411 end do
412 write(line(1), *) imat, (vib%infrared(imat, idir), idir = 1, ndim)
413 call restart_dump%write(iunit_restart, line, 1, ierr)
414 if (ierr /= 0) then
415 message(1) = "Could not write restart information."
416 call messages_warning(1, namespace=sys%namespace)
417 end if
418 call restart_dump%close(iunit_restart)
419
420 message(1) = ""
421 call messages_info(1, namespace=sys%namespace)
422 end do
423
424 safe_deallocate_p(pert)
425
426 safe_deallocate_a(grad_rho_core)
427 safe_deallocate_a(drho_core)
428 safe_deallocate_a(dvxc_bare)
429 safe_deallocate_a(ddrho_tot)
430 safe_deallocate_a(ddvxc_resp)
431 safe_deallocate_a(zdrho_tot)
432 safe_deallocate_a(zdvxc_resp)
433
434 if (symmetrize) call vibrations_symmetrize_dyn_matrix(vib)
436 call vibrations_output(vib)
437 call axsf_mode_output(vib, ions, gr, sys%namespace)
438
439 if (do_infrared) then
440 if (sys%space%is_periodic() .and. .not. smear_is_semiconducting(st%smear)) then
441 message(1) = "Cannot calculate infrared intensities for periodic system with smearing (i.e. without a gap)."
442 call messages_info(1, namespace=sys%namespace)
443 else
444 call born_from_infrared(vib, born)
445 call born_output_charges(born, ions%atom, ions%charge, ions%natoms, sys%namespace, &
446 ndim, vib_modes_dir, write_real = .true.)
447 call calc_infrared()
448 end if
449
450 call born_charges_end(born)
451 end if
452
453 if (normal_mode_wfs) then
454 message(1) = "Calculating response wavefunctions for normal modes."
455 call messages_info(1, namespace=sys%namespace)
456 if (states_are_real(st)) then
457 call dphonons_lr_wavefunctions(lr(1), sys%namespace, sys%space, st, sys%gr, sys%kpoints, vib, restart_load, &
458 restart_dump)
459 else
460 call zphonons_lr_wavefunctions(lr(1), sys%namespace, sys%space, st, sys%gr, sys%kpoints, vib, restart_load, &
461 restart_dump)
462 end if
463 end if
464
465 !DESTRUCT
466
467 call lr_dealloc(lr(1))
468 call vibrations_end(vib)
469 call sternheimer_end(sh)
471 if (sys%space%is_periodic() .and. do_infrared) then
472 do idir = 1, sys%space%periodic_dim
473 call lr_dealloc(kdotp_lr(idir))
474 end do
475 end if
476 call restart_load%end()
477 call restart_dump%end()
478
479 pop_sub(phonons_lr_run_legacy)
480
481 contains
482
483 ! ---------------------------------------------------------
489 subroutine build_ionic_dyn_matrix()
490 real(real64) :: term, weight, xi(1:ndim), dx(1:ndim), r2
491
493
494 assert(.not. ions%space%is_periodic())
495
496 vib%dyn_matrix(:,:) = m_zero
497
498 do iatom = 1, natoms
499 xi = ions%pos(:, iatom)
500
501 do jatom = 1, natoms
502 if(iatom == jatom) cycle
503
504 dx = xi - ions%pos(:, jatom)
505 r2 = dot_product(dx, dx)
506
507 weight = ions%charge(iatom) * ions%charge(jatom) /(sqrt(r2)**3)
508
509 do idir = 1, ndim
510 do jdir = 1, ndim
511
512 term = weight * (ddelta(idir, jdir) - m_three*dx(idir)*dx(jdir)/r2)
513
514 ! The force is given by F_I = Z_I \sum_K Z_K (R_I-R_K)/|R_I-R_K|^3
515 ! There is therefore a diagonal term from the case J=I, with the sum over K
516 vib%dyn_matrix(vibrations_get_index(vib, iatom, jdir), vibrations_get_index(vib, iatom, idir)) = &
517 vib%dyn_matrix(vibrations_get_index(vib, iatom, jdir), vibrations_get_index(vib, iatom, idir)) + term
518
519 vib%dyn_matrix(vibrations_get_index(vib, jatom, jdir), vibrations_get_index(vib, iatom, idir)) = &
520 vib%dyn_matrix(vibrations_get_index(vib, jatom, jdir), vibrations_get_index(vib, iatom, idir)) - term
521 end do
522 end do
523 end do
524 end do
525
527 end subroutine build_ionic_dyn_matrix
528
529 ! ---------------------------------------------------------
531 subroutine calc_infrared()
532
533 integer :: iunit_ir
534 real(real64) :: lir(1:sys%space%dim+1)
535
537
538 iunit_ir = io_open(vib_modes_dir//'infrared', sys%namespace, action='write')
539
540 ! dP/dQ over a dimensionless normal-mode eigenvector is a charge, so the columns
541 ! below are in units of the elementary charge and do not depend on UnitsOutput.
542 write(iunit_ir, '(a)', advance = 'no') '# freq ['//trim(units_abbrev(unit_invcm))//']'
543 do idir = 1, ndim
544 write(iunit_ir, '(a14)', advance = 'no') '<' // index2axis(idir) // '> [e]'
545 end do
546 write(iunit_ir, '(a14)') 'average [e]'
547
548 do iatom = 1, natoms
549 do idir = 1, ndim
550
551 imat = vibrations_get_index(vib, iatom, idir)
552
553 write(iunit_ir, '(f17.8)', advance = 'no') units_from_atomic(unit_invcm, vib%freq(imat))
554 do jdir = 1, ndim
555 lir(jdir) = dot_product(vib%infrared(:, jdir), vib%normal_mode(:, imat))
556 write(iunit_ir, '(f14.5)', advance = 'no') units_from_atomic(unit_one, lir(jdir))
557 end do
558
559 lir(ndim+1) = norm2(lir(1:ndim))/sqrt(real(ndim, real64) )
560 write(iunit_ir, '(f17.8)') units_from_atomic(unit_one, lir(ndim + 1))
561 end do
562 end do
563
564 call io_close(iunit_ir)
566 end subroutine calc_infrared
567
568 end subroutine phonons_lr_run_legacy
569
570
571 ! ---------------------------------------------------------
572 subroutine born_from_infrared(vib, born)
573 type(vibrations_t), intent(in) :: vib
574 type(born_charges_t), intent(inout) :: born
575
576 integer :: imat, idir, iatom
577
578 push_sub(born_from_infrared)
579
580 do imat = 1, vib%num_modes
581 idir = vibrations_get_dir(vib, imat)
582 iatom = vibrations_get_atom(vib, imat)
583 born%charge(1:vib%ndim, idir, iatom) = -vib%infrared(imat, 1:vib%ndim)
584 end do
585
586 pop_sub(born_from_infrared)
587 end subroutine born_from_infrared
588
589
590 ! ---------------------------------------------------------
591 character(len=100) function phn_rho_tag(iatom, dir) result(str)
592 integer, intent(in) :: iatom, dir
593
594 push_sub(phn_rho_tag)
595
596 write(str, '(a,i4.4,a,i1)') 'phn_rho_', iatom, '_', dir
597
598 pop_sub(phn_rho_tag)
599
600 end function phn_rho_tag
601
602
603 ! ---------------------------------------------------------
604 character(len=100) function phn_wfs_tag(iatom, dir) result(str)
605 integer, intent(in) :: iatom, dir
606
607 push_sub(phn_wfs_tag)
608
609 write(str, '(a,i4.4,a,a)') "phn_wfs_", iatom, "_", index2axis(dir)
610
611 pop_sub(phn_wfs_tag)
612
613 end function phn_wfs_tag
614
615
616 ! ---------------------------------------------------------
617 character(len=100) function phn_nm_wfs_tag(inm) result(str)
618 integer, intent(in) :: inm
619
620 push_sub(phn_nm_wfs_tag)
621
622 write(str, '(a,i5.5)') "phn_nm_wfs_", inm
623
624 pop_sub(phn_nm_wfs_tag)
625
626 end function phn_nm_wfs_tag
627
628
629 ! ---------------------------------------------------------
631 subroutine axsf_mode_output(this, ions, mesh, namespace)
632 type(vibrations_t), intent(in) :: this
633 type(ions_t), intent(in) :: ions
634 class(mesh_t), intent(in) :: mesh
635 type(namespace_t), intent(in) :: namespace
636
637 integer :: iunit, iatom, idir, imat, jmat
638 real(real64), allocatable :: forces(:,:)
639 character(len=2) :: suffix
640
641 if (.not. mpi_world%is_root()) return
642
643 push_sub(axsf_mode_output)
644
645 ! for some reason, direct usage of this%suffix gives an odd result
646 suffix = vibrations_get_suffix(this)
647 iunit = io_open(vib_modes_dir//'normal_modes_'//suffix//'.axsf', namespace, action='write')
648
649 write(iunit, '(a,i6)') 'ANIMSTEPS ', this%num_modes
650 safe_allocate(forces(1:ions%space%dim, 1:ions%natoms))
651 do imat = 1, this%num_modes
652 do jmat = 1, this%num_modes
653 iatom = vibrations_get_atom(this, jmat)
654 idir = vibrations_get_dir(this, jmat)
655 forces(idir, iatom) = this%normal_mode(jmat, imat)
656 end do
657 call write_xsf_geometry(iunit, ions%space, ions%latt, ions%pos, ions%atom, mesh, forces = forces, index = imat)
658 end do
659 safe_deallocate_a(forces)
660 call io_close(iunit)
661
662 pop_sub(axsf_mode_output)
663 end subroutine axsf_mode_output
664
665 ! ---------------------------------------------------------
667 subroutine phonons_load(restart, vib, start_mode)
668 type(restart_t), intent(in) :: restart
669 type(vibrations_t), intent(inout) :: vib
670 integer, intent(out) :: start_mode
671
672 integer :: iunit, ierr, imode, jmode, imode_read, jmode_read
673 character(len=120) :: line(1)
674
675 push_sub(phonons_load)
676
677 iunit = restart%open('restart')
678 if (iunit /= -1) then
679 imode_loop: do imode = 1, vib%num_modes
680 do jmode = 1, vib%num_modes
681 call restart%read(iunit, line, 1, ierr)
682 if (ierr /= 0) exit imode_loop
683 read(line(1), fmt=*, iostat=ierr) jmode_read, imode_read, vib%dyn_matrix(jmode, imode)
684 if (imode_read /= imode) then
685 write(message(1),'(a,i9,a,i9)') "Corruption of restart data: row ", imode, " is labeled as ", imode_read
687 end if
688 if (jmode_read /= jmode) then
689 write(message(1),'(a,i9,a,i9)') "Corruption of restart data: column ", jmode, " is labeled as ", jmode_read
690 call messages_fatal(1)
691 end if
692 end do
693
694 call restart%read(iunit, line, 1, ierr)
695 if (ierr /= 0) exit
696
697 start_mode = imode + 1
698
699 read(line(1), fmt=*, iostat=ierr) imode_read, vib%infrared(imode, 1:vib%ndim)
700 if (imode_read /= imode) then
701 write(message(1),'(a,i9,a,i9)') "Corruption of restart data: infrared row ", imode, " is labeled as ", imode_read
702 call messages_fatal(1)
703 end if
704 end do imode_loop
705
706 write(message(1),'(a,i9,a,i9)') 'Info: Read saved dynamical-matrix rows for ', &
707 start_mode - 1, ' modes out of ', vib%num_modes
708 call messages_info(1)
709
710 call restart%close(iunit)
711 else
712 start_mode = 1
713
714 message(1) = "Could not open restart file 'restart'. Starting from scratch."
715 call messages_warning(1)
716 end if
717
718 pop_sub(phonons_load)
719 end subroutine phonons_load
720
721#include "complex.F90"
722#include "phonons_lr_inc.F90"
723
724#include "undef.F90"
725
726#include "real.F90"
727#include "phonons_lr_inc.F90"
728
729end module phonons_lr_oct_m
730
731!! Local Variables:
732!! mode: f90
733!! coding: utf-8
734!! 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:1317
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:1995
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_experimental(name, namespace)
Definition: messages.F90:1040
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:904
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:860
subroutine born_from_infrared(vib, born)
Definition: phonons_lr.F90:668
character(len=100) function, public phn_nm_wfs_tag(inm)
Definition: phonons_lr.F90:713
subroutine phonons_load(restart, vib, start_mode)
Load restart information for a linear-response phonon calculation.
Definition: phonons_lr.F90:763
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:727
character(len=100) function, public phn_rho_tag(iatom, dir)
Definition: phonons_lr.F90:687
character(len=100) function, public phn_wfs_tag(iatom, dir)
Definition: phonons_lr.F90:700
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:627
subroutine build_ionic_dyn_matrix()
Computes the ionic contribution to the dynamical matrix.
Definition: phonons_lr.F90:585
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)