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