2
C$Id: scf.f,v 1.3 1997-03-04 06:17:21 d3e129 Exp $
3
implicit double precision (a-h, o-z)
6
dimension orbs(nbfn*nbfn), dens(nnbfn), fock(nnbfn),
7
$ work(nbfn*nbfn), evals(nbfn)
8
data tinit, tonel, ttwoel, tdiag, tdens, tprint /6*0.0d0/
9
data eone, etwo, energy, deltad /4*0.0d0/
11
c initalize the parallel message passing environment
18
c initialize a bunch of stuff and initial density matrix
22
call denges(dens, work)
25
c make initial orthogonal orbital set for jacobi diagonalizer
27
call makeob(orbs, work)
31
do 10 iter = 1, mxiter
33
c make info for sparsity test ... redone every iter to save space
35
call makesz(work, schwmax)
37
c make the one particle contribution to the fock matrix (in fock)
38
c and the partial contribution to the energy
40
call oneel(dens, work, schwmax, fock, eone)
41
call dgop(1, eone, 1, '+')
42
tonel = tonel + timer()
44
c compute the two particle contribution and then add up the
45
c contributions from each process with dgop
47
call twoel(dens, work, schwmax, fock, etwo)
48
call dgop(2, etwo, 1, '+')
49
call dgop(3, fock, nnbfn, '+')
50
ttwoel = ttwoel + timer()
52
c only process 0 diagonalizes and updates the density
56
c diagonalize the fock matrix ...
58
call diagon(fock, orbs, evals, work, tester, iter)
60
tdiag = tdiag + timer()
62
c make the new density matrix in work from orbitals in orbs,
63
c compute the norm of the change in the density matrix and
64
c then update the density matrix in dens with damping.
66
call makden(orbs, work)
67
deltad = dendif(dens, work)
70
else if (iter .le. 5) then
71
if (nbfn .gt. 60) then
79
call damp(scale, dens, work)
80
tdens = tdens + timer()
82
c add up energy and print out convergence information
84
energy = enrep + eone + etwo
85
call prnout(iter, energy, deltad, tester)
86
tprint = tprint + timer()
89
c brodcast new density matrix and deltad to everyone
91
call brdcst(4+MSGDBL, dens, mdtob(nnbfn), 0)
92
call brdcst(5+MSGDBL, deltad, mdtob(1), 0)
94
c if converged then exit iteration loop
96
if (deltad .lt. tol) goto 20
99
$ write(6,*) ' SCF failed to converge in ', mxiter, ' iters'
101
c finished ... print out eigenvalues and occupied orbitals
104
call igop(6, icut1, 1, '+')
105
call igop(7, icut2, 1, '+')
106
call igop(8, icut3, 1, '+')
109
c print out timing information
111
call prnfin(energy, evals, orbs)
112
write(6,1) tinit, tonel, ttwoel, tdiag, tdens, tprint,
114
1 format(/' init onel twoel diag dens print ncpu'/
115
$ ' ------ ------ ------ ------ ------ ------ ------'/
118
c print out information on # integrals evaulated each iteration
120
nints = nnbfn*(nnbfn+1)/2
121
frac = dble(icut3)/dble(nints)
122
write(6,2) icut1, icut2, icut3, nints, frac
123
2 format(/' No. of integrals screened or computed '
124
$ /' -------------------------------------'/
125
$ /1x,' #ij test #kl test #compute #total',
127
$ /1x,' --------- --------- --------- ---------',
137
subroutine makesz(schwarz, schwmax)
138
implicit double precision (a-h, o-z)
140
include 'msgtypesf.h'
141
dimension schwarz(nnbfn)
143
c schwarz(ij) = (ij|ij) for sparsity test
150
call dfill(nnbfn, 0.0d0, schwarz, 1)
157
if (mod(ij,nproc).eq.me) then
158
call g(gg, i, j, i, j)
159
schwarz(ij) = sqrt(gg)
160
schwmax = max(schwmax, schwarz(ij))
165
call dgop(101+MSGDBL, schwarz, nnbfn, '+')
166
call dgop(102+MSGDBL, schwmax, 1, 'max')
170
implicit double precision (a-h, o-z)
173
c write a little welcome message
175
if (nodeid().eq.0) write(6,1) natom, nocc, nbfn, tol
176
1 format(/' Example Direct Self Consistent Field Program '/
177
$ ' -------------------------------------------- '//
178
$ ' no. of atoms ............... ',i3/
179
$ ' no. of occupied orbitals ... ',i3/
180
$ ' no. of basis functions ..... ',i3/
181
$ ' convergence threshold ...... ',d9.2//)
183
c generate normalisation coefficients for the basis functions
184
c and the index array iky
191
rnorm(i) = (expnt(i)*2.0d0/pi)**0.75d0
194
c initialize common for computing f0
199
double precision function h(i,j)
200
implicit double precision (a-h, o-z)
205
c generate the one particle hamiltonian matrix element
206
c over the normalized primitive 1s functions i and j
210
rab2 = (x(i)-x(j))**2 + (y(i)-y(j))**2 + (z(i)-z(j))**2
211
facij = expnt(i)*expnt(j)/(expnt(i)+expnt(j))
212
expij = exprjh(-facij*rab2)
213
repij = (2.0d0*pi/(expnt(i)+expnt(j))) * expij
215
c first do the nuclear attraction integrals
218
xp = (x(i)*expnt(i) + x(j)*expnt(j))/(expnt(i)+expnt(j))
219
yp = (y(i)*expnt(i) + y(j)*expnt(j))/(expnt(i)+expnt(j))
220
zp = (z(i)*expnt(i) + z(j)*expnt(j))/(expnt(i)+expnt(j))
221
rpc2 = (xp-ax(iat))**2 + (yp-ay(iat))**2 + (zp-az(iat))**2
223
call f0(f0val, (expnt(i)+expnt(j))*rpc2)
224
sum = sum - repij * q(iat) * f0val
227
c add on the kinetic energy term
229
sum = sum + facij*(3.0d0-2.0d0*facij*rab2) *
230
$ (pi/(expnt(i)+expnt(j)))**1.5d0 * expij
232
c finally multiply by the normalization constants
234
h = sum * rnorm(i) * rnorm(j)
237
double precision function s(i,j)
238
implicit double precision (a-h, o-z)
241
c generate the overlap matrix element between the normalized
242
c primitve gaussian 1s functions i and j
244
rab2 = (x(i)-x(j))**2 + (y(i)-y(j))**2 + (z(i)-z(j))**2
245
facij = expnt(i)*expnt(j)/(expnt(i)+expnt(j))
246
s = (pi/(expnt(i)+expnt(j)))**1.5d0 * exprjh(-facij*rab2) *
250
subroutine makden(orbs, dens)
251
implicit double precision (a-h, o-z)
253
dimension orbs(nbfn, nbfn), dens(nnbfn)
255
c generate density matrix from orbitals in orbs. the first
256
c nocc orbitals are doubly occupied. Note that the diagonal
257
c elements are scaled by 0.5
264
p = p + orbs(i,k)*orbs(j,k)
269
dens(ij) = dens(ij)*0.5d0
273
subroutine oneel(dens, schwarz, schwmax, fock, eone)
274
implicit double precision (a-h, o-z)
276
dimension dens(nnbfn), fock(nnbfn), schwarz(nnbfn)
278
c fill in the one-electron part of the fock matrix and
279
c compute the one-electron energy contribution
281
c simple structure to share out the work between processes
286
call dfill(nnbfn, 0.0d0, fock, 1)
287
do 10 i = me+1, nbfn, nproc
290
if (schwarz(ij)*schwmax.gt.tol2e) fock(ij) = h(i,j)
293
eone = ddot(nnbfn, fock, 1, dens, 1)
296
integer function nxtask(nproc)
297
parameter (ichunk = 10)
299
data nleft, icount /0, 0/
301
c wrapper round nxtval() to increase granularity
302
c and thus reduce no. of requests to shared counter
306
icount = nxtval(nproc) * ichunk
318
c following does dumb static load balancing
320
c$$$ if(nproc.gt.0) then
321
c$$$ if (nleft .eq. 0) then
322
c$$$ icount = nodeid()
326
c$$$ icount = icount + nnodes()
332
subroutine twoel(dens, schwarz, schwmax, fock, etwo)
333
implicit double precision (a-h, o-z)
335
dimension dens(nnbfn), fock(nnbfn), schwarz(nnbfn)
337
c add in the two-electron contribution to the fock matrix
343
next = nnbfn - nxtask(nproc)
344
do 10 i = nbfn, 1, -1
347
if (ij .eq. next) then
348
if (schwarz(ij)*schwmax .lt. tol2e) then
356
if (schwarz(ij)*schwarz(kl).lt.tol2e) then
361
c compute value of integral (ij|kl) and add into fock matrix
363
call g(gg, i, j, k, l)
364
call addin(gg*0.5d0, i, j, k, l, fock,
370
next = nnbfn - nxtask(nproc)
375
etwo = ddot(nnbfn, fock, 1, dens, 1)
377
c wait for all processes to finish work
379
junk = nxtask(-nproc)
382
subroutine damp(fac, dens, work)
383
implicit double precision (a-h, o-z)
385
dimension dens(nnbfn), work(nnbfn)
389
dens(i) = fac*dens(i) + ofac*work(i)
393
subroutine prnout(iter, energy, deltad, tester)
394
implicit double precision (a-h, o-z)
397
c printout results of each iteration
399
write(6,1) iter, energy, deltad, tester
401
1 format(' iter=',i3,', energy=',f13.8,', deltad=',d9.2,
405
double precision function dendif(dens, work)
406
implicit double precision (a-h, o-z)
408
dimension dens(nnbfn), work(nnbfn)
410
c compute largest change in density matrix elements
414
denmax = max(denmax, abs(work(i)-dens(i)))
419
subroutine prnfin(energy, evals, orbs)
420
implicit double precision (a-h, o-z)
422
dimension evals(nbfn), orbs(nbfn, nbfn)
424
c printout final results
427
1 format(//' final energy = ',f16.11//' eigenvalues')
428
call output(evals, 1, min(nbfn,nocc+5), 1, 1, nbfn, 1, 1)
430
2 format(//' eigenvectors ')
431
call output(orbs, 1, nbfn, 1, nocc, nbfn, nbfn, 1)
434
subroutine g(value,i,j,k,l)
435
implicit double precision (a-h, o-z)
438
c compute the two electon integral (ij|kl) over normalized
439
c primitive 1s gaussians
442
rab2 = (x(i)-x(j))**2 + (y(i)-y(j))**2 + (z(i)-z(j))**2
443
rcd2 = (x(k)-x(l))**2 + (y(k)-y(l))**2 + (z(k)-z(l))**2
444
facij = expnt(i)*expnt(j)/(expnt(i)+expnt(j))
445
fackl = expnt(k)*expnt(l)/(expnt(k)+expnt(l))
446
exijkl = exprjh(- facij*rab2 - fackl*rcd2)
447
denom = (expnt(i)+expnt(j))*(expnt(k)+expnt(l)) *
448
$ sqrt(expnt(i)+expnt(j)+expnt(k)+expnt(l))
449
fac = (expnt(i)+expnt(j))*(expnt(k)+expnt(l)) /
450
$ (expnt(i)+expnt(j)+expnt(k)+expnt(l))
452
xp = (x(i)*expnt(i) + x(j)*expnt(j))/(expnt(i)+expnt(j))
453
yp = (y(i)*expnt(i) + y(j)*expnt(j))/(expnt(i)+expnt(j))
454
zp = (z(i)*expnt(i) + z(j)*expnt(j))/(expnt(i)+expnt(j))
455
xq = (x(k)*expnt(k) + x(l)*expnt(l))/(expnt(k)+expnt(l))
456
yq = (y(k)*expnt(k) + y(l)*expnt(l))/(expnt(k)+expnt(l))
457
zq = (z(k)*expnt(k) + z(l)*expnt(l))/(expnt(k)+expnt(l))
458
rpq2 = (xp-xq)**2 + (yp-yq)**2 + (zp-zq)**2
460
call f0(f0val, fac*rpq2)
461
value = (2.0d0 * pi**2.5d0 / denom) * exijkl * f0val *
462
$ rnorm(i)*rnorm(j)*rnorm(k)*rnorm(l)
465
subroutine diagon(fock, orbs, evals, work, tester, iter)
466
implicit double precision (a-h, o-z)
468
dimension fock(nnbfn), orbs(nbfn, nbfn), evals(nbfn),
470
dimension ilifq(nbfn), work2(nbfn*nbfn)
473
ilifq(i) = (i-1)*nbfn
476
c transform fock matrix from AO to MO basis
478
call zsqua(nbfn, fock, work)
479
call dgemm('n', 'n', nbfn, nbfn, nbfn, 1.0d0,
480
$ work, nbfn, orbs, nbfn, 0.0d0, work2, nbfn)
481
call dgemm('t', 'n', nbfn, nbfn, nbfn, 1.0d0,
482
$ orbs, nbfn, work2, nbfn, 0.0d0, work, nbfn)
483
call zfold(nbfn, fock, work)
490
tester = max(tester, abs(fock(iky(i)+j)))
494
if (tester.gt.0.3d0) then
497
if (nbfn .gt. 60) then
504
do 40 i = nocc+1, nbfn
505
fock(iky(i)+i) = fock(iky(i)+i) + shift
508
thresh = min(0.0001d0,max(1.0d-12,tester*0.01d0))
509
call jacobi(fock, iky, nbfn, orbs, ilifq, nbfn, evals, iop1,
512
do 50 i = nocc+1, nbfn
513
evals(i) = evals(i) - shift
518
subroutine makeob(orbs, work)
519
implicit double precision (a-h, o-z)
521
include 'msgtypesf.h'
522
dimension orbs(nbfn,nbfn), work(nbfn,nbfn)
523
dimension tmp1(nbfn), tmp2(nbfn)
525
c generate set of orthonormal vectors by orthoging twice
526
c a set of random vectors ... don't do this at home!
527
c ... should really diagonalize the overlap to get sym adaption
529
if (nodeid().eq.0) then
534
orbs(j,i) = drand48(0)
537
call orthv2(nbfn, orbs, work, tmp1, tmp2)
538
call orthv2(nbfn, orbs, work, tmp1, tmp2)
540
call brdcst(99+MSGDBL, orbs, mdtob(nbfn*nbfn), 0)
543
subroutine denges(dens, work)
544
implicit double precision (a-h, o-z)
546
dimension dens(nnbfn), work(nbfn, nbfn)
548
c Form guess density from superposition of atomic densities in the AO
549
c basis set ... instead of doing the atomic SCF hardwire for this
550
c small basis set for the Be atom.
552
dimension atdens(15,15)
554
$ 0.000002,0.000027,0.000129,0.000428,0.000950,0.001180,
555
$ 0.000457,-0.000270,-0.000271,0.000004,0.000004,0.000004,
556
$ 0.000004,0.000004,0.000004,0.000027,0.000102,0.000987,
557
$ 0.003269,0.007254,0.009007,0.003492,-0.002099,-0.002108,
558
$ 0.000035,0.000035,0.000035,0.000035,0.000035,0.000035,
559
$ 0.000129,0.000987,0.002381,0.015766,0.034988,0.043433,
560
$ 0.016835,-0.010038,-0.010082,0.000166,0.000166,0.000166,
561
$ 0.000166,0.000166,0.000166,0.000428,0.003269,0.015766,
562
$ 0.026100,0.115858,0.144064,0.055967,-0.035878,-0.035990,
563
$ 0.000584,0.000584,0.000584,0.000584,0.000584,0.000584,
564
$ 0.000950,0.007254,0.034988,0.115858,0.128586,0.320120,
565
$ 0.124539,-0.083334,-0.083536,0.001346,0.001346,0.001346,
566
$ 0.001346,0.001346,0.001346,0.001180,0.009007,0.043433,
567
$ 0.144064,0.320120,0.201952,0.159935,-0.162762,-0.162267,
568
$ 0.002471,0.002471,0.002471,0.002471,0.002471,0.002471,
569
$ 0.000457,0.003492,0.016835,0.055967,0.124539,0.159935,
570
$ 0.032378,-0.093780,-0.093202,0.001372,0.001372,0.001372,
571
$ 0.001372,0.001372,0.001372,-0.000270,-0.002099,-0.010038,
572
$ -0.035878,-0.083334,-0.162762,-0.093780,0.334488,0.660918,
573
$ -0.009090,-0.009090,-0.009090,-0.009090,-0.009090,-0.009090,
574
$ -0.000271,-0.002108,-0.010082,-0.035990,-0.083536,-0.162267,
575
$ -0.093202,0.660918,0.326482,-0.008982,-0.008982,-0.008981,
576
$ -0.008981,-0.008981,-0.008982,0.000004,0.000035,0.000166,
577
$ 0.000584,0.001346,0.002471,0.001372,-0.009090,-0.008982,
578
$ 0.000062,0.000124,0.000124,0.000124,0.000124,0.000124,
579
$ 0.000004,0.000035,0.000166,0.000584,0.001346,0.002471,
580
$ 0.001372,-0.009090,-0.008982,0.000124,0.000062,0.000124,
581
$ 0.000124,0.000124,0.000124,0.000004,0.000035,0.000166,
582
$ 0.000584,0.001346,0.002471,0.001372,-0.009090,-0.008981,
583
$ 0.000124,0.000124,0.000062,0.000124,0.000124,0.000124,
584
$ 0.000004,0.000035,0.000166,0.000584,0.001346,0.002471,
585
$ 0.001372,-0.009090,-0.008981,0.000124,0.000124,0.000124,
586
$ 0.000062,0.000124,0.000124,0.000004,0.000035,0.000166,
587
$ 0.000584,0.001346,0.002471,0.001372,-0.009090,-0.008981,
588
$ 0.000124,0.000124,0.000124,0.000124,0.000062,0.000124,
589
$ 0.000004,0.000035,0.000166,0.000584,0.001346,0.002471,
590
$ 0.001372,-0.009090,-0.008982,0.000124,0.000124,0.000124,
591
$ 0.000124,0.000124,0.000062/
593
call dfill(nbfn*nbfn,0.0d0,work,1)
598
work(ioff+j,ioff+i) = atdens(j,i)*0.5d0
603
call zfold(nbfn,dens,work)