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
135 if (sys%kpoints%use_symmetries)
then
136 call messages_experimental(
"CalculationMode = vib_modes with k-points symmetries", namespace=sys%namespace)
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)
152 call parse_variable(sys%namespace,
'CalcNormalModeWfs', .false., normal_mode_wfs)
184 call gs_restart%end()
186 message(1) =
"Previous gs calculation is required."
191 if (sys%space%is_periodic() .and. do_infrared)
then
192 message(1) =
"Reading kdotp wavefunctions for periodic directions."
197 message(1) =
"Unable to read kdotp wavefunctions."
198 message(2) =
"Previous kdotp calculation required."
202 do idir = 1, sys%space%periodic_dim
208 call kdotp_restart%open_dir(
wfs_tag_sigma(sys%namespace, str_tmp, 1), ierr)
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))
213 call kdotp_restart%close_dir()
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."
221 call kdotp_restart%end()
224 message(1) =
'Info: Setting up Hamiltonian for linear response.'
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, &
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."
237 call vibrations_init(vib, ions%space, ions%natoms, ions%mass,
"lr", sys%namespace)
241 if (do_infrared)
then
242 call born_charges_init(born, sys%namespace, ions%natoms, st%val_charge, st%qtot, ndim)
263 if (fromscratch)
then
270 if (start_mode == 1)
call restart_dump%rm(
'restart')
273 do imat = 1, start_mode - 1
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))
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))
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))
296 do imat = start_mode, vib%num_modes
300 write(
message(1),
'(a,i5,a,a1,a)') &
301 "Calculating response to displacement of atom ", iatom,
" in ",
index2axis(idir),
"-direction."
307 if (.not. fromscratch)
then
308 message(1) =
"Loading restart wavefunctions for linear response."
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))
316 message(1) =
"Unable to read response wavefunctions from '"//&
320 call restart_load%close_dir()
323 call pert%setup_atom(iatom)
324 call pert%setup_dir(idir)
326 if (sys%hm%ep%nlcc)
then
331 drho_core(1:gr%np, 1:st%d%nspin) =
m_zero
332 do ispin = 1, st%d%spin_channels
333 drho_core(1:gr%np, ispin) = -grad_rho_core(1:gr%np, idir) / st%d%spin_channels
336 lr_rho = drho_core, exclude_hartree = .
true.)
337 call pert%set_nlcc_response(dvxc_bare(:, :, 1))
342 safe_allocate(force_deriv(1:ndim, 1:natoms))
345 call dsternheimer_solve(sh, sys%namespace, sys%space, sys%gr, sys%kpoints, sys%st, sys%hm, sys%mc, &
348 if (sys%hm%ep%nlcc)
then
351 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)
353 lr_rho = ddrho_tot, exclude_hartree = .
true.)
354 call dforces_derivative(gr, sys%namespace, sys%space, ions, sys%hm%ep, st, sys%kpoints, lr(1), lr(1), force_deriv, &
355 sys%hm%lda_u_level, vxc_response = ddvxc_resp(:, :, 1))
357 call dforces_derivative(gr, sys%namespace, sys%space, ions, sys%hm%ep, st, sys%kpoints, lr(1), lr(1), force_deriv, &
363 call zsternheimer_solve(sh, sys%namespace, sys%space, sys%gr, sys%kpoints, sys%st, sys%hm, sys%mc, &
366 if (sys%hm%ep%nlcc)
then
367 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)
369 lr_rho = zdrho_tot, exclude_hartree = .
true.)
370 call zforces_derivative(gr, sys%namespace, sys%space, ions, sys%hm%ep, st, sys%kpoints, lr(1), lr(1), force_deriv, &
371 sys%hm%lda_u_level, vxc_response = zdvxc_resp(:, :, 1))
373 call zforces_derivative(gr, sys%namespace, sys%space, ions, sys%hm%ep, st, sys%kpoints, lr(1), lr(1), force_deriv, &
379 do jmat = 1, vib%num_modes
380 if (.not. symmetrize .and. jmat < imat)
then
381 vib%dyn_matrix(jmat, imat) = vib%dyn_matrix(imat, jmat)
388 vib%dyn_matrix(jmat, imat) = vib%dyn_matrix(jmat, imat) + real(force_deriv(jdir, jatom), real64)
391 safe_deallocate_a(force_deriv)
395 if (do_infrared)
then
403 iunit_restart = restart_dump%open(
'restart', position=
'append')
405 do jmat = 1, vib%num_modes
406 write(line(1), *) jmat, imat, vib%dyn_matrix(jmat, imat)
407 call restart_dump%write(iunit_restart, line, 1, ierr)
409 message(1) =
"Could not write restart information."
413 write(line(1), *) imat, (vib%infrared(imat, idir), idir = 1, ndim)
414 call restart_dump%write(iunit_restart, line, 1, ierr)
416 message(1) =
"Could not write restart information."
419 call restart_dump%close(iunit_restart)
425 safe_deallocate_p(pert)
427 safe_deallocate_a(grad_rho_core)
428 safe_deallocate_a(drho_core)
429 safe_deallocate_a(dvxc_bare)
430 safe_deallocate_a(ddrho_tot)
431 safe_deallocate_a(ddvxc_resp)
432 safe_deallocate_a(zdrho_tot)
433 safe_deallocate_a(zdvxc_resp)
440 if (do_infrared)
then
442 message(1) =
"Cannot calculate infrared intensities for periodic system with smearing (i.e. without a gap)."
454 if (normal_mode_wfs)
then
455 message(1) =
"Calculating response wavefunctions for normal modes."
472 if (sys%space%is_periodic() .and. do_infrared)
then
473 do idir = 1, sys%space%periodic_dim
477 call restart_load%end()
478 call restart_dump%end()
491 real(real64) :: term, weight, xi(1:ndim), dx(1:ndim), r2
495 assert(.not. ions%space%is_periodic())
497 vib%dyn_matrix(:,:) =
m_zero
500 xi = ions%pos(:, iatom)
503 if(iatom == jatom) cycle
505 dx = xi - ions%pos(:, jatom)
506 r2 = dot_product(dx, dx)
508 weight = ions%charge(iatom) * ions%charge(jatom) /(
sqrt(r2)**3)
513 term = weight * (
ddelta(idir, jdir) -
m_three*dx(idir)*dx(jdir)/r2)
535 real(real64) :: lir(1:sys%space%dim+1)
545 write(iunit_ir,
'(a14)', advance =
'no')
'<' //
index2axis(idir) //
'> [e]'
547 write(iunit_ir,
'(a14)')
'average [e]'
556 lir(jdir) = dot_product(vib%infrared(:, jdir), vib%normal_mode(:, imat))
560 lir(ndim+1) = norm2(lir(1:ndim))/
sqrt(real(ndim, real64) )
577 integer :: imat, idir, iatom
581 do imat = 1, vib%num_modes
584 born%charge(1:vib%ndim, idir, iatom) = -vib%infrared(imat, 1:vib%ndim)
592 character(len=100) function phn_rho_tag(iatom, dir)
result(str)
593 integer,
intent(in) :: iatom, dir
597 write(str,
'(a,i4.4,a,i1)')
'phn_rho_', iatom,
'_', dir
605 character(len=100) function phn_wfs_tag(iatom, dir)
result(str)
606 integer,
intent(in) :: iatom, dir
610 write(str,
'(a,i4.4,a,a)')
"phn_wfs_", iatom,
"_",
index2axis(dir)
619 integer,
intent(in) :: inm
623 write(str,
'(a,i5.5)')
"phn_nm_wfs_", inm
634 type(
ions_t),
intent(in) :: ions
635 class(
mesh_t),
intent(in) :: mesh
638 integer :: iunit, iatom, idir, imat, jmat
639 real(real64),
allocatable :: forces(:,:)
640 character(len=2) :: suffix
650 write(iunit,
'(a,i6)')
'ANIMSTEPS ', this%num_modes
651 safe_allocate(forces(1:ions%space%dim, 1:ions%natoms))
652 do imat = 1, this%num_modes
653 do jmat = 1, this%num_modes
656 forces(idir, iatom) = this%normal_mode(jmat, imat)
658 call write_xsf_geometry(iunit, ions%space, ions%latt, ions%pos, ions%atom, mesh, forces = forces, index = imat)
660 safe_deallocate_a(forces)
671 integer,
intent(out) :: start_mode
673 integer :: iunit, ierr, imode, jmode, imode_read, jmode_read
674 character(len=120) :: line(1)
678 iunit = restart%open(
'restart')
679 if (iunit /= -1)
then
680 imode_loop:
do imode = 1, vib%num_modes
681 do jmode = 1, vib%num_modes
682 call restart%read(iunit, line, 1, ierr)
683 if (ierr /= 0)
exit imode_loop
684 read(line(1), fmt=*, iostat=ierr) jmode_read, imode_read, vib%dyn_matrix(jmode, imode)
685 if (imode_read /= imode)
then
686 write(
message(1),
'(a,i9,a,i9)')
"Corruption of restart data: row ", imode,
" is labeled as ", imode_read
689 if (jmode_read /= jmode)
then
690 write(
message(1),
'(a,i9,a,i9)')
"Corruption of restart data: column ", jmode,
" is labeled as ", jmode_read
695 call restart%read(iunit, line, 1, ierr)
698 start_mode = imode + 1
700 read(line(1), fmt=*, iostat=ierr) imode_read, vib%infrared(imode, 1:vib%ndim)
701 if (imode_read /= imode)
then
702 write(
message(1),
'(a,i9,a,i9)')
"Corruption of restart data: infrared row ", imode,
" is labeled as ", imode_read
707 write(
message(1),
'(a,i9,a,i9)')
'Info: Read saved dynamical-matrix rows for ', &
708 start_mode - 1,
' modes out of ', vib%num_modes
711 call restart%close(iunit)
715 message(1) =
"Could not open restart file 'restart'. Starting from scratch."
722#include "complex.F90"
723#include "phonons_lr_inc.F90"
728#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_experimental(name, 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.