32 use,
intrinsic :: iso_fortran_env
77 class(*),
intent(inout) :: system
78 logical,
intent(in) :: from_scratch
84 message(1) =
"CalculationMode = vib_modes not implemented for multi-system calculations"
95 type(electrons_t),
target,
intent(inout) :: sys
96 logical,
intent(in) :: fromscratch
98 type(sternheimer_t) :: sh
99 type(lr_t) :: lr(1:1), kdotp_lr(sys%space%dim)
100 type(vibrations_t) :: vib
101 class(perturbation_ionic_t),
pointer :: pert
103 type(ions_t),
pointer :: ions
104 type(states_elec_t),
pointer :: st
105 type(grid_t),
pointer :: gr
107 integer :: natoms, ndim, iatom, idir, jatom, jdir, imat, jmat, iunit_restart, ierr, start_mode
108 complex(real64),
allocatable :: force_deriv(:,:)
109 character(len=80) :: str_tmp
110 character(len=300) :: line(1)
111 type(born_charges_t) :: born
112 logical :: normal_mode_wfs, do_infrared, symmetrize
113 type(restart_t) :: restart_load, restart_dump, kdotp_restart, gs_restart
123 if (sys%hm%pcm%run_pcm)
then
127 if (sys%space%is_periodic())
then
131 if (sys%hm%ep%nlcc)
then
132 call messages_not_implemented(
'linear-response vib_modes with non-linear core corrections', namespace=sys%namespace)
144 call parse_variable(sys%namespace,
'CalcNormalModeWfs', .false., normal_mode_wfs)
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
202 call states_elec_load(kdotp_restart, sys%namespace, sys%space, sys%st, sys%gr, sys%kpoints, ierr, lr=kdotp_lr(idir))
207 message(1) =
"Unable to read kdotp wavefunctions from '"//trim(
wfs_tag_sigma(sys%namespace, str_tmp, 1))//
"'."
208 message(2) =
"Previous kdotp calculation required."
215 message(1) =
'Info: Setting up Hamiltonian for linear response.'
218 call v_ks_h_setup(sys%namespace, sys%space, sys%gr, sys%ions, sys%ext_partners, sys%st, sys%ks, sys%hm)
219 call sternheimer_init(sh, sys%namespace, sys%space, sys%gr, sys%st, sys%hm, sys%ks%xc, sys%mc, &
222 call vibrations_init(vib, ions%space, ions%natoms, ions%mass,
"lr", sys%namespace)
226 if (do_infrared)
then
227 call born_charges_init(born, sys%namespace, ions%natoms, st%val_charge, st%qtot, ndim)
248 if (fromscratch)
then
255 if (start_mode == 1)
call restart_rm(restart_dump,
'restart')
258 do imat = 1, start_mode - 1
268 do imat = start_mode, vib%num_modes
272 write(
message(1),
'(a,i5,a,a1,a)') &
273 "Calculating response to displacement of atom ", iatom,
" in ",
index2axis(idir),
"-direction."
279 if (.not. fromscratch)
then
280 message(1) =
"Loading restart wavefunctions for linear response."
284 call states_elec_load(restart_load, sys%namespace, sys%space, st, sys%gr, sys%kpoints, ierr, lr = lr(1))
287 message(1) =
"Unable to read response wavefunctions from '"//&
294 call pert%setup_atom(iatom)
295 call pert%setup_dir(idir)
299 safe_allocate(force_deriv(1:ndim, 1:natoms))
302 call dsternheimer_solve(sh, sys%namespace, sys%space, sys%gr, sys%kpoints, sys%st, sys%hm, sys%mc, &
305 call dforces_derivative(gr, sys%namespace, sys%space, ions, sys%hm%ep, st, sys%kpoints, lr(1), lr(1), force_deriv, &
310 call zsternheimer_solve(sh, sys%namespace, sys%space, sys%gr, sys%kpoints, sys%st, sys%hm, sys%mc, &
313 call zforces_derivative(gr, sys%namespace, sys%space, ions, sys%hm%ep, st, sys%kpoints, lr(1), lr(1), force_deriv, &
318 do jmat = 1, vib%num_modes
319 if (.not. symmetrize .and. jmat < imat)
then
320 vib%dyn_matrix(jmat, imat) = vib%dyn_matrix(imat, jmat)
327 vib%dyn_matrix(jmat, imat) = vib%dyn_matrix(jmat, imat) + real(force_deriv(jdir, jatom), real64)
330 safe_deallocate_a(force_deriv)
334 if (do_infrared)
then
342 iunit_restart =
restart_open(restart_dump,
'restart', position=
'append')
344 do jmat = 1, vib%num_modes
345 write(line(1), *) jmat, imat, vib%dyn_matrix(jmat, imat)
346 call restart_write(restart_dump, iunit_restart, line, 1, ierr)
348 message(1) =
"Could not write restart information."
352 write(line(1), *) imat, (vib%infrared(imat, idir), idir = 1, ndim)
353 call restart_write(restart_dump, iunit_restart, line, 1, ierr)
355 message(1) =
"Could not write restart information."
364 safe_deallocate_p(pert)
371 if (do_infrared)
then
373 message(1) =
"Cannot calculate infrared intensities for periodic system with smearing (i.e. without a gap)."
385 if (normal_mode_wfs)
then
386 message(1) =
"Calculating response wavefunctions for normal modes."
403 if (sys%space%is_periodic() .and. do_infrared)
then
404 do idir = 1, sys%space%periodic_dim
422 real(real64) :: term, weight, xi(1:ndim), dx(1:ndim), r2
426 assert(.not. ions%space%is_periodic())
428 vib%dyn_matrix(:,:) =
m_zero
431 xi = ions%pos(:, iatom)
434 if(iatom == jatom) cycle
436 dx = xi - ions%pos(:, jatom)
437 r2 = dot_product(dx, dx)
439 weight = ions%charge(iatom) * ions%charge(jatom) /(
sqrt(r2)**3)
444 term = weight * (
ddelta(idir, jdir) -
m_three*dx(idir)*dx(jdir)/r2)
466 real(real64) :: lir(1:sys%space%dim+1)
485 lir(jdir) = dot_product(vib%infrared(:, jdir), vib%normal_mode(:, imat))
489 lir(ndim+1) = norm2(lir(1:ndim))/
sqrt(real(ndim, real64) )
506 integer :: imat, idir, iatom
510 do imat = 1, vib%num_modes
513 born%charge(1:vib%ndim, idir, iatom) = -vib%infrared(imat, 1:vib%ndim)
521 character(len=100) function phn_rho_tag(iatom, dir)
result(str)
522 integer,
intent(in) :: iatom, dir
526 write(str,
'(a,i4.4,a,i1)')
'phn_rho_', iatom,
'_', dir
534 character(len=100) function phn_wfs_tag(iatom, dir)
result(str)
535 integer,
intent(in) :: iatom, dir
539 write(str,
'(a,i4.4,a,a)')
"phn_wfs_", iatom,
"_",
index2axis(dir)
548 integer,
intent(in) :: inm
552 write(str,
'(a,i5.5)')
"phn_nm_wfs_", inm
563 type(
ions_t),
intent(in) :: ions
564 class(
mesh_t),
intent(in) :: mesh
567 integer :: iunit, iatom, idir, imat, jmat
568 real(real64),
allocatable :: forces(:,:)
569 character(len=2) :: suffix
579 write(iunit,
'(a,i6)')
'ANIMSTEPS ', this%num_modes
580 safe_allocate(forces(1:ions%space%dim, 1:ions%natoms))
581 do imat = 1, this%num_modes
582 do jmat = 1, this%num_modes
585 forces(idir, iatom) = this%normal_mode(jmat, imat)
587 call write_xsf_geometry(iunit, ions%space, ions%latt, ions%pos, ions%atom, mesh, forces = forces, index = imat)
589 safe_deallocate_a(forces)
600 integer,
intent(out) :: start_mode
602 integer :: iunit, ierr, imode, jmode, imode_read, jmode_read
603 character(len=120) :: line(1)
609 imode_loop:
do imode = 1, vib%num_modes
610 do jmode = 1, vib%num_modes
612 if (ierr /= 0)
exit imode_loop
613 read(line(1), fmt=*, iostat=ierr) jmode_read, imode_read, vib%dyn_matrix(jmode, imode)
614 if (imode_read /= imode)
then
615 write(
message(1),
'(a,i9,a,i9)')
"Corruption of restart data: row ", imode,
" is labeled as ", imode_read
618 if (jmode_read /= jmode)
then
619 write(
message(1),
'(a,i9,a,i9)')
"Corruption of restart data: column ", jmode,
" is labeled as ", jmode_read
627 start_mode = imode + 1
629 read(line(1), fmt=*, iostat=ierr) imode_read, vib%infrared(imode, 1:vib%ndim)
630 if (imode_read /= imode)
then
631 write(
message(1),
'(a,i9,a,i9)')
"Corruption of restart data: infrared row ", imode,
" is labeled as ", imode_read
636 write(
message(1),
'(a,i9,a,i9)')
'Info: Read saved dynamical-matrix rows for ', &
637 start_mode - 1,
' modes out of ', vib%num_modes
644 message(1) =
"Could not open restart file 'restart'. Starting from scratch."
651#include "complex.F90"
652#include "phonons_lr_inc.F90"
657#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 zforces_derivative(gr, namespace, space, ions, ep, st, kpoints, lr, lr2, force_deriv, lda_u_level)
subroutine, public dforces_derivative(gr, namespace, space, ions, ep, st, kpoints, lr, lr2, force_deriv, lda_u_level)
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)
subroutine, public messages_info(no_lines, iunit, verbose_limit, stress, all_nodes, namespace)
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
logical function mpi_grp_is_root(grp)
Is the current MPI process of grpcomm, root.
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)
subroutine, public restart_read(restart, iunit, lines, nlines, ierr)
subroutine, public restart_close(restart, iunit)
Close a file previously opened with restart_open.
integer, parameter, public restart_kdotp
subroutine, public restart_rm(restart, name)
Remove directory or file "name" that is located inside the current restart directory.
integer, parameter, public restart_gs
subroutine, public restart_init(restart, namespace, data_type, type, mc, ierr, mesh, dir, exact)
Initializes a restart object.
integer, parameter, public restart_type_dump
subroutine, public restart_write(restart, iunit, lines, nlines, ierr)
integer, parameter, public restart_vib_modes
integer function, public restart_open(restart, filename, status, position, silent)
Open file "filename" found inside the current restart directory. Depending on the type of restart,...
subroutine, public restart_open_dir(restart, dirname, ierr)
Change the restart directory to dirname, where "dirname" is a subdirectory of the base restart direct...
integer, parameter, public restart_type_load
subroutine, public restart_end(restart)
subroutine, public restart_close_dir(restart)
Change back to the base directory. To be called after restart_open_dir.
logical pure function, public smear_is_semiconducting(this)
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, is_complex, packed)
subroutine, public states_elec_load(restart, namespace, space, st, mesh, kpoints, 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 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.
character(len=100) function, public wfs_tag_sigma(namespace, base_name, isigma)
subroutine, public sternheimer_init(this, namespace, space, gr, st, hm, xc, mc, wfs_are_cplx, set_ham_var, set_occ_response, set_last_occ_response, occ_response_by_sternheimer)
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)
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_system_t), public units_out
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.