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 do ispin = 1, st%d%nspin
332 drho_core(1:gr%np, ispin) = -grad_rho_core(1:gr%np, idir) / st%d%spin_channels
335 lr_rho = drho_core, exclude_hartree = .
true.)
336 call pert%set_nlcc_response(dvxc_bare(:, :, 1))
341 safe_allocate(force_deriv(1:ndim, 1:natoms))
344 call dsternheimer_solve(sh, sys%namespace, sys%space, sys%gr, sys%kpoints, sys%st, sys%hm, sys%mc, &
347 if (sys%hm%ep%nlcc)
then
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)
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))
356 call dforces_derivative(gr, sys%namespace, sys%space, ions, sys%hm%ep, st, sys%kpoints, lr(1), lr(1), force_deriv, &
362 call zsternheimer_solve(sh, sys%namespace, sys%space, sys%gr, sys%kpoints, sys%st, sys%hm, sys%mc, &
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)
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))
372 call zforces_derivative(gr, sys%namespace, sys%space, ions, sys%hm%ep, st, sys%kpoints, lr(1), lr(1), force_deriv, &
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)
387 vib%dyn_matrix(jmat, imat) = vib%dyn_matrix(jmat, imat) + real(force_deriv(jdir, jatom), real64)
390 safe_deallocate_a(force_deriv)
394 if (do_infrared)
then
402 iunit_restart = restart_dump%open(
'restart', position=
'append')
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)
408 message(1) =
"Could not write restart information."
412 write(line(1), *) imat, (vib%infrared(imat, idir), idir = 1, ndim)
413 call restart_dump%write(iunit_restart, line, 1, ierr)
415 message(1) =
"Could not write restart information."
418 call restart_dump%close(iunit_restart)
424 safe_deallocate_p(pert)
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)
439 if (do_infrared)
then
441 message(1) =
"Cannot calculate infrared intensities for periodic system with smearing (i.e. without a gap)."
453 if (normal_mode_wfs)
then
454 message(1) =
"Calculating response wavefunctions for normal modes."
471 if (sys%space%is_periodic() .and. do_infrared)
then
472 do idir = 1, sys%space%periodic_dim
476 call restart_load%end()
477 call restart_dump%end()
490 real(real64) :: term, weight, xi(1:ndim), dx(1:ndim), r2
494 assert(.not. ions%space%is_periodic())
496 vib%dyn_matrix(:,:) =
m_zero
499 xi = ions%pos(:, iatom)
502 if(iatom == jatom) cycle
504 dx = xi - ions%pos(:, jatom)
505 r2 = dot_product(dx, dx)
507 weight = ions%charge(iatom) * ions%charge(jatom) /(
sqrt(r2)**3)
512 term = weight * (
ddelta(idir, jdir) -
m_three*dx(idir)*dx(jdir)/r2)
534 real(real64) :: lir(1:sys%space%dim+1)
544 write(iunit_ir,
'(a14)', advance =
'no')
'<' //
index2axis(idir) //
'> [e]'
546 write(iunit_ir,
'(a14)')
'average [e]'
555 lir(jdir) = dot_product(vib%infrared(:, jdir), vib%normal_mode(:, imat))
559 lir(ndim+1) = norm2(lir(1:ndim))/
sqrt(real(ndim, real64) )
576 integer :: imat, idir, iatom
580 do imat = 1, vib%num_modes
583 born%charge(1:vib%ndim, idir, iatom) = -vib%infrared(imat, 1:vib%ndim)
591 character(len=100) function phn_rho_tag(iatom, dir)
result(str)
592 integer,
intent(in) :: iatom, dir
596 write(str,
'(a,i4.4,a,i1)')
'phn_rho_', iatom,
'_', dir
604 character(len=100) function phn_wfs_tag(iatom, dir)
result(str)
605 integer,
intent(in) :: iatom, dir
609 write(str,
'(a,i4.4,a,a)')
"phn_wfs_", iatom,
"_",
index2axis(dir)
618 integer,
intent(in) :: inm
622 write(str,
'(a,i5.5)')
"phn_nm_wfs_", inm
633 type(
ions_t),
intent(in) :: ions
634 class(
mesh_t),
intent(in) :: mesh
637 integer :: iunit, iatom, idir, imat, jmat
638 real(real64),
allocatable :: forces(:,:)
639 character(len=2) :: suffix
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
655 forces(idir, iatom) = this%normal_mode(jmat, imat)
657 call write_xsf_geometry(iunit, ions%space, ions%latt, ions%pos, ions%atom, mesh, forces = forces, index = imat)
659 safe_deallocate_a(forces)
670 integer,
intent(out) :: start_mode
672 integer :: iunit, ierr, imode, jmode, imode_read, jmode_read
673 character(len=120) :: line(1)
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
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
694 call restart%read(iunit, line, 1, ierr)
697 start_mode = imode + 1
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
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
710 call restart%close(iunit)
714 message(1) =
"Could not open restart file 'restart'. Starting from scratch."
721#include "complex.F90"
722#include "phonons_lr_inc.F90"
727#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.