(git:d1312bc)
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-2026 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) THEN
189 CALL cp_abort(__location__, "Nuclear basis with angular momentum higher than "// &
190 "atom_types::lmat is not supported yet.")
191 END IF
192
193 set_index = 0
194 shell_index = 0
195 basis%nprim = 0
196 basis%nbas = 0
197 DO i = 1, nset
198 DO j = lmin(i), min(lmax(i), lmat)
199 basis%nprim(j) = basis%nprim(j) + npgf(i)
200 END DO
201 DO j = 1, nshell(i)
202 l = ls(j, i)
203 IF (l <= lmat) THEN
204 basis%nbas(l) = basis%nbas(l) + 1
205 k = basis%nbas(l)
206 cpassert(k <= 100)
207 set_index(l, k) = i
208 shell_index(l, k) = j
209 END IF
210 END DO
211 END DO
212
213 nl = maxval(basis%nprim)
214 ns = maxval(basis%nbas)
215 ALLOCATE (basis%am(nl, 0:lmat))
216 basis%am = 0._dp
217 ALLOCATE (basis%cm(nl, ns, 0:lmat))
218 basis%cm = 0._dp
219 DO l = 0, lmat
220 nl = 0
221 ns = 0
222 DO i = 1, nset
223 IF (l >= lmin(i) .AND. l <= lmax(i)) THEN
224 DO ipgf = 1, npgf(i)
225 basis%am(nl + ipgf, l) = zet(ipgf, i)
226 END DO
227 DO ii = 1, nshell(i)
228 IF (ls(ii, i) == l) THEN
229 ns = ns + 1
230 DO ipgf = 1, npgf(i)
231 basis%cm(nl + ipgf, ns, l) = gcc_h(ipgf, ii, i) ! NOTE: not normalized
232 END DO
233 END IF
234 END DO
235 nl = nl + npgf(i)
236 END IF
237 END DO
238 END DO
239
240 ! overlap, kinetic and transformation matrices
241 CALL atom_int_setup(integrals, basis)
242
243 ! make the integrals full matrix form
244 ALLOCATE (ovlp(nsgf, nsgf), kin(nsgf, nsgf), utrans(nsgf, nsgf))
245 ovlp = 0.0_dp
246 kin = 0.0_dp
247 utrans = 0.0_dp
248 CALL get_cneo_potential(potential, mass=mass)
249 mass = mass*massunit
250 massinv = 1._dp/mass
251 nne = 0 ! number of linear-independent spherical basis functions
252 DO l = 0, lmat
253 ll = 2*l
254 DO k2 = 1, integrals%nne(l)
255 DO m = 0, ll
256 nne = nne + 1
257 DO k1 = 1, basis%nbas(l)
258 scal1 = sqrt(integrals%ovlp(k1, k1, l))
259 i = first_sgf(shell_index(l, k1), set_index(l, k1))
260 utrans(i + m, nne) = integrals%utrans(k1, k2, l)*scal1
261 END DO
262 END DO
263 END DO
264 DO k1 = 1, basis%nbas(l)
265 scal1 = 1._dp/sqrt(integrals%ovlp(k1, k1, l))
266 i = first_sgf(shell_index(l, k1), set_index(l, k1))
267 DO k2 = 1, basis%nbas(l)
268 scal = scal1/sqrt(integrals%ovlp(k2, k2, l))
269 j = first_sgf(shell_index(l, k2), set_index(l, k2))
270 DO m = 0, ll
271 ! normalize the integrals
272 ovlp(i + m, j + m) = integrals%ovlp(k1, k2, l)*scal
273 kin(i + m, j + m) = integrals%kin(k1, k2, l)*scal*massinv
274 END DO
275 END DO
276 END DO
277 END DO
278
279 nsotot = maxso*nset
280 ALLOCATE (my_gcc_h(nsotot, nsgf), my_gcc_s(nsotot, nsgf))
281 my_gcc_h = 0.0_dp
282 my_gcc_s = 0.0_dp
283 ! create gcc that really 3D-normalize the basis functions
284 DO l = 0, min(maxl, lmat)
285 ns = 0
286 m = 0
287 ll = 2*l
288 k = nsoset(l - 1) + 1
289 DO i = 1, nset
290 IF (l >= lmin(i) .AND. l <= lmax(i)) THEN
291 nsox = nsoset(lmax(i))
292 DO ii = 1, nshell(i)
293 IF (ls(ii, i) == l) THEN
294 ns = ns + 1
295 k1 = first_sgf(shell_index(l, ns), set_index(l, ns))
296 scal = 1._dp/sqrt(integrals%ovlp(ns, ns, l))
297 DO ipgf = 1, npgf(i)
298 gcc_tmp = gcc_h(ipgf, ii, i)*scal
299 k2 = (ipgf - 1)*nsox + m
300 DO j = 0, ll
301 my_gcc_h(k + k2 + j, k1 + j) = gcc_tmp
302 END DO
303 END DO
304 DO ipgf = 1, npgf_s(i)
305 gcc_tmp = gcc_s(ipgf, ii, i)*scal
306 k2 = (ipgf - 1)*nsox + m
307 DO j = 0, ll
308 my_gcc_s(k + k2 + j, k1 + j) = gcc_tmp
309 END DO
310 END DO
311 END IF
312 END DO
313 END IF
314 m = m + maxso
315 END DO
316 END DO
317
318 CALL atom_int_release(integrals)
319 CALL set_cneo_potential(potential, nsgf=nsgf, nne=nne, nsotot=nsotot, &
320 my_gcc_h=my_gcc_h, my_gcc_s=my_gcc_s, &
321 ovlp=ovlp, kin=kin, utrans=utrans)
322 CALL release_atom_basis(basis)
323 DEALLOCATE (basis, integrals)
324
325 ! initialize my_CG
326 lmax_sphere = gapw_control%lmax_sphere
327 ! make sure llmax is at least 1 such that distance matrices can be generated
328 llmax = max(1, min(lmax_sphere, 2*maxl))
329 max_s_harm = nsoset(llmax)
330 max_s = nsoset(maxl)
331 NULLIFY (my_cg)
332 CALL reallocate(my_cg, 1, max_s, 1, max_s, 1, max_s_harm)
333 CALL create_my_cg_cneo(my_cg, max(llmax, 2*maxl, 1), maxl, llmax)
334
335 ! initialize harmonics
336 CALL allocate_harmonics_atom(harmonics)
337 CALL create_harmonics_atom_cneo(harmonics, my_cg, llmax, max_s, max_s_harm)
338 DEALLOCATE (my_cg)
339 CALL get_maxl_cg_cneo(harmonics, nuc_basis, llmax, max_s_harm)
340
341 CALL set_cneo_potential(potential, harmonics=harmonics)
342
343 ! initialize my own rad2l and oorad2l
344 ! copied from qs_grid_atom::create_grid_atom
345 nr = grid_atom%nr
346 NULLIFY (rad2l, oorad2l)
347 CALL reallocate(rad2l, 1, nr, 0, llmax + 1)
348 CALL reallocate(oorad2l, 1, nr, 0, llmax + 1)
349 rad2l(:, 0) = 1._dp
350 oorad2l(:, 0) = 1._dp
351 DO l = 1, llmax + 1
352 rad2l(:, l) = rad2l(:, l - 1)*grid_atom%rad(:)
353 oorad2l(:, l) = oorad2l(:, l - 1)/grid_atom%rad(:)
354 END DO
355 CALL set_cneo_potential(potential, rad2l=rad2l, oorad2l=oorad2l)
356 ! still need to bump lmax in grid_atom as qs_rho0_types::calculate_g0 uses it
357 IF (SIZE(rad2l, 2) > SIZE(grid_atom%rad2l, 2)) THEN
358 cpassert(SIZE(rad2l, 1) == SIZE(grid_atom%rad2l, 1))
359 DEALLOCATE (grid_atom%rad2l)
360 NULLIFY (grid_atom%rad2l)
361 CALL reallocate(grid_atom%rad2l, 1, nr, 0, llmax + 1)
362 grid_atom%rad2l = rad2l
363 END IF
364 IF (SIZE(oorad2l, 2) > SIZE(grid_atom%oorad2l, 2)) THEN
365 cpassert(SIZE(oorad2l, 1) == SIZE(grid_atom%oorad2l, 1))
366 DEALLOCATE (grid_atom%oorad2l)
367 NULLIFY (grid_atom%oorad2l)
368 CALL reallocate(grid_atom%oorad2l, 1, nr, 0, llmax + 1)
369 grid_atom%oorad2l = oorad2l
370 END IF
371
372 ! distance matrices
373 ALLOCATE (distance(nsgf, nsgf, 3), dist(nsotot, nsotot, 3))
374 distance = 0.0_dp
375 dist = 0.0_dp
376 ! initialize gg and vgg
377 ! mostly copied from qs_rho_atom_methods::calculate_rho_atom
378 max_iso_not0 = harmonics%max_iso_not0
379 lmax_expansion = indso(1, max_iso_not0)
380 my_cg => harmonics%my_CG
381 ALLOCATE (g1(nr), g2(nr), gg0(nr), gg(nr, 0:2*maxl, npgf_sum*(npgf_sum + 1)/2))
382 ALLOCATE (erf_zet12(nr), vgg(nr, 0:2*maxl, 0:indso(1, max_iso_not0), npgf_sum*(npgf_sum + 1)/2))
383 ALLOCATE (done_vgg(0:2*maxl, 0:indso(1, max_iso_not0)))
384 ALLOCATE (int1(nr), int2(nr))
385 ALLOCATE (cg_list(2, nsoset(maxl)**2, max_s_harm), cg_n_list(max_s_harm))
386
387 j = 0
388 m1 = 0
389 DO iset1 = 1, nset
390 n1 = nsoset(lmax(iset1))
391 m2 = 0
392 DO iset2 = 1, iset1
393 n2 = nsoset(lmax(iset2))
394
395 CALL get_none0_cg_list(my_cg, lmin(iset1), lmax(iset1), lmin(iset2), lmax(iset2), &
396 max_s_harm, lmax_expansion, cg_list, cg_n_list, max_iso_not0_local)
397 cpassert(max_iso_not0_local <= max_iso_not0)
398
399 DO ipgf1 = 1, npgf(iset1)
400 g1(1:nr) = exp(-zet(ipgf1, iset1)*grid_atom%rad2(1:nr))
401
402 IF (iset2 == iset1) THEN
403 npgf2 = ipgf1
404 ELSE
405 npgf2 = npgf(iset2)
406 END IF
407 DO ipgf2 = 1, npgf2
408 zet12 = zet(ipgf1, iset1) + zet(ipgf2, iset2)
409
410 ! distance part
411 ! -1 -> y -> 2, 0 -> z -> 3, 1 -> x -> 1
412 DO m = -1, 1
413 k = m + 3
414 IF (m == 1) k = 1
415 iso = indso_inv(1, m)
416 DO icg = 1, cg_n_list(iso)
417 is1 = cg_list(1, icg, iso)
418 is2 = cg_list(2, icg, iso)
419
420 iso1 = is1 + n1*(ipgf1 - 1) + m1
421 iso2 = is2 + n2*(ipgf2 - 1) + m2
422
423 l = indso(1, is1) + indso(1, is2)
424 dist(iso1, iso2, k) = dist(iso1, iso2, k) + my_cg(is1, is2, iso)* &
425 pi*dfac(l + 2)/ &
426 ((2.0_dp*zet12)**((l + 3)/2)*sqrt(3.0_dp*zet12))
427 dist(iso2, iso1, k) = dist(iso1, iso2, k) ! symmetric
428 END DO !icg
429 END DO
430
431 ! gg and vgg part
432 j = j + 1
433 g2(1:nr) = exp(-zet(ipgf2, iset2)*grid_atom%rad2(1:nr))
434 lmin12 = lmin(iset1) + lmin(iset2)
435 lmax12 = lmax(iset1) + lmax(iset2)
436
437 root_zet12 = sqrt(zet12)
438 DO ir = 1, nr
439 erf_zet12(ir) = erf(root_zet12*grid_atom%rad(ir))
440 END DO
441
442 gg(:, :, j) = 0.0_dp
443 vgg(:, :, :, j) = 0.0_dp
444 done_vgg = .false.
445 ! reduce the number of terms in the expansion local densities
446 IF (lmin12 <= lmax_expansion) THEN
447 IF (lmin12 == 0) THEN
448 gg(1:nr, lmin12, j) = g1(1:nr)*g2(1:nr)
449 gg0(1:nr) = gg(1:nr, lmin12, j)
450 ELSE
451 gg0(1:nr) = g1(1:nr)*g2(1:nr)
452 gg(1:nr, lmin12, j) = rad2l(1:nr, lmin12)*g1(1:nr)*g2(1:nr)
453 END IF
454
455 ! reduce the number of terms in the expansion local densities
456 IF (lmax12 > lmax_expansion) lmax12 = lmax_expansion
457
458 DO l = lmin12 + 1, lmax12
459 gg(1:nr, l, j) = grid_atom%rad(1:nr)*gg(1:nr, l - 1, j)
460 END DO
461
462 c2 = sqrt(pi*pi*pi/(zet12*zet12*zet12))
463
464 DO iso = 1, max_iso_not0_local
465 l_iso = indso(1, iso)
466 c1 = fourpi/(2._dp*real(l_iso, dp) + 1._dp)
467 DO icg = 1, cg_n_list(iso)
468 iso1 = cg_list(1, icg, iso)
469 iso2 = cg_list(2, icg, iso)
470
471 l = indso(1, iso1) + indso(1, iso2)
472 cpassert(l <= lmax_expansion)
473 IF (done_vgg(l, l_iso)) cycle
474 l_sum = l + l_iso
475 l_sub = l - l_iso
476
477 IF (l_sum == 0) THEN
478 vgg(1:nr, l, l_iso, j) = erf_zet12(1:nr)*oorad2l(1:nr, 1)*c2
479 ELSE
480 CALL whittaker_c0a(int1, grid_atom%rad, gg0, erf_zet12, zet12, l, l_iso, nr)
481 CALL whittaker_ci(int2, grid_atom%rad, gg0, zet12, l_sub, nr)
482
483 DO ir = 1, nr
484 int2(ir) = rad2l(ir, l_iso)*int2(ir)
485 vgg(ir, l, l_iso, j) = c1*(int1(ir) + int2(ir))
486 END DO
487 END IF
488 done_vgg(l, l_iso) = .true.
489 END DO
490 END DO
491 END IF ! lmax_expansion
492
493 END DO ! ipgf2
494 END DO ! ipgf1
495 m2 = m2 + maxso
496 END DO ! iset2
497 m1 = m1 + maxso
498 END DO ! iset1
499
500 DEALLOCATE (g1, g2, gg0, erf_zet12, int1, int2, done_vgg)
501 DEALLOCATE (cg_list, cg_n_list)
502
503 ALLOCATE (work(nsotot, nsgf))
504 DO k = 1, 3
505 CALL dgemm("N", "N", nsotot, nsgf, nsotot, 1.0_dp, dist(:, :, k), nsotot, my_gcc_h, &
506 nsotot, 0.0_dp, work, nsotot)
507 CALL dgemm("T", "N", nsgf, nsgf, nsotot, 1.0_dp, my_gcc_h, nsotot, work, &
508 nsotot, 0.0_dp, distance(:, :, k), nsgf)
509 END DO
510 DEALLOCATE (work, dist)
511 CALL set_cneo_potential(potential, distance=distance, gg=gg, vgg=vgg)
512
513 ! Index transformation OLD-NEW
514 ! copied from paw_proj_set_types::build_projector
515 ALLOCATE (o2nindex(nsotot))
516 ALLOCATE (n2oindex(nsotot))
517 o2nindex = 0
518 n2oindex = 0
519 ico = 1
520 DO iset = 1, nset
521 iso_set = (iset - 1)*maxso + 1
522 nsox = nsoset(lmax(iset))
523 DO ipgf = 1, npgf(iset)
524 iso_pgf = iso_set + (ipgf - 1)*nsox
525 iso = iso_pgf + nsoset(lmin(iset) - 1)
526 DO l = lmin(iset), lmax(iset)
527 DO k = 1, nso(l)
528 n2oindex(ico) = iso
529 o2nindex(iso) = ico
530 iso = iso + 1
531 ico = ico + 1
532 END DO
533 END DO
534 END DO
535 END DO
536 npsgf = ico - 1
537 CALL set_cneo_potential(potential, npsgf=npsgf, n2oindex=n2oindex, o2nindex=o2nindex)
538
539 CALL timestop(handle)
540
541 END SUBROUTINE init_cneo_potential_internals
542
543! **************************************************************************************************
544!> \brief ...
545!> \param rhoz_cneo_set ...
546!> \param atomic_kind_set ...
547!> \param qs_kind_set ...
548!> \param qs_env ...
549! **************************************************************************************************
550 SUBROUTINE allocate_rhoz_cneo_internals(rhoz_cneo_set, atomic_kind_set, &
551 qs_kind_set, qs_env)
552
553 TYPE(rhoz_cneo_type), DIMENSION(:), POINTER :: rhoz_cneo_set
554 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
555 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
556 TYPE(qs_environment_type), POINTER :: qs_env
557
558 CHARACTER(len=*), PARAMETER :: routinen = 'allocate_rhoz_cneo_internals'
559
560 INTEGER :: bo(2), handle, iat, iatom, ikind, &
561 max_iso_not0, mepos, nat, natom, &
562 npsgf, nr, nsgf, nsotot, num_pe
563 INTEGER, DIMENSION(:), POINTER :: atom_list
564 LOGICAL :: paw_atom
565 TYPE(cneo_potential_type), POINTER :: cneo_potential
566 TYPE(mp_para_env_type), POINTER :: para_env
567
568 CALL timeset(routinen, handle)
569
570 CALL get_atomic_kind_set(atomic_kind_set, natom=natom)
571
572 CALL allocate_rhoz_cneo_set(rhoz_cneo_set, natom)
573
574 NULLIFY (para_env)
575 CALL get_qs_env(qs_env, para_env=para_env)
576
577 DO ikind = 1, SIZE(atomic_kind_set)
578
579 NULLIFY (cneo_potential)
580 CALL get_qs_kind(qs_kind_set(ikind), &
581 ngrid_rad=nr, &
582 paw_atom=paw_atom, &
583 cneo_potential=cneo_potential)
584
585 IF (ASSOCIATED(cneo_potential)) THEN
586 cpassert(paw_atom)
587
588 NULLIFY (atom_list)
589 CALL get_atomic_kind(atomic_kind_set(ikind), atom_list=atom_list, natom=nat)
590
591 nsgf = cneo_potential%nsgf
592 npsgf = cneo_potential%npsgf
593 nsotot = cneo_potential%nsotot
594
595 DO iat = 1, nat
596 iatom = atom_list(iat)
597
598 ! density matrices, core and soft vmat will be broadcast to all processes
599 ALLOCATE (rhoz_cneo_set(iatom)%pmat(1:nsgf, 1:nsgf), &
600 rhoz_cneo_set(iatom)%cpc_h(1:npsgf, 1:npsgf), &
601 rhoz_cneo_set(iatom)%cpc_s(1:npsgf, 1:npsgf), &
602 rhoz_cneo_set(iatom)%core(1:nsgf, 1:nsgf), &
603 rhoz_cneo_set(iatom)%vmat(1:nsgf, 1:nsgf))
604 rhoz_cneo_set(iatom)%pmat = 0.0_dp
605 rhoz_cneo_set(iatom)%cpc_h = 0.0_dp
606 rhoz_cneo_set(iatom)%cpc_s = 0.0_dp
607 rhoz_cneo_set(iatom)%core = 0.0_dp
608 rhoz_cneo_set(iatom)%vmat = 0.0_dp
609 END DO
610
611 max_iso_not0 = cneo_potential%harmonics%max_iso_not0
612 num_pe = para_env%num_pe
613 mepos = para_env%mepos
614 bo = get_limit(nat, num_pe, mepos)
615 DO iat = bo(1), bo(2)
616 iatom = atom_list(iat)
617
618 ALLOCATE (rhoz_cneo_set(iatom)%fmat(1:nsgf, 1:nsgf), &
619 rhoz_cneo_set(iatom)%wfn(1:nsgf, 1:nsgf))
620 rhoz_cneo_set(iatom)%fmat = 0.0_dp
621 rhoz_cneo_set(iatom)%wfn = 0.0_dp
622
623 ALLOCATE (rhoz_cneo_set(iatom)%rho_rad_h(1:nr, 1:max_iso_not0), &
624 rhoz_cneo_set(iatom)%rho_rad_s(1:nr, 1:max_iso_not0), &
625 rhoz_cneo_set(iatom)%vrho_rad_h(1:nr, 1:max_iso_not0), &
626 rhoz_cneo_set(iatom)%vrho_rad_s(1:nr, 1:max_iso_not0))
627 rhoz_cneo_set(iatom)%rho_rad_h = 0.0_dp
628 rhoz_cneo_set(iatom)%rho_rad_s = 0.0_dp
629 rhoz_cneo_set(iatom)%vrho_rad_h = 0.0_dp
630 rhoz_cneo_set(iatom)%vrho_rad_s = 0.0_dp
631
632 NULLIFY (rhoz_cneo_set(iatom)%ga_Vlocal_gb_h)
633 CALL reallocate(rhoz_cneo_set(iatom)%ga_Vlocal_gb_h, 1, nsotot, 1, nsotot)
634 rhoz_cneo_set(iatom)%ga_Vlocal_gb_h = 0.0_dp
635 NULLIFY (rhoz_cneo_set(iatom)%ga_Vlocal_gb_s)
636 CALL reallocate(rhoz_cneo_set(iatom)%ga_Vlocal_gb_s, 1, nsotot, 1, nsotot)
637 rhoz_cneo_set(iatom)%ga_Vlocal_gb_s = 0.0_dp
638 END DO ! iat
639 END IF
640
641 END DO
642
643 CALL timestop(handle)
644
645 END SUBROUTINE allocate_rhoz_cneo_internals
646
647! **************************************************************************************************
648!> \brief ...
649!> \param qs_env ...
650!> \param calculate_forces ...
651!> \param nder ...
652! **************************************************************************************************
653 SUBROUTINE cneo_core_matrices(qs_env, calculate_forces, nder)
654 TYPE(qs_environment_type), POINTER :: qs_env
655 LOGICAL, INTENT(IN) :: calculate_forces
656 INTEGER, INTENT(IN) :: nder
657
658 LOGICAL :: use_virial
659 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
660 TYPE(distribution_1d_type), POINTER :: distribution_1d
661 TYPE(mp_para_env_type), POINTER :: para_env
662 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
663 POINTER :: sab_cneo
664 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
665 TYPE(qs_force_type), DIMENSION(:), POINTER :: force
666 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
667 TYPE(rhoz_cneo_type), DIMENSION(:), POINTER :: rhoz_cneo_set
668 TYPE(virial_type), POINTER :: virial
669
670 NULLIFY (rhoz_cneo_set)
671 CALL get_qs_env(qs_env=qs_env, rhoz_cneo_set=rhoz_cneo_set)
672
673 IF (ASSOCIATED(rhoz_cneo_set)) THEN
674 NULLIFY (force, virial)
675 ! force
676 IF (calculate_forces) CALL get_qs_env(qs_env=qs_env, force=force)
677 ! virial
678 CALL get_qs_env(qs_env=qs_env, virial=virial)
679 use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
680
681 NULLIFY (qs_kind_set, atomic_kind_set, particle_set, distribution_1d, para_env, sab_cneo)
682 CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set, atomic_kind_set=atomic_kind_set, &
683 particle_set=particle_set, local_particles=distribution_1d, &
684 para_env=para_env, sab_cneo=sab_cneo)
685 CALL build_core_cneo(rhoz_cneo_set, force, virial, calculate_forces, use_virial, nder, &
686 qs_kind_set, atomic_kind_set, particle_set, distribution_1d, &
687 sab_cneo, para_env)
688 END IF
689
690 END SUBROUTINE cneo_core_matrices
691
692! **************************************************************************************************
693!> \brief ...
694!> \param rhoz_cneo_set ...
695!> \param force ...
696!> \param virial ...
697!> \param calculate_forces ...
698!> \param use_virial ...
699!> \param nder ...
700!> \param qs_kind_set ...
701!> \param atomic_kind_set ...
702!> \param particle_set ...
703!> \param distribution_1d ...
704!> \param sab_cneo ...
705!> \param para_env ...
706! **************************************************************************************************
707 SUBROUTINE build_core_cneo(rhoz_cneo_set, force, virial, calculate_forces, use_virial, nder, &
708 qs_kind_set, atomic_kind_set, particle_set, distribution_1d, &
709 sab_cneo, para_env)
710 TYPE(rhoz_cneo_type), DIMENSION(:), POINTER :: rhoz_cneo_set
711 TYPE(qs_force_type), DIMENSION(:), POINTER :: force
712 TYPE(virial_type), POINTER :: virial
713 LOGICAL, INTENT(IN) :: calculate_forces, use_virial
714 INTEGER, INTENT(IN) :: nder
715 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
716 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
717 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
718 TYPE(distribution_1d_type), POINTER :: distribution_1d
719 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
720 POINTER :: sab_cneo
721 TYPE(mp_para_env_type), POINTER :: para_env
722
723 CHARACTER(LEN=*), PARAMETER :: routinen = 'build_core_cneo'
724
725 INTEGER :: atom_a, handle, iat, iatom, ikind, iset, jatom, jkind, jset, ldai, ldsab, maxco, &
726 maxl, maxnset, maxsgf, mepos, na_plus, nat, natom, nb_plus, ncoa, ncob, nij, nkind, nset, &
727 nthread, sgfa, sgfb
728 INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_of_kind, kind_of
729 INTEGER, DIMENSION(:), POINTER :: atom_list, lmax, lmin, npgf, nsgf
730 INTEGER, DIMENSION(:, :), POINTER :: first_sgf
731 REAL(kind=dp) :: alpha_c, core_charge, core_radius, dab, &
732 f0, rab2, zeta_i, zeta_j
733 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: ff
734 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: habd, work
735 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: hab, pab, verf, vnuc
736 REAL(kind=dp), DIMENSION(3) :: force_a, force_b, force_i, rab
737 REAL(kind=dp), DIMENSION(3, 3) :: pv_thread
739 DIMENSION(:), POINTER :: ap_iterator
740 TYPE(gto_basis_set_type), POINTER :: basis_set
741 TYPE(cneo_potential_type), POINTER :: cneo_potential, cneo_tmp
742 REAL(kind=dp), DIMENSION(:, :), POINTER :: core, pmat, rpgf, sphi, zet
743 REAL(kind=dp), DIMENSION(:), POINTER :: set_radius
744 REAL(kind=dp), DIMENSION(3, SIZE(particle_set)) :: force_thread
745
746 IF (calculate_forces) THEN
747 CALL timeset(routinen//"_forces", handle)
748 ELSE
749 CALL timeset(routinen, handle)
750 END IF
751
752 nkind = SIZE(atomic_kind_set)
753 natom = SIZE(particle_set)
754
755 force_thread = 0.0_dp
756 pv_thread = 0.0_dp
757
758 ! re-initialize core matrices to zero, as later will use para_env%sum to broadcast
759 DO ikind = 1, nkind
760 NULLIFY (cneo_potential)
761 CALL get_qs_kind(qs_kind_set(ikind), cneo_potential=cneo_potential)
762
763 IF (ASSOCIATED(cneo_potential)) THEN
764 NULLIFY (atom_list)
765 CALL get_atomic_kind(atomic_kind_set(ikind), atom_list=atom_list, natom=nat)
766 DO iat = 1, nat
767 iatom = atom_list(iat)
768 rhoz_cneo_set(iatom)%core = 0.0_dp
769 END DO
770 END IF
771 END DO
772
773 CALL get_qs_kind_set(qs_kind_set, basis_type="NUC", &
774 maxco=maxco, maxlgto=maxl, maxsgf=maxsgf, maxnset=maxnset)
775 CALL init_orbital_pointers(maxl + nder + 1)
776 ldsab = max(maxco, maxsgf)
777 ldai = ncoset(maxl + nder + 1)
778
779 nthread = 1
780!$ nthread = omp_get_max_threads()
781
782 CALL neighbor_list_iterator_create(ap_iterator, sab_cneo, search=.true., nthread=nthread)
783
784!$OMP PARALLEL &
785!$OMP DEFAULT (NONE) &
786!$OMP SHARED (rhoz_cneo_set, ap_iterator, distribution_1d, calculate_forces, use_virial, &
787!$OMP qs_kind_set, nthread, ncoset, nkind, iat, ldsab, maxnset, ldai, nder, maxl, &
788!$OMP maxco, para_env) &
789!$OMP PRIVATE (ikind, jkind, iatom, jatom, basis_set, first_sgf, lmax, lmin, npgf, nset, &
790!$OMP nsgf, rpgf, sphi, zet, set_radius, zeta_i, zeta_j, alpha_c, core_charge, &
791!$OMP core_radius, rab, rab2, dab, core, pmat, iset, ncoa, sgfa, jset, ncob, sgfb, &
792!$OMP work, pab, hab, na_plus, nb_plus, verf, vnuc, force_a, force_b, force_i, &
793!$OMP mepos, habd, f0, nij, ff, cneo_potential, cneo_tmp) &
794!$OMP REDUCTION (+ : pv_thread, force_thread )
795
796 mepos = 0
797!$ mepos = omp_get_thread_num()
798
799 ALLOCATE (hab(ldsab, ldsab, maxnset*(maxnset + 1)/2), work(ldsab, ldsab))
800 ALLOCATE (verf(ldai, ldai, 2*maxl + nder + 1), vnuc(ldai, ldai, 2*maxl + nder + 1), ff(0:2*maxl + nder))
801 IF (calculate_forces) THEN
802 ALLOCATE (pab(maxco, maxco, maxnset*(maxnset + 1)/2))
803 END IF
804
805 DO ikind = 1, nkind
806 NULLIFY (cneo_potential)
807 CALL get_qs_kind(qs_kind_set(ikind), basis_set=basis_set, basis_type="NUC", &
808 cneo_potential=cneo_potential, zeff=zeta_i)
809 IF (ASSOCIATED(cneo_potential)) THEN
810 cpassert(ASSOCIATED(basis_set))
811 first_sgf => basis_set%first_sgf
812 lmax => basis_set%lmax
813 lmin => basis_set%lmin
814 npgf => basis_set%npgf
815 nset = basis_set%nset
816 nsgf => basis_set%nsgf_set
817 rpgf => basis_set%pgf_radius
818 set_radius => basis_set%set_radius
819 sphi => basis_set%sphi
820 zet => basis_set%zet
821
822!$OMP DO SCHEDULE(GUIDED)
823 DO iat = 1, distribution_1d%n_el(ikind)
824 iatom = distribution_1d%list(ikind)%array(iat)
825 core => rhoz_cneo_set(iatom)%core
826 cpassert(ASSOCIATED(core))
827 core = cneo_potential%kin ! copy kinetic matrix to core
828 IF (calculate_forces) THEN
829 cpassert(rhoz_cneo_set(iatom)%ready)
830 pmat => rhoz_cneo_set(iatom)%pmat
831 cpassert(ASSOCIATED(pmat))
832 ! *** Decontract density matrix ***
833 DO iset = 1, nset
834 ncoa = npgf(iset)*ncoset(lmax(iset))
835 sgfa = first_sgf(1, iset)
836 DO jset = 1, iset
837 ncob = npgf(jset)*ncoset(lmax(jset))
838 sgfb = first_sgf(1, jset)
839 nij = jset + (iset - 1)*iset/2
840 work(1:ncoa, 1:nsgf(jset)) = matmul(sphi(1:ncoa, sgfa:sgfa + nsgf(iset) - 1), &
841 pmat(sgfa:sgfa + nsgf(iset) - 1, sgfb:sgfb + nsgf(jset) - 1))
842 pab(1:ncoa, 1:ncob, nij) = matmul(work(1:ncoa, 1:nsgf(jset)), &
843 transpose(sphi(1:ncob, sgfb:sgfb + nsgf(jset) - 1)))
844 END DO
845 END DO
846 END IF
847
848 hab = 0._dp
849 DO jkind = 1, nkind
850 NULLIFY (cneo_tmp)
851 CALL get_qs_kind(qs_kind_set(jkind), cneo_potential=cneo_tmp)
852 IF (.NOT. ASSOCIATED(cneo_tmp)) THEN
853 CALL get_qs_kind(qs_kind_set(jkind), &
854 alpha_core_charge=alpha_c, zeff=zeta_j, &
855 ccore_charge=core_charge, core_charge_radius=core_radius)
856 CALL nl_set_sub_iterator(ap_iterator, ikind, jkind, iatom, mepos=mepos)
857
858 DO WHILE (nl_sub_iterate(ap_iterator, mepos=mepos) == 0)
859 CALL get_iterator_info(ap_iterator, jatom=jatom, r=rab, mepos=mepos)
860 rab2 = sum(rab*rab)
861 dab = sqrt(rab2)
862 IF (maxval(set_radius(:)) + core_radius < dab) cycle
863 DO iset = 1, nset
864 IF (set_radius(iset) + core_radius < dab) cycle
865 ncoa = npgf(iset)*ncoset(lmax(iset))
866 sgfa = first_sgf(1, iset)
867 DO jset = 1, iset ! symmetric
868 IF (set_radius(jset) + core_radius < dab) cycle
869 ncob = npgf(jset)*ncoset(lmax(jset))
870 sgfb = first_sgf(1, jset)
871 nij = jset + (iset - 1)*iset/2
872 IF (calculate_forces) THEN
873 IF (jset == iset) THEN
874 f0 = -zeta_i
875 ELSE
876 f0 = -2.0_dp*zeta_i
877 END IF
878 na_plus = npgf(iset)*ncoset(lmax(iset) + nder)
879 nb_plus = npgf(jset)*ncoset(lmax(jset))
880 ALLOCATE (habd(na_plus, nb_plus))
881 habd = 0._dp
882 CALL verfc( &
883 lmax(iset) + nder, npgf(iset), zet(:, iset), rpgf(:, iset), lmin(iset), &
884 lmax(jset), npgf(jset), zet(:, jset), rpgf(:, jset), lmin(jset), &
885 alpha_c, core_radius, zeta_j, core_charge, &
886 [0.0_dp, 0.0_dp, 0.0_dp], 0.0_dp, rab, rab2, rab2, &
887 hab(:, :, nij), verf, vnuc, ff(0:), nder, habd)
888
889 ! *** The derivatives w.r.t. atomic center b are ***
890 ! *** calculated using the translational invariance ***
891 ! *** of the first derivatives ***
892 CALL verfc_force(habd, pab(:, :, nij), force_a, force_b, nder, &
893 lmax(iset), lmin(iset), npgf(iset), zet(:, iset), &
894 lmax(jset), lmin(jset), npgf(jset), zet(:, jset), &
895 [0.0_dp, 0.0_dp, 0.0_dp])
896
897 DEALLOCATE (habd)
898 force_i = force_a + force_b
899
900 force_thread(1, iatom) = force_thread(1, iatom) + f0*force_i(1)
901 force_thread(2, iatom) = force_thread(2, iatom) + f0*force_i(2)
902 force_thread(3, iatom) = force_thread(3, iatom) + f0*force_i(3)
903
904 force_thread(1, jatom) = force_thread(1, jatom) - f0*force_i(1)
905 force_thread(2, jatom) = force_thread(2, jatom) - f0*force_i(2)
906 force_thread(3, jatom) = force_thread(3, jatom) - f0*force_i(3)
907
908 IF (use_virial) THEN
909 CALL virial_pair_force(pv_thread, f0, force_i, rab)
910 END IF
911 ELSE
912 CALL verfc( &
913 lmax(iset), npgf(iset), zet(:, iset), rpgf(:, iset), lmin(iset), &
914 lmax(jset), npgf(jset), zet(:, jset), rpgf(:, jset), lmin(jset), &
915 alpha_c, core_radius, zeta_j, core_charge, &
916 [0.0_dp, 0.0_dp, 0.0_dp], 0.0_dp, rab, rab2, rab2, &
917 hab(:, :, nij), verf, vnuc, ff(0:))
918 END IF
919 END DO
920 END DO
921 END DO
922 END IF
923 END DO
924 ! *** Contract nuclear repulsion integrals
925 DO iset = 1, nset
926 ncoa = npgf(iset)*ncoset(lmax(iset))
927 sgfa = first_sgf(1, iset)
928 DO jset = 1, iset
929 ncob = npgf(jset)*ncoset(lmax(jset))
930 sgfb = first_sgf(1, jset)
931 nij = jset + (iset - 1)*iset/2
932 work(1:ncoa, 1:nsgf(jset)) = matmul(hab(1:ncoa, 1:ncob, nij), &
933 sphi(1:ncob, sgfb:sgfb + nsgf(jset) - 1))
934 core(sgfa:sgfa + nsgf(iset) - 1, sgfb:sgfb + nsgf(jset) - 1) = &
935 core(sgfa:sgfa + nsgf(iset) - 1, sgfb:sgfb + nsgf(jset) - 1) - zeta_i* &
936 matmul(transpose(sphi(1:ncoa, sgfa:sgfa + nsgf(iset) - 1)), work(1:ncoa, 1:nsgf(jset)))
937 ! symmetrize core matrix
938 IF (iset /= jset) THEN
939 core(sgfb:sgfb + nsgf(jset) - 1, sgfa:sgfa + nsgf(iset) - 1) = &
940 transpose(core(sgfa:sgfa + nsgf(iset) - 1, sgfb:sgfb + nsgf(jset) - 1))
941 END IF
942 END DO
943 END DO
944 END DO
945 END IF
946 END DO
947
948 DEALLOCATE (hab, work, verf, vnuc, ff)
949 IF (calculate_forces) THEN
950 DEALLOCATE (pab)
951 END IF
952
953!$OMP END PARALLEL
954
955 CALL neighbor_list_iterator_release(ap_iterator)
956
957 IF (calculate_forces) THEN
958 CALL get_atomic_kind_set(atomic_kind_set, atom_of_kind=atom_of_kind, &
959 kind_of=kind_of)
960!$OMP DO
961 DO iatom = 1, natom
962 atom_a = atom_of_kind(iatom)
963 ikind = kind_of(iatom)
964 force(ikind)%cneo_potential(:, atom_a) = force(ikind)%cneo_potential(:, atom_a) + &
965 force_thread(:, iatom)
966 END DO
967!$OMP END DO
968 END IF
969
970 IF (calculate_forces .AND. use_virial) THEN
971 virial%pv_ppl = virial%pv_ppl + pv_thread
972 virial%pv_virial = virial%pv_virial + pv_thread
973 END IF
974
975 ! broadcast core matrices
976 DO ikind = 1, nkind
977 NULLIFY (cneo_potential)
978 CALL get_qs_kind(qs_kind_set(ikind), cneo_potential=cneo_potential)
979
980 IF (ASSOCIATED(cneo_potential)) THEN
981 NULLIFY (atom_list)
982 CALL get_atomic_kind(atomic_kind_set(ikind), atom_list=atom_list, natom=nat)
983 DO iat = 1, nat
984 iatom = atom_list(iat)
985 CALL para_env%sum(rhoz_cneo_set(iatom)%core)
986 END DO
987 END IF
988 END DO
989
990 CALL timestop(handle)
991
992 END SUBROUTINE build_core_cneo
993
994! **************************************************************************************************
995!> \brief ...
996!> \param rho ...
997!> \param potential ...
998!> \param cg_list ...
999!> \param cg_n_list ...
1000!> \param nset ...
1001!> \param npgf ...
1002!> \param lmin ...
1003!> \param lmax ...
1004!> \param maxl ...
1005!> \param maxso ...
1006! **************************************************************************************************
1007 SUBROUTINE calculate_rhoz_cneo(rho, potential, cg_list, cg_n_list, nset, npgf, &
1008 lmin, lmax, maxl, maxso)
1009
1010 TYPE(rhoz_cneo_type), POINTER :: rho
1011 TYPE(cneo_potential_type), POINTER :: potential
1012 INTEGER, DIMENSION(:, :, :), INTENT(INOUT) :: cg_list
1013 INTEGER, DIMENSION(:), INTENT(INOUT) :: cg_n_list
1014 INTEGER, INTENT(IN) :: nset
1015 INTEGER, DIMENSION(:), POINTER :: npgf, lmin, lmax
1016 INTEGER, INTENT(IN) :: maxl, maxso
1017
1018 CHARACTER(len=*), PARAMETER :: routinen = 'calculate_rhoz_cneo'
1019
1020 INTEGER :: handle, i, i1, i2, icg, ipgf1, ipgf2, iset1, iset2, iso, iso1, iso1_first, &
1021 iso1_last, iso2, iso2_first, iso2_last, iter, j, l, l1, l2, l_iso, lmax_expansion, m1s, &
1022 m2s, max_iso_not0, max_iso_not0_local, max_iter, max_s_harm, n1s, n2s, nne, npgf2, npsgf, &
1023 nsgf, nsotot, size1, size2
1024 INTEGER, DIMENSION(:), POINTER :: n2oindex, o2nindex
1025 REAL(kind=dp) :: det, df_norm, factor, g0, g0p, g1, step, &
1026 zeff
1027 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: ener
1028 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: cpch_sphere, cpcs_sphere, work
1029 REAL(kind=dp), DIMENSION(3) :: df, f_tmp, r, r_tmp
1030 REAL(kind=dp), DIMENSION(3, 3) :: jac, jac_inv
1031 REAL(kind=dp), DIMENSION(:), POINTER :: f
1032 REAL(kind=dp), DIMENSION(:, :), POINTER :: core, cpc_h, cpc_s, fmat, int_local_h, &
1033 int_local_s, my_gcc_h, my_gcc_s, pmat, rho_rad_h, rho_rad_s, utrans, vmat, vrho_rad_h, &
1034 vrho_rad_s, wfn
1035 REAL(kind=dp), DIMENSION(:, :, :), POINTER :: distance, gg, my_cg
1036 REAL(kind=dp), DIMENSION(:, :, :, :), POINTER :: vgg
1037 TYPE(harmonics_atom_type), POINTER :: harmonics
1038
1039 cpassert(ASSOCIATED(rho))
1040 cpassert(ASSOCIATED(potential))
1041
1042 CALL timeset(routinen, handle)
1043
1044 ! convert ga_Vlocal_gb to compressed form V_Hartree
1045 ! use fmat to store V_Hartree
1046 NULLIFY (utrans, my_gcc_h, my_gcc_s, distance, n2oindex, o2nindex)
1047 CALL get_cneo_potential(potential, zeff=zeff, nsgf=nsgf, nne=nne, npsgf=npsgf, &
1048 nsotot=nsotot, my_gcc_h=my_gcc_h, my_gcc_s=my_gcc_s, &
1049 utrans=utrans, distance=distance, n2oindex=n2oindex, &
1050 o2nindex=o2nindex)
1051 fmat => rho%fmat
1052 int_local_h => rho%ga_Vlocal_gb_h
1053 int_local_s => rho%ga_Vlocal_gb_s
1054 ALLOCATE (work(nsotot, nsgf))
1055 CALL dgemm("N", "N", nsotot, nsgf, nsotot, 1.0_dp, int_local_h, nsotot, my_gcc_h, &
1056 nsotot, 0.0_dp, work, nsotot)
1057 CALL dgemm("T", "N", nsgf, nsgf, nsotot, 1.0_dp, my_gcc_h, nsotot, work, &
1058 nsotot, 0.0_dp, fmat, nsgf)
1059 CALL dgemm("N", "N", nsotot, nsgf, nsotot, 1.0_dp, int_local_s, nsotot, my_gcc_s, &
1060 nsotot, 0.0_dp, work, nsotot)
1061 CALL dgemm("T", "N", nsgf, nsgf, nsotot, -1.0_dp, my_gcc_s, nsotot, work, &
1062 nsotot, 1.0_dp, fmat, nsgf)
1063 ! add the soft basis FFT grid part
1064 vmat => rho%vmat
1065 fmat = fmat + vmat
1066
1067 core => rho%core
1068 wfn => rho%wfn
1069 pmat => rho%pmat
1070 f => rho%f
1071 ALLOCATE (ener(nne))
1072 ! build the fock matrix: F = T + V_core + V_Hartree
1073 fmat = fmat + core
1074 ! conduct the constrained optimization with F + f*x
1075 ! initial guess of f is taken from the result of last iteration
1076 CALL atom_solve_cneo(fmat, f, utrans, wfn, ener, pmat, r, distance, nsgf, nne)
1077 ! test if zero initial guess is better
1078 IF (norm2(r) > 1.e-12_dp .AND. dot_product(f, f) /= 0.0_dp) THEN
1079 CALL atom_solve_cneo(fmat, [0.0_dp, 0.0_dp, 0.0_dp], utrans, wfn, &
1080 ener, pmat, r_tmp, distance, nsgf, nne)
1081 IF (dot_product(r_tmp, r_tmp) < dot_product(r, r)) THEN
1082 f = 0.0_dp
1083 r = r_tmp
1084 END IF
1085 END IF
1086 max_iter = 20
1087 iter = 0
1088 ! using Newton's method to solve for f
1089 DO WHILE (norm2(r) > 1.e-12_dp)
1090 iter = iter + 1
1091 ! construct numerical Jacobian with one-side finite difference
1092 DO i = 1, 3
1093 f_tmp = f
1094 f_tmp(i) = f(i) + sign(1.e-4_dp, r(i)) ! forward or backward based on the sign of r
1095 CALL atom_solve_cneo(fmat, f_tmp, utrans, wfn, ener, pmat, r_tmp, distance, nsgf, nne)
1096 DO j = 1, 3
1097 jac(j, i) = (r_tmp(j) - r(j))*sign(1.e4_dp, r(i))
1098 END DO
1099 END DO
1100 CALL invert_matrix_3x3(jac, jac_inv, det)
1101 IF (abs(det) < 1.0e-8_dp) THEN
1102 CALL cp_warn(__location__, "Determinant of the CNEO position Jacobian is small! "// &
1103 trim(cp_to_string(det))//" Trying central difference.")
1104 ! construct numerical Jacobian with central finite difference
1105 DO i = 1, 3
1106 f_tmp = f
1107 f_tmp(i) = f(i) - sign(1.e-4_dp, r(i))
1108 CALL atom_solve_cneo(fmat, f_tmp, utrans, wfn, ener, pmat, r_tmp, distance, nsgf, nne)
1109 DO j = 1, 3
1110 jac(j, i) = (jac(j, i)*sign(1.e-4_dp, r(i)) + r(j) - r_tmp(j)) &
1111 /sign(2.e-4_dp, r(i))
1112 END DO
1113 END DO
1114 CALL invert_matrix_3x3(jac, jac_inv, det)
1115 IF (abs(det) < 1.0e-8_dp) THEN
1116 CALL cp_warn(__location__, "Determinant of the CNEO position Jacobian is small! "// &
1117 "(Central difference) "//trim(cp_to_string(det))//" Using pseudoinverse.")
1118 END IF
1119 CALL invert_matrix_3x3(jac, jac_inv, det, try_svd=.true.)
1120 END IF
1121 df = -reshape(matmul(jac_inv, reshape(r, [3, 1])), [3])
1122 df_norm = norm2(df)
1123 f_tmp = f
1124 r_tmp = r
1125 g0 = norm2(r_tmp)
1126 f = f_tmp + df
1127 CALL atom_solve_cneo(fmat, f, utrans, wfn, ener, pmat, r, distance, nsgf, nne)
1128 g1 = norm2(r)
1129 step = 1.0_dp
1130 DO WHILE (g1 >= g0)
1131 ! line search
1132 IF (step < 0.0101_dp) THEN
1133 cpwarn("CNEO nuclear position constraint solver line search failure.")
1134 EXIT
1135 END IF
1136 g0p = -g0/(step*df_norm)
1137 step = step*max(-g0p/(2.0_dp*(g1 - g0 - g0p)), 0.1_dp)
1138 f = f_tmp + step*df
1139 CALL atom_solve_cneo(fmat, f, utrans, wfn, ener, pmat, r, distance, nsgf, nne)
1140 g1 = norm2(r)
1141 END DO
1142 IF (iter >= max_iter) THEN
1143 CALL cp_warn(__location__, "CNEO nuclear position constraint solver failed to "// &
1144 "converge in "//trim(cp_to_string(max_iter))//" steps. "// &
1145 "Nuclear position error (x,y,z): "//trim(cp_to_string(r(1)))// &
1146 ", "//trim(cp_to_string(r(2)))//", "//trim(cp_to_string(r(3)))// &
1147 ". This does not hurt as long as it is not the final SCF iteration.")
1148 EXIT
1149 END IF
1150 END DO
1151 DEALLOCATE (ener)
1152 rho%e_core = trace_r_axb(core, nsgf, pmat, nsgf, nsgf, nsgf)
1153
1154 ! decontract the density matrix
1155 ! first use ga_Vlocal_gb to store the decompressed form
1156 CALL dgemm("N", "N", nsotot, nsgf, nsgf, 1.0_dp, my_gcc_h, nsotot, pmat, nsgf, &
1157 0.0_dp, work, nsotot)
1158 CALL dgemm("N", "T", nsotot, nsotot, nsgf, 1.0_dp, work, nsotot, my_gcc_h, nsotot, &
1159 0.0_dp, int_local_h, nsotot)
1160 CALL dgemm("N", "N", nsotot, nsgf, nsgf, 1.0_dp, my_gcc_s, nsotot, pmat, nsgf, &
1161 0.0_dp, work, nsotot)
1162 CALL dgemm("N", "T", nsotot, nsotot, nsgf, 1.0_dp, work, nsotot, my_gcc_s, nsotot, &
1163 0.0_dp, int_local_s, nsotot)
1164 DEALLOCATE (work)
1165 ! compress the density matrix
1166 cpc_h => rho%cpc_h
1167 cpc_s => rho%cpc_s
1168 CALL cneo_gather(int_local_h, cpc_h, npsgf, n2oindex)
1169 CALL cneo_gather(int_local_s, cpc_s, npsgf, n2oindex)
1170 ! restore ga_Vlocal_gb to zeros
1171 int_local_h = 0.0_dp
1172 int_local_s = 0.0_dp
1173
1174 ! construct the nuclear density and its Hartree potential
1175 ! rho_rad_h and vrho_rad_h should contain the -Zeff factor
1176 ! mostly copied from qs_rho_atom_methods::calculate_rho_atom
1177 NULLIFY (harmonics, gg, vgg)
1178 CALL get_cneo_potential(potential, harmonics=harmonics, gg=gg, vgg=vgg)
1179 rho_rad_h => rho%rho_rad_h
1180 rho_rad_s => rho%rho_rad_s
1181 rho_rad_h = 0.0_dp
1182 rho_rad_s = 0.0_dp
1183 vrho_rad_h => rho%vrho_rad_h
1184 vrho_rad_s => rho%vrho_rad_s
1185 vrho_rad_h = 0.0_dp
1186 vrho_rad_s = 0.0_dp
1187 my_cg => harmonics%my_CG
1188 max_iso_not0 = harmonics%max_iso_not0
1189 max_s_harm = harmonics%max_s_harm
1190 lmax_expansion = indso(1, max_iso_not0)
1191
1192 ALLOCATE (cpch_sphere(nsoset(maxl), nsoset(maxl)))
1193 ALLOCATE (cpcs_sphere(nsoset(maxl), nsoset(maxl)))
1194 j = 0
1195 m1s = 0
1196 DO iset1 = 1, nset
1197 m2s = 0
1198 n1s = nsoset(lmax(iset1))
1199 DO iset2 = 1, iset1
1200
1201 CALL get_none0_cg_list(my_cg, lmin(iset1), lmax(iset1), lmin(iset2), lmax(iset2), &
1202 max_s_harm, lmax_expansion, cg_list, cg_n_list, max_iso_not0_local)
1203 cpassert(max_iso_not0_local <= max_iso_not0)
1204
1205 n2s = nsoset(lmax(iset2))
1206 DO ipgf1 = 1, npgf(iset1)
1207 iso1_first = nsoset(lmin(iset1) - 1) + 1 + n1s*(ipgf1 - 1) + m1s
1208 iso1_last = nsoset(lmax(iset1)) + n1s*(ipgf1 - 1) + m1s
1209 size1 = iso1_last - iso1_first + 1
1210 iso1_first = o2nindex(iso1_first)
1211 iso1_last = o2nindex(iso1_last)
1212 i1 = iso1_last - iso1_first + 1
1213 cpassert(size1 == i1)
1214 i1 = nsoset(lmin(iset1) - 1) + 1
1215
1216 IF (iset2 == iset1) THEN
1217 npgf2 = ipgf1
1218 ELSE
1219 npgf2 = npgf(iset2)
1220 END IF
1221 DO ipgf2 = 1, npgf2
1222 j = j + 1
1223 iso2_first = nsoset(lmin(iset2) - 1) + 1 + n2s*(ipgf2 - 1) + m2s
1224 iso2_last = nsoset(lmax(iset2)) + n2s*(ipgf2 - 1) + m2s
1225 size2 = iso2_last - iso2_first + 1
1226 iso2_first = o2nindex(iso2_first)
1227 iso2_last = o2nindex(iso2_last)
1228 i2 = iso2_last - iso2_first + 1
1229 cpassert(size2 == i2)
1230 i2 = nsoset(lmin(iset2) - 1) + 1
1231
1232 IF (iset2 == iset1 .AND. ipgf2 == ipgf1) THEN
1233 factor = -zeff
1234 ELSE
1235 factor = -2.0_dp*zeff
1236 END IF
1237
1238 cpch_sphere = 0.0_dp
1239 cpcs_sphere = 0.0_dp
1240 cpch_sphere(i1:i1 + size1 - 1, i2:i2 + size2 - 1) = cpc_h(iso1_first:iso1_last, iso2_first:iso2_last)
1241 cpcs_sphere(i1:i1 + size1 - 1, i2:i2 + size2 - 1) = cpc_s(iso1_first:iso1_last, iso2_first:iso2_last)
1242 DO iso = 1, max_iso_not0_local
1243 l_iso = indso(1, iso)
1244 DO icg = 1, cg_n_list(iso)
1245 iso1 = cg_list(1, icg, iso)
1246 iso2 = cg_list(2, icg, iso)
1247
1248 l1 = indso(1, iso1)
1249 l2 = indso(1, iso2)
1250
1251 l = indso(1, iso1) + indso(1, iso2)
1252 cpassert(l <= lmax_expansion)
1253
1254 rho_rad_h(:, iso) = rho_rad_h(:, iso) + gg(:, l, j)* &
1255 cpch_sphere(iso1, iso2)*my_cg(iso1, iso2, iso)*factor
1256
1257 rho_rad_s(:, iso) = rho_rad_s(:, iso) + gg(:, l, j)* &
1258 cpcs_sphere(iso1, iso2)*my_cg(iso1, iso2, iso)*factor
1259
1260 vrho_rad_h(:, iso) = vrho_rad_h(:, iso) + vgg(:, l, l_iso, j)* &
1261 cpch_sphere(iso1, iso2)*my_cg(iso1, iso2, iso)*factor
1262
1263 vrho_rad_s(:, iso) = vrho_rad_s(:, iso) + vgg(:, l, l_iso, j)* &
1264 cpcs_sphere(iso1, iso2)*my_cg(iso1, iso2, iso)*factor
1265 END DO ! icg
1266 END DO ! iso
1267 END DO ! ipgf2
1268 END DO ! ipgf1
1269 m2s = m2s + maxso
1270 END DO ! iset2
1271 m1s = m1s + maxso
1272 END DO ! iset1
1273 DEALLOCATE (cpch_sphere, cpcs_sphere)
1274
1275 CALL timestop(handle)
1276
1277 END SUBROUTINE calculate_rhoz_cneo
1278
1279! **************************************************************************************************
1280!> \brief Mostly copied from hartree_local_methods::Vh_1c_atom_integrals
1281!> \param rhoz_cneo ...
1282!> \param zeff ...
1283!> \param aVh1b_hh ...
1284!> \param aVh1b_ss ...
1285!> \param aVh1b_00 ...
1286!> \param Vh1_h ...
1287!> \param Vh1_s ...
1288!> \param max_iso_not0_elec ...
1289!> \param max_iso_not0_nuc ...
1290!> \param max_s_harm ...
1291!> \param llmax ...
1292!> \param cg_list ...
1293!> \param cg_n_list ...
1294!> \param nset ...
1295!> \param npgf ...
1296!> \param lmin ...
1297!> \param lmax ...
1298!> \param nsotot ...
1299!> \param maxso ...
1300!> \param nchan_0 ...
1301!> \param gsph ...
1302!> \param g0_h_w ...
1303!> \param my_CG ...
1304!> \param Qlm_gg ...
1305! **************************************************************************************************
1306 SUBROUTINE vh_1c_nuc_integrals(rhoz_cneo, zeff, &
1307 aVh1b_hh, aVh1b_ss, aVh1b_00, Vh1_h, Vh1_s, &
1308 max_iso_not0_elec, max_iso_not0_nuc, &
1309 max_s_harm, llmax, cg_list, cg_n_list, &
1310 nset, npgf, lmin, lmax, nsotot, maxso, nchan_0, gsph, &
1311 g0_h_w, my_CG, Qlm_gg)
1312
1313 TYPE(rhoz_cneo_type), POINTER :: rhoz_cneo
1314 REAL(kind=dp), INTENT(IN) :: zeff
1315 REAL(kind=dp), DIMENSION(:, :) :: avh1b_hh, avh1b_ss, avh1b_00
1316 REAL(kind=dp), DIMENSION(:, :), POINTER :: vh1_h, vh1_s
1317 INTEGER, INTENT(IN) :: max_iso_not0_elec, max_iso_not0_nuc, &
1318 max_s_harm, llmax
1319 INTEGER, DIMENSION(:, :, :) :: cg_list
1320 INTEGER, DIMENSION(:) :: cg_n_list
1321 INTEGER, INTENT(IN) :: nset
1322 INTEGER, DIMENSION(:), POINTER :: npgf, lmin, lmax
1323 INTEGER, INTENT(IN) :: nsotot, maxso, nchan_0
1324 REAL(kind=dp), DIMENSION(:, :), POINTER :: gsph
1325 REAL(kind=dp), DIMENSION(:, 0:) :: g0_h_w
1326 REAL(kind=dp), DIMENSION(:, :, :), POINTER :: my_cg, qlm_gg
1327
1328 INTEGER :: icg, ipgf1, ipgf2, ir, is1, is2, iset1, &
1329 iset2, iso, iso1, iso2, l_ang, m1, m2, &
1330 max_iso_not0_local, n1, n2, nr
1331 REAL(kind=dp) :: gvg_0, gvg_h, gvg_s
1332
1333 ! Calculate the integrals of the potential with 2 primitives
1334 avh1b_hh = 0.0_dp
1335 avh1b_ss = 0.0_dp
1336 avh1b_00 = 0.0_dp
1337
1338 nr = SIZE(gsph, 1)
1339
1340 m1 = 0
1341 DO iset1 = 1, nset
1342 n1 = nsoset(lmax(iset1))
1343 m2 = 0
1344 DO iset2 = 1, nset
1345 CALL get_none0_cg_list(my_cg, lmin(iset1), lmax(iset1), lmin(iset2), lmax(iset2), &
1346 max_s_harm, llmax, cg_list, cg_n_list, max_iso_not0_local)
1347
1348 n2 = nsoset(lmax(iset2))
1349 DO ipgf1 = 1, npgf(iset1)
1350 DO ipgf2 = 1, npgf(iset2)
1351 DO iso = 1, min(max_iso_not0_elec, max_iso_not0_nuc)
1352 DO icg = 1, cg_n_list(iso)
1353 is1 = cg_list(1, icg, iso)
1354 is2 = cg_list(2, icg, iso)
1355
1356 iso1 = is1 + n1*(ipgf1 - 1) + m1
1357 iso2 = is2 + n2*(ipgf2 - 1) + m2
1358 gvg_h = 0.0_dp
1359 gvg_s = 0.0_dp
1360
1361 DO ir = 1, nr
1362 gvg_h = gvg_h + gsph(ir, iso1)*gsph(ir, iso2)*vh1_h(ir, iso)
1363 gvg_s = gvg_s + gsph(ir, iso1)*gsph(ir, iso2)*vh1_s(ir, iso)
1364 END DO ! ir
1365
1366 avh1b_hh(iso1, iso2) = avh1b_hh(iso1, iso2) + gvg_h*my_cg(is1, is2, iso)
1367 avh1b_ss(iso1, iso2) = avh1b_ss(iso1, iso2) + gvg_s*my_cg(is1, is2, iso)
1368
1369 END DO !icg
1370 END DO ! iso
1371 DO iso = max_iso_not0_elec + 1, max_iso_not0_nuc
1372 DO icg = 1, cg_n_list(iso)
1373 is1 = cg_list(1, icg, iso)
1374 is2 = cg_list(2, icg, iso)
1375
1376 iso1 = is1 + n1*(ipgf1 - 1) + m1
1377 iso2 = is2 + n2*(ipgf2 - 1) + m2
1378 gvg_s = 0.0_dp
1379
1380 DO ir = 1, nr
1381 gvg_s = gvg_s + gsph(ir, iso1)*gsph(ir, iso2)*vh1_s(ir, iso)
1382 END DO ! ir
1383
1384 avh1b_ss(iso1, iso2) = avh1b_ss(iso1, iso2) + gvg_s*my_cg(is1, is2, iso)
1385
1386 END DO !icg
1387 END DO ! iso
1388 DO iso = 1, min(nchan_0, max_iso_not0_nuc)
1389 l_ang = indso(1, iso)
1390 gvg_0 = sum(vh1_s(:, iso)*g0_h_w(:, l_ang))
1391 DO icg = 1, cg_n_list(iso)
1392 is1 = cg_list(1, icg, iso)
1393 is2 = cg_list(2, icg, iso)
1394
1395 iso1 = is1 + n1*(ipgf1 - 1) + m1
1396 iso2 = is2 + n2*(ipgf2 - 1) + m2
1397
1398 avh1b_00(iso1, iso2) = avh1b_00(iso1, iso2) + gvg_0*qlm_gg(iso1, iso2, iso)
1399
1400 END DO !icg
1401 END DO ! iso
1402 END DO ! ipgf2
1403 END DO ! ipgf1
1404 m2 = m2 + maxso
1405 END DO ! iset2
1406 m1 = m1 + maxso
1407 END DO !iset1
1408
1409 CALL daxpy(nsotot*nsotot, -zeff, avh1b_hh, 1, rhoz_cneo%ga_Vlocal_gb_h, 1)
1410 CALL daxpy(nsotot*nsotot, -zeff, avh1b_ss, 1, rhoz_cneo%ga_Vlocal_gb_s, 1)
1411 CALL daxpy(nsotot*nsotot, zeff, avh1b_00, 1, rhoz_cneo%ga_Vlocal_gb_h, 1)
1412 CALL daxpy(nsotot*nsotot, zeff, avh1b_00, 1, rhoz_cneo%ga_Vlocal_gb_s, 1)
1413
1414 END SUBROUTINE vh_1c_nuc_integrals
1415
1416! **************************************************************************************************
1417!> \brief Analytical inversion of a 3x3 matrix
1418!> \param matrix ...
1419!> \param inv_matrix ...
1420!> \param det ...
1421!> \param try_svd ...
1422! **************************************************************************************************
1423 SUBROUTINE invert_matrix_3x3(matrix, inv_matrix, det, try_svd)
1424 REAL(kind=dp), DIMENSION(3, 3), INTENT(IN) :: matrix
1425 REAL(kind=dp), DIMENSION(3, 3), INTENT(OUT) :: inv_matrix
1426 REAL(kind=dp), INTENT(OUT) :: det
1427 LOGICAL, INTENT(IN), OPTIONAL :: try_svd
1428
1429 LOGICAL :: my_try_svd
1430
1431 my_try_svd = .false.
1432 IF (PRESENT(try_svd)) my_try_svd = try_svd
1433
1434 det = matrix(1, 1)*(matrix(2, 2)*matrix(3, 3) - matrix(2, 3)*matrix(3, 2)) &
1435 - matrix(1, 2)*(matrix(2, 1)*matrix(3, 3) - matrix(2, 3)*matrix(3, 1)) &
1436 + matrix(1, 3)*(matrix(2, 1)*matrix(3, 2) - matrix(2, 2)*matrix(3, 1))
1437 IF (abs(det) < 1.0e-8_dp) THEN
1438 IF (my_try_svd) THEN
1439 ! pseudo inverse using SVD
1440 CALL get_pseudo_inverse_svd(matrix, inv_matrix, 1.0e-6_dp, det)
1441 ELSE
1442 inv_matrix = 0.0_dp
1443 END IF
1444 ELSE
1445 inv_matrix(1, 1) = matrix(2, 2)*matrix(3, 3) - matrix(2, 3)*matrix(3, 2)
1446 inv_matrix(1, 2) = matrix(1, 3)*matrix(3, 2) - matrix(1, 2)*matrix(3, 3)
1447 inv_matrix(1, 3) = matrix(1, 2)*matrix(2, 3) - matrix(1, 3)*matrix(2, 2)
1448 inv_matrix(2, 1) = matrix(2, 3)*matrix(3, 1) - matrix(2, 1)*matrix(3, 3)
1449 inv_matrix(2, 2) = matrix(1, 1)*matrix(3, 3) - matrix(1, 3)*matrix(3, 1)
1450 inv_matrix(2, 3) = matrix(1, 3)*matrix(2, 1) - matrix(1, 1)*matrix(2, 3)
1451 inv_matrix(3, 1) = matrix(2, 1)*matrix(3, 2) - matrix(2, 2)*matrix(3, 1)
1452 inv_matrix(3, 2) = matrix(1, 2)*matrix(3, 1) - matrix(1, 1)*matrix(3, 2)
1453 inv_matrix(3, 3) = matrix(1, 1)*matrix(2, 2) - matrix(1, 2)*matrix(2, 1)
1454 inv_matrix = inv_matrix/det
1455 END IF
1456 END SUBROUTINE invert_matrix_3x3
1457
1458END 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:926
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, ccon)
...
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:560
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:946
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, mimic, 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, matrix_vhxc, 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, xcint_weights, 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, hund_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, proj_shell_charge, lr_atom, do_mtlr, u_j_loop, ao_coef, init_u_ramping_each_scf, reltmat, ghost, monovalent, 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, do_mtlr_present, 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.