28 use,
intrinsic :: iso_fortran_env
68 class(perturbation_t),
pointer :: pert => null()
69 class(perturbation_t),
pointer :: pert2 => null()
71 real(real64),
allocatable :: eff_mass_inv(:,:,:,:)
73 real(real64),
allocatable :: velocity(:,:,:)
75 type(lr_t),
allocatable :: lr(:,:)
79 type(lr_t),
allocatable :: lr2(:,:,:)
83 integer :: occ_solution_method
84 real(real64) :: degen_thres
92 class(*),
intent(inout) :: system
93 logical,
intent(in) :: from_scratch
99 message(1) =
"CalculationMode = kdotp not implemented for multi-system calculations"
110 type(electrons_t),
intent(inout) :: sys
111 logical,
intent(in) :: fromScratch
113 type(kdotp_t) :: kdotp_vars
114 type(sternheimer_t) :: sh, sh2
115 logical :: calc_eff_mass, calc_2nd_order, complex_response
117 integer :: idir, idir2, ierr, pdim, ispin
118 character(len=100) :: str_tmp
119 real(real64) :: errornorm
120 type(restart_t) :: restart_load, restart_dump
122 class(perturbation_t),
pointer :: pert2
126 call messages_experimental(
"k.p perturbation and calculation of effective masses", namespace=sys%namespace)
128 if (sys%hm%pcm%run_pcm)
then
143 if (sys%kpoints%use_symmetries)
then
144 call messages_experimental(
"KPoints symmetries with CalculationMode = kdotp", namespace=sys%namespace)
147 pdim = sys%space%periodic_dim
149 if (.not. sys%space%is_periodic())
then
150 message(1) =
"k.p perturbation cannot be used for a finite system."
155 safe_allocate(kdotp_vars%lr(1, 1:pdim))
159 if (calc_2nd_order)
then
162 call kdotp_vars%pert2%setup_dir(1)
163 safe_allocate(kdotp_vars%lr2(1, 1:pdim, 1:pdim))
171 is_complex = complex_response)
174 message(1) =
"A previous gs calculation is required."
190 message(1) =
'Info: Setting up Hamiltonian for linear response.'
192 call v_ks_h_setup(sys%namespace, sys%space, sys%gr, sys%ions, sys%ext_partners, sys%st, sys%ks, sys%hm)
195 message(1) =
'Info: Using real wavefunctions.'
197 message(1) =
'Info: Using complex wavefunctions.'
206 safe_allocate(kdotp_vars%velocity(1:pdim, 1:sys%st%nst, 1:sys%st%nik))
207 call calc_band_velocity(sys%namespace, sys%space, sys%gr, sys%st, sys%hm, kdotp_vars%pert, &
208 kdotp_vars%velocity(:,:,:))
215 safe_deallocate_a(kdotp_vars%velocity)
219 call sternheimer_init(sh, sys%namespace, sys%space, sys%gr, sys%st, sys%hm, sys%ks%xc, sys%mc, complex_response, &
220 set_ham_var = 0, set_occ_response = (kdotp_vars%occ_solution_method == 0), &
221 set_last_occ_response = (kdotp_vars%occ_solution_method == 0), occ_response_by_sternheimer = .
true.)
223 if (calc_2nd_order)
then
224 call sternheimer_init(sh2, sys%namespace, sys%space, sys%gr, sys%st, sys%hm, sys%ks%xc, sys%mc, complex_response, &
225 set_ham_var = 0, set_occ_response = .false., set_last_occ_response = .false.)
229 call lr_init(kdotp_vars%lr(1, idir))
230 call lr_allocate(kdotp_vars%lr(1, idir), sys%st, sys%gr)
232 if (calc_2nd_order)
then
233 do idir2 = idir, pdim
234 call lr_init(kdotp_vars%lr2(1, idir, idir2))
235 call lr_allocate(kdotp_vars%lr2(1, idir, idir2), sys%st, sys%gr)
240 if (.not. fromscratch)
then
243 if (ierr == 0)
call states_elec_load(restart_load, sys%namespace, sys%space, sys%st, sys%gr, sys%kpoints, &
244 ierr, lr=kdotp_vars%lr(1, idir))
248 message(1) =
"Unable to read response wavefunctions from '"//trim(
wfs_tag_sigma(sys%namespace, str_tmp, 1))//
"'."
252 if (calc_2nd_order)
then
253 do idir2 = idir, pdim
257 call states_elec_load(restart_load, sys%namespace, sys%space, sys%st, sys%gr, sys%kpoints, &
258 ierr, lr=kdotp_vars%lr2(1, idir, idir2))
263 message(1) =
"Unable to read response wavefunctions from '"//trim(
wfs_tag_sigma(sys%namespace, str_tmp, 1))//
"'."
272 message(1) =
"Info: Calculating k.p linear response of ground-state wavefunctions."
274 kdotp_vars%converged = .
true.
278 write(
message(1),
'(3a)')
'Info: Calculating response for the ',
index2axis(idir), &
281 call kdotp_vars%pert%setup_dir(idir)
284 call dsternheimer_solve(sh, sys%namespace, sys%space, sys%gr, sys%kpoints, sys%st, sys%hm, sys%mc, &
285 kdotp_vars%lr(1:1, idir), 1,
m_zero, kdotp_vars%pert, restart_dump,
"",
kdotp_wfs_tag(idir), &
286 have_restart_rho = .false.)
287 if (kdotp_vars%occ_solution_method == 1)
then
288 call dkdotp_add_occ(sys%namespace, sys%space, sys%gr, sys%st, sys%hm, kdotp_vars%pert, &
289 kdotp_vars%lr(1, idir), kdotp_vars%degen_thres)
292 call zsternheimer_solve(sh, sys%namespace, sys%space, sys%gr, sys%kpoints, sys%st, sys%hm, sys%mc, &
293 kdotp_vars%lr(1:1, idir), 1,
m_zi * kdotp_vars%eta, kdotp_vars%pert, restart_dump,
"", &
295 if (kdotp_vars%occ_solution_method == 1)
then
296 call zkdotp_add_occ(sys%namespace, sys%space, sys%gr, sys%st, sys%hm, kdotp_vars%pert, &
297 kdotp_vars%lr(1, idir), kdotp_vars%degen_thres)
305 call doutput_lr(sys%outp, sys%namespace, sys%space,
kdotp_dir, sys%st, sys%gr, kdotp_vars%lr(1, idir), idir, 1, &
308 do ispin = 1, sys%st%d%nspin
309 errornorm =
hypot(errornorm,
dmf_nrm2(sys%gr, kdotp_vars%lr(1, idir)%ddl_rho(:, ispin)))
312 call zoutput_lr(sys%outp, sys%namespace, sys%space,
kdotp_dir, sys%st, sys%gr, kdotp_vars%lr(1, idir), idir, 1, &
315 do ispin = 1, sys%st%d%nspin
316 errornorm =
hypot(errornorm,
zmf_nrm2(sys%gr, kdotp_vars%lr(1, idir)%zdl_rho(:, ispin)))
320 write(
message(1),
'(a,g13.6)')
"Norm of relative density variation = ", errornorm / sys%st%qtot
323 if (calc_2nd_order)
then
325 do idir2 = idir, pdim
326 write(
message(1),
'(3a)')
'Info: Calculating second-order response in the ',
index2axis(idir2), &
330 call pert2%setup_dir(idir2)
334 sys%mc, kdotp_vars%lr(1:1, idir), kdotp_vars%lr(1:1, idir2), &
336 kdotp_vars%lr2(1:1, idir, idir2), kdotp_vars%pert2, restart_dump,
"",
kdotp_wfs_tag(idir, idir2), &
337 have_restart_rho = .false., have_exact_freq = .
true.)
340 sys%mc, kdotp_vars%lr(1:1, idir), kdotp_vars%lr(1:1, idir2), &
341 1,
m_zi * kdotp_vars%eta,
m_zi * kdotp_vars%eta, kdotp_vars%pert, pert2, &
342 kdotp_vars%lr2(1:1, idir, idir2), kdotp_vars%pert2, restart_dump,
"",
kdotp_wfs_tag(idir, idir2), &
343 have_restart_rho = .false., have_exact_freq = .
true.)
353 if (calc_eff_mass)
then
354 message(1) =
"Info: Calculating effective masses."
357 safe_allocate(kdotp_vars%eff_mass_inv(1:pdim, 1:pdim, 1:sys%st%nst, 1:sys%st%nik))
358 kdotp_vars%eff_mass_inv(:,:,:,:) =
m_zero
362 call dcalc_eff_mass_inv(sys%namespace, sys%space, sys%gr, sys%st, sys%hm, kdotp_vars%lr, &
363 kdotp_vars%pert, kdotp_vars%eff_mass_inv, kdotp_vars%degen_thres)
365 call zcalc_eff_mass_inv(sys%namespace, sys%space, sys%gr, sys%st, sys%hm, kdotp_vars%lr, &
366 kdotp_vars%pert, kdotp_vars%eff_mass_inv, kdotp_vars%degen_thres)
370 call kdotp_write_eff_mass(sys%st, sys%kpoints, kdotp_vars, sys%namespace, sys%space%periodic_dim)
372 safe_deallocate_a(kdotp_vars%eff_mass_inv)
379 if (calc_2nd_order)
then
380 do idir2 = idir, pdim
381 call lr_dealloc(kdotp_vars%lr2(1, idir, idir2))
389 deallocate(kdotp_vars%pert)
390 safe_deallocate_a(kdotp_vars%lr)
392 if (calc_2nd_order)
then
394 safe_deallocate_p(pert2)
395 deallocate(kdotp_vars%pert2)
396 safe_deallocate_a(kdotp_vars%lr2)
429 call parse_variable(sys%namespace,
'KdotPOccupiedSolutionMethod', 0, kdotp_vars%occ_solution_method)
432 namespace=sys%namespace)
444 kdotp_vars%degen_thres)
468 call parse_variable(sys%namespace,
'KdotPCalculateEffectiveMasses', .
true., calc_eff_mass)
479 call parse_variable(sys%namespace,
'KdotPCalcSecondOrder', .false., calc_2nd_order)
490 call kdotp_vars%pert%info()
494 if (kdotp_vars%occ_solution_method == 0)
then
495 message(1) =
'Occupied solution method: Sternheimer equation.'
497 message(1) =
'Occupied solution method: sum over states.'
513 integer,
intent(in) :: periodic_dim
514 real(real64),
intent(in) :: velocity(:,:,:)
517 character(len=80) :: filename, tmp
518 integer :: iunit, ik, ist, ik2, ispin, idir
524 write(filename,
'(a)')
kdotp_dir//
'velocity'
525 iunit =
io_open(trim(filename), namespace, action=
'write')
526 write(iunit,
'(a)')
'# Band velocities'
529 ispin = st%d%get_spin_index(ik)
530 ik2 = st%d%get_kpoint_index(ik)
533 write(iunit,
'(a,i1,a,a)')
'# spin = ', ispin,
', k-point = ', trim(tmp)
535 write(iunit,
'(a)',advance=
'no')
'# state energy '
536 do idir = 1, periodic_dim
537 write(iunit,
'(3a)',advance=
'no')
'vg(', trim(
index2axis(idir)),
') '
542 do idir = 1, periodic_dim
549 velocity(1:periodic_dim, ist, ik)
561 type(
kdotp_t),
intent(inout) :: kdotp_vars
563 integer,
intent(in) :: periodic_dim
565 character(len=80) :: filename, tmp
566 integer :: iunit, ik, ist, ik2, ispin
573 ispin = st%d%get_spin_index(ik)
574 ik2 = st%d%get_kpoint_index(ik)
577 write(filename,
'(3a, i1)')
kdotp_dir//
'kpoint_', trim(tmp),
'_', ispin
578 iunit =
io_open(trim(filename), namespace, action=
'write')
580 write(iunit,
'(a, i10)')
'# spin index = ', ispin
581 write(iunit,
'(a, i10)')
'# k-point index = ', ik2
582 write(iunit,
'(a, 99f12.8)')
'# k-point coordinates = ', kpoints%get_point(ik2)
583 if (.not. kdotp_vars%converged)
write(iunit,
'(a)')
"# WARNING: not converged"
586 write(iunit,
'(a)')
'# Inverse effective-mass tensors'
590 write(iunit,
'(a, a, a, f12.8, a, a)')
'State #', trim(tmp),
', Energy = ', &
596 write(iunit,
'(a)')
'# Effective-mass tensors'
600 write(iunit,
'(a, a, a, f12.8, a, a)')
'State #', trim(tmp),
', Energy = ', &
602 call lalg_inverse(periodic_dim, kdotp_vars%eff_mass_inv(:, :, ist, ik),
'dir')
615 real(real64),
intent(in) :: threshold
618 character(len=80) :: tmp
619 integer :: ik, ist, ist2, ik2, ispin
628 ispin = st%d%get_spin_index(ik)
629 ik2 = st%d%get_kpoint_index(ik)
632 write(
message(1),
'(3a, i1)')
'k-point ', trim(tmp),
', spin ', ispin
636 do while (ist <= st%nst)
640 write(
message(2),
'(a, a, a, f12.8, a, a)')
'State #', trim(tmp),
', Energy = ', &
645 do while (ist2 <= st%nst .and. &
646 abs(st%eigenval(min(ist2, st%nst), ik) - st%eigenval(ist, ik)) < threshold)
648 write(
message(1),
'(a, a, a, f12.8, a, a)')
'State #', trim(tmp),
', Energy = ', &
661 message(1) =
"Velocities and effective masses are not correct within degenerate subspaces."
668 character(len=12) pure function int2str(ii) result(str)
669 integer,
intent(in) :: ii
671 write(str,
'(i11)') ii
672 str = trim(adjustl(str))
double hypot(double __x, double __y) __attribute__((__nothrow__
real(real64), parameter, public m_zero
character(len= *), parameter, public kdotp_dir
complex(real64), parameter, public m_zi
real(real64), parameter, public m_epsilon
This module implements the underlying real-space grid.
subroutine, public io_close(iunit, grp)
subroutine, public io_mkdir(fname, namespace, parents)
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
subroutine, public calc_band_velocity(namespace, space, gr, st, hm, pert, velocity)
Computes the k-point and band-resolved velocity.
subroutine, public dkdotp_add_occ(namespace, space, gr, st, hm, pert, kdotp_lr, degen_thres)
add projection onto occupied states, by sum over states
subroutine, public zkdotp_add_occ(namespace, space, gr, st, hm, pert, kdotp_lr, degen_thres)
add projection onto occupied states, by sum over states
subroutine, public dcalc_eff_mass_inv(namespace, space, gr, st, hm, lr, pert, eff_mass_inv, degen_thres)
Computes the effective mass tensor.
character(len=100) function, public kdotp_wfs_tag(dir, dir2)
subroutine, public zcalc_eff_mass_inv(namespace, space, gr, st, hm, lr, pert, eff_mass_inv, degen_thres)
Computes the effective mass tensor.
subroutine kdotp_write_band_velocity(st, periodic_dim, velocity, namespace)
subroutine kdotp_lr_run_legacy(sys, fromScratch)
subroutine kdotp_write_eff_mass(st, kpoints, kdotp_vars, namespace, periodic_dim)
subroutine kdotp_write_degeneracies(st, threshold, namespace)
subroutine, public kdotp_lr_run(system, from_scratch)
character(len=12) pure function, public int2str(ii)
A module to handle KS potential, without the external potential.
integer, parameter, public hartree_fock
integer, parameter, public generalized_kohn_sham_dft
subroutine, public lr_allocate(lr, st, mesh, allocate_rho)
subroutine, public lr_init(lr)
subroutine, public lr_dealloc(lr)
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
subroutine, public messages_print_with_emphasis(msg, iunit, namespace)
subroutine, public messages_not_implemented(feature, namespace)
character(len=512), private msg
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)
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.
this module contains the output system
subroutine, public zoutput_lr(outp, namespace, space, dir, st, mesh, lr, idir, isigma, ions, pert_unit)
subroutine, public doutput_lr(outp, namespace, space, dir, st, mesh, lr, idir, isigma, ions, pert_unit)
integer, parameter, public restart_kdotp
integer, parameter, public restart_gs
type(restart_data_t), dimension(restart_n_data_types) info
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_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.
logical function, public sternheimer_has_converged(this)
character(len=100) function, public wfs_tag_sigma(namespace, base_name, isigma)
subroutine, public dsternheimer_solve_order2(sh1, sh2, sh_2ndorder, namespace, space, gr, kpoints, st, hm, mc, lr1, lr2, nsigma, omega1, omega2, pert1, pert2, lr_2ndorder, pert_2ndorder, restart, rho_tag, wfs_tag, have_restart_rho, have_exact_freq, give_pert1psi2, give_dl_eig1)
subroutine, public zsternheimer_solve_order2(sh1, sh2, sh_2ndorder, namespace, space, gr, kpoints, st, hm, mc, lr1, lr2, nsigma, omega1, omega2, pert1, pert2, lr_2ndorder, pert_2ndorder, restart, rho_tag, wfs_tag, have_restart_rho, have_exact_freq, give_pert1psi2, give_dl_eig1)
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)
subroutine, public sternheimer_obsolete_variables(namespace, old_prefix, new_prefix)
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_system_t), public units_out
type(unit_system_t), public units_inp
the units systems for reading and writing
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.
subroutine, public output_tensor(tensor, ndim, unit, write_average, iunit, namespace)
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)
Class describing the electron system.
Container class for lists of system_oct_m::system_t.
The states_elec_t class contains all electronic wave functions.