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