1!--------------------------------------------------------------------------------------------------! 2! CP2K: A general program to perform molecular dynamics simulations ! 3! Copyright (C) 2000 - 2019 CP2K developers group ! 4!--------------------------------------------------------------------------------------------------! 5 6! ************************************************************************************************** 7!> \brief Analytical derivatives of Integrals for semi-empirical methods 8!> \author Teodoro Laino - Zurich University 04.2007 [tlaino] 9!> \par History 10!> 23.11.2007 jhu short range version of integrals 11!> Teodoro Laino (04.2008) [tlaino] - University of Zurich : new driver 12!> for computing integrals 13!> Teodoro Laino (05.2008) [tlaino] - University of Zurich : analytical 14!> derivatives for d-orbitals 15! ************************************************************************************************** 16MODULE semi_empirical_int_ana 17 18 USE input_constants, ONLY: do_method_am1,& 19 do_method_pchg,& 20 do_method_pdg,& 21 do_method_pm3,& 22 do_method_pm6,& 23 do_method_pm6fm,& 24 do_method_undef,& 25 do_se_IS_kdso_d 26 USE kinds, ONLY: dp 27 USE multipole_types, ONLY: do_multipole_none 28 USE physcon, ONLY: angstrom,& 29 evolt 30 USE semi_empirical_int_arrays, ONLY: & 31 fac_x_to_z, ijkl_ind, ijkl_sym, inddd, inddp, indexa, indexb, indpp, int2c_type, l_index, & 32 map_x_to_z, rij_threshold 33 USE semi_empirical_int_num, ONLY: nucint_d_num,& 34 nucint_sp_num,& 35 terep_d_num,& 36 terep_sp_num 37 USE semi_empirical_int_utils, ONLY: d_ijkl_d,& 38 d_ijkl_sp,& 39 rot_2el_2c_first,& 40 rotmat,& 41 store_2el_2c_diag 42 USE semi_empirical_types, ONLY: rotmat_create,& 43 rotmat_release,& 44 rotmat_type,& 45 se_int_control_type,& 46 se_int_screen_type,& 47 se_taper_type,& 48 semi_empirical_type,& 49 setup_se_int_control_type 50 USE taper_types, ONLY: dtaper_eval,& 51 taper_eval 52#include "./base/base_uses.f90" 53 54 IMPLICIT NONE 55 PRIVATE 56#include "semi_empirical_int_debug.h" 57#include "semi_empirical_int_args.h" 58 59 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'semi_empirical_int_ana' 60 LOGICAL, PARAMETER, PRIVATE :: debug_this_module = .FALSE. 61 PUBLIC :: rotnuc_ana, rotint_ana, corecore_ana, corecore_el_ana 62 63CONTAINS 64 65! ************************************************************************************************** 66!> \brief Computes analytical gradients for semiempirical integrals 67!> \param sepi Atomic parameters of first atom 68!> \param sepj Atomic parameters of second atom 69!> \param rijv Coordinate vector i -> j 70!> \param itype ... 71!> \param e1b Array of electron-nuclear attraction integrals, Electron on atom ni attracting nucleus of nj. 72!> \param e2a Array of electron-nuclear attraction integrals, Electron on atom nj attracting nucleus of ni. 73!> \param de1b derivative of e1b term 74!> \param de2a derivative of e2a term 75!> \param se_int_control input parameters that control the calculation of SE 76!> integrals (shortrange, R3 residual, screening type) 77!> \param se_taper ... 78!> \par History 79!> 04.2007 created [tlaino] 80!> Teodoro Laino (04.2008) [tlaino] - University of Zurich : new driver 81!> for computing integrals 82!> Teodoro Laino [tlaino] - University of Zurich 04.2008 : removed the core-core part 83!> \author Teodoro Laino [tlaino] - Zurich University 84!> \note 85!> Analytical version of the MOPAC rotnuc routine 86! ************************************************************************************************** 87 RECURSIVE SUBROUTINE rotnuc_ana(sepi, sepj, rijv, itype, e1b, e2a, de1b, de2a, & 88 se_int_control, se_taper) 89 TYPE(semi_empirical_type), POINTER :: sepi, sepj 90 REAL(dp), DIMENSION(3), INTENT(IN) :: rijv 91 INTEGER, INTENT(IN) :: itype 92 REAL(dp), DIMENSION(45), INTENT(OUT), OPTIONAL :: e1b, e2a 93 REAL(dp), DIMENSION(3, 45), INTENT(OUT), OPTIONAL :: de1b, de2a 94 TYPE(se_int_control_type), INTENT(IN) :: se_int_control 95 TYPE(se_taper_type), POINTER :: se_taper 96 97 CHARACTER(len=*), PARAMETER :: routineN = 'rotnuc_ana', routineP = moduleN//':'//routineN 98 99 INTEGER :: i, idd, idp, ind1, ind2, ipp, j, & 100 last_orbital(2), m, n 101 LOGICAL :: invert, l_de1b, l_de2a, l_e1b, l_e2a, & 102 lgrad, task(2) 103 REAL(KIND=dp) :: rij, xtmp 104 REAL(KIND=dp), DIMENSION(10, 2) :: core, dcore 105 REAL(KIND=dp), DIMENSION(3) :: drij 106 REAL(KIND=dp), DIMENSION(3, 45) :: tmp_d 107 REAL(KIND=dp), DIMENSION(45) :: tmp 108 TYPE(rotmat_type), POINTER :: ij_matrix 109 110 NULLIFY (ij_matrix) 111 rij = DOT_PRODUCT(rijv, rijv) 112 ! Initialization 113 l_e1b = PRESENT(e1b) 114 l_e2a = PRESENT(e2a) 115 l_de1b = PRESENT(de1b) 116 l_de2a = PRESENT(de2a) 117 lgrad = l_de1b .OR. l_de2a 118 119 IF (rij > rij_threshold) THEN 120 ! Compute Integrals in diatomic frame opportunely inverted 121 rij = SQRT(rij) 122 ! Create the rotation matrix 123 CALL rotmat_create(ij_matrix) 124 CALL rotmat(sepi, sepj, rijv, rij, ij_matrix, do_derivatives=lgrad, do_invert=invert) 125 126 IF (lgrad) THEN 127 drij(1) = rijv(1)/rij 128 drij(2) = rijv(2)/rij 129 drij(3) = rijv(3)/rij 130 ! Possibly Invert Frame 131 IF (invert) THEN 132 xtmp = drij(3) 133 drij(3) = drij(1) 134 drij(1) = xtmp 135 END IF 136 END IF 137 138 CALL dcore_nucint_ana(sepi, sepj, rij, core=core, dcore=dcore, itype=itype, se_taper=se_taper, & 139 se_int_control=se_int_control, lgrad=lgrad) 140 141 ! Copy parameters over to arrays for do loop. 142 last_orbital(1) = sepi%natorb 143 last_orbital(2) = sepj%natorb 144 task(1) = l_e1b 145 task(2) = l_e2a 146 DO n = 1, 2 147 IF (.NOT. task(n)) CYCLE 148 DO i = 1, last_orbital(n) 149 ind1 = i - 1 150 DO j = 1, i 151 ind2 = j - 1 152 m = (i*(i - 1))/2 + j 153 ! Perform Rotations ... 154 IF (ind2 == 0) THEN 155 IF (ind1 == 0) THEN 156 ! Type of Integral (SS/) 157 tmp(m) = core(1, n) 158 ELSE IF (ind1 < 4) THEN 159 ! Type of Integral (SP/) 160 tmp(m) = ij_matrix%sp(1, ind1)*core(2, n) 161 ELSE 162 ! Type of Integral (SD/) 163 tmp(m) = ij_matrix%sd(1, ind1 - 3)*core(5, n) 164 END IF 165 ELSE IF (ind2 < 4) THEN 166 IF (ind1 < 4) THEN 167 ! Type of Integral (PP/) 168 ipp = indpp(ind1, ind2) 169 tmp(m) = core(3, n)*ij_matrix%pp(ipp, 1, 1) + & 170 core(4, n)*(ij_matrix%pp(ipp, 2, 2) + ij_matrix%pp(ipp, 3, 3)) 171 ELSE 172 ! Type of Integral (PD/) 173 idp = inddp(ind1 - 3, ind2) 174 tmp(m) = core(6, n)*ij_matrix%pd(idp, 1, 1) + & 175 core(8, n)*(ij_matrix%pd(idp, 2, 2) + ij_matrix%pd(idp, 3, 3)) 176 END IF 177 ELSE 178 ! Type of Integral (DD/) 179 idd = inddd(ind1 - 3, ind2 - 3) 180 tmp(m) = core(7, n)*ij_matrix%dd(idd, 1, 1) + & 181 core(9, n)*(ij_matrix%dd(idd, 2, 2) + ij_matrix%dd(idd, 3, 3)) + & 182 core(10, n)*(ij_matrix%dd(idd, 4, 4) + ij_matrix%dd(idd, 5, 5)) 183 END IF 184 END DO 185 END DO 186 IF (n == 1) THEN 187 DO i = 1, sepi%atm_int_size 188 e1b(i) = -tmp(i) 189 END DO 190 END IF 191 IF (n == 2) THEN 192 DO i = 1, sepj%atm_int_size 193 e2a(i) = -tmp(i) 194 END DO 195 END IF 196 END DO 197 IF (invert .AND. l_e1b) CALL invert_integral(sepi, sepi, int1el=e1b) 198 IF (invert .AND. l_e2a) CALL invert_integral(sepj, sepj, int1el=e2a) 199 200 ! Possibly compute derivatives 201 task(1) = l_de1b 202 task(2) = l_de2a 203 DO n = 1, 2 204 IF (.NOT. task(n)) CYCLE 205 DO i = 1, last_orbital(n) 206 ind1 = i - 1 207 DO j = 1, i 208 ind2 = j - 1 209 m = (i*(i - 1))/2 + j 210 ! Perform Rotations ... 211 IF (ind2 == 0) THEN 212 IF (ind1 == 0) THEN 213 ! Type of Integral (SS/) 214 tmp_d(1, m) = dcore(1, n)*drij(1) 215 tmp_d(2, m) = dcore(1, n)*drij(2) 216 tmp_d(3, m) = dcore(1, n)*drij(3) 217 ELSE IF (ind1 < 4) THEN 218 ! Type of Integral (SP/) 219 tmp_d(1, m) = ij_matrix%sp_d(1, 1, ind1)*core(2, n) + & 220 ij_matrix%sp(1, ind1)*dcore(2, n)*drij(1) 221 222 tmp_d(2, m) = ij_matrix%sp_d(2, 1, ind1)*core(2, n) + & 223 ij_matrix%sp(1, ind1)*dcore(2, n)*drij(2) 224 225 tmp_d(3, m) = ij_matrix%sp_d(3, 1, ind1)*core(2, n) + & 226 ij_matrix%sp(1, ind1)*dcore(2, n)*drij(3) 227 ELSE 228 ! Type of Integral (SD/) 229 tmp_d(1, m) = ij_matrix%sd_d(1, 1, ind1 - 3)*core(5, n) + & 230 ij_matrix%sd(1, ind1 - 3)*dcore(5, n)*drij(1) 231 232 tmp_d(2, m) = ij_matrix%sd_d(2, 1, ind1 - 3)*core(5, n) + & 233 ij_matrix%sd(1, ind1 - 3)*dcore(5, n)*drij(2) 234 235 tmp_d(3, m) = ij_matrix%sd_d(3, 1, ind1 - 3)*core(5, n) + & 236 ij_matrix%sd(1, ind1 - 3)*dcore(5, n)*drij(3) 237 END IF 238 ELSE IF (ind2 < 4) THEN 239 IF (ind1 < 4) THEN 240 ! Type of Integral (PP/) 241 ipp = indpp(ind1, ind2) 242 tmp_d(1, m) = dcore(3, n)*drij(1)*ij_matrix%pp(ipp, 1, 1) + & 243 core(3, n)*ij_matrix%pp_d(1, ipp, 1, 1) + & 244 dcore(4, n)*drij(1)*(ij_matrix%pp(ipp, 2, 2) + ij_matrix%pp(ipp, 3, 3)) + & 245 core(4, n)*(ij_matrix%pp_d(1, ipp, 2, 2) + ij_matrix%pp_d(1, ipp, 3, 3)) 246 247 tmp_d(2, m) = dcore(3, n)*drij(2)*ij_matrix%pp(ipp, 1, 1) + & 248 core(3, n)*ij_matrix%pp_d(2, ipp, 1, 1) + & 249 dcore(4, n)*drij(2)*(ij_matrix%pp(ipp, 2, 2) + ij_matrix%pp(ipp, 3, 3)) + & 250 core(4, n)*(ij_matrix%pp_d(2, ipp, 2, 2) + ij_matrix%pp_d(2, ipp, 3, 3)) 251 252 tmp_d(3, m) = dcore(3, n)*drij(3)*ij_matrix%pp(ipp, 1, 1) + & 253 core(3, n)*ij_matrix%pp_d(3, ipp, 1, 1) + & 254 dcore(4, n)*drij(3)*(ij_matrix%pp(ipp, 2, 2) + ij_matrix%pp(ipp, 3, 3)) + & 255 core(4, n)*(ij_matrix%pp_d(3, ipp, 2, 2) + ij_matrix%pp_d(3, ipp, 3, 3)) 256 ELSE 257 ! Type of Integral (PD/) 258 idp = inddp(ind1 - 3, ind2) 259 tmp_d(1, m) = dcore(6, n)*drij(1)*ij_matrix%pd(idp, 1, 1) + & 260 core(6, n)*ij_matrix%pd_d(1, idp, 1, 1) + & 261 dcore(8, n)*drij(1)*(ij_matrix%pd(idp, 2, 2) + ij_matrix%pd(idp, 3, 3)) + & 262 core(8, n)*(ij_matrix%pd_d(1, idp, 2, 2) + ij_matrix%pd_d(1, idp, 3, 3)) 263 264 tmp_d(2, m) = dcore(6, n)*drij(2)*ij_matrix%pd(idp, 1, 1) + & 265 core(6, n)*ij_matrix%pd_d(2, idp, 1, 1) + & 266 dcore(8, n)*drij(2)*(ij_matrix%pd(idp, 2, 2) + ij_matrix%pd(idp, 3, 3)) + & 267 core(8, n)*(ij_matrix%pd_d(2, idp, 2, 2) + ij_matrix%pd_d(2, idp, 3, 3)) 268 269 tmp_d(3, m) = dcore(6, n)*drij(3)*ij_matrix%pd(idp, 1, 1) + & 270 core(6, n)*ij_matrix%pd_d(3, idp, 1, 1) + & 271 dcore(8, n)*drij(3)*(ij_matrix%pd(idp, 2, 2) + ij_matrix%pd(idp, 3, 3)) + & 272 core(8, n)*(ij_matrix%pd_d(3, idp, 2, 2) + ij_matrix%pd_d(3, idp, 3, 3)) 273 END IF 274 ELSE 275 ! Type of Integral (DD/) 276 idd = inddd(ind1 - 3, ind2 - 3) 277 tmp_d(1, m) = dcore(7, n)*drij(1)*ij_matrix%dd(idd, 1, 1) + & 278 core(7, n)*ij_matrix%dd_d(1, idd, 1, 1) + & 279 dcore(9, n)*drij(1)*(ij_matrix%dd(idd, 2, 2) + ij_matrix%dd(idd, 3, 3)) + & 280 core(9, n)*(ij_matrix%dd_d(1, idd, 2, 2) + ij_matrix%dd_d(1, idd, 3, 3)) + & 281 dcore(10, n)*drij(1)*(ij_matrix%dd(idd, 4, 4) + ij_matrix%dd(idd, 5, 5)) + & 282 core(10, n)*(ij_matrix%dd_d(1, idd, 4, 4) + ij_matrix%dd_d(1, idd, 5, 5)) 283 284 tmp_d(2, m) = dcore(7, n)*drij(2)*ij_matrix%dd(idd, 1, 1) + & 285 core(7, n)*ij_matrix%dd_d(2, idd, 1, 1) + & 286 dcore(9, n)*drij(2)*(ij_matrix%dd(idd, 2, 2) + ij_matrix%dd(idd, 3, 3)) + & 287 core(9, n)*(ij_matrix%dd_d(2, idd, 2, 2) + ij_matrix%dd_d(2, idd, 3, 3)) + & 288 dcore(10, n)*drij(2)*(ij_matrix%dd(idd, 4, 4) + ij_matrix%dd(idd, 5, 5)) + & 289 core(10, n)*(ij_matrix%dd_d(2, idd, 4, 4) + ij_matrix%dd_d(2, idd, 5, 5)) 290 291 tmp_d(3, m) = dcore(7, n)*drij(3)*ij_matrix%dd(idd, 1, 1) + & 292 core(7, n)*ij_matrix%dd_d(3, idd, 1, 1) + & 293 dcore(9, n)*drij(3)*(ij_matrix%dd(idd, 2, 2) + ij_matrix%dd(idd, 3, 3)) + & 294 core(9, n)*(ij_matrix%dd_d(3, idd, 2, 2) + ij_matrix%dd_d(3, idd, 3, 3)) + & 295 dcore(10, n)*drij(3)*(ij_matrix%dd(idd, 4, 4) + ij_matrix%dd(idd, 5, 5)) + & 296 core(10, n)*(ij_matrix%dd_d(3, idd, 4, 4) + ij_matrix%dd_d(3, idd, 5, 5)) 297 END IF 298 END DO 299 END DO 300 IF (n == 1) THEN 301 DO i = 1, sepi%atm_int_size 302 de1b(1, i) = -tmp_d(1, i) 303 de1b(2, i) = -tmp_d(2, i) 304 de1b(3, i) = -tmp_d(3, i) 305 END DO 306 END IF 307 IF (n == 2) THEN 308 DO i = 1, sepj%atm_int_size 309 de2a(1, i) = -tmp_d(1, i) 310 de2a(2, i) = -tmp_d(2, i) 311 de2a(3, i) = -tmp_d(3, i) 312 END DO 313 END IF 314 END DO 315 IF (invert .AND. l_de1b) CALL invert_derivative(sepi, sepi, dint1el=de1b) 316 IF (invert .AND. l_de2a) CALL invert_derivative(sepj, sepj, dint1el=de2a) 317 CALL rotmat_release(ij_matrix) 318 319 ! Possibly debug the analytical values versus the numerical ones 320 IF (debug_this_module) THEN 321 CALL check_drotnuc_ana(sepi, sepj, rijv, itype, se_int_control, se_taper, e1b, e2a, de1b, de2a) 322 END IF 323 END IF 324 END SUBROUTINE rotnuc_ana 325 326! ************************************************************************************************** 327!> \brief Computes analytical gradients for semiempirical core-core interaction. 328!> \param sepi Atomic parameters of first atom 329!> \param sepj Atomic parameters of second atom 330!> \param rijv Coordinate vector i -> j 331!> \param itype ... 332!> \param enuc nuclear-nuclear repulsion term. 333!> \param denuc derivative of nuclear-nuclear repulsion term. 334!> \param se_int_control input parameters that control the calculation of SE 335!> integrals (shortrange, R3 residual, screening type) 336!> \param se_taper ... 337!> \par History 338!> 04.2007 created [tlaino] 339!> Teodoro Laino (04.2008) [tlaino] - University of Zurich : new driver 340!> for computing integrals 341!> Teodoro Laino [tlaino] - University of Zurich 04.2008 : removed the 342!> core-core part 343!> \author Teodoro Laino [tlaino] - Zurich University 344!> \note 345!> Analytical version of the MOPAC rotnuc routine 346! ************************************************************************************************** 347 RECURSIVE SUBROUTINE corecore_ana(sepi, sepj, rijv, itype, enuc, denuc, se_int_control, se_taper) 348 TYPE(semi_empirical_type), POINTER :: sepi, sepj 349 REAL(dp), DIMENSION(3), INTENT(IN) :: rijv 350 INTEGER, INTENT(IN) :: itype 351 REAL(dp), INTENT(OUT), OPTIONAL :: enuc 352 REAL(dp), DIMENSION(3), INTENT(OUT), OPTIONAL :: denuc 353 TYPE(se_int_control_type), INTENT(IN) :: se_int_control 354 TYPE(se_taper_type), POINTER :: se_taper 355 356 CHARACTER(len=*), PARAMETER :: routineN = 'corecore_ana', routineP = moduleN//':'//routineN 357 358 INTEGER :: ig, nt 359 LOGICAL :: l_denuc, l_enuc 360 REAL(dp) :: aab, alpi, alpj, apdg, ax, dai, daj, dax, dbi, dbj, denuc_loc, dqcorr, drija, & 361 dscale, dssss, dssss_sr, dtmp, dzz, enuc_loc, pai, paj, pbi, pbj, qcorr, rij, rija, & 362 scale, ssss, ssss_sr, tmp, xab, xtmp, zaf, zbf, zz 363 REAL(dp), DIMENSION(3) :: drij 364 REAL(dp), DIMENSION(4) :: fni1, fni2, fni3, fnj1, fnj2, fnj3 365 TYPE(se_int_control_type) :: se_int_control_off 366 367 rij = DOT_PRODUCT(rijv, rijv) 368 ! Initialization 369 l_enuc = PRESENT(enuc) 370 l_denuc = PRESENT(denuc) 371 IF ((rij > rij_threshold) .AND. (l_enuc .OR. l_denuc)) THEN 372 ! Compute Integrals in diatomic frame 373 rij = SQRT(rij) 374 CALL setup_se_int_control_type(se_int_control_off, shortrange=.FALSE., do_ewald_r3=.FALSE., & 375 do_ewald_gks=.FALSE., integral_screening=se_int_control%integral_screening, & 376 max_multipole=do_multipole_none, pc_coulomb_int=.FALSE.) 377 CALL dssss_nucint_ana(sepi, sepj, rij, ssss=ssss, dssss=dssss, itype=itype, se_taper=se_taper, & 378 se_int_control=se_int_control_off, lgrad=l_denuc) 379 ! In case let's compute the short-range part of the (ss|ss) integral 380 IF (se_int_control%shortrange) THEN 381 CALL dssss_nucint_ana(sepi, sepj, rij, ssss=ssss_sr, dssss=dssss_sr, itype=itype, & 382 se_taper=se_taper, se_int_control=se_int_control, lgrad=l_denuc) 383 ELSE 384 ssss_sr = ssss 385 dssss_sr = dssss 386 END IF 387 ! Zeroing local method dependent core-core corrections 388 enuc_loc = 0.0_dp 389 denuc_loc = 0.0_dp 390 qcorr = 0.0_dp 391 scale = 0.0_dp 392 dscale = 0.0_dp 393 dqcorr = 0.0_dp 394 zz = sepi%zeff*sepj%zeff 395 ! Core Core electrostatic contribution 396 IF (l_enuc) enuc_loc = zz*ssss_sr 397 IF (l_denuc) denuc_loc = zz*dssss_sr 398 ! Method dependent code 399 tmp = zz*ssss 400 IF (l_denuc) dtmp = zz*dssss 401 IF (itype /= do_method_pm6 .AND. itype /= do_method_pm6fm) THEN 402 alpi = sepi%alp 403 alpj = sepj%alp 404 scale = EXP(-alpi*rij) + EXP(-alpj*rij) 405 IF (l_denuc) THEN 406 dscale = -alpi*EXP(-alpi*rij) - alpj*EXP(-alpj*rij) 407 END IF 408 nt = sepi%z + sepj%z 409 IF (nt == 8 .OR. nt == 9) THEN 410 IF (sepi%z == 7 .OR. sepi%z == 8) THEN 411 scale = scale + (angstrom*rij - 1._dp)*EXP(-alpi*rij) 412 IF (l_denuc) THEN 413 dscale = dscale + angstrom*EXP(-alpi*rij) - (angstrom*rij - 1._dp)*alpi*EXP(-alpi*rij) 414 END IF 415 END IF 416 IF (sepj%z == 7 .OR. sepj%z == 8) THEN 417 scale = scale + (angstrom*rij - 1._dp)*EXP(-alpj*rij) 418 IF (l_denuc) THEN 419 dscale = dscale + angstrom*EXP(-alpj*rij) - (angstrom*rij - 1._dp)*alpj*EXP(-alpj*rij) 420 END IF 421 END IF 422 ENDIF 423 IF (l_denuc) THEN 424 dscale = SIGN(1.0_dp, scale*tmp)*(dscale*tmp + scale*dtmp) 425 dzz = -zz/rij**2 426 END IF 427 scale = ABS(scale*tmp) 428 zz = zz/rij 429 IF (itype == do_method_am1 .OR. itype == do_method_pm3 .OR. itype == do_method_pdg) THEN 430 IF (itype == do_method_am1 .AND. sepi%z == 5) THEN 431 !special case AM1 Boron 432 SELECT CASE (sepj%z) 433 CASE DEFAULT 434 nt = 1 435 CASE (1) 436 nt = 2 437 CASE (6) 438 nt = 3 439 CASE (9, 17, 35, 53) 440 nt = 4 441 END SELECT 442 fni1(1) = sepi%bfn1(1, nt) 443 fni1(2) = sepi%bfn1(2, nt) 444 fni1(3) = sepi%bfn1(3, nt) 445 fni1(4) = sepi%bfn1(4, nt) 446 fni2(1) = sepi%bfn2(1, nt) 447 fni2(2) = sepi%bfn2(2, nt) 448 fni2(3) = sepi%bfn2(3, nt) 449 fni2(4) = sepi%bfn2(4, nt) 450 fni3(1) = sepi%bfn3(1, nt) 451 fni3(2) = sepi%bfn3(2, nt) 452 fni3(3) = sepi%bfn3(3, nt) 453 fni3(4) = sepi%bfn3(4, nt) 454 ELSE 455 fni1(1) = sepi%fn1(1) 456 fni1(2) = sepi%fn1(2) 457 fni1(3) = sepi%fn1(3) 458 fni1(4) = sepi%fn1(4) 459 fni2(1) = sepi%fn2(1) 460 fni2(2) = sepi%fn2(2) 461 fni2(3) = sepi%fn2(3) 462 fni2(4) = sepi%fn2(4) 463 fni3(1) = sepi%fn3(1) 464 fni3(2) = sepi%fn3(2) 465 fni3(3) = sepi%fn3(3) 466 fni3(4) = sepi%fn3(4) 467 END IF 468 IF (itype == do_method_am1 .AND. sepj%z == 5) THEN 469 !special case AM1 Boron 470 SELECT CASE (sepi%z) 471 CASE DEFAULT 472 nt = 1 473 CASE (1) 474 nt = 2 475 CASE (6) 476 nt = 3 477 CASE (9, 17, 35, 53) 478 nt = 4 479 END SELECT 480 fnj1(1) = sepj%bfn1(1, nt) 481 fnj1(2) = sepj%bfn1(2, nt) 482 fnj1(3) = sepj%bfn1(3, nt) 483 fnj1(4) = sepj%bfn1(4, nt) 484 fnj2(1) = sepj%bfn2(1, nt) 485 fnj2(2) = sepj%bfn2(2, nt) 486 fnj2(3) = sepj%bfn2(3, nt) 487 fnj2(4) = sepj%bfn2(4, nt) 488 fnj3(1) = sepj%bfn3(1, nt) 489 fnj3(2) = sepj%bfn3(2, nt) 490 fnj3(3) = sepj%bfn3(3, nt) 491 fnj3(4) = sepj%bfn3(4, nt) 492 ELSE 493 fnj1(1) = sepj%fn1(1) 494 fnj1(2) = sepj%fn1(2) 495 fnj1(3) = sepj%fn1(3) 496 fnj1(4) = sepj%fn1(4) 497 fnj2(1) = sepj%fn2(1) 498 fnj2(2) = sepj%fn2(2) 499 fnj2(3) = sepj%fn2(3) 500 fnj2(4) = sepj%fn2(4) 501 fnj3(1) = sepj%fn3(1) 502 fnj3(2) = sepj%fn3(2) 503 fnj3(3) = sepj%fn3(3) 504 fnj3(4) = sepj%fn3(4) 505 END IF 506 ! AM1/PM3/PDG correction to nuclear repulsion 507 DO ig = 1, SIZE(fni1) 508 IF (ABS(fni1(ig)) > 0._dp) THEN 509 ax = fni2(ig)*(rij - fni3(ig))**2 510 IF (ax <= 25._dp) THEN 511 scale = scale + zz*fni1(ig)*EXP(-ax) 512 IF (l_denuc) THEN 513 dax = fni2(ig)*2.0_dp*(rij - fni3(ig)) 514 dscale = dscale + dzz*fni1(ig)*EXP(-ax) - dax*zz*fni1(ig)*EXP(-ax) 515 END IF 516 ENDIF 517 ENDIF 518 IF (ABS(fnj1(ig)) > 0._dp) THEN 519 ax = fnj2(ig)*(rij - fnj3(ig))**2 520 IF (ax <= 25._dp) THEN 521 scale = scale + zz*fnj1(ig)*EXP(-ax) 522 IF (l_denuc) THEN 523 dax = fnj2(ig)*2.0_dp*(rij - fnj3(ig)) 524 dscale = dscale + dzz*fnj1(ig)*EXP(-ax) - dax*zz*fnj1(ig)*EXP(-ax) 525 END IF 526 ENDIF 527 ENDIF 528 END DO 529 ENDIF 530 IF (itype == do_method_pdg) THEN 531 ! PDDG function 532 zaf = sepi%zeff/nt 533 zbf = sepj%zeff/nt 534 pai = sepi%pre(1) 535 pbi = sepi%pre(2) 536 paj = sepj%pre(1) 537 pbj = sepj%pre(2) 538 dai = sepi%d(1) 539 dbi = sepi%d(2) 540 daj = sepj%d(1) 541 dbj = sepj%d(2) 542 apdg = 10._dp*angstrom**2 543 qcorr = (zaf*pai + zbf*paj)*EXP(-apdg*(rij - dai - daj)**2) + & 544 (zaf*pai + zbf*pbj)*EXP(-apdg*(rij - dai - dbj)**2) + & 545 (zaf*pbi + zbf*paj)*EXP(-apdg*(rij - dbi - daj)**2) + & 546 (zaf*pbi + zbf*pbj)*EXP(-apdg*(rij - dbi - dbj)**2) 547 IF (l_denuc) THEN 548 dqcorr = (zaf*pai + zbf*paj)*EXP(-apdg*(rij - dai - daj)**2)*(-2.0_dp*apdg*(rij - dai - daj)) + & 549 (zaf*pai + zbf*pbj)*EXP(-apdg*(rij - dai - dbj)**2)*(-2.0_dp*apdg*(rij - dai - dbj)) + & 550 (zaf*pbi + zbf*paj)*EXP(-apdg*(rij - dbi - daj)**2)*(-2.0_dp*apdg*(rij - dbi - daj)) + & 551 (zaf*pbi + zbf*pbj)*EXP(-apdg*(rij - dbi - dbj)**2)*(-2.0_dp*apdg*(rij - dbi - dbj)) 552 END IF 553 ELSEIF (itype == do_method_pchg) THEN 554 qcorr = 0.0_dp 555 scale = 0.0_dp 556 dscale = 0.0_dp 557 dqcorr = 0.0_dp 558 ELSE 559 qcorr = 0.0_dp 560 dqcorr = 0.0_dp 561 END IF 562 ELSE 563 ! PM6 core-core terms 564 scale = tmp 565 IF (l_denuc) dscale = dtmp 566 drija = angstrom 567 rija = rij*drija 568 xab = sepi%xab(sepj%z) 569 aab = sepi%aab(sepj%z) 570 IF ((sepi%z == 1 .AND. (sepj%z == 6 .OR. sepj%z == 7 .OR. sepj%z == 8)) .OR. & 571 (sepj%z == 1 .AND. (sepi%z == 6 .OR. sepi%z == 7 .OR. sepi%z == 8))) THEN 572 ! Special Case O-H or N-H or C-H 573 IF (l_denuc) dscale = dscale*(2._dp*xab*EXP(-aab*rija*rija)) - & 574 scale*2._dp*xab*EXP(-aab*rija*rija)*(2.0_dp*aab*rija)*drija 575 IF (l_enuc) scale = scale*(2._dp*xab*EXP(-aab*rija*rija)) 576 ELSEIF (sepi%z == 6 .AND. sepj%z == 6) THEN 577 ! Special Case C-C 578 IF (l_denuc) dscale = & 579 dscale*(2._dp*xab*EXP(-aab*(rija + 0.0003_dp*rija**6)) + 9.28_dp*EXP(-5.98_dp*rija)) & 580 - scale*2._dp*xab*EXP(-aab*(rija + 0.0003_dp*rija**6))*aab*(1.0_dp + 6.0_dp*0.0003_dp*rija**5)*drija & 581 - scale*9.28_dp*EXP(-5.98_dp*rija)*5.98_dp*drija 582 IF (l_enuc) scale = scale*(2._dp*xab*EXP(-aab*(rija + 0.0003_dp*rija**6)) + 9.28_dp*EXP(-5.98_dp*rija)) 583 ELSEIF ((sepi%z == 8 .AND. sepj%z == 14) .OR. & 584 (sepj%z == 8 .AND. sepi%z == 14)) THEN 585 ! Special Case Si-O 586 IF (l_denuc) dscale = & 587 dscale*(2._dp*xab*EXP(-aab*(rija + 0.0003_dp*rija**6)) - 0.0007_dp*EXP(-(rija - 2.9_dp)**2)) & 588 - scale*2._dp*xab*EXP(-aab*(rija + 0.0003_dp*rija**6))*aab*(1.0_dp + 6.0_dp*0.0003_dp*rija**5)*drija + & 589 scale*0.0007_dp*EXP(-(rija - 2.9_dp)**2)*(2.0_dp*(rija - 2.9_dp)*drija) 590 IF (l_enuc) scale = scale*(2._dp*xab*EXP(-aab*(rija + 0.0003_dp*rija**6)) - 0.0007_dp*EXP(-(rija - 2.9_dp)**2)) 591 ELSE 592 ! General Case 593 ! Factor of 2 found by experiment 594 IF (l_denuc) dscale = dscale*(2._dp*xab*EXP(-aab*(rija + 0.0003_dp*rija**6))) & 595 - scale*2._dp*xab*EXP(-aab*(rija + 0.0003_dp*rija**6))*aab*(1.0_dp + 6.0_dp*0.0003_dp*rija**5)*drija 596 IF (l_enuc) scale = scale*(2._dp*xab*EXP(-aab*(rija + 0.0003_dp*rija**6))) 597 END IF 598 ! General correction term a*exp(-b*(rij-c)^2) 599 xtmp = 1.e-8_dp/evolt*((REAL(sepi%z, dp)**(1._dp/3._dp) + REAL(sepj%z, dp)**(1._dp/3._dp))/rija)**12 600 IF (l_enuc) THEN 601 qcorr = (sepi%a*EXP(-sepi%b*(rij - sepi%c)**2))*zz/rij + & 602 (sepj%a*EXP(-sepj%b*(rij - sepj%c)**2))*zz/rij + & 603 ! Hard core repulsion 604 xtmp 605 END IF 606 IF (l_denuc) THEN 607 dqcorr = (sepi%a*EXP(-sepi%b*(rij - sepi%c)**2)*(-2.0_dp*sepi%b*(rij - sepi%c)))*zz/rij - & 608 (sepi%a*EXP(-sepi%b*(rij - sepi%c)**2))*zz/rij**2 + & 609 (sepj%a*EXP(-sepj%b*(rij - sepj%c)**2)*(-2.0_dp*sepj%b*(rij - sepj%c)))*zz/rij - & 610 (sepj%a*EXP(-sepj%b*(rij - sepj%c)**2))*zz/rij**2 + & 611 ! Hard core repulsion 612 (-12.0_dp*xtmp/rija*drija) 613 END IF 614 ENDIF 615 616 ! Only at the very end let's sum-up the several contributions energy/derivatives 617 ! This assignment should be method indipendent 618 IF (l_enuc) THEN 619 enuc = enuc_loc + scale + qcorr 620 END IF 621 IF (l_denuc) THEN 622 drij(1) = rijv(1)/rij 623 drij(2) = rijv(2)/rij 624 drij(3) = rijv(3)/rij 625 denuc = (denuc_loc + dscale + dqcorr)*drij 626 END IF 627 ! Debug statement 628 IF (debug_this_module) THEN 629 CALL check_dcorecore_ana(sepi, sepj, rijv, itype, se_int_control, se_taper, enuc, denuc) 630 END IF 631 ENDIF 632 END SUBROUTINE corecore_ana 633 634! ************************************************************************************************** 635!> \brief Computes analytical gradients for semiempirical core-core electrostatic 636!> interaction only. 637!> \param sepi Atomic parameters of first atom 638!> \param sepj Atomic parameters of second atom 639!> \param rijv Coordinate vector i -> j 640!> \param itype ... 641!> \param enuc nuclear-nuclear electrostatic repulsion term. 642!> \param denuc derivative of nuclear-nuclear electrostatic 643!> repulsion term. 644!> \param se_int_control input parameters that control the calculation of SE 645!> integrals (shortrange, R3 residual, screening type) 646!> \param se_taper ... 647!> \par History 648!> 04.2007 created [tlaino] 649!> Teodoro Laino (04.2008) [tlaino] - University of Zurich : new driver 650!> for computing integrals 651!> Teodoro Laino [tlaino] - University of Zurich 04.2008 : removed the 652!> core-core part 653!> \author Teodoro Laino [tlaino] - Zurich University 654!> \note 655!> Analytical version of the MOPAC rotnuc routine 656! ************************************************************************************************** 657 RECURSIVE SUBROUTINE corecore_el_ana(sepi, sepj, rijv, itype, enuc, denuc, & 658 se_int_control, se_taper) 659 TYPE(semi_empirical_type), POINTER :: sepi, sepj 660 REAL(dp), DIMENSION(3), INTENT(IN) :: rijv 661 INTEGER, INTENT(IN) :: itype 662 REAL(dp), INTENT(OUT), OPTIONAL :: enuc 663 REAL(dp), DIMENSION(3), INTENT(OUT), OPTIONAL :: denuc 664 TYPE(se_int_control_type), INTENT(IN) :: se_int_control 665 TYPE(se_taper_type), POINTER :: se_taper 666 667 CHARACTER(len=*), PARAMETER :: routineN = 'corecore_el_ana', & 668 routineP = moduleN//':'//routineN 669 670 LOGICAL :: l_denuc, l_enuc 671 REAL(dp) :: drij(3), dssss, dssss_sr, rij, ssss, & 672 ssss_sr, tmp, zz 673 TYPE(se_int_control_type) :: se_int_control_off 674 675 rij = DOT_PRODUCT(rijv, rijv) 676 ! Initialization 677 l_enuc = PRESENT(enuc) 678 l_denuc = PRESENT(denuc) 679 IF ((rij > rij_threshold) .AND. (l_enuc .OR. l_denuc)) THEN 680 ! Compute Integrals in diatomic frame 681 rij = SQRT(rij) 682 CALL setup_se_int_control_type(se_int_control_off, shortrange=.FALSE., do_ewald_r3=.FALSE., & 683 do_ewald_gks=.FALSE., integral_screening=se_int_control%integral_screening, & 684 max_multipole=do_multipole_none, pc_coulomb_int=.FALSE.) 685 CALL dssss_nucint_ana(sepi, sepj, rij, ssss=ssss, dssss=dssss, itype=itype, se_taper=se_taper, & 686 se_int_control=se_int_control_off, lgrad=l_denuc) 687 ! In case let's compute the short-range part of the (ss|ss) integral 688 IF (se_int_control%shortrange .OR. se_int_control%pc_coulomb_int) THEN 689 CALL dssss_nucint_ana(sepi, sepj, rij, ssss=ssss_sr, dssss=dssss_sr, itype=itype, & 690 se_taper=se_taper, se_int_control=se_int_control, lgrad=l_denuc) 691 ELSE 692 ssss_sr = ssss 693 dssss_sr = dssss 694 END IF 695 zz = sepi%zeff*sepj%zeff 696 ! Core Core electrostatic contribution 697 IF (l_enuc) enuc = zz*ssss_sr 698 IF (l_denuc) THEN 699 drij(1) = rijv(1)/rij 700 drij(2) = rijv(2)/rij 701 drij(3) = rijv(3)/rij 702 tmp = zz*dssss_sr 703 denuc = tmp*drij 704 END IF 705 END IF 706 END SUBROUTINE corecore_el_ana 707 708! ************************************************************************************************** 709!> \brief Exploits inversion symmetry to avoid divergence 710!> \param sepi ... 711!> \param sepj ... 712!> \param int1el ... 713!> \param int2el ... 714!> \par History 715!> 04.2007 created [tlaino] 716!> 05.2008 New driver for integral invertion (supports d-orbitals) 717!> \author Teodoro Laino - Zurich University 718! ************************************************************************************************** 719 SUBROUTINE invert_integral(sepi, sepj, int1el, int2el) 720 TYPE(semi_empirical_type), POINTER :: sepi, sepj 721 REAL(dp), DIMENSION(:), INTENT(INOUT), OPTIONAL :: int1el, int2el 722 723 CHARACTER(len=*), PARAMETER :: routineN = 'invert_integral', & 724 routineP = moduleN//':'//routineN 725 726 INTEGER :: fdim, gind, gknd, i, imap, ind, j, jmap, & 727 jnd, k, kmap, knd, l, lmap, lnd, ndim, & 728 sdim, tdim, tind 729 REAL(KIND=dp) :: ifac, jfac, kfac, lfac 730 REAL(KIND=dp), DIMENSION(2025) :: tmp2el 731 REAL(KIND=dp), DIMENSION(45) :: tmp1el 732 733! One-electron integral 734 735 IF (PRESENT(int1el)) THEN 736 fdim = sepi%atm_int_size 737 ndim = 0 738 DO i = 1, fdim 739 tmp1el(i) = 0.0_dp 740 END DO 741 DO i = 1, sepi%natorb 742 DO j = 1, i 743 ndim = ndim + 1 744 745 ! Get the integral in the original frame (along z) 746 DO ind = 1, 2 747 imap = map_x_to_z(ind, i) 748 IF (imap == 0) CYCLE 749 ifac = fac_x_to_z(ind, i) 750 DO jnd = 1, 2 751 jmap = map_x_to_z(jnd, j) 752 IF (jmap == 0) CYCLE 753 jfac = fac_x_to_z(jnd, j) 754 gind = indexb(imap, jmap) 755 756 tmp1el(ndim) = tmp1el(ndim) + ifac*jfac*int1el(gind) 757 END DO 758 END DO 759 END DO 760 END DO 761 DO i = 1, fdim 762 int1el(i) = tmp1el(i) 763 END DO 764 END IF 765 766 ! Two electron integrals 767 IF (PRESENT(int2el)) THEN 768 sdim = sepi%atm_int_size 769 tdim = sepj%atm_int_size 770 fdim = sdim*tdim 771 ndim = 0 772 DO i = 1, fdim 773 tmp2el(i) = 0.0_dp 774 END DO 775 DO i = 1, sepi%natorb 776 DO j = 1, i 777 DO k = 1, sepj%natorb 778 DO l = 1, k 779 ndim = ndim + 1 780 781 ! Get the integral in the original frame (along z) 782 DO ind = 1, 2 783 imap = map_x_to_z(ind, i) 784 IF (imap == 0) CYCLE 785 ifac = fac_x_to_z(ind, i) 786 DO jnd = 1, 2 787 jmap = map_x_to_z(jnd, j) 788 IF (jmap == 0) CYCLE 789 jfac = fac_x_to_z(jnd, j) 790 gind = indexb(imap, jmap) 791 792 ! Get the integral in the original frame (along z) 793 DO knd = 1, 2 794 kmap = map_x_to_z(knd, k) 795 IF (kmap == 0) CYCLE 796 kfac = fac_x_to_z(knd, k) 797 DO lnd = 1, 2 798 lmap = map_x_to_z(lnd, l) 799 IF (lmap == 0) CYCLE 800 lfac = fac_x_to_z(lnd, l) 801 gknd = indexb(kmap, lmap) 802 803 tind = (gind - 1)*tdim + gknd 804 tmp2el(ndim) = tmp2el(ndim) + ifac*jfac*lfac*kfac*int2el(tind) 805 END DO 806 END DO 807 808 END DO 809 END DO 810 811 END DO 812 END DO 813 END DO 814 END DO 815 DO i = 1, fdim 816 int2el(i) = tmp2el(i) 817 END DO 818 END IF 819 END SUBROUTINE invert_integral 820 821! ************************************************************************************************** 822!> \brief Exploits inversion symmetry to avoid divergence 823!> \param sepi ... 824!> \param sepj ... 825!> \param dint1el ... 826!> \param dint2el ... 827!> \par History 828!> 04.2007 created [tlaino] 829!> \author Teodoro Laino - Zurich University 830! ************************************************************************************************** 831 SUBROUTINE invert_derivative(sepi, sepj, dint1el, dint2el) 832 TYPE(semi_empirical_type), POINTER :: sepi, sepj 833 REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT), & 834 OPTIONAL :: dint1el, dint2el 835 836 CHARACTER(len=*), PARAMETER :: routineN = 'invert_derivative', & 837 routineP = moduleN//':'//routineN 838 839 INTEGER :: i, m 840 REAL(KIND=dp) :: tmp 841 842! Integral part 843 844 DO i = 1, 3 845 IF (PRESENT(dint1el)) THEN 846 CALL invert_integral(sepi, sepj, int1el=dint1el(i, :)) 847 END IF 848 IF (PRESENT(dint2el)) THEN 849 CALL invert_integral(sepi, sepj, int2el=dint2el(i, :)) 850 END IF 851 END DO 852 853 ! Derivatives part 854 IF (PRESENT(dint1el)) THEN 855 DO m = 1, SIZE(dint1el, 2) 856 tmp = dint1el(3, m) 857 dint1el(3, m) = dint1el(1, m) 858 dint1el(1, m) = tmp 859 END DO 860 END IF 861 IF (PRESENT(dint2el)) THEN 862 DO m = 1, SIZE(dint2el, 2) 863 tmp = dint2el(3, m) 864 dint2el(3, m) = dint2el(1, m) 865 dint2el(1, m) = tmp 866 END DO 867 END IF 868 END SUBROUTINE invert_derivative 869 870! ************************************************************************************************** 871!> \brief Calculates the ssss integral and analytical derivatives (main driver) 872!> \param sepi paramters of atom i 873!> \param sepj paramters of atom j 874!> \param rij interatomic distance 875!> \param ssss ... 876!> \param dssss derivative of (ssss) integral 877!> derivatives are intended w.r.t. rij 878!> \param itype ... 879!> \param se_taper ... 880!> \param se_int_control input parameters that control the calculation of SE 881!> integrals (shortrange, R3 residual, screening type) 882!> \param lgrad ... 883!> \par History 884!> 03.2007 created [tlaino] 885!> Teodoro Laino (04.2008) [tlaino] - University of Zurich : new driver 886!> for computing integrals 887!> \author Teodoro Laino - Zurich University 888!> \note 889!> Analytical version - Analytical evaluation of gradients 890!> Teodoro Laino - Zurich University 04.2007 891!> 892! ************************************************************************************************** 893 SUBROUTINE dssss_nucint_ana(sepi, sepj, rij, ssss, dssss, itype, se_taper, se_int_control, & 894 lgrad) 895 TYPE(semi_empirical_type), POINTER :: sepi, sepj 896 REAL(dp), INTENT(IN) :: rij 897 REAL(dp), INTENT(OUT) :: ssss, dssss 898 INTEGER, INTENT(IN) :: itype 899 TYPE(se_taper_type), POINTER :: se_taper 900 TYPE(se_int_control_type), INTENT(IN) :: se_int_control 901 LOGICAL, INTENT(IN) :: lgrad 902 903 CHARACTER(len=*), PARAMETER :: routineN = 'dssss_nucint_ana', & 904 routineP = moduleN//':'//routineN 905 906 REAL(KIND=dp) :: dft, ft 907 TYPE(se_int_screen_type) :: se_int_screen 908 909! Compute the Tapering function 910 911 ft = 1.0_dp 912 dft = 0.0_dp 913 IF (itype /= do_method_pchg) THEN 914 ft = taper_eval(se_taper%taper, rij) 915 dft = dtaper_eval(se_taper%taper, rij) 916 END IF 917 ! Evaluate additional taper function for dumped integrals 918 IF (se_int_control%integral_screening == do_se_IS_kdso_d) THEN 919 se_int_screen%ft = 1.0_dp 920 se_int_screen%dft = 0.0_dp 921 IF (itype /= do_method_pchg) THEN 922 se_int_screen%ft = taper_eval(se_taper%taper_add, rij) 923 se_int_screen%dft = dtaper_eval(se_taper%taper_add, rij) 924 END IF 925 END IF 926 927 ! Value of the integrals for sp shell 928 CALL nucint_sp_num(sepi, sepj, rij, ssss=ssss, itype=itype, se_int_control=se_int_control, & 929 se_int_screen=se_int_screen) 930 931 IF (lgrad) THEN 932 ! Integrals derivatives for sp shell 933 CALL dnucint_sp_ana(sepi, sepj, rij, dssss=dssss, itype=itype, se_int_control=se_int_control, & 934 se_int_screen=se_int_screen) 935 END IF 936 937 ! Tapering the value of the integrals 938 IF (lgrad) THEN 939 dssss = ft*dssss + dft*ssss 940 END IF 941 ssss = ft*ssss 942 943 ! Debug Procedure.. Check valifity of analytical gradients of nucint 944 IF (debug_this_module .AND. lgrad) THEN 945 CALL check_dssss_nucint_ana(sepi, sepj, rij, dssss, itype, se_int_control, se_taper=se_taper) 946 END IF 947 END SUBROUTINE dssss_nucint_ana 948 949! ************************************************************************************************** 950!> \brief Calculates the nuclear attraction integrals and analytical integrals (main driver) 951!> \param sepi paramters of atom i 952!> \param sepj paramters of atom j 953!> \param rij interatomic distance 954!> \param core ... 955!> \param dcore derivative of 4 X 2 array of electron-core attraction integrals 956!> derivatives are intended w.r.t. rij 957!> The storage of the nuclear attraction integrals core(kl/ij) iS 958!> (SS/)=1, (SO/)=2, (OO/)=3, (PP/)=4 959!> where ij=1 if the orbitals centred on atom i, =2 if on atom j. 960!> \param itype type of semi_empirical model 961!> extension to the original routine to compute qm/mm 962!> integrals 963!> \param se_taper ... 964!> \param se_int_control input parameters that control the calculation of SE 965!> integrals (shortrange, R3 residual, screening type) 966!> \param lgrad ... 967!> \par History 968!> 03.2007 created [tlaino] 969!> Teodoro Laino (04.2008) [tlaino] - University of Zurich : new driver 970!> for computing integrals 971!> \author Teodoro Laino - Zurich University 972!> \note 973!> Analytical version - Analytical evaluation of gradients 974!> Teodoro Laino - Zurich University 04.2007 975!> 976! ************************************************************************************************** 977 SUBROUTINE dcore_nucint_ana(sepi, sepj, rij, core, dcore, itype, se_taper, & 978 se_int_control, lgrad) 979 TYPE(semi_empirical_type), POINTER :: sepi, sepj 980 REAL(dp), INTENT(IN) :: rij 981 REAL(dp), DIMENSION(10, 2), INTENT(OUT) :: core, dcore 982 INTEGER, INTENT(IN) :: itype 983 TYPE(se_taper_type), POINTER :: se_taper 984 TYPE(se_int_control_type), INTENT(IN) :: se_int_control 985 LOGICAL, INTENT(IN) :: lgrad 986 987 CHARACTER(len=*), PARAMETER :: routineN = 'dcore_nucint_ana', & 988 routineP = moduleN//':'//routineN 989 990 INTEGER :: i 991 REAL(KIND=dp) :: dft, ft 992 TYPE(se_int_screen_type) :: se_int_screen 993 994! Compute the Tapering function 995 996 ft = 1.0_dp 997 dft = 0.0_dp 998 IF (itype /= do_method_pchg) THEN 999 ft = taper_eval(se_taper%taper, rij) 1000 dft = dtaper_eval(se_taper%taper, rij) 1001 END IF 1002 ! Evaluate additional taper function for dumped integrals 1003 IF (se_int_control%integral_screening == do_se_IS_kdso_d) THEN 1004 se_int_screen%ft = 1.0_dp 1005 se_int_screen%dft = 0.0_dp 1006 IF (itype /= do_method_pchg) THEN 1007 se_int_screen%ft = taper_eval(se_taper%taper_add, rij) 1008 se_int_screen%dft = dtaper_eval(se_taper%taper_add, rij) 1009 END IF 1010 END IF 1011 1012 ! Value of the integrals for sp shell 1013 CALL nucint_sp_num(sepi, sepj, rij, core=core, itype=itype, & 1014 se_int_control=se_int_control, se_int_screen=se_int_screen) 1015 1016 IF (sepi%dorb .OR. sepj%dorb) THEN 1017 ! Compute the contribution from d-orbitals 1018 CALL nucint_d_num(sepi, sepj, rij, core, itype, & 1019 se_int_control=se_int_control, se_int_screen=se_int_screen) 1020 END IF 1021 1022 IF (lgrad) THEN 1023 ! Integrals derivatives for sp shell 1024 CALL dnucint_sp_ana(sepi, sepj, rij, dcore=dcore, itype=itype, & 1025 se_int_control=se_int_control, se_int_screen=se_int_screen) 1026 1027 IF (sepi%dorb .OR. sepj%dorb) THEN 1028 ! Integral derivatives involving d-orbitals 1029 CALL dnucint_d_ana(sepi, sepj, rij, dcore=dcore, itype=itype, & 1030 se_int_control=se_int_control, se_int_screen=se_int_screen) 1031 END IF 1032 END IF 1033 1034 ! Tapering the value of the integrals 1035 IF (lgrad) THEN 1036 DO i = 1, sepi%core_size 1037 dcore(i, 1) = ft*dcore(i, 1) + dft*core(i, 1) 1038 END DO 1039 DO i = 1, sepj%core_size 1040 dcore(i, 2) = ft*dcore(i, 2) + dft*core(i, 2) 1041 END DO 1042 END IF 1043 DO i = 1, sepi%core_size 1044 core(i, 1) = ft*core(i, 1) 1045 END DO 1046 DO i = 1, sepj%core_size 1047 core(i, 2) = ft*core(i, 2) 1048 END DO 1049 1050 ! Debug Procedure.. Check valifity of analytical gradients of nucint 1051 IF (debug_this_module .AND. lgrad) THEN 1052 CALL check_dcore_nucint_ana(sepi, sepj, rij, dcore, itype, se_int_control, se_taper=se_taper) 1053 END IF 1054 END SUBROUTINE dcore_nucint_ana 1055 1056! ************************************************************************************************** 1057!> \brief Calculates the nuclear attraction integrals and derivatives for sp basis 1058!> \param sepi paramters of atom i 1059!> \param sepj paramters of atom j 1060!> \param rij interatomic distance 1061!> \param dssss derivative of (ssss) integral 1062!> derivatives are intended w.r.t. rij 1063!> where ij=1 if the orbitals centred on atom i, =2 if on atom j. 1064!> \param dcore derivative of 4 X 2 array of electron-core attraction integrals 1065!> The storage of the nuclear attraction integrals core(kl/ij) iS 1066!> (SS/)=1, (SP/)=2, (PP/)=3, (P+P+/)=4, (SD/)=5, 1067!> (DP/)=6, (DD/)=7, (D+P+)=8, (D+D+/)=9, (D#D#)=10 1068!> \param itype type of semi_empirical model 1069!> extension to the original routine to compute qm/mm 1070!> integrals 1071!> \param se_int_control input parameters that control the calculation of SE 1072!> integrals (shortrange, R3 residual, screening type) 1073!> \param se_int_screen ... 1074!> \par History 1075!> 04.2007 created [tlaino] 1076!> Teodoro Laino (03.2008) [tlaino] - University of Zurich : new driver 1077!> for computing integrals 1078!> 05.2008 Teodoro Laino [tlaino] - University of Zurich: major rewriting 1079!> \author Teodoro Laino - Zurich University 1080!> \note 1081!> Analytical version - Analytical evaluation of gradients 1082!> Teodoro Laino - Zurich University 04.2007 1083!> routine adapted from mopac7 (repp) 1084!> vector version written by Ernest R. Davidson, Indiana University 1085! ************************************************************************************************** 1086 SUBROUTINE dnucint_sp_ana(sepi, sepj, rij, dssss, dcore, itype, se_int_control, & 1087 se_int_screen) 1088 TYPE(semi_empirical_type), POINTER :: sepi, sepj 1089 REAL(dp), INTENT(IN) :: rij 1090 REAL(dp), INTENT(INOUT), OPTIONAL :: dssss 1091 REAL(dp), DIMENSION(10, 2), INTENT(INOUT), & 1092 OPTIONAL :: dcore 1093 INTEGER, INTENT(IN) :: itype 1094 TYPE(se_int_control_type), INTENT(IN) :: se_int_control 1095 TYPE(se_int_screen_type), INTENT(IN) :: se_int_screen 1096 1097 CHARACTER(len=*), PARAMETER :: routineN = 'dnucint_sp_ana', routineP = moduleN//':'//routineN 1098 1099 INTEGER :: ij, kl 1100 LOGICAL :: l_core, l_ssss, si, sj 1101 1102 l_core = PRESENT(dcore) 1103 l_ssss = PRESENT(dssss) 1104 IF (.NOT. (l_core .OR. l_ssss)) RETURN 1105 1106 si = (sepi%natorb > 1) 1107 sj = (sepj%natorb > 1) 1108 1109 ij = indexa(1, 1) 1110 IF (l_ssss) THEN 1111 ! Store the value for the derivative of <S S | S S > (Used for computing the core-core interactions) 1112 dssss = d_ijkl_sp(sepi, sepj, ij, ij, 0, 0, 0, 0, -1, rij, CPPint_args) 1113 END IF 1114 1115 IF (l_core) THEN 1116 ! <S S | S S > 1117 kl = indexa(1, 1) 1118 dcore(1, 1) = d_ijkl_sp(sepi, sepj, kl, ij, 0, 0, 0, 0, 2, rij, CPPint_args)*sepj%zeff 1119 IF (si) THEN 1120 ! <S P | S S > 1121 kl = indexa(2, 1) 1122 dcore(2, 1) = d_ijkl_sp(sepi, sepj, kl, ij, 0, 1, 0, 0, 2, rij, CPPint_args)*sepj%zeff 1123 ! <P P | S S > 1124 kl = indexa(2, 2) 1125 dcore(3, 1) = d_ijkl_sp(sepi, sepj, kl, ij, 1, 1, 0, 0, 2, rij, CPPint_args)*sepj%zeff 1126 ! <P+ P+ | S S > 1127 kl = indexa(3, 3) 1128 dcore(4, 1) = d_ijkl_sp(sepi, sepj, kl, ij, 1, 1, 0, 0, 2, rij, CPPint_args)*sepj%zeff 1129 END IF 1130 1131 ! <S S | S S > 1132 kl = indexa(1, 1) 1133 dcore(1, 2) = d_ijkl_sp(sepi, sepj, ij, kl, 0, 0, 0, 0, 1, rij, CPPint_args)*sepi%zeff 1134 IF (sj) THEN 1135 ! <S S | S P > 1136 kl = indexa(2, 1) 1137 dcore(2, 2) = d_ijkl_sp(sepi, sepj, ij, kl, 0, 0, 0, 1, 1, rij, CPPint_args)*sepi%zeff 1138 ! <S S | P P > 1139 kl = indexa(2, 2) 1140 dcore(3, 2) = d_ijkl_sp(sepi, sepj, ij, kl, 0, 0, 1, 1, 1, rij, CPPint_args)*sepi%zeff 1141 ! <S S | P+ P+ > 1142 kl = indexa(3, 3) 1143 dcore(4, 2) = d_ijkl_sp(sepi, sepj, ij, kl, 0, 0, 1, 1, 1, rij, CPPint_args)*sepi%zeff 1144 END IF 1145 END IF 1146 END SUBROUTINE dnucint_sp_ana 1147 1148! ************************************************************************************************** 1149!> \brief Calculates the analytical derivative of the nuclear attraction 1150!> integrals involving d orbitals 1151!> \param sepi paramters of atom i 1152!> \param sepj paramters of atom j 1153!> \param rij interatomic distance 1154!> \param dcore 4 X 2 array of electron-core attraction integrals 1155!> The storage of the nuclear attraction integrals core(kl/ij) iS 1156!> (SS/)=1, (SP/)=2, (PP/)=3, (P+P+/)=4, (SD/)=5, 1157!> (DP/)=6, (DD/)=7, (D+P+)=8, (D+D+/)=9, (D#D#)=10 1158!> 1159!> where ij=1 if the orbitals centred on atom i, =2 if on atom j. 1160!> \param itype type of semi_empirical model 1161!> extension to the original routine to compute qm/mm 1162!> integrals 1163!> \param se_int_control input parameters that control the calculation of SE 1164!> integrals (shortrange, R3 residual, screening type) 1165!> \param se_int_screen ... 1166!> \author 1167!> Teodoro Laino (05.2008) [tlaino] - University of Zurich: created 1168! ************************************************************************************************** 1169 SUBROUTINE dnucint_d_ana(sepi, sepj, rij, dcore, itype, se_int_control, & 1170 se_int_screen) 1171 TYPE(semi_empirical_type), POINTER :: sepi, sepj 1172 REAL(dp), INTENT(IN) :: rij 1173 REAL(dp), DIMENSION(10, 2), INTENT(INOUT) :: dcore 1174 INTEGER, INTENT(IN) :: itype 1175 TYPE(se_int_control_type), INTENT(IN) :: se_int_control 1176 TYPE(se_int_screen_type), INTENT(IN) :: se_int_screen 1177 1178 CHARACTER(len=*), PARAMETER :: routineN = 'dnucint_d_ana', routineP = moduleN//':'//routineN 1179 1180 INTEGER :: ij, kl 1181 1182! Check if d-orbitals are present 1183 1184 IF (sepi%dorb .OR. sepj%dorb) THEN 1185 ij = indexa(1, 1) 1186 IF (sepj%dorb) THEN 1187 ! <S S | D S> 1188 kl = indexa(5, 1) 1189 dcore(5, 2) = d_ijkl_d(sepi, sepj, ij, kl, 0, 0, 2, 0, 1, rij, CPPint_args)*sepi%zeff 1190 ! <S S | D P > 1191 kl = indexa(5, 2) 1192 dcore(6, 2) = d_ijkl_d(sepi, sepj, ij, kl, 0, 0, 2, 1, 1, rij, CPPint_args)*sepi%zeff 1193 ! <S S | D D > 1194 kl = indexa(5, 5) 1195 dcore(7, 2) = d_ijkl_d(sepi, sepj, ij, kl, 0, 0, 2, 2, 1, rij, CPPint_args)*sepi%zeff 1196 ! <S S | D+P+> 1197 kl = indexa(6, 3) 1198 dcore(8, 2) = d_ijkl_d(sepi, sepj, ij, kl, 0, 0, 2, 1, 1, rij, CPPint_args)*sepi%zeff 1199 ! <S S | D+D+> 1200 kl = indexa(6, 6) 1201 dcore(9, 2) = d_ijkl_d(sepi, sepj, ij, kl, 0, 0, 2, 2, 1, rij, CPPint_args)*sepi%zeff 1202 ! <S S | D#D#> 1203 kl = indexa(8, 8) 1204 dcore(10, 2) = d_ijkl_d(sepi, sepj, ij, kl, 0, 0, 2, 2, 1, rij, CPPint_args)*sepi%zeff 1205 END IF 1206 IF (sepi%dorb) THEN 1207 ! <D S | S S> 1208 kl = indexa(5, 1) 1209 dcore(5, 1) = d_ijkl_d(sepi, sepj, kl, ij, 2, 0, 0, 0, 2, rij, CPPint_args)*sepj%zeff 1210 ! <D P | S S > 1211 kl = indexa(5, 2) 1212 dcore(6, 1) = d_ijkl_d(sepi, sepj, kl, ij, 2, 1, 0, 0, 2, rij, CPPint_args)*sepj%zeff 1213 ! <D D | S S > 1214 kl = indexa(5, 5) 1215 dcore(7, 1) = d_ijkl_d(sepi, sepj, kl, ij, 2, 2, 0, 0, 2, rij, CPPint_args)*sepj%zeff 1216 ! <D+P+| S S > 1217 kl = indexa(6, 3) 1218 dcore(8, 1) = d_ijkl_d(sepi, sepj, kl, ij, 2, 1, 0, 0, 2, rij, CPPint_args)*sepj%zeff 1219 ! <D+D+| S S > 1220 kl = indexa(6, 6) 1221 dcore(9, 1) = d_ijkl_d(sepi, sepj, kl, ij, 2, 2, 0, 0, 2, rij, CPPint_args)*sepj%zeff 1222 ! <D#D#| S S > 1223 kl = indexa(8, 8) 1224 dcore(10, 1) = d_ijkl_d(sepi, sepj, kl, ij, 2, 2, 0, 0, 2, rij, CPPint_args)*sepj%zeff 1225 END IF 1226 END IF 1227 END SUBROUTINE dnucint_d_ana 1228 1229! ************************************************************************************************** 1230!> \brief calculates the derivative of the two-particle interactions 1231!> \param sepi Atomic parameters of first atom 1232!> \param sepj Atomic parameters of second atom 1233!> \param rijv Coordinate vector i -> j 1234!> \param w Array of two-electron repulsion integrals. 1235!> \param dw ... 1236!> \param se_int_control ... 1237!> \param se_taper ... 1238!> \par History 1239!> 04.2007 created [tlaino] 1240!> Teodoro Laino (04.2008) [tlaino] - University of Zurich : new driver 1241!> for computing integrals 1242!> \author Teodoro Laino - Zurich University 1243!> \note 1244!> Analytical version - Analytical evaluation of gradients 1245!> Teodoro Laino - Zurich University 04.2007 1246!> routine adapted from mopac7 (repp) 1247!> vector version written by Ernest R. Davidson, Indiana University 1248! ************************************************************************************************** 1249 RECURSIVE SUBROUTINE rotint_ana(sepi, sepj, rijv, w, dw, se_int_control, se_taper) 1250 TYPE(semi_empirical_type), POINTER :: sepi, sepj 1251 REAL(dp), DIMENSION(3), INTENT(IN) :: rijv 1252 REAL(dp), DIMENSION(2025), INTENT(OUT), OPTIONAL :: w 1253 REAL(dp), DIMENSION(3, 2025), INTENT(OUT), & 1254 OPTIONAL :: dw 1255 TYPE(se_int_control_type), INTENT(IN) :: se_int_control 1256 TYPE(se_taper_type), POINTER :: se_taper 1257 1258 CHARACTER(len=*), PARAMETER :: routineN = 'rotint_ana', routineP = moduleN//':'//routineN 1259 1260 INTEGER :: i, i1, ii, ij, ij1, iminus, istep, & 1261 iw_loc, j, j1, jj, k, kk, kl, l, & 1262 limij, limkl, mm 1263 LOGICAL :: invert, l_w, lgrad 1264 LOGICAL, DIMENSION(45, 45) :: logv, logv_d 1265 REAL(dp) :: rij, xtmp 1266 REAL(dp), DIMENSION(3) :: drij 1267 REAL(KIND=dp) :: cc, cc_d(3), wrepp, wrepp_d(3) 1268 REAL(KIND=dp), DIMENSION(2025) :: ww 1269 REAL(KIND=dp), DIMENSION(3, 2025) :: ww_d 1270 REAL(KIND=dp), DIMENSION(3, 45, 45) :: v_d 1271 REAL(KIND=dp), DIMENSION(45, 45) :: v 1272 REAL(KIND=dp), DIMENSION(491) :: rep, rep_d 1273 TYPE(rotmat_type), POINTER :: ij_matrix 1274 1275 NULLIFY (ij_matrix) 1276 l_w = PRESENT(w) 1277 lgrad = PRESENT(dw) 1278 IF (.NOT. (l_w .OR. lgrad)) RETURN 1279 1280 rij = DOT_PRODUCT(rijv, rijv) 1281 IF (rij > rij_threshold) THEN 1282 ! The repulsion integrals over molecular frame (w) are stored in the 1283 ! order in which they will later be used. ie. (i,j/k,l) where 1284 ! j.le.i and l.le.k and l varies most rapidly and i least 1285 ! rapidly. (anti-normal computer storage) 1286 rij = SQRT(rij) 1287 1288 ! Create the rotation matrix 1289 CALL rotmat_create(ij_matrix) 1290 CALL rotmat(sepi, sepj, rijv, rij, ij_matrix, do_derivatives=lgrad, do_invert=invert) 1291 1292 ! Compute integrals in diatomic frame as well their derivatives (if requested) 1293 CALL dterep_ana(sepi, sepj, rij, rep, rep_d, se_taper, se_int_control, lgrad=lgrad) 1294 1295 IF (lgrad) THEN 1296 drij(1) = rijv(1)/rij 1297 drij(2) = rijv(2)/rij 1298 drij(3) = rijv(3)/rij 1299 ! Possibly Invert Frame 1300 IF (invert) THEN 1301 xtmp = drij(3) 1302 drij(3) = drij(1) 1303 drij(1) = xtmp 1304 END IF 1305 END IF 1306 1307 ii = sepi%natorb 1308 kk = sepj%natorb 1309 ! First step in rotation of integrals 1310 CALL rot_2el_2c_first(sepi, sepj, rijv, se_int_control, se_taper, invert, ii, kk, rep, logv, ij_matrix, & 1311 v, lgrad, rep_d, v_d, logv_d, drij) 1312 1313 ! Integrals if requested 1314 IF (l_w) THEN 1315 ! Rotate Integrals 1316 IF (ii*kk > 0) THEN 1317 limij = sepi%atm_int_size 1318 limkl = sepj%atm_int_size 1319 istep = limkl*limij 1320 DO i1 = 1, istep 1321 ww(i1) = 0.0_dp 1322 END DO 1323 ! Second step in rotation of integrals 1324 DO i1 = 1, ii 1325 DO j1 = 1, i1 1326 ij = indexa(i1, j1) 1327 jj = indexb(i1, j1) 1328 mm = int2c_type(jj) 1329 DO k = 1, kk 1330 DO l = 1, k 1331 kl = indexb(k, l) 1332 IF (logv(ij, kl)) THEN 1333 wrepp = v(ij, kl) 1334 SELECT CASE (mm) 1335 CASE (1) 1336 ! (SS/) 1337 i = 1 1338 j = 1 1339 iw_loc = (indexb(i, j) - 1)*limkl + kl 1340 ww(iw_loc) = wrepp 1341 CASE (2) 1342 ! (SP/) 1343 j = 1 1344 DO i = 1, 3 1345 iw_loc = (indexb(i + 1, j) - 1)*limkl + kl 1346 ww(iw_loc) = ww(iw_loc) + ij_matrix%sp(i1 - 1, i)*wrepp 1347 END DO 1348 CASE (3) 1349 ! (PP/) 1350 DO i = 1, 3 1351 cc = ij_matrix%pp(i, i1 - 1, j1 - 1) 1352 iw_loc = (indexb(i + 1, i + 1) - 1)*limkl + kl 1353 ww(iw_loc) = ww(iw_loc) + cc*wrepp 1354 iminus = i - 1 1355 IF (iminus /= 0) THEN 1356 DO j = 1, iminus 1357 cc = ij_matrix%pp(1 + i + j, i1 - 1, j1 - 1) 1358 iw_loc = (indexb(i + 1, j + 1) - 1)*limkl + kl 1359 ww(iw_loc) = ww(iw_loc) + cc*wrepp 1360 END DO 1361 END IF 1362 END DO 1363 CASE (4) 1364 ! (SD/) 1365 j = 1 1366 DO i = 1, 5 1367 iw_loc = (indexb(i + 4, j) - 1)*limkl + kl 1368 ww(iw_loc) = ww(iw_loc) + ij_matrix%sd(i1 - 4, i)*wrepp 1369 END DO 1370 CASE (5) 1371 ! (DP/) 1372 DO i = 1, 5 1373 DO j = 1, 3 1374 iw_loc = (indexb(i + 4, j + 1) - 1)*limkl + kl 1375 ij1 = 3*(i - 1) + j 1376 ww(iw_loc) = ww(iw_loc) + ij_matrix%pd(ij1, i1 - 4, j1 - 1)*wrepp 1377 END DO 1378 END DO 1379 CASE (6) 1380 ! (DD/) 1381 DO i = 1, 5 1382 cc = ij_matrix%dd(i, i1 - 4, j1 - 4) 1383 iw_loc = (indexb(i + 4, i + 4) - 1)*limkl + kl 1384 ww(iw_loc) = ww(iw_loc) + cc*wrepp 1385 iminus = i - 1 1386 IF (iminus /= 0) THEN 1387 DO j = 1, iminus 1388 ij1 = inddd(i, j) 1389 cc = ij_matrix%dd(ij1, i1 - 4, j1 - 4) 1390 iw_loc = (indexb(i + 4, j + 4) - 1)*limkl + kl 1391 ww(iw_loc) = ww(iw_loc) + cc*wrepp 1392 END DO 1393 END IF 1394 END DO 1395 END SELECT 1396 END IF 1397 END DO 1398 END DO 1399 END DO 1400 END DO 1401 ! Store two electron integrals in the triangular format 1402 CALL store_2el_2c_diag(limij, limkl, ww(1:istep), w) 1403 IF (invert) CALL invert_integral(sepi, sepj, int2el=w) 1404 END IF 1405 1406 IF (debug_this_module) THEN 1407 ! Check value of integrals 1408 CALL check_rotint_ana(sepi, sepj, rijv, w, se_int_control=se_int_control, se_taper=se_taper) 1409 END IF 1410 END IF 1411 1412 ! Gradients if requested 1413 IF (lgrad) THEN 1414 ! Rotate Integrals derivatives 1415 IF (ii*kk > 0) THEN 1416 limij = sepi%atm_int_size 1417 limkl = sepj%atm_int_size 1418 istep = limkl*limij 1419 DO i1 = 1, istep 1420 ww_d(1, i1) = 0.0_dp 1421 ww_d(2, i1) = 0.0_dp 1422 ww_d(3, i1) = 0.0_dp 1423 END DO 1424 1425 ! Second step in rotation of integrals 1426 DO i1 = 1, ii 1427 DO j1 = 1, i1 1428 ij = indexa(i1, j1) 1429 jj = indexb(i1, j1) 1430 mm = int2c_type(jj) 1431 DO k = 1, kk 1432 DO l = 1, k 1433 kl = indexb(k, l) 1434 IF (logv_d(ij, kl)) THEN 1435 wrepp_d(1) = v_d(1, ij, kl) 1436 wrepp_d(2) = v_d(2, ij, kl) 1437 wrepp_d(3) = v_d(3, ij, kl) 1438 wrepp = v(ij, kl) 1439 SELECT CASE (mm) 1440 CASE (1) 1441 ! (SS/) 1442 i = 1 1443 j = 1 1444 iw_loc = (indexb(i, j) - 1)*limkl + kl 1445 ww_d(1, iw_loc) = wrepp_d(1) 1446 ww_d(2, iw_loc) = wrepp_d(2) 1447 ww_d(3, iw_loc) = wrepp_d(3) 1448 CASE (2) 1449 ! (SP/) 1450 j = 1 1451 DO i = 1, 3 1452 iw_loc = (indexb(i + 1, j) - 1)*limkl + kl 1453 ww_d(1, iw_loc) = ww_d(1, iw_loc) + ij_matrix%sp_d(1, i1 - 1, i)*wrepp + & 1454 ij_matrix%sp(i1 - 1, i)*wrepp_d(1) 1455 1456 ww_d(2, iw_loc) = ww_d(2, iw_loc) + ij_matrix%sp_d(2, i1 - 1, i)*wrepp + & 1457 ij_matrix%sp(i1 - 1, i)*wrepp_d(2) 1458 1459 ww_d(3, iw_loc) = ww_d(3, iw_loc) + ij_matrix%sp_d(3, i1 - 1, i)*wrepp + & 1460 ij_matrix%sp(i1 - 1, i)*wrepp_d(3) 1461 END DO 1462 CASE (3) 1463 ! (PP/) 1464 DO i = 1, 3 1465 cc = ij_matrix%pp(i, i1 - 1, j1 - 1) 1466 cc_d(1) = ij_matrix%pp_d(1, i, i1 - 1, j1 - 1) 1467 cc_d(2) = ij_matrix%pp_d(2, i, i1 - 1, j1 - 1) 1468 cc_d(3) = ij_matrix%pp_d(3, i, i1 - 1, j1 - 1) 1469 iw_loc = (indexb(i + 1, i + 1) - 1)*limkl + kl 1470 ww_d(1, iw_loc) = ww_d(1, iw_loc) + cc_d(1)*wrepp + cc*wrepp_d(1) 1471 ww_d(2, iw_loc) = ww_d(2, iw_loc) + cc_d(2)*wrepp + cc*wrepp_d(2) 1472 ww_d(3, iw_loc) = ww_d(3, iw_loc) + cc_d(3)*wrepp + cc*wrepp_d(3) 1473 iminus = i - 1 1474 IF (iminus /= 0) THEN 1475 DO j = 1, iminus 1476 cc = ij_matrix%pp(1 + i + j, i1 - 1, j1 - 1) 1477 cc_d(1) = ij_matrix%pp_d(1, 1 + i + j, i1 - 1, j1 - 1) 1478 cc_d(2) = ij_matrix%pp_d(2, 1 + i + j, i1 - 1, j1 - 1) 1479 cc_d(3) = ij_matrix%pp_d(3, 1 + i + j, i1 - 1, j1 - 1) 1480 iw_loc = (indexb(i + 1, j + 1) - 1)*limkl + kl 1481 ww_d(1, iw_loc) = ww_d(1, iw_loc) + cc_d(1)*wrepp + cc*wrepp_d(1) 1482 ww_d(2, iw_loc) = ww_d(2, iw_loc) + cc_d(2)*wrepp + cc*wrepp_d(2) 1483 ww_d(3, iw_loc) = ww_d(3, iw_loc) + cc_d(3)*wrepp + cc*wrepp_d(3) 1484 END DO 1485 END IF 1486 END DO 1487 CASE (4) 1488 ! (SD/) 1489 j = 1 1490 DO i = 1, 5 1491 iw_loc = (indexb(i + 4, j) - 1)*limkl + kl 1492 ww_d(1, iw_loc) = ww_d(1, iw_loc) + ij_matrix%sd_d(1, i1 - 4, i)*wrepp + & 1493 ij_matrix%sd(i1 - 4, i)*wrepp_d(1) 1494 1495 ww_d(2, iw_loc) = ww_d(2, iw_loc) + ij_matrix%sd_d(2, i1 - 4, i)*wrepp + & 1496 ij_matrix%sd(i1 - 4, i)*wrepp_d(2) 1497 1498 ww_d(3, iw_loc) = ww_d(3, iw_loc) + ij_matrix%sd_d(3, i1 - 4, i)*wrepp + & 1499 ij_matrix%sd(i1 - 4, i)*wrepp_d(3) 1500 END DO 1501 CASE (5) 1502 ! (DP/) 1503 DO i = 1, 5 1504 DO j = 1, 3 1505 iw_loc = (indexb(i + 4, j + 1) - 1)*limkl + kl 1506 ij1 = 3*(i - 1) + j 1507 ww_d(1, iw_loc) = ww_d(1, iw_loc) + ij_matrix%pd_d(1, ij1, i1 - 4, j1 - 1)*wrepp + & 1508 ij_matrix%pd(ij1, i1 - 4, j1 - 1)*wrepp_d(1) 1509 1510 ww_d(2, iw_loc) = ww_d(2, iw_loc) + ij_matrix%pd_d(2, ij1, i1 - 4, j1 - 1)*wrepp + & 1511 ij_matrix%pd(ij1, i1 - 4, j1 - 1)*wrepp_d(2) 1512 1513 ww_d(3, iw_loc) = ww_d(3, iw_loc) + ij_matrix%pd_d(3, ij1, i1 - 4, j1 - 1)*wrepp + & 1514 ij_matrix%pd(ij1, i1 - 4, j1 - 1)*wrepp_d(3) 1515 END DO 1516 END DO 1517 CASE (6) 1518 ! (DD/) 1519 DO i = 1, 5 1520 cc = ij_matrix%dd(i, i1 - 4, j1 - 4) 1521 cc_d = ij_matrix%dd_d(:, i, i1 - 4, j1 - 4) 1522 iw_loc = (indexb(i + 4, i + 4) - 1)*limkl + kl 1523 ww_d(1, iw_loc) = ww_d(1, iw_loc) + cc_d(1)*wrepp + cc*wrepp_d(1) 1524 ww_d(2, iw_loc) = ww_d(2, iw_loc) + cc_d(2)*wrepp + cc*wrepp_d(2) 1525 ww_d(3, iw_loc) = ww_d(3, iw_loc) + cc_d(3)*wrepp + cc*wrepp_d(3) 1526 iminus = i - 1 1527 IF (iminus /= 0) THEN 1528 DO j = 1, iminus 1529 ij1 = inddd(i, j) 1530 cc = ij_matrix%dd(ij1, i1 - 4, j1 - 4) 1531 cc_d(1) = ij_matrix%dd_d(1, ij1, i1 - 4, j1 - 4) 1532 cc_d(2) = ij_matrix%dd_d(2, ij1, i1 - 4, j1 - 4) 1533 cc_d(3) = ij_matrix%dd_d(3, ij1, i1 - 4, j1 - 4) 1534 iw_loc = (indexb(i + 4, j + 4) - 1)*limkl + kl 1535 ww_d(1, iw_loc) = ww_d(1, iw_loc) + cc_d(1)*wrepp + cc*wrepp_d(1) 1536 ww_d(2, iw_loc) = ww_d(2, iw_loc) + cc_d(2)*wrepp + cc*wrepp_d(2) 1537 ww_d(3, iw_loc) = ww_d(3, iw_loc) + cc_d(3)*wrepp + cc*wrepp_d(3) 1538 END DO 1539 END IF 1540 END DO 1541 END SELECT 1542 END IF 1543 END DO 1544 END DO 1545 END DO 1546 END DO 1547 ! Store two electron integrals in the triangular format 1548 CALL store_2el_2c_diag(limij, limkl, ww_dx=ww_d(1, 1:istep), ww_dy=ww_d(2, 1:istep), ww_dz=ww_d(3, 1:istep), & 1549 dw=dw) 1550 IF (invert) CALL invert_derivative(sepi, sepj, dint2el=dw) 1551 END IF 1552 1553 IF (debug_this_module) THEN 1554 ! Check derivatives 1555 CALL check_rotint_ana(sepi, sepj, rijv, dw=dw, se_int_control=se_int_control, se_taper=se_taper) 1556 END IF 1557 END IF 1558 CALL rotmat_release(ij_matrix) 1559 ENDIF 1560 END SUBROUTINE rotint_ana 1561 1562! ************************************************************************************************** 1563!> \brief Calculates the derivative and the value of two-electron repulsion 1564!> integrals and the nuclear attraction integrals w.r.t. |r| 1565!> \param sepi paramters of atom i 1566!> \param sepj paramters of atom j 1567!> \param rij interatomic distance 1568!> \param rep rray of two-electron repulsion integrals 1569!> \param rep_d array of two-electron repulsion integrals derivatives 1570!> \param se_taper ... 1571!> \param se_int_control input parameters that control the calculation of SE 1572!> integrals (shortrange, R3 residual, screening type) 1573!> \param lgrad ... 1574!> \par History 1575!> 03.2008 created [tlaino] 1576!> \author Teodoro Laino [tlaino] - Zurich University 1577! ************************************************************************************************** 1578 RECURSIVE SUBROUTINE dterep_ana(sepi, sepj, rij, rep, rep_d, se_taper, & 1579 se_int_control, lgrad) 1580 TYPE(semi_empirical_type), POINTER :: sepi, sepj 1581 REAL(KIND=dp), INTENT(IN) :: rij 1582 REAL(KIND=dp), DIMENSION(491), INTENT(OUT) :: rep, rep_d 1583 TYPE(se_taper_type), POINTER :: se_taper 1584 TYPE(se_int_control_type), INTENT(IN) :: se_int_control 1585 LOGICAL, INTENT(IN) :: lgrad 1586 1587 CHARACTER(len=*), PARAMETER :: routineN = 'dterep_ana', routineP = moduleN//':'//routineN 1588 1589 INTEGER :: i, ij, j, k, kl, l, lasti, lastj, li, & 1590 lj, lk, ll, numb 1591 REAL(KIND=dp) :: dft, ft, ft1 1592 TYPE(se_int_screen_type) :: se_int_screen 1593 1594! Compute the tapering function and its derivatives 1595 1596 ft = taper_eval(se_taper%taper, rij) 1597 dft = 0.0_dp 1598 ft1 = ft 1599 IF (lgrad) THEN 1600 ft1 = 1.0_dp 1601 dft = dtaper_eval(se_taper%taper, rij) 1602 END IF 1603 ! Evaluate additional taper function for dumped integrals 1604 IF (se_int_control%integral_screening == do_se_IS_kdso_d) THEN 1605 se_int_screen%ft = taper_eval(se_taper%taper_add, rij) 1606 IF (lgrad) & 1607 se_int_screen%dft = dtaper_eval(se_taper%taper_add, rij) 1608 END IF 1609 1610 ! Integral Values for sp shells only 1611 CALL terep_sp_num(sepi, sepj, rij, rep, se_int_control=se_int_control, & 1612 se_int_screen=se_int_screen, ft=ft1) 1613 1614 IF (sepi%dorb .OR. sepj%dorb) THEN 1615 ! Compute the contribution from d-orbitals 1616 CALL terep_d_num(sepi, sepj, rij, rep, se_int_control=se_int_control, & 1617 se_int_screen=se_int_screen, ft=ft1) 1618 END IF 1619 1620 IF (lgrad) THEN 1621 ! Integral Derivatives 1622 CALL dterep_sp_ana(sepi, sepj, rij, rep_d, rep, se_int_control, & 1623 se_int_screen, ft, dft) 1624 1625 IF (sepi%dorb .OR. sepj%dorb) THEN 1626 ! Compute the derivatives from d-orbitals 1627 CALL dterep_d_ana(sepi, sepj, rij, rep_d, rep, se_int_control, & 1628 se_int_screen, ft, dft) 1629 END IF 1630 1631 ! Tapering Integral values 1632 lasti = sepi%natorb 1633 lastj = sepj%natorb 1634 DO i = 1, lasti 1635 li = l_index(i) 1636 DO j = 1, i 1637 lj = l_index(j) 1638 ij = indexa(i, j) 1639 DO k = 1, lastj 1640 lk = l_index(k) 1641 DO l = 1, k 1642 ll = l_index(l) 1643 kl = indexa(k, l) 1644 numb = ijkl_ind(ij, kl) 1645 IF (numb > 0) rep(numb) = rep(numb)*ft 1646 END DO 1647 END DO 1648 END DO 1649 END DO 1650 END IF 1651 1652 ! Possibly debug 2el 2cent integrals and derivatives 1653 IF (debug_this_module) THEN 1654 CALL check_dterep_ana(sepi, sepj, rij, rep, rep_d, se_int_control, se_taper=se_taper, & 1655 lgrad=lgrad) 1656 END IF 1657 END SUBROUTINE dterep_ana 1658 1659! ************************************************************************************************** 1660!> \brief Calculates the derivative and the value of two-electron repulsion 1661!> integrals and the nuclear attraction integrals w.r.t. |r| - sp shells only 1662!> \param sepi paramters of atom i 1663!> \param sepj paramters of atom j 1664!> \param rij interatomic distance 1665!> \param drep array of derivatives of two-electron repulsion integrals 1666!> \param rep array of two-electron repulsion integrals 1667!> \param se_int_control input parameters that control the calculation of SE 1668!> integrals (shortrange, R3 residual, screening type) 1669!> \param se_int_screen ... 1670!> \param ft ... 1671!> \param dft ... 1672!> \par History 1673!> 04.2007 created [tlaino] 1674!> Teodoro Laino (03.2008) [tlaino] - University of Zurich : new driver 1675!> for computing integrals 1676!> 05.2008 Teodoro Laino [tlaino] - University of Zurich: major rewriting 1677!> \author Teodoro Laino - Zurich University 1678!> \note 1679!> Analytical version - Analytical evaluation of gradients 1680!> Teodoro Laino - Zurich University 04.2007 1681!> routine adapted from mopac7 (repp) 1682!> vector version written by Ernest R. Davidson, Indiana University 1683! ************************************************************************************************** 1684 SUBROUTINE dterep_sp_ana(sepi, sepj, rij, drep, rep, se_int_control, & 1685 se_int_screen, ft, dft) 1686 TYPE(semi_empirical_type), POINTER :: sepi, sepj 1687 REAL(dp), INTENT(IN) :: rij 1688 REAL(dp), DIMENSION(491), INTENT(OUT) :: drep 1689 REAL(dp), DIMENSION(491), INTENT(IN) :: rep 1690 TYPE(se_int_control_type), INTENT(IN) :: se_int_control 1691 TYPE(se_int_screen_type), INTENT(IN) :: se_int_screen 1692 REAL(dp), INTENT(IN) :: ft, dft 1693 1694 CHARACTER(len=*), PARAMETER :: routineN = 'dterep_sp_ana', routineP = moduleN//':'//routineN 1695 1696 INTEGER :: i, ij, j, k, kl, l, lasti, lastj, li, & 1697 lj, lk, ll, nold, numb 1698 REAL(KIND=dp) :: tmp 1699 1700 lasti = sepi%natorb 1701 lastj = sepj%natorb 1702 DO i = 1, MIN(lasti, 4) 1703 li = l_index(i) 1704 DO j = 1, i 1705 lj = l_index(j) 1706 ij = indexa(i, j) 1707 DO k = 1, MIN(lastj, 4) 1708 lk = l_index(k) 1709 DO l = 1, k 1710 ll = l_index(l) 1711 kl = indexa(k, l) 1712 1713 numb = ijkl_ind(ij, kl) 1714 IF (numb > 0) THEN 1715 nold = ijkl_sym(numb) 1716 IF (nold > 0) THEN 1717 drep(numb) = drep(nold) 1718 ELSE IF (nold < 0) THEN 1719 drep(numb) = -drep(-nold) 1720 ELSE IF (nold == 0) THEN 1721 tmp = d_ijkl_sp(sepi, sepj, ij, kl, li, lj, lk, ll, 0, rij, & 1722 se_int_control, se_int_screen, do_method_undef) 1723 drep(numb) = dft*rep(numb) + ft*tmp 1724 END IF 1725 END IF 1726 END DO 1727 END DO 1728 END DO 1729 END DO 1730 END SUBROUTINE dterep_sp_ana 1731 1732! ************************************************************************************************** 1733!> \brief Calculates the derivatives of the two-electron repulsion integrals - d shell only 1734!> \param sepi paramters of atom i 1735!> \param sepj paramters of atom j 1736!> \param rij interatomic distance 1737!> \param drep ... 1738!> \param rep array of two-electron repulsion integrals 1739!> \param se_int_control input parameters that control the calculation of 1740!> integrals (shortrange, R3 residual, screening type) 1741!> \param se_int_screen ... 1742!> \param ft ... 1743!> \param dft ... 1744!> \par History 1745!> Teodoro Laino (05.2008) [tlaino] - University of Zurich : new driver 1746!> for computing integral derivatives for d-orbitals 1747! ************************************************************************************************** 1748 SUBROUTINE dterep_d_ana(sepi, sepj, rij, drep, rep, se_int_control, & 1749 se_int_screen, ft, dft) 1750 TYPE(semi_empirical_type), POINTER :: sepi, sepj 1751 REAL(dp), INTENT(IN) :: rij 1752 REAL(dp), DIMENSION(491), INTENT(INOUT) :: drep 1753 REAL(dp), DIMENSION(491), INTENT(IN) :: rep 1754 TYPE(se_int_control_type), INTENT(IN) :: se_int_control 1755 TYPE(se_int_screen_type), INTENT(IN) :: se_int_screen 1756 REAL(dp), INTENT(IN) :: ft, dft 1757 1758 CHARACTER(len=*), PARAMETER :: routineN = 'dterep_d_ana', routineP = moduleN//':'//routineN 1759 1760 INTEGER :: i, ij, j, k, kl, l, lasti, lastj, li, & 1761 lj, lk, ll, nold, numb 1762 REAL(KIND=dp) :: tmp 1763 1764 lasti = sepi%natorb 1765 lastj = sepj%natorb 1766 DO i = 1, lasti 1767 li = l_index(i) 1768 DO j = 1, i 1769 lj = l_index(j) 1770 ij = indexa(i, j) 1771 DO k = 1, lastj 1772 lk = l_index(k) 1773 DO l = 1, k 1774 ll = l_index(l) 1775 kl = indexa(k, l) 1776 1777 numb = ijkl_ind(ij, kl) 1778 ! From 1 to 34 we store integrals involving sp shells 1779 IF (numb > 34) THEN 1780 nold = ijkl_sym(numb) 1781 IF (nold > 34) THEN 1782 drep(numb) = drep(nold) 1783 ELSE IF (nold < -34) THEN 1784 drep(numb) = -drep(-nold) 1785 ELSE IF (nold == 0) THEN 1786 tmp = d_ijkl_d(sepi, sepj, ij, kl, li, lj, lk, ll, 0, rij, & 1787 se_int_control, se_int_screen, do_method_undef) 1788 drep(numb) = dft*rep(numb) + ft*tmp 1789 END IF 1790 END IF 1791 END DO 1792 END DO 1793 END DO 1794 END DO 1795 END SUBROUTINE dterep_d_ana 1796 1797END MODULE semi_empirical_int_ana 1798