LCOV - code coverage report
Current view: top level - src - qs_harmonics_atom.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:24d69ee) Lines: 98.5 % 135 133
Test Date: 2026-09-03 07:32:15 Functions: 85.7 % 7 6

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : ! **************************************************************************************************
       8              : MODULE qs_harmonics_atom
       9              : 
      10              :    USE basis_set_types,                 ONLY: get_gto_basis_set,&
      11              :                                               gto_basis_set_type
      12              :    USE kinds,                           ONLY: dp
      13              :    USE lebedev,                         ONLY: lebedev_grid
      14              :    USE memory_utilities,                ONLY: reallocate
      15              :    USE orbital_pointers,                ONLY: indco,&
      16              :                                               indso,&
      17              :                                               nco,&
      18              :                                               ncoset,&
      19              :                                               nso,&
      20              :                                               nsoset
      21              :    USE orbital_transformation_matrices, ONLY: orbtramat
      22              :    USE spherical_harmonics,             ONLY: dy_lm,&
      23              :                                               y_lm
      24              : #include "./base/base_uses.f90"
      25              : 
      26              :    IMPLICIT NONE
      27              : 
      28              :    PRIVATE
      29              : 
      30              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_harmonics_atom'
      31              : 
      32              :    TYPE harmonics_atom_type
      33              :       INTEGER                                :: max_s_harm = -1, llmax = -1, &
      34              :                                                 max_iso_not0 = -1, &
      35              :                                                 dmax_iso_not0 = -1, &
      36              :                                                 damax_iso_not0 = -1, &
      37              :                                                 ngrid = -1
      38              :       REAL(dp), DIMENSION(:, :), POINTER   :: a => NULL(), slm => NULL()
      39              :       REAL(dp), DIMENSION(:, :, :), POINTER   :: dslm => NULL(), dslm_dxyz => NULL()
      40              :       REAL(dp), DIMENSION(:, :, :), POINTER   :: my_CG => NULL()
      41              :       REAL(dp), DIMENSION(:, :, :, :), POINTER :: my_CG_dxyz => NULL()
      42              :       REAL(dp), DIMENSION(:, :, :, :), POINTER :: my_CG_dxyz_asym => NULL()
      43              :       REAL(dp), DIMENSION(:), POINTER        :: slm_int => NULL()
      44              : 
      45              :    END TYPE harmonics_atom_type
      46              : 
      47              :    PUBLIC :: allocate_harmonics_atom, &
      48              :              create_harmonics_atom, &
      49              :              deallocate_harmonics_atom, &
      50              :              get_none0_cg_list
      51              : 
      52              :    PUBLIC :: harmonics_atom_type, get_maxl_CG
      53              : 
      54              :    INTERFACE get_none0_cg_list
      55              :       MODULE PROCEDURE get_none0_cg_list3, get_none0_cg_list4
      56              :    END INTERFACE
      57              : 
      58              : CONTAINS
      59              : 
      60              : ! **************************************************************************************************
      61              : !> \brief   Allocate a spherical harmonics set for the atom grid.
      62              : !> \param harmonics ...
      63              : !> \version 1.0
      64              : ! **************************************************************************************************
      65         3038 :    SUBROUTINE allocate_harmonics_atom(harmonics)
      66              : 
      67              :       TYPE(harmonics_atom_type), POINTER                 :: harmonics
      68              : 
      69         3038 :       IF (ASSOCIATED(harmonics)) CALL deallocate_harmonics_atom(harmonics)
      70              : 
      71         3038 :       ALLOCATE (harmonics)
      72              : 
      73         3038 :       harmonics%max_s_harm = 0
      74         3038 :       harmonics%llmax = 0
      75         3038 :       harmonics%max_iso_not0 = 0
      76         3038 :       harmonics%dmax_iso_not0 = 0
      77         3038 :       harmonics%damax_iso_not0 = 0
      78         3038 :       harmonics%ngrid = 0
      79              : 
      80              :       NULLIFY (harmonics%slm)
      81              :       NULLIFY (harmonics%dslm)
      82              :       NULLIFY (harmonics%dslm_dxyz)
      83              :       NULLIFY (harmonics%slm_int)
      84              :       NULLIFY (harmonics%my_CG)
      85              :       NULLIFY (harmonics%my_CG_dxyz)
      86              :       NULLIFY (harmonics%my_CG_dxyz_asym)
      87              :       NULLIFY (harmonics%a)
      88              : 
      89         3038 :    END SUBROUTINE allocate_harmonics_atom
      90              : 
      91              : ! **************************************************************************************************
      92              : !> \brief   Deallocate the spherical harmonics set for the atom grid.
      93              : !> \param harmonics ...
      94              : !> \version 1.0
      95              : ! **************************************************************************************************
      96         3038 :    SUBROUTINE deallocate_harmonics_atom(harmonics)
      97              : 
      98              :       TYPE(harmonics_atom_type), POINTER                 :: harmonics
      99              : 
     100         3038 :       IF (ASSOCIATED(harmonics)) THEN
     101              : 
     102         3038 :          IF (ASSOCIATED(harmonics%slm)) THEN
     103         3030 :             DEALLOCATE (harmonics%slm)
     104              :          END IF
     105              : 
     106         3038 :          IF (ASSOCIATED(harmonics%dslm)) THEN
     107         3030 :             DEALLOCATE (harmonics%dslm)
     108              :          END IF
     109              : 
     110         3038 :          IF (ASSOCIATED(harmonics%dslm_dxyz)) THEN
     111         3030 :             DEALLOCATE (harmonics%dslm_dxyz)
     112              :          END IF
     113              : 
     114         3038 :          IF (ASSOCIATED(harmonics%slm_int)) THEN
     115         3030 :             DEALLOCATE (harmonics%slm_int)
     116              :          END IF
     117              : 
     118         3038 :          IF (ASSOCIATED(harmonics%my_CG)) THEN
     119         3038 :             DEALLOCATE (harmonics%my_CG)
     120              :          END IF
     121              : 
     122         3038 :          IF (ASSOCIATED(harmonics%my_CG_dxyz)) THEN
     123         3030 :             DEALLOCATE (harmonics%my_CG_dxyz)
     124              :          END IF
     125              : 
     126         3038 :          IF (ASSOCIATED(harmonics%my_CG_dxyz_asym)) THEN
     127         3030 :             DEALLOCATE (harmonics%my_CG_dxyz_asym)
     128              :          END IF
     129              : 
     130         3038 :          IF (ASSOCIATED(harmonics%a)) THEN
     131         3030 :             DEALLOCATE (harmonics%a)
     132              :          END IF
     133              : 
     134         3038 :          DEALLOCATE (harmonics)
     135              :       ELSE
     136              :          CALL cp_abort(__LOCATION__, &
     137              :                        "The pointer harmonics is not associated and "// &
     138            0 :                        "cannot be deallocated")
     139              :       END IF
     140              : 
     141         3038 :    END SUBROUTINE deallocate_harmonics_atom
     142              : 
     143              : ! **************************************************************************************************
     144              : !> \brief ...
     145              : !> \param harmonics ...
     146              : !> \param my_CG ...
     147              : !> \param na ...
     148              : !> \param llmax ...
     149              : !> \param maxs ...
     150              : !> \param max_s_harm ...
     151              : !> \param ll ...
     152              : !> \param wa ...
     153              : !> \param azi ...
     154              : !> \param pol ...
     155              : !> \note Slight refactoring + OMP parallelized (03.2020 A. Bussy)
     156              : ! **************************************************************************************************
     157         3030 :    SUBROUTINE create_harmonics_atom(harmonics, my_CG, na, llmax, maxs, max_s_harm, ll, wa, azi, pol)
     158              : 
     159              :       TYPE(harmonics_atom_type), POINTER                 :: harmonics
     160              :       REAL(dp), DIMENSION(:, :, :), POINTER              :: my_CG
     161              :       INTEGER, INTENT(IN)                                :: na, llmax, maxs, max_s_harm, ll
     162              :       REAL(dp), DIMENSION(:), INTENT(IN)                 :: wa, azi, pol
     163              : 
     164              :       CHARACTER(len=*), PARAMETER :: routineN = 'create_harmonics_atom'
     165              : 
     166              :       INTEGER                                            :: handle, i, ia, ic, is, is1, is2, iso, &
     167              :                                                             iso1, iso2, l, l1, l2, lmax_grid, lx, &
     168              :                                                             ly, lz, m, m1, m2, max_s_grid, n
     169              :       REAL(dp)                                           :: drx, dry, drz, rx, ry, rz
     170              :       REAL(dp), DIMENSION(2)                             :: cin, dylm
     171         3030 :       REAL(dp), DIMENSION(:), POINTER                    :: slm_int, y
     172         3030 :       REAL(dp), DIMENSION(:, :), POINTER                 :: dc, slm
     173         3030 :       REAL(dp), DIMENSION(:, :, :), POINTER              :: dslm_dxyz
     174              : 
     175         3030 :       CALL timeset(routineN, handle)
     176              : 
     177         3030 :       NULLIFY (y, slm, dslm_dxyz, dc)
     178              : 
     179         3030 :       CPASSERT(ASSOCIATED(harmonics))
     180              : 
     181         3030 :       max_s_grid = MAX(maxs, max_s_harm)
     182         3030 :       lmax_grid = indso(1, max_s_grid)
     183              : 
     184         3030 :       harmonics%max_s_harm = max_s_harm
     185         3030 :       harmonics%llmax = llmax
     186         3030 :       harmonics%ngrid = na
     187              : 
     188         3030 :       NULLIFY (harmonics%my_CG, harmonics%my_CG_dxyz, harmonics%my_CG_dxyz_asym)
     189         3030 :       CALL reallocate(harmonics%my_CG, 1, maxs, 1, maxs, 1, max_s_harm)
     190         3030 :       CALL reallocate(harmonics%my_CG_dxyz, 1, 3, 1, maxs, 1, maxs, 1, max_s_harm)
     191         3030 :       CALL reallocate(harmonics%my_CG_dxyz_asym, 1, 3, 1, maxs, 1, maxs, 1, max_s_harm)
     192              : 
     193        67772 :       DO i = 1, max_s_harm
     194       553024 :          DO is1 = 1, maxs
     195     12876166 :             harmonics%my_CG(1:maxs, is1, i) = my_CG(1:maxs, is1, i)
     196              :          END DO
     197              :       END DO
     198              : 
     199              :       ! allocate and calculate the spherical harmonics LM for this grid
     200              :       ! and their derivatives
     201         3030 :       NULLIFY (harmonics%slm, harmonics%dslm, harmonics%dslm_dxyz, harmonics%a, harmonics%slm_int)
     202         3030 :       CALL reallocate(harmonics%slm, 1, na, 1, max_s_grid)
     203         3030 :       CALL reallocate(harmonics%dslm, 1, 2, 1, na, 1, maxs)
     204         3030 :       CALL reallocate(harmonics%dslm_dxyz, 1, 3, 1, na, 1, max_s_grid)
     205         3030 :       CALL reallocate(harmonics%a, 1, 3, 1, na)
     206         3030 :       CALL reallocate(harmonics%slm_int, 1, max_s_grid)
     207              : 
     208              :       NULLIFY (slm, dslm_dxyz, slm_int)
     209         3030 :       slm => harmonics%slm
     210         3030 :       dslm_dxyz => harmonics%dslm_dxyz
     211     15058124 :       dslm_dxyz = 0.0_dp
     212         3030 :       slm_int => harmonics%slm_int
     213        67772 :       slm_int = 0.0_dp
     214              : 
     215              : !$OMP PARALLEL DEFAULT(NONE), &
     216              : !$OMP SHARED (slm,dslm_dxyz,slm_int,max_s_harm,max_s_grid,ll,lebedev_grid,na,harmonics,wa,indco,orbtramat) &
     217              : !$OMP SHARED (nso,nsoset,nco,maxs,indso,ncoset,pol,azi,llmax,lmax_grid) &
     218              : !$OMP PRIVATE(ia,iso,l,m,i,lx,ly,lz,rx,ry,rz,drx,dry,drz,ic,dc,iso1,iso2,cin,dylm) &
     219         3030 : !$OMP PRIVATE(is1,l1,m1,is2,l2,m2,is,n,y)
     220              : 
     221              :       ALLOCATE (y(na))
     222              : !$OMP DO
     223              :       DO iso = 1, max_s_grid
     224              :          l = indso(1, iso)
     225              :          m = indso(2, iso)
     226              :          CALL y_lm(lebedev_grid(ll)%r, y, l, m)
     227              : 
     228              :          DO ia = 1, na
     229              :             slm(ia, iso) = y(ia)
     230              :             slm_int(iso) = slm_int(iso) + slm(ia, iso)*wa(ia)
     231              :          END DO ! ia
     232              :       END DO ! iso
     233              : !$OMP END DO
     234              :       DEALLOCATE (y)
     235              : 
     236              : !$OMP DO
     237              :       DO ia = 1, na
     238              :          harmonics%a(:, ia) = lebedev_grid(ll)%r(:, ia)
     239              :       END DO
     240              : !$OMP END DO
     241              : 
     242              :       !
     243              :       ! The derivatives dslm_dxyz and its expansions my_CG_dxyz and my_CG_dxyz_asymm
     244              :       ! are NOT the dSlm/dx but the scaled by r**(l-1) derivatives of the monomial
     245              :       ! terms x^n1 y^n2 z^n3 transformed by spherical harmonics expansion coefficients
     246              :       !
     247              : 
     248              :       ALLOCATE (dc(nco(lmax_grid), 3))
     249              : !$OMP DO
     250              :       DO ia = 1, na
     251              :          DO l = 0, lmax_grid
     252              :             DO ic = 1, nco(l)
     253              :                lx = indco(1, ic + ncoset(l - 1))
     254              :                ly = indco(2, ic + ncoset(l - 1))
     255              :                lz = indco(3, ic + ncoset(l - 1))
     256              : 
     257              :                IF (lx == 0) THEN
     258              :                   rx = 1.0_dp
     259              :                   drx = 0.0_dp
     260              :                ELSE IF (lx == 1) THEN
     261              :                   rx = lebedev_grid(ll)%r(1, ia)
     262              :                   drx = 1.0_dp
     263              :                ELSE
     264              :                   rx = lebedev_grid(ll)%r(1, ia)**lx
     265              :                   drx = REAL(lx, dp)*lebedev_grid(ll)%r(1, ia)**(lx - 1)
     266              :                END IF
     267              :                IF (ly == 0) THEN
     268              :                   ry = 1.0_dp
     269              :                   dry = 0.0_dp
     270              :                ELSE IF (ly == 1) THEN
     271              :                   ry = lebedev_grid(ll)%r(2, ia)
     272              :                   dry = 1.0_dp
     273              :                ELSE
     274              :                   ry = lebedev_grid(ll)%r(2, ia)**ly
     275              :                   dry = REAL(ly, dp)*lebedev_grid(ll)%r(2, ia)**(ly - 1)
     276              :                END IF
     277              :                IF (lz == 0) THEN
     278              :                   rz = 1.0_dp
     279              :                   drz = 0.0_dp
     280              :                ELSE IF (lz == 1) THEN
     281              :                   rz = lebedev_grid(ll)%r(3, ia)
     282              :                   drz = 1.0_dp
     283              :                ELSE
     284              :                   rz = lebedev_grid(ll)%r(3, ia)**lz
     285              :                   drz = REAL(lz, dp)*lebedev_grid(ll)%r(3, ia)**(lz - 1)
     286              :                END IF
     287              :                dc(ic, 1) = drx*ry*rz
     288              :                dc(ic, 2) = rx*dry*rz
     289              :                dc(ic, 3) = rx*ry*drz
     290              :             END DO
     291              :             n = nsoset(l - 1)
     292              :             DO is = 1, nso(l)
     293              :                iso = is + n
     294              :                DO ic = 1, nco(l)
     295              :                   dslm_dxyz(:, ia, iso) = dslm_dxyz(:, ia, iso) + &
     296              :                                           orbtramat(l)%slm(is, ic)*dc(ic, :)
     297              :                END DO
     298              :             END DO
     299              :          END DO ! l
     300              :       END DO !ia
     301              : !$OMP END DO
     302              :       DEALLOCATE (dc)
     303              : 
     304              :       ! Expansion coefficients of the cartesian derivatives
     305              :       ! of the product of two harmonics :
     306              :       ! d(Y(l1m1) * Y(l2m2))/dx ; d(Y(l1m1) * Y(l2m2))/dy ; d(Y(l1m1) * Y(l2m2))/dz
     307              : 
     308              : !$OMP DO COLLAPSE(3)
     309              :       DO iso1 = 1, maxs
     310              :          DO iso2 = 1, maxs
     311              :             DO iso = 1, max_s_harm
     312              :                rx = 0.0_dp
     313              :                ry = 0.0_dp
     314              :                rz = 0.0_dp
     315              : 
     316              :                DO ia = 1, na
     317              :                   rx = rx + wa(ia)*slm(ia, iso)* &
     318              :                        (dslm_dxyz(1, ia, iso1)*slm(ia, iso2) + slm(ia, iso1)*dslm_dxyz(1, ia, iso2))
     319              :                   ry = ry + wa(ia)*slm(ia, iso)* &
     320              :                        (dslm_dxyz(2, ia, iso1)*slm(ia, iso2) + slm(ia, iso1)*dslm_dxyz(2, ia, iso2))
     321              :                   rz = rz + wa(ia)*slm(ia, iso)* &
     322              :                        (dslm_dxyz(3, ia, iso1)*slm(ia, iso2) + slm(ia, iso1)*dslm_dxyz(3, ia, iso2))
     323              :                END DO
     324              : 
     325              :                harmonics%my_CG_dxyz(1, iso1, iso2, iso) = rx
     326              :                harmonics%my_CG_dxyz(2, iso1, iso2, iso) = ry
     327              :                harmonics%my_CG_dxyz(3, iso1, iso2, iso) = rz
     328              : 
     329              :             END DO
     330              :          END DO
     331              :       END DO
     332              : !$OMP END DO
     333              : 
     334              :       ! Expansion coefficients of the cartesian of the combinations
     335              :       ! Y(l1m1) * d(Y(l2m2))/dx -  d(Y(l1m1))/dx * Y(l2m2)
     336              :       ! Y(l1m1) * d(Y(l2m2))/dy -  d(Y(l1m1))/dy * Y(l2m2)
     337              :       ! Y(l1m1) * d(Y(l2m2))/dz -  d(Y(l1m1))/dz * Y(l2m2)
     338              : 
     339              : !$OMP DO COLLAPSE(3)
     340              :       DO iso1 = 1, maxs
     341              :          DO iso2 = 1, maxs
     342              :             DO iso = 1, max_s_harm
     343              :                drx = 0.0_dp
     344              :                dry = 0.0_dp
     345              :                drz = 0.0_dp
     346              : 
     347              :                DO ia = 1, na
     348              :                   drx = drx + wa(ia)*slm(ia, iso)* &
     349              :                         (-dslm_dxyz(1, ia, iso1)*slm(ia, iso2) + &
     350              :                          slm(ia, iso1)*dslm_dxyz(1, ia, iso2))
     351              :                   dry = dry + wa(ia)*slm(ia, iso)* &
     352              :                         (-dslm_dxyz(2, ia, iso1)*slm(ia, iso2) + &
     353              :                          slm(ia, iso1)*dslm_dxyz(2, ia, iso2))
     354              :                   drz = drz + wa(ia)*slm(ia, iso)* &
     355              :                         (-dslm_dxyz(3, ia, iso1)*slm(ia, iso2) + &
     356              :                          slm(ia, iso1)*dslm_dxyz(3, ia, iso2))
     357              :                END DO
     358              : 
     359              :                harmonics%my_CG_dxyz_asym(1, iso1, iso2, iso) = drx
     360              :                harmonics%my_CG_dxyz_asym(2, iso1, iso2, iso) = dry
     361              :                harmonics%my_CG_dxyz_asym(3, iso1, iso2, iso) = drz
     362              : 
     363              :             END DO ! iso
     364              :          END DO ! iso2
     365              :       END DO ! iso1
     366              : !$OMP END DO
     367              : 
     368              :       ! Calculate the derivatives of the harmonics with respect of the 2 angles
     369              :       ! the first angle (polar) is acos(lebedev_grid(ll)%r(3))
     370              :       ! the second angle (azimutal) is atan(lebedev_grid(ll)%r(2)/lebedev_grid(ll)%r(1))
     371              : !$OMP DO
     372              :       DO iso = 1, maxs
     373              :          l = indso(1, iso)
     374              :          m = indso(2, iso)
     375              :          DO ia = 1, na
     376              :             cin(1) = pol(ia)
     377              :             cin(2) = azi(ia)
     378              :             CALL dy_lm(cin, dylm, l, m)
     379              :             harmonics%dslm(:, ia, iso) = dylm(:)
     380              :          END DO
     381              :       END DO
     382              : !$OMP END DO
     383              : 
     384              :       ! expansion coefficients of product of polar angle derivatives (dslm(1...)) in
     385              :       ! spherical harmonics (used for tau functionals)
     386              : !$OMP END PARALLEL
     387              : 
     388         3030 :       CALL timestop(handle)
     389              : 
     390         3030 :    END SUBROUTINE create_harmonics_atom
     391              : 
     392              : ! **************************************************************************************************
     393              : !> \brief ...
     394              : !> \param harmonics ...
     395              : !> \param orb_basis ...
     396              : !> \param llmax ...
     397              : !> \param max_s_harm ...
     398              : ! **************************************************************************************************
     399         6060 :    SUBROUTINE get_maxl_CG(harmonics, orb_basis, llmax, max_s_harm)
     400              : 
     401              :       TYPE(harmonics_atom_type), POINTER                 :: harmonics
     402              :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis
     403              :       INTEGER, INTENT(IN)                                :: llmax, max_s_harm
     404              : 
     405              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'get_maxl_CG'
     406              : 
     407              :       INTEGER                                            :: damax_iso_not0, dmax_iso_not0, handle, &
     408              :                                                             is1, is2, itmp, max_iso_not0, nset
     409         3030 :       INTEGER, DIMENSION(:), POINTER                     :: lmax, lmin
     410              : 
     411         3030 :       CALL timeset(routineN, handle)
     412              : 
     413         3030 :       CPASSERT(ASSOCIATED(harmonics))
     414              : 
     415         3030 :       CALL get_gto_basis_set(gto_basis_set=orb_basis, lmax=lmax, lmin=lmin, nset=nset)
     416              : 
     417              :       !   *** Assign indexes for the non null CG coefficients ***
     418         3030 :       max_iso_not0 = 0
     419         3030 :       dmax_iso_not0 = 0
     420         3030 :       damax_iso_not0 = 0
     421        11936 :       DO is1 = 1, nset
     422        49302 :          DO is2 = 1, nset
     423              :             CALL get_none0_cg_list(harmonics%my_CG, &
     424              :                                    lmin(is1), lmax(is1), lmin(is2), lmax(is2), &
     425        37366 :                                    max_s_harm, llmax, max_iso_not0=itmp)
     426        37366 :             max_iso_not0 = MAX(max_iso_not0, itmp)
     427              :             CALL get_none0_cg_list(harmonics%my_CG_dxyz, &
     428              :                                    lmin(is1), lmax(is1), lmin(is2), lmax(is2), &
     429        37366 :                                    max_s_harm, llmax, max_iso_not0=itmp)
     430        37366 :             dmax_iso_not0 = MAX(dmax_iso_not0, itmp)
     431              :             CALL get_none0_cg_list(harmonics%my_CG_dxyz_asym, &
     432              :                                    lmin(is1), lmax(is1), lmin(is2), lmax(is2), &
     433        37366 :                                    max_s_harm, llmax, max_iso_not0=itmp)
     434        46272 :             damax_iso_not0 = MAX(damax_iso_not0, itmp)
     435              :          END DO ! is2
     436              :       END DO ! is1
     437         3030 :       harmonics%max_iso_not0 = max_iso_not0
     438         3030 :       harmonics%dmax_iso_not0 = dmax_iso_not0
     439         3030 :       harmonics%damax_iso_not0 = damax_iso_not0
     440              : 
     441         3030 :       CALL timestop(handle)
     442              : 
     443         3030 :    END SUBROUTINE get_maxl_CG
     444              : 
     445              : ! **************************************************************************************************
     446              : !> \brief ...
     447              : !> \param cgc ...
     448              : !> \param lmin1 ...
     449              : !> \param lmax1 ...
     450              : !> \param lmin2 ...
     451              : !> \param lmax2 ...
     452              : !> \param max_s_harm ...
     453              : !> \param llmax ...
     454              : !> \param list ...
     455              : !> \param n_list ...
     456              : !> \param max_iso_not0 ...
     457              : ! **************************************************************************************************
     458      1103280 :    SUBROUTINE get_none0_cg_list4(cgc, lmin1, lmax1, lmin2, lmax2, max_s_harm, llmax, &
     459      1103280 :                                  list, n_list, max_iso_not0)
     460              : 
     461              :       REAL(dp), DIMENSION(:, :, :, :), INTENT(IN)        :: cgc
     462              :       INTEGER, INTENT(IN)                                :: lmin1, lmax1, lmin2, lmax2, max_s_harm, &
     463              :                                                             llmax
     464              :       INTEGER, DIMENSION(:, :, :), INTENT(OUT), OPTIONAL :: list
     465              :       INTEGER, DIMENSION(:), INTENT(OUT), OPTIONAL       :: n_list
     466              :       INTEGER, INTENT(OUT)                               :: max_iso_not0
     467              : 
     468              :       INTEGER                                            :: iso, iso1, iso2, l1, l2, nlist
     469              : 
     470      1103280 :       CPASSERT(nsoset(lmax1) <= SIZE(cgc, 2))
     471      1103280 :       CPASSERT(nsoset(lmax2) <= SIZE(cgc, 3))
     472      1103280 :       CPASSERT(max_s_harm <= SIZE(cgc, 4))
     473      1103280 :       IF (PRESENT(n_list) .AND. PRESENT(list)) THEN
     474      1028548 :          CPASSERT(max_s_harm <= SIZE(list, 3))
     475              :       END IF
     476      1103280 :       max_iso_not0 = 0
     477     25792408 :       IF (PRESENT(n_list) .AND. PRESENT(list)) n_list = 0
     478     27140704 :       DO iso = 1, max_s_harm
     479     26037424 :          nlist = 0
     480     56888382 :          DO l1 = lmin1, lmax1
     481    134667362 :             DO iso1 = nsoset(l1 - 1) + 1, nsoset(l1)
     482    206121051 :                DO l2 = lmin2, lmax2
     483     97491113 :                   IF (l1 + l2 > llmax) CYCLE
     484    438265168 :                   DO iso2 = nsoset(l2 - 1) + 1, nsoset(l2)
     485    263035525 :                      IF (ABS(cgc(1, iso1, iso2, iso)) + &
     486              :                          ABS(cgc(2, iso1, iso2, iso)) + &
     487     97491113 :                          ABS(cgc(3, iso1, iso2, iso)) > 1.E-8_dp) THEN
     488     33257751 :                         nlist = nlist + 1
     489     33257751 :                         IF (PRESENT(n_list) .AND. PRESENT(list)) THEN
     490     28804337 :                            list(1, nlist, iso) = iso1
     491     28804337 :                            list(2, nlist, iso) = iso2
     492              :                         END IF
     493     33257751 :                         max_iso_not0 = MAX(max_iso_not0, iso)
     494              :                      END IF
     495              :                   END DO
     496              :                END DO
     497              :             END DO
     498              :          END DO
     499     27140704 :          IF (PRESENT(n_list) .AND. PRESENT(list)) n_list(iso) = nlist
     500              :       END DO
     501      1103280 :    END SUBROUTINE get_none0_cg_list4
     502              : 
     503              : ! **************************************************************************************************
     504              : !> \brief ...
     505              : !> \param cgc ...
     506              : !> \param lmin1 ...
     507              : !> \param lmax1 ...
     508              : !> \param lmin2 ...
     509              : !> \param lmax2 ...
     510              : !> \param max_s_harm ...
     511              : !> \param llmax ...
     512              : !> \param list ...
     513              : !> \param n_list ...
     514              : !> \param max_iso_not0 ...
     515              : ! **************************************************************************************************
     516      1912388 :    SUBROUTINE get_none0_cg_list3(cgc, lmin1, lmax1, lmin2, lmax2, max_s_harm, llmax, &
     517      1912388 :                                  list, n_list, max_iso_not0)
     518              : 
     519              :       REAL(dp), DIMENSION(:, :, :), INTENT(IN)           :: cgc
     520              :       INTEGER, INTENT(IN)                                :: lmin1, lmax1, lmin2, lmax2, max_s_harm, &
     521              :                                                             llmax
     522              :       INTEGER, DIMENSION(:, :, :), INTENT(OUT), OPTIONAL :: list
     523              :       INTEGER, DIMENSION(:), INTENT(OUT), OPTIONAL       :: n_list
     524              :       INTEGER, INTENT(OUT)                               :: max_iso_not0
     525              : 
     526              :       INTEGER                                            :: iso, iso1, iso2, l1, l2, nlist
     527              : 
     528      1912388 :       CPASSERT(nsoset(lmax1) <= SIZE(cgc, 1))
     529      1912388 :       CPASSERT(nsoset(lmax2) <= SIZE(cgc, 2))
     530      1912388 :       CPASSERT(max_s_harm <= SIZE(cgc, 3))
     531      1912388 :       IF (PRESENT(n_list) .AND. PRESENT(list)) THEN
     532      1874374 :          CPASSERT(max_s_harm <= SIZE(list, 3))
     533              :       END IF
     534      1912388 :       max_iso_not0 = 0
     535     49040712 :       IF (PRESENT(n_list) .AND. PRESENT(list)) n_list = 0
     536     48370384 :       DO iso = 1, max_s_harm
     537     46457996 :          nlist = 0
     538    101482459 :          DO l1 = lmin1, lmax1
     539    238244242 :             DO iso1 = nsoset(l1 - 1) + 1, nsoset(l1)
     540    363383709 :                DO l2 = lmin2, lmax2
     541    171597463 :                   IF (l1 + l2 > llmax) CYCLE
     542    764710203 :                   DO iso2 = nsoset(l2 - 1) + 1, nsoset(l2)
     543    628010445 :                      IF (ABS(cgc(iso1, iso2, iso)) > 1.E-8_dp) THEN
     544     30510191 :                         nlist = nlist + 1
     545     30510191 :                         IF (PRESENT(n_list) .AND. PRESENT(list)) THEN
     546     29692873 :                            list(1, nlist, iso) = iso1
     547     29692873 :                            list(2, nlist, iso) = iso2
     548              :                         END IF
     549     30510191 :                         max_iso_not0 = MAX(max_iso_not0, iso)
     550              :                      END IF
     551              :                   END DO
     552              :                END DO
     553              :             END DO
     554              :          END DO
     555     48370384 :          IF (PRESENT(n_list) .AND. PRESENT(list)) n_list(iso) = nlist
     556              :       END DO
     557      1912388 :    END SUBROUTINE get_none0_cg_list3
     558              : 
     559            0 : END MODULE qs_harmonics_atom
        

Generated by: LCOV version 2.0-1