(git:f8a708f)
Loading...
Searching...
No Matches
atom_sgp.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! **************************************************************************************************
9MODULE atom_sgp
11 USE atom_types, ONLY: &
14 USE atom_utils, ONLY: integrate_grid,&
17 USE input_constants, ONLY: ecp_pseudo,&
18 gaussian,&
20 no_pseudo,&
25 USE kinds, ONLY: dp
26 USE mathconstants, ONLY: dfac,&
27 fourpi,&
28 rootpi,&
29 sqrt2
30 USE mathlib, ONLY: diamat_all,&
32 USE powell, ONLY: opt_state_type,&
35#include "../base/base_uses.f90"
36
37 IMPLICIT NONE
38
40 LOGICAL :: has_nonlocal = .false.
41 INTEGER :: n_nonlocal = 0
42 INTEGER :: lmax = 0
43 LOGICAL, DIMENSION(0:5) :: is_nonlocal = .false.
44 REAL(kind=dp), DIMENSION(:), POINTER :: a_nonlocal => null()
45 REAL(kind=dp), DIMENSION(:, :), POINTER :: h_nonlocal => null()
46 REAL(kind=dp), DIMENSION(:, :, :), POINTER :: c_nonlocal => null()
47 LOGICAL :: has_local = .false.
48 INTEGER :: n_local = 0
49 REAL(kind=dp) :: zval = 0.0_dp
50 REAL(kind=dp) :: ac_local = 0.0_dp
51 REAL(kind=dp), DIMENSION(:), POINTER :: a_local => null()
52 REAL(kind=dp), DIMENSION(:), POINTER :: c_local => null()
53 LOGICAL :: has_nlcc = .false.
54 INTEGER :: n_nlcc = 0
55 REAL(kind=dp), DIMENSION(:), POINTER :: a_nlcc => null()
56 REAL(kind=dp), DIMENSION(:), POINTER :: c_nlcc => null()
58
59 PRIVATE
63
64 CHARACTER(len=*), PARAMETER, PRIVATE :: modulen = 'atom_sgp'
65
66! **************************************************************************************************
67
68CONTAINS
69
70! **************************************************************************************************
71!> \brief ...
72!> \param sgp_pot ...
73!> \param ecp_pot ...
74!> \param upf_pot ...
75!> \param orb_basis ...
76!> \param error ...
77! **************************************************************************************************
78 SUBROUTINE sgp_construction(sgp_pot, ecp_pot, upf_pot, orb_basis, error)
79
80 TYPE(atom_sgp_potential_type) :: sgp_pot
81 TYPE(atom_ecppot_type), OPTIONAL :: ecp_pot
82 TYPE(atom_upfpot_type), OPTIONAL :: upf_pot
83 TYPE(gto_basis_set_type), OPTIONAL, POINTER :: orb_basis
84 REAL(kind=dp), DIMENSION(6) :: error
85
86 INTEGER :: i, n
87 INTEGER, DIMENSION(3) :: mloc
88 LOGICAL :: is_ecp, is_upf
89 REAL(kind=dp) :: errcc, rcut
90 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: cgauss, cutpots, cutpotu
91 TYPE(atom_basis_type) :: basis
92 TYPE(opmat_type), POINTER :: core, hnl, score, shnl
93
94 ! define basis
95 IF (PRESENT(orb_basis)) THEN
96 CALL set_kind_basis_atomic(basis, orb_basis, has_pp=.true., cp2k_norm=.true.)
97 ELSE
99 END IF
100
101 is_ecp = .false.
102 IF (PRESENT(ecp_pot)) is_ecp = .true.
103 is_upf = .false.
104 IF (PRESENT(upf_pot)) is_upf = .true.
105 cpassert(.NOT. (is_ecp .AND. is_upf))
106
107 ! upf has often very small grids, use a smooth cutoff function
108 IF (is_upf) THEN
109 n = SIZE(upf_pot%r)
110 ALLOCATE (cutpotu(n))
111 rcut = maxval(upf_pot%r)
112 CALL cutpot(cutpotu, upf_pot%r, rcut, 2.5_dp)
113 n = basis%grid%nr
114 ALLOCATE (cutpots(n))
115 CALL cutpot(cutpots, basis%grid%rad, rcut, 2.5_dp)
116 ELSE
117 n = basis%grid%nr
118 ALLOCATE (cutpots(n))
119 cutpots = 1.0_dp
120 END IF
121
122 ! generate the transformed potentials
123 IF (is_ecp) THEN
124 CALL ecp_sgp_constr(ecp_pot, sgp_pot, basis)
125 ELSE IF (is_upf) THEN
126 CALL upf_sgp_constr(upf_pot, sgp_pot, basis)
127 ELSE
128 cpabort("Either ecp_pot or upf_pot is needed for sgp_construction")
129 END IF
130
131 NULLIFY (core, hnl)
132 CALL create_opmat(core, basis%nbas)
133 CALL create_opmat(hnl, basis%nbas, 5)
134 NULLIFY (score, shnl)
135 CALL create_opmat(score, basis%nbas)
136 CALL create_opmat(shnl, basis%nbas, 5)
137 !
138 IF (is_ecp) THEN
139 CALL ecpints(hnl%op, basis, ecp_pot)
140 ELSE IF (is_upf) THEN
141 CALL upfints(core%op, hnl%op, basis, upf_pot, cutpotu, sgp_pot%ac_local)
142 ELSE
143 cpabort("Either ecp_pot or upf_pot is needed for sgp_construction")
144 END IF
145 !
146 CALL sgpints(score%op, shnl%op, basis, sgp_pot, cutpots)
147 !
148 error = 0.0_dp
149 IF (sgp_pot%has_local) THEN
150 n = min(3, ubound(core%op, 3))
151 error(1) = maxval(abs(core%op(:, :, 0:n) - score%op(:, :, 0:n)))
152 mloc = maxloc(abs(core%op(:, :, 0:n) - score%op(:, :, 0:n)))
153 ! MAXLOC returns positions starting at one, whereas the angular index starts at zero.
154 mloc(3) = mloc(3) - 1
155 error(4) = error(1)/max(abs(core%op(mloc(1), mloc(2), mloc(3))), 1.e-6_dp)
156 END IF
157 IF (sgp_pot%has_nonlocal) THEN
158 n = min(3, ubound(hnl%op, 3))
159 error(2) = maxval(abs(hnl%op(:, :, 0:n) - shnl%op(:, :, 0:n)))
160 mloc = maxloc(abs(hnl%op(:, :, 0:n) - shnl%op(:, :, 0:n)))
161 mloc(3) = mloc(3) - 1
162 error(5) = error(2)/max(abs(hnl%op(mloc(1), mloc(2), mloc(3))), 1.e-6_dp)
163 END IF
164 IF (sgp_pot%has_nlcc) THEN
165 IF (is_upf) THEN
166 n = SIZE(upf_pot%r)
167 ALLOCATE (cgauss(n))
168 cgauss = 0.0_dp
169 DO i = 1, sgp_pot%n_nlcc
170 cgauss(:) = cgauss(:) + sgp_pot%c_nlcc(i)*exp(-sgp_pot%a_nlcc(i)*upf_pot%r(:)**2)
171 END DO
172 errcc = sum((cgauss(:) - upf_pot%rho_nlcc(:))**2*upf_pot%r(:)**2*upf_pot%rab(:))
173 errcc = sqrt(errcc/real(n, kind=dp))
174 DEALLOCATE (cgauss)
175 ELSE
176 cpabort("sgp_pot%has_nlcc requires is_upf")
177 END IF
178 error(3) = errcc
179 END IF
180 !
181 IF (is_upf) THEN
182 DEALLOCATE (cutpotu)
183 DEALLOCATE (cutpots)
184 ELSE
185 DEALLOCATE (cutpots)
186 END IF
187 !
188 CALL release_opmat(score)
189 CALL release_opmat(shnl)
190 CALL release_opmat(core)
191 CALL release_opmat(hnl)
192
193 CALL release_atom_basis(basis)
194
195 END SUBROUTINE sgp_construction
196
197! **************************************************************************************************
198!> \brief ...
199!> \param atom_info ...
200!> \param input_section ...
201!> \param iw ...
202! **************************************************************************************************
203 SUBROUTINE atom_sgp_construction(atom_info, input_section, iw)
204
205 TYPE(atom_p_type), DIMENSION(:, :), POINTER :: atom_info
206 TYPE(section_vals_type), POINTER :: input_section
207 INTEGER, INTENT(IN) :: iw
208
209 INTEGER :: i, n, ppot_type
210 LOGICAL :: do_transform, explicit, is_ecp, is_upf
211 REAL(kind=dp) :: errcc, rcut
212 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: cgauss, cutpots, cutpotu
213 TYPE(atom_ecppot_type), POINTER :: ecp_pot
214 TYPE(atom_sgp_potential_type) :: sgp_pot
215 TYPE(atom_type), POINTER :: atom_ref
216 TYPE(atom_upfpot_type), POINTER :: upf_pot
217 TYPE(opmat_type), POINTER :: core, hnl, score, shnl
218
219 CALL section_vals_get(input_section, explicit=explicit)
220 IF (.NOT. explicit) RETURN
221
222 IF (iw > 0) WRITE (iw, '(/," ",79("*"),/,T24,A,/," ",79("*"))') "SEPARABLE GAUSSIAN PSEUDOPOTENTIAL"
223
224 atom_ref => atom_info(1, 1)%atom
225
226 ppot_type = atom_ref%potential%ppot_type
227 SELECT CASE (ppot_type)
228 CASE (gth_pseudo)
229 IF (iw > 0) WRITE (iw, '(" GTH Pseudopotential is already in SGP form. ")')
230 do_transform = .false.
231 CASE (ecp_pseudo)
232 do_transform = .true.
233 is_ecp = .true.
234 is_upf = .false.
235 ecp_pot => atom_ref%potential%ecp_pot
236 CASE (upf_pseudo)
237 do_transform = .true.
238 is_ecp = .false.
239 is_upf = .true.
240 upf_pot => atom_ref%potential%upf_pot
241 CASE (no_pseudo)
242 IF (iw > 0) WRITE (iw, '(" No Pseudopotential available for transformation. ")')
243 do_transform = .false.
244 CASE DEFAULT
245 cpabort("Unknown ppot_type")
246 END SELECT
247
248 ! generate the transformed potentials
249 IF (do_transform) THEN
250 IF (is_ecp) THEN
251 CALL ecp_sgp_constr(ecp_pot, sgp_pot, atom_ref%basis)
252 ELSE IF (is_upf) THEN
253 CALL upf_sgp_constr(upf_pot, sgp_pot, atom_ref%basis)
254 ELSE
255 cpabort("Either ecp_pseudo or upf_pseudo is needed for atom_sgp_construction")
256 END IF
257 END IF
258
259 ! Check the result
260 IF (do_transform) THEN
261 NULLIFY (core, hnl)
262 CALL create_opmat(core, atom_ref%basis%nbas)
263 CALL create_opmat(hnl, atom_ref%basis%nbas, 5)
264 NULLIFY (score, shnl)
265 CALL create_opmat(score, atom_ref%basis%nbas)
266 CALL create_opmat(shnl, atom_ref%basis%nbas, 5)
267 !
268 ! upf has often very small grids, use a smooth cutoff function
269 IF (is_upf) THEN
270 n = SIZE(upf_pot%r)
271 ALLOCATE (cutpotu(n))
272 rcut = maxval(upf_pot%r)
273 CALL cutpot(cutpotu, upf_pot%r, rcut, 2.5_dp)
274 n = atom_ref%basis%grid%nr
275 ALLOCATE (cutpots(n))
276 CALL cutpot(cutpots, atom_ref%basis%grid%rad, rcut, 2.5_dp)
277 ELSE
278 n = atom_ref%basis%grid%nr
279 ALLOCATE (cutpots(n))
280 cutpots = 1.0_dp
281 END IF
282 !
283 IF (is_ecp) THEN
284 CALL ecpints(hnl%op, atom_ref%basis, ecp_pot)
285 ELSE IF (is_upf) THEN
286 CALL upfints(core%op, hnl%op, atom_ref%basis, upf_pot, cutpotu, sgp_pot%ac_local)
287 ELSE
288 cpabort("Either ecp_pseudo or upf_pseudo is needed for atom_sgp_construction")
289 END IF
290 !
291 CALL sgpints(score%op, shnl%op, atom_ref%basis, sgp_pot, cutpots)
292 !
293 IF (sgp_pot%has_local) THEN
294 n = min(3, ubound(core%op, 3))
295 errcc = maxval(abs(core%op(:, :, 0:n) - score%op(:, :, 0:n)))
296 IF (iw > 0) THEN
297 WRITE (iw, '(" Local part of pseudopotential")')
298 WRITE (iw, '(" Number of basis functions ",T77,i4)') sgp_pot%n_local
299 WRITE (iw, '(" Max. abs. error of matrix elements ",T65,f16.8)') errcc
300 END IF
301 END IF
302 IF (sgp_pot%has_nonlocal) THEN
303 IF (iw > 0) THEN
304 WRITE (iw, '(" Nonlocal part of pseudopotential")')
305 WRITE (iw, '(" Max. l-quantum number",T77,i4)') sgp_pot%lmax
306 WRITE (iw, '(" Number of projector basis functions ",T77,i4)') sgp_pot%n_nonlocal
307 DO i = 0, sgp_pot%lmax
308 errcc = maxval(abs(hnl%op(:, :, i) - shnl%op(:, :, i)))
309 WRITE (iw, '(" Max. abs. error of matrix elements: l=",i2,T69,f12.8)') i, errcc
310 END DO
311 END IF
312 END IF
313 IF (sgp_pot%has_nlcc) THEN
314 IF (is_upf) THEN
315 n = SIZE(upf_pot%r)
316 ALLOCATE (cgauss(n))
317 cgauss = 0.0_dp
318 DO i = 1, sgp_pot%n_nlcc
319 cgauss(:) = cgauss(:) + sgp_pot%c_nlcc(i)*exp(-sgp_pot%a_nlcc(i)*upf_pot%r(:)**2)
320 END DO
321 errcc = sum((cgauss(:) - upf_pot%rho_nlcc(:))**2*upf_pot%r(:)**2*upf_pot%rab(:))
322 errcc = sqrt(errcc/real(n, kind=dp))
323 DEALLOCATE (cgauss)
324 ELSE
325 cpabort("sgp_pot%has_nlcc requires is_upf")
326 END IF
327 IF (iw > 0) THEN
328 WRITE (iw, '(" Non-linear core correction: core density")')
329 WRITE (iw, '(" Number of basis functions ",T77,i4)') sgp_pot%n_nlcc
330 WRITE (iw, '(" RMS error of core density ",T69,f12.8)') errcc
331 END IF
332 END IF
333 !
334 IF (is_upf) THEN
335 DEALLOCATE (cutpotu)
336 DEALLOCATE (cutpots)
337 ELSE
338 DEALLOCATE (cutpots)
339 END IF
340 !
341 CALL release_opmat(score)
342 CALL release_opmat(shnl)
343 CALL release_opmat(core)
344 CALL release_opmat(hnl)
345 END IF
346
347 CALL atom_sgp_release(sgp_pot)
348
349 IF (iw > 0) WRITE (iw, '(" ",79("*"))')
350
351 END SUBROUTINE atom_sgp_construction
352
353! **************************************************************************************************
354!> \brief ...
355!> \param ecp_pot ...
356!> \param sgp_pot ...
357!> \param basis ...
358! **************************************************************************************************
359 SUBROUTINE ecp_sgp_constr(ecp_pot, sgp_pot, basis)
360
361 TYPE(atom_ecppot_type) :: ecp_pot
362 TYPE(atom_sgp_potential_type) :: sgp_pot
363 TYPE(atom_basis_type) :: basis
364
365 INTEGER :: i, ia, ir, j, k, l, n, na, nl, nr
366 REAL(kind=dp) :: alpha, amx, cmx
367 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: al, cl, cpot, pgauss
368 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: cmat, qmat, score, sinv, smat, tmat
369 REAL(kind=dp), DIMENSION(:), POINTER :: rad
370
371 sgp_pot%has_nlcc = .false.
372 sgp_pot%n_nlcc = 0
373 sgp_pot%has_local = .false.
374 sgp_pot%n_local = 0
375
376 ! transform semilocal potential into a separable local form
377 sgp_pot%has_nonlocal = .true.
378 !
379 ! hardcoded number of projectors (equal for all l values)
380 nl = 8
381 !
382 sgp_pot%n_nonlocal = nl
383 sgp_pot%lmax = ecp_pot%lmax
384 ALLOCATE (sgp_pot%a_nonlocal(nl))
385 ALLOCATE (sgp_pot%h_nonlocal(nl, 0:ecp_pot%lmax))
386 ALLOCATE (sgp_pot%c_nonlocal(nl, nl, 0:ecp_pot%lmax))
387 !
388 ALLOCATE (al(nl), cl(nl))
389 ALLOCATE (smat(nl, nl), sinv(nl, nl))
390 ALLOCATE (tmat(nl, nl), cmat(nl, nl))
391 al = 0.0_dp
392 amx = maxval(ecp_pot%bpot)
393 cmx = amx/0.15_dp
394 cmx = cmx**(1._dp/real(nl - 1, dp))
395 cmx = 1._dp/cmx
396 DO ir = 1, nl
397 al(ir) = amx*cmx**(ir - 1)
398 END DO
399 !
400 sgp_pot%a_nonlocal(1:nl) = al(1:nl)
401 !
402 nr = basis%grid%nr
403 rad => basis%grid%rad
404 ALLOCATE (cpot(nr), pgauss(nr))
405 DO l = 0, ecp_pot%lmax
406 na = basis%nbas(l)
407 ALLOCATE (score(na, na), qmat(na, nl))
408 cpot = 0._dp
409 DO k = 1, ecp_pot%npot(l)
410 n = ecp_pot%nrpot(k, l)
411 alpha = ecp_pot%bpot(k, l)
412 cpot(:) = cpot + ecp_pot%apot(k, l)*rad**(n - 2)*exp(-alpha*rad**2)
413 END DO
414 DO i = 1, na
415 DO j = i, na
416 score(i, j) = integrate_grid(cpot, basis%bf(:, i, l), basis%bf(:, j, l), basis%grid)
417 score(j, i) = score(i, j)
418 END DO
419 END DO
420 ! overlap basis with projectors
421 DO i = 1, nl
422 pgauss(:) = exp(-al(i)*rad(:)**2)*rad(:)**l
423 DO ia = 1, na
424 qmat(ia, i) = integrate_grid(basis%bf(:, ia, l), pgauss(:), basis%grid)
425 END DO
426 END DO
427 qmat = sqrt(fourpi)*qmat
428 ! tmat = qmat * score * qmat
429 tmat(1:nl, 1:nl) = matmul(transpose(qmat(1:na, 1:nl)), matmul(score(1:na, 1:na), qmat(1:na, 1:nl)))
430 smat(1:nl, 1:nl) = matmul(transpose(qmat(1:na, 1:nl)), qmat(1:na, 1:nl))
431 CALL get_pseudo_inverse_diag(smat(1:nl, 1:nl), sinv(1:nl, 1:nl), 1.e-10_dp)
432 cmat(1:nl, 1:nl) = matmul(sinv(1:nl, 1:nl), matmul(tmat(1:nl, 1:nl), sinv(1:nl, 1:nl)))
433 cmat(1:nl, 1:nl) = (cmat(1:nl, 1:nl) + transpose(cmat(1:nl, 1:nl)))*0.5_dp
434 !
435 ! Residium
436 !
437 CALL diamat_all(cmat(1:nl, 1:nl), cl(1:nl), .true.)
438 !
439 sgp_pot%h_nonlocal(1:nl, l) = cl(1:nl)
440 sgp_pot%c_nonlocal(1:nl, 1:nl, l) = cmat(1:nl, 1:nl)
441 sgp_pot%is_nonlocal(l) = .true.
442 !
443 DEALLOCATE (score, qmat)
444 END DO
445 DEALLOCATE (cpot, pgauss)
446 DEALLOCATE (al, cl, smat, sinv, tmat, cmat)
447
448 END SUBROUTINE ecp_sgp_constr
449
450! **************************************************************************************************
451!> \brief ...
452!> \param upf_pot ...
453!> \param sgp_pot ...
454!> \param basis ...
455! **************************************************************************************************
456 SUBROUTINE upf_sgp_constr(upf_pot, sgp_pot, basis)
457
458 TYPE(atom_upfpot_type) :: upf_pot
459 TYPE(atom_sgp_potential_type) :: sgp_pot
460 TYPE(atom_basis_type) :: basis
461
462 CHARACTER(len=4) :: ptype
463 INTEGER :: ia, ib, ipa, ipb, ir, la, lb, na, nl, &
464 np, nr
465 LOGICAL :: nl_trans
466 REAL(kind=dp) :: cpa, cpb, eee, ei, errloc, rc, x(2), zval
467 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: al, cl, pgauss, pproa, pprob, vgauss, &
468 vloc, ww
469 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: cmat, qmat, score, sinv, smat, tmat
470 TYPE(atom_basis_type) :: gbasis
471 TYPE(opt_state_type) :: ostate
472
473 IF (upf_pot%is_ultrasoft .OR. upf_pot%is_paw .OR. upf_pot%is_coulomb) THEN
474 sgp_pot%has_nonlocal = .false.
475 sgp_pot%n_nonlocal = 0
476 sgp_pot%has_local = .false.
477 sgp_pot%n_local = 0
478 sgp_pot%has_nlcc = .false.
479 sgp_pot%n_nlcc = 0
480 RETURN
481 END IF
482
483 ! radial grid
484 nr = SIZE(upf_pot%r)
485 ! weights for integration
486 ALLOCATE (ww(nr))
487 ww(:) = upf_pot%r(:)**2*upf_pot%rab(:)
488
489 ! start with local potential
490 sgp_pot%has_local = .true.
491 ! fit local potential to Gaussian form
492 ALLOCATE (vloc(nr), vgauss(nr))
493 ! smearing of core charge
494 zval = upf_pot%zion
495 ! Try to find an optimal Gaussian charge distribution
496 CALL erffit(sgp_pot%ac_local, upf_pot%vlocal, upf_pot%r, zval)
497 sgp_pot%zval = zval
498 DO ir = 1, nr
499 IF (upf_pot%r(ir) < 1.e-12_dp) THEN
500 vgauss(ir) = -sqrt(2.0_dp)*zval/rootpi/sgp_pot%ac_local
501 ELSE
502 rc = upf_pot%r(ir)/sgp_pot%ac_local/sqrt(2.0_dp)
503 vgauss(ir) = -zval/upf_pot%r(ir)*erf(rc)
504 END IF
505 END DO
506 vloc(:) = upf_pot%vlocal(:) - vgauss(:)
507 !
508 CALL atom_basis_gridrep(basis, gbasis, upf_pot%r, upf_pot%rab)
509 !
510 nl = 12
511 ALLOCATE (al(nl), cl(nl))
512 ostate%nf = 0
513 ostate%nvar = 2
514 x(1) = 1.00_dp !starting point of geometric series
515 x(2) = 1.20_dp !factor of series
516 ostate%rhoend = 1.e-12_dp
517 ostate%rhobeg = 5.e-2_dp
518 ostate%maxfun = 1000
519 ostate%iprint = 1
520 ostate%unit = -1
521 ostate%state = 0
522 DO
523 IF (ostate%state == 2) THEN
524 DO ir = 1, nl
525 al(ir) = x(1)*x(2)**(ir - 1)
526 END DO
527 CALL pplocal_error(nl, al, cl, vloc, vgauss, gbasis, upf_pot%r, ww, 1, ostate%f)
528 END IF
529 IF (ostate%state == -1) EXIT
530 CALL powell_optimize(ostate%nvar, x, ostate)
531 END DO
532 ostate%state = 8
533 CALL powell_optimize(ostate%nvar, x, ostate)
534 DO ir = 1, nl
535 al(ir) = x(1)*x(2)**(ir - 1)
536 END DO
537 CALL pplocal_error(nl, al, cl, vloc, vgauss, gbasis, upf_pot%r, ww, 1, errloc)
538 !
539 ALLOCATE (sgp_pot%a_local(nl), sgp_pot%c_local(nl))
540 sgp_pot%n_local = nl
541 sgp_pot%a_local(1:nl) = al(1:nl)
542 sgp_pot%c_local(1:nl) = cl(1:nl)
543 DEALLOCATE (vloc, vgauss)
544 DEALLOCATE (al, cl)
545 CALL release_atom_basis(gbasis)
546 !
547 ptype = adjustl(trim(upf_pot%pseudo_type))
548 IF (ptype(1:2) == "NC" .OR. ptype(1:2) == "US") THEN
549 nl_trans = .false.
550 ELSE IF (ptype(1:2) == "SL") THEN
551 nl_trans = .true.
552 ELSE
553 cpabort("Pseudopotential type: ["//adjustl(trim(ptype))//"] not known")
554 END IF
555
556 ! purely local pseudopotentials
557 IF (upf_pot%l_max < 0) THEN
558 sgp_pot%n_nonlocal = 0
559 sgp_pot%lmax = -1
560 sgp_pot%has_nonlocal = .false.
561 ELSE
562 ! Non-local pseudopotential in Gaussian form
563 IF (nl_trans) THEN
564 sgp_pot%has_nonlocal = .true.
565 ! semi local pseudopotential
566 ! fit to nonlocal form
567 ! get basis representation on UPF grid
568 nl = 8
569 !
570 sgp_pot%n_nonlocal = nl
571 sgp_pot%lmax = upf_pot%l_max
572 ALLOCATE (sgp_pot%a_nonlocal(nl))
573 ALLOCATE (sgp_pot%h_nonlocal(nl, 0:upf_pot%l_max))
574 ALLOCATE (sgp_pot%c_nonlocal(nl, nl, 0:upf_pot%l_max))
575 !
576 ALLOCATE (al(nl), cl(nl))
577 ALLOCATE (smat(nl, nl), sinv(nl, nl))
578 ALLOCATE (tmat(nl, nl), cmat(nl, nl))
579 al = 0.0_dp
580 DO ir = 1, nl
581 al(ir) = 10.0_dp*0.60_dp**(ir - 1)
582 END DO
583 !
584 sgp_pot%a_nonlocal(1:nl) = al(1:nl)
585 !
586 CALL atom_basis_gridrep(basis, gbasis, upf_pot%r, upf_pot%rab)
587 ALLOCATE (pgauss(nr), vloc(nr))
588 DO la = 0, upf_pot%l_max
589 IF (la == upf_pot%l_local) cycle
590 sgp_pot%is_nonlocal(la) = .true.
591 na = gbasis%nbas(la)
592 ALLOCATE (score(na, na), qmat(na, nl))
593 ! Reference matrix
594 vloc(:) = upf_pot%vsemi(:, la + 1) - upf_pot%vlocal(:)
595 DO ia = 1, na
596 DO ib = ia, na
597 score(ia, ib) = sum(vloc(:)*gbasis%bf(:, ia, la)*gbasis%bf(:, ib, la)*ww(:))
598 score(ib, ia) = score(ia, ib)
599 END DO
600 END DO
601 ! overlap basis with projectors
602 DO ir = 1, nl
603 pgauss(:) = exp(-al(ir)*upf_pot%r(:)**2)*upf_pot%r(:)**la
604 eee = rootpi/(2._dp**(la + 2)*dfac(2*la + 1))/(2._dp*al(ir))**(la + 1.5_dp)
605 pgauss(:) = pgauss(:)/sqrt(eee)
606 DO ia = 1, na
607 qmat(ia, ir) = sum(gbasis%bf(:, ia, la)*pgauss(:)*ww)
608 END DO
609 END DO
610 ! tmat = qmat * score * qmat
611 tmat(1:nl, 1:nl) = matmul(transpose(qmat(1:na, 1:nl)), matmul(score(1:na, 1:na), qmat(1:na, 1:nl)))
612 smat(1:nl, 1:nl) = matmul(transpose(qmat(1:na, 1:nl)), qmat(1:na, 1:nl))
613 CALL get_pseudo_inverse_diag(smat(1:nl, 1:nl), sinv(1:nl, 1:nl), 1.e-10_dp)
614 cmat(1:nl, 1:nl) = matmul(sinv(1:nl, 1:nl), matmul(tmat(1:nl, 1:nl), sinv(1:nl, 1:nl)))
615 cmat(1:nl, 1:nl) = (cmat(1:nl, 1:nl) + transpose(cmat(1:nl, 1:nl)))*0.5_dp
616 CALL diamat_all(cmat(1:nl, 1:nl), cl(1:nl), .true.)
617 !
618 ! get back unnormalized Gaussians
619 DO ir = 1, nl
620 ei = rootpi/(2._dp**(la + 2)*dfac(2*la + 1))/(2._dp*al(ir))**(la + 1.5_dp)
621 cmat(ir, 1:nl) = cmat(ir, 1:nl)/sqrt(ei)
622 END DO
623 sgp_pot%h_nonlocal(1:nl, la) = cl(1:nl)
624 sgp_pot%c_nonlocal(1:nl, 1:nl, la) = cmat(1:nl, 1:nl)
625 sgp_pot%is_nonlocal(la) = .true.
626 DEALLOCATE (score, qmat)
627 END DO
628 ! SQRT(4PI)
629 sgp_pot%c_nonlocal = sgp_pot%c_nonlocal/sqrt(fourpi)
630 CALL release_atom_basis(gbasis)
631 DEALLOCATE (pgauss, vloc)
632 DEALLOCATE (al, cl, smat, sinv, tmat, cmat)
633 ELSE
634 sgp_pot%has_nonlocal = .true.
635 ! non local pseudopotential
636 ALLOCATE (pproa(nr), pprob(nr), pgauss(nr))
637 np = upf_pot%number_of_proj
638 nl = 8
639 ALLOCATE (al(nl), cl(nl))
640 ALLOCATE (smat(nl, nl), sinv(nl, nl))
641 ALLOCATE (tmat(nl, nl), cmat(nl, nl))
642 al = 0.0_dp
643 cl = 0.0_dp
644 DO ir = 1, nl
645 al(ir) = 10.0_dp*0.60_dp**(ir - 1)
646 END DO
647 !
648 sgp_pot%lmax = maxval(upf_pot%lbeta(:))
649 sgp_pot%n_nonlocal = nl
650 ALLOCATE (sgp_pot%a_nonlocal(nl))
651 ALLOCATE (sgp_pot%h_nonlocal(nl, 0:sgp_pot%lmax))
652 ALLOCATE (sgp_pot%c_nonlocal(nl, nl, 0:sgp_pot%lmax))
653 !
654 sgp_pot%a_nonlocal(1:nl) = al(1:nl)
655 !
656 CALL atom_basis_gridrep(basis, gbasis, upf_pot%r, upf_pot%rab)
657 DO la = 0, sgp_pot%lmax
658 sgp_pot%is_nonlocal(la) = .true.
659 na = gbasis%nbas(la)
660 ALLOCATE (score(na, na), qmat(na, nl))
661 ! Reference matrix
662 score = 0.0_dp
663 DO ipa = 1, np
664 lb = upf_pot%lbeta(ipa)
665 IF (la /= lb) cycle
666 pproa(:) = upf_pot%beta(:, ipa)
667 DO ipb = 1, np
668 lb = upf_pot%lbeta(ipb)
669 IF (la /= lb) cycle
670 pprob(:) = upf_pot%beta(:, ipb)
671 eee = upf_pot%dion(ipa, ipb)
672 DO ia = 1, na
673 cpa = sum(pproa(:)*gbasis%bf(:, ia, la)*ww(:))
674 DO ib = ia, na
675 cpb = sum(pprob(:)*gbasis%bf(:, ib, la)*ww(:))
676 score(ia, ib) = score(ia, ib) + cpa*eee*cpb
677 score(ib, ia) = score(ia, ib)
678 END DO
679 END DO
680 END DO
681 END DO
682 ! overlap basis with projectors
683 DO ir = 1, nl
684 pgauss(:) = exp(-al(ir)*upf_pot%r(:)**2)*upf_pot%r(:)**la
685 eee = rootpi/(2._dp**(la + 2)*dfac(2*la + 1))/(2._dp*al(ir))**(la + 1.5_dp)
686 pgauss(:) = pgauss(:)/sqrt(eee)
687 DO ia = 1, na
688 qmat(ia, ir) = sum(gbasis%bf(:, ia, la)*pgauss(:)*ww)
689 END DO
690 END DO
691 ! tmat = qmat * score * qmat
692 tmat(1:nl, 1:nl) = matmul(transpose(qmat(1:na, 1:nl)), matmul(score(1:na, 1:na), qmat(1:na, 1:nl)))
693 smat(1:nl, 1:nl) = matmul(transpose(qmat(1:na, 1:nl)), qmat(1:na, 1:nl))
694 CALL get_pseudo_inverse_diag(smat(1:nl, 1:nl), sinv(1:nl, 1:nl), 1.e-10_dp)
695 cmat(1:nl, 1:nl) = matmul(sinv(1:nl, 1:nl), matmul(tmat(1:nl, 1:nl), sinv(1:nl, 1:nl)))
696 cmat(1:nl, 1:nl) = (cmat(1:nl, 1:nl) + transpose(cmat(1:nl, 1:nl)))*0.5_dp
697 CALL diamat_all(cmat(1:nl, 1:nl), cl(1:nl), .true.)
698 !
699 ! get back unnormalized Gaussians
700 DO ir = 1, nl
701 ei = rootpi/(2._dp**(la + 2)*dfac(2*la + 1))/(2._dp*al(ir))**(la + 1.5_dp)
702 cmat(ir, 1:nl) = cmat(ir, 1:nl)/sqrt(ei)
703 END DO
704 sgp_pot%h_nonlocal(1:nl, la) = cl(1:nl)
705 sgp_pot%c_nonlocal(1:nl, 1:nl, la) = cmat(1:nl, 1:nl)
706 sgp_pot%is_nonlocal(la) = .true.
707 DEALLOCATE (score, qmat)
708 END DO
709 ! SQRT(4PI)
710 sgp_pot%c_nonlocal = sgp_pot%c_nonlocal/sqrt(fourpi)
711 CALL release_atom_basis(gbasis)
712 DEALLOCATE (pgauss, pproa, pprob)
713 DEALLOCATE (al, cl, smat, sinv, tmat, cmat)
714 END IF
715 END IF
716
717 IF (upf_pot%core_correction) THEN
718 sgp_pot%has_nlcc = .true.
719 ELSE
720 sgp_pot%has_nlcc = .false.
721 sgp_pot%n_nlcc = 0
722 END IF
723
724 ! fit core charge to Gaussian form
725 IF (sgp_pot%has_nlcc) THEN
726 CALL fit_core_density_gaussians(upf_pot%r, upf_pot%rab, upf_pot%rho_nlcc, al, cl)
727 sgp_pot%n_nlcc = SIZE(al)
728 ALLOCATE (sgp_pot%a_nlcc, source=al)
729 ALLOCATE (sgp_pot%c_nlcc, source=cl)
730 DEALLOCATE (al, cl)
731 END IF
732
733 DEALLOCATE (ww)
734
735 END SUBROUTINE upf_sgp_constr
736
737! **************************************************************************************************
738!> \brief Fit a tabulated core density without forming ill-conditioned normal equations.
739!> Column-normalized, radial least squares use a direct SVD. A broad Gaussian
740!> sequence resolves both the core and its smooth tail. Zero-density samples
741!> beyond the tabulated mesh prevent an unconstrained diffuse continuation.
742!> \param r Radial grid in bohr.
743!> \param rab Radial mesh Jacobian dr/dj.
744!> \param rho True spherical density (without the 4*pi*r**2 prefactor).
745!> \param alpha Gaussian exponents in inverse square bohr.
746!> \param coeff Coefficients multiplying exp(-alpha*r**2).
747! **************************************************************************************************
748 SUBROUTINE fit_core_density_gaussians(r, rab, rho, alpha, coeff)
749 REAL(dp), INTENT(IN) :: r(:), rab(:), rho(:)
750 REAL(dp), ALLOCATABLE, INTENT(OUT) :: alpha(:), coeff(:)
751
752 INTEGER, PARAMETER :: ng = 48, ntail = 200
753 REAL(dp), PARAMETER :: amax = 300.0_dp, amin = 0.03_dp, &
754 rcond = 1.e-12_dp
755
756 INTEGER :: i, info, lwork, m, nr, rank
757 REAL(dp) :: dr, extent, norms(ng), singular(ng), &
758 work_query(1)
759 REAL(dp), ALLOCATABLE :: matrix(:, :), rhs(:, :), rr(:), sw(:), &
760 work(:)
761
762 nr = SIZE(r)
763 cpassert(nr >= 2 .AND. SIZE(rab) == nr .AND. SIZE(rho) == nr)
764 cpassert(all(r >= 0.0_dp) .AND. all(rab > 0.0_dp))
765 cpassert(all(r(2:) > r(:nr - 1)))
766 m = nr + ntail
767 ALLOCATE (alpha(ng), coeff(ng), matrix(m, ng), rhs(m, 1), rr(m), sw(m))
768 rr(:nr) = r
769 sw(:nr) = r*sqrt(rab)
770 ! At 50 bohr even the most diffuse fitting Gaussian is below exp(-75).
771 extent = max(r(nr) + 1.0_dp, 50.0_dp)
772 dr = (extent - r(nr))/real(ntail, dp)
773 DO i = 1, ntail
774 rr(nr + i) = r(nr) + real(i, dp)*dr
775 sw(nr + i) = rr(nr + i)*sqrt(dr)
776 END DO
777 sw(m) = sw(m)/sqrt(2.0_dp)
778 rhs = 0.0_dp
779 rhs(:nr, 1) = rho*sw(:nr)
780 DO i = 1, ng
781 alpha(i) = amin*exp(log(amax/amin)*real(i - 1, dp)/real(ng - 1, dp))
782 matrix(:, i) = exp(-alpha(i)*rr**2)*sw
783 norms(i) = sqrt(sum(matrix(:, i)**2))
784 cpassert(norms(i) > 0.0_dp)
785 matrix(:, i) = matrix(:, i)/norms(i)
786 END DO
787 CALL dgelss(m, ng, 1, matrix, m, rhs, m, singular, rcond, rank, work_query, -1, info)
788 cpassert(info == 0)
789 lwork = max(1, ceiling(work_query(1)))
790 ALLOCATE (work(lwork))
791 CALL dgelss(m, ng, 1, matrix, m, rhs, m, singular, rcond, rank, work, lwork, info)
792 IF (info /= 0) cpabort("SVD failed while fitting the UPF core density")
793 coeff(:) = rhs(:ng, 1)/norms
794 END SUBROUTINE fit_core_density_gaussians
795
796! **************************************************************************************************
797!> \brief ...
798!> \param sgp_pot ...
799! **************************************************************************************************
800 SUBROUTINE atom_sgp_release(sgp_pot)
801
802 TYPE(atom_sgp_potential_type) :: sgp_pot
803
804 IF (ASSOCIATED(sgp_pot%a_nonlocal)) DEALLOCATE (sgp_pot%a_nonlocal)
805 IF (ASSOCIATED(sgp_pot%h_nonlocal)) DEALLOCATE (sgp_pot%h_nonlocal)
806 IF (ASSOCIATED(sgp_pot%c_nonlocal)) DEALLOCATE (sgp_pot%c_nonlocal)
807
808 IF (ASSOCIATED(sgp_pot%a_local)) DEALLOCATE (sgp_pot%a_local)
809 IF (ASSOCIATED(sgp_pot%c_local)) DEALLOCATE (sgp_pot%c_local)
810
811 IF (ASSOCIATED(sgp_pot%a_nlcc)) DEALLOCATE (sgp_pot%a_nlcc)
812 IF (ASSOCIATED(sgp_pot%c_nlcc)) DEALLOCATE (sgp_pot%c_nlcc)
813
814 sgp_pot = atom_sgp_potential_type()
815
816 END SUBROUTINE atom_sgp_release
817
818! **************************************************************************************************
819!> \brief ...
820!> \param core ...
821!> \param hnl ...
822!> \param basis ...
823!> \param upf_pot ...
824!> \param cutpotu ...
825!> \param ac_local ...
826! **************************************************************************************************
827 SUBROUTINE upfints(core, hnl, basis, upf_pot, cutpotu, ac_local)
828 REAL(kind=dp), DIMENSION(:, :, 0:) :: core, hnl
829 TYPE(atom_basis_type), INTENT(INOUT) :: basis
830 TYPE(atom_upfpot_type) :: upf_pot
831 REAL(kind=dp), DIMENSION(:), INTENT(IN) :: cutpotu
832 REAL(kind=dp), INTENT(IN) :: ac_local
833
834 CHARACTER(len=4) :: ptype
835 INTEGER :: i, j, k1, k2, la, lb, m, n
836 REAL(kind=dp) :: rc, zval
837 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: spot
838 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: spmat
839 TYPE(atom_basis_type) :: gbasis
840
841 ! get basis representation on UPF grid
842 CALL atom_basis_gridrep(basis, gbasis, upf_pot%r, upf_pot%rab)
843
844 ! local pseudopotential
845 core = 0._dp
846 n = SIZE(upf_pot%r)
847 ALLOCATE (spot(n))
848 spot(:) = upf_pot%vlocal(:)
849 zval = upf_pot%zion
850 DO i = 1, n
851 IF (upf_pot%r(i) < 1.e-12_dp) THEN
852 spot(i) = spot(i) + sqrt2*zval/rootpi/ac_local
853 ELSE
854 rc = upf_pot%r(i)/ac_local/sqrt2
855 spot(i) = spot(i) + zval/upf_pot%r(i)*erf(rc)
856 END IF
857 END DO
858 spot(:) = spot(:)*cutpotu(:)
859
860 CALL numpot_matrix(core, spot, gbasis, 0)
861 DEALLOCATE (spot)
862
863 hnl = 0._dp
864 ptype = adjustl(trim(upf_pot%pseudo_type))
865 IF (ptype(1:2) == "NC" .OR. ptype(1:2) == "US") THEN
866 ! non local pseudopotential
867 n = maxval(gbasis%nbas(:))
868 m = upf_pot%number_of_proj
869 ALLOCATE (spmat(n, m))
870 spmat = 0.0_dp
871 DO i = 1, m
872 la = upf_pot%lbeta(i)
873 DO j = 1, gbasis%nbas(la)
874 spmat(j, i) = integrate_grid(upf_pot%beta(:, i), gbasis%bf(:, j, la), gbasis%grid)
875 END DO
876 END DO
877 DO i = 1, m
878 la = upf_pot%lbeta(i)
879 DO j = 1, m
880 lb = upf_pot%lbeta(j)
881 IF (la == lb) THEN
882 DO k1 = 1, gbasis%nbas(la)
883 DO k2 = 1, gbasis%nbas(la)
884 hnl(k1, k2, la) = hnl(k1, k2, la) + spmat(k1, i)*upf_pot%dion(i, j)*spmat(k2, j)
885 END DO
886 END DO
887 END IF
888 END DO
889 END DO
890 DEALLOCATE (spmat)
891 ELSE IF (ptype(1:2) == "SL") THEN
892 ! semi local pseudopotential
893 DO la = 0, upf_pot%l_max
894 IF (la == upf_pot%l_local) cycle
895 m = SIZE(upf_pot%vsemi(:, la + 1))
896 ALLOCATE (spot(m))
897 spot(:) = upf_pot%vsemi(:, la + 1) - upf_pot%vlocal(:)
898 spot(:) = spot(:)*cutpotu(:)
899 n = basis%nbas(la)
900 DO i = 1, n
901 DO j = i, n
902 hnl(i, j, la) = hnl(i, j, la) + &
903 integrate_grid(spot(:), &
904 gbasis%bf(:, i, la), gbasis%bf(:, j, la), gbasis%grid)
905 hnl(j, i, la) = hnl(i, j, la)
906 END DO
907 END DO
908 DEALLOCATE (spot)
909 END DO
910 ELSE
911 cpabort("Pseudopotential type: ["//adjustl(trim(ptype))//"] not known")
912 END IF
913
914 ! release basis representation on UPF grid
915 CALL release_atom_basis(gbasis)
916
917 END SUBROUTINE upfints
918
919! **************************************************************************************************
920!> \brief ...
921!> \param hnl ...
922!> \param basis ...
923!> \param ecp_pot ...
924! **************************************************************************************************
925 SUBROUTINE ecpints(hnl, basis, ecp_pot)
926 REAL(kind=dp), DIMENSION(:, :, 0:) :: hnl
927 TYPE(atom_basis_type), INTENT(INOUT) :: basis
928 TYPE(atom_ecppot_type) :: ecp_pot
929
930 INTEGER :: i, j, k, l, m, n
931 REAL(kind=dp) :: alpha
932 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: cpot
933 REAL(kind=dp), DIMENSION(:), POINTER :: rad
934
935 rad => basis%grid%rad
936 m = basis%grid%nr
937 ALLOCATE (cpot(1:m))
938
939 ! non local pseudopotential
940 hnl = 0.0_dp
941 DO l = 0, ecp_pot%lmax
942 cpot = 0._dp
943 DO k = 1, ecp_pot%npot(l)
944 n = ecp_pot%nrpot(k, l)
945 alpha = ecp_pot%bpot(k, l)
946 cpot(:) = cpot(:) + ecp_pot%apot(k, l)*rad(:)**(n - 2)*exp(-alpha*rad(:)**2)
947 END DO
948 DO i = 1, basis%nbas(l)
949 DO j = i, basis%nbas(l)
950 hnl(i, j, l) = integrate_grid(cpot, basis%bf(:, i, l), basis%bf(:, j, l), basis%grid)
951 hnl(j, i, l) = hnl(i, j, l)
952 END DO
953 END DO
954 END DO
955 DEALLOCATE (cpot)
956
957 END SUBROUTINE ecpints
958
959! **************************************************************************************************
960!> \brief ...
961!> \param core ...
962!> \param hnl ...
963!> \param basis ...
964!> \param sgp_pot ...
965!> \param cutpots ...
966! **************************************************************************************************
967 SUBROUTINE sgpints(core, hnl, basis, sgp_pot, cutpots)
968 REAL(kind=dp), DIMENSION(:, :, 0:) :: core, hnl
969 TYPE(atom_basis_type), INTENT(INOUT) :: basis
970 TYPE(atom_sgp_potential_type) :: sgp_pot
971 REAL(kind=dp), DIMENSION(:), INTENT(IN) :: cutpots
972
973 INTEGER :: i, ia, j, l, m, n, na
974 REAL(kind=dp) :: a, zval
975 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: cpot, pgauss
976 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: qmat
977 REAL(kind=dp), DIMENSION(:), POINTER :: rad
978
979 rad => basis%grid%rad
980 m = basis%grid%nr
981
982 ! local pseudopotential
983 ALLOCATE (cpot(m))
984 IF (sgp_pot%has_local) THEN
985 zval = sgp_pot%zval
986 core = 0._dp
987 cpot = 0.0_dp
988 DO i = 1, sgp_pot%n_local
989 cpot(:) = cpot(:) + sgp_pot%c_local(i)*exp(-sgp_pot%a_local(i)*rad(:)**2)
990 END DO
991 cpot(:) = cpot(:)*cutpots(:)
992 CALL numpot_matrix(core, cpot, basis, 0)
993 END IF
994 DEALLOCATE (cpot)
995
996 ! nonlocal pseudopotential
997 IF (sgp_pot%has_nonlocal) THEN
998 hnl = 0.0_dp
999 ALLOCATE (pgauss(1:m))
1000 n = sgp_pot%n_nonlocal
1001 !
1002 DO l = 0, sgp_pot%lmax
1003 cpassert(l <= ubound(basis%nbas, 1))
1004 IF (.NOT. sgp_pot%is_nonlocal(l)) cycle
1005 ! overlap (a|p)
1006 na = basis%nbas(l)
1007 ALLOCATE (qmat(na, n))
1008 DO i = 1, n
1009 a = sgp_pot%a_nonlocal(i)
1010 pgauss(:) = cutpots(:)*exp(-a*rad(:)**2)*rad(:)**l
1011 DO ia = 1, na
1012 qmat(ia, i) = integrate_grid(basis%bf(:, ia, l), pgauss(:), basis%grid)
1013 END DO
1014 END DO
1015 qmat(1:na, 1:n) = sqrt(fourpi)*matmul(qmat(1:na, 1:n), sgp_pot%c_nonlocal(1:n, 1:n, l))
1016 DO i = 1, na
1017 DO j = i, na
1018 DO ia = 1, n
1019 hnl(i, j, l) = hnl(i, j, l) + qmat(i, ia)*qmat(j, ia)*sgp_pot%h_nonlocal(ia, l)
1020 END DO
1021 hnl(j, i, l) = hnl(i, j, l)
1022 END DO
1023 END DO
1024 DEALLOCATE (qmat)
1025 END DO
1026 DEALLOCATE (pgauss)
1027 END IF
1028
1029 END SUBROUTINE sgpints
1030
1031! **************************************************************************************************
1032!> \brief ...
1033!> \param ac ...
1034!> \param vlocal ...
1035!> \param r ...
1036!> \param z ...
1037! **************************************************************************************************
1038 SUBROUTINE erffit(ac, vlocal, r, z)
1039 REAL(kind=dp), INTENT(OUT) :: ac
1040 REAL(kind=dp), DIMENSION(:), INTENT(IN) :: vlocal, r
1041 REAL(kind=dp), INTENT(IN) :: z
1042
1043 REAL(kind=dp), PARAMETER :: rcut = 1.4_dp
1044
1045 INTEGER :: i, j, m, m1
1046 REAL(kind=dp) :: a1, a2, an, e2, en, rc
1047 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: epot, rval, vpot
1048
1049 m = SIZE(r)
1050 ALLOCATE (epot(m), vpot(m), rval(m))
1051 cpassert(SIZE(vlocal) == m)
1052 IF (r(1) > r(m)) THEN
1053 DO i = 1, m
1054 vpot(m - i + 1) = vlocal(i)
1055 rval(m - i + 1) = r(i)
1056 END DO
1057 ELSE
1058 vpot(1:m) = vlocal(1:m)
1059 rval(1:m) = r(1:m)
1060 END IF
1061 m1 = 1
1062 DO i = 1, m
1063 IF (rval(i) > rcut) THEN
1064 m1 = i
1065 EXIT
1066 END IF
1067 END DO
1068
1069 a1 = 0.2_dp
1070 a2 = 0.2_dp
1071 e2 = 1.e20_dp
1072 epot = 0.0_dp
1073 DO i = 0, 20
1074 an = a1 + i*0.025_dp
1075 rc = 1._dp/(an*sqrt(2.0_dp))
1076 DO j = m1, m
1077 epot(j) = vpot(j) + z/rval(j)*erf(rval(j)*rc)
1078 END DO
1079 en = sum(abs(epot(m1:m)*rval(m1:m)**2))
1080 IF (en < e2) THEN
1081 e2 = en
1082 a2 = an
1083 END IF
1084 END DO
1085 ac = a2
1086
1087 DEALLOCATE (epot, vpot, rval)
1088
1089 END SUBROUTINE erffit
1090
1091! **************************************************************************************************
1092!> \brief ...
1093!> \param nl ...
1094!> \param al ...
1095!> \param cl ...
1096!> \param vloc ...
1097!> \param vgauss ...
1098!> \param gbasis ...
1099!> \param rad ...
1100!> \param ww ...
1101!> \param method ...
1102!> \param errloc ...
1103! **************************************************************************************************
1104 SUBROUTINE pplocal_error(nl, al, cl, vloc, vgauss, gbasis, rad, ww, method, errloc)
1105 INTEGER :: nl
1106 REAL(kind=dp), DIMENSION(:) :: al, cl, vloc, vgauss
1107 TYPE(atom_basis_type) :: gbasis
1108 REAL(kind=dp), DIMENSION(:) :: rad, ww
1109 INTEGER, INTENT(IN) :: method
1110 REAL(kind=dp) :: errloc
1111
1112 INTEGER :: ia, ib, ir, ix, la, na
1113 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: tv
1114 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: rmat, sinv, smat
1115 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: gmat
1116
1117 cl = 0.0_dp
1118 IF (method == 1) THEN
1119 ALLOCATE (tv(nl), smat(nl, nl), sinv(nl, nl))
1120 DO ir = 1, nl
1121 vgauss(:) = exp(-al(ir)*rad(:)**2)
1122 DO ix = 1, nl
1123 smat(ir, ix) = sum(vgauss(:)*exp(-al(ix)*rad(:)**2)*ww(:))
1124 END DO
1125 tv(ir) = sum(vloc(:)*vgauss(:)*ww(:))
1126 END DO
1127 CALL get_pseudo_inverse_diag(smat(1:nl, 1:nl), sinv(1:nl, 1:nl), 1.e-12_dp)
1128 cl(1:nl) = matmul(sinv(1:nl, 1:nl), tv(1:nl))
1129 ELSE
1130 !
1131 ALLOCATE (tv(nl), smat(nl, nl), sinv(nl, nl))
1132 !
1133 smat = 0.0_dp
1134 tv = 0.0_dp
1135 DO la = 0, min(ubound(gbasis%nbas, 1), 3)
1136 na = gbasis%nbas(la)
1137 ALLOCATE (rmat(na, na), gmat(na, na, nl))
1138 rmat = 0.0_dp
1139 gmat = 0.0_dp
1140 DO ia = 1, na
1141 DO ib = ia, na
1142 rmat(ia, ib) = sum(gbasis%bf(:, ia, la)*gbasis%bf(:, ib, la)*vloc(:)*ww(:))
1143 rmat(ib, ia) = rmat(ia, ib)
1144 END DO
1145 END DO
1146 DO ir = 1, nl
1147 vgauss(:) = exp(-al(ir)*rad(:)**2)
1148 DO ia = 1, na
1149 DO ib = ia, na
1150 gmat(ia, ib, ir) = sum(gbasis%bf(:, ia, la)*gbasis%bf(:, ib, la)*vgauss(:)*ww(:))
1151 gmat(ib, ia, ir) = gmat(ia, ib, ir)
1152 END DO
1153 END DO
1154 END DO
1155 DO ir = 1, nl
1156 tv(ir) = tv(ir) + accurate_dot_product(rmat, gmat(:, :, ir))
1157 DO ix = ir, nl
1158 smat(ir, ix) = smat(ir, ix) + accurate_dot_product(gmat(:, :, ix), gmat(:, :, ir))
1159 smat(ix, ir) = smat(ir, ix)
1160 END DO
1161 END DO
1162 DEALLOCATE (rmat, gmat)
1163 END DO
1164 sinv = 0.0_dp
1165 CALL get_pseudo_inverse_diag(smat(1:nl, 1:nl), sinv(1:nl, 1:nl), 1.e-12_dp)
1166 cl(1:nl) = matmul(sinv(1:nl, 1:nl), tv(1:nl))
1167 END IF
1168 !
1169 vgauss = 0.0_dp
1170 DO ir = 1, nl
1171 vgauss(:) = vgauss(:) + cl(ir)*exp(-al(ir)*rad(:)**2)
1172 END DO
1173 errloc = sum((vgauss - vloc)**2*ww)
1174 !
1175 DEALLOCATE (tv, smat, sinv)
1176 !
1177 END SUBROUTINE pplocal_error
1178
1179! **************************************************************************************************
1180!> \brief ...
1181!> \param pot ...
1182!> \param r ...
1183!> \param rcut ...
1184!> \param rsmooth ...
1185! **************************************************************************************************
1186 SUBROUTINE cutpot(pot, r, rcut, rsmooth)
1187 REAL(kind=dp), DIMENSION(:), INTENT(INOUT) :: pot
1188 REAL(kind=dp), DIMENSION(:), INTENT(IN) :: r
1189 REAL(kind=dp), INTENT(IN) :: rcut, rsmooth
1190
1191 INTEGER :: i, n
1192 REAL(kind=dp) :: rab, rx, x
1193
1194 n = SIZE(pot)
1195 cpassert(n <= SIZE(r))
1196
1197 pot(:) = 1.0_dp
1198 DO i = 1, n
1199 rab = r(i)
1200 IF (rab > rcut) THEN
1201 pot(i) = 0.0_dp
1202 ELSE IF (rab > rcut - rsmooth) THEN
1203 rx = rab - (rcut - rsmooth)
1204 x = rx/rsmooth
1205 pot(i) = -6._dp*x**5 + 15._dp*x**4 - 10._dp*x**3 + 1._dp
1206 END IF
1207 END DO
1208
1209 END SUBROUTINE cutpot
1210
1211END MODULE atom_sgp
subroutine, public set_kind_basis_atomic(basis, orb_basis_set, has_pp, agrid, cp2k_norm)
...
subroutine, public atom_sgp_release(sgp_pot)
...
Definition atom_sgp.F:801
subroutine, public sgp_construction(sgp_pot, ecp_pot, upf_pot, orb_basis, error)
...
Definition atom_sgp.F:79
subroutine, public fit_core_density_gaussians(r, rab, rho, alpha, coeff)
Fit a tabulated core density without forming ill-conditioned normal equations. Column-normalized,...
Definition atom_sgp.F:749
subroutine, public atom_sgp_construction(atom_info, input_section, iw)
...
Definition atom_sgp.F:204
Define the atom type and its sub types.
Definition atom_types.F:15
subroutine, public release_opmat(opmat)
...
subroutine, public release_atom_basis(basis)
...
Definition atom_types.F:934
subroutine, public init_atom_basis_default_pp(basis)
...
Definition atom_types.F:723
subroutine, public create_opmat(opmat, n, lmax)
...
subroutine, public atom_basis_gridrep(basis, gbasis, r, rab)
...
Definition atom_types.F:800
Some basic routines for atomic calculations.
Definition atom_utils.F:15
subroutine, public numpot_matrix(imat, cpot, basis, derivatives)
Calculate a potential matrix by integrating the potential on an atomic radial grid.
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public gth_pseudo
integer, parameter, public ecp_pseudo
integer, parameter, public upf_pseudo
integer, parameter, public no_pseudo
integer, parameter, public gaussian
objects that represent the structure of input sections and the data contained in an input section
subroutine, public section_vals_get(section_vals, ref_count, n_repetition, n_subs_vals_rep, section, explicit)
returns various attributes about the section_vals
sums arrays of real/complex numbers with much reduced round-off as compared to a naive implementation...
Definition kahan_sum.F:29
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), dimension(-1:2 *maxfac+1), parameter, public dfac
real(kind=dp), parameter, public rootpi
real(kind=dp), parameter, public fourpi
real(kind=dp), parameter, public sqrt2
Collection of simple mathematical functions and subroutines.
Definition mathlib.F:15
subroutine, public get_pseudo_inverse_diag(a, a_pinverse, rskip)
returns the pseudoinverse of a real, symmetric and positive definite matrix using diagonalization.
Definition mathlib.F:1028
subroutine, public diamat_all(a, eigval, dac)
Diagonalize the symmetric n by n matrix a using the LAPACK library. Only the upper triangle of matrix...
Definition mathlib.F:381
Definition powell.F:9
subroutine, public powell_optimize(n, x, optstate)
...
Definition powell.F:52
Owned UPF dataset and radial conventions shared by ATOM and Quickstep. Dataset availability does not ...
Definition upf_types.F:12
Provides all information about a basis set.
Definition atom_types.F:79
Provides all information about an atomic kind.
Definition atom_types.F:294
Operator matrices.
Definition atom_types.F:252