LCOV - code coverage report
Current view: top level - src/aobasis - orbital_transformation_matrices.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:262480d) Lines: 130 255 51.0 %
Date: 2024-11-22 07:00:40 Functions: 5 13 38.5 %

          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             : !> \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        6324 :    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        6324 : !$    IF (omp_get_level() > 0) &
      80           0 : !$       CPABORT("create_spherical_harmonics is not thread-safe")
      81             : 
      82        6324 :       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        6324 :       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       52550 :       ALLOCATE (orbtramat(0:maxl))
      95        6324 :       nc = ncoset(maxl)
      96        6324 :       ns = nsoset(maxl)
      97             : 
      98       39902 :       DO l = 0, maxl
      99       33578 :          nc = nco(l)
     100       33578 :          ns = nso(l)
     101      134312 :          ALLOCATE (orbtramat(l)%c2s(ns, nc))
     102     2835312 :          orbtramat(l)%c2s = 0.0_dp
     103      100734 :          ALLOCATE (orbtramat(l)%s2c(ns, nc))
     104     2835312 :          orbtramat(l)%s2c = 0.0_dp
     105      100734 :          ALLOCATE (orbtramat(l)%slm(ns, nc))
     106     2835312 :          orbtramat(l)%slm = 0.0_dp
     107      100734 :          ALLOCATE (orbtramat(l)%slm_inv(ns, nc))
     108     2841636 :          orbtramat(l)%slm_inv = 0.0_dp
     109             :       END DO
     110             : 
     111             :       ! Loop over all angular momentum quantum numbers l
     112             : 
     113       39902 :       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      144611 :          DO lx = 0, l
     119      435511 :             DO ly = 0, l - lx
     120      290900 :                lz = l - lx - ly
     121      290900 :                ic = co(lx, ly, lz)
     122     2912767 :                DO m = -l, l
     123     2510834 :                   is = l + m + 1
     124     2510834 :                   ma = ABS(m)
     125     2510834 :                   j = lx + ly - ma
     126     2801734 :                   IF ((j >= 0) .AND. (MODULO(j, 2) == 0)) THEN
     127     1030878 :                      j = j/2
     128     1030878 :                      s1 = 0.0_dp
     129     3042636 :                      DO i = 0, (l - ma)/2
     130     2011758 :                         s2 = 0.0_dp
     131     5843828 :                         DO k = 0, j
     132     3143113 :                            IF (((m < 0) .AND. (MODULO(ABS(ma - lx), 2) == 1)) .OR. &
     133     3832070 :                                ((m > 0) .AND. (MODULO(ABS(ma - lx), 2) == 0))) THEN
     134     1469866 :                               expo = (ma - lx + 2*k)/2
     135     1469866 :                               s = (-1.0_dp)**expo*SQRT(2.0_dp)
     136     2362204 :                            ELSE IF ((m == 0) .AND. (MODULO(lx, 2) == 0)) THEN
     137      577194 :                               expo = k - lx/2
     138      577194 :                               s = (-1.0_dp)**expo
     139             :                            ELSE
     140             :                               s = 0.0_dp
     141             :                            END IF
     142     5843828 :                            s2 = s2 + binomial(j, k)*binomial(ma, lx - 2*k)*s
     143             :                         END DO
     144             :                         s1 = s1 + binomial(l, i)*binomial(i, j)* &
     145     3042636 :                              (-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     1030878 :                         (2.0_dp**l*fac(l))
     151             :                   ELSE
     152     1479956 :                      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      144611 :          DO lx1 = 0, l
     162      435511 :             DO ly1 = 0, l - lx1
     163      290900 :                lz1 = l - lx1 - ly1
     164      290900 :                ic1 = co(lx1, ly1, lz1)
     165             :                s1 = SQRT((fac(lx1)*fac(ly1)*fac(lz1))/ &
     166      290900 :                          (fac(2*lx1)*fac(2*ly1)*fac(2*lz1)))
     167     1802800 :                DO lx2 = 0, l
     168     6199989 :                   DO ly2 = 0, l - lx2
     169     4508222 :                      lz2 = l - lx2 - ly2
     170     4508222 :                      ic2 = co(lx2, ly2, lz2)
     171     4508222 :                      lx = lx1 + lx2
     172     4508222 :                      ly = ly1 + ly2
     173     4508222 :                      lz = lz1 + lz2
     174             :                      IF ((MODULO(lx, 2) == 0) .AND. &
     175     4508222 :                          (MODULO(ly, 2) == 0) .AND. &
     176     1400867 :                          (MODULO(lz, 2) == 0)) THEN
     177             :                         s2 = SQRT((fac(lx2)*fac(ly2)*fac(lz2))/ &
     178     1236152 :                                   (fac(2*lx2)*fac(2*ly2)*fac(2*lz2)))
     179             :                         s = fac(lx)*fac(ly)*fac(lz)*s1*s2/ &
     180     1236152 :                             (fac(lx/2)*fac(ly/2)*fac(lz/2))
     181    14374750 :                         DO is = 1, nso(l)
     182             :                            orbtramat(l)%s2c(is, ic1) = orbtramat(l)%s2c(is, ic1) + &
     183    14374750 :                                                        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       33578 :          s = SQRT(0.25_dp*dfac(2*l + 1)/pi)
     194             : 
     195      150935 :          DO lx = 0, l
     196      435511 :             DO ly = 0, l - lx
     197      290900 :                lz = l - lx - ly
     198      290900 :                ic = co(lx, ly, lz)
     199     2912767 :                DO m = -l, l
     200     2510834 :                   is = l + m + 1
     201     2510834 :                   s1 = SQRT(dfac(2*lx - 1)*dfac(2*ly - 1)*dfac(2*lz - 1))
     202     2510834 :                   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     2801734 :                   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        6324 :       current_maxl = maxl
     215             : 
     216        6324 :    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       15254 :    SUBROUTINE deallocate_spherical_harmonics()
     225             : 
     226             :       INTEGER                                            :: l
     227             : 
     228       15254 : !$    IF (omp_get_level() > 0) &
     229           0 : !$       CPABORT("deallocate_spherical_harmonics is not thread-safe")
     230             : 
     231       15254 :       IF (current_maxl > -1) THEN
     232       39902 :          DO l = 0, SIZE(orbtramat, 1) - 1
     233       33578 :             DEALLOCATE (orbtramat(l)%c2s)
     234       33578 :             DEALLOCATE (orbtramat(l)%s2c)
     235       33578 :             DEALLOCATE (orbtramat(l)%slm)
     236       39902 :             DEALLOCATE (orbtramat(l)%slm_inv)
     237             :          END DO
     238        6324 :          DEALLOCATE (orbtramat)
     239        6324 :          current_maxl = -1
     240             :       END IF
     241             : 
     242       15254 :    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       23718 :    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       23718 : !$    IF (omp_get_level() > 0) &
     263           0 : !$       CPABORT("init_spherical_harmonics is not thread-safe")
     264             : 
     265       23718 :       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       23718 :       IF (maxl > current_maxl) THEN
     272             : 
     273        6324 :          CALL deallocate_spherical_harmonics()
     274        6324 :          CALL create_spherical_harmonics(maxl)
     275             : 
     276             :          ! Print the spherical harmonics and the orbital transformation matrices
     277             : 
     278        6324 :          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       23718 :    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
     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 1.15