28 use,
intrinsic :: iso_fortran_env
67 class(perturbation_t),
pointer :: pert => null()
68 class(perturbation_t),
pointer :: pert2 => null()
70 real(real64),
allocatable :: eff_mass_inv(:,:,:,:)
72 real(real64),
allocatable :: velocity(:,:,:)
74 type(lr_t),
allocatable :: lr(:,:)
78 type(lr_t),
allocatable :: lr2(:,:,:)
82 integer :: occ_solution_method
83 real(real64) :: degen_thres
91 class(*),
intent(inout) :: system
92 logical,
intent(in) :: from_scratch
98 message(1) =
"CalculationMode = kdotp not implemented for multi-system calculations"
109 type(electrons_t),
intent(inout) :: sys
110 logical,
intent(in) :: fromScratch
112 type(kdotp_t) :: kdotp_vars
113 type(sternheimer_t) :: sh, sh2
114 logical :: calc_eff_mass, calc_2nd_order, complex_response
116 integer :: idir, idir2, ierr, pdim, ispin
117 character(len=100) :: str_tmp
118 real(real64) :: errornorm
119 type(restart_t) :: restart_load, restart_dump
121 class(perturbation_t),
pointer :: pert2
125 call messages_experimental(
"k.p perturbation and calculation of effective masses", namespace=sys%namespace)
127 if (sys%hm%pcm%run_pcm)
then
142 if (sys%kpoints%use_symmetries)
then
143 call messages_experimental(
"KPoints symmetries with CalculationMode = kdotp", namespace=sys%namespace)
146 pdim = sys%space%periodic_dim
148 if (.not. sys%space%is_periodic())
then
149 message(1) =
"k.p perturbation cannot be used for a finite system."
154 safe_allocate(kdotp_vars%lr(1, 1:pdim))
158 if (calc_2nd_order)
then
161 call kdotp_vars%pert2%setup_dir(1)
162 safe_allocate(kdotp_vars%lr2(1, 1:pdim, 1:pdim))
170 is_complex = complex_response)
173 message(1) =
"A previous gs calculation is required."
189 message(1) =
'Info: Setting up Hamiltonian for linear response.'
191 call v_ks_h_setup(sys%namespace, sys%space, sys%gr, sys%ions, sys%ext_partners, sys%st, sys%ks, sys%hm)
194 message(1) =
'Info: Using real wavefunctions.'
196 message(1) =
'Info: Using complex wavefunctions.'
205 safe_allocate(kdotp_vars%velocity(1:pdim, 1:sys%st%nst, 1:sys%st%nik))
206 call calc_band_velocity(sys%namespace, sys%space, sys%gr, sys%st, sys%hm, kdotp_vars%pert, &
207 kdotp_vars%velocity(:,:,:))
214 safe_deallocate_a(kdotp_vars%velocity)
218 call sternheimer_init(sh, sys%namespace, sys%space, sys%gr, sys%st, sys%hm, sys%ks%xc, sys%mc, complex_response, &
219 set_ham_var = 0, set_occ_response = (kdotp_vars%occ_solution_method == 0), &
220 set_last_occ_response = (kdotp_vars%occ_solution_method == 0), occ_response_by_sternheimer = .
true.)
222 if (calc_2nd_order)
then
223 call sternheimer_init(sh2, sys%namespace, sys%space, sys%gr, sys%st, sys%hm, sys%ks%xc, sys%mc, complex_response, &
224 set_ham_var = 0, set_occ_response = .false., set_last_occ_response = .false.)
228 call lr_init(kdotp_vars%lr(1, idir))
229 call lr_allocate(kdotp_vars%lr(1, idir), sys%st, sys%gr)
231 if (calc_2nd_order)
then
232 do idir2 = idir, pdim
233 call lr_init(kdotp_vars%lr2(1, idir, idir2))
234 call lr_allocate(kdotp_vars%lr2(1, idir, idir2), sys%st, sys%gr)
239 if (.not. fromscratch)
then
242 if (ierr == 0)
call states_elec_load(restart_load, sys%namespace, sys%space, sys%st, sys%gr, sys%kpoints, &
243 ierr, lr=kdotp_vars%lr(1, idir))
247 message(1) =
"Unable to read response wavefunctions from '"//trim(
wfs_tag_sigma(sys%namespace, str_tmp, 1))//
"'."
251 if (calc_2nd_order)
then
252 do idir2 = idir, pdim
256 call states_elec_load(restart_load, sys%namespace, sys%space, sys%st, sys%gr, sys%kpoints, &
257 ierr, lr=kdotp_vars%lr2(1, idir, idir2))
262 message(1) =
"Unable to read response wavefunctions from '"//trim(
wfs_tag_sigma(sys%namespace, str_tmp, 1))//
"'."
271 message(1) =
"Info: Calculating k.p linear response of ground-state wavefunctions."
273 kdotp_vars%converged = .
true.
277 write(
message(1),
'(3a)')
'Info: Calculating response for the ',
index2axis(idir), &
280 call kdotp_vars%pert%setup_dir(idir)
283 call dsternheimer_solve(sh, sys%namespace, sys%space, sys%gr, sys%kpoints, sys%st, sys%hm, sys%mc, &
284 kdotp_vars%lr(1:1, idir), 1,
m_zero, kdotp_vars%pert, restart_dump,
"",
kdotp_wfs_tag(idir), &
285 have_restart_rho = .false.)
286 if (kdotp_vars%occ_solution_method == 1)
then
287 call dkdotp_add_occ(sys%namespace, sys%space, sys%gr, sys%st, sys%hm, kdotp_vars%pert, &
288 kdotp_vars%lr(1, idir), kdotp_vars%degen_thres)
291 call zsternheimer_solve(sh, sys%namespace, sys%space, sys%gr, sys%kpoints, sys%st, sys%hm, sys%mc, &
292 kdotp_vars%lr(1:1, idir), 1,
m_zi * kdotp_vars%eta, kdotp_vars%pert, restart_dump,
"", &
294 if (kdotp_vars%occ_solution_method == 1)
then
295 call zkdotp_add_occ(sys%namespace, sys%space, sys%gr, sys%st, sys%hm, kdotp_vars%pert, &
296 kdotp_vars%lr(1, idir), kdotp_vars%degen_thres)
304 call doutput_lr(sys%outp, sys%namespace, sys%space,
kdotp_dir, sys%st, sys%gr, kdotp_vars%lr(1, idir), idir, 1, &
307 do ispin = 1, sys%st%d%nspin
308 errornorm =
hypot(errornorm,
dmf_nrm2(sys%gr, kdotp_vars%lr(1, idir)%ddl_rho(:, ispin)))
311 call zoutput_lr(sys%outp, sys%namespace, sys%space,
kdotp_dir, sys%st, sys%gr, kdotp_vars%lr(1, idir), idir, 1, &
314 do ispin = 1, sys%st%d%nspin
315 errornorm =
hypot(errornorm,
zmf_nrm2(sys%gr, kdotp_vars%lr(1, idir)%zdl_rho(:, ispin)))
319 write(
message(1),
'(a,g13.6)')
"Norm of relative density variation = ", errornorm / sys%st%qtot
322 if (calc_2nd_order)
then
324 do idir2 = idir, pdim
325 write(
message(1),
'(3a)')
'Info: Calculating second-order response in the ',
index2axis(idir2), &
329 call pert2%setup_dir(idir2)
333 sys%mc, kdotp_vars%lr(1:1, idir), kdotp_vars%lr(1:1, idir2), &
335 kdotp_vars%lr2(1:1, idir, idir2), kdotp_vars%pert2, restart_dump,
"",
kdotp_wfs_tag(idir, idir2), &
336 have_restart_rho = .false., have_exact_freq = .
true.)
339 sys%mc, kdotp_vars%lr(1:1, idir), kdotp_vars%lr(1:1, idir2), &
340 1,
m_zi * kdotp_vars%eta,
m_zi * kdotp_vars%eta, kdotp_vars%pert, pert2, &
341 kdotp_vars%lr2(1:1, idir, idir2), kdotp_vars%pert2, restart_dump,
"",
kdotp_wfs_tag(idir, idir2), &
342 have_restart_rho = .false., have_exact_freq = .
true.)
352 if (calc_eff_mass)
then
353 message(1) =
"Info: Calculating effective masses."
356 safe_allocate(kdotp_vars%eff_mass_inv(1:pdim, 1:pdim, 1:sys%st%nst, 1:sys%st%nik))
357 kdotp_vars%eff_mass_inv(:,:,:,:) =
m_zero
361 call dcalc_eff_mass_inv(sys%namespace, sys%space, sys%gr, sys%st, sys%hm, kdotp_vars%lr, &
362 kdotp_vars%pert, kdotp_vars%eff_mass_inv, kdotp_vars%degen_thres)
364 call zcalc_eff_mass_inv(sys%namespace, sys%space, sys%gr, sys%st, sys%hm, kdotp_vars%lr, &
365 kdotp_vars%pert, kdotp_vars%eff_mass_inv, kdotp_vars%degen_thres)
369 call kdotp_write_eff_mass(sys%st, sys%kpoints, kdotp_vars, sys%namespace, sys%space%periodic_dim)
371 safe_deallocate_a(kdotp_vars%eff_mass_inv)
378 if (calc_2nd_order)
then
379 do idir2 = idir, pdim
380 call lr_dealloc(kdotp_vars%lr2(1, idir, idir2))
388 deallocate(kdotp_vars%pert)
389 safe_deallocate_a(kdotp_vars%lr)
391 if (calc_2nd_order)
then
393 safe_deallocate_p(pert2)
394 deallocate(kdotp_vars%pert2)
395 safe_deallocate_a(kdotp_vars%lr2)
428 call parse_variable(sys%namespace,
'KdotPOccupiedSolutionMethod', 0, kdotp_vars%occ_solution_method)
431 namespace=sys%namespace)
443 kdotp_vars%degen_thres)
467 call parse_variable(sys%namespace,
'KdotPCalculateEffectiveMasses', .
true., calc_eff_mass)
478 call parse_variable(sys%namespace,
'KdotPCalcSecondOrder', .false., calc_2nd_order)
489 call kdotp_vars%pert%info()
493 if (kdotp_vars%occ_solution_method == 0)
then
494 message(1) =
'Occupied solution method: Sternheimer equation.'
496 message(1) =
'Occupied solution method: sum over states.'
512 integer,
intent(in) :: periodic_dim
513 real(real64),
intent(in) :: velocity(:,:,:)
516 character(len=80) :: filename, tmp
517 integer :: iunit, ik, ist, ik2, ispin, idir
523 write(filename,
'(a)')
kdotp_dir//
'velocity'
524 iunit =
io_open(trim(filename), namespace, action=
'write')
525 write(iunit,
'(a)')
'# Band velocities'
528 ispin = st%d%get_spin_index(ik)
529 ik2 = st%d%get_kpoint_index(ik)
532 write(iunit,
'(a,i1,a,a)')
'# spin = ', ispin,
', k-point = ', trim(tmp)
534 write(iunit,
'(a)',advance=
'no')
'# state energy '
535 do idir = 1, periodic_dim
536 write(iunit,
'(3a)',advance=
'no')
'vg(', trim(
index2axis(idir)),
') '
541 do idir = 1, periodic_dim
548 velocity(1:periodic_dim, ist, ik)
560 type(
kdotp_t),
intent(inout) :: kdotp_vars
562 integer,
intent(in) :: periodic_dim
564 character(len=80) :: filename, tmp
565 integer :: iunit, ik, ist, ik2, ispin
572 ispin = st%d%get_spin_index(ik)
573 ik2 = st%d%get_kpoint_index(ik)
576 write(filename,
'(3a, i1)')
kdotp_dir//
'kpoint_', trim(tmp),
'_', ispin
577 iunit =
io_open(trim(filename), namespace, action=
'write')
579 write(iunit,
'(a, i10)')
'# spin index = ', ispin
580 write(iunit,
'(a, i10)')
'# k-point index = ', ik2
581 write(iunit,
'(a, 99f12.8)')
'# k-point coordinates = ', kpoints%get_point(ik2)
582 if (.not. kdotp_vars%converged)
write(iunit,
'(a)')
"# WARNING: not converged"
585 write(iunit,
'(a)')
'# Inverse effective-mass tensors'
589 write(iunit,
'(a, a, a, f12.8, a, a)')
'State #', trim(tmp),
', Energy = ', &
595 write(iunit,
'(a)')
'# Effective-mass tensors'
599 write(iunit,
'(a, a, a, f12.8, a, a)')
'State #', trim(tmp),
', Energy = ', &
601 call lalg_inverse(periodic_dim, kdotp_vars%eff_mass_inv(:, :, ist, ik),
'dir')
614 real(real64),
intent(in) :: threshold
617 character(len=80) :: tmp
618 integer :: ik, ist, ist2, ik2, ispin
627 ispin = st%d%get_spin_index(ik)
628 ik2 = st%d%get_kpoint_index(ik)
631 write(
message(1),
'(3a, i1)')
'k-point ', trim(tmp),
', spin ', ispin
635 do while (ist <= st%nst)
639 write(
message(2),
'(a, a, a, f12.8, a, a)')
'State #', trim(tmp),
', Energy = ', &
644 do while (ist2 <= st%nst .and. &
645 abs(st%eigenval(min(ist2, st%nst), ik) - st%eigenval(ist, ik)) < threshold)
647 write(
message(1),
'(a, a, a, f12.8, a, a)')
'State #', trim(tmp),
', Energy = ', &
660 message(1) =
"Velocities and effective masses are not correct within degenerate subspaces."
667 character(len=12) pure function int2str(ii) result(str)
668 integer,
intent(in) :: ii
670 write(str,
'(i11)') ii
671 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.
integer, parameter, public generalized_kohn_sham_dft
integer, parameter, public hartree_fock
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)
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)
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)
subroutine, public messages_experimental(name, 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.