Octopus
xc_ks_inversion.F90
Go to the documentation of this file.
1!! Copyright (C) 2010 H. Appel, N. Helbig
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
22 use debug_oct_m
26 use global_oct_m
27 use grid_oct_m
29 use io_oct_m
32 use ions_oct_m
33 use, intrinsic :: iso_fortran_env
36 use lasers_oct_m
38 use mesh_oct_m
42 use parser_oct_m
44 use space_oct_m
49 use unit_oct_m
52 use xc_f03_lib_m
53 use xc_oct_m
54
55 implicit none
56
57 private
58 public :: &
67
69 integer, public, parameter :: &
70 XC_INV_METHOD_TWO_PARTICLE = 1, &
74
76 integer, public, parameter :: &
77 XC_KS_INVERSION_NONE = 1, &
80
82 integer, public, parameter :: &
83 XC_ASYMPTOTICS_NONE = 1, &
85
86 integer, parameter :: &
87 XC_FLAGS_NONE = 0
88
90 private
91 integer, public :: method
92 integer :: level = xc_ks_inversion_none
93 integer :: asymptotics
94 real(real64), allocatable :: vhxc_previous_step(:, :)
95 type(states_elec_t), public :: aux_st
96 type(hamiltonian_elec_t) :: aux_hm
97 type(eigensolver_t), public :: eigensolver
98 ! List with all the external partners
99 ! This will become a list of interactions in the future
100 type(partner_list_t) :: ext_partners
101
102 integer, public :: max_iter
103 end type xc_ks_inversion_t
104
105
106contains
107
108 ! ---------------------------------------------------------
109 subroutine xc_ks_inversion_init(ks_inv, namespace, gr, ions, st, xc, mc, space, kpoints)
110 type(xc_ks_inversion_t), intent(inout) :: ks_inv
111 type(namespace_t), intent(in) :: namespace
112 type(grid_t), intent(inout) :: gr
113 type(ions_t), intent(inout) :: ions
114 type(states_elec_t), intent(in) :: st
115 type(xc_t), intent(in) :: xc
116 type(multicomm_t), intent(in) :: mc
117 class(space_t), intent(in) :: space
118 type(kpoints_t), intent(in) :: kpoints
119
120 class(lasers_t), pointer :: lasers
121
122 push_sub(xc_ks_inversion_init)
123
124 if(gr%parallel_in_domains) then
125 call messages_not_implemented("Kohn-Sham inversion in parallel", namespace=namespace)
126 end if
127
128 call messages_experimental("Kohn-Sham inversion")
129
130 !%Variable InvertKSmethod
131 !%Type integer
132 !%Default iter_godby
133 !%Section Calculation Modes::Invert KS
134 !%Description
135 !% Selects whether the exact two-particle method or the iterative scheme
136 !% is used to invert the density to get the KS potential.
137 !%Option two_particle 1
138 !% Exact two-particle scheme.
139 !%Option iterative 2
140 !% Iterative scheme for <math>v_s</math>.
141 !%Option iter_stella 3
142 !% Iterative scheme for <math>v_s</math> using Stella and Verstraete method.
143 !%Option iter_godby 4
144 !% Iterative scheme for <math>v_s</math> using power method from Rex Godby.
145 !%End
146 call parse_variable(namespace, 'InvertKSmethod', xc_inv_method_iter_godby, ks_inv%method)
147
148 if (ks_inv%method < xc_inv_method_two_particle &
149 .or. ks_inv%method > xc_inv_method_iter_godby) then
150 call messages_input_error(namespace, 'InvertKSmethod')
151 call messages_fatal(1, namespace=namespace)
152 end if
153
154 !%Variable KSInversionLevel
155 !%Type integer
156 !%Default ks_inversion_adiabatic
157 !%Section Calculation Modes::Invert KS
158 !%Description
159 !% At what level <tt>Octopus</tt> shall handle the KS inversion.
160 !%Option ks_inversion_none 1
161 !% Do not compute KS inversion.
162 !%Option ks_inversion_adiabatic 2
163 !% Compute exact adiabatic <math>v_{xc}</math>.
164 !%End
165 call messages_obsolete_variable(namespace, 'KS_Inversion_Level', 'KSInversionLevel')
166 call parse_variable(namespace, 'KSInversionLevel', xc_ks_inversion_adiabatic, ks_inv%level)
167 if (.not. varinfo_valid_option('KSInversionLevel', ks_inv%level)) call messages_input_error(namespace, 'KSInversionLevel')
168
169 !%Variable KSInversionAsymptotics
170 !%Type integer
171 !%Default xc_asymptotics_none
172 !%Section Calculation Modes::Invert KS
173 !%Description
174 !% Asymptotic correction applied to <math>v_{xc}</math>.
175 !%Option xc_asymptotics_none 1
176 !% Do not apply any correction in the asymptotic region.
177 !%Option xc_asymptotics_sc 2
178 !% Applies the soft-Coulomb decay of <math>-1/\sqrt{r^2+1}</math> to <math>v_{xc}</math> in the asymptotic region.
179 !%End
180 call parse_variable(namespace, 'KSInversionAsymptotics', xc_asymptotics_none, ks_inv%asymptotics)
181 if (ks_inv%asymptotics /= xc_asymptotics_none .and. space%dim > 1) then
182 call messages_not_implemented("KSInversionAsymptotics /= xc_asymptotics_sc for dimensions higher than 1.")
183 end if
185 ! In order to get properly converged states, given a vxc, we might need to run more than
186 ! one eigensolver run.
187 ! This variable is documented in scf.F90
188 call parse_variable(namespace, 'MaximumIter', 50, ks_inv%max_iter)
190 if (ks_inv%level /= xc_ks_inversion_none) then
191 call states_elec_copy(ks_inv%aux_st, st, exclude_wfns = .true.)
193 ! initialize auxiliary random wavefunctions
194 call states_elec_allocate_wfns(ks_inv%aux_st, gr)
195 call states_elec_generate_random(ks_inv%aux_st, gr, kpoints)
196
197 ! initialize densities, hamiltonian and eigensolver
198 call states_elec_densities_init(ks_inv%aux_st, gr)
199
200 lasers => lasers_t(namespace)
202 call lasers_generate_potentials(lasers, gr, space, ions%latt)
203
204 if(lasers%no_lasers > 0) then
205 call ks_inv%ext_partners%add(lasers)
206 call lasers_check_symmetries(lasers, kpoints)
207 else
208 deallocate(lasers)
209 end if
210
211 call hamiltonian_elec_init(ks_inv%aux_hm, namespace, space, gr, ions, ks_inv%ext_partners, ks_inv%aux_st, &
212 kohn_sham_dft, xc, mc, kpoints)
213 call eigensolver_init(ks_inv%eigensolver, namespace, gr, ks_inv%aux_st, ks_inv%aux_hm, mc, space)
214 end if
215
216 pop_sub(xc_ks_inversion_init)
217 end subroutine xc_ks_inversion_init
218
219
220 ! ---------------------------------------------------------
221 subroutine xc_ks_inversion_end(ks_inv)
222 type(xc_ks_inversion_t), intent(inout) :: ks_inv
223
224 type(partner_iterator_t) :: iter
225 class(interaction_partner_t), pointer :: partner
226
227 push_sub(xc_ks_inversion_end)
228
229 if (ks_inv%level /= xc_ks_inversion_none) then
230 ! cleanup
231 call eigensolver_end(ks_inv%eigensolver)
232 call hamiltonian_elec_end(ks_inv%aux_hm)
233 call states_elec_end(ks_inv%aux_st)
234
235 call iter%start(ks_inv%ext_partners)
236 do while (iter%has_next())
237 partner => iter%get_next()
238 safe_deallocate_p(partner)
239 end do
240 call ks_inv%ext_partners%empty()
241
242 end if
243
244 pop_sub(xc_ks_inversion_end)
245 end subroutine xc_ks_inversion_end
246
247
248 ! ---------------------------------------------------------
249 subroutine xc_ks_inversion_write_info(ks_inversion, iunit, namespace)
250 type(xc_ks_inversion_t), intent(in) :: ks_inversion
251 integer, optional, intent(in) :: iunit
252 type(namespace_t), optional, intent(in) :: namespace
253
254 if (ks_inversion%level == xc_ks_inversion_none) return
255
257
258 call messages_print_var_option('KSInversionLevel', ks_inversion%level, iunit=iunit, namespace=namespace)
259
261 end subroutine xc_ks_inversion_write_info
262
263
264 ! ---------------------------------------------------------
270 subroutine invertks_2part(ks_inv, target_rho, nspin, aux_hm, gr, st, eigensolver, &
271 namespace, space, ext_partners)
272 type(xc_ks_inversion_t), intent(in) :: ks_inv
273 real(real64), intent(in) :: target_rho(:, :)
274 integer, intent(in) :: nspin
275 type(hamiltonian_elec_t), intent(inout) :: aux_hm
276 type(grid_t), intent(in) :: gr
277 type(states_elec_t), intent(inout) :: st
278 type(eigensolver_t), intent(inout) :: eigensolver
279 type(namespace_t), intent(in) :: namespace
280 class(space_t), intent(in) :: space
281 type(partner_list_t), intent(in) :: ext_partners
282
283 integer :: asym1, asym2, ip, ispin
284 integer :: np
285 real(real64) :: rr, shift
286 real(real64), parameter :: smalldensity = 5e-12_real64
287 real(real64), allocatable :: sqrtrho(:, :), laplace(:, :), vks(:, :), x_shifted(:)
288 type(spline_t) :: spl, lapl_spl
289
290 push_sub(invertks_2part)
291
292 assert(.not. gr%parallel_in_domains)
293
294 ! In periodic systems, the aymptotics needs to done differently.
295 ! In the KLI code, I used a formula from the litterature. The same logic could used here too - NTD
296 assert(space%periodic_dim == 0)
297
298 ! The treatment of the asymptotics is only valid for the 1D case
299 assert(space%dim == 1)
300
301 np = gr%np
302
303 safe_allocate(sqrtrho(1:gr%np_part, 1:nspin))
304 safe_allocate(vks(1:np, 1:nspin))
305 safe_allocate(laplace(1:gr%np, 1:nspin))
306
307 if (any(target_rho(:, :) < -m_epsilon)) then
308 write(message(1),*) "Target density has negative points. min value = ", minval(target_rho(:, :))
309 call messages_warning(1, namespace=namespace)
310 end if
311
312 ! Computing the square root of the density
313 !$omp parallel private(ip)
314 do ispin = 1, nspin
315 !$omp do simd
316 do ip = 1, gr%np
317 sqrtrho(ip, ispin) = sqrt(target_rho(ip, ispin))
318 end do
319 !$omp end do simd
320 end do
321 !$omp end parallel
322
323 ! Computing the Laplacian of \sqrt{\rho}
324 if (space%dim == 1) then
325 ! In the 1D case, we fit by a spline and compute the derivative with it
326 do ispin = 1, nspin
327 call spline_init(spl)
328 call spline_init(lapl_spl)
329 call spline_fit(gr%np, gr%x_t(:, 1), sqrtrho(:, ispin), spl)
330 ! Importantly, here we use a staggered grid to force interpolation
331 ! Without this, the low density region shows large oscilations, as for the case of finite differences.
332 ! To avoid this, we evaluate the derivative of the cubic spline on a different grid
333 ! than the one used in the calculation, fit this result and reevalute (interpolate) it on the actual grid.
334 ! This is needed as a cubic spline is by construction passing by the points on which it is fitted.
335 ! This leads to a much smoother result for Laplacian of the density in the low-density regions.
336
337 call spline_generate_shifted_grid(spl, x_shifted)
338 call spline_der2(spl, lapl_spl, m_zero, grid=x_shifted)
339 safe_deallocate_a(x_shifted)
340
341
342 do ip = 1, gr%np
343 laplace(ip, ispin) = spline_eval(lapl_spl, gr%x_t(ip, 1))
344 end do
345 call spline_end(spl)
346 call spline_end(lapl_spl)
347 end do
348
349 else
350 do ispin = 1, nspin
351 call dderivatives_lapl(gr%der, sqrtrho(:, ispin), laplace(:, ispin))
352 end do
353 end if
354
355 ! Used to check the asymptotics
356 ! Note that this does not work for open-shell systems where the up and down density are different.
357 ! This could cause problems for spin-polarized H atom for instance
358 asym1 = 0
359 asym2 = 0
360
361 ! Note that the code below does not works for grid parallelization
362 ! It also assumes a special ordering of the points, which which is only guarantied in 1D
363 ! A better approach would be to fix the constant with the eigenvalue (user input option or restarting)
364 do ispin = 1, nspin
365 !avoid division by zero and set parameters for asymptotics
366 !only for 1D potentials at the moment
367 !need to find a way to find all points from where asymptotics should start in 2D and 3D
368 do ip = 1, int(np/2)
369 if (target_rho(ip, ispin) < smalldensity) then
370 vks(ip, ispin) = aux_hm%ep%vpsl(ip) + aux_hm%ks_pot%vhartree(ip)
371 asym1 = ip
372 end if
373 if (target_rho(np-ip+1, ispin) < smalldensity) then
374 vks(np-ip+1, ispin) = aux_hm%ep%vpsl(np-ip+1) + aux_hm%ks_pot%vhartree(np-ip+1)
375 asym2 = np - ip + 1
376 end if
377 end do
378
379 ! The actual expression is \epsilon + 1/2 [\nabla^2 \sqrt{\rho}]/\sqrt{\rho} - v_{ext} - v_H
380 ! We first compute the first part
381 !$omp parallel do private(ip)
382 do ip = asym1+1, asym2-1
383 vks(ip, ispin) = m_half * laplace(ip, ispin) / (sqrtrho(ip, ispin) + m_tiny)
384 end do
385
386 ! And then compute the remaining part
387 !$omp parallel do private(ip)
388 do ip = 1, gr%np
389 aux_hm%ks_pot%vxc(ip, ispin) = vks(ip, ispin) - aux_hm%ep%vpsl(ip) - aux_hm%ks_pot%vhartree(ip)
390 end do
391 end do
392
393 !ensure correct asymptotic behavior, only for 1D potentials at the moment
394 !need to find a way to find all points from where asymptotics should start in 2D and 3D
395 if (ks_inv%asymptotics == xc_asymptotics_sc) then
396 do ispin = 1, nspin
397 !$omp parallel do private(rr, ip)
398 do ip = 1, asym1
399 call mesh_r(gr, ip, rr)
400 aux_hm%ks_pot%vxc(ip, ispin) = -st%qtot/sqrt(rr**2 + m_one)
401 end do
402 !$omp end parallel do
403
404 ! calculate constant shift for correct asymptotics and shift accordingly
405 call mesh_r(gr, asym1+1, rr)
406 shift = aux_hm%ks_pot%vxc(asym1+1, ispin) + st%qtot/sqrt(rr**2 + m_one)
407
408 !$omp parallel do simd
409 do ip = asym1+1, asym2-1
410 aux_hm%ks_pot%vxc(ip, ispin) = aux_hm%ks_pot%vxc(ip, ispin) - shift
411 end do
412 !$omp end parallel do simd
413
414
415 call mesh_r(gr, asym2-1, rr)
416 shift = aux_hm%ks_pot%vxc(asym2-1, ispin) + st%qtot/sqrt(rr**2 + m_one)
417
418 !$omp parallel private(rr, ip)
419 !$omp do simd
420 do ip = 1, asym2-1
421 aux_hm%ks_pot%vxc(ip, ispin) = aux_hm%ks_pot%vxc(ip, ispin) - shift
422 end do
423 !$omp end do simd
424
425 !$omp do
426 do ip = asym2, np
427 call mesh_r(gr, ip, rr)
428 aux_hm%ks_pot%vxc(ip, ispin) = -st%qtot/sqrt(rr**2 + m_one)
429 end do
430 !$omp end do
431 !$omp end parallel
432 end do
433 end if !apply asymptotic correction
434
435 ! Remove a shift, imposing vxc to be continuous
436 if (ks_inv%asymptotics == xc_asymptotics_none) then
437 assert(asym1 > 0)
438 assert(asym2 > 0)
439 do ispin = 1, nspin
440 ! calculate constant shift to make potential continuous
441
442 ! Note that this will fail if the density does not vanish below small_density
443 shift = aux_hm%ks_pot%vxc(asym1+1, ispin)
444 !$omp parallel do simd
445 do ip = asym1+1, asym2-1
446 aux_hm%ks_pot%vxc(ip, ispin) = aux_hm%ks_pot%vxc(ip, ispin) - shift
447 end do
448 !$omp end parallel do simd
449
450 shift = aux_hm%ks_pot%vxc(asym2-1, ispin)
451 !$omp parallel do simd
452 do ip = 1, asym2-1
453 aux_hm%ks_pot%vxc(ip, ispin) = aux_hm%ks_pot%vxc(ip, ispin) - shift
454 end do
455 !$omp end parallel do simd
456 end do
457 end if
458
459 ! Store the final result
460 !$omp parallel private(ispin, ip)
461 do ispin = 1, nspin
462 !$omp do
463 do ip = 1, gr%np
464 aux_hm%ks_pot%vhxc(ip, ispin) = aux_hm%ks_pot%vxc(ip, ispin) + aux_hm%ks_pot%vhartree(ip)
465 end do
466 end do
467 !$omp end parallel
468
469
470 call invertks_update_hamiltonian(namespace, gr, space, ext_partners, eigensolver, st, aux_hm, ks_inv%max_iter)
471
472 safe_deallocate_a(sqrtrho)
473 safe_deallocate_a(laplace)
474 safe_deallocate_a(vks)
475
476 pop_sub(invertks_2part)
477 end subroutine invertks_2part
478
480 subroutine invertks_update_hamiltonian(namespace, gr, space, ext_partners, eigensolver, st, hm, max_iter)
481 type(namespace_t), intent(in) :: namespace
482 type(grid_t), intent(in) :: gr
483 class(space_t), intent(in) :: space
484 type(partner_list_t), intent(in) :: ext_partners
485 type(eigensolver_t), intent(inout) :: eigensolver
486 type(states_elec_t), intent(inout) :: st
487 type(hamiltonian_elec_t), intent(inout) :: hm
488 integer, intent(in) :: max_iter
489
490 logical :: converged
491 integer :: iter, nst_conv
492
494
495 call hm%update(gr, namespace, space, ext_partners)
496
497 !Poor-man estimate of the number of occupied states. Should be improved
498 nst_conv = floor(st%qtot/st%smear%el_per_state)
499
500 do iter = 1, max_iter
501 call eigensolver%run(namespace, gr, st, hm, space, ext_partners, 1, converged, nst_conv)
502
503 !TODO: Should we allow for updating the occupations? This might be necessary for open-shell or metallic systems
504 ! call states_elec_fermi(st, namespace, gr)
505
506 call write_iter()
507
508 if (converged) exit
509 end do
510
511 if (converged) then
512 message(1) = 'All states converged.'
513 call messages_info(1, namespace=namespace)
514 else
515 message(1) = 'Some of the states are not fully converged!'
516 call messages_info(1, namespace=namespace)
517 end if
518
519 write(message(1),'(a, e17.6)') 'Criterion = ', eigensolver%tolerance
520 call messages_info(1, namespace=namespace)
521 call messages_new_line()
522
523 ! Get the new guess density
524 call density_calc(st, gr, st%rho)
525
527
528 contains
529 ! ---------------------------------------------------------
530 subroutine write_iter()
531 character(len=50) :: str
532
534
535 write(str, '(a,i5)') 'Kohn-Sham inversion eigensolver iteration #', iter
536 call messages_print_with_emphasis(msg=trim(str), namespace=namespace)
537
538 write(message(1),'(a,i6)') 'Converged states: ', minval(eigensolver%converged(1:st%nik))
539 call messages_info(1, namespace=namespace)
540
541 call states_elec_write_eigenvalues(st%nst, st, space, hm%kpoints, &
542 eigensolver%diff, compact = .true., namespace=namespace)
543
544 call messages_print_with_emphasis(namespace=namespace)
545
547 end subroutine write_iter
548 end subroutine invertks_update_hamiltonian
549
550 ! ---------------------------------------------------------
555 subroutine invertks_iter(ks_inv, target_rho, namespace, space, ext_partners, nspin, aux_hm, gr, &
556 st, eigensolver)
557 type(xc_ks_inversion_t), intent(in) :: ks_inv
558 real(real64), intent(in) :: target_rho(:, :)
559 type(grid_t), intent(in) :: gr
560 type(namespace_t), intent(in) :: namespace
561 class(space_t), intent(in) :: space
562 type(partner_list_t), intent(in) :: ext_partners
563 type(states_elec_t), intent(inout) :: st
564 type(hamiltonian_elec_t), intent(inout) :: aux_hm
565 type(eigensolver_t), intent(inout) :: eigensolver
566 integer, intent(in) :: nspin
567
568 integer :: ip, ispin, ierr, asym1, asym2
569 integer :: iunit, verbosity, counter, np
570 integer :: max_iter
571 integer :: imax
572 real(real64) :: rr, shift
573 real(real64) :: alpha, beta
574 real(real64) :: mu, npower, npower_in ! these constants are from Rex Godbys scheme
575 real(real64) :: convdensity, diffdensity
576 real(real64), allocatable :: vhxc(:, :)
577 real(real64), parameter :: small_density = 5e-12_real64
578
579 character(len=256) :: fname
580
581 push_sub(invertks_iter)
582
583 ! The treatment of the asymptotics is only valid for the 1D case
584 assert(space%dim == 1)
585
586 np = gr%np
587
588 !%Variable InvertKSConvAbsDens
589 !%Type float
590 !%Default 1e-5
591 !%Section Calculation Modes::Invert KS
592 !%Description
593 !% Absolute difference between the calculated and the target density in the KS
594 !% inversion. Has to be larger than the convergence of the density in the SCF run.
595 !%End
596 call parse_variable(namespace, 'InvertKSConvAbsDens', 1e-5_real64, convdensity)
597
598 !%Variable InvertKSStellaBeta
599 !%Type float
600 !%Default 1.0e-6
601 !%Section Calculation Modes::Invert KS
602 !%Description
603 !% residual term in Stella iterative scheme to avoid 0 denominators
604 !%End
605 call parse_variable(namespace, 'InvertKSStellaBeta', 1e-6_real64, beta)
606
607 !%Variable InvertKSStellaAlpha
608 !%Type float
609 !%Default 0.25
610 !%Section Calculation Modes::Invert KS
611 !%Description
612 !% prefactor term in iterative scheme from L. Stella
613 !%End
614 call parse_variable(namespace, 'InvertKSStellaAlpha', 0.25_real64, alpha)
615
616 !%Variable InvertKSGodbyMu
617 !%Type float
618 !%Default 1.0
619 !%Section Calculation Modes::Invert KS
620 !%Description
621 !% prefactor for iterative KS inversion convergence scheme from Godby based on van Leeuwen scheme
622 !%End
623 call parse_variable(namespace, 'InvertKSGodbyMu', m_one, mu)
624
625 !%Variable InvertKSGodbyPower
626 !%Type float
627 !%Default 0.05
628 !%Section Calculation Modes::Invert KS
629 !%Description
630 !% power to which density is elevated for iterative KS inversion convergence
631 !% scheme from Godby based on van Leeuwen scheme
632 !%End
633 call parse_variable(namespace, 'InvertKSGodbyPower', 0.05_real64, npower_in)
634 npower = npower_in
635
636 !%Variable InvertKSVerbosity
637 !%Type integer
638 !%Default 0
639 !%Section Calculation Modes::Invert KS
640 !%Description
641 !% Selects what is output during the calculation of the KS potential.
642 !%Option 0
643 !% Only outputs the converged density and KS potential.
644 !%Option 1
645 !% Same as 0 but outputs the maximum difference to the target density in each
646 !% iteration in addition.
647 !%Option 2
648 !% Same as 1 but outputs the density and the KS potential in each iteration in
649 !% addition.
650 !%End
651 call parse_variable(namespace, 'InvertKSVerbosity', 0, verbosity)
652 if (verbosity < 0 .or. verbosity > 2) then
653 call messages_input_error(namespace, 'InvertKSVerbosity')
654 call messages_fatal(1, namespace=namespace)
655 end if
656
657 !%Variable InvertKSMaxIter
658 !%Type integer
659 !%Default 200
660 !%Section Calculation Modes::Invert KS
661 !%Description
662 !% Selects how many iterations of inversion will be done in the iterative scheme
663 !%End
664 call parse_variable(namespace, 'InvertKSMaxIter', 200, max_iter)
665
666 safe_allocate(vhxc(1:np, 1:nspin))
667 call lalg_copy(np, nspin, aux_hm%ks_pot%vhxc, vhxc)
668
669 if (verbosity == 1 .or. verbosity == 2) then
670 iunit = io_open('InvertKSconvergence', namespace, action = 'write')
671 end if
672
673 counter = 0
674 imax = 0
675
676 diffdensity = m_zero
677 do ispin = 1, nspin
678 do ip = 1, np
679 if (abs(st%rho(ip, ispin)-target_rho(ip, ispin)) > diffdensity) then
680 diffdensity = abs(st%rho(ip, ispin)-target_rho(ip, ispin))
681 imax = ip
682 end if
683 end do
684 end do
685
686
687 do while(diffdensity > convdensity .and. counter < max_iter)
688
689 counter = counter + 1
690
691 if (verbosity == 2) then
692 write(fname,'(i6.6)') counter
693 call dio_function_output(io_function_fill_how("AxisX"), ".", "vhxc"//fname, namespace, space, &
694 gr, aux_hm%ks_pot%vhxc(:,1), units_out%energy, ierr)
695 call dio_function_output(io_function_fill_how("AxisX"), ".", "rho"//fname, namespace, space, &
696 gr, st%rho(:,1), units_out%length**(-space%dim), ierr)
697 end if
698
699 ! Update the Hamiltonian
700 call invertks_update_hamiltonian(namespace, gr, space, ext_partners, eigensolver, st, aux_hm, ks_inv%max_iter)
701
702 ! Iterative inversion with fixed parameters in Stella Verstraete method
703 select case(ks_inv%method)
705 !$omp parallel private(ip)
706 do ispin = 1, nspin
707 !$omp do simd
708 do ip = 1, np
709 vhxc(ip, ispin) = vhxc(ip, ispin) &
710 + ((st%rho(ip, ispin) - target_rho(ip, ispin))/(target_rho(ip, ispin) + beta))*alpha
711 end do
712 !$omp end do simd
713 end do
714 !$omp end parallel
715
716 ! adaptative iterative method, with update of alpha and beta coefficients
717 ! based on residual in density
719 beta = diffdensity*1e-3_real64 !parameter to avoid numerical problems due to small denominator
720
721 ! proposition to increase convergence speed progressively
722 alpha = max(0.05_real64, m_half - diffdensity*100.0_real64*0.45_real64)
723 write(message(1),'(a,2E15.4,3I8, 2E15.4)') &
724 ' KSinversion: diffdensity, convdensity, imax, counter, max_iter, alpha, beta ', &
725 diffdensity, convdensity, imax, counter, max_iter, alpha, beta
726 call messages_info(1, namespace=namespace)
727
728 !$omp parallel private(ip)
729 do ispin = 1, nspin
730 !$omp do simd
731 do ip = 1, np
732 vhxc(ip, ispin) = vhxc(ip, ispin) &
733 + ((st%rho(ip, ispin) - target_rho(ip, ispin))/(target_rho(ip, ispin) + beta))*alpha
734 end do
735 !$omp end do simd
736 end do
737 !$omp end parallel
738
740! ! below 1.e-3 start reducing power down to 0.01
741! if (diffdensity < 0.001_real64) then
742! npower = min(npower_in, diffdensity*50.0_real64)
743! end if
744 write(message(1),'(a,2E15.4,3I8, 2E15.4)') &
745 ' KSinversion: diffdensity, convdensity, imax, counter, max_iter, power, mu ', &
746 diffdensity, convdensity, imax, counter, max_iter, npower, mu
747 call messages_info(1, namespace=namespace)
748
749 !$omp parallel private(ip)
750 do ispin = 1, nspin
751 !$omp do simd
752 do ip = 1, np
753 vhxc(ip, ispin) = vhxc(ip, ispin) &
754 + (st%rho(ip, ispin)**npower - target_rho(ip, ispin)**npower)*mu
755 end do
756 !$omp end do simd
757 end do
758 !$omp end parallel
759
760 case default
761 assert(.false.)
762 end select
763
764 diffdensity = m_zero
765 !diffdensity = maxval(abs(st%rho(1:np,1:nspin)-target_rho(1:np,1:nspin)))
766
767 ! Note: The code below requires a reduction over the grid.
768 ! We now have routines for this, see mesh_minmaxloc - NTD
769 assert(.not. gr%parallel_in_domains)
770
771 do ispin = 1, nspin
772 do ip = 1, np
773 if (abs(st%rho(ip, ispin)-target_rho(ip, ispin)) > diffdensity) then
774 diffdensity = abs(st%rho(ip, ispin)-target_rho(ip, ispin))
775 imax = ip
776 end if
777 end do
778 end do
779
780 if (verbosity == 1 .or. verbosity == 2) then
781 write(iunit,'(i6.6)', advance = 'no') counter
782 write(iunit,'(es18.10)') diffdensity
783#ifdef HAVE_FLUSH
784 call flush(iunit)
785#endif
786 end if
787
788 ! Store the final result
789 call lalg_copy(np, nspin, vhxc, aux_hm%ks_pot%vhxc)
790 !$omp parallel private(ispin, ip)
791 do ispin = 1, nspin
792 !$omp do
793 do ip = 1, np
794 aux_hm%ks_pot%vxc(ip, ispin) = vhxc(ip, ispin) - aux_hm%ks_pot%vhartree(ip)
795 end do
796 end do
797 !$omp end parallel
798
799 end do ! end while statement on convergence
800
801 !ensure correct asymptotic behavior, only for 1D potentials at the moment
802 !need to find a way to find all points from where asymptotics should start in 2 and 3D
803 if (ks_inv%asymptotics == xc_asymptotics_sc) then
804 !Asympotics is only for vxc
805 call lalg_copy(np, nspin, aux_hm%ks_pot%vxc, vhxc)
806
807 do ispin = 1, nspin
808 ! In case the density is never smaller than 'small_density', we take the edge points
809 asym1 = 1
810 asym2 = np
811
812 do ip = 1, int(np/2)
813 if (target_rho(ip, ispin) < small_density) then
814 call mesh_r(gr, ip, rr)
815 vhxc(ip, ispin) = -st%qtot/sqrt(rr**2 + m_one)
816 asym1 = ip
817 end if
818 if (target_rho(np-ip+1, ispin) < small_density) then
819 asym2 = np - ip + 1
820 end if
821 end do
822
823 ! calculate constant shift for correct asymptotics and shift accordingly
824 call mesh_r(gr, asym1+1, rr)
825 shift = vhxc(asym1+1, ispin) + st%qtot/sqrt(rr**2 + m_one)
826
827 !$omp parallel do simd
828 do ip = asym1+1, asym2-1
829 vhxc(ip, ispin) = vhxc(ip, ispin) - shift
830 end do
831 !$omp end parallel do simd
832
833 call mesh_r(gr, asym2-1, rr)
834 shift = vhxc(asym2-1, ispin) + st%qtot/sqrt(rr**2 + m_one)
835
836 !$omp parallel private(rr)
837 !$omp do simd
838 do ip = 1, asym2-1
839 vhxc(ip, ispin) = vhxc(ip, ispin) - shift
840 end do
841 !$omp end do simd
842
843 !$omp do
844 do ip = asym2, np
845 call mesh_r(gr, ip, rr)
846 vhxc(ip, ispin) = -st%qtot/sqrt(rr**2 + m_one)
847 end do
848 !$omp end do
849 !$omp end parallel
850 end do
851
852 ! See the above comment, vhxc contains vxc here
853 call lalg_copy(np, nspin, vhxc, aux_hm%ks_pot%vxc)
854 !$omp parallel private(ispin, ip)
855 do ispin = 1, nspin
856 !$omp do
857 do ip = 1, np
858 aux_hm%ks_pot%vhxc(ip, ispin) = vhxc(ip, ispin) + aux_hm%ks_pot%vhartree(ip)
859 end do
860 end do
861 !$omp end parallel
862 end if
863
864 !TODO: check that all arrays needed by hamiltonian update are sync`d in MPI fashion
865
866 !calculate final density
867 call invertks_update_hamiltonian(namespace, gr, space, ext_partners, eigensolver, st, aux_hm, ks_inv%max_iter)
868
869 write(message(1),'(a,I8)') "Iterative KS inversion, iterations needed:", counter
870 call messages_info(1, namespace=namespace)
871
872 if (verbosity == 1 .or. verbosity == 2) then
873 call io_close(iunit)
874 end if
875
876 safe_deallocate_a(vhxc)
877
878 pop_sub(invertks_iter)
879 end subroutine invertks_iter
880
881 ! ---------------------------------------------------------
882 subroutine xc_ks_inversion_calc(ks_inversion, namespace, space, gr, hm, ext_partners, st, vxc, time)
883 type(xc_ks_inversion_t), intent(inout) :: ks_inversion
884 type(namespace_t), intent(in) :: namespace
885 class(space_t), intent(in) :: space
886 type(grid_t), intent(in) :: gr
887 type(hamiltonian_elec_t), intent(in) :: hm
888 type(partner_list_t), intent(in) :: ext_partners
889 type(states_elec_t), intent(inout) :: st
890 real(real64), intent(inout) :: vxc(:, :)
891 real(real64), optional, intent(in) :: time
892
893 integer :: ispin, ip
894
895 if (ks_inversion%level == xc_ks_inversion_none) return
896
897 push_sub(x(xc_ks_inversion_calc))
898
899 if (optional_default(time, m_zero) > m_zero) then
900 write(message(1),'(A,F18.12)') 'xc_ks_inversion_calc - time:', time
901 call messages_info(1, namespace=namespace)
902 end if
903
904 ks_inversion%aux_hm%energy%intnvxc = m_zero
905 ks_inversion%aux_hm%energy%hartree = m_zero
906 ks_inversion%aux_hm%energy%exchange = m_zero
907 ks_inversion%aux_hm%energy%correlation = m_zero
908
909 call lalg_copy(gr%np, hm%ks_pot%vhartree, ks_inversion%aux_hm%ks_pot%vhartree)
910
911 if (optional_default(time, m_zero) > m_zero) then
912 call lalg_copy(gr%np, st%d%nspin, ks_inversion%vhxc_previous_step, ks_inversion%aux_hm%ks_pot%vhxc)
913
914 else
915! no restart data available, start with vhxc = vh, which we know from exact input rho
916 do ispin = 1, st%d%nspin
917 ks_inversion%aux_hm%ks_pot%vxc(1:gr%np, ispin) = m_zero !hm%ep%vpsl(:)
918 !$omp parallel do
919 do ip = 1, gr%np
920 ks_inversion%aux_hm%ks_pot%vhxc(ip, ispin) = hm%ks_pot%vhartree(ip) &
921 + ks_inversion%aux_hm%ks_pot%vxc(ip, ispin)
922 end do
923 !$omp end parallel do
924 end do
925! TODO: restart data found. Use first KS orbital to invert equation and get starting vhxc
926! call invertks_2part(ks_inversion%aux_st%rho, st%d%nspin, ks_inversion%aux_hm, gr, &
927! ks_inversion%aux_st, ks_inversion%eigensolver, namespace, ks_inversion%asymp)
928
929 end if
930 !ks_inversion%aux_hm%ep%vpsl(:) = M_ZERO ! hm%ep%vpsl(:)
931 call lalg_copy(gr%np, hm%ep%vpsl, ks_inversion%aux_hm%ep%vpsl)
932
933 ! compute ks inversion, vhxc contains total KS potential
934 ! Update the Hamiltonian
935 call invertks_update_hamiltonian(namespace, gr, space, ext_partners, &
936 ks_inversion%eigensolver, ks_inversion%aux_st, ks_inversion%aux_hm, ks_inversion%max_iter)
937
938
939 ! these 2 routines need to be cleaned - they are not consistent in updating
940 ! the hamiltonian, states, etc...
941 select case (ks_inversion%method)
942 ! adiabatic ks inversion
943 case (xc_inv_method_two_particle)
944 call invertks_2part(ks_inversion, ks_inversion%aux_st%rho, st%d%nspin, ks_inversion%aux_hm, gr, &
945 ks_inversion%aux_st, ks_inversion%eigensolver, namespace, space, ext_partners)
946
948 call invertks_iter(ks_inversion, st%rho, namespace, space, ext_partners, st%d%nspin, ks_inversion%aux_hm, gr, &
949 ks_inversion%aux_st, ks_inversion%eigensolver)
950 end select
951
952 ! subtract Hartree potential
953 ! ATTENTION: subtracts true external potential not adiabatic one
954
955 do ispin = 1, st%d%nspin
956 call lalg_axpy(gr%np, -m_one, hm%ks_pot%vhartree, ks_inversion%aux_hm%ks_pot%vhxc(:,ispin))
957 end do
958
959 vxc = ks_inversion%aux_hm%ks_pot%vxc
960
961 ! save vhxc for next step if we are running td
962 if (present(time)) then
963 call lalg_copy(gr%np, st%d%nspin, ks_inversion%aux_hm%ks_pot%vhxc, ks_inversion%vhxc_previous_step)
964 end if
965
966 pop_sub(x(xc_ks_inversion_calc))
967
968 end subroutine xc_ks_inversion_calc
969
970
971end module xc_ks_inversion_oct_m
972
973!! Local Variables:
974!! mode: f90
975!! coding: utf-8
976!! End:
constant times a vector plus a vector
Definition: lalg_basic.F90:173
Copies a vector x, to a vector y.
Definition: lalg_basic.F90:188
Some operations may be done for one spline-function, or for an array of them.
Definition: splines.F90:179
double floor(double __x) __attribute__((__nothrow__
This module implements a calculator for the density and defines related functions.
Definition: density.F90:122
subroutine, public density_calc(st, gr, density, istin)
Computes the density from the orbitals in st.
Definition: density.F90:653
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, hm, mc, space, deactivate_oracle)
subroutine, public eigensolver_end(eigens)
real(real64), parameter, public m_zero
Definition: global.F90:200
real(real64), parameter, public m_tiny
Definition: global.F90:217
integer, parameter, public kohn_sham_dft
Definition: global.F90:250
real(real64), parameter, public m_epsilon
Definition: global.F90:216
real(real64), parameter, public m_half
Definition: global.F90:206
real(real64), parameter, public m_one
Definition: global.F90:201
This module implements the underlying real-space grid.
Definition: grid.F90:119
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)
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...
Definition: io.F90:116
subroutine, public io_close(iunit, grp)
Definition: io.F90:467
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:402
A module to handle KS potential, without the external potential.
subroutine, public lasers_check_symmetries(this, kpoints)
Definition: lasers.F90:558
subroutine, public lasers_parse_external_fields(this)
Definition: lasers.F90:247
subroutine, public lasers_generate_potentials(this, mesh, space, latt)
Definition: lasers.F90:446
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
pure subroutine, public mesh_r(mesh, ip, rr, origin, coords)
return the distance to the origin for a given grid point
Definition: mesh.F90:342
subroutine, public messages_print_with_emphasis(msg, iunit, namespace)
Definition: messages.F90:898
subroutine, public messages_not_implemented(feature, namespace)
Definition: messages.F90:1068
character(len=512), private msg
Definition: messages.F90:167
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:525
subroutine, public messages_obsolete_variable(namespace, name, rep)
Definition: messages.F90:1000
subroutine, public messages_new_line()
Definition: messages.F90:1089
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:410
subroutine, public messages_input_error(namespace, var, details, row, column)
Definition: messages.F90:691
subroutine, public messages_experimental(name, namespace)
Definition: messages.F90:1040
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
This module handles the communicators for the various parallelization strategies.
Definition: multicomm.F90:147
subroutine, public spline_fit(nrc, rofi, ffit, spl, threshold)
Definition: splines.F90:413
subroutine, public spline_der2(spl, dspl, threshold, grid)
Returns a spline that contains the second derivative of the original spline.
Definition: splines.F90:889
real(real64) function, public spline_eval(spl, x)
Definition: splines.F90:441
subroutine, public spline_generate_shifted_grid(this, x_shifted)
Definition: splines.F90:1117
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.
Definition: unit.F90:134
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,...
Definition: xc.F90:120
Description of the grid, containing information on derivatives, stencil, and symmetries.
Definition: grid.F90:171
abstract class for general interaction partners
the basic spline datatype
Definition: splines.F90:156
The states_elec_t class contains all electronic wave functions.
int true(void)
subroutine write_iter()