LCOV - code coverage report
Current view: top level - src - atom_sgp.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:42dac4a) Lines: 82.6 % 645 533
Test Date: 2025-07-25 12:55:17 Functions: 91.7 % 12 11

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : MODULE atom_sgp
      10              :    USE ai_onecenter,                    ONLY: sg_overlap
      11              :    USE atom_set_basis,                  ONLY: set_kind_basis_atomic
      12              :    USE atom_types,                      ONLY: &
      13              :         atom_basis_gridrep, atom_basis_type, atom_ecppot_type, atom_p_type, atom_type, &
      14              :         create_opmat, init_atom_basis_default_pp, opmat_type, release_atom_basis, release_opmat
      15              :    USE atom_upf,                        ONLY: atom_upfpot_type
      16              :    USE atom_utils,                      ONLY: integrate_grid,&
      17              :                                               numpot_matrix
      18              :    USE basis_set_types,                 ONLY: gto_basis_set_type
      19              :    USE input_constants,                 ONLY: ecp_pseudo,&
      20              :                                               gaussian,&
      21              :                                               gth_pseudo,&
      22              :                                               no_pseudo,&
      23              :                                               upf_pseudo
      24              :    USE input_section_types,             ONLY: section_vals_get,&
      25              :                                               section_vals_type
      26              :    USE kahan_sum,                       ONLY: accurate_dot_product
      27              :    USE kinds,                           ONLY: dp
      28              :    USE mathconstants,                   ONLY: dfac,&
      29              :                                               fourpi,&
      30              :                                               rootpi,&
      31              :                                               sqrt2
      32              :    USE mathlib,                         ONLY: diamat_all,&
      33              :                                               get_pseudo_inverse_diag
      34              :    USE powell,                          ONLY: opt_state_type,&
      35              :                                               powell_optimize
      36              : #include "./base/base_uses.f90"
      37              : 
      38              :    IMPLICIT NONE
      39              : 
      40              :    TYPE atom_sgp_potential_type
      41              :       LOGICAL                                  :: has_nonlocal = .FALSE.
      42              :       INTEGER                                  :: n_nonlocal = 0
      43              :       INTEGER                                  :: lmax = 0
      44              :       LOGICAL, DIMENSION(0:5)                  :: is_nonlocal = .FALSE.
      45              :       REAL(KIND=dp), DIMENSION(:), POINTER     :: a_nonlocal => Null()
      46              :       REAL(KIND=dp), DIMENSION(:, :), POINTER  :: h_nonlocal => Null()
      47              :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER  :: c_nonlocal => Null()
      48              :       LOGICAL                                  :: has_local = .FALSE.
      49              :       INTEGER                                  :: n_local = 0
      50              :       REAL(KIND=dp)                            :: zval = 0.0_dp
      51              :       REAL(KIND=dp)                            :: ac_local = 0.0_dp
      52              :       REAL(KIND=dp), DIMENSION(:), POINTER     :: a_local => Null()
      53              :       REAL(KIND=dp), DIMENSION(:), POINTER     :: c_local => Null()
      54              :       LOGICAL                                  :: has_nlcc = .FALSE.
      55              :       INTEGER                                  :: n_nlcc = 0
      56              :       REAL(KIND=dp), DIMENSION(:), POINTER     :: a_nlcc => Null()
      57              :       REAL(KIND=dp), DIMENSION(:), POINTER     :: c_nlcc => Null()
      58              :    END TYPE
      59              : 
      60              :    PRIVATE
      61              :    PUBLIC  :: atom_sgp_potential_type, atom_sgp_release
      62              :    PUBLIC  :: atom_sgp_construction, sgp_construction
      63              : 
      64              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'atom_sgp'
      65              : 
      66              : ! **************************************************************************************************
      67              : 
      68              : CONTAINS
      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           12 :    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           12 :       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           12 :       IF (PRESENT(orb_basis)) THEN
      96            0 :          CALL set_kind_basis_atomic(basis, orb_basis, has_pp=.TRUE., cp2k_norm=.TRUE.)
      97              :       ELSE
      98           12 :          CALL init_atom_basis_default_pp(basis)
      99              :       END IF
     100              : 
     101           12 :       is_ecp = .FALSE.
     102           12 :       IF (PRESENT(ecp_pot)) is_ecp = .TRUE.
     103           12 :       is_upf = .FALSE.
     104           12 :       IF (PRESENT(upf_pot)) is_upf = .TRUE.
     105           12 :       CPASSERT(.NOT. (is_ecp .AND. is_upf))
     106              : 
     107              :       ! upf has often very small grids, use a smooth cutoff function
     108           12 :       IF (is_upf) THEN
     109           12 :          n = SIZE(upf_pot%r)
     110           36 :          ALLOCATE (cutpotu(n))
     111        12124 :          rcut = MAXVAL(upf_pot%r)
     112           12 :          CALL cutpot(cutpotu, upf_pot%r, rcut, 2.5_dp)
     113           12 :          n = basis%grid%nr
     114           36 :          ALLOCATE (cutpots(n))
     115           12 :          CALL cutpot(cutpots, basis%grid%rad, rcut, 2.5_dp)
     116              :       ELSE
     117            0 :          n = basis%grid%nr
     118            0 :          ALLOCATE (cutpots(n))
     119            0 :          cutpots = 1.0_dp
     120              :       END IF
     121              : 
     122              :       ! generate the transformed potentials
     123           12 :       IF (is_ecp) THEN
     124            0 :          CALL ecp_sgp_constr(ecp_pot, sgp_pot, basis)
     125           12 :       ELSEIF (is_upf) THEN
     126           12 :          CALL upf_sgp_constr(upf_pot, sgp_pot, basis)
     127              :       ELSE
     128            0 :          CPABORT("")
     129              :       END IF
     130              : 
     131           12 :       NULLIFY (core, hnl)
     132           12 :       CALL create_opmat(core, basis%nbas)
     133           12 :       CALL create_opmat(hnl, basis%nbas, 5)
     134           12 :       NULLIFY (score, shnl)
     135           12 :       CALL create_opmat(score, basis%nbas)
     136           12 :       CALL create_opmat(shnl, basis%nbas, 5)
     137              :       !
     138           12 :       IF (is_ecp) THEN
     139            0 :          CALL ecpints(hnl%op, basis, ecp_pot)
     140           12 :       ELSEIF (is_upf) THEN
     141           12 :          CALL upfints(core%op, hnl%op, basis, upf_pot, cutpotu, sgp_pot%ac_local)
     142              :       ELSE
     143            0 :          CPABORT("")
     144              :       END IF
     145              :       !
     146           12 :       CALL sgpints(score%op, shnl%op, basis, sgp_pot, cutpots)
     147              :       !
     148           12 :       error = 0.0_dp
     149           12 :       IF (sgp_pot%has_local) THEN
     150           12 :          n = MIN(3, UBOUND(core%op, 3))
     151        20220 :          error(1) = MAXVAL(ABS(core%op(:, :, 0:n) - score%op(:, :, 0:n)))
     152        20220 :          mloc = MAXLOC(ABS(core%op(:, :, 0:n) - score%op(:, :, 0:n)))
     153           12 :          error(4) = error(1)/MAX(ABS(score%op(mloc(1), mloc(2), mloc(3))), 1.E-6_dp)
     154              :       END IF
     155           12 :       IF (sgp_pot%has_nonlocal) THEN
     156            6 :          n = MIN(3, UBOUND(hnl%op, 3))
     157        10110 :          error(2) = MAXVAL(ABS(hnl%op(:, :, 0:n) - shnl%op(:, :, 0:n)))
     158        10110 :          mloc = MAXLOC(ABS(hnl%op(:, :, 0:n) - shnl%op(:, :, 0:n)))
     159            6 :          error(5) = error(1)/MAX(ABS(hnl%op(mloc(1), mloc(2), mloc(3))), 1.E-6_dp)
     160              :       END IF
     161           12 :       IF (sgp_pot%has_nlcc) THEN
     162            0 :          IF (is_upf) THEN
     163            0 :             n = SIZE(upf_pot%r)
     164            0 :             ALLOCATE (cgauss(n))
     165            0 :             cgauss = 0.0_dp
     166            0 :             DO i = 1, sgp_pot%n_nlcc
     167            0 :                cgauss(:) = cgauss(:) + sgp_pot%c_nlcc(i)*EXP(-sgp_pot%a_nlcc(i)*upf_pot%r(:)**2)
     168              :             END DO
     169            0 :             errcc = SUM((cgauss(:) - upf_pot%rho_nlcc(:))**2*upf_pot%r(:)**2*upf_pot%rab(:))
     170            0 :             errcc = SQRT(errcc/REAL(n, KIND=dp))
     171            0 :             DEALLOCATE (cgauss)
     172              :          ELSE
     173            0 :             CPABORT("")
     174              :          END IF
     175            0 :          error(3) = errcc
     176              :       END IF
     177              :       !
     178           12 :       IF (is_upf) THEN
     179           12 :          DEALLOCATE (cutpotu)
     180           12 :          DEALLOCATE (cutpots)
     181              :       ELSE
     182            0 :          DEALLOCATE (cutpots)
     183              :       END IF
     184              :       !
     185           12 :       CALL release_opmat(score)
     186           12 :       CALL release_opmat(shnl)
     187           12 :       CALL release_opmat(core)
     188           12 :       CALL release_opmat(hnl)
     189              : 
     190           12 :       CALL release_atom_basis(basis)
     191              : 
     192          240 :    END SUBROUTINE sgp_construction
     193              : 
     194              : ! **************************************************************************************************
     195              : !> \brief ...
     196              : !> \param atom_info ...
     197              : !> \param input_section ...
     198              : !> \param iw ...
     199              : ! **************************************************************************************************
     200            5 :    SUBROUTINE atom_sgp_construction(atom_info, input_section, iw)
     201              : 
     202              :       TYPE(atom_p_type), DIMENSION(:, :), POINTER        :: atom_info
     203              :       TYPE(section_vals_type), POINTER                   :: input_section
     204              :       INTEGER, INTENT(IN)                                :: iw
     205              : 
     206              :       INTEGER                                            :: i, n, ppot_type
     207              :       LOGICAL                                            :: do_transform, explicit, is_ecp, is_upf
     208              :       REAL(KIND=dp)                                      :: errcc, rcut
     209            5 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: cgauss, cutpots, cutpotu
     210              :       TYPE(atom_ecppot_type), POINTER                    :: ecp_pot
     211              :       TYPE(atom_sgp_potential_type)                      :: sgp_pot
     212              :       TYPE(atom_type), POINTER                           :: atom_ref
     213              :       TYPE(atom_upfpot_type), POINTER                    :: upf_pot
     214              :       TYPE(opmat_type), POINTER                          :: core, hnl, score, shnl
     215              : 
     216            5 :       CALL section_vals_get(input_section, explicit=explicit)
     217            5 :       IF (.NOT. explicit) RETURN
     218              : 
     219            5 :       IF (iw > 0) WRITE (iw, '(/," ",79("*"),/,T24,A,/," ",79("*"))') "SEPARABLE GAUSSIAN PSEUDOPOTENTIAL"
     220              : 
     221            5 :       atom_ref => atom_info(1, 1)%atom
     222              : 
     223            5 :       ppot_type = atom_ref%potential%ppot_type
     224            0 :       SELECT CASE (ppot_type)
     225              :       CASE (gth_pseudo)
     226            0 :          IF (iw > 0) WRITE (iw, '(" GTH Pseudopotential is already in SGP form. ")')
     227            3 :          do_transform = .FALSE.
     228              :       CASE (ecp_pseudo)
     229            3 :          do_transform = .TRUE.
     230            3 :          is_ecp = .TRUE.
     231            3 :          is_upf = .FALSE.
     232            3 :          ecp_pot => atom_ref%potential%ecp_pot
     233              :       CASE (upf_pseudo)
     234            2 :          do_transform = .TRUE.
     235            2 :          is_ecp = .FALSE.
     236            2 :          is_upf = .TRUE.
     237            2 :          upf_pot => atom_ref%potential%upf_pot
     238              :       CASE (no_pseudo)
     239            0 :          IF (iw > 0) WRITE (iw, '(" No Pseudopotential available for transformation. ")')
     240            0 :          do_transform = .FALSE.
     241              :       CASE DEFAULT
     242            5 :          CPABORT("")
     243              :       END SELECT
     244              : 
     245              :       ! generate the transformed potentials
     246            5 :       IF (do_transform) THEN
     247            5 :          IF (is_ecp) THEN
     248            3 :             CALL ecp_sgp_constr(ecp_pot, sgp_pot, atom_ref%basis)
     249            2 :          ELSEIF (is_upf) THEN
     250            2 :             CALL upf_sgp_constr(upf_pot, sgp_pot, atom_ref%basis)
     251              :          ELSE
     252            0 :             CPABORT("")
     253              :          END IF
     254              :       END IF
     255              : 
     256              :       ! Check the result
     257            5 :       IF (do_transform) THEN
     258            5 :          NULLIFY (core, hnl)
     259            5 :          CALL create_opmat(core, atom_ref%basis%nbas)
     260            5 :          CALL create_opmat(hnl, atom_ref%basis%nbas, 5)
     261            5 :          NULLIFY (score, shnl)
     262            5 :          CALL create_opmat(score, atom_ref%basis%nbas)
     263            5 :          CALL create_opmat(shnl, atom_ref%basis%nbas, 5)
     264              :          !
     265              :          ! upf has often very small grids, use a smooth cutoff function
     266            5 :          IF (is_upf) THEN
     267            2 :             n = SIZE(upf_pot%r)
     268            6 :             ALLOCATE (cutpotu(n))
     269         1538 :             rcut = MAXVAL(upf_pot%r)
     270            2 :             CALL cutpot(cutpotu, upf_pot%r, rcut, 2.5_dp)
     271            2 :             n = atom_ref%basis%grid%nr
     272            6 :             ALLOCATE (cutpots(n))
     273            2 :             CALL cutpot(cutpots, atom_ref%basis%grid%rad, rcut, 2.5_dp)
     274              :          ELSE
     275            3 :             n = atom_ref%basis%grid%nr
     276            9 :             ALLOCATE (cutpots(n))
     277         1203 :             cutpots = 1.0_dp
     278              :          END IF
     279              :          !
     280            5 :          IF (is_ecp) THEN
     281            3 :             CALL ecpints(hnl%op, atom_ref%basis, ecp_pot)
     282            2 :          ELSEIF (is_upf) THEN
     283            2 :             CALL upfints(core%op, hnl%op, atom_ref%basis, upf_pot, cutpotu, sgp_pot%ac_local)
     284              :          ELSE
     285            0 :             CPABORT("")
     286              :          END IF
     287              :          !
     288            5 :          CALL sgpints(score%op, shnl%op, atom_ref%basis, sgp_pot, cutpots)
     289              :          !
     290            5 :          IF (sgp_pot%has_local) THEN
     291            2 :             n = MIN(3, UBOUND(core%op, 3))
     292         2186 :             errcc = MAXVAL(ABS(core%op(:, :, 0:n) - score%op(:, :, 0:n)))
     293            2 :             IF (iw > 0) THEN
     294            2 :                WRITE (iw, '(" Local part of pseudopotential")')
     295            2 :                WRITE (iw, '(" Number of basis functions ",T77,i4)') sgp_pot%n_local
     296            2 :                WRITE (iw, '(" Max. abs. error of matrix elements ",T65,f16.8)') errcc
     297              :             END IF
     298              :          END IF
     299            5 :          IF (sgp_pot%has_nonlocal) THEN
     300            5 :             IF (iw > 0) THEN
     301            5 :                WRITE (iw, '(" Nonlocal part of pseudopotential")')
     302            5 :                WRITE (iw, '(" Max. l-quantum number",T77,i4)') sgp_pot%lmax
     303            5 :                WRITE (iw, '(" Number of projector basis functions ",T77,i4)') sgp_pot%n_nonlocal
     304           21 :                DO i = 0, sgp_pot%lmax
     305         4368 :                   errcc = MAXVAL(ABS(hnl%op(:, :, i) - shnl%op(:, :, i)))
     306           21 :                   WRITE (iw, '(" Max. abs. error of matrix elements: l=",i2,T69,f12.8)') i, errcc
     307              :                END DO
     308              :             END IF
     309              :          END IF
     310            5 :          IF (sgp_pot%has_nlcc) THEN
     311            0 :             IF (is_upf) THEN
     312            0 :                n = SIZE(upf_pot%r)
     313            0 :                ALLOCATE (cgauss(n))
     314            0 :                cgauss = 0.0_dp
     315            0 :                DO i = 1, sgp_pot%n_nlcc
     316            0 :                   cgauss(:) = cgauss(:) + sgp_pot%c_nlcc(i)*EXP(-sgp_pot%a_nlcc(i)*upf_pot%r(:)**2)
     317              :                END DO
     318            0 :                errcc = SUM((cgauss(:) - upf_pot%rho_nlcc(:))**2*upf_pot%r(:)**2*upf_pot%rab(:))
     319            0 :                errcc = SQRT(errcc/REAL(n, KIND=dp))
     320            0 :                DEALLOCATE (cgauss)
     321              :             ELSE
     322            0 :                CPABORT("")
     323              :             END IF
     324            0 :             IF (iw > 0) THEN
     325            0 :                WRITE (iw, '(" Non-linear core correction: core density")')
     326            0 :                WRITE (iw, '(" Number of basis functions ",T77,i4)') sgp_pot%n_nlcc
     327            0 :                WRITE (iw, '(" RMS error of core density ",T69,f12.8)') errcc
     328              :             END IF
     329              :          END IF
     330              :          !
     331            5 :          IF (is_upf) THEN
     332            2 :             DEALLOCATE (cutpotu)
     333            2 :             DEALLOCATE (cutpots)
     334              :          ELSE
     335            3 :             DEALLOCATE (cutpots)
     336              :          END IF
     337              :          !
     338            5 :          CALL release_opmat(score)
     339            5 :          CALL release_opmat(shnl)
     340            5 :          CALL release_opmat(core)
     341            5 :          CALL release_opmat(hnl)
     342              :       END IF
     343              : 
     344            5 :       CALL atom_sgp_release(sgp_pot)
     345              : 
     346            5 :       IF (iw > 0) WRITE (iw, '(" ",79("*"))')
     347              : 
     348           40 :    END SUBROUTINE atom_sgp_construction
     349              : 
     350              : ! **************************************************************************************************
     351              : !> \brief ...
     352              : !> \param ecp_pot ...
     353              : !> \param sgp_pot ...
     354              : !> \param basis ...
     355              : ! **************************************************************************************************
     356            3 :    SUBROUTINE ecp_sgp_constr(ecp_pot, sgp_pot, basis)
     357              : 
     358              :       TYPE(atom_ecppot_type)                             :: ecp_pot
     359              :       TYPE(atom_sgp_potential_type)                      :: sgp_pot
     360              :       TYPE(atom_basis_type)                              :: basis
     361              : 
     362              :       INTEGER                                            :: i, ia, ir, j, k, l, n, na, nl, nr
     363              :       REAL(KIND=dp)                                      :: alpha, amx, cmx
     364            3 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: al, cl, cpot, pgauss
     365            3 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: cmat, qmat, score, sinv, smat, tmat
     366            3 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: rad
     367              : 
     368            3 :       sgp_pot%has_nlcc = .FALSE.
     369            3 :       sgp_pot%n_nlcc = 0
     370            3 :       sgp_pot%has_local = .FALSE.
     371            3 :       sgp_pot%n_local = 0
     372              : 
     373              :       ! transform semilocal potential into a separable local form
     374            3 :       sgp_pot%has_nonlocal = .TRUE.
     375              :       !
     376              :       ! hardcoded number of projectors (equal for all l values)
     377            3 :       nl = 8
     378              :       !
     379            3 :       sgp_pot%n_nonlocal = nl
     380            3 :       sgp_pot%lmax = ecp_pot%lmax
     381            0 :       ALLOCATE (sgp_pot%a_nonlocal(nl))
     382            9 :       ALLOCATE (sgp_pot%h_nonlocal(nl, 0:ecp_pot%lmax))
     383            9 :       ALLOCATE (sgp_pot%c_nonlocal(nl, nl, 0:ecp_pot%lmax))
     384              :       !
     385            3 :       ALLOCATE (al(nl), cl(nl))
     386            3 :       ALLOCATE (smat(nl, nl), sinv(nl, nl))
     387            3 :       ALLOCATE (tmat(nl, nl), cmat(nl, nl))
     388           27 :       al = 0.0_dp
     389          531 :       amx = MAXVAL(ecp_pot%bpot)
     390            3 :       cmx = amx/0.15_dp
     391            3 :       cmx = cmx**(1._dp/REAL(nl - 1, dp))
     392            3 :       cmx = 1._dp/cmx
     393           27 :       DO ir = 1, nl
     394           27 :          al(ir) = amx*cmx**(ir - 1)
     395              :       END DO
     396              :       !
     397           27 :       sgp_pot%a_nonlocal(1:nl) = al(1:nl)
     398              :       !
     399            3 :       nr = basis%grid%nr
     400            3 :       rad => basis%grid%rad
     401           12 :       ALLOCATE (cpot(nr), pgauss(nr))
     402           14 :       DO l = 0, ecp_pot%lmax
     403           11 :          na = basis%nbas(l)
     404           66 :          ALLOCATE (score(na, na), qmat(na, nl))
     405         4411 :          cpot = 0._dp
     406           26 :          DO k = 1, ecp_pot%npot(l)
     407           15 :             n = ecp_pot%nrpot(k, l)
     408           15 :             alpha = ecp_pot%bpot(k, l)
     409         6026 :             cpot(:) = cpot + ecp_pot%apot(k, l)*rad**(n - 2)*EXP(-alpha*rad**2)
     410              :          END DO
     411          187 :          DO i = 1, na
     412         1683 :             DO j = i, na
     413         1496 :                score(i, j) = integrate_grid(cpot, basis%bf(:, i, l), basis%bf(:, j, l), basis%grid)
     414         1672 :                score(j, i) = score(i, j)
     415              :             END DO
     416              :          END DO
     417              :          ! overlap basis with projectors
     418           99 :          DO i = 1, nl
     419        35288 :             pgauss(:) = EXP(-al(i)*rad(:)**2)*rad(:)**l
     420         1507 :             DO ia = 1, na
     421         1496 :                qmat(ia, i) = integrate_grid(basis%bf(:, ia, l), pgauss(:), basis%grid)
     422              :             END DO
     423              :          END DO
     424         1507 :          qmat = SQRT(fourpi)*qmat
     425              :          ! tmat = qmat * score * qmat
     426        72204 :          tmat(1:nl, 1:nl) = MATMUL(TRANSPOSE(qmat(1:na, 1:nl)), MATMUL(score(1:na, 1:na), qmat(1:na, 1:nl)))
     427        12859 :          smat(1:nl, 1:nl) = MATMUL(TRANSPOSE(qmat(1:na, 1:nl)), qmat(1:na, 1:nl))
     428           11 :          CALL get_pseudo_inverse_diag(smat(1:nl, 1:nl), sinv(1:nl, 1:nl), 1.e-10_dp)
     429        25707 :          cmat(1:nl, 1:nl) = MATMUL(sinv(1:nl, 1:nl), MATMUL(tmat(1:nl, 1:nl), sinv(1:nl, 1:nl)))
     430         1595 :          cmat(1:nl, 1:nl) = (cmat(1:nl, 1:nl) + TRANSPOSE(cmat(1:nl, 1:nl)))*0.5_dp
     431              :          !
     432              :          ! Residium
     433              :          !
     434           11 :          CALL diamat_all(cmat(1:nl, 1:nl), cl(1:nl), .TRUE.)
     435              :          !
     436           99 :          sgp_pot%h_nonlocal(1:nl, l) = cl(1:nl)
     437          803 :          sgp_pot%c_nonlocal(1:nl, 1:nl, l) = cmat(1:nl, 1:nl)
     438           11 :          sgp_pot%is_nonlocal(l) = .TRUE.
     439              :          !
     440           14 :          DEALLOCATE (score, qmat)
     441              :       END DO
     442            3 :       DEALLOCATE (cpot, pgauss)
     443            3 :       DEALLOCATE (al, cl, smat, sinv, tmat, cmat)
     444              : 
     445            6 :    END SUBROUTINE ecp_sgp_constr
     446              : 
     447              : ! **************************************************************************************************
     448              : !> \brief ...
     449              : !> \param upf_pot ...
     450              : !> \param sgp_pot ...
     451              : !> \param basis ...
     452              : ! **************************************************************************************************
     453           14 :    SUBROUTINE upf_sgp_constr(upf_pot, sgp_pot, basis)
     454              : 
     455              :       TYPE(atom_upfpot_type)                             :: upf_pot
     456              :       TYPE(atom_sgp_potential_type)                      :: sgp_pot
     457              :       TYPE(atom_basis_type)                              :: basis
     458              : 
     459              :       CHARACTER(len=4)                                   :: ptype
     460              :       INTEGER                                            :: ia, ib, ipa, ipb, ir, la, lb, na, nl, &
     461              :                                                             np, nr
     462              :       LOGICAL                                            :: nl_trans
     463              :       REAL(KIND=dp)                                      :: cpa, cpb, eee, ei, errcc, errloc, rc, &
     464              :                                                             x(2), zval
     465           28 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: al, ccharge, cgauss, cl, pgauss, pproa, &
     466           14 :                                                             pprob, tv, vgauss, vloc, ww
     467           14 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: cmat, qmat, score, sinv, smat, tmat
     468              :       TYPE(atom_basis_type)                              :: gbasis
     469              :       TYPE(opt_state_type)                               :: ostate
     470              : 
     471           14 :       IF (upf_pot%is_ultrasoft .OR. upf_pot%is_paw .OR. upf_pot%is_coulomb) THEN
     472            0 :          sgp_pot%has_nonlocal = .FALSE.
     473            0 :          sgp_pot%n_nonlocal = 0
     474            0 :          sgp_pot%has_local = .FALSE.
     475            0 :          sgp_pot%n_local = 0
     476            0 :          sgp_pot%has_nlcc = .FALSE.
     477            0 :          sgp_pot%n_nlcc = 0
     478            0 :          RETURN
     479              :       END IF
     480              : 
     481              :       ! radial grid
     482           14 :       nr = SIZE(upf_pot%r)
     483              :       ! weights for integration
     484           42 :       ALLOCATE (ww(nr))
     485        13648 :       ww(:) = upf_pot%r(:)**2*upf_pot%rab(:)
     486              : 
     487              :       ! start with local potential
     488           14 :       sgp_pot%has_local = .TRUE.
     489              :       ! fit local potential to Gaussian form
     490           42 :       ALLOCATE (vloc(nr), vgauss(nr))
     491              :       ! smearing of core charge
     492           14 :       zval = upf_pot%zion
     493              :       ! Try to find an optimal Gaussian charge distribution
     494           14 :       CALL erffit(sgp_pot%ac_local, upf_pot%vlocal, upf_pot%r, zval)
     495           14 :       sgp_pot%zval = zval
     496        13648 :       DO ir = 1, nr
     497        13648 :          IF (upf_pot%r(ir) < 1.e-12_dp) THEN
     498            0 :             vgauss(ir) = -SQRT(2.0_dp)*zval/rootpi/sgp_pot%ac_local
     499              :          ELSE
     500        13634 :             rc = upf_pot%r(ir)/sgp_pot%ac_local/SQRT(2.0_dp)
     501        13634 :             vgauss(ir) = -zval/upf_pot%r(ir)*erf(rc)
     502              :          END IF
     503              :       END DO
     504        13648 :       vloc(:) = upf_pot%vlocal(:) - vgauss(:)
     505              :       !
     506           14 :       CALL atom_basis_gridrep(basis, gbasis, upf_pot%r, upf_pot%rab)
     507              :       !
     508           14 :       nl = 12
     509           14 :       ALLOCATE (al(nl), cl(nl))
     510           14 :       ostate%nf = 0
     511           14 :       ostate%nvar = 2
     512           14 :       x(1) = 1.00_dp !starting point of geometric series
     513           14 :       x(2) = 1.20_dp !factor of series
     514           14 :       ostate%rhoend = 1.e-12_dp
     515           14 :       ostate%rhobeg = 5.e-2_dp
     516           14 :       ostate%maxfun = 1000
     517           14 :       ostate%iprint = 1
     518           14 :       ostate%unit = -1
     519           14 :       ostate%state = 0
     520         1153 :       DO
     521         1167 :          IF (ostate%state == 2) THEN
     522        14625 :             DO ir = 1, nl
     523        14625 :                al(ir) = x(1)*x(2)**(ir - 1)
     524              :             END DO
     525         1125 :             CALL pplocal_error(nl, al, cl, vloc, vgauss, gbasis, upf_pot%r, ww, 1, ostate%f)
     526              :          END IF
     527         1167 :          IF (ostate%state == -1) EXIT
     528         1153 :          CALL powell_optimize(ostate%nvar, x, ostate)
     529              :       END DO
     530           14 :       ostate%state = 8
     531           14 :       CALL powell_optimize(ostate%nvar, x, ostate)
     532          182 :       DO ir = 1, nl
     533          182 :          al(ir) = x(1)*x(2)**(ir - 1)
     534              :       END DO
     535           14 :       CALL pplocal_error(nl, al, cl, vloc, vgauss, gbasis, upf_pot%r, ww, 1, errloc)
     536              :       !
     537           14 :       ALLOCATE (sgp_pot%a_local(nl), sgp_pot%c_local(nl))
     538           14 :       sgp_pot%n_local = nl
     539          182 :       sgp_pot%a_local(1:nl) = al(1:nl)
     540          182 :       sgp_pot%c_local(1:nl) = cl(1:nl)
     541           14 :       DEALLOCATE (vloc, vgauss)
     542           14 :       DEALLOCATE (al, cl)
     543           14 :       CALL release_atom_basis(gbasis)
     544              :       !
     545           14 :       ptype = ADJUSTL(TRIM(upf_pot%pseudo_type))
     546           14 :       IF (ptype(1:2) == "NC" .OR. ptype(1:2) == "US") THEN
     547              :          nl_trans = .FALSE.
     548            1 :       ELSE IF (ptype(1:2) == "SL") THEN
     549              :          nl_trans = .TRUE.
     550              :       ELSE
     551            0 :          CPABORT("Pseudopotential type: ["//ADJUSTL(TRIM(ptype))//"] not known")
     552              :       END IF
     553              : 
     554              :       ! purely local pseudopotentials
     555           14 :       IF (upf_pot%l_max < 0) THEN
     556            6 :          sgp_pot%n_nonlocal = 0
     557            6 :          sgp_pot%lmax = -1
     558            6 :          sgp_pot%has_nonlocal = .FALSE.
     559              :       ELSE
     560              :          ! Non-local pseudopotential in Gaussian form
     561            8 :          IF (nl_trans) THEN
     562            1 :             sgp_pot%has_nonlocal = .TRUE.
     563              :             ! semi local pseudopotential
     564              :             ! fit to nonlocal form
     565              :             ! get basis representation on UPF grid
     566            1 :             nl = 8
     567              :             !
     568            1 :             sgp_pot%n_nonlocal = nl
     569            1 :             sgp_pot%lmax = upf_pot%l_max
     570            1 :             ALLOCATE (sgp_pot%a_nonlocal(nl))
     571            3 :             ALLOCATE (sgp_pot%h_nonlocal(nl, 0:upf_pot%l_max))
     572            3 :             ALLOCATE (sgp_pot%c_nonlocal(nl, nl, 0:upf_pot%l_max))
     573              :             !
     574            1 :             ALLOCATE (al(nl), cl(nl))
     575            1 :             ALLOCATE (smat(nl, nl), sinv(nl, nl))
     576            1 :             ALLOCATE (tmat(nl, nl), cmat(nl, nl))
     577            9 :             al = 0.0_dp
     578            9 :             DO ir = 1, nl
     579            9 :                al(ir) = 10.0_dp*0.60_dp**(ir - 1)
     580              :             END DO
     581              :             !
     582            9 :             sgp_pot%a_nonlocal(1:nl) = al(1:nl)
     583              :             !
     584            1 :             CALL atom_basis_gridrep(basis, gbasis, upf_pot%r, upf_pot%rab)
     585            3 :             ALLOCATE (pgauss(nr), vloc(nr))
     586            5 :             DO la = 0, upf_pot%l_max
     587            4 :                IF (la == upf_pot%l_local) CYCLE
     588            3 :                sgp_pot%is_nonlocal(la) = .TRUE.
     589            3 :                na = gbasis%nbas(la)
     590           21 :                ALLOCATE (score(na, na), qmat(na, nl))
     591              :                ! Reference matrix
     592         1386 :                vloc(:) = upf_pot%vsemi(:, la + 1) - upf_pot%vlocal(:)
     593           51 :                DO ia = 1, na
     594          459 :                   DO ib = ia, na
     595       188496 :                      score(ia, ib) = SUM(vloc(:)*gbasis%bf(:, ia, la)*gbasis%bf(:, ib, la)*ww(:))
     596          456 :                      score(ib, ia) = score(ia, ib)
     597              :                   END DO
     598              :                END DO
     599              :                ! overlap basis with projectors
     600           27 :                DO ir = 1, nl
     601        11088 :                   pgauss(:) = EXP(-al(ir)*upf_pot%r(:)**2)*upf_pot%r(:)**la
     602           24 :                   eee = rootpi/(2._dp**(la + 2)*dfac(2*la + 1))/(2._dp*al(ir))**(la + 1.5_dp)
     603        11088 :                   pgauss(:) = pgauss(:)/SQRT(eee)
     604          411 :                   DO ia = 1, na
     605       177432 :                      qmat(ia, ir) = SUM(gbasis%bf(:, ia, la)*pgauss(:)*ww)
     606              :                   END DO
     607              :                END DO
     608              :                ! tmat = qmat * score * qmat
     609        19692 :                tmat(1:nl, 1:nl) = MATMUL(TRANSPOSE(qmat(1:na, 1:nl)), MATMUL(score(1:na, 1:na), qmat(1:na, 1:nl)))
     610         3507 :                smat(1:nl, 1:nl) = MATMUL(TRANSPOSE(qmat(1:na, 1:nl)), qmat(1:na, 1:nl))
     611            3 :                CALL get_pseudo_inverse_diag(smat(1:nl, 1:nl), sinv(1:nl, 1:nl), 1.e-10_dp)
     612         7011 :                cmat(1:nl, 1:nl) = MATMUL(sinv(1:nl, 1:nl), MATMUL(tmat(1:nl, 1:nl), sinv(1:nl, 1:nl)))
     613          435 :                cmat(1:nl, 1:nl) = (cmat(1:nl, 1:nl) + TRANSPOSE(cmat(1:nl, 1:nl)))*0.5_dp
     614            3 :                CALL diamat_all(cmat(1:nl, 1:nl), cl(1:nl), .TRUE.)
     615              :                !
     616              :                ! get back unnormalized Gaussians
     617           27 :                DO ir = 1, nl
     618           24 :                   ei = rootpi/(2._dp**(la + 2)*dfac(2*la + 1))/(2._dp*al(ir))**(la + 1.5_dp)
     619          219 :                   cmat(ir, 1:nl) = cmat(ir, 1:nl)/SQRT(ei)
     620              :                END DO
     621           27 :                sgp_pot%h_nonlocal(1:nl, la) = cl(1:nl)
     622          219 :                sgp_pot%c_nonlocal(1:nl, 1:nl, la) = cmat(1:nl, 1:nl)
     623            3 :                sgp_pot%is_nonlocal(la) = .TRUE.
     624            4 :                DEALLOCATE (score, qmat)
     625              :             END DO
     626              :             ! SQRT(4PI)
     627          293 :             sgp_pot%c_nonlocal = sgp_pot%c_nonlocal/SQRT(fourpi)
     628            1 :             CALL release_atom_basis(gbasis)
     629            1 :             DEALLOCATE (pgauss, vloc)
     630            1 :             DEALLOCATE (al, cl, smat, sinv, tmat, cmat)
     631              :          ELSE
     632            7 :             sgp_pot%has_nonlocal = .TRUE.
     633              :             ! non local pseudopotential
     634           28 :             ALLOCATE (pproa(nr), pprob(nr), pgauss(nr))
     635            7 :             np = upf_pot%number_of_proj
     636            7 :             nl = 8
     637            7 :             ALLOCATE (al(nl), cl(nl))
     638            7 :             ALLOCATE (smat(nl, nl), sinv(nl, nl))
     639            7 :             ALLOCATE (tmat(nl, nl), cmat(nl, nl))
     640           63 :             al = 0.0_dp
     641           63 :             cl = 0.0_dp
     642           63 :             DO ir = 1, nl
     643           63 :                al(ir) = 10.0_dp*0.60_dp**(ir - 1)
     644              :             END DO
     645              :             !
     646           14 :             sgp_pot%lmax = MAXVAL(upf_pot%lbeta(:))
     647            7 :             sgp_pot%n_nonlocal = nl
     648            7 :             ALLOCATE (sgp_pot%a_nonlocal(nl))
     649           21 :             ALLOCATE (sgp_pot%h_nonlocal(nl, 0:sgp_pot%lmax))
     650           21 :             ALLOCATE (sgp_pot%c_nonlocal(nl, nl, 0:sgp_pot%lmax))
     651              :             !
     652           63 :             sgp_pot%a_nonlocal(1:nl) = al(1:nl)
     653              :             !
     654            7 :             CALL atom_basis_gridrep(basis, gbasis, upf_pot%r, upf_pot%rab)
     655           14 :             DO la = 0, sgp_pot%lmax
     656            7 :                sgp_pot%is_nonlocal(la) = .TRUE.
     657            7 :                na = gbasis%nbas(la)
     658           49 :                ALLOCATE (score(na, na), qmat(na, nl))
     659              :                ! Reference matrix
     660         2799 :                score = 0.0_dp
     661           14 :                DO ipa = 1, np
     662            7 :                   lb = upf_pot%lbeta(ipa)
     663            7 :                   IF (la /= lb) CYCLE
     664         7606 :                   pproa(:) = upf_pot%beta(:, ipa)
     665           21 :                   DO ipb = 1, np
     666            7 :                      lb = upf_pot%lbeta(ipb)
     667            7 :                      IF (la /= lb) CYCLE
     668         7606 :                      pprob(:) = upf_pot%beta(:, ipb)
     669            7 :                      eee = upf_pot%dion(ipa, ipb)
     670          150 :                      DO ia = 1, na
     671       147824 :                         cpa = SUM(pproa(:)*gbasis%bf(:, ia, la)*ww(:))
     672         1539 :                         DO ib = ia, na
     673      1517784 :                            cpb = SUM(pprob(:)*gbasis%bf(:, ib, la)*ww(:))
     674         1396 :                            score(ia, ib) = score(ia, ib) + cpa*eee*cpb
     675         1532 :                            score(ib, ia) = score(ia, ib)
     676              :                         END DO
     677              :                      END DO
     678              :                   END DO
     679              :                END DO
     680              :                ! overlap basis with projectors
     681           63 :                DO ir = 1, nl
     682        60848 :                   pgauss(:) = EXP(-al(ir)*upf_pot%r(:)**2)*upf_pot%r(:)**la
     683           56 :                   eee = rootpi/(2._dp**(la + 2)*dfac(2*la + 1))/(2._dp*al(ir))**(la + 1.5_dp)
     684        60848 :                   pgauss(:) = pgauss(:)/SQRT(eee)
     685         1151 :                   DO ia = 1, na
     686      1182648 :                      qmat(ia, ir) = SUM(gbasis%bf(:, ia, la)*pgauss(:)*ww)
     687              :                   END DO
     688              :                END DO
     689              :                ! tmat = qmat * score * qmat
     690        63228 :                tmat(1:nl, 1:nl) = MATMUL(TRANSPOSE(qmat(1:na, 1:nl)), MATMUL(score(1:na, 1:na), qmat(1:na, 1:nl)))
     691         9719 :                smat(1:nl, 1:nl) = MATMUL(TRANSPOSE(qmat(1:na, 1:nl)), qmat(1:na, 1:nl))
     692            7 :                CALL get_pseudo_inverse_diag(smat(1:nl, 1:nl), sinv(1:nl, 1:nl), 1.e-10_dp)
     693        16359 :                cmat(1:nl, 1:nl) = MATMUL(sinv(1:nl, 1:nl), MATMUL(tmat(1:nl, 1:nl), sinv(1:nl, 1:nl)))
     694         1015 :                cmat(1:nl, 1:nl) = (cmat(1:nl, 1:nl) + TRANSPOSE(cmat(1:nl, 1:nl)))*0.5_dp
     695            7 :                CALL diamat_all(cmat(1:nl, 1:nl), cl(1:nl), .TRUE.)
     696              :                !
     697              :                ! get back unnormalized Gaussians
     698           63 :                DO ir = 1, nl
     699           56 :                   ei = rootpi/(2._dp**(la + 2)*dfac(2*la + 1))/(2._dp*al(ir))**(la + 1.5_dp)
     700          511 :                   cmat(ir, 1:nl) = cmat(ir, 1:nl)/SQRT(ei)
     701              :                END DO
     702           63 :                sgp_pot%h_nonlocal(1:nl, la) = cl(1:nl)
     703          511 :                sgp_pot%c_nonlocal(1:nl, 1:nl, la) = cmat(1:nl, 1:nl)
     704            7 :                sgp_pot%is_nonlocal(la) = .TRUE.
     705           14 :                DEALLOCATE (score, qmat)
     706              :             END DO
     707              :             ! SQRT(4PI)
     708          518 :             sgp_pot%c_nonlocal = sgp_pot%c_nonlocal/SQRT(fourpi)
     709            7 :             CALL release_atom_basis(gbasis)
     710            7 :             DEALLOCATE (pgauss, pproa, pprob)
     711            7 :             DEALLOCATE (al, cl, smat, sinv, tmat, cmat)
     712              :          END IF
     713              :       END IF
     714              : 
     715           14 :       IF (upf_pot%core_correction) THEN
     716            0 :          sgp_pot%has_nlcc = .TRUE.
     717              :       ELSE
     718           14 :          sgp_pot%has_nlcc = .FALSE.
     719           14 :          sgp_pot%n_nlcc = 0
     720              :       END IF
     721              : 
     722              :       ! fit core charge to Gaussian form
     723           14 :       IF (sgp_pot%has_nlcc) THEN
     724            0 :          ALLOCATE (ccharge(nr), cgauss(nr))
     725            0 :          ccharge(:) = upf_pot%rho_nlcc(:)
     726            0 :          nl = 8
     727            0 :          ALLOCATE (al(nl), cl(nl), tv(nl))
     728            0 :          ALLOCATE (smat(nl, nl), sinv(nl, nl))
     729            0 :          al = 0.0_dp
     730            0 :          cl = 0.0_dp
     731            0 :          DO ir = 1, nl
     732            0 :             al(ir) = 10.0_dp*0.6_dp**(ir - 1)
     733              :          END DO
     734              :          ! calculate integrals
     735            0 :          smat = 0.0_dp
     736            0 :          sinv = 0.0_dp
     737            0 :          tv = 0.0_dp
     738            0 :          CALL sg_overlap(smat(1:nl, 1:nl), 0, al(1:nl), al(1:nl))
     739            0 :          DO ir = 1, nl
     740            0 :             cgauss(:) = EXP(-al(ir)*upf_pot%r(:)**2)
     741            0 :             tv(ir) = SUM(cgauss*ccharge*ww)
     742              :          END DO
     743            0 :          CALL get_pseudo_inverse_diag(smat(1:nl, 1:nl), sinv(1:nl, 1:nl), 1.e-10_dp)
     744            0 :          cl(1:nl) = MATMUL(sinv(1:nl, 1:nl), tv(1:nl))
     745            0 :          cgauss = 0.0_dp
     746            0 :          DO ir = 1, nl
     747            0 :             cgauss(:) = cgauss(:) + cl(ir)*EXP(-al(ir)*upf_pot%r(:)**2)
     748              :          END DO
     749            0 :          errcc = SUM((cgauss - ccharge)**2*ww)
     750            0 :          ALLOCATE (sgp_pot%a_local(nl), sgp_pot%c_local(nl))
     751            0 :          sgp_pot%n_nlcc = nl
     752            0 :          sgp_pot%a_nlcc(1:nl) = al(1:nl)
     753            0 :          sgp_pot%c_nlcc(1:nl) = cl(1:nl)
     754            0 :          DEALLOCATE (ccharge, cgauss)
     755            0 :          DEALLOCATE (al, cl, tv, smat, sinv)
     756              :       END IF
     757              : 
     758           14 :       DEALLOCATE (ww)
     759              : 
     760          280 :    END SUBROUTINE upf_sgp_constr
     761              : 
     762              : ! **************************************************************************************************
     763              : !> \brief ...
     764              : !> \param sgp_pot ...
     765              : ! **************************************************************************************************
     766           45 :    SUBROUTINE atom_sgp_release(sgp_pot)
     767              : 
     768              :       TYPE(atom_sgp_potential_type)                      :: sgp_pot
     769              : 
     770           45 :       IF (ASSOCIATED(sgp_pot%a_nonlocal)) DEALLOCATE (sgp_pot%a_nonlocal)
     771           45 :       IF (ASSOCIATED(sgp_pot%h_nonlocal)) DEALLOCATE (sgp_pot%h_nonlocal)
     772           45 :       IF (ASSOCIATED(sgp_pot%c_nonlocal)) DEALLOCATE (sgp_pot%c_nonlocal)
     773              : 
     774           45 :       IF (ASSOCIATED(sgp_pot%a_local)) DEALLOCATE (sgp_pot%a_local)
     775           45 :       IF (ASSOCIATED(sgp_pot%c_local)) DEALLOCATE (sgp_pot%c_local)
     776              : 
     777           45 :       IF (ASSOCIATED(sgp_pot%a_nlcc)) DEALLOCATE (sgp_pot%a_nlcc)
     778           45 :       IF (ASSOCIATED(sgp_pot%c_nlcc)) DEALLOCATE (sgp_pot%c_nlcc)
     779              : 
     780           45 :    END SUBROUTINE atom_sgp_release
     781              : 
     782              : ! **************************************************************************************************
     783              : !> \brief ...
     784              : !> \param core ...
     785              : !> \param hnl ...
     786              : !> \param basis ...
     787              : !> \param upf_pot ...
     788              : !> \param cutpotu ...
     789              : !> \param ac_local ...
     790              : ! **************************************************************************************************
     791           14 :    SUBROUTINE upfints(core, hnl, basis, upf_pot, cutpotu, ac_local)
     792              :       REAL(KIND=dp), DIMENSION(:, :, 0:)                 :: core, hnl
     793              :       TYPE(atom_basis_type), INTENT(INOUT)               :: basis
     794              :       TYPE(atom_upfpot_type)                             :: upf_pot
     795              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: cutpotu
     796              :       REAL(KIND=dp), INTENT(IN)                          :: ac_local
     797              : 
     798              :       CHARACTER(len=4)                                   :: ptype
     799              :       INTEGER                                            :: i, j, k1, k2, la, lb, m, n
     800              :       REAL(KIND=dp)                                      :: rc, zval
     801           14 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: spot
     802           14 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: spmat
     803              :       TYPE(atom_basis_type)                              :: gbasis
     804              : 
     805              :       ! get basis representation on UPF grid
     806           14 :       CALL atom_basis_gridrep(basis, gbasis, upf_pot%r, upf_pot%rab)
     807              : 
     808              :       ! local pseudopotential
     809        33602 :       core = 0._dp
     810           14 :       n = SIZE(upf_pot%r)
     811           42 :       ALLOCATE (spot(n))
     812        13648 :       spot(:) = upf_pot%vlocal(:)
     813           14 :       zval = upf_pot%zion
     814        13648 :       DO i = 1, n
     815        13648 :          IF (upf_pot%r(i) < 1.e-12_dp) THEN
     816            0 :             spot(i) = spot(i) + sqrt2*zval/rootpi/ac_local
     817              :          ELSE
     818        13634 :             rc = upf_pot%r(i)/ac_local/sqrt2
     819        13634 :             spot(i) = spot(i) + zval/upf_pot%r(i)*erf(rc)
     820              :          END IF
     821              :       END DO
     822        13648 :       spot(:) = spot(:)*cutpotu(:)
     823              : 
     824           14 :       CALL numpot_matrix(core, spot, gbasis, 0)
     825           14 :       DEALLOCATE (spot)
     826              : 
     827        33602 :       hnl = 0._dp
     828           14 :       ptype = ADJUSTL(TRIM(upf_pot%pseudo_type))
     829           14 :       IF (ptype(1:2) == "NC" .OR. ptype(1:2) == "US") THEN
     830              :          ! non local pseudopotential
     831           91 :          n = MAXVAL(gbasis%nbas(:))
     832           13 :          m = upf_pot%number_of_proj
     833           46 :          ALLOCATE (spmat(n, m))
     834          156 :          spmat = 0.0_dp
     835           20 :          DO i = 1, m
     836            7 :             la = upf_pot%lbeta(i)
     837          156 :             DO j = 1, gbasis%nbas(la)
     838          143 :                spmat(j, i) = integrate_grid(upf_pot%beta(:, i), gbasis%bf(:, j, la), gbasis%grid)
     839              :             END DO
     840              :          END DO
     841           20 :          DO i = 1, m
     842            7 :             la = upf_pot%lbeta(i)
     843           27 :             DO j = 1, m
     844            7 :                lb = upf_pot%lbeta(j)
     845           14 :                IF (la == lb) THEN
     846          143 :                   DO k1 = 1, gbasis%nbas(la)
     847         2799 :                      DO k2 = 1, gbasis%nbas(la)
     848         2792 :                         hnl(k1, k2, la) = hnl(k1, k2, la) + spmat(k1, i)*upf_pot%dion(i, j)*spmat(k2, j)
     849              :                      END DO
     850              :                   END DO
     851              :                END IF
     852              :             END DO
     853              :          END DO
     854           13 :          DEALLOCATE (spmat)
     855            1 :       ELSE IF (ptype(1:2) == "SL") THEN
     856              :          ! semi local pseudopotential
     857            5 :          DO la = 0, upf_pot%l_max
     858            4 :             IF (la == upf_pot%l_local) CYCLE
     859            3 :             m = SIZE(upf_pot%vsemi(:, la + 1))
     860            9 :             ALLOCATE (spot(m))
     861         1386 :             spot(:) = upf_pot%vsemi(:, la + 1) - upf_pot%vlocal(:)
     862         1386 :             spot(:) = spot(:)*cutpotu(:)
     863            3 :             n = basis%nbas(la)
     864           51 :             DO i = 1, n
     865          459 :                DO j = i, n
     866              :                   hnl(i, j, la) = hnl(i, j, la) + &
     867              :                                   integrate_grid(spot(:), &
     868          408 :                                                  gbasis%bf(:, i, la), gbasis%bf(:, j, la), gbasis%grid)
     869          456 :                   hnl(j, i, la) = hnl(i, j, la)
     870              :                END DO
     871              :             END DO
     872            5 :             DEALLOCATE (spot)
     873              :          END DO
     874              :       ELSE
     875            0 :          CPABORT("Pseudopotential type: ["//ADJUSTL(TRIM(ptype))//"] not known")
     876              :       END IF
     877              : 
     878              :       ! release basis representation on UPF grid
     879           14 :       CALL release_atom_basis(gbasis)
     880              : 
     881          280 :    END SUBROUTINE upfints
     882              : 
     883              : ! **************************************************************************************************
     884              : !> \brief ...
     885              : !> \param hnl ...
     886              : !> \param basis ...
     887              : !> \param ecp_pot ...
     888              : ! **************************************************************************************************
     889            3 :    SUBROUTINE ecpints(hnl, basis, ecp_pot)
     890              :       REAL(KIND=dp), DIMENSION(:, :, 0:)                 :: hnl
     891              :       TYPE(atom_basis_type), INTENT(INOUT)               :: basis
     892              :       TYPE(atom_ecppot_type)                             :: ecp_pot
     893              : 
     894              :       INTEGER                                            :: i, j, k, l, m, n
     895              :       REAL(KIND=dp)                                      :: alpha
     896            3 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: cpot
     897            3 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: rad
     898              : 
     899            3 :       rad => basis%grid%rad
     900            3 :       m = basis%grid%nr
     901            9 :       ALLOCATE (cpot(1:m))
     902              : 
     903              :       ! non local pseudopotential
     904         4917 :       hnl = 0.0_dp
     905           14 :       DO l = 0, ecp_pot%lmax
     906         4411 :          cpot = 0._dp
     907           26 :          DO k = 1, ecp_pot%npot(l)
     908           15 :             n = ecp_pot%nrpot(k, l)
     909           15 :             alpha = ecp_pot%bpot(k, l)
     910         6026 :             cpot(:) = cpot(:) + ecp_pot%apot(k, l)*rad(:)**(n - 2)*EXP(-alpha*rad(:)**2)
     911              :          END DO
     912          190 :          DO i = 1, basis%nbas(l)
     913         1683 :             DO j = i, basis%nbas(l)
     914         1496 :                hnl(i, j, l) = integrate_grid(cpot, basis%bf(:, i, l), basis%bf(:, j, l), basis%grid)
     915         1672 :                hnl(j, i, l) = hnl(i, j, l)
     916              :             END DO
     917              :          END DO
     918              :       END DO
     919            3 :       DEALLOCATE (cpot)
     920              : 
     921            3 :    END SUBROUTINE ecpints
     922              : 
     923              : ! **************************************************************************************************
     924              : !> \brief ...
     925              : !> \param core ...
     926              : !> \param hnl ...
     927              : !> \param basis ...
     928              : !> \param sgp_pot ...
     929              : !> \param cutpots ...
     930              : ! **************************************************************************************************
     931           17 :    SUBROUTINE sgpints(core, hnl, basis, sgp_pot, cutpots)
     932              :       REAL(KIND=dp), DIMENSION(:, :, 0:)                 :: core, hnl
     933              :       TYPE(atom_basis_type), INTENT(INOUT)               :: basis
     934              :       TYPE(atom_sgp_potential_type)                      :: sgp_pot
     935              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: cutpots
     936              : 
     937              :       INTEGER                                            :: i, ia, j, l, m, n, na
     938              :       REAL(KIND=dp)                                      :: a, zval
     939           17 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: cpot, pgauss
     940           17 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: qmat
     941           17 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: rad
     942              : 
     943           17 :       rad => basis%grid%rad
     944           17 :       m = basis%grid%nr
     945              : 
     946              :       ! local pseudopotential
     947           51 :       ALLOCATE (cpot(m))
     948           17 :       IF (sgp_pot%has_local) THEN
     949           98 :          zval = sgp_pot%zval
     950        33602 :          core = 0._dp
     951         6814 :          cpot = 0.0_dp
     952          182 :          DO i = 1, sgp_pot%n_local
     953        81782 :             cpot(:) = cpot(:) + sgp_pot%c_local(i)*EXP(-sgp_pot%a_local(i)*rad(:)**2)
     954              :          END DO
     955         6814 :          cpot(:) = cpot(:)*cutpots(:)
     956           14 :          CALL numpot_matrix(core, cpot, basis, 0)
     957              :       END IF
     958           17 :       DEALLOCATE (cpot)
     959              : 
     960              :       ! nonlocal pseudopotential
     961           17 :       IF (sgp_pot%has_nonlocal) THEN
     962        23357 :          hnl = 0.0_dp
     963           33 :          ALLOCATE (pgauss(1:m))
     964           11 :          n = sgp_pot%n_nonlocal
     965              :          !
     966           33 :          DO l = 0, sgp_pot%lmax
     967           22 :             CPASSERT(l <= UBOUND(basis%nbas, 1))
     968           22 :             IF (.NOT. sgp_pot%is_nonlocal(l)) CYCLE
     969              :             ! overlap (a|p)
     970           21 :             na = basis%nbas(l)
     971           84 :             ALLOCATE (qmat(na, n))
     972          189 :             DO i = 1, n
     973          168 :                a = sgp_pot%a_nonlocal(i)
     974        72168 :                pgauss(:) = cutpots(:)*EXP(-a*rad(:)**2)*rad(:)**l
     975         3069 :                DO ia = 1, na
     976         3048 :                   qmat(ia, i) = integrate_grid(basis%bf(:, ia, l), pgauss(:), basis%grid)
     977              :                END DO
     978              :             END DO
     979        30732 :             qmat(1:na, 1:n) = SQRT(fourpi)*MATMUL(qmat(1:na, 1:n), sgp_pot%c_nonlocal(1:n, 1:n, l))
     980          381 :             DO i = 1, na
     981         3681 :                DO j = i, na
     982        29700 :                   DO ia = 1, n
     983        29700 :                      hnl(i, j, l) = hnl(i, j, l) + qmat(i, ia)*qmat(j, ia)*sgp_pot%h_nonlocal(ia, l)
     984              :                   END DO
     985         3660 :                   hnl(j, i, l) = hnl(i, j, l)
     986              :                END DO
     987              :             END DO
     988           32 :             DEALLOCATE (qmat)
     989              :          END DO
     990           11 :          DEALLOCATE (pgauss)
     991              :       END IF
     992              : 
     993           34 :    END SUBROUTINE sgpints
     994              : 
     995              : ! **************************************************************************************************
     996              : !> \brief ...
     997              : !> \param ac ...
     998              : !> \param vlocal ...
     999              : !> \param r ...
    1000              : !> \param z ...
    1001              : ! **************************************************************************************************
    1002           14 :    SUBROUTINE erffit(ac, vlocal, r, z)
    1003              :       REAL(KIND=dp), INTENT(OUT)                         :: ac
    1004              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: vlocal, r
    1005              :       REAL(KIND=dp), INTENT(IN)                          :: z
    1006              : 
    1007              :       REAL(KIND=dp), PARAMETER                           :: rcut = 1.4_dp
    1008              : 
    1009              :       INTEGER                                            :: i, j, m, m1
    1010              :       REAL(KIND=dp)                                      :: a1, a2, an, e2, en, rc
    1011           14 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: epot, rval, vpot
    1012              : 
    1013           14 :       m = SIZE(r)
    1014           70 :       ALLOCATE (epot(m), vpot(m), rval(m))
    1015           14 :       CPASSERT(SIZE(vlocal) == m)
    1016           14 :       IF (r(1) > r(m)) THEN
    1017            0 :          DO i = 1, m
    1018            0 :             vpot(m - i + 1) = vlocal(i)
    1019            0 :             rval(m - i + 1) = r(i)
    1020              :          END DO
    1021              :       ELSE
    1022        13648 :          vpot(1:m) = vlocal(1:m)
    1023        13648 :          rval(1:m) = r(1:m)
    1024              :       END IF
    1025           14 :       m1 = 1
    1026         9041 :       DO i = 1, m
    1027         9041 :          IF (rval(i) > rcut) THEN
    1028              :             m1 = i
    1029              :             EXIT
    1030              :          END IF
    1031              :       END DO
    1032              : 
    1033           14 :       a1 = 0.2_dp
    1034           14 :       a2 = 0.2_dp
    1035           14 :       e2 = 1.e20_dp
    1036        13648 :       epot = 0.0_dp
    1037          308 :       DO i = 0, 20
    1038          294 :          an = a1 + i*0.025_dp
    1039          294 :          rc = 1._dp/(an*SQRT(2.0_dp))
    1040        97041 :          DO j = m1, m
    1041        97041 :             epot(j) = vpot(j) + z/rval(j)*erf(rval(j)*rc)
    1042              :          END DO
    1043        97041 :          en = SUM(ABS(epot(m1:m)*rval(m1:m)**2))
    1044          308 :          IF (en < e2) THEN
    1045           67 :             e2 = en
    1046           67 :             a2 = an
    1047              :          END IF
    1048              :       END DO
    1049           14 :       ac = a2
    1050              : 
    1051           14 :       DEALLOCATE (epot, vpot, rval)
    1052              : 
    1053           14 :    END SUBROUTINE erffit
    1054              : 
    1055              : ! **************************************************************************************************
    1056              : !> \brief ...
    1057              : !> \param nl ...
    1058              : !> \param al ...
    1059              : !> \param cl ...
    1060              : !> \param vloc ...
    1061              : !> \param vgauss ...
    1062              : !> \param gbasis ...
    1063              : !> \param rad ...
    1064              : !> \param ww ...
    1065              : !> \param method ...
    1066              : !> \param errloc ...
    1067              : ! **************************************************************************************************
    1068         1139 :    SUBROUTINE pplocal_error(nl, al, cl, vloc, vgauss, gbasis, rad, ww, method, errloc)
    1069              :       INTEGER                                            :: nl
    1070              :       REAL(KIND=dp), DIMENSION(:)                        :: al, cl, vloc, vgauss
    1071              :       TYPE(atom_basis_type)                              :: gbasis
    1072              :       REAL(KIND=dp), DIMENSION(:)                        :: rad, ww
    1073              :       INTEGER, INTENT(IN)                                :: method
    1074              :       REAL(KIND=dp)                                      :: errloc
    1075              : 
    1076              :       INTEGER                                            :: ia, ib, ir, ix, la, na
    1077         1139 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: tv
    1078         1139 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: rmat, sinv, smat
    1079         1139 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: gmat
    1080              : 
    1081        14807 :       cl = 0.0_dp
    1082         1139 :       IF (method == 1) THEN
    1083         9112 :          ALLOCATE (tv(nl), smat(nl, nl), sinv(nl, nl))
    1084        14807 :          DO ir = 1, nl
    1085     12999912 :             vgauss(:) = EXP(-al(ir)*rad(:)**2)
    1086       177684 :             DO ix = 1, nl
    1087    156012612 :                smat(ir, ix) = SUM(vgauss(:)*EXP(-al(ix)*rad(:)**2)*ww(:))
    1088              :             END DO
    1089     13001051 :             tv(ir) = SUM(vloc(:)*vgauss(:)*ww(:))
    1090              :          END DO
    1091         1139 :          CALL get_pseudo_inverse_diag(smat(1:nl, 1:nl), sinv(1:nl, 1:nl), 1.e-12_dp)
    1092       192491 :          cl(1:nl) = MATMUL(sinv(1:nl, 1:nl), tv(1:nl))
    1093              :       ELSE
    1094              :          !
    1095            0 :          ALLOCATE (tv(nl), smat(nl, nl), sinv(nl, nl))
    1096              :          !
    1097            0 :          smat = 0.0_dp
    1098            0 :          tv = 0.0_dp
    1099            0 :          DO la = 0, MIN(UBOUND(gbasis%nbas, 1), 3)
    1100            0 :             na = gbasis%nbas(la)
    1101            0 :             ALLOCATE (rmat(na, na), gmat(na, na, nl))
    1102            0 :             rmat = 0.0_dp
    1103            0 :             gmat = 0.0_dp
    1104            0 :             DO ia = 1, na
    1105            0 :                DO ib = ia, na
    1106            0 :                   rmat(ia, ib) = SUM(gbasis%bf(:, ia, la)*gbasis%bf(:, ib, la)*vloc(:)*ww(:))
    1107            0 :                   rmat(ib, ia) = rmat(ia, ib)
    1108              :                END DO
    1109              :             END DO
    1110            0 :             DO ir = 1, nl
    1111            0 :                vgauss(:) = EXP(-al(ir)*rad(:)**2)
    1112            0 :                DO ia = 1, na
    1113            0 :                   DO ib = ia, na
    1114            0 :                      gmat(ia, ib, ir) = SUM(gbasis%bf(:, ia, la)*gbasis%bf(:, ib, la)*vgauss(:)*ww(:))
    1115            0 :                      gmat(ib, ia, ir) = gmat(ia, ib, ir)
    1116              :                   END DO
    1117              :                END DO
    1118              :             END DO
    1119            0 :             DO ir = 1, nl
    1120            0 :                tv(ir) = tv(ir) + accurate_dot_product(rmat, gmat(:, :, ir))
    1121            0 :                DO ix = ir, nl
    1122            0 :                   smat(ir, ix) = smat(ir, ix) + accurate_dot_product(gmat(:, :, ix), gmat(:, :, ir))
    1123            0 :                   smat(ix, ir) = smat(ir, ix)
    1124              :                END DO
    1125              :             END DO
    1126            0 :             DEALLOCATE (rmat, gmat)
    1127              :          END DO
    1128            0 :          sinv = 0.0_dp
    1129            0 :          CALL get_pseudo_inverse_diag(smat(1:nl, 1:nl), sinv(1:nl, 1:nl), 1.e-12_dp)
    1130            0 :          cl(1:nl) = MATMUL(sinv(1:nl, 1:nl), tv(1:nl))
    1131              :       END IF
    1132              :       !
    1133      1083326 :       vgauss = 0.0_dp
    1134        14807 :       DO ir = 1, nl
    1135     13001051 :          vgauss(:) = vgauss(:) + cl(ir)*EXP(-al(ir)*rad(:)**2)
    1136              :       END DO
    1137      1083326 :       errloc = SUM((vgauss - vloc)**2*ww)
    1138              :       !
    1139         1139 :       DEALLOCATE (tv, smat, sinv)
    1140              :       !
    1141         1139 :    END SUBROUTINE pplocal_error
    1142              : 
    1143              : ! **************************************************************************************************
    1144              : !> \brief ...
    1145              : !> \param pot ...
    1146              : !> \param r ...
    1147              : !> \param rcut ...
    1148              : !> \param rsmooth ...
    1149              : ! **************************************************************************************************
    1150           28 :    SUBROUTINE cutpot(pot, r, rcut, rsmooth)
    1151              :       REAL(KIND=dp), DIMENSION(:), INTENT(INOUT)         :: pot
    1152              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: r
    1153              :       REAL(KIND=dp), INTENT(IN)                          :: rcut, rsmooth
    1154              : 
    1155              :       INTEGER                                            :: i, n
    1156              :       REAL(KIND=dp)                                      :: rab, rx, x
    1157              : 
    1158           28 :       n = SIZE(pot)
    1159           28 :       CPASSERT(n <= SIZE(r))
    1160              : 
    1161        20462 :       pot(:) = 1.0_dp
    1162        20462 :       DO i = 1, n
    1163        20434 :          rab = r(i)
    1164        20462 :          IF (rab > rcut) THEN
    1165            0 :             pot(i) = 0.0_dp
    1166        20434 :          ELSE IF (rab > rcut - rsmooth) THEN
    1167           41 :             rx = rab - (rcut - rsmooth)
    1168           41 :             x = rx/rsmooth
    1169           41 :             pot(i) = -6._dp*x**5 + 15._dp*x**4 - 10._dp*x**3 + 1._dp
    1170              :          END IF
    1171              :       END DO
    1172              : 
    1173           28 :    END SUBROUTINE cutpot
    1174              : 
    1175           42 : END MODULE atom_sgp
        

Generated by: LCOV version 2.0-1