LCOV - code coverage report
Current view: top level - src/motion - pint_normalmode.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:b279b6b) Lines: 103 107 96.3 %
Date: 2024-04-24 07:13:09 Functions: 7 7 100.0 %

          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  Data type and methods dealing with PI calcs in normal mode coords
      10             : !> \author fawzi
      11             : !> \par    History
      12             : !>         2006-02 created
      13             : !>         2006-11 modified so it might actually work [hforbert]
      14             : !>         2009-04-07 moved from pint_types module to a separate file [lwalewski]
      15             : !>         2015-10 added alternative normal mode transformation needed by RPMD
      16             : !>                 [Felix Uhl
      17             : ! **************************************************************************************************
      18             : MODULE pint_normalmode
      19             :    USE input_constants,                 ONLY: propagator_cmd,&
      20             :                                               propagator_pimd,&
      21             :                                               propagator_rpmd
      22             :    USE input_section_types,             ONLY: section_vals_type,&
      23             :                                               section_vals_val_get
      24             :    USE kinds,                           ONLY: dp
      25             :    USE mathconstants,                   ONLY: pi,&
      26             :                                               twopi
      27             :    USE pint_types,                      ONLY: normalmode_env_type
      28             : #include "../base/base_uses.f90"
      29             : 
      30             :    IMPLICIT NONE
      31             :    PRIVATE
      32             : 
      33             :    LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .TRUE.
      34             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'pint_normalmode'
      35             : 
      36             :    PUBLIC :: normalmode_env_create
      37             :    PUBLIC :: normalmode_release
      38             :    PUBLIC :: normalmode_init_masses
      39             :    PUBLIC :: normalmode_x2u
      40             :    PUBLIC :: normalmode_u2x
      41             :    PUBLIC :: normalmode_f2uf
      42             :    PUBLIC :: normalmode_calc_uf_h
      43             : 
      44             : CONTAINS
      45             : 
      46             : ! ***************************************************************************
      47             : !> \brief creates the data needed for a normal mode transformation
      48             : !> \param normalmode_env ...
      49             : !> \param normalmode_section ...
      50             : !> \param p ...
      51             : !> \param kT ...
      52             : !> \param propagator ...
      53             : !> \author Harald Forbert
      54             : ! **************************************************************************************************
      55          56 :    SUBROUTINE normalmode_env_create(normalmode_env, normalmode_section, p, kT, propagator)
      56             :       TYPE(normalmode_env_type), INTENT(OUT)             :: normalmode_env
      57             :       TYPE(section_vals_type), POINTER                   :: normalmode_section
      58             :       INTEGER, INTENT(in)                                :: p
      59             :       REAL(kind=dp), INTENT(in)                          :: kT
      60             :       INTEGER, INTENT(in)                                :: propagator
      61             : 
      62             :       INTEGER                                            :: i, j, k, li
      63             :       LOGICAL                                            :: explicit_gamma, explicit_modefactor
      64             :       REAL(kind=dp)                                      :: gamma_parameter, invsqrtp, pip, sqrt2p, &
      65             :                                                             twopip
      66             : 
      67         224 :       ALLOCATE (normalmode_env%x2u(p, p))
      68         224 :       ALLOCATE (normalmode_env%u2x(p, p))
      69         168 :       ALLOCATE (normalmode_env%lambda(p))
      70             : 
      71          56 :       normalmode_env%p = p
      72             : 
      73             :       CALL section_vals_val_get(normalmode_section, "Q_CENTROID", &
      74          56 :                                 r_val=normalmode_env%Q_centroid)
      75             :       CALL section_vals_val_get(normalmode_section, "Q_BEAD", &
      76          56 :                                 r_val=normalmode_env%Q_bead)
      77             :       CALL section_vals_val_get(normalmode_section, "MODEFACTOR", &
      78             :                                 explicit=explicit_modefactor, &
      79          56 :                                 r_val=normalmode_env%modefactor)
      80             :       CALL section_vals_val_get(normalmode_section, "GAMMA", &
      81             :                                 r_val=gamma_parameter, &
      82          56 :                                 explicit=explicit_gamma)
      83             : 
      84          56 :       IF (explicit_modefactor .AND. explicit_gamma) THEN
      85           0 :          CPABORT("Both GAMMA and MODEFACTOR have been declared. Please use only one.")
      86             :       END IF
      87          56 :       IF (explicit_gamma) THEN
      88           4 :          normalmode_env%modefactor = 1.0_dp/gamma_parameter**2
      89             :       END IF
      90             : 
      91          56 :       IF (propagator == propagator_cmd) THEN
      92           4 :          IF (.NOT. explicit_gamma) THEN
      93           0 :             CPABORT("GAMMA needs to be specified with CMD PROPAGATOR")
      94             :          END IF
      95           4 :          IF (gamma_parameter <= 1.0_dp) THEN
      96           0 :             CPWARN("GAMMA should be larger than 1.0 for CMD PROPAGATOR")
      97             :          END IF
      98             :       END IF
      99             : 
     100          56 :       IF (normalmode_env%Q_centroid < 0.0_dp) THEN
     101          56 :          normalmode_env%Q_centroid = -normalmode_env%Q_centroid/(kT*p)
     102             :       END IF
     103          56 :       IF (normalmode_env%Q_bead < 0.0_dp) THEN
     104          56 :          normalmode_env%Q_bead = -normalmode_env%Q_bead/(kT*p)
     105             :       END IF
     106             : 
     107             :       !Use different normal mode transformations depending on the propagator
     108          56 :       IF (propagator == propagator_pimd .OR. propagator == propagator_cmd) THEN
     109             : 
     110          38 :          IF (propagator == propagator_pimd) THEN
     111          34 :             normalmode_env%harm = p*kT*kT/normalmode_env%modefactor
     112           4 :          ELSE IF (propagator == propagator_cmd) THEN
     113           4 :             normalmode_env%harm = p*kT*kT*gamma_parameter*gamma_parameter
     114           4 :             normalmode_env%modefactor = 1.0_dp/(gamma_parameter*gamma_parameter)
     115             :          END IF
     116             : 
     117             :          ! set up the transformation matrices
     118         214 :          DO i = 1, p
     119         176 :             normalmode_env%lambda(i) = 2.0_dp*(1.0_dp - COS(pi*(i/2)*2.0_dp/p))
     120        1206 :             DO j = 1, p
     121         992 :                k = ((i/2)*(j - 1))/p
     122         992 :                k = (i/2)*(j - 1) - k*p
     123         992 :                li = 2*(i - 2*(i/2))*p - p
     124        1168 :                normalmode_env%u2x(j, i) = SQRT(2.0_dp/p)*SIN(twopi*(k + 0.125_dp*li)/p)
     125             :             END DO
     126             :          END DO
     127          38 :          normalmode_env%lambda(1) = 1.0_dp/(p*normalmode_env%modefactor)
     128         214 :          DO i = 1, p
     129        1206 :             DO j = 1, p
     130             :                normalmode_env%x2u(i, j) = SQRT(normalmode_env%lambda(i)* &
     131             :                                                normalmode_env%modefactor)* &
     132        1168 :                                           normalmode_env%u2x(j, i)
     133             :             END DO
     134             :          END DO
     135         214 :          DO i = 1, p
     136        1206 :             DO j = 1, p
     137             :                normalmode_env%u2x(i, j) = normalmode_env%u2x(i, j)/ &
     138             :                                           SQRT(normalmode_env%lambda(j)* &
     139        1168 :                                                normalmode_env%modefactor)
     140             :             END DO
     141             :          END DO
     142         214 :          normalmode_env%lambda(:) = normalmode_env%harm
     143             : 
     144          18 :       ELSE IF (propagator == propagator_rpmd) THEN
     145          18 :          normalmode_env%harm = kT/normalmode_env%modefactor
     146          18 :          sqrt2p = SQRT(2.0_dp/REAL(p, dp))
     147          18 :          twopip = twopi/REAL(p, dp)
     148          18 :          pip = pi/REAL(p, dp)
     149          18 :          invsqrtp = 1.0_dp/SQRT(REAL(p, dp))
     150        3226 :          normalmode_env%x2u(:, :) = 0.0_dp
     151         186 :          normalmode_env%x2u(1, :) = invsqrtp
     152         186 :          DO j = 1, p
     153        1688 :             DO i = 2, p/2 + 1
     154        1688 :                normalmode_env%x2u(i, j) = sqrt2p*COS(twopip*(i - 1)*(j - 1))
     155             :             END DO
     156        1538 :             DO i = p/2 + 2, p
     157        1520 :                normalmode_env%x2u(i, j) = sqrt2p*SIN(twopip*(i - 1)*(j - 1))
     158             :             END DO
     159             :          END DO
     160          18 :          IF (MOD(p, 2) == 0) THEN
     161          18 :             DO i = 1, p - 1, 2
     162          84 :                normalmode_env%x2u(p/2 + 1, i) = invsqrtp
     163          84 :                normalmode_env%x2u(p/2 + 1, i + 1) = -1.0_dp*invsqrtp
     164             :             END DO
     165             :          END IF
     166             : 
     167        6434 :          normalmode_env%u2x = TRANSPOSE(normalmode_env%x2u)
     168             : 
     169             :          ! Setting up propagator frequencies for rpmd
     170          18 :          normalmode_env%lambda(1) = 0.0_dp
     171         168 :          DO i = 2, p
     172         150 :             normalmode_env%lambda(i) = 2.0_dp*normalmode_env%harm*SIN((i - 1)*pip)
     173         168 :             normalmode_env%lambda(i) = normalmode_env%lambda(i)*normalmode_env%lambda(i)
     174             :          END DO
     175          18 :          normalmode_env%harm = kT*kT
     176             :       ELSE
     177           0 :          CPABORT("UNKNOWN PROPAGATOR FOR PINT SELECTED")
     178             :       END IF
     179             : 
     180          56 :    END SUBROUTINE normalmode_env_create
     181             : 
     182             : ! ***************************************************************************
     183             : !> \brief releases the normalmode environment
     184             : !> \param normalmode_env the normalmode_env to release
     185             : !> \author Harald Forbert
     186             : ! **************************************************************************************************
     187          56 :    PURE SUBROUTINE normalmode_release(normalmode_env)
     188             : 
     189             :       TYPE(normalmode_env_type), INTENT(INOUT)           :: normalmode_env
     190             : 
     191          56 :       DEALLOCATE (normalmode_env%x2u)
     192          56 :       DEALLOCATE (normalmode_env%u2x)
     193          56 :       DEALLOCATE (normalmode_env%lambda)
     194             : 
     195          56 :    END SUBROUTINE normalmode_release
     196             : 
     197             : ! ***************************************************************************
     198             : !> \brief initializes the masses and fictitious masses compatible with the
     199             : !>      normal mode information
     200             : !> \param normalmode_env the definition of the normal mode transformation
     201             : !> \param mass *input* the masses of the particles
     202             : !> \param mass_beads masses of the beads
     203             : !> \param mass_fict the fictitious masses
     204             : !> \param Q masses of the nose thermostats
     205             : !> \author Harald Forbert
     206             : ! **************************************************************************************************
     207          56 :    PURE SUBROUTINE normalmode_init_masses(normalmode_env, mass, mass_beads, mass_fict, &
     208          56 :                                           Q)
     209             : 
     210             :       TYPE(normalmode_env_type), INTENT(IN)              :: normalmode_env
     211             :       REAL(kind=dp), DIMENSION(:), INTENT(in)            :: mass
     212             :       REAL(kind=dp), DIMENSION(:, :), INTENT(out), &
     213             :          OPTIONAL                                        :: mass_beads, mass_fict
     214             :       REAL(kind=dp), DIMENSION(:), INTENT(out), OPTIONAL :: Q
     215             : 
     216             :       INTEGER                                            :: iat, ib
     217             : 
     218          56 :       IF (PRESENT(Q)) THEN
     219         400 :          Q = normalmode_env%Q_bead
     220          56 :          Q(1) = normalmode_env%Q_centroid
     221             :       END IF
     222          56 :       IF (PRESENT(mass_beads) .OR. PRESENT(mass_fict)) THEN
     223          56 :          IF (PRESENT(mass_beads)) THEN
     224       64964 :             DO iat = 1, SIZE(mass)
     225       64908 :                mass_beads(1, iat) = 0.0_dp
     226      297632 :                DO ib = 2, normalmode_env%p
     227      297576 :                   mass_beads(ib, iat) = mass(iat)
     228             :                END DO
     229             :             END DO
     230             :          END IF
     231          56 :          IF (PRESENT(mass_fict)) THEN
     232       64964 :             DO iat = 1, SIZE(mass)
     233      362540 :                DO ib = 1, normalmode_env%p
     234      362484 :                   mass_fict(ib, iat) = mass(iat)
     235             :                END DO
     236             :             END DO
     237             :          END IF
     238             :       END IF
     239             : 
     240          56 :    END SUBROUTINE normalmode_init_masses
     241             : 
     242             : ! ***************************************************************************
     243             : !> \brief Transforms from the x into the u variables using a normal mode
     244             : !>      transformation for the positions
     245             : !> \param normalmode_env the environment for the normal mode transformation
     246             : !> \param ux will contain the u variable
     247             : !> \param x the positions to transform
     248             : !> \author Harald Forbert
     249             : ! **************************************************************************************************
     250          95 :    SUBROUTINE normalmode_x2u(normalmode_env, ux, x)
     251             :       TYPE(normalmode_env_type), INTENT(INOUT)           :: normalmode_env
     252             :       REAL(kind=dp), DIMENSION(:, :), INTENT(out)        :: ux
     253             :       REAL(kind=dp), DIMENSION(:, :), INTENT(in)         :: x
     254             : 
     255             :       CALL DGEMM('N', 'N', normalmode_env%p, SIZE(x, 2), normalmode_env%p, 1.0_dp, &
     256             :                  normalmode_env%x2u(1, 1), SIZE(normalmode_env%x2u, 1), x(1, 1), SIZE(x, 1), &
     257          95 :                  0.0_dp, ux, SIZE(ux, 1))
     258          95 :    END SUBROUTINE normalmode_x2u
     259             : 
     260             : ! ***************************************************************************
     261             : !> \brief transform from the u variable to the x (back normal mode
     262             : !>      transformation for the positions)
     263             : !> \param normalmode_env the environment for the normal mode transformation
     264             : !> \param ux the u variable (positions to be backtransformed)
     265             : !> \param x will contain the positions
     266             : !> \author Harald Forbert
     267             : ! **************************************************************************************************
     268        2243 :    SUBROUTINE normalmode_u2x(normalmode_env, ux, x)
     269             :       TYPE(normalmode_env_type), INTENT(INOUT)           :: normalmode_env
     270             :       REAL(kind=dp), DIMENSION(:, :), INTENT(in)         :: ux
     271             :       REAL(kind=dp), DIMENSION(:, :), INTENT(out)        :: x
     272             : 
     273             :       CALL DGEMM('N', 'N', normalmode_env%p, SIZE(ux, 2), normalmode_env%p, 1.0_dp, &
     274             :                  normalmode_env%u2x(1, 1), SIZE(normalmode_env%u2x, 1), ux(1, 1), SIZE(ux, 1), &
     275        2243 :                  0.0_dp, x, SIZE(x, 1))
     276        2243 :    END SUBROUTINE normalmode_u2x
     277             : 
     278             : ! ***************************************************************************
     279             : !> \brief normalmode transformation for the forces
     280             : !> \param normalmode_env the environment for the normal mode transformation
     281             : !> \param uf will contain the forces for the transformed variables afterwards
     282             : !> \param f the forces to transform
     283             : !> \author Harald Forbert
     284             : ! **************************************************************************************************
     285         510 :    SUBROUTINE normalmode_f2uf(normalmode_env, uf, f)
     286             :       TYPE(normalmode_env_type), INTENT(INOUT)           :: normalmode_env
     287             :       REAL(kind=dp), DIMENSION(:, :), INTENT(out)        :: uf
     288             :       REAL(kind=dp), DIMENSION(:, :), INTENT(in)         :: f
     289             : 
     290             :       CALL DGEMM('T', 'N', normalmode_env%p, SIZE(f, 2), normalmode_env%p, 1.0_dp, &
     291             :                  normalmode_env%u2x(1, 1), SIZE(normalmode_env%u2x, 1), f(1, 1), SIZE(f, 1), &
     292         510 :                  0.0_dp, uf, SIZE(uf, 1))
     293         510 :    END SUBROUTINE normalmode_f2uf
     294             : 
     295             : ! ***************************************************************************
     296             : !> \brief calculates the harmonic force in the normal mode basis
     297             : !> \param normalmode_env the normal mode environment
     298             : !> \param mass_beads the masses of the beads
     299             : !> \param ux the positions of the beads in the staging basis
     300             : !> \param uf_h the harmonic forces (not accelerations)
     301             : !> \param e_h ...
     302             : !> \author Harald Forbert
     303             : ! **************************************************************************************************
     304        1242 :    PURE SUBROUTINE normalmode_calc_uf_h(normalmode_env, mass_beads, ux, uf_h, e_h)
     305             :       TYPE(normalmode_env_type), INTENT(IN)              :: normalmode_env
     306             :       REAL(kind=dp), DIMENSION(:, :), POINTER            :: mass_beads, ux, uf_h
     307             :       REAL(KIND=dp), INTENT(OUT)                         :: e_h
     308             : 
     309             :       INTEGER                                            :: ibead, idim
     310             :       REAL(kind=dp)                                      :: f
     311             : 
     312        1242 :       e_h = 0.0_dp
     313      446742 :       DO idim = 1, SIZE(mass_beads, 2)
     314             : 
     315             :          ! starting at 2 since the centroid is at 1 and it's mass_beads
     316             :          ! SHOULD be zero anyways:
     317             : 
     318      445500 :          uf_h(1, idim) = 0.0_dp
     319     2116746 :          DO ibead = 2, normalmode_env%p
     320     1670004 :             f = -mass_beads(ibead, idim)*normalmode_env%lambda(ibead)*ux(ibead, idim)
     321     1670004 :             uf_h(ibead, idim) = f
     322             :             ! - to cancel the - in the force f.
     323     2115504 :             e_h = e_h - 0.5_dp*ux(ibead, idim)*f
     324             :          END DO
     325             : 
     326             :       END DO
     327        1242 :    END SUBROUTINE normalmode_calc_uf_h
     328             : 
     329             : END MODULE pint_normalmode

Generated by: LCOV version 1.15