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