32 use,
intrinsic :: iso_fortran_env
78 class(*),
intent(inout) :: system
79 logical,
intent(in) :: from_scratch
85 message(1) =
"CalculationMode = vib_modes not implemented for multi-system calculations"
96 type(electrons_t),
target,
intent(inout) :: sys
97 logical,
intent(in) :: fromscratch
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
104 type(ions_t),
pointer :: ions
105 type(states_elec_t),
pointer :: st
106 type(grid_t),
pointer :: gr
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
127 if (sys%hm%pcm%run_pcm)
then
131 if (sys%space%is_periodic())
then
144 call parse_variable(sys%namespace,
'CalcNormalModeWfs', .false., normal_mode_wfs)
176 call gs_restart%end()
178 message(1) =
"Previous gs calculation is required."
183 if (sys%space%is_periodic() .and. do_infrared)
then
184 message(1) =
"Reading kdotp wavefunctions for periodic directions."
189 message(1) =
"Unable to read kdotp wavefunctions."
190 message(2) =
"Previous kdotp calculation required."
194 do idir = 1, sys%space%periodic_dim
200 call kdotp_restart%open_dir(
wfs_tag_sigma(sys%namespace, str_tmp, 1), ierr)
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))
205 call kdotp_restart%close_dir()
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."
213 call kdotp_restart%end()
216 message(1) =
'Info: Setting up Hamiltonian for linear response.'
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, &
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."
229 call vibrations_init(vib, ions%space, ions%natoms, ions%mass,
"lr", sys%namespace)
233 if (do_infrared)
then
234 call born_charges_init(born, sys%namespace, ions%natoms, st%val_charge, st%qtot, ndim)
255 if (fromscratch)
then
262 if (start_mode == 1)
call restart_dump%rm(
'restart')
265 do imat = 1, start_mode - 1
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))
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))
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))
288 do imat = start_mode, vib%num_modes
292 write(
message(1),
'(a,i5,a,a1,a)') &
293 "Calculating response to displacement of atom ", iatom,
" in ",
index2axis(idir),
"-direction."
299 if (.not. fromscratch)
then
300 message(1) =
"Loading restart wavefunctions for linear response."
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))
308 message(1) =
"Unable to read response wavefunctions from '"//&
312 call restart_load%close_dir()
315 call pert%setup_atom(iatom)
316 call pert%setup_dir(idir)
318 if (sys%hm%ep%nlcc)
then
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
327 lr_rho = drho_core, exclude_hartree = .
true.)
328 call pert%set_nlcc_response(dvxc_bare(:, :, 1))
333 safe_allocate(force_deriv(1:ndim, 1:natoms))
336 call dsternheimer_solve(sh, sys%namespace, sys%space, sys%gr, sys%kpoints, sys%st, sys%hm, sys%mc, &
339 if (sys%hm%ep%nlcc)
then
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)
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))
348 call dforces_derivative(gr, sys%namespace, sys%space, ions, sys%hm%ep, st, sys%kpoints, lr(1), lr(1), force_deriv, &
354 call zsternheimer_solve(sh, sys%namespace, sys%space, sys%gr, sys%kpoints, sys%st, sys%hm, sys%mc, &
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)
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))
364 call zforces_derivative(gr, sys%namespace, sys%space, ions, sys%hm%ep, st, sys%kpoints, lr(1), lr(1), force_deriv, &
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)
379 vib%dyn_matrix(jmat, imat) = vib%dyn_matrix(jmat, imat) + real(force_deriv(jdir, jatom), real64)
382 safe_deallocate_a(force_deriv)
386 if (do_infrared)
then
394 iunit_restart = restart_dump%open(
'restart', position=
'append')
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)
400 message(1) =
"Could not write restart information."
404 write(line(1), *) imat, (vib%infrared(imat, idir), idir = 1, ndim)
405 call restart_dump%write(iunit_restart, line, 1, ierr)
407 message(1) =
"Could not write restart information."
410 call restart_dump%close(iunit_restart)
416 safe_deallocate_p(pert)
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)
431 if (do_infrared)
then
433 message(1) =
"Cannot calculate infrared intensities for periodic system with smearing (i.e. without a gap)."
445 if (normal_mode_wfs)
then
446 message(1) =
"Calculating response wavefunctions for normal modes."
463 if (sys%space%is_periodic() .and. do_infrared)
then
464 do idir = 1, sys%space%periodic_dim
468 call restart_load%end()
469 call restart_dump%end()
482 real(real64) :: term, weight, xi(1:ndim), dx(1:ndim), r2
486 assert(.not. ions%space%is_periodic())
488 vib%dyn_matrix(:,:) =
m_zero
491 xi = ions%pos(:, iatom)
494 if(iatom == jatom) cycle
496 dx = xi - ions%pos(:, jatom)
497 r2 = dot_product(dx, dx)
499 weight = ions%charge(iatom) * ions%charge(jatom) /(
sqrt(r2)**3)
504 term = weight * (
ddelta(idir, jdir) -
m_three*dx(idir)*dx(jdir)/r2)
526 real(real64) :: lir(1:sys%space%dim+1)
536 write(iunit_ir,
'(a14)', advance =
'no')
'<' //
index2axis(idir) //
'> [e]'
538 write(iunit_ir,
'(a14)')
'average [e]'
547 lir(jdir) = dot_product(vib%infrared(:, jdir), vib%normal_mode(:, imat))
551 lir(ndim+1) = norm2(lir(1:ndim))/
sqrt(real(ndim, real64) )
568 integer :: imat, idir, iatom
572 do imat = 1, vib%num_modes
575 born%charge(1:vib%ndim, idir, iatom) = -vib%infrared(imat, 1:vib%ndim)
583 character(len=100) function phn_rho_tag(iatom, dir)
result(str)
584 integer,
intent(in) :: iatom, dir
588 write(str,
'(a,i4.4,a,i1)')
'phn_rho_', iatom,
'_', dir
596 character(len=100) function phn_wfs_tag(iatom, dir)
result(str)
597 integer,
intent(in) :: iatom, dir
601 write(str,
'(a,i4.4,a,a)')
"phn_wfs_", iatom,
"_",
index2axis(dir)
610 integer,
intent(in) :: inm
614 write(str,
'(a,i5.5)')
"phn_nm_wfs_", inm
625 type(
ions_t),
intent(in) :: ions
626 class(
mesh_t),
intent(in) :: mesh
629 integer :: iunit, iatom, idir, imat, jmat
630 real(real64),
allocatable :: forces(:,:)
631 character(len=2) :: suffix
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
647 forces(idir, iatom) = this%normal_mode(jmat, imat)
649 call write_xsf_geometry(iunit, ions%space, ions%latt, ions%pos, ions%atom, mesh, forces = forces, index = imat)
651 safe_deallocate_a(forces)
662 integer,
intent(out) :: start_mode
664 integer :: iunit, ierr, imode, jmode, imode_read, jmode_read
665 character(len=120) :: line(1)
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
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
686 call restart%read(iunit, line, 1, ierr)
689 start_mode = imode + 1
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
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
702 call restart%close(iunit)
706 message(1) =
"Could not open restart file 'restart'. Starting from scratch."
713#include "complex.F90"
714#include "phonons_lr_inc.F90"
719#include "phonons_lr_inc.F90"
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)
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...
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...
real(real64), parameter, public m_zero
character(len= *), parameter, public vib_modes_dir
complex(real64), parameter, public m_z0
real(real64), parameter, public m_three
This module implements the underlying real-space grid.
subroutine, public write_xsf_geometry(iunit, space, latt, pos, atoms, mesh, forces, index)
for format specification see: http:
subroutine, public io_close(iunit, grp)
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
character(len=100) function, public kdotp_wfs_tag(dir, dir2)
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.
real(real64) pure function, public ddelta(i, j)
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
subroutine, public messages_not_implemented(feature, namespace)
subroutine, public messages_warning(no_lines, all_nodes, namespace)
subroutine, public messages_obsolete_variable(namespace, name, rep)
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
type(mpi_grp_t), public mpi_world
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
subroutine, public phonons_lr_run(system, from_scratch)
subroutine zphonons_lr_infrared(mesh, ions, st, lr, kdotp_lr, imat, iatom, idir, infrared)
subroutine born_from_infrared(vib, born)
character(len=100) function, public phn_nm_wfs_tag(inm)
subroutine phonons_load(restart, vib, start_mode)
Load restart information for a linear-response phonon calculation.
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)
subroutine, public axsf_mode_output(this, ions, mesh, namespace)
output eigenvectors as animated XSF file, one per frame, displacements as forces
character(len=100) function, public phn_rho_tag(iatom, dir)
character(len=100) function, public phn_wfs_tag(iatom, dir)
integer, parameter, public restart_kdotp
integer, parameter, public restart_gs
integer, parameter, public restart_type_dump
integer, parameter, public restart_vib_modes
integer, parameter, public restart_type_load
logical pure function, public smear_is_semiconducting(this)
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.
character(len=20) pure function, public units_abbrev(this)
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.
character pure function, public index2axis(idir)
subroutine, public v_ks_h_setup(namespace, space, gr, ions, ext_partners, st, ks, hm, calc_eigenval, calc_current)
character(len=2) pure function, public vibrations_get_suffix(this)
real(real64) pure function, public vibrations_norm_factor(this, iatom, jatom)
subroutine, public vibrations_diag_dyn_matrix(this)
Diagonalize the dynamical matrix.
subroutine, public vibrations_out_dyn_matrix_row(this, imat)
Outputs one row of the dynamical matrix.
subroutine, public vibrations_init(this, space, natoms, mass, suffix, namespace)
integer pure function, public vibrations_get_dir(this, index)
subroutine, public vibrations_symmetrize_dyn_matrix(this)
Symmetrize the dynamical matric, which is real symmetric matrix.
integer pure function, public vibrations_get_index(this, iatom, idim)
subroutine, public vibrations_output(this)
Outputs the eigenvectors and eigenenergies of the dynamical matrix.
subroutine, public vibrations_end(this)
integer pure function, public vibrations_get_atom(this, index)
subroutine calc_infrared()
calculate infrared intensities
subroutine build_ionic_dyn_matrix()
Computes the ionic contribution to the dynamical matrix.
Class describing the electron system.
Describes mesh distribution to nodes.
Container class for lists of system_oct_m::system_t.