Octopus
atomic.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
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
21module atomic_oct_m
22 use debug_oct_m
23 use global_oct_m
24 use, intrinsic :: iso_fortran_env
25 use logrid_oct_m
29 use sort_oct_m
30 use xc_f03_lib_m
31#ifdef HAVE_LIBXC_FUNCS
32 use xc_f03_funcs_m
33#endif
34 use iso_c_binding
35 implicit none
36
37 private
38 public :: &
39 atomxc, &
40 atomhxc, &
42
44 public :: &
45 valconf_t, &
52
53 character(len=1), parameter :: &
54 spec_notation(0:3) = (/ 's', 'p', 'd', 'f' /)
55
56 integer, parameter :: VALCONF_STRING_LENGTH = 80
57
58 type valconf_t
59 ! Components are public by default
60 integer :: z = 0
61 character(len=3) :: symbol = ""
62 integer :: type = 0
63 integer :: p = 0
64 integer :: n(15) = 0
65 integer :: l(15) = 0
66 real(real64) :: occ(15,2) = m_zero
67 real(real64) :: j(15) = m_zero
68 end type valconf_t
69
70
71contains
72
73 ! ---------------------------------------------------------
74 subroutine valconf_copy(cout, cin)
75 type(valconf_t), intent(out) :: cout
76 type(valconf_t), intent(in) :: cin
77
78 push_sub(valconf_copy)
79
80 cout%z = cin%z
81 cout%symbol = cin%symbol
82 cout%type = cin%type
83 cout%p = cin%p
84 cout%n = cin%n
85 cout%l = cin%l
86 cout%occ = cin%occ
87 cout%j = cin%j
88
89 pop_sub(valconf_copy)
90 end subroutine valconf_copy
91
92 subroutine valconf_sort_by_l(c, lmax)
93 type(valconf_t), intent(inout) :: c
94 integer, intent(in) :: lmax
95
96 integer :: ll
97 integer, allocatable :: order(:)
98 type(valconf_t) :: tmp_c
99
100 push_sub(valconf_sort_by_l)
101
102 call valconf_copy(tmp_c, c)
103
104 ! In order to work in the following, we need to sort the occupations by angular momentum
105 safe_allocate(order(1:lmax+1))
106 call sort(c%l(1:lmax+1), order)
107 do ll = 0, lmax
108 c%occ(ll+1, 1:2) = tmp_c%occ(order(ll+1), 1:2)
109 c%n(ll+1) = tmp_c%n(order(ll+1))
110 c%j(ll+1) = tmp_c%j(order(ll+1))
111 end do
112 safe_deallocate_a(order)
113
114 pop_sub(valconf_sort_by_l)
115 end subroutine valconf_sort_by_l
117 ! ---------------------------------------------------------
118 subroutine write_valconf(c, s)
119 type(valconf_t), intent(in) :: c
120 character(len=VALCONF_STRING_LENGTH), intent(out) :: s
121
122 integer :: j
123
124 push_sub(write_valconf)
125
126 write(s,'(i2,1x,a2,i1,1x,i1,a1,6(i1,a1,f6.3,a1))') c%z, c%symbol, c%type, c%p, ':',&
127 (c%n(j),spec_notation(c%l(j)),c%occ(j,1),',',j=1,c%p)
128
129 pop_sub(write_valconf)
130 end subroutine write_valconf
131
132
133 ! ---------------------------------------------------------
134 subroutine read_valconf(namespace, s, c)
135 type(namespace_t), intent(in) :: namespace
136 character(len=VALCONF_STRING_LENGTH), intent(in) :: s
137 type(valconf_t), intent(out) :: c
138
139 integer :: j
140 character(len=1) :: lvalues(1:6)
141
142 push_sub(read_valconf)
143
144 read (s,'(i2,1x,a2,i1,1x,i1,1x,6(i1,a1,f6.3,1x))') c%z, c%symbol, c%type, c%p,&
145 (c%n(j),lvalues(j),c%occ(j,1),j=1,c%p)
146 do j = 1, c%p
147 select case (lvalues(j))
148 case ('s')
149 c%l(j) = 0
150 case ('p')
151 c%l(j) = 1
152 case ('d')
153 c%l(j) = 2
154 case ('f')
155 c%l(j) = 3
156 case default
157 message(1) = 'read_valconf.'
158 call messages_fatal(1, namespace=namespace)
159 end select
160 end do
162 c%j = m_zero
163
164 pop_sub(read_valconf)
165 end subroutine read_valconf
166
167 !In case of spin-polarized calculations, we properly distribute the electrons
168 subroutine valconf_unpolarized_to_polarized(conf)
169 type(valconf_t), intent(inout) :: conf
170
171 integer :: ii, ll
172 real(real64) :: xx
173
175
176 do ii = 1, conf%p
177 ll = conf%l(ii)
178 xx = conf%occ(ii, 1)
179 conf%occ(ii, 1) = min(xx, real(2*ll+1, real64) )
180 conf%occ(ii, 2) = xx - conf%occ(ii,1)
181 end do
182
185
186
187 ! ---------------------------------------------------------
188 subroutine atomhxc(namespace, functl, g, nspin, dens, v, extra)
189 type(namespace_t), intent(in) :: namespace
190 character(len=*), intent(in) :: functl
191 type(logrid_t), intent(in) :: g
192 integer, intent(in) :: nspin
193 real(real64), intent(in) :: dens(g%nrval, nspin)
194 real(real64), intent(out) :: v(g%nrval, nspin)
195 real(real64), intent(in), optional :: extra(g%nrval)
196
197 character(len=5) :: xcfunc, xcauth
198 integer :: is, ir
199 real(real64), allocatable :: xc(:, :), ve(:, :), rho(:, :)
200 real(real64) :: r2, ex, ec, dx, dc
201
202 push_sub(atomhxc)
203
204 safe_allocate( ve(1:g%nrval, 1:nspin))
205 safe_allocate( xc(1:g%nrval, 1:nspin))
206 safe_allocate(rho(1:g%nrval, 1:nspin))
207 ve = m_zero
208 xc = m_zero
209 rho = m_zero
210
211 ! To calculate the Hartree term, we put all the density in one variable.
212 do is = 1, nspin
213 rho(:, 1) = rho(:, 1) + dens(:, is)
214 end do
215 ve = m_zero
216 do is = 1, nspin
217 call vhrtre(rho(:, 1), ve(:, is), g%rofi, g%drdi, g%s, g%nrval, g%a)
218 end do
219 ve(1, 1:nspin) = ve(2, 1:nspin)
220
221 select case (functl)
222 case ('LDA')
223 xcfunc = 'LDA'
224 xcauth = 'PZ'
225 case ('GGA')
226 xcfunc = 'GGA'
227 xcauth = 'PBE'
228 case default
229 message(1) = 'Internal Error in atomhxc: unknown functl'
230 call messages_fatal(1, namespace=namespace)
231 end select
232
233 rho(:, :) = dens(:, :)
234 do is = 1, nspin
235 if (present(extra)) rho(:, is) = rho(:, is) + extra(:)/nspin
236 rho(2:g%nrval, is) = rho(2:g%nrval, is)/(m_four*m_pi*g%r2ofi(2:g%nrval))
237 end do
238 r2 = g%rofi(2)/(g%rofi(3)-g%rofi(2))
239 rho(1, 1:nspin) = rho(2, 1:nspin) - (rho(3, 1:nspin)-rho(2, 1:nspin))*r2
240
241 do is = 1, nspin
242 do ir = 1, g%nrval
243 if (rho(ir, is) < m_epsilon) rho(ir, is) = m_zero
244 end do
245 end do
246
247 call atomxc(namespace, xcfunc, xcauth, g%nrval, g%nrval, g%rofi, nspin, rho, ex, ec, dx, dc, xc)
248 v = ve + xc
249
250 safe_deallocate_a(ve)
251 safe_deallocate_a(xc)
252 safe_deallocate_a(rho)
253
254 pop_sub(atomhxc)
255 end subroutine atomhxc
256
257
258!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
297 subroutine atomxc(namespace, FUNCTL, AUTHOR, NR, MAXR, RMESH, NSPIN, DENS, EX, EC, DX, DC, V_XC)
298 type(namespace_t), intent(in) :: namespace
299 character(len=*), intent(in) :: functl, author
300 integer, intent(in) :: nr, maxr
301 real(real64), intent(in) :: rmesh(maxr)
302 integer, intent(in) :: nspin
303 real(real64), intent(in) :: dens(maxr,nspin)
304 real(real64), intent(out) :: dc, dx, ec, ex, v_xc(maxr,nspin)
305
306!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
307! Internal parameters !
308! NN : order of the numerical derivatives: the number of radial !
309! points used is 2*NN+1 !
310!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
311
312 integer, parameter :: nn = 5
313
314!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
315! Fix energy unit: EUNIT=1.0 => Hartrees, !
316! EUNIT=0.5 => Rydbergs, !
317! EUNIT=0.03674903 => eV !
318!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
319
320 real(real64), parameter :: eunit = m_half
321
322!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
323! DVMIN is added to differential of volume to avoid division by zero !
324!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
325
326 real(real64), parameter :: dvmin = 1.0e-12_real64
327
328!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
329! Local variables and arrays !
330!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
331
332 logical :: gga
333 integer :: in, in1, in2, ir, is, jn
334 real(real64) :: aux(maxr), d(nspin), &
335 dgdm(-nn:nn), dgidfj(-nn:nn), drdm, dvol, &
336 f1, f2, gd(3,nspin), sigma(3), vxsigma(3), vcsigma(3), &
337 epsx(1), epsc(1), &
338 dexdd(nspin), dexdgd(3,nspin), decdd(nspin), decdgd(3,nspin)
339 type(xc_f03_func_t) :: x_conf, c_conf
340
341 push_sub(atomxc)
342
343 ! sanity check
344 assert(nspin == 1 .or. nspin == 2)
345
346 ! Set GGA switch
347 if (functl .eq. 'LDA' .or. functl .eq. 'lda' .or. &
348 functl .eq. 'LSD' .or. functl .eq. 'lsd') then
349 gga = .false.
350 else if (functl .eq. 'GGA' .or. functl .eq. 'gga') then
351 gga = .true.
352 else
353 gga = .false.
354 write(message(1),'(a,a)') 'atomxc: Unknown functional ', functl
355 call messages_fatal(1, namespace=namespace)
356 end if
357
358 ! initialize xc functional
359 if (gga) then
360 call xc_f03_func_init(x_conf, xc_gga_x_pbe, nspin)
361 call xc_f03_func_init(c_conf, xc_gga_c_pbe, nspin)
362 else
363 call xc_f03_func_init(x_conf, xc_lda_x, nspin)
364 if (author .eq. 'CA' .or. author .eq. 'ca' .or. &
365 author .eq. 'PZ' .or. author .eq. 'pz') then
366 call xc_f03_func_init(c_conf, xc_lda_c_pz, nspin)
367 else if (author .eq. 'PW92' .or. author .eq. 'pw92') then
368 call xc_f03_func_init(c_conf, xc_lda_c_pw, nspin)
369 else
370 write(message(1),'(a,a)') 'LDAXC: Unknown author ', author
371 call messages_fatal(1, namespace=namespace)
372 end if
373 end if
374
375!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
376! Initialize output !
377!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
378
379 ex = m_zero
380 ec = m_zero
381 dx = m_zero
382 dc = m_zero
383 do is = 1,nspin
384 do ir = 1,nr
385 v_xc(ir,is) = m_zero
386 end do
387 end do
388
389!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
390! Loop on mesh points !
391!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
393 do ir = 1,nr
394
395 ! Find interval of neighbour points to calculate derivatives
396 in1 = max( 1, ir-nn ) - ir
397 in2 = min( nr, ir+nn ) - ir
398
399 ! Find weights of numerical derivative from Lagrange
400 ! interpolation formula
401 do in = in1,in2
402 if (in == 0) then
403 dgdm(in) = 0
404 do jn = in1,in2
405 if (jn /= 0) dgdm(in) = dgdm(in) + m_one / (0 - jn)
406 end do
407 else
408 f1 = 1
409 f2 = 1
410 do jn = in1,in2
411 if (jn /= in .and. jn /= 0) f1 = f1 * (0 - jn)
412 if (jn /= in) f2 = f2 * (in - jn)
413 end do
414 dgdm(in) = f1 / f2
415 end if
416 end do
417
418 ! Find dr/dmesh
419 drdm = 0
420 do in = in1,in2
421 drdm = drdm + rmesh(ir+in) * dgdm(in)
422 end do
423
424 ! Find differential of volume. Use trapezoidal integration rule
425 dvol = 4 * m_pi * rmesh(ir)**2 * drdm
426
427 ! DVMIN is a small number added to avoid a division by zero
428 dvol = safe_tol(dvol, dvmin)
429 if (ir == 1 .or. ir == nr) dvol = dvol / 2
430 if (gga) aux(ir) = dvol
431
432 ! Find the weights for the derivative d(gradF(i))/d(F(j)), of
433 ! the gradient at point i with respect to the value at point j
434 if (gga) then
435 do in = in1,in2
436 dgidfj(in) = dgdm(in) / drdm
437 end do
438 end if
439
440 ! Find density and gradient of density at this point
441 do is = 1,nspin
442 d(is) = dens(ir,is)
443 end do
444 if (gga) then
445 do is = 1,nspin
446 gd(:,is) = m_zero
447 do in = in1,in2
448 gd(3,is) = gd(3,is) + dgidfj(in) * dens(ir+in,is)
449 end do
450 end do
451 else
452 gd = m_zero
453 end if
454
455 ! The xc_f03_gga routines need as input these combinations of
456 ! the gradient of the densities.
457 sigma(1) = gd(3, 1)*gd(3, 1)
458 if (nspin > 1) then
459 sigma(2) = gd(3, 1) * gd(3, 2)
460 sigma(3) = gd(3, 2) * gd(3, 2)
461 end if
462
463 ! Find exchange and correlation energy densities and their
464 ! derivatives with respect to density and density gradient
465 if (gga) then
466 call xc_f03_gga_exc_vxc(x_conf, int(1, c_size_t), d, sigma, epsx, dexdd, vxsigma)
467 call xc_f03_gga_exc_vxc(c_conf, int(1, c_size_t), d, sigma, epsc, decdd, vcsigma)
468 else
469 call xc_f03_lda_exc_vxc(x_conf, int(1, c_size_t), d, epsx, dexdd)
470 call xc_f03_lda_exc_vxc(c_conf, int(1, c_size_t), d, epsc, decdd)
471 end if
472
473 ! The derivatives of the exchange and correlation energies per particle with
474 ! respect to the density gradient have to be recovered from the derivatives
475 ! with respect to the sigma values defined above.
476 if (gga) then
477 dexdgd(:, 1) = m_two * vxsigma(1) * gd(:, 1)
478 decdgd(:, 1) = m_two * vcsigma(1) * gd(:, 1)
479 if (nspin == 2) then
480 dexdgd(:, 1) = dexdgd(:, 1) + vxsigma(2)*gd(:, 2)
481 dexdgd(:, 2) = m_two * vxsigma(3) * gd(:, 2) + vxsigma(2) * gd(:, 1)
482 decdgd(:, 1) = decdgd(:, 1) + vcsigma(2)*gd(:, 2)
483 decdgd(:, 2) = m_two * vcsigma(3) * gd(:, 2) + vcsigma(2) * gd(:, 1)
484 end if
485 end if
486
487 ! Add contributions to exchange-correlation energy and its
488 ! derivatives with respect to density at all points
489 do is = 1, nspin
490 ex = ex + dvol * d(is) * epsx(1)
491 ec = ec + dvol * d(is) * epsc(1)
492 dx = dx + dvol * d(is) * (epsx(1) - dexdd(is))
493 dc = dc + dvol * d(is) * (epsc(1) - decdd(is))
494 if (gga) then
495 v_xc(ir,is) = v_xc(ir,is) + dvol * (dexdd(is) + decdd(is))
496 do in = in1,in2
497 dx = dx - dvol * dens(ir+in,is) * dexdgd(3,is) * dgidfj(in)
498 dc = dc - dvol * dens(ir+in,is) * decdgd(3,is) * dgidfj(in)
499 v_xc(ir+in,is) = v_xc(ir+in,is) + dvol * &
500 (dexdgd(3,is) + decdgd(3,is)) * dgidfj(in)
501 end do
502 else
503 v_xc(ir,is) = dexdd(is) + decdd(is)
504 end if
505 end do
506
507 end do
508
509!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
510! Divide by volume element to obtain the potential (per electron) !
511!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
512
513 if (gga) then
514 do is = 1,nspin
515 do ir = 1,nr
516 dvol = aux(ir)
517 v_xc(ir,is) = v_xc(ir,is) / dvol
518 end do
519 end do
520 end if
521
522!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
523! Divide by energy unit !
524!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
525
526 ex = ex / eunit
527 ec = ec / eunit
528 dx = dx / eunit
529 dc = dc / eunit
530 do is = 1,nspin
531 do ir = 1,nr
532 v_xc(ir,is) = v_xc(ir,is) / eunit
533 end do
534 end do
535
536 call xc_f03_func_end(x_conf)
537 call xc_f03_func_end(c_conf)
538
539 pop_sub(atomxc)
540 end subroutine atomxc
541
542
543!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
562 subroutine vhrtre(rho, v, r, drdi, srdrdi, nr, a)
563 real(real64), intent(in) :: rho(:)
564 real(real64), intent(out) :: v(:)
565 real(real64), intent(in) :: r(:), drdi(:), srdrdi(:)
566 integer, intent(in) :: nr
567 real(real64), intent(in) :: a
568
569 real(real64) :: x,y,q,a2by4,ybyq,qbyy,qpartc,v0,qt,dz,t,beta,dv
570 integer :: nrm1,nrm2,ir
571
572 push_sub(vhrtre)
573
574 nrm1 = nr - 1
575 nrm2 = nr - 2
576 a2by4 = a*a/m_four
577 ybyq = m_one - a*a/48.0_real64
578 qbyy = m_one/ybyq
579
580!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
581! SIMPSON`S RULE IS USED TO PERFORM TWO INTEGRALS OVER THE ELECTRON !
582! DENSITY. THE TOTAL CHARGE QT IS USED TO FIX THE POTENTIAL AT R=R(NR) !
583! AND V0 (THE INTEGRAL OF THE ELECTRON DENSITY DIVIDED BY R) FIXES !
584! THE ELECTROSTATIC POTENTIAL AT THE ORIGIN !
585! Modified to be consistent with pseudopotential generation (use the !
586! trapezoidal rule for integration). A. Rubio. Jan. 2000 !
587!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
588
589 v0 = m_zero
590 qt = m_zero
591 do ir = 2, nrm1, 2
592 dz = drdi(ir)*rho(ir)
593 qt = qt + dz
594 v0 = v0 + dz/r(ir)
595 end do
596
597 do ir=3, nrm2, 2
598 dz = drdi(ir)*rho(ir)
599 qt = qt + dz
600 v0 = v0 + dz/r(ir)
601 end do
602 dz = drdi(nr)*rho(nr)
603
604 qt = (qt + qt + dz)*m_half
605 v0 = (v0 + v0 + dz/r(nr))
606 v(1) = m_two*v0
607
608!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
609! THE ELECTROSTATIC POTENTIAL AT R=0 IS SET EQUAL TO !
610! THE AVERAGE VALUE OF RHO(R)/R !
611! BEGIN CONSTRUCTION OF THE POTENTIAL AT FINITE !
612!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
613
614 ir = 2
615 t = srdrdi(ir)/r(ir)
616 beta = drdi(ir)*t*rho(ir)
617
618!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
619! THE NEXT 4 STATEMENTS INDICATE THAT WE FIRST FIND THE PARTICULAR !
620! SOLUTION TO THE INHOMOGENEOUS EQN. FOR WHICH Q(2)=0, WE THEN !
621! ADD TO THIS PARTICULAR SOLUTION A SOLUTION OF THE HOMOGENEOUS EQN. !
622! (A CONSTANT IN V OR A Q PROPORTIONAL TO R) !
623! WHICH WHEN DIVIDED BY R IN GOING FROM Q TO V GIVES !
624! THE POTENTIAL THE DESIRED COULOMB TAIL OUTSIDE THE ELECTRON DENSITY. !
625! THE SIGNIFICANCE OF THE SOLUTION VANISHING AT THE SECOND RADIAL !
626! MESH POINT IS THAT, SINCE ALL REGULAR SOLUTIONS OF THE EQUATION !
627! FOR Q=R*V VANISH AT THE ORIGIN, THE KNOWLEDGE OF THE SOLUTION !
628! VALUE AT THE SECOND MESH POINT PROVIDES THE TWO SOLUTION VALUES !
629! REQUIRED TO START THE NUMEROV PROCEDURE. !
630!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
631
632 x = m_zero
633 y = m_zero
634 q = (y - beta / 12.0_real64) * qbyy
635 v(ir) = m_two * t * q
636
637!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
638! BEGINNING OF THE NUMEROV ALGORITHM !
639!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
640
641 do ir = 2, nr
642 x = x + a2by4 * q - beta
643 y = y + x
644 t = srdrdi(ir) / r(ir)
645 beta = t * drdi(ir) * rho(ir)
646 q = (y - beta / 12.0_real64) * qbyy
647 v(ir) = m_two * t * q
648 end do
649
650!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
651! END OF THE NUMEROV ALGORITHM !
652! !
653! WE HAVE NOW FOUND A PARTICULAR SOLUTION TO THE INHOMOGENEOUS EQN. !
654! FOR WHICH Q(R) AT THE SECOND RADIAL MESH POINT EQUALS ZERO. !
655! NOTE THAT ALL REGULAR SOLUTIONS TO THE EQUATION FOR Q=R*V !
656! VANISH AT THE ORIGIN. !
657!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
658
659 qpartc = r(nr)*v(nr)/m_two
660 dz = qt - qpartc
661 dv = m_two*dz/r(nr)
662
663!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
664! THE LOOP FOLLOWING ADDS THE CONSTANT SOLUTION OF THE HOMOGENEOUS !
665! EQN TO THE PARTICULAR SOLUTION OF THE INHOMOGENEOUS EQN. !
666! NOTE THAT V(1) IS CONSTRUCTED INDEPENDENTLY !
667!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
668
669 do ir = 2, nr
670 v(ir) = v(ir) + dv
671 end do
672
673 pop_sub(vhrtre)
674 end subroutine vhrtre
675
676!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
677! FROM NOW, ON, ALL SUBROUTINES ARE IN DOUBLE PRECISION, NO MATTER IF THE CODE
678! IS COMPILED WITH SINGLE PRECISION OR NOT. APPARENTLY DOUBLE PRECISION IS
679! NEEDED FOR THESE PROCEDURES.
680!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
681
682!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
700 subroutine egofv(namespace, h, s, n, e, g, y, l, z, a, b, rmax, nprin, nnode, dr, ierr)
701 type(namespace_t), intent(in) :: namespace
702 real(real64), intent(in) :: h(:), s(:)
703 integer, intent(in) :: n
704 real(real64), intent(inout) :: e
705 real(real64), intent(out) :: g(:), y(:)
706 integer, intent(in) :: l
707 real(real64), intent(in) :: z, a, b, rmax
708 integer, intent(in) :: nprin, nnode
709 real(real64), intent(in) :: dr
710 integer, intent(out) :: ierr
711
712 integer :: i,ncor,n1,n2,niter,nt
713 real(real64) :: e1, e2, del, de, et, t
714 real(real64), parameter :: tol = 1.0e-5_real64
715
716 push_sub(egofv)
717
718 ncor = nprin-l-1
719 n1 = nnode
720 n2 = nnode-1
721 e1 = e
722 e2 = e
723 ierr = 1
724
725!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
726! !
727! the labels 1 and 2 refer to the bisection process, defining the !
728! range in which the desired solution is located. the initial !
729! settings of n1, n2, e1 and e2 are not consistent with the bisection !
730! algorithm; they are set to consistent values when the desired !
731! energy interval has been located. !
732! !
733!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
734
735 nt = 0
736 del = m_half
737 de = m_zero
738
739 do niter = 0, 40
740
741 et = e + de
742 ! the following line is the fundamental "bisection"
743 e = m_half*(e1+e2)
744
745!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
746! !
747! the following concatenation of logical ors ensures that node !
748! counting is used unless the previous integration of the radial !
749! eq produced both the correct number of nodes and a sensible !
750! prediction for the energy. !
751! !
752! sensible means that et must be greater than e1 and less than e2 !
753! correct number of nodes means that nt = nnode or nnode-1. !
754! !
755! leaving e set to its bisection value, and transfering to !
756! the call to yofe means that we are performing bisection, !
757! whereas setting e to et is use of the variational estimate. !
758! !
759!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
760
761
762 if (.not. (et <= e1 .or. et >= e2 .or. nt < nnode-1 .or. nt > nnode)) then
763 e = et
764 if (abs(de) < tol) then
765 ierr = 0
766 exit
767 end if
768 end if
769 call yofe(e,de,dr,rmax,h,s,y,n,l,ncor,nt,z,a,b)
770
771
772!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
773! !
774! yofe integrates the schro eq.; now the bisection logic !
775! !
776!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
777
778 if (nt < nnode) then
779 ! too few nodes; set e1 and n1
780 e1 = e
781 n1 = nt
782
783!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
784! !
785! at this point, we have just set the bottom of the bisection range; !
786! if the top is also set, we proceed. if the top of the range has not !
787! been set, it means that we have yet to find an e greater than the !
788! desired energy. the upper end of the range is extended. !
789! !
790!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
791
792 if (n2 >= nnode) cycle
793 del=del*m_two
794 e2=e1+del
795 cycle
796 end if
797
798 ! too many nodes; set e2 and n2
799 e2=e
800 n2=nt
801
802
803!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
804! !
805! at this point, we have just set the top of the bisection range; !
806! if the top is also set, we proceed. if the top of the range has !
807! not been set, it means that we have yet to find an e less than the !
808! desired energy. the lower end of the range is extended. !
809! !
810!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
811
812 if (n1 < nnode) cycle
813 del=del*m_two
814 e1=e2-del
815
816 end do
817
818!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
819! !
820! the Numerov method uses a transformation of the radial wavefunction. !
821! that we call "y". having located the eigenenergy, we transform !
822! y to "g", from which the density is easily constructed. !
823! finally, the call to "nrmlzg" normalizes g to one electron. !
824! !
825!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
826
827 if (ierr /= 1) then
828 g(1) = m_zero
829 do i = 2, n
830 t = h(i) - e * s(i)
831 g(i) = y(i) / (m_one - t / 12._real64)
832 end do
833 call nrmlzg(namespace, g, s, n)
834 end if
835
836 pop_sub(egofv)
837 end subroutine egofv
838
839
840 subroutine yofe(e,de,dr,rmax,h,s,y,nmax,l,ncor,nnode,z,a,b)
841
842
843!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
860
861 real(real64), intent(inout) :: e
862 real(real64), intent(out) :: de
863 real(real64), intent(in) :: dr, rmax
864 real(real64), intent(in) :: h(:), s(:)
865 real(real64), intent(out) :: y(:)
866 integer, intent(in) :: nmax, l
867 integer, intent(in) :: ncor
868 integer, intent(out) :: nnode
869 real(real64), intent(in) :: z, a, b
870
871 real(real64) :: y2, g, gsg, x, gin, gsgin, xin
872 integer :: n,knk,nndin,i
873 real(real64) :: zdr, yn, ratio, t
874
875 ! No PUSH SUB, called too often.
876
877 zdr = z*a*b
878
879 do n = nmax, 1, -1
880 if (h(n)-e*s(n) < m_one) then
881 knk = n
882 exit
883 end if
884 y(n) = m_zero
885 end do
886
887 call bcorgn(e,h,s,l,zdr,y2)
888
889
890!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
891! !
892! bcorgn computes y2, which embodies the boundary condition !
893! satisfied by the radial wavefunction at the origin !
894!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
895
896 call numout(e,h,s,y,ncor,knk,nnode,y2,g,gsg,x)
897
898!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
899! !
900! the outward integration is now complete !
901! !
902! we first decide if the kinetic energy is sufficiently non !
903! negative to permit use of the numerov eq at rmax. if !
904! it is not, then zero-value boundary condition is used !
905! !
906!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
907
908
909 yn = m_zero
910 if (.not. (n < nmax .or. abs(dr) > 1.e3_real64)) then
911 call bcrmax(e,dr,rmax,h,s,n,yn,a,b)
912 end if
913
914
915!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
916! !
917! bcrmax computes yn, which embodies the boundary condition !
918! satisfied by the radial wavefunction at rmax !
919! !
920!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
921
922 ! n should be larger than 1
923 n = max(n, 2)
924 knk = max(knk, 1)
925 call numin(e,h,s,y,n,nndin,yn,gin,gsgin,xin,knk)
926
927
928!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
929! !
930! numin performs the inward integration by the Numerov method !
931! !
932! the energy increment is now evaluated from the kink in psi !
933! !
934!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
936
937 ratio = g / gin
938 xin = xin * ratio
939 gsg = gsg + gsgin * ratio * ratio
940 t = h(knk) - e * s(knk)
941 de = g * (x + xin + t * g) / gsg
942 nnode = nnode + nndin
943 if (de < m_zero) nnode = nnode + 1
944
945 do i = knk, n
946 y(i) = y(i) * ratio
947 end do
948
949 end subroutine yofe
950
951
952 subroutine nrmlzg(namespace, g, s, n)
953
954
955!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
974 type(namespace_t), intent(in) :: namespace
975 real(real64), intent(inout) :: g(:)
976 real(real64), intent(in) :: s(:)
977 integer, intent(in) :: n
978
979 integer :: nm1,nm2,i
980 real(real64) :: norm, srnrm
981
982 push_sub(nrmlzg)
983
984!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
985! determine the norm of g(i) using Simpson`s rule !
986!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
987
988
989 if (mod(n,2) /= 1) then
990 write(message(1),'(a,i6)') ' nrmlzg: n should be odd. n =', n
991 call messages_warning(1, namespace=namespace)
992 end if
993
994 norm = m_zero
995 nm1 = n - 1
996 do i = 2,nm1,2
997 norm=norm + g(i)*s(i)*g(i)
998 end do
999 norm = norm * m_two
1000 nm2 = n - 2
1001 do i = 3,nm2,2
1002 norm=norm + g(i)*s(i)*g(i)
1003 end do
1004 norm = norm * m_two
1005 nm2 = n - 2
1006 do i = 1, n, nm1
1007 norm = norm + g(i) * s(i) * g(i)
1008 end do
1009 norm = norm / m_three
1010 srnrm = sqrt(norm)
1011 do i = 1, n
1012 g(i) = g(i) / srnrm
1013 end do
1014
1015 pop_sub(nrmlzg)
1016 end subroutine nrmlzg
1017
1018
1019 subroutine bcorgn(e,h,s,l,zdr,y2)
1020 real(real64), intent(in) :: e
1021 real(real64), intent(in) :: h(:), s(:)
1022 integer, intent(in) :: l
1023 real(real64), intent(in) :: zdr
1024 real(real64), intent(out) :: y2
1025
1026 real(real64) :: t2, t3, d2, c0, c1, c2
1027
1028 ! no PUSH SUB, called too often
1029
1030!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1031! the quantity called d(i) in the program is actually the inverse !
1032! of the diagonal of the tri-diagonal Numerov matrix !
1033!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1034
1035 t2 = h(2) - e * s(2)
1036 d2 = -((24._real64 + 10.0_real64 * t2) / (12._real64 - t2))
1037
1038!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1039! The following section deals with the fact that the independent !
1040! variable "y" in the Numerov equation is not zero at the origin !
1041! for l less than 2. !
1042! The l=0 solution g vanishes, but the first and second !
1043! derivatives are finite, making the Numerov variable y finite. !
1044! The l=1 solution g vanishes, and gprime also vanishes, but !
1045! The second derivative gpp is finite making y finite. For l > 1, !
1046! g and its first two derivatives vanish, making y zero. !
1047!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1048
1049 if (l < 2) then
1050 if (l <= 0) then
1051 c0=zdr/6.0_real64
1052 c0=c0/(m_one-0.75_real64*zdr)
1053 else
1054 c0=m_one/12._real64
1055 c0=(-c0)*8.0_real64/m_three
1056 end if
1057
1058 c1=c0*(12._real64+13._real64*t2)/(12._real64-t2)
1059 t3=h(3)-e*s(3)
1060 c2=(-m_half)*c0*(24._real64-t3)/(12._real64-t3)
1061 d2=(d2-c1)/(m_one-c2)
1062 end if
1063 y2=(-m_one)/d2
1064
1065 if (l < 2) then
1066 if (l <= 0) then
1067 c0=zdr/6.0_real64
1068 c0=c0/(m_one-0.75_real64*zdr)
1069 else
1070 c0=m_one/12._real64
1071 c0=(-c0)*8.0_real64/m_three
1072 end if
1073 c1=c0*(12._real64+13._real64*t2)/(12._real64-t2)
1074 t3=h(3)-e*s(3)
1075 c2=(-m_half)*c0*(24._real64-t3)/(12._real64-t3)
1076 d2=(d2-c1)/(m_one-c2)
1077 end if
1078 y2=(-m_one)/d2
1079
1080 end subroutine bcorgn
1081
1082
1083!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1084! 22.7.85 !
1085!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1086 subroutine bcrmax(e, dr, rmax, h, s, n, yn, a, b)
1087 real(real64), intent(in) :: e, dr, rmax
1088 real(real64), intent(in) :: h(:), s(:)
1089 integer, intent(in) :: n
1090 real(real64), intent(out) :: yn
1091 real(real64), intent(in) :: a, b
1092
1093 real(real64) :: tnm1, tn, tnp1, beta, dg, c1, c2, c3, dn
1094
1095 push_sub(bcrmax)
1096
1097 tnm1=h(n-1)-e*s(n-1)
1098 tn =h(n )-e*s(n )
1099 tnp1=h(n+1)-e*s(n+1)
1100 beta=m_one+b/rmax
1101 dg=a*beta*(dr+m_one-m_half/beta)
1102
1103 c2=24._real64*dg/(12._real64-tn)
1104 dn=-((24._real64+10._real64*tn)/(12._real64-tn))
1105
1106 c1= (m_one-tnm1/6.0_real64)/(m_one-tnm1/12._real64)
1107 c3=-((m_one-tnp1/6.0_real64)/(m_one-tnp1/12._real64))
1108 yn=-((m_one-c1/c3)/(dn-c2/c3))
1109
1110 pop_sub(bcrmax)
1111 end subroutine bcrmax
1112
1113
1114 subroutine numin(e,h,s,y,n,nnode,yn,g,gsg,x,knk)
1115 real(real64), intent(in) :: e, h(:), s(:)
1116 real(real64), intent(inout) :: y(:)
1117 integer, intent(in) :: n
1118 integer, intent(out) :: nnode
1119 real(real64), intent(in) :: yn
1120 real(real64), intent(out) :: g, gsg, x
1121 integer, intent(in) :: knk
1122
1123 integer :: i
1124 real(real64) :: t
1125
1126 ! no PUSH SUB, called too often
1127
1128 y(n)=yn
1129 t=h(n)-e*s(n)
1130 g=y(n)/(m_one-t/12._real64)
1131 gsg=g*s(n)*g
1132 i=n-1
1133 y(i)=m_one
1134 t=h(i)-e*s(i)
1135 g=y(i)/(m_one-t/12._real64)
1136 gsg=gsg+g*s(i)*g
1137 x=y(i)-y(n)
1138 nnode=0
1139
1140
1141!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1142! !
1143! begin the inward integration by the Numerov method !
1144! !
1145!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1146
1147 assert(knk > 0)
1148
1149 do i = n - 2, knk, -1
1150 x = x + t * g
1151 y(i) = y(i+1) + x
1152 ! y(i) * y(i+1) can lead to overflows. This is now prevented
1153 ! by comparing only the signs
1154 if (sign(m_one,y(i)) * sign(m_one,y(i+1)) < m_zero) nnode = nnode + 1
1155 t = h(i) - e * s(i)
1156 g = y(i) / (m_one - t / 12._real64)
1157 gsg = gsg + g * s(i) * g
1158 end do
1159
1160
1161!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1162! !
1163! The kink radius is defined as the point where !
1164! psi first turns downward. this usually means at the outermost !
1165! maximum !
1166! !
1167! the inward integration is now complete !
1168! !
1169!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1170
1171 end subroutine numin
1172
1173
1174 subroutine numout(e, h, s, y, ncor, knk, nnode, y2, g, gsg, x)
1175 real(real64), intent(in) :: e, h(:), s(:)
1176 real(real64), intent(inout) :: y(:)
1177 integer, intent(in) :: ncor
1178 integer, intent(inout) :: knk
1179 integer, intent(out) :: nnode
1180 real(real64), intent(in) :: y2
1181 real(real64), intent(out) :: g, gsg, x
1182
1183 integer :: i, nm4
1184 real(real64) :: t, xl
1185
1186 ! no PUSH SUB, called too often
1187
1188 y(1)=m_zero
1189 y(2)=y2
1190 t=h(2)-e*s(2)
1191 g=y(2)/(m_one-t/12._real64)
1192 gsg=g*s(2)*g
1193 y(3)=m_one
1194 t=h(3)-e*s(3)
1195 g=y(3)/(m_one-t/12._real64)
1196 gsg=gsg+g*s(3)*g
1197 x=y(3)-y(2)
1198 nnode=0
1199
1200!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1201! !
1202! begin the outward integration by the Numerov method !
1203! !
1204!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1205
1206 nm4 = knk - 4
1207 knk = nm4
1208 do i = 4, nm4
1209 xl = x
1210 x = x + t * g
1211 y(i) = y(i-1) + x
1212 ! y(i) * y(i-1) can lead to overflows. This is now prevented
1213 ! by comparing only the signs
1214 if (sign(m_one,y(i)) * sign(m_one,y(i-1)) < m_zero) nnode = nnode + 1
1215 t = h(i) - e * s(i)
1216 g = y(i) / (m_one - t / 12._real64)
1217 gsg = gsg + g * s(i) * g
1218 if (.not. (nnode < ncor .or. xl*x > m_zero)) then
1219 knk = i
1220 exit
1221 end if
1222 end do
1223
1224!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1225! !
1226! the outward integration is now complete !
1227! !
1228!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1229 end subroutine numout
1230
1231end module atomic_oct_m
1232
1233!! Local Variables:
1234!! mode: f90
1235!! coding: utf-8
1236!! End:
This is the common interface to a sorting routine. It performs the shell algorithm,...
Definition: sort.F90:151
double sqrt(double __x) __attribute__((__nothrow__
subroutine bcrmax(e, dr, rmax, h, s, n, yn, a, b)
Definition: atomic.F90:1182
subroutine, public atomhxc(namespace, functl, g, nspin, dens, v, extra)
Definition: atomic.F90:284
subroutine, public write_valconf(c, s)
Definition: atomic.F90:214
subroutine nrmlzg(namespace, g, s, n)
Definition: atomic.F90:1048
subroutine yofe(e, de, dr, rmax, h, s, y, nmax, l, ncor, nnode, z, a, b)
Definition: atomic.F90:936
subroutine, public atomxc(namespace, FUNCTL, AUTHOR, NR, MAXR, RMESH, NSPIN, DENS, EX, EC, DX, DC, V_XC)
Finds total exchange-correlation energy and potential for a ! spherical electron density distribution...
Definition: atomic.F90:393
subroutine, public valconf_unpolarized_to_polarized(conf)
Definition: atomic.F90:264
integer, parameter, public valconf_string_length
Definition: atomic.F90:151
subroutine, public valconf_copy(cout, cin)
Definition: atomic.F90:170
subroutine, public valconf_sort_by_l(c, lmax)
Definition: atomic.F90:188
subroutine, public read_valconf(namespace, s, c)
Definition: atomic.F90:230
subroutine numin(e, h, s, y, n, nnode, yn, g, gsg, x, knk)
Definition: atomic.F90:1210
subroutine numout(e, h, s, y, ncor, knk, nnode, y2, g, gsg, x)
Definition: atomic.F90:1270
subroutine bcorgn(e, h, s, l, zdr, y2)
Definition: atomic.F90:1115
subroutine, public vhrtre(rho, v, r, drdi, srdrdi, nr, a)
VHRTRE CONSTRUCTS THE ELECTROSTATIC POTENTIAL DUE TO A SUPPLIED ! ELECTRON DENSITY....
Definition: atomic.F90:658
subroutine, public egofv(namespace, h, s, n, e, g, y, l, z, a, b, rmax, nprin, nnode, dr, ierr)
egofv determines the eigenenergy and wavefunction corresponding ! to a particular l,...
Definition: atomic.F90:796
real(real64), parameter, public m_two
Definition: global.F90:193
real(real64), parameter, public m_zero
Definition: global.F90:191
real(real64), parameter, public m_four
Definition: global.F90:195
real(real64), parameter, public m_pi
some mathematical constants
Definition: global.F90:189
real(real64), parameter, public m_epsilon
Definition: global.F90:207
type(conf_t), public conf
Global instance of Octopus configuration.
Definition: global.F90:181
real(real64), parameter, public m_half
Definition: global.F90:197
real(real64), parameter, public m_one
Definition: global.F90:192
real(real64), parameter, public m_three
Definition: global.F90:194
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:525
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
This module is intended to contain "only mathematical" functions and procedures.
Definition: sort.F90:119
int true(void)