(git:15c1bfc)
Loading...
Searching...
No Matches
qs_cneo_methods.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2025 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \brief A collection of functions used by CNEO-DFT
10!> (see J. Chem. Theory Comput. 2025, 21, 16, 7865–7877)
11!> \par History
12!> 08.2025 created [zc62]
13!> \author Zehua Chen
14! **************************************************************************************************
16 USE ai_verfc, ONLY: verfc
17 USE ao_util, ONLY: trace_r_axb
20 USE atom_types, ONLY: cgto_basis,&
23 lmat,&
30 USE bibliography, ONLY: chen2025,&
31 cite_reference
32 USE core_ae, ONLY: verfc_force
36 USE kinds, ONLY: dp
37 USE mathconstants, ONLY: dfac,&
38 fourpi,&
39 pi
43 USE orbital_pointers, ONLY: indso,&
44 indso_inv,&
46 ncoset,&
47 nso,&
48 nsoset
50 USE physcon, ONLY: massunit
69 USE qs_kind_types, ONLY: get_qs_kind,&
79 USE util, ONLY: get_limit
81 USE virial_types, ONLY: virial_type
82 USE whittaker, ONLY: whittaker_c0a,&
84
85!$ USE OMP_LIB, ONLY: omp_get_max_threads, omp_get_thread_num
86
87#include "./base/base_uses.f90"
88
89 IMPLICIT NONE
90
91 PRIVATE
92
93 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_cneo_methods'
94
97
98CONTAINS
99
100! **************************************************************************************************
101!> \brief ...
102!> \param potential ...
103!> \param nuc_basis ...
104!> \param nuc_soft_basis ...
105!> \param gapw_control ...
106!> \param grid_atom ...
107! **************************************************************************************************
108 SUBROUTINE init_cneo_potential_internals(potential, nuc_basis, nuc_soft_basis, gapw_control, grid_atom)
109
110 TYPE(cneo_potential_type), POINTER :: potential
111 TYPE(gto_basis_set_type), POINTER :: nuc_basis, nuc_soft_basis
112 TYPE(gapw_control_type), POINTER :: gapw_control
113 TYPE(grid_atom_type), POINTER :: grid_atom
114
115 CHARACTER(len=*), PARAMETER :: routinen = 'init_cneo_potential_internals'
116
117 INTEGER :: handle, i, icg, ico, ii, ipgf, ipgf1, ipgf2, ir, is1, is2, iset, iset1, iset2, &
118 iso, iso1, iso2, iso_pgf, iso_set, j, k, k1, k2, l, l_iso, l_sub, l_sum, ll, llmax, &
119 lmax12, lmax_expansion, lmax_sphere, lmin12, m, m1, m2, max_iso_not0, max_iso_not0_local, &
120 max_s, max_s_harm, maxl, maxso, n1, n2, nl, nne, npgf2, npgf_sum, npsgf, nr, ns, nset, &
121 nsgf, nsotot, nsox
122 INTEGER, ALLOCATABLE, DIMENSION(:) :: cg_n_list
123 INTEGER, ALLOCATABLE, DIMENSION(:, :, :) :: cg_list
124 INTEGER, DIMENSION(0:lmat, 100) :: set_index, shell_index
125 INTEGER, DIMENSION(:), POINTER :: lmax, lmin, n2oindex, npgf, npgf_s, &
126 nshell, o2nindex
127 INTEGER, DIMENSION(:, :), POINTER :: first_sgf, ls
128 LOGICAL, ALLOCATABLE, DIMENSION(:, :) :: done_vgg
129 REAL(kind=dp) :: c1, c2, gcc_tmp, mass, massinv, &
130 root_zet12, scal, scal1, zet12
131 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: erf_zet12, g1, g2, gg0, int1, int2
132 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: work
133 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: dist
134 REAL(kind=dp), DIMENSION(:, :), POINTER :: kin, my_gcc_h, my_gcc_s, oorad2l, ovlp, &
135 rad2l, utrans, zet
136 REAL(kind=dp), DIMENSION(:, :, :), POINTER :: distance, gcc_h, gcc_s, gg, my_cg
137 REAL(kind=dp), DIMENSION(:, :, :, :), POINTER :: vgg
138 TYPE(atom_basis_type), POINTER :: basis
139 TYPE(atom_integrals), POINTER :: integrals
140 TYPE(grid_atom_type), POINTER :: grid
141 TYPE(harmonics_atom_type), POINTER :: harmonics
142
143 cpassert(ASSOCIATED(potential))
144 cpassert(ASSOCIATED(nuc_basis))
145 cpassert(ASSOCIATED(nuc_soft_basis))
146
147 CALL cite_reference(chen2025)
148
149 CALL timeset(routinen, handle)
150
151 CALL get_cneo_potential(potential, my_gcc_h=my_gcc_h, my_gcc_s=my_gcc_s, &
152 ovlp=ovlp, kin=kin, utrans=utrans, distance=distance, &
153 harmonics=harmonics, gg=gg, vgg=vgg, n2oindex=n2oindex, &
154 o2nindex=o2nindex, rad2l=rad2l, oorad2l=oorad2l)
155 cpassert(.NOT. ASSOCIATED(my_gcc_h))
156 cpassert(.NOT. ASSOCIATED(my_gcc_s))
157 cpassert(.NOT. ASSOCIATED(ovlp))
158 cpassert(.NOT. ASSOCIATED(kin))
159 cpassert(.NOT. ASSOCIATED(utrans))
160 cpassert(.NOT. ASSOCIATED(distance))
161 cpassert(.NOT. ASSOCIATED(harmonics))
162 cpassert(.NOT. ASSOCIATED(gg))
163 cpassert(.NOT. ASSOCIATED(vgg))
164 cpassert(.NOT. ASSOCIATED(n2oindex))
165 cpassert(.NOT. ASSOCIATED(o2nindex))
166 cpassert(.NOT. ASSOCIATED(rad2l))
167 cpassert(.NOT. ASSOCIATED(oorad2l))
168
169 ! ovlp, kin and utrans parts are mostly copied from atom_kind_orbitals::calculate_atomic_orbitals
170 ! and atom_set_basis::set_kind_basis_atomic
171 NULLIFY (basis, integrals, grid)
172 ALLOCATE (basis, integrals)
173 CALL allocate_grid_atom(grid)
174 basis%grid => grid
175 NULLIFY (basis%am, basis%cm, basis%as, basis%ns, basis%bf, basis%dbf, basis%ddbf)
176 ! fill in the basis data structures
177 basis%basis_type = cgto_basis
178 basis%eps_eig = 1.e-12_dp
179
180 NULLIFY (nshell, npgf, lmin, lmax, ls, zet, gcc_h, first_sgf)
181 CALL get_gto_basis_set(nuc_basis, nset=nset, nshell=nshell, npgf=npgf, lmin=lmin, &
182 lmax=lmax, l=ls, nsgf=nsgf, zet=zet, gcc=gcc_h, first_sgf=first_sgf, &
183 maxl=maxl, maxso=maxso, npgf_sum=npgf_sum)
184 NULLIFY (npgf_s, gcc_s)
185 CALL get_gto_basis_set(nuc_soft_basis, npgf=npgf_s, gcc=gcc_s)
186 ! There is such a limitation because we rely on atomic code to build S, T and U.
187 ! Usually l=5 is more than enough, suppoting PB6H basis.
188 IF (maxl > lmat) &
189 CALL cp_abort(__location__, "Nuclear basis with angular momentum higher than "// &
190 "atom_types::lmat is not supported yet.")
191
192 set_index = 0
193 shell_index = 0
194 basis%nprim = 0
195 basis%nbas = 0
196 DO i = 1, nset
197 DO j = lmin(i), min(lmax(i), lmat)
198 basis%nprim(j) = basis%nprim(j) + npgf(i)
199 END DO
200 DO j = 1, nshell(i)
201 l = ls(j, i)
202 IF (l <= lmat) THEN
203 basis%nbas(l) = basis%nbas(l) + 1
204 k = basis%nbas(l)
205 cpassert(k <= 100)
206 set_index(l, k) = i
207 shell_index(l, k) = j
208 END IF
209 END DO
210 END DO
211
212 nl = maxval(basis%nprim)
213 ns = maxval(basis%nbas)
214 ALLOCATE (basis%am(nl, 0:lmat))
215 basis%am = 0._dp
216 ALLOCATE (basis%cm(nl, ns, 0:lmat))
217 basis%cm = 0._dp
218 DO l = 0, lmat
219 nl = 0
220 ns = 0
221 DO i = 1, nset
222 IF (l >= lmin(i) .AND. l <= lmax(i)) THEN
223 DO ipgf = 1, npgf(i)
224 basis%am(nl + ipgf, l) = zet(ipgf, i)
225 END DO
226 DO ii = 1, nshell(i)
227 IF (ls(ii, i) == l) THEN
228 ns = ns + 1
229 DO ipgf = 1, npgf(i)
230 basis%cm(nl + ipgf, ns, l) = gcc_h(ipgf, ii, i) ! NOTE: not normalized
231 END DO
232 END IF
233 END DO
234 nl = nl + npgf(i)
235 END IF
236 END DO
237 END DO
238
239 ! overlap, kinetic and transformation matrices
240 CALL atom_int_setup(integrals, basis)
241
242 ! make the integrals full matrix form
243 ALLOCATE (ovlp(nsgf, nsgf), kin(nsgf, nsgf), utrans(nsgf, nsgf))
244 ovlp = 0.0_dp
245 kin = 0.0_dp
246 utrans = 0.0_dp
247 CALL get_cneo_potential(potential, mass=mass)
248 mass = mass*massunit
249 massinv = 1._dp/mass
250 nne = 0 ! number of linear-independent spherical basis functions
251 DO l = 0, lmat
252 ll = 2*l
253 DO k2 = 1, integrals%nne(l)
254 DO m = 0, ll
255 nne = nne + 1
256 DO k1 = 1, basis%nbas(l)
257 scal1 = sqrt(integrals%ovlp(k1, k1, l))
258 i = first_sgf(shell_index(l, k1), set_index(l, k1))
259 utrans(i + m, nne) = integrals%utrans(k1, k2, l)*scal1
260 END DO
261 END DO
262 END DO
263 DO k1 = 1, basis%nbas(l)
264 scal1 = 1._dp/sqrt(integrals%ovlp(k1, k1, l))
265 i = first_sgf(shell_index(l, k1), set_index(l, k1))
266 DO k2 = 1, basis%nbas(l)
267 scal = scal1/sqrt(integrals%ovlp(k2, k2, l))
268 j = first_sgf(shell_index(l, k2), set_index(l, k2))
269 DO m = 0, ll
270 ! normalize the integrals
271 ovlp(i + m, j + m) = integrals%ovlp(k1, k2, l)*scal
272 kin(i + m, j + m) = integrals%kin(k1, k2, l)*scal*massinv
273 END DO
274 END DO
275 END DO
276 END DO
277
278 nsotot = maxso*nset
279 ALLOCATE (my_gcc_h(nsotot, nsgf), my_gcc_s(nsotot, nsgf))
280 my_gcc_h = 0.0_dp
281 my_gcc_s = 0.0_dp
282 ! create gcc that really 3D-normalize the basis functions
283 DO l = 0, min(maxl, lmat)
284 ns = 0
285 m = 0
286 ll = 2*l
287 k = nsoset(l - 1) + 1
288 DO i = 1, nset
289 IF (l >= lmin(i) .AND. l <= lmax(i)) THEN
290 nsox = nsoset(lmax(i))
291 DO ii = 1, nshell(i)
292 IF (ls(ii, i) == l) THEN
293 ns = ns + 1
294 k1 = first_sgf(shell_index(l, ns), set_index(l, ns))
295 scal = 1._dp/sqrt(integrals%ovlp(ns, ns, l))
296 DO ipgf = 1, npgf(i)
297 gcc_tmp = gcc_h(ipgf, ii, i)*scal
298 k2 = (ipgf - 1)*nsox + m
299 DO j = 0, ll
300 my_gcc_h(k + k2 + j, k1 + j) = gcc_tmp
301 END DO
302 END DO
303 DO ipgf = 1, npgf_s(i)
304 gcc_tmp = gcc_s(ipgf, ii, i)*scal
305 k2 = (ipgf - 1)*nsox + m
306 DO j = 0, ll
307 my_gcc_s(k + k2 + j, k1 + j) = gcc_tmp
308 END DO
309 END DO
310 END IF
311 END DO
312 END IF
313 m = m + maxso
314 END DO
315 END DO
316
317 CALL atom_int_release(integrals)
318 CALL set_cneo_potential(potential, nsgf=nsgf, nne=nne, nsotot=nsotot, &
319 my_gcc_h=my_gcc_h, my_gcc_s=my_gcc_s, &
320 ovlp=ovlp, kin=kin, utrans=utrans)
321 CALL release_atom_basis(basis)
322 DEALLOCATE (basis, integrals)
323
324 ! initialize my_CG
325 lmax_sphere = gapw_control%lmax_sphere
326 ! make sure llmax is at least 1 such that distance matrices can be generated
327 llmax = max(1, min(lmax_sphere, 2*maxl))
328 max_s_harm = nsoset(llmax)
329 max_s = nsoset(maxl)
330 NULLIFY (my_cg)
331 CALL reallocate(my_cg, 1, max_s, 1, max_s, 1, max_s_harm)
332 CALL create_my_cg_cneo(my_cg, max(llmax, 2*maxl, 1), maxl, llmax)
333
334 ! initialize harmonics
335 CALL allocate_harmonics_atom(harmonics)
336 CALL create_harmonics_atom_cneo(harmonics, my_cg, llmax, max_s, max_s_harm)
337 DEALLOCATE (my_cg)
338 CALL get_maxl_cg_cneo(harmonics, nuc_basis, llmax, max_s_harm)
339
340 CALL set_cneo_potential(potential, harmonics=harmonics)
341
342 ! initialize my own rad2l and oorad2l
343 ! copied from qs_grid_atom::create_grid_atom
344 nr = grid_atom%nr
345 NULLIFY (rad2l, oorad2l)
346 CALL reallocate(rad2l, 1, nr, 0, llmax + 1)
347 CALL reallocate(oorad2l, 1, nr, 0, llmax + 1)
348 rad2l(:, 0) = 1._dp
349 oorad2l(:, 0) = 1._dp
350 DO l = 1, llmax + 1
351 rad2l(:, l) = rad2l(:, l - 1)*grid_atom%rad(:)
352 oorad2l(:, l) = oorad2l(:, l - 1)/grid_atom%rad(:)
353 END DO
354 CALL set_cneo_potential(potential, rad2l=rad2l, oorad2l=oorad2l)
355 ! still need to bump lmax in grid_atom as qs_rho0_types::calculate_g0 uses it
356 IF (SIZE(rad2l, 2) > SIZE(grid_atom%rad2l, 2)) THEN
357 cpassert(SIZE(rad2l, 1) == SIZE(grid_atom%rad2l, 1))
358 DEALLOCATE (grid_atom%rad2l)
359 NULLIFY (grid_atom%rad2l)
360 CALL reallocate(grid_atom%rad2l, 1, nr, 0, llmax + 1)
361 grid_atom%rad2l = rad2l
362 END IF
363 IF (SIZE(oorad2l, 2) > SIZE(grid_atom%oorad2l, 2)) THEN
364 cpassert(SIZE(oorad2l, 1) == SIZE(grid_atom%oorad2l, 1))
365 DEALLOCATE (grid_atom%oorad2l)
366 NULLIFY (grid_atom%oorad2l)
367 CALL reallocate(grid_atom%oorad2l, 1, nr, 0, llmax + 1)
368 grid_atom%oorad2l = oorad2l
369 END IF
370
371 ! distance matrices
372 ALLOCATE (distance(nsgf, nsgf, 3), dist(nsotot, nsotot, 3))
373 distance = 0.0_dp
374 dist = 0.0_dp
375 ! initialize gg and vgg
376 ! mostly copied from qs_rho_atom_methods::calculate_rho_atom
377 max_iso_not0 = harmonics%max_iso_not0
378 lmax_expansion = indso(1, max_iso_not0)
379 my_cg => harmonics%my_CG
380 ALLOCATE (g1(nr), g2(nr), gg0(nr), gg(nr, 0:2*maxl, npgf_sum*(npgf_sum + 1)/2))
381 ALLOCATE (erf_zet12(nr), vgg(nr, 0:2*maxl, 0:indso(1, max_iso_not0), npgf_sum*(npgf_sum + 1)/2))
382 ALLOCATE (done_vgg(0:2*maxl, 0:indso(1, max_iso_not0)))
383 ALLOCATE (int1(nr), int2(nr))
384 ALLOCATE (cg_list(2, nsoset(maxl)**2, max_s_harm), cg_n_list(max_s_harm))
385
386 j = 0
387 m1 = 0
388 DO iset1 = 1, nset
389 n1 = nsoset(lmax(iset1))
390 m2 = 0
391 DO iset2 = 1, iset1
392 n2 = nsoset(lmax(iset2))
393
394 CALL get_none0_cg_list(my_cg, lmin(iset1), lmax(iset1), lmin(iset2), lmax(iset2), &
395 max_s_harm, lmax_expansion, cg_list, cg_n_list, max_iso_not0_local)
396 cpassert(max_iso_not0_local .LE. max_iso_not0)
397
398 DO ipgf1 = 1, npgf(iset1)
399 g1(1:nr) = exp(-zet(ipgf1, iset1)*grid_atom%rad2(1:nr))
400
401 IF (iset2 == iset1) THEN
402 npgf2 = ipgf1
403 ELSE
404 npgf2 = npgf(iset2)
405 END IF
406 DO ipgf2 = 1, npgf2
407 zet12 = zet(ipgf1, iset1) + zet(ipgf2, iset2)
408
409 ! distance part
410 ! -1 -> y -> 2, 0 -> z -> 3, 1 -> x -> 1
411 DO m = -1, 1
412 k = m + 3
413 IF (m == 1) k = 1
414 iso = indso_inv(1, m)
415 DO icg = 1, cg_n_list(iso)
416 is1 = cg_list(1, icg, iso)
417 is2 = cg_list(2, icg, iso)
418
419 iso1 = is1 + n1*(ipgf1 - 1) + m1
420 iso2 = is2 + n2*(ipgf2 - 1) + m2
421
422 l = indso(1, is1) + indso(1, is2)
423 dist(iso1, iso2, k) = dist(iso1, iso2, k) + my_cg(is1, is2, iso)* &
424 pi*dfac(l + 2)/ &
425 ((2.0_dp*zet12)**((l + 3)/2)*sqrt(3.0_dp*zet12))
426 dist(iso2, iso1, k) = dist(iso1, iso2, k) ! symmetric
427 END DO !icg
428 END DO
429
430 ! gg and vgg part
431 j = j + 1
432 g2(1:nr) = exp(-zet(ipgf2, iset2)*grid_atom%rad2(1:nr))
433 lmin12 = lmin(iset1) + lmin(iset2)
434 lmax12 = lmax(iset1) + lmax(iset2)
435
436 root_zet12 = sqrt(zet12)
437 DO ir = 1, nr
438 erf_zet12(ir) = erf(root_zet12*grid_atom%rad(ir))
439 END DO
440
441 gg(:, :, j) = 0.0_dp
442 vgg(:, :, :, j) = 0.0_dp
443 done_vgg = .false.
444 ! reduce the number of terms in the expansion local densities
445 IF (lmin12 .LE. lmax_expansion) THEN
446 IF (lmin12 == 0) THEN
447 gg(1:nr, lmin12, j) = g1(1:nr)*g2(1:nr)
448 gg0(1:nr) = gg(1:nr, lmin12, j)
449 ELSE
450 gg0(1:nr) = g1(1:nr)*g2(1:nr)
451 gg(1:nr, lmin12, j) = rad2l(1:nr, lmin12)*g1(1:nr)*g2(1:nr)
452 END IF
453
454 ! reduce the number of terms in the expansion local densities
455 IF (lmax12 .GT. lmax_expansion) lmax12 = lmax_expansion
456
457 DO l = lmin12 + 1, lmax12
458 gg(1:nr, l, j) = grid_atom%rad(1:nr)*gg(1:nr, l - 1, j)
459 END DO
460
461 c2 = sqrt(pi*pi*pi/(zet12*zet12*zet12))
462
463 DO iso = 1, max_iso_not0_local
464 l_iso = indso(1, iso)
465 c1 = fourpi/(2._dp*real(l_iso, dp) + 1._dp)
466 DO icg = 1, cg_n_list(iso)
467 iso1 = cg_list(1, icg, iso)
468 iso2 = cg_list(2, icg, iso)
469
470 l = indso(1, iso1) + indso(1, iso2)
471 cpassert(l <= lmax_expansion)
472 IF (done_vgg(l, l_iso)) cycle
473 l_sum = l + l_iso
474 l_sub = l - l_iso
475
476 IF (l_sum == 0) THEN
477 vgg(1:nr, l, l_iso, j) = erf_zet12(1:nr)*oorad2l(1:nr, 1)*c2
478 ELSE
479 CALL whittaker_c0a(int1, grid_atom%rad, gg0, erf_zet12, zet12, l, l_iso, nr)
480 CALL whittaker_ci(int2, grid_atom%rad, gg0, zet12, l_sub, nr)
481
482 DO ir = 1, nr
483 int2(ir) = rad2l(ir, l_iso)*int2(ir)
484 vgg(ir, l, l_iso, j) = c1*(int1(ir) + int2(ir))
485 END DO
486 END IF
487 done_vgg(l, l_iso) = .true.
488 END DO
489 END DO
490 END IF ! lmax_expansion
491
492 END DO ! ipgf2
493 END DO ! ipgf1
494 m2 = m2 + maxso
495 END DO ! iset2
496 m1 = m1 + maxso
497 END DO ! iset1
498
499 DEALLOCATE (g1, g2, gg0, erf_zet12, int1, int2, done_vgg)
500 DEALLOCATE (cg_list, cg_n_list)
501
502 ALLOCATE (work(nsotot, nsgf))
503 DO k = 1, 3
504 CALL dgemm("N", "N", nsotot, nsgf, nsotot, 1.0_dp, dist(:, :, k), nsotot, my_gcc_h, &
505 nsotot, 0.0_dp, work, nsotot)
506 CALL dgemm("T", "N", nsgf, nsgf, nsotot, 1.0_dp, my_gcc_h, nsotot, work, &
507 nsotot, 0.0_dp, distance(:, :, k), nsgf)
508 END DO
509 DEALLOCATE (work, dist)
510 CALL set_cneo_potential(potential, distance=distance, gg=gg, vgg=vgg)
511
512 ! Index transformation OLD-NEW
513 ! copied from paw_proj_set_types::build_projector
514 ALLOCATE (o2nindex(nsotot))
515 ALLOCATE (n2oindex(nsotot))
516 o2nindex = 0
517 n2oindex = 0
518 ico = 1
519 DO iset = 1, nset
520 iso_set = (iset - 1)*maxso + 1
521 nsox = nsoset(lmax(iset))
522 DO ipgf = 1, npgf(iset)
523 iso_pgf = iso_set + (ipgf - 1)*nsox
524 iso = iso_pgf + nsoset(lmin(iset) - 1)
525 DO l = lmin(iset), lmax(iset)
526 DO k = 1, nso(l)
527 n2oindex(ico) = iso
528 o2nindex(iso) = ico
529 iso = iso + 1
530 ico = ico + 1
531 END DO
532 END DO
533 END DO
534 END DO
535 npsgf = ico - 1
536 CALL set_cneo_potential(potential, npsgf=npsgf, n2oindex=n2oindex, o2nindex=o2nindex)
537
538 CALL timestop(handle)
539
540 END SUBROUTINE init_cneo_potential_internals
541
542! **************************************************************************************************
543!> \brief ...
544!> \param rhoz_cneo_set ...
545!> \param atomic_kind_set ...
546!> \param qs_kind_set ...
547!> \param qs_env ...
548! **************************************************************************************************
549 SUBROUTINE allocate_rhoz_cneo_internals(rhoz_cneo_set, atomic_kind_set, &
550 qs_kind_set, qs_env)
551
552 TYPE(rhoz_cneo_type), DIMENSION(:), POINTER :: rhoz_cneo_set
553 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
554 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
555 TYPE(qs_environment_type), POINTER :: qs_env
556
557 CHARACTER(len=*), PARAMETER :: routinen = 'allocate_rhoz_cneo_internals'
558
559 INTEGER :: bo(2), handle, iat, iatom, ikind, &
560 max_iso_not0, mepos, nat, natom, &
561 npsgf, nr, nsgf, nsotot, num_pe
562 INTEGER, DIMENSION(:), POINTER :: atom_list
563 LOGICAL :: paw_atom
564 TYPE(cneo_potential_type), POINTER :: cneo_potential
565 TYPE(mp_para_env_type), POINTER :: para_env
566
567 CALL timeset(routinen, handle)
568
569 CALL get_atomic_kind_set(atomic_kind_set, natom=natom)
570
571 CALL allocate_rhoz_cneo_set(rhoz_cneo_set, natom)
572
573 NULLIFY (para_env)
574 CALL get_qs_env(qs_env, para_env=para_env)
575
576 DO ikind = 1, SIZE(atomic_kind_set)
577
578 NULLIFY (cneo_potential)
579 CALL get_qs_kind(qs_kind_set(ikind), &
580 ngrid_rad=nr, &
581 paw_atom=paw_atom, &
582 cneo_potential=cneo_potential)
583
584 IF (ASSOCIATED(cneo_potential)) THEN
585 cpassert(paw_atom)
586
587 NULLIFY (atom_list)
588 CALL get_atomic_kind(atomic_kind_set(ikind), atom_list=atom_list, natom=nat)
589
590 nsgf = cneo_potential%nsgf
591 npsgf = cneo_potential%npsgf
592 nsotot = cneo_potential%nsotot
593
594 DO iat = 1, nat
595 iatom = atom_list(iat)
596
597 ! density matrices, core and soft vmat will be broadcast to all processes
598 ALLOCATE (rhoz_cneo_set(iatom)%pmat(1:nsgf, 1:nsgf), &
599 rhoz_cneo_set(iatom)%cpc_h(1:npsgf, 1:npsgf), &
600 rhoz_cneo_set(iatom)%cpc_s(1:npsgf, 1:npsgf), &
601 rhoz_cneo_set(iatom)%core(1:nsgf, 1:nsgf), &
602 rhoz_cneo_set(iatom)%vmat(1:nsgf, 1:nsgf))
603 rhoz_cneo_set(iatom)%pmat = 0.0_dp
604 rhoz_cneo_set(iatom)%cpc_h = 0.0_dp
605 rhoz_cneo_set(iatom)%cpc_s = 0.0_dp
606 rhoz_cneo_set(iatom)%core = 0.0_dp
607 rhoz_cneo_set(iatom)%vmat = 0.0_dp
608 END DO
609
610 max_iso_not0 = cneo_potential%harmonics%max_iso_not0
611 num_pe = para_env%num_pe
612 mepos = para_env%mepos
613 bo = get_limit(nat, num_pe, mepos)
614 DO iat = bo(1), bo(2)
615 iatom = atom_list(iat)
616
617 ALLOCATE (rhoz_cneo_set(iatom)%fmat(1:nsgf, 1:nsgf), &
618 rhoz_cneo_set(iatom)%wfn(1:nsgf, 1:nsgf))
619 rhoz_cneo_set(iatom)%fmat = 0.0_dp
620 rhoz_cneo_set(iatom)%wfn = 0.0_dp
621
622 ALLOCATE (rhoz_cneo_set(iatom)%rho_rad_h(1:nr, 1:max_iso_not0), &
623 rhoz_cneo_set(iatom)%rho_rad_s(1:nr, 1:max_iso_not0), &
624 rhoz_cneo_set(iatom)%vrho_rad_h(1:nr, 1:max_iso_not0), &
625 rhoz_cneo_set(iatom)%vrho_rad_s(1:nr, 1:max_iso_not0))
626 rhoz_cneo_set(iatom)%rho_rad_h = 0.0_dp
627 rhoz_cneo_set(iatom)%rho_rad_s = 0.0_dp
628 rhoz_cneo_set(iatom)%vrho_rad_h = 0.0_dp
629 rhoz_cneo_set(iatom)%vrho_rad_s = 0.0_dp
630
631 NULLIFY (rhoz_cneo_set(iatom)%ga_Vlocal_gb_h)
632 CALL reallocate(rhoz_cneo_set(iatom)%ga_Vlocal_gb_h, 1, nsotot, 1, nsotot)
633 rhoz_cneo_set(iatom)%ga_Vlocal_gb_h = 0.0_dp
634 NULLIFY (rhoz_cneo_set(iatom)%ga_Vlocal_gb_s)
635 CALL reallocate(rhoz_cneo_set(iatom)%ga_Vlocal_gb_s, 1, nsotot, 1, nsotot)
636 rhoz_cneo_set(iatom)%ga_Vlocal_gb_s = 0.0_dp
637 END DO ! iat
638 END IF
639
640 END DO
641
642 CALL timestop(handle)
643
644 END SUBROUTINE allocate_rhoz_cneo_internals
645
646! **************************************************************************************************
647!> \brief ...
648!> \param qs_env ...
649!> \param calculate_forces ...
650!> \param nder ...
651! **************************************************************************************************
652 SUBROUTINE cneo_core_matrices(qs_env, calculate_forces, nder)
653 TYPE(qs_environment_type), POINTER :: qs_env
654 LOGICAL, INTENT(IN) :: calculate_forces
655 INTEGER, INTENT(IN) :: nder
656
657 LOGICAL :: use_virial
658 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
659 TYPE(distribution_1d_type), POINTER :: distribution_1d
660 TYPE(mp_para_env_type), POINTER :: para_env
661 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
662 POINTER :: sab_cneo
663 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
664 TYPE(qs_force_type), DIMENSION(:), POINTER :: force
665 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
666 TYPE(rhoz_cneo_type), DIMENSION(:), POINTER :: rhoz_cneo_set
667 TYPE(virial_type), POINTER :: virial
668
669 NULLIFY (rhoz_cneo_set)
670 CALL get_qs_env(qs_env=qs_env, rhoz_cneo_set=rhoz_cneo_set)
671
672 IF (ASSOCIATED(rhoz_cneo_set)) THEN
673 NULLIFY (force, virial)
674 ! force
675 IF (calculate_forces) CALL get_qs_env(qs_env=qs_env, force=force)
676 ! virial
677 CALL get_qs_env(qs_env=qs_env, virial=virial)
678 use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
679
680 NULLIFY (qs_kind_set, atomic_kind_set, particle_set, distribution_1d, para_env, sab_cneo)
681 CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set, atomic_kind_set=atomic_kind_set, &
682 particle_set=particle_set, local_particles=distribution_1d, &
683 para_env=para_env, sab_cneo=sab_cneo)
684 CALL build_core_cneo(rhoz_cneo_set, force, virial, calculate_forces, use_virial, nder, &
685 qs_kind_set, atomic_kind_set, particle_set, distribution_1d, &
686 sab_cneo, para_env)
687 END IF
688
689 END SUBROUTINE cneo_core_matrices
690
691! **************************************************************************************************
692!> \brief ...
693!> \param rhoz_cneo_set ...
694!> \param force ...
695!> \param virial ...
696!> \param calculate_forces ...
697!> \param use_virial ...
698!> \param nder ...
699!> \param qs_kind_set ...
700!> \param atomic_kind_set ...
701!> \param particle_set ...
702!> \param distribution_1d ...
703!> \param sab_cneo ...
704!> \param para_env ...
705! **************************************************************************************************
706 SUBROUTINE build_core_cneo(rhoz_cneo_set, force, virial, calculate_forces, use_virial, nder, &
707 qs_kind_set, atomic_kind_set, particle_set, distribution_1d, &
708 sab_cneo, para_env)
709 TYPE(rhoz_cneo_type), DIMENSION(:), POINTER :: rhoz_cneo_set
710 TYPE(qs_force_type), DIMENSION(:), POINTER :: force
711 TYPE(virial_type), POINTER :: virial
712 LOGICAL, INTENT(IN) :: calculate_forces, use_virial
713 INTEGER, INTENT(IN) :: nder
714 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
715 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
716 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
717 TYPE(distribution_1d_type), POINTER :: distribution_1d
718 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
719 POINTER :: sab_cneo
720 TYPE(mp_para_env_type), POINTER :: para_env
721
722 CHARACTER(LEN=*), PARAMETER :: routinen = 'build_core_cneo'
723
724 INTEGER :: atom_a, handle, iat, iatom, ikind, iset, jatom, jkind, jset, ldai, ldsab, maxco, &
725 maxl, maxnset, maxsgf, mepos, na_plus, nat, natom, nb_plus, ncoa, ncob, nij, nkind, nset, &
726 nthread, sgfa, sgfb
727 INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_of_kind, kind_of
728 INTEGER, DIMENSION(:), POINTER :: atom_list, lmax, lmin, npgf, nsgf
729 INTEGER, DIMENSION(:, :), POINTER :: first_sgf
730 REAL(kind=dp) :: alpha_c, core_charge, core_radius, dab, &
731 f0, rab2, zeta_i, zeta_j
732 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: ff
733 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: habd, work
734 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: hab, pab, verf, vnuc
735 REAL(kind=dp), DIMENSION(3) :: force_a, force_b, force_i, rab
736 REAL(kind=dp), DIMENSION(3, 3) :: pv_thread
738 DIMENSION(:), POINTER :: ap_iterator
739 TYPE(gto_basis_set_type), POINTER :: basis_set
740 TYPE(cneo_potential_type), POINTER :: cneo_potential, cneo_tmp
741 REAL(kind=dp), DIMENSION(:, :), POINTER :: core, pmat, rpgf, sphi, zet
742 REAL(kind=dp), DIMENSION(:), POINTER :: set_radius
743 REAL(kind=dp), DIMENSION(3, SIZE(particle_set)) :: force_thread
744
745 IF (calculate_forces) THEN
746 CALL timeset(routinen//"_forces", handle)
747 ELSE
748 CALL timeset(routinen, handle)
749 END IF
750
751 nkind = SIZE(atomic_kind_set)
752 natom = SIZE(particle_set)
753
754 force_thread = 0.0_dp
755 pv_thread = 0.0_dp
756
757 ! re-initialize core matrices to zero, as later will use para_env%sum to broadcast
758 DO ikind = 1, nkind
759 NULLIFY (cneo_potential)
760 CALL get_qs_kind(qs_kind_set(ikind), cneo_potential=cneo_potential)
761
762 IF (ASSOCIATED(cneo_potential)) THEN
763 NULLIFY (atom_list)
764 CALL get_atomic_kind(atomic_kind_set(ikind), atom_list=atom_list, natom=nat)
765 DO iat = 1, nat
766 iatom = atom_list(iat)
767 rhoz_cneo_set(iatom)%core = 0.0_dp
768 END DO
769 END IF
770 END DO
771
772 CALL get_qs_kind_set(qs_kind_set, basis_type="NUC", &
773 maxco=maxco, maxlgto=maxl, maxsgf=maxsgf, maxnset=maxnset)
774 CALL init_orbital_pointers(maxl + nder + 1)
775 ldsab = max(maxco, maxsgf)
776 ldai = ncoset(maxl + nder + 1)
777
778 nthread = 1
779!$ nthread = omp_get_max_threads()
780
781 CALL neighbor_list_iterator_create(ap_iterator, sab_cneo, search=.true., nthread=nthread)
782
783!$OMP PARALLEL &
784!$OMP DEFAULT (NONE) &
785!$OMP SHARED (rhoz_cneo_set, ap_iterator, distribution_1d, calculate_forces, use_virial, &
786!$OMP qs_kind_set, nthread, ncoset, nkind, iat, ldsab, maxnset, ldai, nder, maxl, &
787!$OMP maxco, para_env) &
788!$OMP PRIVATE (ikind, jkind, iatom, jatom, basis_set, first_sgf, lmax, lmin, npgf, nset, &
789!$OMP nsgf, rpgf, sphi, zet, set_radius, zeta_i, zeta_j, alpha_c, core_charge, &
790!$OMP core_radius, rab, rab2, dab, core, pmat, iset, ncoa, sgfa, jset, ncob, sgfb, &
791!$OMP work, pab, hab, na_plus, nb_plus, verf, vnuc, force_a, force_b, force_i, &
792!$OMP mepos, habd, f0, nij, ff, cneo_potential, cneo_tmp) &
793!$OMP REDUCTION (+ : pv_thread, force_thread )
794
795 mepos = 0
796!$ mepos = omp_get_thread_num()
797
798 ALLOCATE (hab(ldsab, ldsab, maxnset*(maxnset + 1)/2), work(ldsab, ldsab))
799 ALLOCATE (verf(ldai, ldai, 2*maxl + nder + 1), vnuc(ldai, ldai, 2*maxl + nder + 1), ff(0:2*maxl + nder))
800 IF (calculate_forces) THEN
801 ALLOCATE (pab(maxco, maxco, maxnset*(maxnset + 1)/2))
802 END IF
803
804 DO ikind = 1, nkind
805 NULLIFY (cneo_potential)
806 CALL get_qs_kind(qs_kind_set(ikind), basis_set=basis_set, basis_type="NUC", &
807 cneo_potential=cneo_potential, zeff=zeta_i)
808 IF (ASSOCIATED(cneo_potential)) THEN
809 cpassert(ASSOCIATED(basis_set))
810 first_sgf => basis_set%first_sgf
811 lmax => basis_set%lmax
812 lmin => basis_set%lmin
813 npgf => basis_set%npgf
814 nset = basis_set%nset
815 nsgf => basis_set%nsgf_set
816 rpgf => basis_set%pgf_radius
817 set_radius => basis_set%set_radius
818 sphi => basis_set%sphi
819 zet => basis_set%zet
820
821!$OMP DO SCHEDULE(GUIDED)
822 DO iat = 1, distribution_1d%n_el(ikind)
823 iatom = distribution_1d%list(ikind)%array(iat)
824 core => rhoz_cneo_set(iatom)%core
825 cpassert(ASSOCIATED(core))
826 core = cneo_potential%kin ! copy kinetic matrix to core
827 IF (calculate_forces) THEN
828 cpassert(rhoz_cneo_set(iatom)%ready)
829 pmat => rhoz_cneo_set(iatom)%pmat
830 cpassert(ASSOCIATED(pmat))
831 ! *** Decontract density matrix ***
832 DO iset = 1, nset
833 ncoa = npgf(iset)*ncoset(lmax(iset))
834 sgfa = first_sgf(1, iset)
835 DO jset = 1, iset
836 ncob = npgf(jset)*ncoset(lmax(jset))
837 sgfb = first_sgf(1, jset)
838 nij = jset + (iset - 1)*iset/2
839 work(1:ncoa, 1:nsgf(jset)) = matmul(sphi(1:ncoa, sgfa:sgfa + nsgf(iset) - 1), &
840 pmat(sgfa:sgfa + nsgf(iset) - 1, sgfb:sgfb + nsgf(jset) - 1))
841 pab(1:ncoa, 1:ncob, nij) = matmul(work(1:ncoa, 1:nsgf(jset)), &
842 transpose(sphi(1:ncob, sgfb:sgfb + nsgf(jset) - 1)))
843 END DO
844 END DO
845 END IF
846
847 hab = 0._dp
848 DO jkind = 1, nkind
849 NULLIFY (cneo_tmp)
850 CALL get_qs_kind(qs_kind_set(jkind), cneo_potential=cneo_tmp)
851 IF (.NOT. ASSOCIATED(cneo_tmp)) THEN
852 CALL get_qs_kind(qs_kind_set(jkind), &
853 alpha_core_charge=alpha_c, zeff=zeta_j, &
854 ccore_charge=core_charge, core_charge_radius=core_radius)
855 CALL nl_set_sub_iterator(ap_iterator, ikind, jkind, iatom, mepos=mepos)
856
857 DO WHILE (nl_sub_iterate(ap_iterator, mepos=mepos) == 0)
858 CALL get_iterator_info(ap_iterator, jatom=jatom, r=rab, mepos=mepos)
859 rab2 = sum(rab*rab)
860 dab = sqrt(rab2)
861 IF (maxval(set_radius(:)) + core_radius < dab) cycle
862 DO iset = 1, nset
863 IF (set_radius(iset) + core_radius < dab) cycle
864 ncoa = npgf(iset)*ncoset(lmax(iset))
865 sgfa = first_sgf(1, iset)
866 DO jset = 1, iset ! symmetric
867 IF (set_radius(jset) + core_radius < dab) cycle
868 ncob = npgf(jset)*ncoset(lmax(jset))
869 sgfb = first_sgf(1, jset)
870 nij = jset + (iset - 1)*iset/2
871 IF (calculate_forces) THEN
872 IF (jset == iset) THEN
873 f0 = -zeta_i
874 ELSE
875 f0 = -2.0_dp*zeta_i
876 END IF
877 na_plus = npgf(iset)*ncoset(lmax(iset) + nder)
878 nb_plus = npgf(jset)*ncoset(lmax(jset))
879 ALLOCATE (habd(na_plus, nb_plus))
880 habd = 0._dp
881 CALL verfc( &
882 lmax(iset) + nder, npgf(iset), zet(:, iset), rpgf(:, iset), lmin(iset), &
883 lmax(jset), npgf(jset), zet(:, jset), rpgf(:, jset), lmin(jset), &
884 alpha_c, core_radius, zeta_j, core_charge, &
885 (/0.0_dp, 0.0_dp, 0.0_dp/), 0.0_dp, rab, rab2, rab2, &
886 hab(:, :, nij), verf, vnuc, ff(0:), nder, habd)
887
888 ! *** The derivatives w.r.t. atomic center b are ***
889 ! *** calculated using the translational invariance ***
890 ! *** of the first derivatives ***
891 CALL verfc_force(habd, pab(:, :, nij), force_a, force_b, nder, &
892 lmax(iset), lmin(iset), npgf(iset), zet(:, iset), &
893 lmax(jset), lmin(jset), npgf(jset), zet(:, jset), &
894 (/0.0_dp, 0.0_dp, 0.0_dp/))
895
896 DEALLOCATE (habd)
897 force_i = force_a + force_b
898
899 force_thread(1, iatom) = force_thread(1, iatom) + f0*force_i(1)
900 force_thread(2, iatom) = force_thread(2, iatom) + f0*force_i(2)
901 force_thread(3, iatom) = force_thread(3, iatom) + f0*force_i(3)
902
903 force_thread(1, jatom) = force_thread(1, jatom) - f0*force_i(1)
904 force_thread(2, jatom) = force_thread(2, jatom) - f0*force_i(2)
905 force_thread(3, jatom) = force_thread(3, jatom) - f0*force_i(3)
906
907 IF (use_virial) THEN
908 CALL virial_pair_force(pv_thread, f0, force_i, rab)
909 END IF
910 ELSE
911 CALL verfc( &
912 lmax(iset), npgf(iset), zet(:, iset), rpgf(:, iset), lmin(iset), &
913 lmax(jset), npgf(jset), zet(:, jset), rpgf(:, jset), lmin(jset), &
914 alpha_c, core_radius, zeta_j, core_charge, &
915 (/0.0_dp, 0.0_dp, 0.0_dp/), 0.0_dp, rab, rab2, rab2, &
916 hab(:, :, nij), verf, vnuc, ff(0:))
917 END IF
918 END DO
919 END DO
920 END DO
921 END IF
922 END DO
923 ! *** Contract nuclear repulsion integrals
924 DO iset = 1, nset
925 ncoa = npgf(iset)*ncoset(lmax(iset))
926 sgfa = first_sgf(1, iset)
927 DO jset = 1, iset
928 ncob = npgf(jset)*ncoset(lmax(jset))
929 sgfb = first_sgf(1, jset)
930 nij = jset + (iset - 1)*iset/2
931 work(1:ncoa, 1:nsgf(jset)) = matmul(hab(1:ncoa, 1:ncob, nij), &
932 sphi(1:ncob, sgfb:sgfb + nsgf(jset) - 1))
933 core(sgfa:sgfa + nsgf(iset) - 1, sgfb:sgfb + nsgf(jset) - 1) = &
934 core(sgfa:sgfa + nsgf(iset) - 1, sgfb:sgfb + nsgf(jset) - 1) - zeta_i* &
935 matmul(transpose(sphi(1:ncoa, sgfa:sgfa + nsgf(iset) - 1)), work(1:ncoa, 1:nsgf(jset)))
936 ! symmetrize core matrix
937 IF (iset /= jset) THEN
938 core(sgfb:sgfb + nsgf(jset) - 1, sgfa:sgfa + nsgf(iset) - 1) = &
939 transpose(core(sgfa:sgfa + nsgf(iset) - 1, sgfb:sgfb + nsgf(jset) - 1))
940 END IF
941 END DO
942 END DO
943 END DO
944 END IF
945 END DO
946
947 DEALLOCATE (hab, work, verf, vnuc, ff)
948 IF (calculate_forces) THEN
949 DEALLOCATE (pab)
950 END IF
951
952!$OMP END PARALLEL
953
954 CALL neighbor_list_iterator_release(ap_iterator)
955
956 IF (calculate_forces) THEN
957 CALL get_atomic_kind_set(atomic_kind_set, atom_of_kind=atom_of_kind, &
958 kind_of=kind_of)
959!$OMP DO
960 DO iatom = 1, natom
961 atom_a = atom_of_kind(iatom)
962 ikind = kind_of(iatom)
963 force(ikind)%cneo_potential(:, atom_a) = force(ikind)%cneo_potential(:, atom_a) + &
964 force_thread(:, iatom)
965 END DO
966!$OMP END DO
967 END IF
968
969 IF (calculate_forces .AND. use_virial) THEN
970 virial%pv_ppl = virial%pv_ppl + pv_thread
971 virial%pv_virial = virial%pv_virial + pv_thread
972 END IF
973
974 ! broadcast core matrices
975 DO ikind = 1, nkind
976 NULLIFY (cneo_potential)
977 CALL get_qs_kind(qs_kind_set(ikind), cneo_potential=cneo_potential)
978
979 IF (ASSOCIATED(cneo_potential)) THEN
980 NULLIFY (atom_list)
981 CALL get_atomic_kind(atomic_kind_set(ikind), atom_list=atom_list, natom=nat)
982 DO iat = 1, nat
983 iatom = atom_list(iat)
984 CALL para_env%sum(rhoz_cneo_set(iatom)%core)
985 END DO
986 END IF
987 END DO
988
989 CALL timestop(handle)
990
991 END SUBROUTINE build_core_cneo
992
993! **************************************************************************************************
994!> \brief ...
995!> \param rho ...
996!> \param potential ...
997!> \param cg_list ...
998!> \param cg_n_list ...
999!> \param nset ...
1000!> \param npgf ...
1001!> \param lmin ...
1002!> \param lmax ...
1003!> \param maxl ...
1004!> \param maxso ...
1005! **************************************************************************************************
1006 SUBROUTINE calculate_rhoz_cneo(rho, potential, cg_list, cg_n_list, nset, npgf, &
1007 lmin, lmax, maxl, maxso)
1008
1009 TYPE(rhoz_cneo_type), POINTER :: rho
1010 TYPE(cneo_potential_type), POINTER :: potential
1011 INTEGER, DIMENSION(:, :, :), INTENT(INOUT) :: cg_list
1012 INTEGER, DIMENSION(:), INTENT(INOUT) :: cg_n_list
1013 INTEGER, INTENT(IN) :: nset
1014 INTEGER, DIMENSION(:), POINTER :: npgf, lmin, lmax
1015 INTEGER, INTENT(IN) :: maxl, maxso
1016
1017 CHARACTER(len=*), PARAMETER :: routinen = 'calculate_rhoz_cneo'
1018
1019 INTEGER :: handle, i, i1, i2, icg, ipgf1, ipgf2, iset1, iset2, iso, iso1, iso1_first, &
1020 iso1_last, iso2, iso2_first, iso2_last, iter, j, l, l1, l2, l_iso, lmax_expansion, m1s, &
1021 m2s, max_iso_not0, max_iso_not0_local, max_iter, max_s_harm, n1s, n2s, nne, npgf2, npsgf, &
1022 nsgf, nsotot, size1, size2
1023 INTEGER, DIMENSION(:), POINTER :: n2oindex, o2nindex
1024 REAL(kind=dp) :: det, df_norm, factor, g0, g0p, g1, step, &
1025 zeff
1026 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: ener
1027 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: cpch_sphere, cpcs_sphere, work
1028 REAL(kind=dp), DIMENSION(3) :: df, f_tmp, r, r_tmp
1029 REAL(kind=dp), DIMENSION(3, 3) :: jac, jac_inv
1030 REAL(kind=dp), DIMENSION(:), POINTER :: f
1031 REAL(kind=dp), DIMENSION(:, :), POINTER :: core, cpc_h, cpc_s, fmat, int_local_h, &
1032 int_local_s, my_gcc_h, my_gcc_s, pmat, rho_rad_h, rho_rad_s, utrans, vmat, vrho_rad_h, &
1033 vrho_rad_s, wfn
1034 REAL(kind=dp), DIMENSION(:, :, :), POINTER :: distance, gg, my_cg
1035 REAL(kind=dp), DIMENSION(:, :, :, :), POINTER :: vgg
1036 TYPE(harmonics_atom_type), POINTER :: harmonics
1037
1038 cpassert(ASSOCIATED(rho))
1039 cpassert(ASSOCIATED(potential))
1040
1041 CALL timeset(routinen, handle)
1042
1043 ! convert ga_Vlocal_gb to compressed form V_Hartree
1044 ! use fmat to store V_Hartree
1045 NULLIFY (utrans, my_gcc_h, my_gcc_s, distance, n2oindex, o2nindex)
1046 CALL get_cneo_potential(potential, zeff=zeff, nsgf=nsgf, nne=nne, npsgf=npsgf, &
1047 nsotot=nsotot, my_gcc_h=my_gcc_h, my_gcc_s=my_gcc_s, &
1048 utrans=utrans, distance=distance, n2oindex=n2oindex, &
1049 o2nindex=o2nindex)
1050 fmat => rho%fmat
1051 int_local_h => rho%ga_Vlocal_gb_h
1052 int_local_s => rho%ga_Vlocal_gb_s
1053 ALLOCATE (work(nsotot, nsgf))
1054 CALL dgemm("N", "N", nsotot, nsgf, nsotot, 1.0_dp, int_local_h, nsotot, my_gcc_h, &
1055 nsotot, 0.0_dp, work, nsotot)
1056 CALL dgemm("T", "N", nsgf, nsgf, nsotot, 1.0_dp, my_gcc_h, nsotot, work, &
1057 nsotot, 0.0_dp, fmat, nsgf)
1058 CALL dgemm("N", "N", nsotot, nsgf, nsotot, 1.0_dp, int_local_s, nsotot, my_gcc_s, &
1059 nsotot, 0.0_dp, work, nsotot)
1060 CALL dgemm("T", "N", nsgf, nsgf, nsotot, -1.0_dp, my_gcc_s, nsotot, work, &
1061 nsotot, 1.0_dp, fmat, nsgf)
1062 ! add the soft basis FFT grid part
1063 vmat => rho%vmat
1064 fmat = fmat + vmat
1065
1066 core => rho%core
1067 wfn => rho%wfn
1068 pmat => rho%pmat
1069 f => rho%f
1070 ALLOCATE (ener(nne))
1071 ! build the fock matrix: F = T + V_core + V_Hartree
1072 fmat = fmat + core
1073 ! conduct the constrained optimization with F + f*x
1074 ! initial guess of f is taken from the result of last iteration
1075 CALL atom_solve_cneo(fmat, f, utrans, wfn, ener, pmat, r, distance, nsgf, nne)
1076 ! test if zero initial guess is better
1077 IF (sqrt(dot_product(r, r)) > 1.e-12_dp .AND. dot_product(f, f) /= 0.0_dp) THEN
1078 CALL atom_solve_cneo(fmat, (/0.0_dp, 0.0_dp, 0.0_dp/), utrans, wfn, &
1079 ener, pmat, r_tmp, distance, nsgf, nne)
1080 IF (dot_product(r_tmp, r_tmp) < dot_product(r, r)) THEN
1081 f = 0.0_dp
1082 r = r_tmp
1083 END IF
1084 END IF
1085 max_iter = 20
1086 iter = 0
1087 ! using Newton's method to solve for f
1088 DO WHILE (sqrt(dot_product(r, r)) > 1.e-12_dp)
1089 iter = iter + 1
1090 ! construct numerical Jacobian with one-side finite difference
1091 DO i = 1, 3
1092 f_tmp = f
1093 f_tmp(i) = f(i) + sign(1.e-4_dp, r(i)) ! forward or backward based on the sign of r
1094 CALL atom_solve_cneo(fmat, f_tmp, utrans, wfn, ener, pmat, r_tmp, distance, nsgf, nne)
1095 DO j = 1, 3
1096 jac(j, i) = (r_tmp(j) - r(j))*sign(1.e4_dp, r(i))
1097 END DO
1098 END DO
1099 CALL invert_matrix_3x3(jac, jac_inv, det)
1100 IF (abs(det) < 1.0e-8_dp) THEN
1101 CALL cp_warn(__location__, "Determinant of the CNEO position Jacobian is small! "// &
1102 trim(cp_to_string(det))//" Trying central difference.")
1103 ! construct numerical Jacobian with central finite difference
1104 DO i = 1, 3
1105 f_tmp = f
1106 f_tmp(i) = f(i) - sign(1.e-4_dp, r(i))
1107 CALL atom_solve_cneo(fmat, f_tmp, utrans, wfn, ener, pmat, r_tmp, distance, nsgf, nne)
1108 DO j = 1, 3
1109 jac(j, i) = (jac(j, i)*sign(1.e-4_dp, r(i)) + r(j) - r_tmp(j)) &
1110 /sign(2.e-4_dp, r(i))
1111 END DO
1112 END DO
1113 CALL invert_matrix_3x3(jac, jac_inv, det)
1114 IF (abs(det) < 1.0e-8_dp) THEN
1115 CALL cp_warn(__location__, "Determinant of the CNEO position Jacobian is small! "// &
1116 "(Central difference) "//trim(cp_to_string(det))//" Using pseudoinverse.")
1117 END IF
1118 CALL invert_matrix_3x3(jac, jac_inv, det, try_svd=.true.)
1119 END IF
1120 df = -reshape(matmul(jac_inv, reshape(r, (/3, 1/))), (/3/))
1121 df_norm = sqrt(dot_product(df, df))
1122 f_tmp = f
1123 r_tmp = r
1124 g0 = sqrt(dot_product(r_tmp, r_tmp))
1125 f = f_tmp + df
1126 CALL atom_solve_cneo(fmat, f, utrans, wfn, ener, pmat, r, distance, nsgf, nne)
1127 g1 = sqrt(dot_product(r, r))
1128 step = 1.0_dp
1129 DO WHILE (g1 >= g0)
1130 ! line search
1131 IF (step < 0.0101_dp) THEN
1132 cpwarn("CNEO nuclear position constraint solver line search failure.")
1133 EXIT
1134 END IF
1135 g0p = -g0/(step*df_norm)
1136 step = step*max(-g0p/(2.0_dp*(g1 - g0 - g0p)), 0.1_dp)
1137 f = f_tmp + step*df
1138 CALL atom_solve_cneo(fmat, f, utrans, wfn, ener, pmat, r, distance, nsgf, nne)
1139 g1 = sqrt(dot_product(r, r))
1140 END DO
1141 IF (iter >= max_iter) THEN
1142 CALL cp_warn(__location__, "CNEO nuclear position constraint solver failed to "// &
1143 "converge in "//trim(cp_to_string(max_iter))//" steps. "// &
1144 "Nuclear position error (x,y,z): "//trim(cp_to_string(r(1)))// &
1145 ", "//trim(cp_to_string(r(2)))//", "//trim(cp_to_string(r(3)))// &
1146 ". This does not hurt as long as it is not the final SCF iteration.")
1147 EXIT
1148 END IF
1149 END DO
1150 DEALLOCATE (ener)
1151 rho%e_core = trace_r_axb(core, nsgf, pmat, nsgf, nsgf, nsgf)
1152
1153 ! decontract the density matrix
1154 ! first use ga_Vlocal_gb to store the decompressed form
1155 CALL dgemm("N", "N", nsotot, nsgf, nsgf, 1.0_dp, my_gcc_h, nsotot, pmat, nsgf, &
1156 0.0_dp, work, nsotot)
1157 CALL dgemm("N", "T", nsotot, nsotot, nsgf, 1.0_dp, work, nsotot, my_gcc_h, nsotot, &
1158 0.0_dp, int_local_h, nsotot)
1159 CALL dgemm("N", "N", nsotot, nsgf, nsgf, 1.0_dp, my_gcc_s, nsotot, pmat, nsgf, &
1160 0.0_dp, work, nsotot)
1161 CALL dgemm("N", "T", nsotot, nsotot, nsgf, 1.0_dp, work, nsotot, my_gcc_s, nsotot, &
1162 0.0_dp, int_local_s, nsotot)
1163 DEALLOCATE (work)
1164 ! compress the density matrix
1165 cpc_h => rho%cpc_h
1166 cpc_s => rho%cpc_s
1167 CALL cneo_gather(int_local_h, cpc_h, npsgf, n2oindex)
1168 CALL cneo_gather(int_local_s, cpc_s, npsgf, n2oindex)
1169 ! restore ga_Vlocal_gb to zeros
1170 int_local_h = 0.0_dp
1171 int_local_s = 0.0_dp
1172
1173 ! construct the nuclear density and its Hartree potential
1174 ! rho_rad_h and vrho_rad_h should contain the -Zeff factor
1175 ! mostly copied from qs_rho_atom_methods::calculate_rho_atom
1176 NULLIFY (harmonics, gg, vgg)
1177 CALL get_cneo_potential(potential, harmonics=harmonics, gg=gg, vgg=vgg)
1178 rho_rad_h => rho%rho_rad_h
1179 rho_rad_s => rho%rho_rad_s
1180 rho_rad_h = 0.0_dp
1181 rho_rad_s = 0.0_dp
1182 vrho_rad_h => rho%vrho_rad_h
1183 vrho_rad_s => rho%vrho_rad_s
1184 vrho_rad_h = 0.0_dp
1185 vrho_rad_s = 0.0_dp
1186 my_cg => harmonics%my_CG
1187 max_iso_not0 = harmonics%max_iso_not0
1188 max_s_harm = harmonics%max_s_harm
1189 lmax_expansion = indso(1, max_iso_not0)
1190
1191 ALLOCATE (cpch_sphere(nsoset(maxl), nsoset(maxl)))
1192 ALLOCATE (cpcs_sphere(nsoset(maxl), nsoset(maxl)))
1193 j = 0
1194 m1s = 0
1195 DO iset1 = 1, nset
1196 m2s = 0
1197 n1s = nsoset(lmax(iset1))
1198 DO iset2 = 1, iset1
1199
1200 CALL get_none0_cg_list(my_cg, lmin(iset1), lmax(iset1), lmin(iset2), lmax(iset2), &
1201 max_s_harm, lmax_expansion, cg_list, cg_n_list, max_iso_not0_local)
1202 cpassert(max_iso_not0_local .LE. max_iso_not0)
1203
1204 n2s = nsoset(lmax(iset2))
1205 DO ipgf1 = 1, npgf(iset1)
1206 iso1_first = nsoset(lmin(iset1) - 1) + 1 + n1s*(ipgf1 - 1) + m1s
1207 iso1_last = nsoset(lmax(iset1)) + n1s*(ipgf1 - 1) + m1s
1208 size1 = iso1_last - iso1_first + 1
1209 iso1_first = o2nindex(iso1_first)
1210 iso1_last = o2nindex(iso1_last)
1211 i1 = iso1_last - iso1_first + 1
1212 cpassert(size1 == i1)
1213 i1 = nsoset(lmin(iset1) - 1) + 1
1214
1215 IF (iset2 == iset1) THEN
1216 npgf2 = ipgf1
1217 ELSE
1218 npgf2 = npgf(iset2)
1219 END IF
1220 DO ipgf2 = 1, npgf2
1221 j = j + 1
1222 iso2_first = nsoset(lmin(iset2) - 1) + 1 + n2s*(ipgf2 - 1) + m2s
1223 iso2_last = nsoset(lmax(iset2)) + n2s*(ipgf2 - 1) + m2s
1224 size2 = iso2_last - iso2_first + 1
1225 iso2_first = o2nindex(iso2_first)
1226 iso2_last = o2nindex(iso2_last)
1227 i2 = iso2_last - iso2_first + 1
1228 cpassert(size2 == i2)
1229 i2 = nsoset(lmin(iset2) - 1) + 1
1230
1231 IF (iset2 == iset1 .AND. ipgf2 == ipgf1) THEN
1232 factor = -zeff
1233 ELSE
1234 factor = -2.0_dp*zeff
1235 END IF
1236
1237 cpch_sphere = 0.0_dp
1238 cpcs_sphere = 0.0_dp
1239 cpch_sphere(i1:i1 + size1 - 1, i2:i2 + size2 - 1) = cpc_h(iso1_first:iso1_last, iso2_first:iso2_last)
1240 cpcs_sphere(i1:i1 + size1 - 1, i2:i2 + size2 - 1) = cpc_s(iso1_first:iso1_last, iso2_first:iso2_last)
1241 DO iso = 1, max_iso_not0_local
1242 l_iso = indso(1, iso)
1243 DO icg = 1, cg_n_list(iso)
1244 iso1 = cg_list(1, icg, iso)
1245 iso2 = cg_list(2, icg, iso)
1246
1247 l1 = indso(1, iso1)
1248 l2 = indso(1, iso2)
1249
1250 l = indso(1, iso1) + indso(1, iso2)
1251 cpassert(l <= lmax_expansion)
1252
1253 rho_rad_h(:, iso) = rho_rad_h(:, iso) + gg(:, l, j)* &
1254 cpch_sphere(iso1, iso2)*my_cg(iso1, iso2, iso)*factor
1255
1256 rho_rad_s(:, iso) = rho_rad_s(:, iso) + gg(:, l, j)* &
1257 cpcs_sphere(iso1, iso2)*my_cg(iso1, iso2, iso)*factor
1258
1259 vrho_rad_h(:, iso) = vrho_rad_h(:, iso) + vgg(:, l, l_iso, j)* &
1260 cpch_sphere(iso1, iso2)*my_cg(iso1, iso2, iso)*factor
1261
1262 vrho_rad_s(:, iso) = vrho_rad_s(:, iso) + vgg(:, l, l_iso, j)* &
1263 cpcs_sphere(iso1, iso2)*my_cg(iso1, iso2, iso)*factor
1264 END DO ! icg
1265 END DO ! iso
1266 END DO ! ipgf2
1267 END DO ! ipgf1
1268 m2s = m2s + maxso
1269 END DO ! iset2
1270 m1s = m1s + maxso
1271 END DO ! iset1
1272 DEALLOCATE (cpch_sphere, cpcs_sphere)
1273
1274 CALL timestop(handle)
1275
1276 END SUBROUTINE calculate_rhoz_cneo
1277
1278! **************************************************************************************************
1279!> \brief Mostly copied from hartree_local_methods::Vh_1c_atom_integrals
1280!> \param rhoz_cneo ...
1281!> \param zeff ...
1282!> \param aVh1b_hh ...
1283!> \param aVh1b_ss ...
1284!> \param aVh1b_00 ...
1285!> \param Vh1_h ...
1286!> \param Vh1_s ...
1287!> \param max_iso_not0_elec ...
1288!> \param max_iso_not0_nuc ...
1289!> \param max_s_harm ...
1290!> \param llmax ...
1291!> \param cg_list ...
1292!> \param cg_n_list ...
1293!> \param nset ...
1294!> \param npgf ...
1295!> \param lmin ...
1296!> \param lmax ...
1297!> \param nsotot ...
1298!> \param maxso ...
1299!> \param nchan_0 ...
1300!> \param gsph ...
1301!> \param g0_h_w ...
1302!> \param my_CG ...
1303!> \param Qlm_gg ...
1304! **************************************************************************************************
1305 SUBROUTINE vh_1c_nuc_integrals(rhoz_cneo, zeff, &
1306 aVh1b_hh, aVh1b_ss, aVh1b_00, Vh1_h, Vh1_s, &
1307 max_iso_not0_elec, max_iso_not0_nuc, &
1308 max_s_harm, llmax, cg_list, cg_n_list, &
1309 nset, npgf, lmin, lmax, nsotot, maxso, nchan_0, gsph, &
1310 g0_h_w, my_CG, Qlm_gg)
1311
1312 TYPE(rhoz_cneo_type), POINTER :: rhoz_cneo
1313 REAL(kind=dp), INTENT(IN) :: zeff
1314 REAL(kind=dp), DIMENSION(:, :) :: avh1b_hh, avh1b_ss, avh1b_00
1315 REAL(kind=dp), DIMENSION(:, :), POINTER :: vh1_h, vh1_s
1316 INTEGER, INTENT(IN) :: max_iso_not0_elec, max_iso_not0_nuc, &
1317 max_s_harm, llmax
1318 INTEGER, DIMENSION(:, :, :) :: cg_list
1319 INTEGER, DIMENSION(:) :: cg_n_list
1320 INTEGER, INTENT(IN) :: nset
1321 INTEGER, DIMENSION(:), POINTER :: npgf, lmin, lmax
1322 INTEGER, INTENT(IN) :: nsotot, maxso, nchan_0
1323 REAL(kind=dp), DIMENSION(:, :), POINTER :: gsph
1324 REAL(kind=dp), DIMENSION(:, 0:) :: g0_h_w
1325 REAL(kind=dp), DIMENSION(:, :, :), POINTER :: my_cg, qlm_gg
1326
1327 INTEGER :: icg, ipgf1, ipgf2, ir, is1, is2, iset1, &
1328 iset2, iso, iso1, iso2, l_ang, m1, m2, &
1329 max_iso_not0_local, n1, n2, nr
1330 REAL(kind=dp) :: gvg_0, gvg_h, gvg_s
1331
1332 ! Calculate the integrals of the potential with 2 primitives
1333 avh1b_hh = 0.0_dp
1334 avh1b_ss = 0.0_dp
1335 avh1b_00 = 0.0_dp
1336
1337 nr = SIZE(gsph, 1)
1338
1339 m1 = 0
1340 DO iset1 = 1, nset
1341 n1 = nsoset(lmax(iset1))
1342 m2 = 0
1343 DO iset2 = 1, nset
1344 CALL get_none0_cg_list(my_cg, lmin(iset1), lmax(iset1), lmin(iset2), lmax(iset2), &
1345 max_s_harm, llmax, cg_list, cg_n_list, max_iso_not0_local)
1346
1347 n2 = nsoset(lmax(iset2))
1348 DO ipgf1 = 1, npgf(iset1)
1349 DO ipgf2 = 1, npgf(iset2)
1350 DO iso = 1, min(max_iso_not0_elec, max_iso_not0_nuc)
1351 DO icg = 1, cg_n_list(iso)
1352 is1 = cg_list(1, icg, iso)
1353 is2 = cg_list(2, icg, iso)
1354
1355 iso1 = is1 + n1*(ipgf1 - 1) + m1
1356 iso2 = is2 + n2*(ipgf2 - 1) + m2
1357 gvg_h = 0.0_dp
1358 gvg_s = 0.0_dp
1359
1360 DO ir = 1, nr
1361 gvg_h = gvg_h + gsph(ir, iso1)*gsph(ir, iso2)*vh1_h(ir, iso)
1362 gvg_s = gvg_s + gsph(ir, iso1)*gsph(ir, iso2)*vh1_s(ir, iso)
1363 END DO ! ir
1364
1365 avh1b_hh(iso1, iso2) = avh1b_hh(iso1, iso2) + gvg_h*my_cg(is1, is2, iso)
1366 avh1b_ss(iso1, iso2) = avh1b_ss(iso1, iso2) + gvg_s*my_cg(is1, is2, iso)
1367
1368 END DO !icg
1369 END DO ! iso
1370 DO iso = max_iso_not0_elec + 1, max_iso_not0_nuc
1371 DO icg = 1, cg_n_list(iso)
1372 is1 = cg_list(1, icg, iso)
1373 is2 = cg_list(2, icg, iso)
1374
1375 iso1 = is1 + n1*(ipgf1 - 1) + m1
1376 iso2 = is2 + n2*(ipgf2 - 1) + m2
1377 gvg_s = 0.0_dp
1378
1379 DO ir = 1, nr
1380 gvg_s = gvg_s + gsph(ir, iso1)*gsph(ir, iso2)*vh1_s(ir, iso)
1381 END DO ! ir
1382
1383 avh1b_ss(iso1, iso2) = avh1b_ss(iso1, iso2) + gvg_s*my_cg(is1, is2, iso)
1384
1385 END DO !icg
1386 END DO ! iso
1387 DO iso = 1, min(nchan_0, max_iso_not0_nuc)
1388 l_ang = indso(1, iso)
1389 gvg_0 = sum(vh1_s(:, iso)*g0_h_w(:, l_ang))
1390 DO icg = 1, cg_n_list(iso)
1391 is1 = cg_list(1, icg, iso)
1392 is2 = cg_list(2, icg, iso)
1393
1394 iso1 = is1 + n1*(ipgf1 - 1) + m1
1395 iso2 = is2 + n2*(ipgf2 - 1) + m2
1396
1397 avh1b_00(iso1, iso2) = avh1b_00(iso1, iso2) + gvg_0*qlm_gg(iso1, iso2, iso)
1398
1399 END DO !icg
1400 END DO ! iso
1401 END DO ! ipgf2
1402 END DO ! ipgf1
1403 m2 = m2 + maxso
1404 END DO ! iset2
1405 m1 = m1 + maxso
1406 END DO !iset1
1407
1408 CALL daxpy(nsotot*nsotot, -zeff, avh1b_hh, 1, rhoz_cneo%ga_Vlocal_gb_h, 1)
1409 CALL daxpy(nsotot*nsotot, -zeff, avh1b_ss, 1, rhoz_cneo%ga_Vlocal_gb_s, 1)
1410 CALL daxpy(nsotot*nsotot, zeff, avh1b_00, 1, rhoz_cneo%ga_Vlocal_gb_h, 1)
1411 CALL daxpy(nsotot*nsotot, zeff, avh1b_00, 1, rhoz_cneo%ga_Vlocal_gb_s, 1)
1412
1413 END SUBROUTINE vh_1c_nuc_integrals
1414
1415! **************************************************************************************************
1416!> \brief Analytical inversion of a 3x3 matrix
1417!> \param matrix ...
1418!> \param inv_matrix ...
1419!> \param det ...
1420!> \param try_svd ...
1421! **************************************************************************************************
1422 SUBROUTINE invert_matrix_3x3(matrix, inv_matrix, det, try_svd)
1423 REAL(kind=dp), DIMENSION(3, 3), INTENT(IN) :: matrix
1424 REAL(kind=dp), DIMENSION(3, 3), INTENT(OUT) :: inv_matrix
1425 REAL(kind=dp), INTENT(OUT) :: det
1426 LOGICAL, INTENT(IN), OPTIONAL :: try_svd
1427
1428 LOGICAL :: my_try_svd
1429
1430 my_try_svd = .false.
1431 IF (PRESENT(try_svd)) my_try_svd = try_svd
1432
1433 det = matrix(1, 1)*(matrix(2, 2)*matrix(3, 3) - matrix(2, 3)*matrix(3, 2)) &
1434 - matrix(1, 2)*(matrix(2, 1)*matrix(3, 3) - matrix(2, 3)*matrix(3, 1)) &
1435 + matrix(1, 3)*(matrix(2, 1)*matrix(3, 2) - matrix(2, 2)*matrix(3, 1))
1436 IF (abs(det) < 1.0e-8_dp) THEN
1437 IF (my_try_svd) THEN
1438 ! pseudo inverse using SVD
1439 CALL get_pseudo_inverse_svd(matrix, inv_matrix, 1.0e-6_dp, det)
1440 ELSE
1441 inv_matrix = 0.0_dp
1442 END IF
1443 ELSE
1444 inv_matrix(1, 1) = matrix(2, 2)*matrix(3, 3) - matrix(2, 3)*matrix(3, 2)
1445 inv_matrix(1, 2) = matrix(1, 3)*matrix(3, 2) - matrix(1, 2)*matrix(3, 3)
1446 inv_matrix(1, 3) = matrix(1, 2)*matrix(2, 3) - matrix(1, 3)*matrix(2, 2)
1447 inv_matrix(2, 1) = matrix(2, 3)*matrix(3, 1) - matrix(2, 1)*matrix(3, 3)
1448 inv_matrix(2, 2) = matrix(1, 1)*matrix(3, 3) - matrix(1, 3)*matrix(3, 1)
1449 inv_matrix(2, 3) = matrix(1, 3)*matrix(2, 1) - matrix(1, 1)*matrix(2, 3)
1450 inv_matrix(3, 1) = matrix(2, 1)*matrix(3, 2) - matrix(2, 2)*matrix(3, 1)
1451 inv_matrix(3, 2) = matrix(1, 2)*matrix(3, 1) - matrix(1, 1)*matrix(3, 2)
1452 inv_matrix(3, 3) = matrix(1, 1)*matrix(2, 2) - matrix(1, 2)*matrix(2, 1)
1453 inv_matrix = inv_matrix/det
1454 END IF
1455 END SUBROUTINE invert_matrix_3x3
1456
1457END MODULE qs_cneo_methods
static void dgemm(const char transa, const char transb, const int m, const int n, const int k, const double alpha, const double *a, const int lda, const double *b, const int ldb, const double beta, double *c, const int ldc)
Convenient wrapper to hide Fortran nature of dgemm_, swapping a and b.
Build up the nuclear potential part of the core Hamiltonian matrix in the case of an allelectron calc...
Definition ai_verfc.F:82
subroutine, public verfc(la_max1, npgfa, zeta, rpgfa, la_min1, lb_max1, npgfb, zetb, rpgfb, lb_min1, zetc, rpgfc, zc, cerf, rab, rab2, rac, rac2, rbc2, vabc, verf, vnuc, f, maxder, vabc_plus, vnabc, pvp_sum, pvp, dkh_erfc)
Calculation of the primitive three-center nuclear potential integrals <a|Z*erfc(r)/r|b> over Cartesia...
Definition ai_verfc.F:141
All kind of helpful little routines.
Definition ao_util.F:14
pure real(dp) function, public trace_r_axb(a, lda, b, ldb, m, n)
...
Definition ao_util.F:331
Calculate the atomic operator matrices.
subroutine, public atom_int_setup(integrals, basis, potential, eri_coulomb, eri_exchange, all_nu)
Set up atomic integrals.
subroutine, public atom_int_release(integrals)
Release memory allocated for atomic integrals (valence electrons).
Define the atom type and its sub types.
Definition atom_types.F:15
integer, parameter, public cgto_basis
Definition atom_types.F:69
integer, parameter, public lmat
Definition atom_types.F:67
subroutine, public release_atom_basis(basis)
...
Definition atom_types.F:913
Define the atomic kind types and their sub types.
subroutine, public get_atomic_kind_set(atomic_kind_set, atom_of_kind, kind_of, natom_of_kind, maxatom, natom, nshell, fist_potential_present, shell_present, shell_adiabatic, shell_check_distance, damping_present)
Get attributes of an atomic kind set.
subroutine, public get_atomic_kind(atomic_kind, fist_potential, element_symbol, name, mass, kind_number, natom, atom_list, rcov, rvdw, z, qeff, apol, cpol, mm_radius, shell, shell_active, damping)
Get attributes of an atomic kind.
subroutine, public get_gto_basis_set(gto_basis_set, name, aliases, norm_type, kind_radius, ncgf, nset, nsgf, cgf_symbol, sgf_symbol, norm_cgf, set_radius, lmax, lmin, lx, ly, lz, m, ncgf_set, npgf, nsgf_set, nshell, cphi, pgf_radius, sphi, scon, zet, first_cgf, first_sgf, l, last_cgf, last_sgf, n, gcc, maxco, maxl, maxpgf, maxsgf_set, maxshell, maxso, nco_sum, npgf_sum, nshell_sum, maxder, short_kind_radius, npgf_seg_sum)
...
collects all references to literature in CP2K as new algorithms / method are included from literature...
integer, save, public chen2025
Calculation of the nuclear attraction contribution to the core Hamiltonian <a|erfc|b> :we only calcul...
Definition core_ae.F:14
subroutine, public verfc_force(habd, pab, fa, fb, nder, la_max, la_min, npgfa, zeta, lb_max, lb_min, npgfb, zetb, rab)
...
Definition core_ae.F:524
Defines control structures, which contain the parameters and the settings for the DFT-based calculati...
various routines to log and control the output. The idea is that decisions about where to log should ...
stores a lists of integer that are local to a processor. The idea is that these integers represent ob...
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Definition of mathematical constants and functions.
real(kind=dp), parameter, public pi
real(kind=dp), dimension(-1:2 *maxfac+1), parameter, public dfac
real(kind=dp), parameter, public fourpi
Collection of simple mathematical functions and subroutines.
Definition mathlib.F:15
subroutine, public get_pseudo_inverse_svd(a, a_pinverse, rskip, determinant, sval)
returns the pseudoinverse of a real, square matrix using singular value decomposition
Definition mathlib.F:938
Utility routines for the memory handling.
Interface to the message passing library MPI.
Provides Cartesian and spherical orbital pointers and indices.
subroutine, public init_orbital_pointers(maxl)
Initialize or update the orbital pointers.
integer, dimension(:), allocatable, public nsoset
integer, dimension(:, :), allocatable, public indso
integer, dimension(:), allocatable, public ncoset
integer, dimension(:), allocatable, public nso
integer, dimension(:, :), allocatable, public indso_inv
Define the data structure for the particle information.
Definition of physical constants:
Definition physcon.F:68
real(kind=dp), parameter, public massunit
Definition physcon.F:141
A collection of functions used by CNEO-DFT (see J. Chem. Theory Comput. 2025, 21, 16,...
subroutine, public vh_1c_nuc_integrals(rhoz_cneo, zeff, avh1b_hh, avh1b_ss, avh1b_00, vh1_h, vh1_s, max_iso_not0_elec, max_iso_not0_nuc, max_s_harm, llmax, cg_list, cg_n_list, nset, npgf, lmin, lmax, nsotot, maxso, nchan_0, gsph, g0_h_w, my_cg, qlm_gg)
Mostly copied from hartree_local_methods::Vh_1c_atom_integrals.
subroutine, public calculate_rhoz_cneo(rho, potential, cg_list, cg_n_list, nset, npgf, lmin, lmax, maxl, maxso)
...
subroutine, public init_cneo_potential_internals(potential, nuc_basis, nuc_soft_basis, gapw_control, grid_atom)
...
subroutine, public cneo_core_matrices(qs_env, calculate_forces, nder)
...
subroutine, public allocate_rhoz_cneo_internals(rhoz_cneo_set, atomic_kind_set, qs_kind_set, qs_env)
...
Types used by CNEO-DFT (see J. Chem. Theory Comput. 2025, 21, 16, 7865–7877)
subroutine, public set_cneo_potential(potential, z, mass, elec_conf, nsgf, nne, npsgf, nsotot, my_gcc_h, my_gcc_s, ovlp, kin, utrans, distance, harmonics, qlm_gg, gg, vgg, n2oindex, o2nindex, rad2l, oorad2l)
...
subroutine, public get_cneo_potential(potential, z, zeff, mass, elec_conf, nsgf, nne, npsgf, nsotot, my_gcc_h, my_gcc_s, ovlp, kin, utrans, distance, harmonics, qlm_gg, gg, vgg, n2oindex, o2nindex, rad2l, oorad2l)
...
subroutine, public allocate_rhoz_cneo_set(rhoz_cneo_set, natom)
...
Utility functions for CNEO-DFT (see J. Chem. Theory Comput. 2025, 21, 16, 7865–7877)
subroutine, public get_maxl_cg_cneo(harmonics, orb_basis, llmax, max_s_harm)
Mostly copied from qs_harmonics_atom::get_maxl_CG.
subroutine, public create_my_cg_cneo(my_cg, lcleb, maxl, llmax)
Mostly copied from qs_rho_atom_methods::init_rho_atom.
subroutine, public atom_solve_cneo(hmat, f, umat, orb, ener, pmat, r, dist, nb, nv)
Mostly copied from atom_utils::atom_solve.
subroutine, public cneo_gather(ain, aout, nbas, n2oindex)
Mostly copied from qs_oce_methods::prj_gather.
subroutine, public create_harmonics_atom_cneo(harmonics, my_cg, llmax, maxs, max_s_harm)
Mostly copied from qs_harmonics_atom::create_harmonics_atom.
subroutine, public get_qs_env(qs_env, atomic_kind_set, qs_kind_set, cell, super_cell, cell_ref, use_ref_cell, kpoints, dft_control, mos, sab_orb, sab_all, qmmm, qmmm_periodic, sac_ae, sac_ppl, sac_lri, sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_almo, sab_kp, sab_kp_nosym, sab_cneo, particle_set, energy, force, matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, run_rtp, rtp, matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_ks_im_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, matrix_s_ri_aux_kp, matrix_s, matrix_s_ri_aux, matrix_w, matrix_p_mp2, matrix_p_mp2_admm, rho, rho_xc, pw_env, ewald_env, ewald_pw, active_space, mpools, input, para_env, blacs_env, scf_control, rel_control, kinetic, qs_charges, vppl, rho_core, rho_nlcc, rho_nlcc_g, ks_env, ks_qmmm_env, wf_history, scf_env, local_particles, local_molecules, distribution_2d, dbcsr_dist, molecule_kind_set, molecule_set, subsys, cp_subsys, oce, local_rho_set, rho_atom_set, task_list, task_list_soft, rho0_atom_set, rho0_mpole, rhoz_set, rhoz_cneo_set, ecoul_1c, rho0_s_rs, rho0_s_gs, rhoz_cneo_s_rs, rhoz_cneo_s_gs, do_kpoints, has_unit_metric, requires_mo_derivs, mo_derivs, mo_loc_history, nkind, natom, nelectron_total, nelectron_spin, efield, neighbor_list_id, linres_control, xas_env, virial, cp_ddapc_env, cp_ddapc_ewald, outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, results, se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, lri_env, lri_density, exstate_env, ec_env, harris_env, dispersion_env, gcp_env, vee, rho_external, external_vxc, mask, mp2_env, bs_env, kg_env, wanniercentres, atprop, ls_scf_env, do_transport, transport_env, v_hartree_rspace, s_mstruct_changed, rho_changed, potential_changed, forces_up_to_date, mscfg_env, almo_scf_env, gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, eeq, rhs, do_rixs, tb_tblite)
Get the QUICKSTEP environment.
subroutine, public allocate_grid_atom(grid_atom)
Initialize components of the grid_atom_type structure.
subroutine, public allocate_harmonics_atom(harmonics)
Allocate a spherical harmonics set for the atom grid.
Define the quickstep kind type and their sub types.
subroutine, public get_qs_kind(qs_kind, basis_set, basis_type, ncgf, nsgf, all_potential, tnadd_potential, gth_potential, sgp_potential, upf_potential, cneo_potential, se_parameter, dftb_parameter, xtb_parameter, dftb3_param, zatom, zeff, elec_conf, mao, lmax_dftb, alpha_core_charge, ccore_charge, core_charge, core_charge_radius, paw_proj_set, paw_atom, hard_radius, hard0_radius, max_rad_local, covalent_radius, vdw_radius, gpw_type_forced, harmonics, max_iso_not0, max_s_harm, grid_atom, ngrid_ang, ngrid_rad, lmax_rho0, dft_plus_u_atom, l_of_dft_plus_u, n_of_dft_plus_u, u_minus_j, u_of_dft_plus_u, j_of_dft_plus_u, alpha_of_dft_plus_u, beta_of_dft_plus_u, j0_of_dft_plus_u, occupation_of_dft_plus_u, dispersion, bs_occupation, magnetization, no_optimize, addel, laddel, naddel, orbitals, max_scf, eps_scf, smear, u_ramping, u_minus_j_target, eps_u_ramping, init_u_ramping_each_scf, reltmat, ghost, floating, name, element_symbol, pao_basis_size, pao_model_file, pao_potentials, pao_descriptors, nelec)
Get attributes of an atomic kind.
subroutine, public get_qs_kind_set(qs_kind_set, all_potential_present, tnadd_potential_present, gth_potential_present, sgp_potential_present, paw_atom_present, dft_plus_u_atom_present, maxcgf, maxsgf, maxco, maxco_proj, maxgtops, maxlgto, maxlprj, maxnset, maxsgf_set, ncgf, npgf, nset, nsgf, nshell, maxpol, maxlppl, maxlppnl, maxppnl, nelectron, maxder, max_ngrid_rad, max_sph_harm, maxg_iso_not0, lmax_rho0, basis_rcut, basis_type, total_zeff_corr, npgf_seg, cneo_potential_present, nkind_q, natom_q)
Get attributes of an atomic kind set.
Define the neighbor list data types and the corresponding functionality.
subroutine, public neighbor_list_iterator_create(iterator_set, nl, search, nthread)
Neighbor list iterator functions.
subroutine, public nl_set_sub_iterator(iterator_set, ikind, jkind, iatom, mepos)
...
subroutine, public neighbor_list_iterator_release(iterator_set)
...
subroutine, public get_iterator_info(iterator_set, mepos, ikind, jkind, nkind, ilist, nlist, inode, nnode, iatom, jatom, r, cell)
...
All kind of helpful little routines.
Definition util.F:14
pure integer function, dimension(2), public get_limit(m, n, me)
divide m entries into n parts, return size of part me
Definition util.F:333
pure subroutine, public virial_pair_force(pv_virial, f0, force, rab)
Computes the contribution to the stress tensor from two-body pair-wise forces.
Calculates special integrals.
Definition whittaker.F:12
subroutine, public whittaker_c0a(wc, r, expa, erfa, alpha, l1, l2, n)
int(y^(2+l1+l2) * exp(-alpha*y*y),y=0..x) / x^(l2+1); wc(:) :: output r(:) :: coordinate expa(:) :: e...
Definition whittaker.F:52
subroutine, public whittaker_ci(wc, r, expa, alpha, l, n)
int(y^(l+1) * exp(-alpha*y*y),y=x..infinity);
Definition whittaker.F:340
Provides all information about a basis set.
Definition atom_types.F:78
Provides all information about an atomic kind.
structure to store local (to a processor) ordered lists of integers.
stores all the informations relevant to an mpi environment
Provides all information about a quickstep kind.