LCOV - code coverage report
Current view: top level - src - topology_curvature_unittest.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:9ccafda) Lines: 100.0 % 91 91
Test Date: 2026-10-15 00:55:44 Functions: 100.0 % 5 5

            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            2 : PROGRAM topology_curvature_unittest
       9            2 :    USE kinds,                           ONLY: dp
      10              :    USE topology_curvature,              ONLY: curvature_density,&
      11              :                                               link_plaquette,&
      12              :                                               polar_link
      13              : 
      14              :    IMPLICIT NONE
      15              :    REAL(KIND=dp), PARAMETER :: pi = 3.1415926535897932384626433832795_dp, tolerance = 1.e-11_dp
      16              :    COMPLEX(KIND=dp) :: p(2, 2, 6), q(2, 2, 6), g(2, 2), link(2, 2)
      17              :    REAL(KIND=dp) :: value, maximum, minimum, dirac_value
      18              :    INTEGER :: i, status
      19            2 :    p(:, :, :) = 0.0_dp
      20           14 :    DO i = 1, 6
      21           12 :       p(1, 1, i) = 1.0_dp
      22           14 :       p(2, 2, i) = 1.0_dp
      23              :    END DO
      24            2 :    p(1, 1, 1) = EXP(CMPLX(0.0_dp, 0.2_dp, dp))
      25            2 :    p(2, 2, 1) = EXP(CMPLX(0.0_dp, -0.1_dp, dp))
      26            2 :    p(1, 1, 6) = EXP(CMPLX(0.0_dp, 0.3_dp, dp))
      27            2 :    p(2, 2, 6) = EXP(CMPLX(0.0_dp, 0.4_dp, dp))
      28            2 :    CALL curvature_density(p, 4, pi/2.0_dp, value, maximum, status)
      29            2 :    IF (status /= 0 .OR. ABS(value - 0.02_dp/(4.0_dp*pi*pi)) > tolerance) ERROR STOP 'Incorrect C2 product trace'
      30            6 :    g(1, :) = [CMPLX(1.0_dp, 0.0_dp, dp), CMPLX(0.0_dp, 1.0_dp, dp)]/SQRT(2.0_dp)
      31            6 :    g(2, :) = [CMPLX(0.0_dp, 1.0_dp, dp), CMPLX(1.0_dp, 0.0_dp, dp)]/SQRT(2.0_dp)
      32           14 :    DO i = 1, 6
      33          434 :       q(:, :, i) = MATMUL(CONJG(TRANSPOSE(g)), MATMUL(p(:, :, i), g))
      34              :    END DO
      35            2 :    CALL curvature_density(q, 4, pi/2.0_dp, value, maximum, status)
      36            2 :    IF (status /= 0 .OR. ABS(value - 0.02_dp/(4.0_dp*pi*pi)) > tolerance) ERROR STOP 'C2 gauge covariance failed'
      37            2 :    CALL curvature_density(p(:, :, 1:1), 2, pi/2.0_dp, value, maximum, status)
      38            2 :    IF (status /= 0 .OR. ABS(value + 0.1_dp/(2.0_dp*pi)) > tolerance) ERROR STOP 'Incorrect determinant C1 phase'
      39            2 :    CALL curvature_density(p, 4, 0.1_dp, value, maximum, status)
      40            2 :    IF (status /= -3) ERROR STOP 'Unresolved C2 phase accepted'
      41           14 :    p(:, :, 1) = 0.0_dp
      42            2 :    CALL polar_link(p(:, :, 1), link, minimum, status, tolerance)
      43            2 :    IF (status == 0) ERROR STOP 'Singular link accepted'
      44            2 :    CALL curvature_density(p, 4, pi/2.0_dp, value, maximum, status)
      45            2 :    IF (status /= -2) ERROR STOP 'Nonunitary plaquette accepted'
      46            2 :    CALL dirac_pairing(8, dirac_value)
      47            2 :    IF (ABS(dirac_value + 0.742412846261164_dp) > 1.e-6_dp) ERROR STOP 'Incorrect non-Abelian Dirac C2'
      48              : CONTAINS
      49              : 
      50              : ! **************************************************************************************************
      51              : !> \brief Non-Abelian occupied doublet of the 4D Dirac model, exact C2=-1 at mass -3.
      52              : !> \param n ...
      53              : !> \param RESULT ...
      54              : ! **************************************************************************************************
      55            2 :    SUBROUTINE dirac_pairing(n, RESULT)
      56              :       INTEGER, INTENT(IN)                                :: n
      57              :       REAL(KIND=dp), INTENT(OUT)                         :: result
      58              : 
      59              :       COMPLEX(KIND=dp)                                   :: gamma(4, 4, 5), h(4, 4), id(2, 2), &
      60              :                                                             overlap(2, 2), plaquettes(2, 2, 6), &
      61              :                                                             sx(2, 2), sy(2, 2), sz(2, 2), work(32)
      62            2 :       COMPLEX(KIND=dp), ALLOCATABLE                      :: links(:, :, :, :), states(:, :, :)
      63              :       INTEGER                                            :: at_mu, at_nu, d, INDEX(4), mu, nu, &
      64              :                                                             other, p, rem, status, v
      65              :       REAL(KIND=dp)                                      :: evals(4), k(4), local_value, maximum, &
      66              :                                                             minimum, rwork(12)
      67              : 
      68            2 :       sx = 0.0_dp
      69            2 :       sx(1, 2) = 1.0_dp
      70            2 :       sx(2, 1) = 1.0_dp
      71           14 :       sy = CMPLX(0.0_dp, 1.0_dp, dp)*sx
      72            2 :       sy(1, 2) = -sy(1, 2)
      73            2 :       sz = 0.0_dp
      74            2 :       sz(1, 1) = 1.0_dp
      75            2 :       sz(2, 2) = -1.0_dp
      76            2 :       id = 0.0_dp
      77            2 :       id(1, 1) = 1.0_dp
      78            2 :       id(2, 2) = 1.0_dp
      79            2 :       CALL tensor(sx, sx, gamma(:, :, 1))
      80            2 :       CALL tensor(sx, sy, gamma(:, :, 2))
      81            2 :       CALL tensor(sx, sz, gamma(:, :, 3))
      82            2 :       CALL tensor(sy, id, gamma(:, :, 4))
      83            2 :       CALL tensor(sz, id, gamma(:, :, 5))
      84           10 :       ALLOCATE (states(4, 2, n**4), links(2, 2, 4, n**4))
      85         8194 :       DO v = 1, n**4
      86         8192 :          rem = v - 1
      87        40960 :          DO d = 1, 4
      88        32768 :             INDEX(d) = MOD(rem, n)
      89        40960 :             rem = rem/n
      90              :          END DO
      91        40960 :          k = 2.0_dp*pi*REAL(index, dp)/REAL(n, dp)
      92         8192 :          h = CMPLX(0.0_dp, 0.0_dp, dp)
      93        40960 :          DO d = 1, 4
      94       696320 :             h = h + SIN(k(d))*gamma(:, :, d)
      95              :          END DO
      96       204800 :          h = h + (-3.0_dp + SUM(COS(k)))*gamma(:, :, 5)
      97         8192 :          CALL zheev('V', 'U', 4, h, 4, evals, work, SIZE(work), rwork, status)
      98         8192 :          IF (status /= 0) ERROR STOP 'Dirac eigensolver failed'
      99        90114 :          states(:, :, v) = h(:, 1:2)
     100              :       END DO
     101         8194 :       DO v = 1, n**4
     102        40962 :          DO d = 1, 4
     103        32768 :             other = neighbour(v, d, n)
     104       753664 :             overlap = MATMUL(CONJG(TRANSPOSE(states(:, :, v))), states(:, :, other))
     105        32768 :             CALL polar_link(overlap, links(:, :, d, v), minimum, status, tolerance)
     106        40960 :             IF (status /= 0) ERROR STOP 'Singular Dirac link'
     107              :          END DO
     108              :       END DO
     109            2 :       RESULT = 0.0_dp
     110         8194 :       DO v = 1, n**4
     111         8192 :          p = 0
     112        40960 :          DO mu = 1, 4
     113        90112 :             DO nu = mu + 1, 4
     114        49152 :                p = p + 1
     115        49152 :                at_mu = neighbour(v, mu, n)
     116        49152 :                at_nu = neighbour(v, nu, n)
     117              :                CALL link_plaquette(links(:, :, mu, v), links(:, :, nu, at_mu), links(:, :, mu, at_nu), &
     118        81920 :                                    links(:, :, nu, v), plaquettes(:, :, p))
     119              :             END DO
     120              :          END DO
     121         8192 :          CALL curvature_density(plaquettes, 4, pi/2.0_dp, local_value, maximum, status)
     122         8192 :          IF (status /= 0) ERROR STOP 'Invalid Dirac plaquette'
     123         8194 :          RESULT = RESULT + local_value
     124              :       END DO
     125            4 :    END SUBROUTINE dirac_pairing
     126              : 
     127              : ! **************************************************************************************************
     128              : !> \brief Periodic forward neighbour in a first-axis-fastest mesh.
     129              : !> \param v ...
     130              : !> \param d ...
     131              : !> \param n ...
     132              : !> \return ...
     133              : ! **************************************************************************************************
     134       131072 :    INTEGER FUNCTION neighbour(v, d, n) RESULT(other)
     135              :       INTEGER, INTENT(IN)                                :: v, d, n
     136              : 
     137              :       INTEGER                                            :: coordinate, stride
     138              : 
     139       131072 :       stride = n**(d - 1)
     140       131072 :       coordinate = MOD((v - 1)/stride, n)
     141       131072 :       other = v + stride
     142       131072 :       IF (coordinate == n - 1) other = other - n*stride
     143       131072 :    END FUNCTION neighbour
     144              : 
     145              : ! **************************************************************************************************
     146              : !> \brief Kronecker product of two 2x2 matrices.
     147              : !> \param a ...
     148              : !> \param b ...
     149              : !> \param c ...
     150              : ! **************************************************************************************************
     151           10 :    SUBROUTINE tensor(a, b, c)
     152              :       COMPLEX(KIND=dp), INTENT(IN)                       :: a(2, 2), b(2, 2)
     153              :       COMPLEX(KIND=dp), INTENT(OUT)                      :: c(4, 4)
     154              : 
     155              :       INTEGER                                            :: i, j
     156              : 
     157           30 :       DO j = 1, 2
     158           70 :          DO i = 1, 2
     159          300 :             c(2*i - 1:2*i, 2*j - 1:2*j) = a(i, j)*b
     160              :          END DO
     161              :       END DO
     162           10 :    END SUBROUTINE tensor
     163              : END PROGRAM topology_curvature_unittest
        

Generated by: LCOV version 2.0-1