|
| 1 | +!**************************************************************************** |
| 2 | +! |
| 3 | +! PROGRAM: HeHSCF |
| 4 | +! |
| 5 | +!**************************************************************************** |
| 6 | + |
| 7 | +program HeHSCF |
| 8 | + implicit none |
| 9 | + real*8 :: IOP, R, ZETA1, ZETA2, ZA, ZB |
| 10 | + integer :: N |
| 11 | + IOP=3 |
| 12 | + N=3 |
| 13 | + R=1.4632D0 |
| 14 | + ZETA1=2.0925D0 |
| 15 | + ZETA2=1.24D0 |
| 16 | + ZA=2.0D0 |
| 17 | + ZB=1.0D0 |
| 18 | + CALL HFCALC(IOP, N, R, ZETA1, ZETA2, ZA, ZB) |
| 19 | +end program HeHSCF |
| 20 | + |
| 21 | +subroutine HFCALC(IOP, N, R, ZETA1, ZETA2, ZA, ZB) |
| 22 | + implicit none |
| 23 | + real*8 :: IOP, R, ZETA1, ZETA2, ZA, ZB |
| 24 | + integer :: N |
| 25 | + if (IOP /= 0) then |
| 26 | + write(*, 10) N, ZA, ZB |
| 27 | + endif |
| 28 | + call INTGRL(IOP, N, R, ZETA1, ZETA2, ZA, ZB) |
| 29 | + call COLECT(IOP, N, R, ZETA1, ZETA2, ZA, ZB) |
| 30 | + call SCF(IOP, N, R, ZETA1, ZETA2, ZA, ZB) |
| 31 | +10 format(' ',2X,'STO-',I1,'G FOR ATOMIC NUMBERS ',F5.2,' AND ',F5.2//) |
| 32 | + return |
| 33 | +end subroutine HFCALC |
| 34 | + |
| 35 | +subroutine INTGRL(IOP,N,R,ZETA1,ZETA2,ZA,ZB) |
| 36 | + implicit none |
| 37 | + real*8 :: IOP, R, ZETA1, ZETA2, ZA, ZB |
| 38 | + integer :: N |
| 39 | + real*8 :: R2,RAP,RBP,RAQ,RBQ,RPQ,RAP2,RBP2,RAQ2,RBQ2,RPQ2 |
| 40 | + real*8 :: S12,T11,T12,T22,V11A,V12A,V22A,V11B,V12B,V22B,V1111,V2111,V2121,V2211,V2221,V2222 |
| 41 | + common /INT/ S12,T11,T12,T22,V11A,V12A,V22A,V11B,V12B,V22B,V1111,V2111,V2121,V2211,V2221,V2222 |
| 42 | + real*8 :: COEF(3,3),EXPON(3,3),D1(3),A1(3),D2(3),A2(3) |
| 43 | + real*8 :: PI=3.1415926535898D0 |
| 44 | + integer I,J,K,L |
| 45 | + real*8, external :: S,T,V,TWOE |
| 46 | + DATA COEF,EXPON /1.0D0,2*0.0D0,0.678914D0,0.430129D0,0.0D0,0.444635D0,0.535328D0,0.154329D0,& |
| 47 | + 0.270950D0,2*0.0D0,0.151623D0,0.851819D0,0.0D0,0.109818D0,0.405771D0,2.22766D0/ |
| 48 | + R2=R*R |
| 49 | + do I=1,N |
| 50 | + A1(I)=EXPON(I,N)*(ZETA1**2) |
| 51 | + D1(I)=COEF(I,N)*((2.0D0*A1(I)/PI)**0.75D0) |
| 52 | + A2(I)=EXPON(I,N)*(ZETA2**2) |
| 53 | + D2(I)=COEF(I,N)*((2.0D0*A2(I)/PI)**0.75D0) |
| 54 | + end do |
| 55 | +! Calculate electron integrals |
| 56 | + S12=0.0D0 |
| 57 | + T11=0.0D0 |
| 58 | + T12=0.0D0 |
| 59 | + T22=0.0D0 |
| 60 | + V11A=0.0D0 |
| 61 | + V12A=0.0D0 |
| 62 | + V22A=0.0D0 |
| 63 | + V11B=0.0D0 |
| 64 | + V12B=0.0D0 |
| 65 | + V22B=0.0D0 |
| 66 | + V1111=0.0D0 |
| 67 | + V2111=0.0D0 |
| 68 | + V2121=0.0D0 |
| 69 | + V2211=0.0D0 |
| 70 | + V2221=0.0D0 |
| 71 | + V2222=0.0D0 |
| 72 | +! one-electron integrals I for atom1, J for atom2 |
| 73 | + do I=1,N |
| 74 | + do J=1,N |
| 75 | + ! R1=0 R2=2 |
| 76 | + RAP=A2(J)*R/(A1(I)+A2(J)) |
| 77 | + RAP2=RAP**2 |
| 78 | + RBP2=(R-RAP)**2 |
| 79 | + S12=S12+S(A1(I),A2(J),R2)*D1(I)*D2(J) |
| 80 | + T11=T11+T(A1(I),A1(J),0.0D0)*D1(I)*D1(J) |
| 81 | + T12=T12+T(A1(I),A2(J),R2)*D1(I)*D2(J) |
| 82 | + T22=T22+T(A2(I),A2(J),0.0D0)*D2(I)*D2(J) |
| 83 | + V11A=V11A+V(A1(I),A1(J),0.0D0,0.0D0,ZA)*D1(I)*D1(J) |
| 84 | + V12A=V12A+V(A1(I),A2(J),R2,RAP2,ZA)*D1(I)*D2(J) |
| 85 | + V22A=V22A+V(A2(I),A2(J),0.0D0,R2,ZA)*D2(I)*D2(J) |
| 86 | + V11B=V11B+V(A1(I),A1(J),0.0D0,R2,ZB)*D1(I)*D1(J) |
| 87 | + V12B=V12B+V(A1(I),A2(J),R2,RBP2,ZB)*D1(I)*D2(J) |
| 88 | + V22B=V22B+V(A2(I),A2(J),0.0D0,0.0D0,ZB)*D2(I)*D2(J) |
| 89 | + end do |
| 90 | + end do |
| 91 | + do I=1,N |
| 92 | + do J=1,N |
| 93 | + do K=1,N |
| 94 | + do L=1,N |
| 95 | + RAP=A2(I)*R/(A2(I)+A1(J)) |
| 96 | + RBP=R-RAP |
| 97 | + RAQ=A2(K)*R/(A2(K)+A1(L)) |
| 98 | + RBQ=R-RAQ |
| 99 | + RPQ=RAP-RAQ |
| 100 | + RAP2=RAP*RAP |
| 101 | + RBP2=RBP*RBP |
| 102 | + RAQ2=RAQ*RAQ |
| 103 | + RBQ2=RBQ*RBQ |
| 104 | + RPQ2=RPQ*RPQ |
| 105 | + V1111=V1111+TWOE(A1(I),A1(J),A1(K),A1(L),0.0D0,0.0D0,0.0D0)*D1(I)*D1(J)*D1(K)*D1(L) |
| 106 | + V2111=V2111+TWOE(A2(I),A1(J),A1(K),A1(L),R2,0.0D0,RAP2)*D2(I)*D1(J)*D1(K)*D1(L) |
| 107 | + V2121=V2121+TWOE(A2(I),A1(J),A2(K),A1(L),R2,R2,RPQ2)*D2(I)*D1(J)*D2(K)*D1(L) |
| 108 | + V2211=V2211+TWOE(A2(I),A2(J),A1(K),A1(L),0.0D0,0.0D0,R2)*D2(I)*D2(J)*D1(K)*D1(L) |
| 109 | + V2221=V2221+TWOE(A2(I),A2(J),A2(K),A1(L),0.0D0,R2,RBQ2)*D2(I)*D2(J)*D2(K)*D1(L) |
| 110 | + V2222=V2222+TWOE(A2(I),A2(J),A2(K),A2(L),0.0D0,0.0D0,0.0D0)*D2(I)*D2(J)*D2(K)*D2(L) |
| 111 | + end do |
| 112 | + end do |
| 113 | + end do |
| 114 | + end do |
| 115 | + if (IOP .EQ. 0) return |
| 116 | + write(*,40) |
| 117 | +40 FORMAT(3X,'R',10X,'ZETA1',6X,'ZETA2',6X,'S12',8X,'T11'/) |
| 118 | + write(*,50) R,ZETA1,ZETA2,S12,T11 |
| 119 | +50 FORMAT(5F11.6//) |
| 120 | + write(*,60) |
| 121 | +60 FORMAT(3X,'T12',8X,'T22',8X,'V11A',7X,'V12A',7X,'V22A'/) |
| 122 | + write(*,50) T12,T22,V11A,V12A,V22A |
| 123 | + write(*,70) |
| 124 | +70 FORMAT(3X,4HV11B,7X,4HV12B,7X,4HV22B,7X,'V1111',6X,'V2111'/) |
| 125 | + write(*,50) V11B,V12B,V22B,V1111,V2111 |
| 126 | + write(*,80) |
| 127 | +80 FORMAT(3X,5HV2121,6X,5HV2211,6X,5HV2221,6X,5HV2222/) |
| 128 | + write(*,50) V2121,V2211,V2221,V2222 |
| 129 | + return |
| 130 | +end subroutine |
| 131 | + |
| 132 | +! Calculate the F FUNCTION F0 ONLY (s-type ORBITALS) |
| 133 | +function F0(ARG) |
| 134 | + implicit none |
| 135 | + real*8 ::ARG |
| 136 | + real*8 :: PI=3.1415926535898D0 |
| 137 | + real*8 :: F0 |
| 138 | + if (ARG < 1.0D-6) then |
| 139 | + F0=1.0D0-ARG/3.0D0 |
| 140 | + else |
| 141 | + F0=DSQRT(PI/ARG)*ERF(DSQRT(ARG))/2.0D0 |
| 142 | + end if |
| 143 | + return |
| 144 | +end function |
| 145 | + |
| 146 | +! Calculate overlaps S |
| 147 | +function S(A,B,RAB2) |
| 148 | + implicit none |
| 149 | + real*8 :: A,B,RAB2 |
| 150 | + real*8 :: S |
| 151 | + real*8 :: PI=3.1415926535898D0 |
| 152 | + S=(PI/(A+B))**1.5D0*DEXP(-A*B*RAB2/(A+B)) |
| 153 | + return |
| 154 | +end function |
| 155 | + |
| 156 | +! Calculate kinetic energy integrals |
| 157 | +function T(A,B,RAB2) |
| 158 | + implicit none |
| 159 | + real*8 :: A,B,RAB2 |
| 160 | + real*8 :: T |
| 161 | + real*8 :: PI=3.1415926535898D0 |
| 162 | + T=A*B/(A+B)*(3.0D0-2.0D0*A*B*RAB2/(A+B))*(PI/(A+B))**1.5D0*DEXP(-A*B*RAB2/(A+B)) |
| 163 | + return |
| 164 | +end function |
| 165 | + |
| 166 | +! Calculate nuclear attraction integrals |
| 167 | +function V(A,B,RAB2,RCP2,ZC) |
| 168 | + implicit none |
| 169 | + real*8 :: A,B,RAB2,RCP2,ZC |
| 170 | + real*8, external :: F0 |
| 171 | + real*8 :: V |
| 172 | + real*8 :: PI=3.1415926535898D0 |
| 173 | + V=2.0D0*PI/(A+B)*F0((A+B)*RCP2)*DEXP(-A*B*RAB2/(A+B)) |
| 174 | + V=-V*ZC |
| 175 | + return |
| 176 | +end function |
| 177 | + |
| 178 | +! Calculate two-electron integrals |
| 179 | +function TWOE(A,B,C,D,RAB2,RCD2,RPQ2) |
| 180 | + implicit none |
| 181 | + real*8 :: A,B,C,D,RAB2,RCD2,RPQ2 |
| 182 | + real*8, external :: F0 |
| 183 | + real*8 :: TWOE |
| 184 | + real*8 :: PI=3.1415926535898D0 |
| 185 | + TWOE=2.0D0*(PI**2.5D0)/((A+B)*(C+D)*DSQRT(A+B+C+D))*F0((A+B)*(C+D)*RPQ2/(A+B+C+D))*DEXP(-A*B*RAB2/(A+B)-C*D*RCD2/(C+D)) |
| 186 | + return |
| 187 | +end function |
| 188 | + |
| 189 | +! THIS TAKES THE BASIC INTEGRALS FROM COMMON AND ASSEMBLES THE RELEVENT MATRICES |
| 190 | +subroutine COLECT(IOP,N,R,ZETA1,ZETA2,ZA,ZB) |
| 191 | + implicit none |
| 192 | + real*8 :: IOP,R,ZETA1,ZETA2,ZA,ZB |
| 193 | + integer :: N |
| 194 | + real*8 :: S(2,2),X(2,2),XT(2,2),H(2,2),F(2,2),G(2,2),C(2,2),FPRIME(2,2),CPRIME(2,2),P(2,2),OLDP(2,2),TT(2,2,2,2),E(2,2) |
| 195 | + common /MATRIX/ S,X,XT,H,F,G,C,FPRIME,CPRIME,P,OLDP,TT,E |
| 196 | + real*8 :: S12,T11,T12,T22,V11A,V12A,V22A,V11B,V12B,V22B,V1111,V2111,V2121,V2211,V2221,V2222 |
| 197 | + common /INT/ S12,T11,T12,T22,V11A,V12A,V22A,V11B,V12B,V22B,V1111,V2111,V2121,V2211,V2221,V2222 |
| 198 | + integer :: I,J,K,L |
| 199 | +! core Hamiltonian |
| 200 | + H(1,1)=T11+V11A+V11B |
| 201 | + H(1,2)=T12+V12A+V12B |
| 202 | + H(2,1)=H(1,2) |
| 203 | + H(2,2)=T22+V22A+V22B |
| 204 | +! S Matrix |
| 205 | + S(1,1)=1.0D0 |
| 206 | + S(1,2)=S12 |
| 207 | + S(2,1)=S(1,2) |
| 208 | + S(2,2)=1.0D0 |
| 209 | +! Schmidt orthogonalization for S Matrix |
| 210 | + X(1,1)=1.0D0/DSQRT(2.0D0*(1.0D0+S12)) |
| 211 | + X(2,1)=X(1,1) |
| 212 | + X(1,2)=1.0D0/DSQRT(2.0D0*(1.0D0-S12)) |
| 213 | + X(2,2)=-X(1,2) |
| 214 | +! Transpose of X |
| 215 | + XT=transpose(X) |
| 216 | +! Matrix of Two-electron integrals |
| 217 | + TT(1,1,1,1)=V1111 |
| 218 | + TT(2,1,1,1)=V2111 |
| 219 | + TT(1,2,1,1)=V2111 |
| 220 | + TT(1,1,2,1)=V2111 |
| 221 | + TT(1,1,1,2)=V2111 |
| 222 | + TT(2,1,2,1)=V2121 |
| 223 | + TT(1,2,2,1)=V2121 |
| 224 | + TT(2,1,1,2)=V2121 |
| 225 | + TT(1,2,1,2)=V2121 |
| 226 | + TT(2,2,1,1)=V2211 |
| 227 | + TT(1,1,2,2)=V2211 |
| 228 | + TT(2,2,2,1)=V2221 |
| 229 | + TT(2,2,1,2)=V2221 |
| 230 | + TT(2,1,2,2)=V2221 |
| 231 | + TT(1,2,2,2)=V2221 |
| 232 | + TT(2,2,2,2)=V2222 |
| 233 | + if (IOP /= 0) then |
| 234 | + CALL MATOUT(S,2,2,2,2,'S') |
| 235 | + CALL MATOUT(X,2,2,2,2,'X') |
| 236 | + CALL MATOUT(H,2,2,2,2,'H') |
| 237 | + write(*,10) |
| 238 | + do I=1,2 |
| 239 | + do J=1,2 |
| 240 | + do K=1,2 |
| 241 | + do L=1,2 |
| 242 | + write(*,20) I,J,K,L,TT(I,J,K,L) |
| 243 | + end do |
| 244 | + end do |
| 245 | + end do |
| 246 | + end do |
| 247 | + end if |
| 248 | +10 FORMAT(//) |
| 249 | +20 FORMAT(3X,'(',4I2,')',F10.6) |
| 250 | +end subroutine |
| 251 | + |
| 252 | +subroutine SCF(IOP,N,R,ZETA1,ZETA2,ZA,ZB) |
| 253 | + implicit none |
| 254 | + real*8 :: IOP,R,ZETA1,ZETA2,ZA,ZB |
| 255 | + integer :: N |
| 256 | + real*8 :: S(2,2),X(2,2),XT(2,2),H(2,2),F(2,2),G(2,2),C(2,2),FPRIME(2,2),CPRIME(2,2),P(2,2),OLDP(2,2),TT(2,2,2,2),E(2,2) |
| 257 | + common /MATRIX/ S,X,XT,H,F,G,C,FPRIME,CPRIME,P,OLDP,TT,E |
| 258 | + real*8 :: PI=3.1415926535898D0 |
| 259 | + real*8 :: CRIT=1.0D-6 |
| 260 | + integer :: max_iter=120,ITER,i,j,k,l,lwork,info |
| 261 | + real*8 :: energy,evals(2),dummy(1),ENT,delta |
| 262 | + real*8, allocatable :: work(:) |
| 263 | + ! Initial guess |
| 264 | + P = 0.0D0 |
| 265 | + ! SCF cyclo |
| 266 | + do iter=1, max_iter |
| 267 | + write(*,'(///,4X,A,I2)') 'START OF ITERATION NUMBER =',iter |
| 268 | + ! Construct F Matrix |
| 269 | + ! F_uv = H_uv + Sum_ls P_ls * [ (uv|sl) - 0.5 * (ul|sv) ] |
| 270 | + F = H |
| 271 | + do i=1,2 |
| 272 | + do j=1,2 |
| 273 | + do k=1,2 |
| 274 | + do l=1,2 |
| 275 | + F(i,j)=F(i,j)+P(k,l)*(TT(i,j,l,k)-0.5D0*TT(i,k,l,j)) |
| 276 | + end do |
| 277 | + end do |
| 278 | + end do |
| 279 | + end do |
| 280 | + |
| 281 | + ! Calculate energy |
| 282 | + energy = 0.0D0 |
| 283 | + do i = 1,2 |
| 284 | + do j = 1,2 |
| 285 | + energy = energy+0.5D0*P(i,j)*(H(i,j)+F(i,j)) |
| 286 | + end do |
| 287 | + end do |
| 288 | + write(*,'(/,4X,A,D20.12)') 'ELECTRONIC ENERGY = ', energy |
| 289 | + |
| 290 | + ! Transition Fock matrix |
| 291 | + FPRIME=matmul(XT,matmul(F,X)) |
| 292 | + |
| 293 | + ! DSYEV |
| 294 | + lwork=-1 |
| 295 | + call dsyev('V','U',2,FPRIME,2,evals,dummy,lwork,info) |
| 296 | + lwork=int(dummy(1)) |
| 297 | + if (allocated(work)) deallocate(work) |
| 298 | + allocate(work(lwork)) |
| 299 | + call dsyev('V','U',2,FPRIME,2,evals,work,lwork,info) |
| 300 | + E(1,1)=evals(1) |
| 301 | + E(2,2)=evals(2) |
| 302 | + ! r transition C |
| 303 | + C=matmul(X, FPRIME) |
| 304 | + |
| 305 | + ! Construct new P |
| 306 | + OLDP=P |
| 307 | + do i=1,2 |
| 308 | + do j=1,2 |
| 309 | + P(i,j)=0.0D0 |
| 310 | + do k=1,1 |
| 311 | + P(i,j)=P(i,j)+2.0D0*C(i,k)*C(j,k) |
| 312 | + end do |
| 313 | + end do |
| 314 | + end do |
| 315 | + if (IOP > 2) then |
| 316 | + CALL MATOUT(F,2,2,2,2,'F') |
| 317 | + CALL MATOUT(E,2,2,2,2,'E') |
| 318 | + CALL MATOUT(C,2,2,2,2,'C') |
| 319 | + CALL MATOUT(P,2,2,2,2,'P') |
| 320 | + end if |
| 321 | + ! Calculate delta |
| 322 | + delta=0.0D0 |
| 323 | + delta = sum((p(:,:) - oldp(:,:))**2) |
| 324 | + delta=DSQRT(delta/4.0D0) |
| 325 | + if (IOP > 0) then |
| 326 | + write(*,'(/,4X,A,F10.6,/)') 'DELTA(CONVERGENCE OF DENSITY MATRIX) =',delta |
| 327 | + end if |
| 328 | + if (delta<CRIT) exit |
| 329 | + if (iter==max_iter .and. delta>CRIT) then |
| 330 | + write(*,'(4X,A)') 'NO CONVERGENCE IN SCF' |
| 331 | + end if |
| 332 | + end do |
| 333 | + ENT=energy+ZA*ZB/R |
| 334 | + if (IOP /= 0) then |
| 335 | + write(*, '(//,4X,A,//,4X,A,D20.12,//,4X,A,D20.12)') & |
| 336 | + 'CALCULATION CONVERGED', & |
| 337 | + 'ELECTRONIC ENERGY = ', energy, & |
| 338 | + 'TOTAL ENERGY = ', ENT |
| 339 | + end if |
| 340 | + if (IOP == 1) then |
| 341 | + call MATOUT(F, 2, 2, 2, 2, 'F') |
| 342 | + call MATOUT(C, 2, 2, 2, 2, 'C') |
| 343 | + call MATOUT(P, 2, 2, 2, 2, 'P') |
| 344 | + end if |
| 345 | + OLDP=matmul(P,S) |
| 346 | + if (IOP /= 0) then |
| 347 | + call MATOUT(OLDP, 2, 2, 2, 2, 'PS') |
| 348 | + end if |
| 349 | + return |
| 350 | +end subroutine |
| 351 | + |
| 352 | +! Print Matrix of size M by N |
| 353 | +subroutine MATOUT(A,IM,INP,M,N,LABEL) |
| 354 | + IMPLICIT NONE |
| 355 | + INTEGER, INTENT(IN) :: IM, INP, M, N |
| 356 | + DOUBLE PRECISION, INTENT(IN) :: A(IM, INP) |
| 357 | + CHARACTER(LEN=*), INTENT(IN) :: LABEL |
| 358 | + INTEGER :: I, J, LOW, IHIGH |
| 359 | + CHARACTER(LEN=100) :: FMT_HEADER, FMT_ROW |
| 360 | + |
| 361 | + IHIGH = 0 |
| 362 | + |
| 363 | + do |
| 364 | + LOW = IHIGH + 1 |
| 365 | + IHIGH = IHIGH + 5 |
| 366 | + IHIGH = MIN(IHIGH, N) |
| 367 | + write(*, '(/3X, "THE ", A, " ARRAY")') TRIM(LABEL) |
| 368 | + write(*, '(15X)', ADVANCE='NO') |
| 369 | + do I = LOW, IHIGH |
| 370 | + write(*, '(10X, I3, 6X)', ADVANCE='NO') I |
| 371 | + end do |
| 372 | + write(*, *) |
| 373 | + |
| 374 | + do I = 1, M |
| 375 | + write(*, '(I10, 5X)', ADVANCE='NO') I |
| 376 | + do J = LOW, IHIGH |
| 377 | + write(*, '(1X, D18.10)', ADVANCE='NO') A(I, J) |
| 378 | + end do |
| 379 | + write(*, *) |
| 380 | + end do |
| 381 | + IF (IHIGH >= N) EXIT |
| 382 | + end do |
| 383 | +end subroutine |
0 commit comments