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, &
203 sys%st%restart_fixed_occ, ierr=ierr, lr=kdotp_lr(idir))
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."
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%xc, sys%mc, &
223 call vibrations_init(vib, ions%space, ions%natoms, ions%mass,
"lr", sys%namespace)
227 if (do_infrared)
then
228 call born_charges_init(born, sys%namespace, ions%natoms, st%val_charge, st%qtot, ndim)
249 if (fromscratch)
then
256 if (start_mode == 1)
call restart_rm(restart_dump,
'restart')
259 do imat = 1, start_mode - 1
269 do imat = start_mode, vib%num_modes
273 write(
message(1),
'(a,i5,a,a1,a)') &
274 "Calculating response to displacement of atom ", iatom,
" in ",
index2axis(idir),
"-direction."
280 if (.not. fromscratch)
then
281 message(1) =
"Loading restart wavefunctions for linear response."
285 call states_elec_load(restart_load, sys%namespace, sys%space, st, sys%gr, sys%kpoints, &
286 sys%st%restart_fixed_occ, ierr=ierr, lr = lr(1))
289 message(1) =
"Unable to read response wavefunctions from '"//&
296 call pert%setup_atom(iatom)
297 call pert%setup_dir(idir)
301 safe_allocate(force_deriv(1:ndim, 1:natoms))
304 call dsternheimer_solve(sh, sys%namespace, sys%space, sys%gr, sys%kpoints, sys%st, sys%hm, sys%mc, &
307 call dforces_derivative(gr, sys%namespace, sys%space, ions, sys%hm%ep, st, sys%kpoints, lr(1), lr(1), force_deriv, &
312 call zsternheimer_solve(sh, sys%namespace, sys%space, sys%gr, sys%kpoints, sys%st, sys%hm, sys%mc, &
315 call zforces_derivative(gr, sys%namespace, sys%space, ions, sys%hm%ep, st, sys%kpoints, lr(1), lr(1), force_deriv, &
320 do jmat = 1, vib%num_modes
321 if (.not. symmetrize .and. jmat < imat)
then
322 vib%dyn_matrix(jmat, imat) = vib%dyn_matrix(imat, jmat)
329 vib%dyn_matrix(jmat, imat) = vib%dyn_matrix(jmat, imat) + real(force_deriv(jdir, jatom), real64)
332 safe_deallocate_a(force_deriv)
336 if (do_infrared)
then
344 iunit_restart =
restart_open(restart_dump,
'restart', position=
'append')
346 do jmat = 1, vib%num_modes
347 write(line(1), *) jmat, imat, vib%dyn_matrix(jmat, imat)
348 call restart_write(restart_dump, iunit_restart, line, 1, ierr)
350 message(1) =
"Could not write restart information."
354 write(line(1), *) imat, (vib%infrared(imat, idir), idir = 1, ndim)
355 call restart_write(restart_dump, iunit_restart, line, 1, ierr)
357 message(1) =
"Could not write restart information."
366 safe_deallocate_p(pert)
373 if (do_infrared)
then
375 message(1) =
"Cannot calculate infrared intensities for periodic system with smearing (i.e. without a gap)."
387 if (normal_mode_wfs)
then
388 message(1) =
"Calculating response wavefunctions for normal modes."
405 if (sys%space%is_periodic() .and. do_infrared)
then
406 do idir = 1, sys%space%periodic_dim
424 real(real64) :: term, weight, xi(1:ndim), dx(1:ndim), r2
428 assert(.not. ions%space%is_periodic())
430 vib%dyn_matrix(:,:) =
m_zero
433 xi = ions%pos(:, iatom)
436 if(iatom == jatom) cycle
438 dx = xi - ions%pos(:, jatom)
439 r2 = dot_product(dx, dx)
441 weight = ions%charge(iatom) * ions%charge(jatom) /(
sqrt(r2)**3)
446 term = weight * (
ddelta(idir, jdir) -
m_three*dx(idir)*dx(jdir)/r2)
468 real(real64) :: lir(1:sys%space%dim+1)
487 lir(jdir) = dot_product(vib%infrared(:, jdir), vib%normal_mode(:, imat))
491 lir(ndim+1) = norm2(lir(1:ndim))/
sqrt(real(ndim, real64) )
508 integer :: imat, idir, iatom
512 do imat = 1, vib%num_modes
515 born%charge(1:vib%ndim, idir, iatom) = -vib%infrared(imat, 1:vib%ndim)
523 character(len=100) function phn_rho_tag(iatom, dir)
result(str)
524 integer,
intent(in) :: iatom, dir
528 write(str,
'(a,i4.4,a,i1)')
'phn_rho_', iatom,
'_', dir
536 character(len=100) function phn_wfs_tag(iatom, dir)
result(str)
537 integer,
intent(in) :: iatom, dir
541 write(str,
'(a,i4.4,a,a)')
"phn_wfs_", iatom,
"_",
index2axis(dir)
550 integer,
intent(in) :: inm
554 write(str,
'(a,i5.5)')
"phn_nm_wfs_", inm
565 type(
ions_t),
intent(in) :: ions
566 class(
mesh_t),
intent(in) :: mesh
569 integer :: iunit, iatom, idir, imat, jmat
570 real(real64),
allocatable :: forces(:,:)
571 character(len=2) :: suffix
581 write(iunit,
'(a,i6)')
'ANIMSTEPS ', this%num_modes
582 safe_allocate(forces(1:ions%space%dim, 1:ions%natoms))
583 do imat = 1, this%num_modes
584 do jmat = 1, this%num_modes
587 forces(idir, iatom) = this%normal_mode(jmat, imat)
589 call write_xsf_geometry(iunit, ions%space, ions%latt, ions%pos, ions%atom, mesh, forces = forces, index = imat)
591 safe_deallocate_a(forces)
602 integer,
intent(out) :: start_mode
604 integer :: iunit, ierr, imode, jmode, imode_read, jmode_read
605 character(len=120) :: line(1)
610 if (iunit /= -1)
then
611 imode_loop:
do imode = 1, vib%num_modes
612 do jmode = 1, vib%num_modes
614 if (ierr /= 0)
exit imode_loop
615 read(line(1), fmt=*, iostat=ierr) jmode_read, imode_read, vib%dyn_matrix(jmode, imode)
616 if (imode_read /= imode)
then
617 write(
message(1),
'(a,i9,a,i9)')
"Corruption of restart data: row ", imode,
" is labeled as ", imode_read
620 if (jmode_read /= jmode)
then
621 write(
message(1),
'(a,i9,a,i9)')
"Corruption of restart data: column ", jmode,
" is labeled as ", jmode_read
629 start_mode = imode + 1
631 read(line(1), fmt=*, iostat=ierr) imode_read, vib%infrared(imode, 1:vib%ndim)
632 if (imode_read /= imode)
then
633 write(
message(1),
'(a,i9,a,i9)')
"Corruption of restart data: infrared row ", imode,
" is labeled as ", imode_read
638 write(
message(1),
'(a,i9,a,i9)')
'Info: Read saved dynamical-matrix rows for ', &
639 start_mode - 1,
' modes out of ', vib%num_modes
646 message(1) =
"Could not open restart file 'restart'. Starting from scratch."
653#include "complex.F90"
654#include "phonons_lr_inc.F90"
659#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)
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)
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, 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 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.