LCOV - code coverage report
Current view: top level - src/aobasis - orbital_transformation_matrices.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:936074a) Lines: 51.0 % 255 130
Test Date: 2025-12-04 06:27:48 Functions: 38.5 % 13 5

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Calculation of the spherical harmonics and the corresponding orbital
      10              : !>        transformation matrices.
      11              : !> \par Literature
      12              : !>      H. B. Schlegel, M. J. Frisch, Int. J. Quantum Chem. 54, 83 (1995)
      13              : !> \par History
      14              : !>      - restructured and cleaned (20.05.2004,MK)
      15              : !> \author Matthias Krack (08.06.2000)
      16              : ! **************************************************************************************************
      17              : MODULE orbital_transformation_matrices
      18              : 
      19              :    USE kinds,                           ONLY: dp
      20              :    USE mathconstants,                   ONLY: dfac,&
      21              :                                               fac,&
      22              :                                               pi
      23              :    USE mathlib,                         ONLY: binomial
      24              :    USE orbital_pointers,                ONLY: co,&
      25              :                                               nco,&
      26              :                                               ncoset,&
      27              :                                               nso,&
      28              :                                               nsoset
      29              :    USE orbital_symbols,                 ONLY: cgf_symbol,&
      30              :                                               sgf_symbol
      31              : 
      32              : !$ USE OMP_LIB, ONLY: omp_get_level
      33              : 
      34              : #include "../base/base_uses.f90"
      35              : 
      36              :    IMPLICIT NONE
      37              : 
      38              :    PRIVATE
      39              : 
      40              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'orbital_transformation_matrices'
      41              : 
      42              :    TYPE orbtramat_type
      43              :       REAL(KIND=dp), DIMENSION(:, :), POINTER :: c2s => NULL(), slm => NULL(), &
      44              :                                                  slm_inv => NULL(), s2c => NULL()
      45              :    END TYPE orbtramat_type
      46              : 
      47              :    TYPE(orbtramat_type), DIMENSION(:), POINTER :: orbtramat => NULL()
      48              : 
      49              :    TYPE orbrotmat_type
      50              :       REAL(KIND=dp), DIMENSION(:, :), POINTER :: mat => NULL()
      51              :    END TYPE orbrotmat_type
      52              : 
      53              :    INTEGER, SAVE :: current_maxl = -1
      54              : 
      55              :    PUBLIC :: orbtramat
      56              :    PUBLIC :: orbrotmat_type, calculate_rotmat, release_rotmat
      57              :    PUBLIC :: deallocate_spherical_harmonics, init_spherical_harmonics
      58              : 
      59              : CONTAINS
      60              : 
      61              : ! **************************************************************************************************
      62              : !> \brief  Allocate and initialize the orbital transformation matrices for
      63              : !>         the transformation and for the backtransformation of orbitals
      64              : !>         from the Cartesian representation to the spherical representation.
      65              : !> \param maxl ...
      66              : !> \date    20.05.2004
      67              : !> \author  MK
      68              : !> \version 1.0
      69              : ! **************************************************************************************************
      70         7068 :    SUBROUTINE create_spherical_harmonics(maxl)
      71              : 
      72              :       INTEGER, INTENT(IN)                                :: maxl
      73              : 
      74              :       INTEGER                                            :: expo, i, ic, ic1, ic2, is, j, k, l, lx, &
      75              :                                                             lx1, lx2, ly, ly1, ly2, lz, lz1, lz2, &
      76              :                                                             m, ma, nc, ns
      77              :       REAL(KIND=dp)                                      :: s, s1, s2
      78              : 
      79         7068 : !$    IF (omp_get_level() > 0) &
      80            0 : !$       CPABORT("create_spherical_harmonics is not thread-safe")
      81              : 
      82         7068 :       IF (current_maxl > -1) THEN
      83              :          CALL cp_abort(__LOCATION__, &
      84              :                        "Spherical harmonics are already allocated. "// &
      85            0 :                        "Use the init routine for an update")
      86              :       END IF
      87              : 
      88         7068 :       IF (maxl < 0) THEN
      89              :          CALL cp_abort(__LOCATION__, &
      90              :                        "A negative maximum angular momentum quantum "// &
      91            0 :                        "number is invalid")
      92              :       END IF
      93              : 
      94        58934 :       ALLOCATE (orbtramat(0:maxl))
      95         7068 :       nc = ncoset(maxl)
      96         7068 :       ns = nsoset(maxl)
      97              : 
      98        44798 :       DO l = 0, maxl
      99        37730 :          nc = nco(l)
     100        37730 :          ns = nso(l)
     101       150920 :          ALLOCATE (orbtramat(l)%c2s(ns, nc))
     102      3211236 :          orbtramat(l)%c2s = 0.0_dp
     103       113190 :          ALLOCATE (orbtramat(l)%s2c(ns, nc))
     104      3211236 :          orbtramat(l)%s2c = 0.0_dp
     105       113190 :          ALLOCATE (orbtramat(l)%slm(ns, nc))
     106      3211236 :          orbtramat(l)%slm = 0.0_dp
     107       113190 :          ALLOCATE (orbtramat(l)%slm_inv(ns, nc))
     108      3218304 :          orbtramat(l)%slm_inv = 0.0_dp
     109              :       END DO
     110              : 
     111              :       ! Loop over all angular momentum quantum numbers l
     112              : 
     113        44798 :       DO l = 0, maxl
     114              : 
     115              :          ! Build the orbital transformation matrix for the transformation
     116              :          ! from Cartesian to spherical orbitals (c2s, formula 15)
     117              : 
     118       162885 :          DO lx = 0, l
     119       491489 :             DO ly = 0, l - lx
     120       328604 :                lz = l - lx - ly
     121       328604 :                ic = co(lx, ly, lz)
     122      3298661 :                DO m = -l, l
     123      2844902 :                   is = l + m + 1
     124      2844902 :                   ma = ABS(m)
     125      2844902 :                   j = lx + ly - ma
     126      3173506 :                   IF ((j >= 0) .AND. (MODULO(j, 2) == 0)) THEN
     127      1167370 :                      j = j/2
     128      1167370 :                      s1 = 0.0_dp
     129      3452476 :                      DO i = 0, (l - ma)/2
     130      2285106 :                         s2 = 0.0_dp
     131      6655588 :                         DO k = 0, j
     132      3583667 :                            IF (((m < 0) .AND. (MODULO(ABS(ma - lx), 2) == 1)) .OR. &
     133      4370482 :                                ((m > 0) .AND. (MODULO(ABS(ma - lx), 2) == 0))) THEN
     134      1678362 :                               expo = (ma - lx + 2*k)/2
     135      1678362 :                               s = (-1.0_dp)**expo*SQRT(2.0_dp)
     136      2692120 :                            ELSE IF ((m == 0) .AND. (MODULO(lx, 2) == 0)) THEN
     137       655174 :                               expo = k - lx/2
     138       655174 :                               s = (-1.0_dp)**expo
     139              :                            ELSE
     140              :                               s = 0.0_dp
     141              :                            END IF
     142      6655588 :                            s2 = s2 + binomial(j, k)*binomial(ma, lx - 2*k)*s
     143              :                         END DO
     144              :                         s1 = s1 + binomial(l, i)*binomial(i, j)* &
     145      3452476 :                              (-1.0_dp)**i*fac(2*l - 2*i)/fac(l - ma - 2*i)*s2
     146              :                      END DO
     147              :                      orbtramat(l)%c2s(is, ic) = &
     148              :                         SQRT((fac(2*lx)*fac(2*ly)*fac(2*lz)*fac(l)*fac(l - ma))/ &
     149              :                              (fac(lx)*fac(ly)*fac(lz)*fac(2*l)*fac(l + ma)))*s1/ &
     150      1167370 :                         (2.0_dp**l*fac(l))
     151              :                   ELSE
     152      1677532 :                      orbtramat(l)%c2s(is, ic) = 0.0_dp
     153              :                   END IF
     154              :                END DO
     155              :             END DO
     156              :          END DO
     157              : 
     158              :          ! Build the corresponding transformation matrix for the transformation from
     159              :          ! spherical to Cartesian orbitals (s2c = s*TRANSPOSE(c2s), formulas 18 and 19)
     160              : 
     161       162885 :          DO lx1 = 0, l
     162       491489 :             DO ly1 = 0, l - lx1
     163       328604 :                lz1 = l - lx1 - ly1
     164       328604 :                ic1 = co(lx1, ly1, lz1)
     165              :                s1 = SQRT((fac(lx1)*fac(ly1)*fac(lz1))/ &
     166       328604 :                          (fac(2*lx1)*fac(2*ly1)*fac(2*lz1)))
     167      2040512 :                DO lx2 = 0, l
     168      7038135 :                   DO ly2 = 0, l - lx2
     169      5122778 :                      lz2 = l - lx2 - ly2
     170      5122778 :                      ic2 = co(lx2, ly2, lz2)
     171      5122778 :                      lx = lx1 + lx2
     172      5122778 :                      ly = ly1 + ly2
     173      5122778 :                      lz = lz1 + lz2
     174              :                      IF ((MODULO(lx, 2) == 0) .AND. &
     175      5122778 :                          (MODULO(ly, 2) == 0) .AND. &
     176      1586753 :                          (MODULO(lz, 2) == 0)) THEN
     177              :                         s2 = SQRT((fac(lx2)*fac(ly2)*fac(lz2))/ &
     178      1403936 :                                   (fac(2*lx2)*fac(2*ly2)*fac(2*lz2)))
     179              :                         s = fac(lx)*fac(ly)*fac(lz)*s1*s2/ &
     180      1403936 :                             (fac(lx/2)*fac(ly/2)*fac(lz/2))
     181     16424002 :                         DO is = 1, nso(l)
     182              :                            orbtramat(l)%s2c(is, ic1) = orbtramat(l)%s2c(is, ic1) + &
     183     16424002 :                                                        s*orbtramat(l)%c2s(is, ic2)
     184              :                         END DO
     185              :                      END IF
     186              :                   END DO
     187              :                END DO
     188              :             END DO
     189              :          END DO
     190              : 
     191              :          ! Build up the real spherical harmonics
     192              : 
     193        37730 :          s = SQRT(0.25_dp*dfac(2*l + 1)/pi)
     194              : 
     195       169953 :          DO lx = 0, l
     196       491489 :             DO ly = 0, l - lx
     197       328604 :                lz = l - lx - ly
     198       328604 :                ic = co(lx, ly, lz)
     199      3298661 :                DO m = -l, l
     200      2844902 :                   is = l + m + 1
     201      2844902 :                   s1 = SQRT(dfac(2*lx - 1)*dfac(2*ly - 1)*dfac(2*lz - 1))
     202      2844902 :                   orbtramat(l)%slm(is, ic) = s*orbtramat(l)%c2s(is, ic)/s1
     203              :                   !MK s2 = (-1.0_dp)**m*s ! alternative S(lm) definition
     204              :                   !MK orbtramat(l)%slm(is, ic) = s2*orbtramat(l)%c2s(is,ic)/s1
     205      3173506 :                   orbtramat(l)%slm_inv(is, ic) = s1*orbtramat(l)%s2c(is, ic)/s
     206              :                END DO
     207              :             END DO
     208              :          END DO
     209              : 
     210              :       END DO
     211              : 
     212              :       ! Save initialization status
     213              : 
     214         7068 :       current_maxl = maxl
     215              : 
     216         7068 :    END SUBROUTINE create_spherical_harmonics
     217              : 
     218              : ! **************************************************************************************************
     219              : !> \brief   Deallocate the orbital transformation matrices.
     220              : !> \date    20.05.2004
     221              : !> \author  MK
     222              : !> \version 1.0
     223              : ! **************************************************************************************************
     224        16752 :    SUBROUTINE deallocate_spherical_harmonics()
     225              : 
     226              :       INTEGER                                            :: l
     227              : 
     228        16752 : !$    IF (omp_get_level() > 0) &
     229            0 : !$       CPABORT("deallocate_spherical_harmonics is not thread-safe")
     230              : 
     231        16752 :       IF (current_maxl > -1) THEN
     232        44798 :          DO l = 0, SIZE(orbtramat, 1) - 1
     233        37730 :             DEALLOCATE (orbtramat(l)%c2s)
     234        37730 :             DEALLOCATE (orbtramat(l)%s2c)
     235        37730 :             DEALLOCATE (orbtramat(l)%slm)
     236        44798 :             DEALLOCATE (orbtramat(l)%slm_inv)
     237              :          END DO
     238         7068 :          DEALLOCATE (orbtramat)
     239         7068 :          current_maxl = -1
     240              :       END IF
     241              : 
     242        16752 :    END SUBROUTINE deallocate_spherical_harmonics
     243              : 
     244              : ! **************************************************************************************************
     245              : !> \brief  Initialize or update the orbital transformation matrices.
     246              : !> \param maxl ...
     247              : !> \param output_unit ...
     248              : !> \date     09.07.1999
     249              : !> \par Variables
     250              : !>      - maxl   : Maximum angular momentum quantum number
     251              : !> \author MK
     252              : !> \version 1.0
     253              : ! **************************************************************************************************
     254        26344 :    SUBROUTINE init_spherical_harmonics(maxl, output_unit)
     255              : 
     256              :       INTEGER, INTENT(IN)                                :: maxl
     257              :       INTEGER                                            :: output_unit
     258              : 
     259              :       CHARACTER(LEN=78)                                  :: headline
     260              :       INTEGER                                            :: l, nc, ns
     261              : 
     262        26344 : !$    IF (omp_get_level() > 0) &
     263            0 : !$       CPABORT("init_spherical_harmonics is not thread-safe")
     264              : 
     265        26344 :       IF (maxl < 0) THEN
     266              :          CALL cp_abort(__LOCATION__, &
     267              :                        "A negative maximum angular momentum quantum "// &
     268            0 :                        "number is invalid")
     269              :       END IF
     270              : 
     271        26344 :       IF (maxl > current_maxl) THEN
     272              : 
     273         7068 :          CALL deallocate_spherical_harmonics()
     274         7068 :          CALL create_spherical_harmonics(maxl)
     275              : 
     276              :          ! Print the spherical harmonics and the orbital transformation matrices
     277              : 
     278         7068 :          IF (output_unit > 0) THEN
     279              : 
     280            4 :             DO l = 0, maxl
     281              : 
     282            3 :                nc = nco(l)
     283            3 :                ns = nso(l)
     284              : 
     285              :                headline = "CARTESIAN ORBITAL TO SPHERICAL ORBITAL "// &
     286            3 :                           "TRANSFORMATION MATRIX"
     287            3 :                CALL write_matrix(orbtramat(l)%c2s, l, output_unit, headline)
     288              : 
     289              :                headline = "SPHERICAL ORBITAL TO CARTESIAN ORBITAL "// &
     290            3 :                           "TRANSFORMATION MATRIX"
     291            3 :                CALL write_matrix(orbtramat(l)%s2c, l, output_unit, headline)
     292              : 
     293            3 :                headline = "SPHERICAL HARMONICS"
     294            3 :                CALL write_matrix(orbtramat(l)%slm, l, output_unit, headline)
     295              : 
     296            3 :                headline = "INVERSE SPHERICAL HARMONICS"
     297            4 :                CALL write_matrix(orbtramat(l)%slm_inv, l, output_unit, headline)
     298              : 
     299              :             END DO
     300              : 
     301            1 :             WRITE (UNIT=output_unit, FMT="(A)") ""
     302              : 
     303              :          END IF
     304              : 
     305              :       END IF
     306              : 
     307        26344 :    END SUBROUTINE init_spherical_harmonics
     308              : 
     309              : ! **************************************************************************************************
     310              : !> \brief   Calculate rotation matrices for spherical harmonics up to value l
     311              : !>          Joseph Ivanic and Klaus Ruedenberg
     312              : !>          Rotation Matrices for Real Spherical Harmonics. Direct Determination by Recursion
     313              : !>          J. Phys. Chem. 1996, 100, 6342-6347
     314              : !> \param orbrotmat ...
     315              : !> \param rotmat ...
     316              : !> \param lval ...
     317              : ! **************************************************************************************************
     318            0 :    SUBROUTINE calculate_rotmat(orbrotmat, rotmat, lval)
     319              :       TYPE(orbrotmat_type), DIMENSION(:), POINTER        :: orbrotmat
     320              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: rotmat
     321              :       INTEGER, INTENT(IN)                                :: lval
     322              : 
     323              :       INTEGER                                            :: l, m1, m2, ns
     324              :       REAL(KIND=dp)                                      :: s3, u, uf, v, vf, w, wf
     325            0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: r
     326              :       REAL(KIND=dp), DIMENSION(-1:1, -1:1)               :: r1
     327              :       REAL(KIND=dp), DIMENSION(-2:2, -2:2)               :: r2
     328              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: t
     329              : 
     330            0 :       CALL release_rotmat(orbrotmat)
     331              : 
     332            0 :       ALLOCATE (orbrotmat(0:lval))
     333            0 :       DO l = 0, lval
     334            0 :          ns = nso(l)
     335            0 :          ALLOCATE (orbrotmat(l)%mat(ns, ns))
     336              :       END DO
     337              : 
     338            0 :       IF (lval >= 0) THEN
     339            0 :          orbrotmat(0)%mat = 1.0_dp
     340              :       END IF
     341            0 :       IF (lval >= 1) THEN
     342            0 :          t(1, 1:3) = rotmat(2, 1:3)
     343            0 :          t(2, 1:3) = rotmat(3, 1:3)
     344            0 :          t(3, 1:3) = rotmat(1, 1:3)
     345            0 :          r1(-1:1, -1) = t(1:3, 2)
     346            0 :          r1(-1:1, 0) = t(1:3, 3)
     347            0 :          r1(-1:1, 1) = t(1:3, 1)
     348            0 :          orbrotmat(1)%mat(1:3, 1:3) = r1(-1:1, -1:1)
     349              :       END IF
     350            0 :       IF (lval >= 2) THEN
     351            0 :          s3 = SQRT(3.0_dp)
     352              :          ! Table 4
     353            0 :          r2(0, 0) = (3.0_dp*r1(0, 0)**2 - 1.0_dp)*0.5_dp
     354            0 :          r2(0, 1) = s3*r1(0, 1)*r1(0, 0)
     355            0 :          r2(0, -1) = s3*r1(0, -1)*r1(0, 0)
     356              :          r2(0, -2) = s3*(r1(0, 1)**2 - r1(0, -1)**2)*0.5_dp
     357            0 :          r2(0, -2) = s3*r1(0, 1)*r1(0, -1)
     358              :          !
     359            0 :          r2(1, 0) = s3*r1(1, 0)*r1(0, 0)
     360            0 :          r2(1, 1) = r1(1, 1)*r1(0, 0) + r1(1, 0)*r1(0, 1)
     361            0 :          r2(1, -1) = r1(1, -1)*r1(0, 0) + r1(1, 0)*r1(0, -1)
     362            0 :          r2(1, 2) = r1(1, 1)*r1(0, 1) - r1(1, -1)*r1(0, -1)
     363            0 :          r2(1, -2) = r1(1, 1)*r1(0, -1) + r1(1, -1)*r1(0, 1)
     364              :          !
     365            0 :          r2(-1, 0) = s3*r1(-1, 0)*r1(0, 0)
     366            0 :          r2(-1, 1) = r1(-1, 1)*r1(0, 0) + r1(-1, 0)*r1(0, 1)
     367            0 :          r2(-1, -1) = r1(-1, -1)*r1(0, 0) + r1(-1, 0)*r1(0, -1)
     368            0 :          r2(-1, 2) = r1(-1, 1)*r1(0, 1) - r1(-1, -1)*r1(0, -1)
     369            0 :          r2(-1, -2) = r1(-1, 1)*r1(0, -1) + r1(-1, -1)*r1(0, 1)
     370              :          !
     371            0 :          r2(2, 0) = s3*(r1(1, 0)**2 - r1(-1, 0)**2)*0.5_dp
     372              :          r2(2, 1) = r1(1, 1)*r1(1, 0) - r1(-1, 1)*r1(-1, 0)
     373              :          r2(2, -1) = r1(1, -1)*r1(1, 0) - r1(-1, -1)*r1(-1, 0)
     374              :          r2(2, 2) = (r1(1, 1)**2 - r1(1, -1)**2 - r1(-1, 1)**2 + r1(-1, -1)**2)*0.5_dp
     375              :          r2(2, -2) = r1(1, 1)*r1(1, -1) - r1(-1, 1)*r1(-1, -1)
     376              :          !
     377            0 :          r2(-2, 0) = s3*r1(1, 0)*r1(-1, 0)
     378            0 :          r2(2, 1) = r1(1, 1)*r1(-1, 0) + r1(1, 0)*r1(-1, 1)
     379            0 :          r2(2, -1) = r1(1, -1)*r1(-1, 0) + r1(1, 0)*r1(-1, -1)
     380            0 :          r2(2, 2) = r1(1, 1)*r1(-1, 1) - r1(1, -1)*r1(-1, -1)
     381            0 :          r2(2, -2) = r1(1, 1)*r1(-1, -1) + r1(1, -1)*r1(-1, 1)
     382              :          !
     383            0 :          orbrotmat(2)%mat(1:5, 1:5) = r2(-2:2, -2:2)
     384              :       END IF
     385            0 :       IF (lval >= 3) THEN
     386              :          ! General recursion
     387            0 :          ALLOCATE (r(0:lval, -lval:lval, -lval:lval))
     388            0 :          r = 0.0_dp
     389            0 :          r(0, 0, 0) = 1.0_dp
     390            0 :          r(1, -1:1, -1:1) = r1(-1:1, -1:1)
     391            0 :          r(2, -2:2, -2:2) = r2(-2:2, -2:2)
     392            0 :          DO l = 3, lval
     393            0 :             DO m1 = -l, l
     394            0 :                DO m2 = -l, l
     395            0 :                   u = u_func(l, m1, m2)
     396            0 :                   v = v_func(l, m1, m2)
     397            0 :                   w = w_func(l, m1, m2)
     398            0 :                   CALL r_recursion(l, m1, m2, r1, r, lval, uf, vf, wf)
     399            0 :                   r(l, m1, m2) = u*uf + v*vf + w*wf
     400              :                END DO
     401              :             END DO
     402              :          END DO
     403            0 :          DO l = 3, lval
     404            0 :             ns = nso(l)
     405            0 :             orbrotmat(l)%mat(1:ns, 1:ns) = r(l, -l:l, -l:l)
     406              :          END DO
     407            0 :          DEALLOCATE (r)
     408              :       END IF
     409              : 
     410            0 :    END SUBROUTINE calculate_rotmat
     411              : 
     412              : ! **************************************************************************************************
     413              : !> \brief ...
     414              : !> \param l ...
     415              : !> \param ma ...
     416              : !> \param mb ...
     417              : !> \return ...
     418              : ! **************************************************************************************************
     419            0 :    FUNCTION u_func(l, ma, mb) RESULT(u)
     420              :       INTEGER                                            :: l, ma, mb
     421              :       REAL(KIND=dp)                                      :: u
     422              : 
     423            0 :       IF (ABS(mb) == l) THEN
     424            0 :          u = REAL((l + ma)*(l - ma), KIND=dp)/REAL(2*l*(2*l - 1), KIND=dp)
     425            0 :          u = SQRT(u)
     426            0 :       ELSE IF (ABS(mb) < l) THEN
     427            0 :          u = REAL((l + ma)*(l - ma), KIND=dp)/REAL((l + mb)*(l - mb), KIND=dp)
     428            0 :          u = SQRT(u)
     429              :       ELSE
     430            0 :          CPABORT("Illegal m value")
     431              :       END IF
     432            0 :    END FUNCTION u_func
     433              : 
     434              : ! **************************************************************************************************
     435              : !> \brief ...
     436              : !> \param l ...
     437              : !> \param ma ...
     438              : !> \param mb ...
     439              : !> \return ...
     440              : ! **************************************************************************************************
     441            0 :    FUNCTION v_func(l, ma, mb) RESULT(v)
     442              :       INTEGER                                            :: l, ma, mb
     443              :       REAL(KIND=dp)                                      :: v
     444              : 
     445              :       INTEGER                                            :: a1, a2, dm0
     446              : 
     447            0 :       dm0 = 0
     448            0 :       IF (ma == 0) dm0 = 1
     449            0 :       IF (ABS(mb) == l) THEN
     450            0 :          a1 = (1 + dm0)*(l + ABS(ma) - 1)*(l + ABS(ma))
     451            0 :          a2 = 2*l*(2*l - 1)
     452            0 :       ELSE IF (ABS(mb) < l) THEN
     453            0 :          a1 = (1 + dm0)*(l + ABS(ma) - 1)*(l + ABS(ma))
     454            0 :          a2 = (l + mb)*(l - mb)
     455              :       ELSE
     456            0 :          CPABORT("Illegal m value")
     457              :       END IF
     458            0 :       v = 0.5_dp*SQRT(REAL(a1, KIND=dp)/REAL(a2, KIND=dp))*REAL(1 - 2*dm0, KIND=dp)
     459            0 :    END FUNCTION v_func
     460              : 
     461              : ! **************************************************************************************************
     462              : !> \brief ...
     463              : !> \param l ...
     464              : !> \param ma ...
     465              : !> \param mb ...
     466              : !> \return ...
     467              : ! **************************************************************************************************
     468            0 :    FUNCTION w_func(l, ma, mb) RESULT(w)
     469              :       INTEGER                                            :: l, ma, mb
     470              :       REAL(KIND=dp)                                      :: w
     471              : 
     472              :       INTEGER                                            :: a1, a2, dm0
     473              : 
     474            0 :       dm0 = 0
     475            0 :       IF (ma == 0) dm0 = 1
     476            0 :       IF (ABS(mb) == l) THEN
     477            0 :          a1 = (l - ABS(ma) - 1)*(l - ABS(ma))
     478            0 :          a2 = 2*l*(2*l - 1)
     479            0 :       ELSE IF (ABS(mb) < l) THEN
     480            0 :          a1 = (l - ABS(ma) - 1)*(l - ABS(ma))
     481            0 :          a2 = (l + mb)*(l - mb)
     482              :       ELSE
     483            0 :          CPABORT("Illegal m value")
     484              :       END IF
     485            0 :       w = -0.5_dp*SQRT(REAL(a1, KIND=dp)/REAL(a2, KIND=dp))*REAL(1 - dm0, KIND=dp)
     486            0 :    END FUNCTION w_func
     487              : 
     488              : ! **************************************************************************************************
     489              : !> \brief ...
     490              : !> \param i ...
     491              : !> \param l ...
     492              : !> \param mu ...
     493              : !> \param m ...
     494              : !> \param r1 ...
     495              : !> \param r ...
     496              : !> \param lr ...
     497              : !> \return ...
     498              : ! **************************************************************************************************
     499            0 :    FUNCTION p_func(i, l, mu, m, r1, r, lr) RESULT(p)
     500              :       INTEGER                                            :: i, l, mu, m
     501              :       REAL(KIND=dp), DIMENSION(-1:1, -1:1)               :: r1
     502              :       INTEGER                                            :: lr
     503              :       REAL(KIND=dp), DIMENSION(0:lr, -lr:lr, -lr:lr)     :: r
     504              :       REAL(KIND=dp)                                      :: p
     505              : 
     506            0 :       IF (m == l) THEN
     507            0 :          p = r1(i, 1)*r(l - 1, mu, m) - r1(i, -1)*r(l - 1, mu, -m)
     508            0 :       ELSE IF (m == -l) THEN
     509            0 :          p = r1(i, 1)*r(l - 1, mu, m) + r1(i, -1)*r(l - 1, mu, -m)
     510            0 :       ELSE IF (ABS(m) < l) THEN
     511            0 :          p = r1(i, 0)*r(l - 1, mu, m)
     512              :       ELSE
     513            0 :          CPABORT("Illegal m value")
     514              :       END IF
     515            0 :    END FUNCTION p_func
     516              : 
     517              : ! **************************************************************************************************
     518              : !> \brief ...
     519              : !> \param l ...
     520              : !> \param ma ...
     521              : !> \param mb ...
     522              : !> \param r1 ...
     523              : !> \param r ...
     524              : !> \param lr ...
     525              : !> \param u ...
     526              : !> \param v ...
     527              : !> \param w ...
     528              : ! **************************************************************************************************
     529            0 :    SUBROUTINE r_recursion(l, ma, mb, r1, r, lr, u, v, w)
     530              :       INTEGER                                            :: l, ma, mb
     531              :       REAL(KIND=dp), DIMENSION(-1:1, -1:1)               :: r1
     532              :       INTEGER                                            :: lr
     533              :       REAL(KIND=dp), DIMENSION(0:lr, -lr:lr, -lr:lr)     :: r
     534              :       REAL(KIND=dp)                                      :: u, v, w
     535              : 
     536              :       REAL(KIND=dp)                                      :: dd
     537              : 
     538            0 :       IF (ma == 0) THEN
     539            0 :          u = p_func(0, l, 0, mb, r1, r, lr)
     540            0 :          v = p_func(1, l, 1, mb, r1, r, lr) + p_func(-1, l, -1, mb, r1, r, lr)
     541            0 :          w = 0.0_dp
     542            0 :       ELSE IF (ma > 0) THEN
     543              :          dd = 1.0_dp
     544              :          IF (ma == 1) dd = 1.0_dp
     545            0 :          u = p_func(0, l, ma, mb, r1, r, lr)
     546            0 :          v = p_func(1, l, ma - 1, mb, r1, r, lr)*SQRT(1.0_dp + dd) - p_func(-1, l, -ma + 1, mb, r1, r, lr)*(1.0_dp - dd)
     547            0 :          w = p_func(1, l, ma + 1, mb, r1, r, lr) + p_func(-1, l, -1 - ma, mb, r1, r, lr)
     548            0 :       ELSE IF (ma < 0) THEN
     549              :          dd = 1.0_dp
     550              :          IF (ma == -1) dd = 1.0_dp
     551            0 :          u = p_func(0, l, ma, mb, r1, r, lr)
     552            0 :          v = p_func(1, l, ma + 1, mb, r1, r, lr)*(1.0_dp - dd) + p_func(-1, l, -ma - 1, mb, r1, r, lr)*SQRT(1.0_dp + dd)
     553            0 :          w = p_func(1, l, ma - 1, mb, r1, r, lr) - p_func(-1, l, -ma + 1, mb, r1, r, lr)
     554              :       END IF
     555            0 :    END SUBROUTINE r_recursion
     556              : 
     557              : ! **************************************************************************************************
     558              : !> \brief   Release rotation matrices
     559              : !> \param orbrotmat ...
     560              : ! **************************************************************************************************
     561           48 :    SUBROUTINE release_rotmat(orbrotmat)
     562              :       TYPE(orbrotmat_type), DIMENSION(:), POINTER        :: orbrotmat
     563              : 
     564              :       INTEGER                                            :: i
     565              : 
     566           48 :       IF (ASSOCIATED(orbrotmat)) THEN
     567            0 :          DO i = LBOUND(orbrotmat, 1), UBOUND(orbrotmat, 1)
     568            0 :             IF (ASSOCIATED(orbrotmat(i)%mat)) DEALLOCATE (orbrotmat(i)%mat)
     569              :          END DO
     570            0 :          DEALLOCATE (orbrotmat)
     571              :       END IF
     572              : 
     573           48 :    END SUBROUTINE release_rotmat
     574              : 
     575              : ! **************************************************************************************************
     576              : !> \brief   Print a matrix to the logical unit "lunit".
     577              : !> \param matrix ...
     578              : !> \param l ...
     579              : !> \param lunit ...
     580              : !> \param headline ...
     581              : !> \date    07.06.2000
     582              : !> \par Variables
     583              : !>      - matrix  : Matrix to be printed.
     584              : !>      - l       : Angular momentum quantum number
     585              : !>      - lunit   : Logical unit number.
     586              : !>      - headline: Headline of the matrix.
     587              : !> \author  MK
     588              : !> \version 1.0
     589              : ! **************************************************************************************************
     590           12 :    SUBROUTINE write_matrix(matrix, l, lunit, headline)
     591              : 
     592              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: matrix
     593              :       INTEGER, INTENT(IN)                                :: l, lunit
     594              :       CHARACTER(LEN=*), INTENT(IN)                       :: headline
     595              : 
     596              :       CHARACTER(12)                                      :: symbol
     597              :       CHARACTER(LEN=78)                                  :: string
     598              :       INTEGER                                            :: from, i, ic, is, jc, lx, ly, lz, m, nc, &
     599              :                                                             to
     600              : 
     601              :       ! Write headline
     602              : 
     603           12 :       WRITE (UNIT=lunit, FMT="(/,/,T2,A)") TRIM(headline)
     604              : 
     605              :       ! Write the matrix in the defined format
     606              : 
     607           12 :       nc = nco(l)
     608              : 
     609           28 :       DO ic = 1, nc, 3
     610           16 :          from = ic
     611           16 :          to = MIN(nc, from + 2)
     612           16 :          i = 1
     613           52 :          DO lx = l, 0, -1
     614          116 :             DO ly = l - lx, 0, -1
     615           64 :                lz = l - lx - ly
     616           64 :                jc = co(lx, ly, lz)
     617          100 :                IF ((jc >= from) .AND. (jc <= to)) THEN
     618          160 :                   symbol = cgf_symbol(1, [lx, ly, lz])
     619           40 :                   WRITE (UNIT=string(i:), FMT="(A18)") TRIM(symbol(3:12))
     620           40 :                   i = i + 18
     621              :                END IF
     622              :             END DO
     623              :          END DO
     624           16 :          WRITE (UNIT=lunit, FMT="(/,T8,A)") TRIM(string)
     625           16 :          symbol = ""
     626           84 :          DO m = -l, l
     627           56 :             is = l + m + 1
     628           56 :             symbol = sgf_symbol(1, l, m)
     629              :             WRITE (UNIT=lunit, FMT="(T4,A4,3(1X,F17.12))") &
     630           72 :                symbol(3:6), (matrix(is, jc), jc=from, to)
     631              :          END DO
     632              :       END DO
     633              : 
     634           12 :    END SUBROUTINE write_matrix
     635              : 
     636            0 : END MODULE orbital_transformation_matrices
        

Generated by: LCOV version 2.0-1