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