33 use,
intrinsic :: iso_fortran_env
68 integer,
public,
parameter :: &
69 XC_INV_METHOD_TWO_PARTICLE = 1, &
75 integer,
public,
parameter :: &
76 XC_KS_INVERSION_NONE = 1, &
81 integer,
public,
parameter :: &
82 XC_ASYMPTOTICS_NONE = 1, &
85 integer,
parameter :: &
90 integer,
public :: method
91 integer :: level = xc_ks_inversion_none
92 integer :: asymptotics
93 real(real64),
allocatable :: vhxc_previous_step(:,:)
94 type(states_elec_t),
public :: aux_st
95 type(hamiltonian_elec_t) :: aux_hm
96 type(eigensolver_t),
public :: eigensolver
99 type(partner_list_t) :: ext_partners
101 integer,
public :: max_iter
109 type(xc_ks_inversion_t),
intent(inout) :: ks_inv
110 type(namespace_t),
intent(in) :: namespace
111 type(grid_t),
intent(inout) :: gr
112 type(ions_t),
intent(inout) :: ions
113 type(states_elec_t),
intent(in) :: st
114 type(xc_t),
intent(in) :: xc
115 type(multicomm_t),
intent(in) :: mc
116 class(space_t),
intent(in) :: space
117 type(kpoints_t),
intent(in) :: kpoints
119 class(lasers_t),
pointer :: lasers
123 if(gr%parallel_in_domains)
then
147 if (ks_inv%method < xc_inv_method_two_particle &
179 call parse_variable(namespace,
'KSInversionAsymptotics', xc_asymptotics_none, ks_inv%asymptotics)
180 if (ks_inv%asymptotics /= xc_asymptotics_none .and. space%dim > 1)
then
189 if (ks_inv%level /= xc_ks_inversion_none)
then
203 if(lasers%no_lasers > 0)
then
204 call ks_inv%ext_partners%add(lasers)
210 call hamiltonian_elec_init(ks_inv%aux_hm, namespace, space, gr, ions, ks_inv%ext_partners, ks_inv%aux_st, &
212 call eigensolver_init(ks_inv%eigensolver, namespace, gr, ks_inv%aux_st, mc, space)
228 if (ks_inv%level /= xc_ks_inversion_none)
then
234 call iter%start(ks_inv%ext_partners)
235 do while (iter%has_next())
236 partner => iter%get_next()
237 safe_deallocate_p(partner)
239 call ks_inv%ext_partners%empty()
250 integer,
optional,
intent(in) :: iunit
251 type(
namespace_t),
optional,
intent(in) :: namespace
253 if (ks_inversion%level == xc_ks_inversion_none)
return
269 subroutine invertks_2part(ks_inv, target_rho, nspin, aux_hm, gr, st, eigensolver, &
270 namespace, space, ext_partners)
272 real(real64),
intent(in) :: target_rho(:,:)
273 integer,
intent(in) :: nspin
275 type(
grid_t),
intent(in) :: gr
279 class(
space_t),
intent(in) :: space
282 integer :: asym1, asym2, ip, ispin
284 real(real64) :: rr, shift
285 real(real64),
parameter :: smalldensity = 5e-12_real64
286 real(real64),
allocatable :: sqrtrho(:,:), laplace(:,:), vks(:,:), x_shifted(:)
291 assert(.not. gr%parallel_in_domains)
295 assert(space%periodic_dim == 0)
298 assert(space%dim == 1)
302 safe_allocate(sqrtrho(1:gr%np_part, 1:nspin))
303 safe_allocate(vks(1:np, 1:nspin))
304 safe_allocate(laplace(1:gr%np, 1:nspin))
306 if (any(target_rho(:,:) < -
m_epsilon))
then
307 write(
message(1),*)
"Target density has negative points. min value = ", minval(target_rho(:,:))
316 sqrtrho(ip, ispin) =
sqrt(target_rho(ip, ispin))
323 if (space%dim == 1)
then
328 call spline_fit(gr%np, gr%x(:, 1), sqrtrho(:, ispin), spl)
338 safe_deallocate_a(x_shifted)
342 laplace(ip, ispin) =
spline_eval(lapl_spl, gr%x(ip, 1))
368 if (target_rho(ip, ispin) < smalldensity)
then
369 vks(ip, ispin) = aux_hm%ep%vpsl(ip) + aux_hm%vhartree(ip)
372 if (target_rho(np-ip+1, ispin) < smalldensity)
then
373 vks(np-ip+1, ispin) = aux_hm%ep%vpsl(np-ip+1) + aux_hm%vhartree(np-ip+1)
381 do ip = asym1+1, asym2-1
382 vks(ip, ispin) =
m_half * laplace(ip, ispin) / (sqrtrho(ip, ispin) +
m_tiny)
388 aux_hm%vxc(ip, ispin) = vks(ip, ispin) - aux_hm%ep%vpsl(ip) - aux_hm%vhartree(ip)
399 aux_hm%vxc(ip, ispin) = -st%qtot/
sqrt(rr**2 +
m_one)
404 call mesh_r(gr, asym1+1, rr)
405 shift = aux_hm%vxc(asym1+1, ispin) + st%qtot/
sqrt(rr**2 +
m_one)
408 do ip = asym1+1, asym2-1
409 aux_hm%vxc(ip, ispin) = aux_hm%vxc(ip, ispin) - shift
414 call mesh_r(gr, asym2-1, rr)
415 shift = aux_hm%vxc(asym2-1, ispin) + st%qtot/
sqrt(rr**2 +
m_one)
420 aux_hm%vxc(ip, ispin) = aux_hm%vxc(ip, ispin) - shift
427 aux_hm%vxc(ip, ispin) = -st%qtot/
sqrt(rr**2 +
m_one)
435 if (ks_inv%asymptotics == xc_asymptotics_none)
then
442 shift = aux_hm%vxc(asym1+1, ispin)
444 do ip = asym1+1, asym2-1
445 aux_hm%vxc(ip, ispin) = aux_hm%vxc(ip, ispin) - shift
449 shift = aux_hm%vxc(asym2-1, ispin)
452 aux_hm%vxc(ip, ispin) = aux_hm%vxc(ip, ispin) - shift
460 aux_hm%vhxc(1:gr%np, ispin) = aux_hm%vxc(1:gr%np, ispin) + aux_hm%vhartree(1:gr%np)
466 safe_deallocate_a(sqrtrho)
467 safe_deallocate_a(laplace)
468 safe_deallocate_a(vks)
476 type(
grid_t),
intent(in) :: gr
477 class(
space_t),
intent(in) :: space
482 integer,
intent(in) :: max_iter
485 integer :: iter, nst_conv
489 call hm%update(gr, namespace, space, ext_partners)
492 nst_conv =
floor(st%qtot/st%smear%el_per_state)
494 do iter = 1, max_iter
495 call eigensolver%run(namespace, gr, st, hm, 1, converged, nst_conv)
506 message(1) =
'All states converged.'
509 message(1) =
'Some of the states are not fully converged!'
513 write(
message(1),
'(a, e17.6)')
'Criterion = ', eigensolver%tolerance
525 character(len=50) :: str
529 write(str,
'(a,i5)')
'Kohn-Sham inversion eigensolver iteration #', iter
532 write(
message(1),
'(a,i6,a,i6)')
'Converged states: ', minval(eigensolver%converged(1:st%nik))
536 eigensolver%diff, compact = .
true., namespace=namespace)
549 subroutine invertks_iter(ks_inv, target_rho, namespace, space, ext_partners, nspin, aux_hm, gr, &
552 real(real64),
intent(in) :: target_rho(:,:)
553 type(
grid_t),
intent(in) :: gr
555 class(
space_t),
intent(in) :: space
560 integer,
intent(in) :: nspin
562 integer :: ip, ispin, ierr, asym1, asym2
563 integer :: iunit, verbosity, counter, np
566 real(real64) :: rr, shift
567 real(real64) :: alpha, beta
568 real(real64) :: mu, npower, npower_in
569 real(real64) :: convdensity, diffdensity
570 real(real64),
allocatable :: vhxc(:,:)
571 real(real64),
parameter :: small_density = 5e-12_real64
573 character(len=256) :: fname
578 assert(space%dim == 1)
590 call parse_variable(namespace,
'InvertKSConvAbsDens', 1e-5_real64, convdensity)
599 call parse_variable(namespace,
'InvertKSStellaBeta', 1e-6_real64, beta)
608 call parse_variable(namespace,
'InvertKSStellaAlpha', 0.25_real64, alpha)
627 call parse_variable(namespace,
'InvertKSGodbyPower', 0.05_real64, npower_in)
646 if (verbosity < 0 .or. verbosity > 2)
then
660 safe_allocate(vhxc(1:np, 1:nspin))
661 call lalg_copy(np, nspin, aux_hm%vhxc, vhxc)
663 if (verbosity == 1 .or. verbosity == 2)
then
664 iunit =
io_open(
'InvertKSconvergence', namespace, action =
'write')
673 if (abs(st%rho(ip, ispin)-target_rho(ip, ispin)) > diffdensity)
then
674 diffdensity = abs(st%rho(ip, ispin)-target_rho(ip, ispin))
681 do while(diffdensity > convdensity .and. counter < max_iter)
683 counter = counter + 1
685 if (verbosity == 2)
then
686 write(fname,
'(i6.6)') counter
688 gr, aux_hm%vhxc(:,1),
units_out%energy, ierr)
690 gr, st%rho(:,1),
units_out%length**(-space%dim), ierr)
697 select case(ks_inv%method)
703 vhxc(ip, ispin) = vhxc(ip, ispin) &
704 + ((st%rho(ip, ispin) - target_rho(ip, ispin))/(target_rho(ip, ispin) + beta))*alpha
713 beta = diffdensity*1e-3_real64
716 alpha = max(0.05_real64,
m_half - diffdensity*100.0_real64*0.45_real64)
717 write(
message(1),
'(a,2E15.4,3I8, 2E15.4)') &
718 ' KSinversion: diffdensity, convdensity, imax, counter, max_iter, alpha, beta ', &
719 diffdensity, convdensity, imax, counter, max_iter, alpha, beta
726 vhxc(ip, ispin) = vhxc(ip, ispin) &
727 + ((st%rho(ip, ispin) - target_rho(ip, ispin))/(target_rho(ip, ispin) + beta))*alpha
738 write(
message(1),
'(a,2E15.4,3I8, 2E15.4)') &
739 ' KSinversion: diffdensity, convdensity, imax, counter, max_iter, power, mu ', &
740 diffdensity, convdensity, imax, counter, max_iter, npower, mu
747 vhxc(ip, ispin) = vhxc(ip, ispin) &
748 + (st%rho(ip, ispin)**npower - target_rho(ip, ispin)**npower)*mu
763 assert(.not. gr%parallel_in_domains)
767 if (abs(st%rho(ip, ispin)-target_rho(ip, ispin)) > diffdensity)
then
768 diffdensity = abs(st%rho(ip, ispin)-target_rho(ip, ispin))
774 if (verbosity == 1 .or. verbosity == 2)
then
775 write(iunit,
'(i6.6)', advance =
'no') counter
776 write(iunit,
'(es18.10)') diffdensity
783 call lalg_copy(np, nspin, vhxc, aux_hm%vhxc)
785 aux_hm%vxc(1:np, ispin) = vhxc(1:np, ispin) - aux_hm%vhartree(1:np)
794 call lalg_copy(np, nspin, aux_hm%vxc, vhxc)
802 if (target_rho(ip, ispin) < small_density)
then
804 vhxc(ip, ispin) = -st%qtot/
sqrt(rr**2 +
m_one)
807 if (target_rho(np-ip+1, ispin) < small_density)
then
813 call mesh_r(gr, asym1+1, rr)
814 shift = vhxc(asym1+1, ispin) + st%qtot/
sqrt(rr**2 +
m_one)
817 do ip = asym1+1, asym2-1
818 vhxc(ip, ispin) = vhxc(ip, ispin) - shift
822 call mesh_r(gr, asym2-1, rr)
823 shift = vhxc(asym2-1, ispin) + st%qtot/
sqrt(rr**2 +
m_one)
828 vhxc(ip, ispin) = vhxc(ip, ispin) - shift
835 vhxc(ip, ispin) = -st%qtot/
sqrt(rr**2 +
m_one)
842 call lalg_copy(np, nspin, vhxc, aux_hm%vxc)
844 aux_hm%vhxc(1:np, ispin) = vhxc(1:np, ispin) + aux_hm%vhartree(1:np)
853 write(
message(1),
'(a,I8)')
"Iterative KS inversion, iterations needed:", counter
858 safe_deallocate_a(vhxc)
864 subroutine xc_ks_inversion_calc(ks_inversion, namespace, space, gr, hm, ext_partners, st, vxc, time)
867 class(
space_t),
intent(in) :: space
868 type(
grid_t),
intent(in) :: gr
872 real(real64),
intent(inout) :: vxc(:,:)
873 real(real64),
optional,
intent(in) :: time
877 if (ks_inversion%level == xc_ks_inversion_none)
return
881 if (
present(time) .and. time >
m_zero)
then
882 write(
message(1),
'(A,F18.12)')
'xc_ks_inversion_calc - time:', time
886 ks_inversion%aux_hm%energy%intnvxc =
m_zero
887 ks_inversion%aux_hm%energy%hartree =
m_zero
888 ks_inversion%aux_hm%energy%exchange =
m_zero
889 ks_inversion%aux_hm%energy%correlation =
m_zero
891 ks_inversion%aux_hm%vhartree = hm%vhartree
893 if (
present(time) .and. time >
m_zero)
then
894 call lalg_copy(gr%np, st%d%nspin, ks_inversion%vhxc_previous_step, ks_inversion%aux_hm%vhxc)
898 do ispin = 1, st%d%nspin
899 ks_inversion%aux_hm%vxc(1:gr%np, ispin) =
m_zero
900 ks_inversion%aux_hm%vhxc(1:gr%np, ispin) = hm%vhartree(1:gr%np) + ks_inversion%aux_hm%vxc(1:gr%np, ispin)
908 call lalg_copy(gr%np, hm%ep%vpsl, ks_inversion%aux_hm%ep%vpsl)
913 ks_inversion%eigensolver, ks_inversion%aux_st, ks_inversion%aux_hm, ks_inversion%max_iter)
918 select case (ks_inversion%method)
920 case (xc_inv_method_two_particle)
921 call invertks_2part(ks_inversion, ks_inversion%aux_st%rho, st%d%nspin, ks_inversion%aux_hm, gr, &
922 ks_inversion%aux_st, ks_inversion%eigensolver, namespace, space, ext_partners)
925 call invertks_iter(ks_inversion, st%rho, namespace, space, ext_partners, st%d%nspin, ks_inversion%aux_hm, gr, &
926 ks_inversion%aux_st, ks_inversion%eigensolver)
932 do ispin = 1, st%d%nspin
933 call lalg_axpy(gr%np, -
m_one, hm%vhartree, ks_inversion%aux_hm%vhxc(:,ispin))
936 vxc = ks_inversion%aux_hm%vxc
939 if (
present(time))
then
940 ks_inversion%vhxc_previous_step = ks_inversion%aux_hm%vhxc
constant times a vector plus a vector
Copies a vector x, to a vector y.
Some operations may be done for one spline-function, or for an array of them.
double floor(double __x) __attribute__((__nothrow__
This module implements a calculator for the density and defines related functions.
subroutine, public density_calc(st, gr, density, istin)
Computes the density from the orbitals in st.
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
subroutine, public dderivatives_lapl(der, ff, op_ff, ghost_update, set_bc, factor)
apply the Laplacian to a mesh function
subroutine, public eigensolver_init(eigens, namespace, gr, st, mc, space)
subroutine, public eigensolver_end(eigens)
real(real64), parameter, public m_zero
real(real64), parameter, public m_tiny
real(real64), parameter, public m_epsilon
real(real64), parameter, public m_half
real(real64), parameter, public m_one
This module implements the underlying real-space grid.
subroutine, public hamiltonian_elec_end(hm)
subroutine, public hamiltonian_elec_init(hm, namespace, space, gr, ions, ext_partners, st, theory_level, xc, mc, kpoints, need_exchange, xc_photons)
integer, parameter, public kohn_sham_dft
This module defines classes and functions for interaction partners.
subroutine, public dio_function_output(how, dir, fname, namespace, space, mesh, ff, unit, ierr, pos, atoms, grp, root)
Top-level IO routine for functions defined on the mesh.
integer(int64) function, public io_function_fill_how(where)
Use this function to quickly plot functions for debugging purposes: call dio_function_output(io_funct...
subroutine, public io_close(iunit, grp)
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
subroutine, public lasers_check_symmetries(this, kpoints)
subroutine, public lasers_parse_external_fields(this)
subroutine, public lasers_generate_potentials(this, mesh, space, latt)
This module defines the meshes, which are used in Octopus.
pure subroutine, public mesh_r(mesh, ip, rr, origin, coords)
return the distance to the origin for a given grid point
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)
subroutine, public messages_new_line()
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_input_error(namespace, var, details, row, column)
subroutine, public messages_experimental(name, namespace)
This module handles the communicators for the various parallelization strategies.
subroutine, public spline_fit(nrc, rofi, ffit, spl, threshold)
subroutine, public spline_der2(spl, dspl, threshold, grid)
Returns a spline that contains the second derivative of the original spline.
real(real64) function, public spline_eval(spl, x)
subroutine, public spline_generate_shifted_grid(this, x_shifted)
This module handles spin dimensions of the states and the k-point distribution.
This module defines routines to write information about states.
subroutine, public states_elec_write_eigenvalues(nst, st, space, kpoints, error, st_start, compact, iunit, namespace)
write the eigenvalues for some states to a file.
subroutine, public states_elec_densities_init(st, gr)
subroutine, public states_elec_end(st)
finalize the states_elec_t object
subroutine, public states_elec_allocate_wfns(st, mesh, wfs_type, skip, packed)
Allocates the KS wavefunctions defined within a states_elec_t structure.
subroutine, public states_elec_copy(stout, stin, exclude_wfns, exclude_eigenval, special)
make a (selective) copy of a states_elec_t object
subroutine, public states_elec_generate_random(st, mesh, kpoints, ist_start_, ist_end_, ikpt_start_, ikpt_end_, normalized)
randomize states
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
This module defines the unit system, used for input and output.
type(unit_system_t), public units_out
subroutine, public xc_ks_inversion_end(ks_inv)
integer, parameter, public xc_inv_method_iter_godby
subroutine, public invertks_2part(ks_inv, target_rho, nspin, aux_hm, gr, st, eigensolver, namespace, space, ext_partners)
Given a density, it performs the Kohn-Sham inversion, assuming a two-particle, one orbital case.
integer, parameter, public xc_ks_inversion_td_exact
integer, parameter, public xc_ks_inversion_adiabatic
integer, parameter, public xc_inv_method_vs_iter
integer, parameter, public xc_asymptotics_sc
subroutine, public xc_ks_inversion_write_info(ks_inversion, iunit, namespace)
subroutine, public invertks_iter(ks_inv, target_rho, namespace, space, ext_partners, nspin, aux_hm, gr, st, eigensolver)
Iterative inversion of KS potential from the density.
subroutine, public xc_ks_inversion_init(ks_inv, namespace, gr, ions, st, xc, mc, space, kpoints)
integer, parameter, public xc_inv_method_iter_stella
subroutine, public xc_ks_inversion_calc(ks_inversion, namespace, space, gr, hm, ext_partners, st, vxc, time)
subroutine, public invertks_update_hamiltonian(namespace, gr, space, ext_partners, eigensolver, st, hm, max_iter)
A small auxiliary function to perform the update of the Hamiltonian, run the eigensolver,...
Description of the grid, containing information on derivatives, stencil, and symmetries.
abstract class for general interaction partners
iterator for the list of partners
the basic spline datatype
The states_elec_t class contains all electronic wave functions.