LCOV - code coverage report
Current view: top level - src - atom_sgp.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:4dc10b3) Lines: 533 645 82.6 %
Date: 2024-11-21 06:45:46 Functions: 11 12 91.7 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 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          29 :    SUBROUTINE atom_sgp_release(sgp_pot)
     767             : 
     768             :       TYPE(atom_sgp_potential_type)                      :: sgp_pot
     769             : 
     770          29 :       IF (ASSOCIATED(sgp_pot%a_nonlocal)) DEALLOCATE (sgp_pot%a_nonlocal)
     771          29 :       IF (ASSOCIATED(sgp_pot%h_nonlocal)) DEALLOCATE (sgp_pot%h_nonlocal)
     772          29 :       IF (ASSOCIATED(sgp_pot%c_nonlocal)) DEALLOCATE (sgp_pot%c_nonlocal)
     773             : 
     774          29 :       IF (ASSOCIATED(sgp_pot%a_local)) DEALLOCATE (sgp_pot%a_local)
     775          29 :       IF (ASSOCIATED(sgp_pot%c_local)) DEALLOCATE (sgp_pot%c_local)
     776             : 
     777          29 :       IF (ASSOCIATED(sgp_pot%a_nlcc)) DEALLOCATE (sgp_pot%a_nlcc)
     778          29 :       IF (ASSOCIATED(sgp_pot%c_nlcc)) DEALLOCATE (sgp_pot%c_nlcc)
     779             : 
     780          29 :    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 1.15