LCOV - code coverage report
Current view: top level - src - constraint_4x6.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:262480d) Lines: 572 588 97.3 %
Date: 2024-11-22 07:00:40 Functions: 10 12 83.3 %

          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             : !> \par History
      10             : !>      none
      11             : ! **************************************************************************************************
      12             : MODULE constraint_4x6
      13             : 
      14             :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      15             :                                               get_atomic_kind
      16             :    USE constraint_fxd,                  ONLY: check_fixed_atom_cns_g4x6
      17             :    USE kinds,                           ONLY: dp
      18             :    USE linear_systems,                  ONLY: solve_system
      19             :    USE molecule_kind_types,             ONLY: fixd_constraint_type,&
      20             :                                               g4x6_constraint_type,&
      21             :                                               get_molecule_kind,&
      22             :                                               molecule_kind_type
      23             :    USE molecule_types,                  ONLY: get_molecule,&
      24             :                                               global_constraint_type,&
      25             :                                               local_g4x6_constraint_type,&
      26             :                                               molecule_type
      27             :    USE particle_types,                  ONLY: particle_type
      28             : #include "./base/base_uses.f90"
      29             : 
      30             :    IMPLICIT NONE
      31             : 
      32             :    PRIVATE
      33             :    PUBLIC :: shake_4x6_int, &
      34             :              rattle_4x6_int, &
      35             :              shake_roll_4x6_int, &
      36             :              rattle_roll_4x6_int, &
      37             :              shake_4x6_ext, &
      38             :              rattle_4x6_ext, &
      39             :              shake_roll_4x6_ext, &
      40             :              rattle_roll_4x6_ext
      41             : 
      42             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'constraint_4x6'
      43             : 
      44             : CONTAINS
      45             : 
      46             : ! **************************************************************************************************
      47             : !> \brief Intramolecular shake_4x6
      48             : !> \param molecule ...
      49             : !> \param particle_set ...
      50             : !> \param pos ...
      51             : !> \param vel ...
      52             : !> \param dt ...
      53             : !> \param ishake ...
      54             : !> \param max_sigma ...
      55             : !> \par History
      56             : !>      none
      57             : ! **************************************************************************************************
      58        2466 :    SUBROUTINE shake_4x6_int(molecule, particle_set, pos, vel, dt, ishake, &
      59             :                             max_sigma)
      60             :       TYPE(molecule_type), POINTER                       :: molecule
      61             :       TYPE(particle_type), POINTER                       :: particle_set(:)
      62             :       REAL(KIND=dp), INTENT(INOUT)                       :: pos(:, :), vel(:, :)
      63             :       REAL(kind=dp), INTENT(in)                          :: dt
      64             :       INTEGER, INTENT(IN)                                :: ishake
      65             :       REAL(KIND=dp), INTENT(INOUT)                       :: max_sigma
      66             : 
      67             :       INTEGER                                            :: first_atom, ng4x6
      68        2466 :       TYPE(fixd_constraint_type), DIMENSION(:), POINTER  :: fixd_list
      69        2466 :       TYPE(g4x6_constraint_type), POINTER                :: g4x6_list(:)
      70        2466 :       TYPE(local_g4x6_constraint_type), POINTER          :: lg4x6(:)
      71             :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind
      72             : 
      73        2466 :       NULLIFY (fixd_list)
      74        2466 :       molecule_kind => molecule%molecule_kind
      75             :       CALL get_molecule_kind(molecule_kind, ng4x6=ng4x6, &
      76        2466 :                              fixd_list=fixd_list, g4x6_list=g4x6_list)
      77        2466 :       CALL get_molecule(molecule, first_atom=first_atom, lg4x6=lg4x6)
      78             :       ! Real Shake
      79             :       CALL shake_4x6_low(fixd_list, g4x6_list, lg4x6, ng4x6, first_atom, &
      80        2466 :                          particle_set, pos, vel, dt, ishake, max_sigma)
      81             : 
      82        2466 :    END SUBROUTINE shake_4x6_int
      83             : 
      84             : ! **************************************************************************************************
      85             : !> \brief Intramolecular shake_4x6_roll
      86             : !> \param molecule ...
      87             : !> \param particle_set ...
      88             : !> \param pos ...
      89             : !> \param vel ...
      90             : !> \param r_shake ...
      91             : !> \param dt ...
      92             : !> \param ishake ...
      93             : !> \param max_sigma ...
      94             : !> \par History
      95             : !>      none
      96             : ! **************************************************************************************************
      97        2225 :    SUBROUTINE shake_roll_4x6_int(molecule, particle_set, pos, vel, r_shake, &
      98             :                                  dt, ishake, max_sigma)
      99             :       TYPE(molecule_type), POINTER                       :: molecule
     100             :       TYPE(particle_type), POINTER                       :: particle_set(:)
     101             :       REAL(KIND=dp), INTENT(INOUT)                       :: pos(:, :), vel(:, :)
     102             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: r_shake
     103             :       REAL(kind=dp), INTENT(in)                          :: dt
     104             :       INTEGER, INTENT(IN)                                :: ishake
     105             :       REAL(KIND=dp), INTENT(INOUT)                       :: max_sigma
     106             : 
     107             :       INTEGER                                            :: first_atom, ng4x6
     108        2225 :       TYPE(fixd_constraint_type), DIMENSION(:), POINTER  :: fixd_list
     109        2225 :       TYPE(g4x6_constraint_type), POINTER                :: g4x6_list(:)
     110        2225 :       TYPE(local_g4x6_constraint_type), POINTER          :: lg4x6(:)
     111             :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind
     112             : 
     113        2225 :       NULLIFY (fixd_list)
     114        2225 :       molecule_kind => molecule%molecule_kind
     115             :       CALL get_molecule_kind(molecule_kind, ng4x6=ng4x6, &
     116        2225 :                              fixd_list=fixd_list, g4x6_list=g4x6_list)
     117        2225 :       CALL get_molecule(molecule, first_atom=first_atom, lg4x6=lg4x6)
     118             :       ! Real Shake
     119             :       CALL shake_roll_4x6_low(fixd_list, g4x6_list, lg4x6, ng4x6, first_atom, &
     120        2225 :                               particle_set, pos, vel, r_shake, dt, ishake, max_sigma)
     121             : 
     122        2225 :    END SUBROUTINE shake_roll_4x6_int
     123             : 
     124             : ! **************************************************************************************************
     125             : !> \brief Intramolecular rattle_4x6
     126             : !> \param molecule ...
     127             : !> \param particle_set ...
     128             : !> \param vel ...
     129             : !> \param dt ...
     130             : !> \par History
     131             : !>      none
     132             : ! **************************************************************************************************
     133         682 :    SUBROUTINE rattle_4x6_int(molecule, particle_set, vel, dt)
     134             :       TYPE(molecule_type), POINTER                       :: molecule
     135             :       TYPE(particle_type), POINTER                       :: particle_set(:)
     136             :       REAL(KIND=dp), INTENT(INOUT)                       :: vel(:, :)
     137             :       REAL(kind=dp), INTENT(in)                          :: dt
     138             : 
     139             :       INTEGER                                            :: first_atom, ng4x6
     140         682 :       TYPE(fixd_constraint_type), DIMENSION(:), POINTER  :: fixd_list
     141         682 :       TYPE(g4x6_constraint_type), POINTER                :: g4x6_list(:)
     142         682 :       TYPE(local_g4x6_constraint_type), POINTER          :: lg4x6(:)
     143             :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind
     144             : 
     145         682 :       NULLIFY (fixd_list)
     146         682 :       molecule_kind => molecule%molecule_kind
     147             :       CALL get_molecule_kind(molecule_kind, ng4x6=ng4x6, &
     148         682 :                              fixd_list=fixd_list, g4x6_list=g4x6_list)
     149         682 :       CALL get_molecule(molecule, first_atom=first_atom, lg4x6=lg4x6)
     150             :       ! Real Rattle
     151             :       CALL rattle_4x6_low(fixd_list, g4x6_list, lg4x6, first_atom, &
     152         682 :                           particle_set, vel, dt)
     153             : 
     154         682 :    END SUBROUTINE rattle_4x6_int
     155             : 
     156             : ! **************************************************************************************************
     157             : !> \brief Intramolecular rattle_4x6_roll
     158             : !> \param molecule ...
     159             : !> \param particle_set ...
     160             : !> \param vel ...
     161             : !> \param r_rattle ...
     162             : !> \param dt ...
     163             : !> \param veps ...
     164             : !> \par History
     165             : !>      none
     166             : ! **************************************************************************************************
     167        1024 :    SUBROUTINE rattle_roll_4x6_int(molecule, particle_set, vel, r_rattle, dt, veps)
     168             :       TYPE(molecule_type), POINTER                       :: molecule
     169             :       TYPE(particle_type), POINTER                       :: particle_set(:)
     170             :       REAL(KIND=dp), INTENT(INOUT)                       :: vel(:, :)
     171             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: r_rattle
     172             :       REAL(kind=dp), INTENT(in)                          :: dt
     173             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: veps
     174             : 
     175             :       INTEGER                                            :: first_atom, ng4x6
     176        1024 :       TYPE(fixd_constraint_type), DIMENSION(:), POINTER  :: fixd_list
     177        1024 :       TYPE(g4x6_constraint_type), POINTER                :: g4x6_list(:)
     178        1024 :       TYPE(local_g4x6_constraint_type), POINTER          :: lg4x6(:)
     179             :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind
     180             : 
     181        1024 :       NULLIFY (fixd_list)
     182        1024 :       molecule_kind => molecule%molecule_kind
     183             :       CALL get_molecule_kind(molecule_kind, ng4x6=ng4x6, &
     184        1024 :                              fixd_list=fixd_list, g4x6_list=g4x6_list)
     185        1024 :       CALL get_molecule(molecule, first_atom=first_atom, lg4x6=lg4x6)
     186             :       ! Real Rattle
     187             :       CALL rattle_roll_4x6_low(fixd_list, g4x6_list, lg4x6, first_atom, &
     188        1024 :                                particle_set, vel, r_rattle, dt, veps)
     189             : 
     190        1024 :    END SUBROUTINE rattle_roll_4x6_int
     191             : 
     192             : ! **************************************************************************************************
     193             : !> \brief Intramolecular shake_4x6
     194             : !> \param gci ...
     195             : !> \param particle_set ...
     196             : !> \param pos ...
     197             : !> \param vel ...
     198             : !> \param dt ...
     199             : !> \param ishake ...
     200             : !> \param max_sigma ...
     201             : !> \par History
     202             : !>      none
     203             : ! **************************************************************************************************
     204          48 :    SUBROUTINE shake_4x6_ext(gci, particle_set, pos, vel, dt, ishake, &
     205             :                             max_sigma)
     206             : 
     207             :       TYPE(global_constraint_type), POINTER              :: gci
     208             :       TYPE(particle_type), POINTER                       :: particle_set(:)
     209             :       REAL(KIND=dp), INTENT(INOUT)                       :: pos(:, :), vel(:, :)
     210             :       REAL(kind=dp), INTENT(in)                          :: dt
     211             :       INTEGER, INTENT(IN)                                :: ishake
     212             :       REAL(KIND=dp), INTENT(INOUT)                       :: max_sigma
     213             : 
     214             :       INTEGER                                            :: first_atom, ng4x6
     215             :       TYPE(fixd_constraint_type), DIMENSION(:), POINTER  :: fixd_list
     216             :       TYPE(g4x6_constraint_type), POINTER                :: g4x6_list(:)
     217             :       TYPE(local_g4x6_constraint_type), POINTER          :: lg4x6(:)
     218             : 
     219          48 :       first_atom = 1
     220          48 :       ng4x6 = gci%ng4x6
     221          48 :       fixd_list => gci%fixd_list
     222          48 :       g4x6_list => gci%g4x6_list
     223          48 :       lg4x6 => gci%lg4x6
     224             :       ! Real Shake
     225             :       CALL shake_4x6_low(fixd_list, g4x6_list, lg4x6, ng4x6, first_atom, &
     226          48 :                          particle_set, pos, vel, dt, ishake, max_sigma)
     227             : 
     228          48 :    END SUBROUTINE shake_4x6_ext
     229             : 
     230             : ! **************************************************************************************************
     231             : !> \brief Intramolecular shake_4x6_roll
     232             : !> \param gci ...
     233             : !> \param particle_set ...
     234             : !> \param pos ...
     235             : !> \param vel ...
     236             : !> \param r_shake ...
     237             : !> \param dt ...
     238             : !> \param ishake ...
     239             : !> \param max_sigma ...
     240             : !> \par History
     241             : !>      none
     242             : ! **************************************************************************************************
     243           0 :    SUBROUTINE shake_roll_4x6_ext(gci, particle_set, pos, vel, r_shake, &
     244             :                                  dt, ishake, max_sigma)
     245             : 
     246             :       TYPE(global_constraint_type), POINTER              :: gci
     247             :       TYPE(particle_type), POINTER                       :: particle_set(:)
     248             :       REAL(KIND=dp), INTENT(INOUT)                       :: pos(:, :), vel(:, :)
     249             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: r_shake
     250             :       REAL(kind=dp), INTENT(in)                          :: dt
     251             :       INTEGER, INTENT(IN)                                :: ishake
     252             :       REAL(KIND=dp), INTENT(INOUT)                       :: max_sigma
     253             : 
     254             :       INTEGER                                            :: first_atom, ng4x6
     255             :       TYPE(fixd_constraint_type), DIMENSION(:), POINTER  :: fixd_list
     256             :       TYPE(g4x6_constraint_type), POINTER                :: g4x6_list(:)
     257             :       TYPE(local_g4x6_constraint_type), POINTER          :: lg4x6(:)
     258             : 
     259           0 :       first_atom = 1
     260           0 :       ng4x6 = gci%ng4x6
     261           0 :       fixd_list => gci%fixd_list
     262           0 :       g4x6_list => gci%g4x6_list
     263           0 :       lg4x6 => gci%lg4x6
     264             :       ! Real Shake
     265             :       CALL shake_roll_4x6_low(fixd_list, g4x6_list, lg4x6, ng4x6, first_atom, &
     266           0 :                               particle_set, pos, vel, r_shake, dt, ishake, max_sigma)
     267             : 
     268           0 :    END SUBROUTINE shake_roll_4x6_ext
     269             : 
     270             : ! **************************************************************************************************
     271             : !> \brief Intramolecular rattle_4x6
     272             : !> \param gci ...
     273             : !> \param particle_set ...
     274             : !> \param vel ...
     275             : !> \param dt ...
     276             : !> \par History
     277             : !>      none
     278             : ! **************************************************************************************************
     279          20 :    SUBROUTINE rattle_4x6_ext(gci, particle_set, vel, dt)
     280             : 
     281             :       TYPE(global_constraint_type), POINTER              :: gci
     282             :       TYPE(particle_type), POINTER                       :: particle_set(:)
     283             :       REAL(KIND=dp), INTENT(INOUT)                       :: vel(:, :)
     284             :       REAL(kind=dp), INTENT(in)                          :: dt
     285             : 
     286             :       INTEGER                                            :: first_atom, ng4x6
     287             :       TYPE(fixd_constraint_type), DIMENSION(:), POINTER  :: fixd_list
     288             :       TYPE(g4x6_constraint_type), POINTER                :: g4x6_list(:)
     289             :       TYPE(local_g4x6_constraint_type), POINTER          :: lg4x6(:)
     290             : 
     291          20 :       first_atom = 1
     292          20 :       ng4x6 = gci%ng4x6
     293          20 :       fixd_list => gci%fixd_list
     294          20 :       g4x6_list => gci%g4x6_list
     295          20 :       lg4x6 => gci%lg4x6
     296             :       ! Real Rattle
     297             :       CALL rattle_4x6_low(fixd_list, g4x6_list, lg4x6, first_atom, &
     298          20 :                           particle_set, vel, dt)
     299             : 
     300          20 :    END SUBROUTINE rattle_4x6_ext
     301             : 
     302             : ! **************************************************************************************************
     303             : !> \brief Intramolecular rattle_4x6_roll
     304             : !> \param gci ...
     305             : !> \param particle_set ...
     306             : !> \param vel ...
     307             : !> \param r_rattle ...
     308             : !> \param dt ...
     309             : !> \param veps ...
     310             : !> \par History
     311             : !>      none
     312             : ! **************************************************************************************************
     313           0 :    SUBROUTINE rattle_roll_4x6_ext(gci, particle_set, vel, r_rattle, dt, veps)
     314             : 
     315             :       TYPE(global_constraint_type), POINTER              :: gci
     316             :       TYPE(particle_type), POINTER                       :: particle_set(:)
     317             :       REAL(KIND=dp), INTENT(INOUT)                       :: vel(:, :)
     318             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: r_rattle
     319             :       REAL(kind=dp), INTENT(in)                          :: dt
     320             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: veps
     321             : 
     322             :       INTEGER                                            :: first_atom, ng4x6
     323             :       TYPE(fixd_constraint_type), DIMENSION(:), POINTER  :: fixd_list
     324             :       TYPE(g4x6_constraint_type), POINTER                :: g4x6_list(:)
     325             :       TYPE(local_g4x6_constraint_type), POINTER          :: lg4x6(:)
     326             : 
     327           0 :       first_atom = 1
     328           0 :       ng4x6 = gci%ng4x6
     329           0 :       fixd_list => gci%fixd_list
     330           0 :       g4x6_list => gci%g4x6_list
     331           0 :       lg4x6 => gci%lg4x6
     332             :       ! Real Rattle
     333             :       CALL rattle_roll_4x6_low(fixd_list, g4x6_list, lg4x6, first_atom, &
     334           0 :                                particle_set, vel, r_rattle, dt, veps)
     335             : 
     336           0 :    END SUBROUTINE rattle_roll_4x6_ext
     337             : 
     338             : ! **************************************************************************************************
     339             : !> \brief ...
     340             : !> \param fixd_list ...
     341             : !> \param g4x6_list ...
     342             : !> \param lg4x6 ...
     343             : !> \param ng4x6 ...
     344             : !> \param first_atom ...
     345             : !> \param particle_set ...
     346             : !> \param pos ...
     347             : !> \param vel ...
     348             : !> \param dt ...
     349             : !> \param ishake ...
     350             : !> \param max_sigma ...
     351             : !> \par History
     352             : !>      none
     353             : ! **************************************************************************************************
     354        2514 :    SUBROUTINE shake_4x6_low(fixd_list, g4x6_list, lg4x6, ng4x6, first_atom, &
     355        2514 :                             particle_set, pos, vel, dt, ishake, max_sigma)
     356             :       TYPE(fixd_constraint_type), DIMENSION(:), POINTER  :: fixd_list
     357             :       TYPE(g4x6_constraint_type), POINTER                :: g4x6_list(:)
     358             :       TYPE(local_g4x6_constraint_type), POINTER          :: lg4x6(:)
     359             :       INTEGER, INTENT(IN)                                :: ng4x6, first_atom
     360             :       TYPE(particle_type), POINTER                       :: particle_set(:)
     361             :       REAL(KIND=dp), INTENT(INOUT)                       :: pos(:, :), vel(:, :)
     362             :       REAL(kind=dp), INTENT(in)                          :: dt
     363             :       INTEGER, INTENT(IN)                                :: ishake
     364             :       REAL(KIND=dp), INTENT(INOUT)                       :: max_sigma
     365             : 
     366             :       INTEGER                                            :: iconst, index_a, index_b, index_c, &
     367             :                                                             index_d
     368             :       REAL(KIND=dp)                                      :: dtby2, dtsqby2, idtsq, imass1, imass2, &
     369             :                                                             imass3, imass4, sigma
     370             :       REAL(KIND=dp), DIMENSION(3)                        :: fc1, fc2, fc3, fc4, r0_12, r0_13, r0_14, &
     371             :                                                             r0_23, r0_24, r0_34, r1, r12, r13, &
     372             :                                                             r14, r2, r23, r24, r3, r34, r4, v1, &
     373             :                                                             v2, v3, v4, vec
     374             :       REAL(KIND=dp), DIMENSION(6, 1)                     :: bvec
     375             :       REAL(KIND=dp), DIMENSION(6, 6)                     :: amat, atemp
     376             :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
     377             : 
     378        2514 :       dtsqby2 = dt*dt*.5_dp
     379        2514 :       idtsq = 1.0_dp/dt/dt
     380        2514 :       dtby2 = dt*.5_dp
     381        5028 :       DO iconst = 1, ng4x6
     382        2514 :          IF (g4x6_list(iconst)%restraint%active) CYCLE
     383        2504 :          index_a = g4x6_list(iconst)%a + first_atom - 1
     384        2504 :          index_b = g4x6_list(iconst)%b + first_atom - 1
     385        2504 :          index_c = g4x6_list(iconst)%c + first_atom - 1
     386        2504 :          index_d = g4x6_list(iconst)%d + first_atom - 1
     387        2504 :          IF (ishake == 1) THEN
     388        2768 :             r0_12(:) = pos(:, index_a) - pos(:, index_b)
     389        2768 :             r0_13(:) = pos(:, index_a) - pos(:, index_c)
     390        2768 :             r0_14(:) = pos(:, index_a) - pos(:, index_d)
     391        2768 :             r0_23(:) = pos(:, index_b) - pos(:, index_c)
     392        2768 :             r0_24(:) = pos(:, index_b) - pos(:, index_d)
     393        2768 :             r0_34(:) = pos(:, index_c) - pos(:, index_d)
     394         692 :             atomic_kind => particle_set(index_a)%atomic_kind
     395         692 :             imass1 = 1.0_dp/atomic_kind%mass
     396         692 :             atomic_kind => particle_set(index_b)%atomic_kind
     397         692 :             imass2 = 1.0_dp/atomic_kind%mass
     398         692 :             atomic_kind => particle_set(index_c)%atomic_kind
     399         692 :             imass3 = 1.0_dp/atomic_kind%mass
     400         692 :             atomic_kind => particle_set(index_d)%atomic_kind
     401         692 :             imass4 = 1.0_dp/atomic_kind%mass
     402             :             lg4x6(iconst)%fa = -2.0_dp*(lg4x6(iconst)%ra_old - &
     403        2768 :                                         lg4x6(iconst)%rb_old)
     404             :             lg4x6(iconst)%fb = -2.0_dp*(lg4x6(iconst)%ra_old - &
     405        2768 :                                         lg4x6(iconst)%rc_old)
     406             :             lg4x6(iconst)%fc = -2.0_dp*(lg4x6(iconst)%ra_old - &
     407        2768 :                                         lg4x6(iconst)%rd_old)
     408             :             lg4x6(iconst)%fd = -2.0_dp*(lg4x6(iconst)%rb_old - &
     409        2768 :                                         lg4x6(iconst)%rc_old)
     410             :             lg4x6(iconst)%fe = -2.0_dp*(lg4x6(iconst)%rb_old - &
     411        2768 :                                         lg4x6(iconst)%rd_old)
     412             :             lg4x6(iconst)%ff = -2.0_dp*(lg4x6(iconst)%rc_old - &
     413        2768 :                                         lg4x6(iconst)%rd_old)
     414             :             ! Check for fixed atom constraints
     415             :             CALL check_fixed_atom_cns_g4x6(imass1, imass2, imass3, imass4, &
     416         692 :                                            index_a, index_b, index_c, index_d, fixd_list, lg4x6(iconst))
     417             :             ! construct matrix
     418        2768 :             amat(1, 1) = (imass1 + imass2)*DOT_PRODUCT(r0_12, lg4x6(iconst)%fa)
     419        2768 :             amat(1, 2) = imass1*DOT_PRODUCT(r0_12, lg4x6(iconst)%fb)
     420        2768 :             amat(1, 3) = imass1*DOT_PRODUCT(r0_12, lg4x6(iconst)%fc)
     421        2768 :             amat(1, 4) = -imass2*DOT_PRODUCT(r0_12, lg4x6(iconst)%fd)
     422        2768 :             amat(1, 5) = -imass2*DOT_PRODUCT(r0_12, lg4x6(iconst)%fe)
     423         692 :             amat(1, 6) = 0.0_dp
     424             : 
     425        2768 :             amat(2, 1) = imass1*DOT_PRODUCT(r0_13, lg4x6(iconst)%fa)
     426        2768 :             amat(2, 2) = (imass1 + imass3)*DOT_PRODUCT(r0_13, lg4x6(iconst)%fb)
     427        2768 :             amat(2, 3) = imass1*DOT_PRODUCT(r0_13, lg4x6(iconst)%fc)
     428        2768 :             amat(2, 4) = imass3*DOT_PRODUCT(r0_13, lg4x6(iconst)%fd)
     429         692 :             amat(2, 5) = 0.0_dp
     430        2768 :             amat(2, 6) = -imass3*DOT_PRODUCT(r0_13, lg4x6(iconst)%ff)
     431             : 
     432        2768 :             amat(3, 1) = imass1*DOT_PRODUCT(r0_14, lg4x6(iconst)%fa)
     433        2768 :             amat(3, 2) = imass1*DOT_PRODUCT(r0_14, lg4x6(iconst)%fb)
     434        2768 :             amat(3, 3) = (imass1 + imass4)*DOT_PRODUCT(r0_14, lg4x6(iconst)%fc)
     435         692 :             amat(3, 4) = 0.0_dp
     436        2768 :             amat(3, 5) = imass4*DOT_PRODUCT(r0_14, lg4x6(iconst)%fe)
     437        2768 :             amat(3, 6) = imass4*DOT_PRODUCT(r0_14, lg4x6(iconst)%ff)
     438             : 
     439        2768 :             amat(4, 1) = -imass2*DOT_PRODUCT(r0_23, lg4x6(iconst)%fa)
     440        2768 :             amat(4, 2) = imass3*DOT_PRODUCT(r0_23, lg4x6(iconst)%fb)
     441         692 :             amat(4, 3) = 0.0_dp
     442        2768 :             amat(4, 4) = (imass3 + imass2)*DOT_PRODUCT(r0_23, lg4x6(iconst)%fd)
     443        2768 :             amat(4, 5) = imass2*DOT_PRODUCT(r0_23, lg4x6(iconst)%fe)
     444        2768 :             amat(4, 6) = -imass3*DOT_PRODUCT(r0_23, lg4x6(iconst)%ff)
     445             : 
     446        2768 :             amat(5, 1) = -imass2*DOT_PRODUCT(r0_24, lg4x6(iconst)%fa)
     447         692 :             amat(5, 2) = 0.0_dp
     448        2768 :             amat(5, 3) = imass4*DOT_PRODUCT(r0_24, lg4x6(iconst)%fc)
     449        2768 :             amat(5, 4) = imass2*DOT_PRODUCT(r0_24, lg4x6(iconst)%fd)
     450        2768 :             amat(5, 5) = (imass4 + imass2)*DOT_PRODUCT(r0_24, lg4x6(iconst)%fe)
     451        2768 :             amat(5, 6) = imass4*DOT_PRODUCT(r0_24, lg4x6(iconst)%ff)
     452             : 
     453         692 :             amat(6, 1) = 0.0_dp
     454        2768 :             amat(6, 2) = -imass3*DOT_PRODUCT(r0_34, lg4x6(iconst)%fb)
     455        2768 :             amat(6, 3) = imass4*DOT_PRODUCT(r0_34, lg4x6(iconst)%fc)
     456        2768 :             amat(6, 4) = -imass3*DOT_PRODUCT(r0_34, lg4x6(iconst)%fd)
     457        2768 :             amat(6, 5) = imass4*DOT_PRODUCT(r0_34, lg4x6(iconst)%fe)
     458        2768 :             amat(6, 6) = (imass3 + imass4)*DOT_PRODUCT(r0_34, lg4x6(iconst)%ff)
     459             :             ! Store values
     460        2768 :             lg4x6(iconst)%r0_12 = r0_12
     461        2768 :             lg4x6(iconst)%r0_13 = r0_13
     462        2768 :             lg4x6(iconst)%r0_14 = r0_14
     463        2768 :             lg4x6(iconst)%r0_23 = r0_23
     464        2768 :             lg4x6(iconst)%r0_24 = r0_24
     465        2768 :             lg4x6(iconst)%r0_34 = r0_34
     466       29756 :             lg4x6(iconst)%amat = amat
     467         692 :             lg4x6(iconst)%imass1 = imass1
     468         692 :             lg4x6(iconst)%imass2 = imass2
     469         692 :             lg4x6(iconst)%imass3 = imass3
     470         692 :             lg4x6(iconst)%imass4 = imass4
     471        4844 :             lg4x6(iconst)%lambda_old = 0.0_dp
     472        4844 :             lg4x6(iconst)%del_lambda = 0.0_dp
     473             :          ELSE
     474             :             ! Retrieve values
     475        7248 :             r0_12 = lg4x6(iconst)%r0_12
     476        7248 :             r0_13 = lg4x6(iconst)%r0_13
     477        7248 :             r0_14 = lg4x6(iconst)%r0_14
     478        7248 :             r0_23 = lg4x6(iconst)%r0_23
     479        7248 :             r0_24 = lg4x6(iconst)%r0_24
     480        7248 :             r0_34 = lg4x6(iconst)%r0_34
     481       77916 :             amat = lg4x6(iconst)%amat
     482        1812 :             imass1 = lg4x6(iconst)%imass1
     483        1812 :             imass2 = lg4x6(iconst)%imass2
     484        1812 :             imass3 = lg4x6(iconst)%imass3
     485        1812 :             imass4 = lg4x6(iconst)%imass4
     486             :          END IF
     487             : 
     488             :          ! Iterate until convergence:
     489             :          vec = lg4x6(iconst)%lambda(1)*lg4x6(iconst)%fa*(imass1 + imass2) + &
     490             :                lg4x6(iconst)%lambda(2)*imass1*lg4x6(iconst)%fb + &
     491             :                lg4x6(iconst)%lambda(3)*imass1*lg4x6(iconst)%fc - &
     492             :                lg4x6(iconst)%lambda(4)*imass2*lg4x6(iconst)%fd - &
     493       10016 :                lg4x6(iconst)%lambda(5)*imass2*lg4x6(iconst)%fe
     494             :          bvec(1, 1) = g4x6_list(iconst)%dab*g4x6_list(iconst)%dab &
     495       20032 :                       - dtsqby2*dtsqby2*DOT_PRODUCT(vec, vec) - DOT_PRODUCT(r0_12, r0_12)
     496             :          vec = lg4x6(iconst)%lambda(2)*lg4x6(iconst)%fb*(imass1 + imass3) + &
     497             :                lg4x6(iconst)%lambda(1)*imass1*lg4x6(iconst)%fa + &
     498             :                lg4x6(iconst)%lambda(3)*imass1*lg4x6(iconst)%fc + &
     499             :                lg4x6(iconst)%lambda(4)*imass3*lg4x6(iconst)%fd - &
     500       10016 :                lg4x6(iconst)%lambda(6)*imass3*lg4x6(iconst)%ff
     501             :          bvec(2, 1) = g4x6_list(iconst)%dac*g4x6_list(iconst)%dac &
     502       20032 :                       - dtsqby2*dtsqby2*DOT_PRODUCT(vec, vec) - DOT_PRODUCT(r0_13, r0_13)
     503             :          vec = lg4x6(iconst)%lambda(3)*lg4x6(iconst)%fc*(imass1 + imass4) + &
     504             :                lg4x6(iconst)%lambda(1)*imass1*lg4x6(iconst)%fa + &
     505             :                lg4x6(iconst)%lambda(2)*imass1*lg4x6(iconst)%fb + &
     506             :                lg4x6(iconst)%lambda(5)*imass4*lg4x6(iconst)%fe + &
     507       10016 :                lg4x6(iconst)%lambda(6)*imass4*lg4x6(iconst)%ff
     508             :          bvec(3, 1) = g4x6_list(iconst)%dad*g4x6_list(iconst)%dad &
     509       20032 :                       - dtsqby2*dtsqby2*DOT_PRODUCT(vec, vec) - DOT_PRODUCT(r0_14, r0_14)
     510             :          vec = lg4x6(iconst)%lambda(4)*lg4x6(iconst)%fd*(imass2 + imass3) - &
     511             :                lg4x6(iconst)%lambda(1)*imass2*lg4x6(iconst)%fa + &
     512             :                lg4x6(iconst)%lambda(2)*imass3*lg4x6(iconst)%fb + &
     513             :                lg4x6(iconst)%lambda(5)*imass2*lg4x6(iconst)%fe - &
     514       10016 :                lg4x6(iconst)%lambda(6)*imass3*lg4x6(iconst)%ff
     515             :          bvec(4, 1) = g4x6_list(iconst)%dbc*g4x6_list(iconst)%dbc &
     516       20032 :                       - dtsqby2*dtsqby2*DOT_PRODUCT(vec, vec) - DOT_PRODUCT(r0_23, r0_23)
     517             :          vec = lg4x6(iconst)%lambda(5)*lg4x6(iconst)%fe*(imass2 + imass4) - &
     518             :                lg4x6(iconst)%lambda(1)*imass2*lg4x6(iconst)%fa + &
     519             :                lg4x6(iconst)%lambda(3)*imass4*lg4x6(iconst)%fc + &
     520             :                lg4x6(iconst)%lambda(4)*imass2*lg4x6(iconst)%fd + &
     521       10016 :                lg4x6(iconst)%lambda(6)*imass4*lg4x6(iconst)%ff
     522             :          bvec(5, 1) = g4x6_list(iconst)%dbd*g4x6_list(iconst)%dbd &
     523       20032 :                       - dtsqby2*dtsqby2*DOT_PRODUCT(vec, vec) - DOT_PRODUCT(r0_24, r0_24)
     524             :          vec = lg4x6(iconst)%lambda(6)*lg4x6(iconst)%ff*(imass3 + imass4) - &
     525             :                lg4x6(iconst)%lambda(2)*imass3*lg4x6(iconst)%fb + &
     526             :                lg4x6(iconst)%lambda(3)*imass4*lg4x6(iconst)%fc - &
     527             :                lg4x6(iconst)%lambda(4)*imass3*lg4x6(iconst)%fd + &
     528       10016 :                lg4x6(iconst)%lambda(5)*imass4*lg4x6(iconst)%fe
     529             :          bvec(6, 1) = g4x6_list(iconst)%dcd*g4x6_list(iconst)%dcd &
     530       20032 :                       - dtsqby2*dtsqby2*DOT_PRODUCT(vec, vec) - DOT_PRODUCT(r0_34, r0_34)
     531       20032 :          bvec = bvec*idtsq
     532             : 
     533             :          ! get lambda
     534        2504 :          atemp = amat
     535        2504 :          CALL solve_system(atemp, 6, bvec)
     536       17528 :          lg4x6(iconst)%lambda(:) = bvec(:, 1)
     537             :          lg4x6(iconst)%del_lambda(:) = lg4x6(iconst)%lambda(:) - &
     538       17528 :                                        lg4x6(iconst)%lambda_old(:)
     539       17528 :          lg4x6(iconst)%lambda_old(:) = lg4x6(iconst)%lambda(:)
     540             : 
     541             :          fc1 = lg4x6(iconst)%del_lambda(1)*lg4x6(iconst)%fa + &
     542             :                lg4x6(iconst)%del_lambda(2)*lg4x6(iconst)%fb + &
     543       10016 :                lg4x6(iconst)%del_lambda(3)*lg4x6(iconst)%fc
     544             :          fc2 = -lg4x6(iconst)%del_lambda(1)*lg4x6(iconst)%fa + &
     545             :                lg4x6(iconst)%del_lambda(4)*lg4x6(iconst)%fd + &
     546       10016 :                lg4x6(iconst)%del_lambda(5)*lg4x6(iconst)%fe
     547             :          fc3 = -lg4x6(iconst)%del_lambda(2)*lg4x6(iconst)%fb - &
     548             :                lg4x6(iconst)%del_lambda(4)*lg4x6(iconst)%fd + &
     549       10016 :                lg4x6(iconst)%del_lambda(6)*lg4x6(iconst)%ff
     550             :          fc4 = -lg4x6(iconst)%del_lambda(3)*lg4x6(iconst)%fc - &
     551             :                lg4x6(iconst)%del_lambda(5)*lg4x6(iconst)%fe - &
     552       10016 :                lg4x6(iconst)%del_lambda(6)*lg4x6(iconst)%ff
     553       10016 :          r1(:) = pos(:, index_a) + imass1*dtsqby2*fc1(:)
     554       10016 :          r2(:) = pos(:, index_b) + imass2*dtsqby2*fc2(:)
     555       10016 :          r3(:) = pos(:, index_c) + imass3*dtsqby2*fc3(:)
     556       10016 :          r4(:) = pos(:, index_d) + imass4*dtsqby2*fc4(:)
     557       10016 :          v1(:) = vel(:, index_a) + imass1*dtby2*fc1(:)
     558       10016 :          v2(:) = vel(:, index_b) + imass2*dtby2*fc2(:)
     559       10016 :          v3(:) = vel(:, index_c) + imass3*dtby2*fc3(:)
     560       10016 :          v4(:) = vel(:, index_d) + imass4*dtby2*fc4(:)
     561       10016 :          r12 = r1 - r2
     562       10016 :          r13 = r1 - r3
     563       10016 :          r14 = r1 - r4
     564       10016 :          r23 = r2 - r3
     565       10016 :          r24 = r2 - r4
     566       10016 :          r34 = r3 - r4
     567             :          ! compute the tolerance:
     568             :          sigma = DOT_PRODUCT(r12, r12) - g4x6_list(iconst)%dab* &
     569       10016 :                  g4x6_list(iconst)%dab
     570        2504 :          max_sigma = MAX(max_sigma, ABS(sigma))
     571             :          sigma = DOT_PRODUCT(r13, r13) - g4x6_list(iconst)%dac* &
     572       10016 :                  g4x6_list(iconst)%dac
     573        2504 :          max_sigma = MAX(max_sigma, ABS(sigma))
     574             :          sigma = DOT_PRODUCT(r14, r14) - g4x6_list(iconst)%dad* &
     575       10016 :                  g4x6_list(iconst)%dad
     576        2504 :          max_sigma = MAX(max_sigma, ABS(sigma))
     577             :          sigma = DOT_PRODUCT(r23, r23) - g4x6_list(iconst)%dbc* &
     578       10016 :                  g4x6_list(iconst)%dbc
     579        2504 :          max_sigma = MAX(max_sigma, ABS(sigma))
     580             :          sigma = DOT_PRODUCT(r24, r24) - g4x6_list(iconst)%dbd* &
     581       10016 :                  g4x6_list(iconst)%dbd
     582        2504 :          max_sigma = MAX(max_sigma, ABS(sigma))
     583             :          sigma = DOT_PRODUCT(r34, r34) - g4x6_list(iconst)%dcd* &
     584       10016 :                  g4x6_list(iconst)%dcd
     585        2504 :          max_sigma = MAX(max_sigma, ABS(sigma))
     586             : 
     587             :          ! update positions with full multiplier
     588       10016 :          pos(:, index_a) = r1(:)
     589       10016 :          pos(:, index_b) = r2(:)
     590       10016 :          pos(:, index_c) = r3(:)
     591       10016 :          pos(:, index_d) = r4(:)
     592             : 
     593             :          ! update velocites with full multiplier
     594       10016 :          vel(:, index_a) = v1(:)
     595       10016 :          vel(:, index_b) = v2(:)
     596       10016 :          vel(:, index_c) = v3(:)
     597       12540 :          vel(:, index_d) = v4(:)
     598             :       END DO
     599        2514 :    END SUBROUTINE shake_4x6_low
     600             : 
     601             : ! **************************************************************************************************
     602             : !> \brief ...
     603             : !> \param fixd_list ...
     604             : !> \param g4x6_list ...
     605             : !> \param lg4x6 ...
     606             : !> \param ng4x6 ...
     607             : !> \param first_atom ...
     608             : !> \param particle_set ...
     609             : !> \param pos ...
     610             : !> \param vel ...
     611             : !> \param r_shake ...
     612             : !> \param dt ...
     613             : !> \param ishake ...
     614             : !> \param max_sigma ...
     615             : !> \par History
     616             : !>      none
     617             : ! **************************************************************************************************
     618        2225 :    SUBROUTINE shake_roll_4x6_low(fixd_list, g4x6_list, lg4x6, ng4x6, first_atom, &
     619        2225 :                                  particle_set, pos, vel, r_shake, dt, ishake, max_sigma)
     620             :       TYPE(fixd_constraint_type), DIMENSION(:), POINTER  :: fixd_list
     621             :       TYPE(g4x6_constraint_type), POINTER                :: g4x6_list(:)
     622             :       TYPE(local_g4x6_constraint_type), POINTER          :: lg4x6(:)
     623             :       INTEGER, INTENT(IN)                                :: ng4x6, first_atom
     624             :       TYPE(particle_type), POINTER                       :: particle_set(:)
     625             :       REAL(KIND=dp), INTENT(INOUT)                       :: pos(:, :), vel(:, :)
     626             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: r_shake
     627             :       REAL(kind=dp), INTENT(in)                          :: dt
     628             :       INTEGER, INTENT(IN)                                :: ishake
     629             :       REAL(KIND=dp), INTENT(INOUT)                       :: max_sigma
     630             : 
     631             :       INTEGER                                            :: iconst, index_a, index_b, index_c, &
     632             :                                                             index_d
     633             :       REAL(KIND=dp)                                      :: dtby2, dtsqby2, idtsq, imass1, imass2, &
     634             :                                                             imass3, imass4, sigma
     635             :       REAL(KIND=dp), DIMENSION(3) :: f_roll1, f_roll2, f_roll3, f_roll4, f_roll5, f_roll6, fc1, &
     636             :          fc2, fc3, fc4, r0_12, r0_13, r0_14, r0_23, r0_24, r0_34, r1, r12, r13, r14, r2, r23, r24, &
     637             :          r3, r34, r4, v1, v2, v3, v4, vec
     638             :       REAL(KIND=dp), DIMENSION(6, 1)                     :: bvec
     639             :       REAL(KIND=dp), DIMENSION(6, 6)                     :: amat, atemp
     640             :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
     641             : 
     642        2225 :       dtsqby2 = dt*dt*.5_dp
     643        2225 :       idtsq = 1.0_dp/dt/dt
     644        2225 :       dtby2 = dt*.5_dp
     645        4450 :       DO iconst = 1, ng4x6
     646        2225 :          IF (g4x6_list(iconst)%restraint%active) CYCLE
     647        2225 :          index_a = g4x6_list(iconst)%a + first_atom - 1
     648        2225 :          index_b = g4x6_list(iconst)%b + first_atom - 1
     649        2225 :          index_c = g4x6_list(iconst)%c + first_atom - 1
     650        2225 :          index_d = g4x6_list(iconst)%d + first_atom - 1
     651        2225 :          IF (ishake == 1) THEN
     652        4352 :             r0_12(:) = pos(:, index_a) - pos(:, index_b)
     653        4352 :             r0_13(:) = pos(:, index_a) - pos(:, index_c)
     654        4352 :             r0_23(:) = pos(:, index_b) - pos(:, index_c)
     655        4352 :             r0_14(:) = pos(:, index_a) - pos(:, index_d)
     656        4352 :             r0_24(:) = pos(:, index_b) - pos(:, index_d)
     657        4352 :             r0_34(:) = pos(:, index_c) - pos(:, index_d)
     658        1088 :             atomic_kind => particle_set(index_a)%atomic_kind
     659        1088 :             imass1 = 1.0_dp/atomic_kind%mass
     660        1088 :             atomic_kind => particle_set(index_b)%atomic_kind
     661        1088 :             imass2 = 1.0_dp/atomic_kind%mass
     662        1088 :             atomic_kind => particle_set(index_c)%atomic_kind
     663        1088 :             imass3 = 1.0_dp/atomic_kind%mass
     664        1088 :             atomic_kind => particle_set(index_d)%atomic_kind
     665        1088 :             imass4 = 1.0_dp/atomic_kind%mass
     666             :             lg4x6(iconst)%fa = -2.0_dp*(lg4x6(iconst)%ra_old - &
     667        4352 :                                         lg4x6(iconst)%rb_old)
     668             :             lg4x6(iconst)%fb = -2.0_dp*(lg4x6(iconst)%ra_old - &
     669        4352 :                                         lg4x6(iconst)%rc_old)
     670             :             lg4x6(iconst)%fc = -2.0_dp*(lg4x6(iconst)%ra_old - &
     671        4352 :                                         lg4x6(iconst)%rd_old)
     672             :             lg4x6(iconst)%fd = -2.0_dp*(lg4x6(iconst)%rb_old - &
     673        4352 :                                         lg4x6(iconst)%rc_old)
     674             :             lg4x6(iconst)%fe = -2.0_dp*(lg4x6(iconst)%rb_old - &
     675        4352 :                                         lg4x6(iconst)%rd_old)
     676             :             lg4x6(iconst)%ff = -2.0_dp*(lg4x6(iconst)%rc_old - &
     677        4352 :                                         lg4x6(iconst)%rd_old)
     678             :             ! Check for fixed atom constraints
     679             :             CALL check_fixed_atom_cns_g4x6(imass1, imass2, imass3, imass4, &
     680        1088 :                                            index_a, index_b, index_c, index_d, fixd_list, lg4x6(iconst))
     681             :             ! rotate fconst:
     682       14144 :             f_roll1 = MATMUL(r_shake, lg4x6(iconst)%fa)
     683       14144 :             f_roll2 = MATMUL(r_shake, lg4x6(iconst)%fb)
     684       14144 :             f_roll3 = MATMUL(r_shake, lg4x6(iconst)%fc)
     685       14144 :             f_roll4 = MATMUL(r_shake, lg4x6(iconst)%fd)
     686       14144 :             f_roll5 = MATMUL(r_shake, lg4x6(iconst)%fe)
     687       14144 :             f_roll6 = MATMUL(r_shake, lg4x6(iconst)%ff)
     688             : 
     689             :             ! construct matrix
     690        4352 :             amat(1, 1) = (imass1 + imass2)*DOT_PRODUCT(r0_12, f_roll1)
     691        4352 :             amat(1, 2) = imass1*DOT_PRODUCT(r0_12, f_roll2)
     692        4352 :             amat(1, 3) = imass1*DOT_PRODUCT(r0_12, f_roll3)
     693        4352 :             amat(1, 4) = -imass2*DOT_PRODUCT(r0_12, f_roll4)
     694        4352 :             amat(1, 5) = -imass2*DOT_PRODUCT(r0_12, f_roll5)
     695        1088 :             amat(1, 6) = 0.0_dp
     696             : 
     697        4352 :             amat(2, 1) = imass1*DOT_PRODUCT(r0_13, f_roll1)
     698        4352 :             amat(2, 2) = (imass1 + imass3)*DOT_PRODUCT(r0_13, f_roll2)
     699        4352 :             amat(2, 3) = imass1*DOT_PRODUCT(r0_13, f_roll3)
     700        4352 :             amat(2, 4) = imass3*DOT_PRODUCT(r0_13, f_roll4)
     701        1088 :             amat(2, 5) = 0.0_dp
     702        4352 :             amat(2, 6) = -imass3*DOT_PRODUCT(r0_13, f_roll6)
     703             : 
     704        4352 :             amat(3, 1) = imass1*DOT_PRODUCT(r0_14, f_roll1)
     705        4352 :             amat(3, 2) = imass1*DOT_PRODUCT(r0_14, f_roll2)
     706        4352 :             amat(3, 3) = (imass1 + imass4)*DOT_PRODUCT(r0_14, f_roll3)
     707        1088 :             amat(3, 4) = 0.0_dp
     708        4352 :             amat(3, 5) = imass4*DOT_PRODUCT(r0_14, f_roll5)
     709        4352 :             amat(3, 6) = imass4*DOT_PRODUCT(r0_14, f_roll6)
     710             : 
     711        4352 :             amat(4, 1) = -imass2*DOT_PRODUCT(r0_23, f_roll1)
     712        4352 :             amat(4, 2) = imass3*DOT_PRODUCT(r0_23, f_roll2)
     713        1088 :             amat(4, 3) = 0.0_dp
     714        4352 :             amat(4, 4) = (imass3 + imass2)*DOT_PRODUCT(r0_23, f_roll4)
     715        4352 :             amat(4, 5) = imass2*DOT_PRODUCT(r0_23, f_roll5)
     716        4352 :             amat(4, 6) = -imass3*DOT_PRODUCT(r0_23, f_roll6)
     717             : 
     718        4352 :             amat(5, 1) = -imass2*DOT_PRODUCT(r0_24, f_roll1)
     719        1088 :             amat(5, 2) = 0.0_dp
     720        4352 :             amat(5, 3) = imass4*DOT_PRODUCT(r0_24, f_roll3)
     721        4352 :             amat(5, 4) = imass2*DOT_PRODUCT(r0_24, f_roll4)
     722        4352 :             amat(5, 5) = (imass4 + imass2)*DOT_PRODUCT(r0_24, f_roll5)
     723        4352 :             amat(5, 6) = imass4*DOT_PRODUCT(r0_24, f_roll6)
     724             : 
     725        1088 :             amat(6, 1) = 0.0_dp
     726        4352 :             amat(6, 2) = -imass3*DOT_PRODUCT(r0_34, f_roll2)
     727        4352 :             amat(6, 3) = imass4*DOT_PRODUCT(r0_34, f_roll3)
     728        4352 :             amat(6, 4) = -imass3*DOT_PRODUCT(r0_34, f_roll4)
     729        4352 :             amat(6, 5) = imass4*DOT_PRODUCT(r0_34, f_roll5)
     730        4352 :             amat(6, 6) = (imass3 + imass4)*DOT_PRODUCT(r0_34, f_roll6)
     731             :             ! Store values
     732        4352 :             lg4x6(iconst)%r0_12 = r0_12
     733        4352 :             lg4x6(iconst)%r0_13 = r0_13
     734        4352 :             lg4x6(iconst)%r0_14 = r0_14
     735        4352 :             lg4x6(iconst)%r0_23 = r0_23
     736        4352 :             lg4x6(iconst)%r0_24 = r0_24
     737        4352 :             lg4x6(iconst)%r0_34 = r0_34
     738        4352 :             lg4x6(iconst)%f_roll1 = f_roll1
     739        4352 :             lg4x6(iconst)%f_roll2 = f_roll2
     740        4352 :             lg4x6(iconst)%f_roll3 = f_roll3
     741        4352 :             lg4x6(iconst)%f_roll4 = f_roll4
     742        4352 :             lg4x6(iconst)%f_roll5 = f_roll5
     743        4352 :             lg4x6(iconst)%f_roll6 = f_roll6
     744       46784 :             lg4x6(iconst)%amat = amat
     745        1088 :             lg4x6(iconst)%imass1 = imass1
     746        1088 :             lg4x6(iconst)%imass2 = imass2
     747        1088 :             lg4x6(iconst)%imass3 = imass3
     748        1088 :             lg4x6(iconst)%imass4 = imass4
     749        7616 :             lg4x6(iconst)%lambda_old = 0.0_dp
     750        7616 :             lg4x6(iconst)%del_lambda = 0.0_dp
     751             :          ELSE
     752             :             ! Retrieve values
     753        4548 :             r0_12 = lg4x6(iconst)%r0_12
     754        4548 :             r0_13 = lg4x6(iconst)%r0_13
     755        4548 :             r0_14 = lg4x6(iconst)%r0_14
     756        4548 :             r0_23 = lg4x6(iconst)%r0_23
     757        4548 :             r0_24 = lg4x6(iconst)%r0_24
     758        4548 :             r0_34 = lg4x6(iconst)%r0_34
     759        4548 :             f_roll1 = lg4x6(iconst)%f_roll1
     760        4548 :             f_roll2 = lg4x6(iconst)%f_roll2
     761        4548 :             f_roll3 = lg4x6(iconst)%f_roll3
     762        4548 :             f_roll4 = lg4x6(iconst)%f_roll4
     763        4548 :             f_roll5 = lg4x6(iconst)%f_roll5
     764        4548 :             f_roll6 = lg4x6(iconst)%f_roll6
     765       48891 :             amat = lg4x6(iconst)%amat
     766        1137 :             imass1 = lg4x6(iconst)%imass1
     767        1137 :             imass2 = lg4x6(iconst)%imass2
     768        1137 :             imass3 = lg4x6(iconst)%imass3
     769        1137 :             imass4 = lg4x6(iconst)%imass4
     770             :          END IF
     771             : 
     772             :          ! Iterate until convergence:
     773             :          vec = lg4x6(iconst)%lambda(1)*f_roll1*(imass1 + imass2) + &
     774             :                lg4x6(iconst)%lambda(2)*imass1*f_roll2 + &
     775             :                lg4x6(iconst)%lambda(3)*imass1*f_roll3 - &
     776             :                lg4x6(iconst)%lambda(4)*imass2*f_roll4 - &
     777        8900 :                lg4x6(iconst)%lambda(5)*imass2*f_roll5
     778             :          bvec(1, 1) = g4x6_list(iconst)%dab*g4x6_list(iconst)%dab &
     779       17800 :                       - dtsqby2*dtsqby2*DOT_PRODUCT(vec, vec) - DOT_PRODUCT(r0_12, r0_12)
     780             :          vec = lg4x6(iconst)%lambda(2)*f_roll2*(imass1 + imass3) + &
     781             :                lg4x6(iconst)%lambda(1)*imass1*f_roll1 + &
     782             :                lg4x6(iconst)%lambda(3)*imass1*f_roll3 + &
     783             :                lg4x6(iconst)%lambda(4)*imass3*f_roll4 - &
     784        8900 :                lg4x6(iconst)%lambda(6)*imass3*f_roll6
     785             :          bvec(2, 1) = g4x6_list(iconst)%dac*g4x6_list(iconst)%dac &
     786       17800 :                       - dtsqby2*dtsqby2*DOT_PRODUCT(vec, vec) - DOT_PRODUCT(r0_13, r0_13)
     787             :          vec = lg4x6(iconst)%lambda(3)*f_roll3*(imass1 + imass4) + &
     788             :                lg4x6(iconst)%lambda(1)*imass1*f_roll1 + &
     789             :                lg4x6(iconst)%lambda(2)*imass1*f_roll2 + &
     790             :                lg4x6(iconst)%lambda(5)*imass4*f_roll5 + &
     791        8900 :                lg4x6(iconst)%lambda(6)*imass4*f_roll6
     792             :          bvec(3, 1) = g4x6_list(iconst)%dad*g4x6_list(iconst)%dad &
     793       17800 :                       - dtsqby2*dtsqby2*DOT_PRODUCT(vec, vec) - DOT_PRODUCT(r0_14, r0_14)
     794             :          vec = lg4x6(iconst)%lambda(4)*f_roll4*(imass2 + imass3) - &
     795             :                lg4x6(iconst)%lambda(1)*imass2*f_roll1 + &
     796             :                lg4x6(iconst)%lambda(2)*imass3*f_roll2 + &
     797             :                lg4x6(iconst)%lambda(5)*imass2*f_roll5 - &
     798        8900 :                lg4x6(iconst)%lambda(6)*imass3*f_roll6
     799             :          bvec(4, 1) = g4x6_list(iconst)%dbc*g4x6_list(iconst)%dbc &
     800       17800 :                       - dtsqby2*dtsqby2*DOT_PRODUCT(vec, vec) - DOT_PRODUCT(r0_23, r0_23)
     801             :          vec = lg4x6(iconst)%lambda(5)*f_roll5*(imass2 + imass4) - &
     802             :                lg4x6(iconst)%lambda(1)*imass2*f_roll1 + &
     803             :                lg4x6(iconst)%lambda(3)*imass4*f_roll3 + &
     804             :                lg4x6(iconst)%lambda(4)*imass2*f_roll4 + &
     805        8900 :                lg4x6(iconst)%lambda(6)*imass4*f_roll6
     806             :          bvec(5, 1) = g4x6_list(iconst)%dbd*g4x6_list(iconst)%dbd &
     807       17800 :                       - dtsqby2*dtsqby2*DOT_PRODUCT(vec, vec) - DOT_PRODUCT(r0_24, r0_24)
     808             :          vec = lg4x6(iconst)%lambda(6)*f_roll6*(imass3 + imass4) - &
     809             :                lg4x6(iconst)%lambda(2)*imass3*f_roll2 + &
     810             :                lg4x6(iconst)%lambda(3)*imass4*f_roll3 - &
     811             :                lg4x6(iconst)%lambda(4)*imass3*f_roll4 + &
     812        8900 :                lg4x6(iconst)%lambda(5)*imass4*f_roll5
     813             :          bvec(6, 1) = g4x6_list(iconst)%dcd*g4x6_list(iconst)%dcd &
     814       17800 :                       - dtsqby2*dtsqby2*DOT_PRODUCT(vec, vec) - DOT_PRODUCT(r0_34, r0_34)
     815       17800 :          bvec = bvec*idtsq
     816             : 
     817             :          ! get lambda
     818        2225 :          atemp = amat
     819        2225 :          CALL solve_system(atemp, 6, bvec)
     820       15575 :          lg4x6(iconst)%lambda(:) = bvec(:, 1)
     821             :          lg4x6(iconst)%del_lambda(:) = lg4x6(iconst)%lambda(:) - &
     822       15575 :                                        lg4x6(iconst)%lambda_old(:)
     823       15575 :          lg4x6(iconst)%lambda_old(:) = lg4x6(iconst)%lambda(:)
     824             : 
     825             :          fc1 = lg4x6(iconst)%del_lambda(1)*lg4x6(iconst)%fa + &
     826             :                lg4x6(iconst)%del_lambda(2)*lg4x6(iconst)%fb + &
     827        8900 :                lg4x6(iconst)%del_lambda(3)*lg4x6(iconst)%fc
     828             :          fc2 = -lg4x6(iconst)%del_lambda(1)*lg4x6(iconst)%fa + &
     829             :                lg4x6(iconst)%del_lambda(4)*lg4x6(iconst)%fd + &
     830        8900 :                lg4x6(iconst)%del_lambda(5)*lg4x6(iconst)%fe
     831             :          fc3 = -lg4x6(iconst)%del_lambda(2)*lg4x6(iconst)%fb - &
     832             :                lg4x6(iconst)%del_lambda(4)*lg4x6(iconst)%fd + &
     833        8900 :                lg4x6(iconst)%del_lambda(6)*lg4x6(iconst)%ff
     834             :          fc4 = -lg4x6(iconst)%del_lambda(3)*lg4x6(iconst)%fc - &
     835             :                lg4x6(iconst)%del_lambda(5)*lg4x6(iconst)%fe - &
     836        8900 :                lg4x6(iconst)%del_lambda(6)*lg4x6(iconst)%ff
     837       35600 :          r1(:) = pos(:, index_a) + imass1*dtsqby2*MATMUL(r_shake, fc1)
     838       35600 :          r2(:) = pos(:, index_b) + imass2*dtsqby2*MATMUL(r_shake, fc2)
     839       35600 :          r3(:) = pos(:, index_c) + imass3*dtsqby2*MATMUL(r_shake, fc3)
     840       35600 :          r4(:) = pos(:, index_d) + imass4*dtsqby2*MATMUL(r_shake, fc4)
     841       35600 :          v1(:) = vel(:, index_a) + imass1*dtby2*MATMUL(r_shake, fc1)
     842       35600 :          v2(:) = vel(:, index_b) + imass2*dtby2*MATMUL(r_shake, fc2)
     843       35600 :          v3(:) = vel(:, index_c) + imass3*dtby2*MATMUL(r_shake, fc3)
     844       35600 :          v4(:) = vel(:, index_d) + imass4*dtby2*MATMUL(r_shake, fc4)
     845             : 
     846        8900 :          r12 = r1 - r2
     847        8900 :          r13 = r1 - r3
     848        8900 :          r23 = r2 - r3
     849        8900 :          r14 = r1 - r4
     850        8900 :          r24 = r2 - r4
     851        8900 :          r34 = r3 - r4
     852             :          ! compute the tolerance:
     853             :          sigma = DOT_PRODUCT(r12, r12) - g4x6_list(iconst)%dab* &
     854        8900 :                  g4x6_list(iconst)%dab
     855        2225 :          max_sigma = MAX(max_sigma, ABS(sigma))
     856             :          sigma = DOT_PRODUCT(r13, r13) - g4x6_list(iconst)%dac* &
     857        8900 :                  g4x6_list(iconst)%dac
     858        2225 :          max_sigma = MAX(max_sigma, ABS(sigma))
     859             :          sigma = DOT_PRODUCT(r14, r14) - g4x6_list(iconst)%dad* &
     860        8900 :                  g4x6_list(iconst)%dad
     861        2225 :          max_sigma = MAX(max_sigma, ABS(sigma))
     862             :          sigma = DOT_PRODUCT(r23, r23) - g4x6_list(iconst)%dbc* &
     863        8900 :                  g4x6_list(iconst)%dbc
     864        2225 :          max_sigma = MAX(max_sigma, ABS(sigma))
     865             :          sigma = DOT_PRODUCT(r24, r24) - g4x6_list(iconst)%dbd* &
     866        8900 :                  g4x6_list(iconst)%dbd
     867        2225 :          max_sigma = MAX(max_sigma, ABS(sigma))
     868             :          sigma = DOT_PRODUCT(r34, r34) - g4x6_list(iconst)%dcd* &
     869        8900 :                  g4x6_list(iconst)%dcd
     870        2225 :          max_sigma = MAX(max_sigma, ABS(sigma))
     871             : 
     872             :          ! update positions with full multiplier
     873        8900 :          pos(:, index_a) = r1(:)
     874        8900 :          pos(:, index_b) = r2(:)
     875        8900 :          pos(:, index_c) = r3(:)
     876        8900 :          pos(:, index_d) = r4(:)
     877             : 
     878             :          ! update velocites with full multiplier
     879        8900 :          vel(:, index_a) = v1(:)
     880        8900 :          vel(:, index_b) = v2(:)
     881        8900 :          vel(:, index_c) = v3(:)
     882       11125 :          vel(:, index_d) = v4(:)
     883             :       END DO
     884        2225 :    END SUBROUTINE shake_roll_4x6_low
     885             : 
     886             : ! **************************************************************************************************
     887             : !> \brief ...
     888             : !> \param fixd_list ...
     889             : !> \param g4x6_list ...
     890             : !> \param lg4x6 ...
     891             : !> \param first_atom ...
     892             : !> \param particle_set ...
     893             : !> \param vel ...
     894             : !> \param dt ...
     895             : !> \par History
     896             : !>      none
     897             : ! **************************************************************************************************
     898         702 :    SUBROUTINE rattle_4x6_low(fixd_list, g4x6_list, lg4x6, first_atom, &
     899         702 :                              particle_set, vel, dt)
     900             : 
     901             :       TYPE(fixd_constraint_type), DIMENSION(:), POINTER  :: fixd_list
     902             :       TYPE(g4x6_constraint_type), POINTER                :: g4x6_list(:)
     903             :       TYPE(local_g4x6_constraint_type), POINTER          :: lg4x6(:)
     904             :       INTEGER, INTENT(IN)                                :: first_atom
     905             :       TYPE(particle_type), POINTER                       :: particle_set(:)
     906             :       REAL(KIND=dp), INTENT(INOUT)                       :: vel(:, :)
     907             :       REAL(kind=dp), INTENT(in)                          :: dt
     908             : 
     909             :       INTEGER                                            :: iconst, index_a, index_b, index_c, &
     910             :                                                             index_d
     911             :       REAL(KIND=dp)                                      :: dtby2, idt, imass1, imass2, imass3, &
     912             :                                                             imass4, mass
     913             :       REAL(KIND=dp), DIMENSION(3)                        :: fc1, fc2, fc3, fc4, r12, r13, r14, r23, &
     914             :                                                             r24, r34, v12, v13, v14, v23, v24, v34
     915             :       REAL(KIND=dp), DIMENSION(6, 1)                     :: bvec
     916             :       REAL(KIND=dp), DIMENSION(6, 6)                     :: amat
     917             :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
     918             : 
     919         702 :       idt = 1.0_dp/dt
     920         702 :       dtby2 = dt*.5_dp
     921        1404 :       DO iconst = 1, SIZE(g4x6_list)
     922         702 :          IF (g4x6_list(iconst)%restraint%active) CYCLE
     923         692 :          index_a = g4x6_list(iconst)%a + first_atom - 1
     924         692 :          index_b = g4x6_list(iconst)%b + first_atom - 1
     925         692 :          index_c = g4x6_list(iconst)%c + first_atom - 1
     926         692 :          index_d = g4x6_list(iconst)%d + first_atom - 1
     927        2768 :          v12(:) = vel(:, index_a) - vel(:, index_b)
     928        2768 :          v13(:) = vel(:, index_a) - vel(:, index_c)
     929        2768 :          v14(:) = vel(:, index_a) - vel(:, index_d)
     930        2768 :          v23(:) = vel(:, index_b) - vel(:, index_c)
     931        2768 :          v24(:) = vel(:, index_b) - vel(:, index_d)
     932        2768 :          v34(:) = vel(:, index_c) - vel(:, index_d)
     933             : 
     934        2768 :          r12(:) = particle_set(index_a)%r(:) - particle_set(index_b)%r(:)
     935        2768 :          r13(:) = particle_set(index_a)%r(:) - particle_set(index_c)%r(:)
     936        2768 :          r14(:) = particle_set(index_a)%r(:) - particle_set(index_d)%r(:)
     937        2768 :          r23(:) = particle_set(index_b)%r(:) - particle_set(index_c)%r(:)
     938        2768 :          r24(:) = particle_set(index_b)%r(:) - particle_set(index_d)%r(:)
     939        2768 :          r34(:) = particle_set(index_c)%r(:) - particle_set(index_d)%r(:)
     940         692 :          atomic_kind => particle_set(index_a)%atomic_kind
     941         692 :          CALL get_atomic_kind(atomic_kind=atomic_kind, mass=mass)
     942         692 :          imass1 = 1.0_dp/mass
     943         692 :          atomic_kind => particle_set(index_b)%atomic_kind
     944         692 :          CALL get_atomic_kind(atomic_kind=atomic_kind, mass=mass)
     945         692 :          imass2 = 1.0_dp/mass
     946         692 :          atomic_kind => particle_set(index_c)%atomic_kind
     947         692 :          CALL get_atomic_kind(atomic_kind=atomic_kind, mass=mass)
     948         692 :          imass3 = 1.0_dp/mass
     949         692 :          atomic_kind => particle_set(index_d)%atomic_kind
     950         692 :          CALL get_atomic_kind(atomic_kind=atomic_kind, mass=mass)
     951         692 :          imass4 = 1.0_dp/mass
     952        2768 :          lg4x6(iconst)%fa = -2.0_dp*r12
     953        2768 :          lg4x6(iconst)%fb = -2.0_dp*r13
     954        2768 :          lg4x6(iconst)%fc = -2.0_dp*r14
     955        2768 :          lg4x6(iconst)%fd = -2.0_dp*r23
     956        2768 :          lg4x6(iconst)%fe = -2.0_dp*r24
     957        2768 :          lg4x6(iconst)%ff = -2.0_dp*r34
     958             :          ! Check for fixed atom constraints
     959             :          CALL check_fixed_atom_cns_g4x6(imass1, imass2, imass3, imass4, &
     960         692 :                                         index_a, index_b, index_c, index_d, fixd_list, lg4x6(iconst))
     961             :          ! construct matrix
     962        2768 :          amat(1, 1) = (imass1 + imass2)*DOT_PRODUCT(r12, lg4x6(iconst)%fa)
     963        2768 :          amat(1, 2) = imass1*DOT_PRODUCT(r12, lg4x6(iconst)%fb)
     964        2768 :          amat(1, 3) = imass1*DOT_PRODUCT(r12, lg4x6(iconst)%fc)
     965        2768 :          amat(1, 4) = -imass2*DOT_PRODUCT(r12, lg4x6(iconst)%fd)
     966        2768 :          amat(1, 5) = -imass2*DOT_PRODUCT(r12, lg4x6(iconst)%fe)
     967         692 :          amat(1, 6) = 0.0_dp
     968             : 
     969        2768 :          amat(2, 1) = imass1*DOT_PRODUCT(r13, lg4x6(iconst)%fa)
     970        2768 :          amat(2, 2) = (imass1 + imass3)*DOT_PRODUCT(r13, lg4x6(iconst)%fb)
     971        2768 :          amat(2, 3) = imass1*DOT_PRODUCT(r13, lg4x6(iconst)%fc)
     972        2768 :          amat(2, 4) = imass3*DOT_PRODUCT(r13, lg4x6(iconst)%fd)
     973         692 :          amat(2, 5) = 0.0_dp
     974        2768 :          amat(2, 6) = -imass3*DOT_PRODUCT(r13, lg4x6(iconst)%ff)
     975             : 
     976        2768 :          amat(3, 1) = imass1*DOT_PRODUCT(r14, lg4x6(iconst)%fa)
     977        2768 :          amat(3, 2) = imass1*DOT_PRODUCT(r14, lg4x6(iconst)%fb)
     978        2768 :          amat(3, 3) = (imass1 + imass4)*DOT_PRODUCT(r14, lg4x6(iconst)%fc)
     979         692 :          amat(3, 4) = 0.0_dp
     980        2768 :          amat(3, 5) = imass4*DOT_PRODUCT(r14, lg4x6(iconst)%fe)
     981        2768 :          amat(3, 6) = imass4*DOT_PRODUCT(r14, lg4x6(iconst)%ff)
     982             : 
     983        2768 :          amat(4, 1) = -imass2*DOT_PRODUCT(r23, lg4x6(iconst)%fa)
     984        2768 :          amat(4, 2) = imass3*DOT_PRODUCT(r23, lg4x6(iconst)%fb)
     985         692 :          amat(4, 3) = 0.0_dp
     986        2768 :          amat(4, 4) = (imass3 + imass2)*DOT_PRODUCT(r23, lg4x6(iconst)%fd)
     987        2768 :          amat(4, 5) = imass2*DOT_PRODUCT(r23, lg4x6(iconst)%fe)
     988        2768 :          amat(4, 6) = -imass3*DOT_PRODUCT(r23, lg4x6(iconst)%ff)
     989             : 
     990        2768 :          amat(5, 1) = -imass2*DOT_PRODUCT(r24, lg4x6(iconst)%fa)
     991         692 :          amat(5, 2) = 0.0_dp
     992        2768 :          amat(5, 3) = imass4*DOT_PRODUCT(r24, lg4x6(iconst)%fc)
     993        2768 :          amat(5, 4) = imass2*DOT_PRODUCT(r24, lg4x6(iconst)%fd)
     994        2768 :          amat(5, 5) = (imass4 + imass2)*DOT_PRODUCT(r24, lg4x6(iconst)%fe)
     995        2768 :          amat(5, 6) = imass4*DOT_PRODUCT(r24, lg4x6(iconst)%ff)
     996             : 
     997         692 :          amat(6, 1) = 0.0_dp
     998        2768 :          amat(6, 2) = -imass3*DOT_PRODUCT(r34, lg4x6(iconst)%fb)
     999        2768 :          amat(6, 3) = imass4*DOT_PRODUCT(r34, lg4x6(iconst)%fc)
    1000        2768 :          amat(6, 4) = -imass3*DOT_PRODUCT(r34, lg4x6(iconst)%fd)
    1001        2768 :          amat(6, 5) = imass4*DOT_PRODUCT(r34, lg4x6(iconst)%fe)
    1002        2768 :          amat(6, 6) = (imass3 + imass4)*DOT_PRODUCT(r34, lg4x6(iconst)%ff)
    1003             : 
    1004             :          ! construct solution vector
    1005        2768 :          bvec(1, 1) = DOT_PRODUCT(r12, v12)
    1006        2768 :          bvec(2, 1) = DOT_PRODUCT(r13, v13)
    1007        2768 :          bvec(3, 1) = DOT_PRODUCT(r14, v14)
    1008        2768 :          bvec(4, 1) = DOT_PRODUCT(r23, v23)
    1009        2768 :          bvec(5, 1) = DOT_PRODUCT(r24, v24)
    1010        2768 :          bvec(6, 1) = DOT_PRODUCT(r34, v34)
    1011        5536 :          bvec = -bvec*2.0_dp*idt
    1012             : 
    1013             :          ! get lambda
    1014         692 :          CALL solve_system(amat, 6, bvec)
    1015        4844 :          lg4x6(iconst)%lambda(:) = bvec(:, 1)
    1016             : 
    1017             :          fc1 = lg4x6(iconst)%lambda(1)*lg4x6(iconst)%fa + &
    1018             :                lg4x6(iconst)%lambda(2)*lg4x6(iconst)%fb + &
    1019        2768 :                lg4x6(iconst)%lambda(3)*lg4x6(iconst)%fc
    1020             :          fc2 = -lg4x6(iconst)%lambda(1)*lg4x6(iconst)%fa + &
    1021             :                lg4x6(iconst)%lambda(4)*lg4x6(iconst)%fd + &
    1022        2768 :                lg4x6(iconst)%lambda(5)*lg4x6(iconst)%fe
    1023             :          fc3 = -lg4x6(iconst)%lambda(2)*lg4x6(iconst)%fb - &
    1024             :                lg4x6(iconst)%lambda(4)*lg4x6(iconst)%fd + &
    1025        2768 :                lg4x6(iconst)%lambda(6)*lg4x6(iconst)%ff
    1026             :          fc4 = -lg4x6(iconst)%lambda(3)*lg4x6(iconst)%fc - &
    1027             :                lg4x6(iconst)%lambda(5)*lg4x6(iconst)%fe - &
    1028        2768 :                lg4x6(iconst)%lambda(6)*lg4x6(iconst)%ff
    1029        2768 :          vel(:, index_a) = vel(:, index_a) + imass1*dtby2*fc1(:)
    1030        2768 :          vel(:, index_b) = vel(:, index_b) + imass2*dtby2*fc2(:)
    1031        2768 :          vel(:, index_c) = vel(:, index_c) + imass3*dtby2*fc3(:)
    1032        4172 :          vel(:, index_d) = vel(:, index_d) + imass4*dtby2*fc4(:)
    1033             :       END DO
    1034         702 :    END SUBROUTINE rattle_4x6_low
    1035             : 
    1036             : ! **************************************************************************************************
    1037             : !> \brief ...
    1038             : !> \param fixd_list ...
    1039             : !> \param g4x6_list ...
    1040             : !> \param lg4x6 ...
    1041             : !> \param first_atom ...
    1042             : !> \param particle_set ...
    1043             : !> \param vel ...
    1044             : !> \param r_rattle ...
    1045             : !> \param dt ...
    1046             : !> \param veps ...
    1047             : !> \par History
    1048             : !>      none
    1049             : ! **************************************************************************************************
    1050        1024 :    SUBROUTINE rattle_roll_4x6_low(fixd_list, g4x6_list, lg4x6, first_atom, &
    1051        1024 :                                   particle_set, vel, r_rattle, dt, veps)
    1052             : 
    1053             :       TYPE(fixd_constraint_type), DIMENSION(:), POINTER  :: fixd_list
    1054             :       TYPE(g4x6_constraint_type), POINTER                :: g4x6_list(:)
    1055             :       TYPE(local_g4x6_constraint_type), POINTER          :: lg4x6(:)
    1056             :       INTEGER, INTENT(IN)                                :: first_atom
    1057             :       TYPE(particle_type), POINTER                       :: particle_set(:)
    1058             :       REAL(KIND=dp), INTENT(INOUT)                       :: vel(:, :)
    1059             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: r_rattle
    1060             :       REAL(kind=dp), INTENT(in)                          :: dt
    1061             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: veps
    1062             : 
    1063             :       INTEGER                                            :: iconst, index_a, index_b, index_c, &
    1064             :                                                             index_d
    1065             :       REAL(KIND=dp)                                      :: dtby2, idt, imass1, imass2, imass3, &
    1066             :                                                             imass4, mass
    1067             :       REAL(KIND=dp), DIMENSION(3)                        :: f_roll1, f_roll2, f_roll3, f_roll4, &
    1068             :                                                             f_roll5, f_roll6, fc1, fc2, fc3, fc4, &
    1069             :                                                             r12, r13, r14, r23, r24, r34, v12, &
    1070             :                                                             v13, v14, v23, v24, v34
    1071             :       REAL(KIND=dp), DIMENSION(6)                        :: lambda
    1072             :       REAL(KIND=dp), DIMENSION(6, 1)                     :: bvec
    1073             :       REAL(KIND=dp), DIMENSION(6, 6)                     :: amat
    1074             :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
    1075             : 
    1076        1024 :       idt = 1.0_dp/dt
    1077        1024 :       dtby2 = dt*.5_dp
    1078        2048 :       DO iconst = 1, SIZE(g4x6_list)
    1079        1024 :          IF (g4x6_list(iconst)%restraint%active) CYCLE
    1080        1024 :          index_a = g4x6_list(iconst)%a + first_atom - 1
    1081        1024 :          index_b = g4x6_list(iconst)%b + first_atom - 1
    1082        1024 :          index_c = g4x6_list(iconst)%c + first_atom - 1
    1083        1024 :          index_d = g4x6_list(iconst)%d + first_atom - 1
    1084        4096 :          v12(:) = vel(:, index_a) - vel(:, index_b)
    1085        4096 :          v13(:) = vel(:, index_a) - vel(:, index_c)
    1086        4096 :          v14(:) = vel(:, index_a) - vel(:, index_d)
    1087        4096 :          v23(:) = vel(:, index_b) - vel(:, index_c)
    1088        4096 :          v24(:) = vel(:, index_b) - vel(:, index_d)
    1089        4096 :          v34(:) = vel(:, index_c) - vel(:, index_d)
    1090             : 
    1091        4096 :          r12(:) = particle_set(index_a)%r(:) - particle_set(index_b)%r(:)
    1092        4096 :          r13(:) = particle_set(index_a)%r(:) - particle_set(index_c)%r(:)
    1093        4096 :          r14(:) = particle_set(index_a)%r(:) - particle_set(index_d)%r(:)
    1094        4096 :          r23(:) = particle_set(index_b)%r(:) - particle_set(index_c)%r(:)
    1095        4096 :          r24(:) = particle_set(index_b)%r(:) - particle_set(index_d)%r(:)
    1096        4096 :          r34(:) = particle_set(index_c)%r(:) - particle_set(index_d)%r(:)
    1097        1024 :          atomic_kind => particle_set(index_a)%atomic_kind
    1098        1024 :          CALL get_atomic_kind(atomic_kind=atomic_kind, mass=mass)
    1099        1024 :          imass1 = 1.0_dp/mass
    1100        1024 :          atomic_kind => particle_set(index_b)%atomic_kind
    1101        1024 :          CALL get_atomic_kind(atomic_kind=atomic_kind, mass=mass)
    1102        1024 :          imass2 = 1.0_dp/mass
    1103        1024 :          atomic_kind => particle_set(index_c)%atomic_kind
    1104        1024 :          CALL get_atomic_kind(atomic_kind=atomic_kind, mass=mass)
    1105        1024 :          imass3 = 1.0_dp/mass
    1106        1024 :          atomic_kind => particle_set(index_d)%atomic_kind
    1107        1024 :          CALL get_atomic_kind(atomic_kind=atomic_kind, mass=mass)
    1108        1024 :          imass4 = 1.0_dp/mass
    1109        4096 :          lg4x6(iconst)%fa = -2.0_dp*r12
    1110        4096 :          lg4x6(iconst)%fb = -2.0_dp*r13
    1111        4096 :          lg4x6(iconst)%fc = -2.0_dp*r14
    1112        4096 :          lg4x6(iconst)%fd = -2.0_dp*r23
    1113        4096 :          lg4x6(iconst)%fe = -2.0_dp*r24
    1114        4096 :          lg4x6(iconst)%ff = -2.0_dp*r34
    1115             :          ! Check for fixed atom constraints
    1116             :          CALL check_fixed_atom_cns_g4x6(imass1, imass2, imass3, imass4, &
    1117        1024 :                                         index_a, index_b, index_c, index_d, fixd_list, lg4x6(iconst))
    1118             :          ! roll the fc
    1119       13312 :          f_roll1 = MATMUL(r_rattle, lg4x6(iconst)%fa)
    1120       13312 :          f_roll2 = MATMUL(r_rattle, lg4x6(iconst)%fb)
    1121       13312 :          f_roll3 = MATMUL(r_rattle, lg4x6(iconst)%fc)
    1122       13312 :          f_roll4 = MATMUL(r_rattle, lg4x6(iconst)%fd)
    1123       13312 :          f_roll5 = MATMUL(r_rattle, lg4x6(iconst)%fe)
    1124       13312 :          f_roll6 = MATMUL(r_rattle, lg4x6(iconst)%ff)
    1125             :          ! construct matrix
    1126        4096 :          amat(1, 1) = (imass1 + imass2)*DOT_PRODUCT(r12, f_roll1)
    1127        4096 :          amat(1, 2) = imass1*DOT_PRODUCT(r12, f_roll2)
    1128        4096 :          amat(1, 3) = imass1*DOT_PRODUCT(r12, f_roll3)
    1129        4096 :          amat(1, 4) = -imass2*DOT_PRODUCT(r12, f_roll4)
    1130        4096 :          amat(1, 5) = -imass2*DOT_PRODUCT(r12, f_roll5)
    1131        1024 :          amat(1, 6) = 0.0_dp
    1132             : 
    1133        4096 :          amat(2, 1) = imass1*DOT_PRODUCT(r13, f_roll1)
    1134        4096 :          amat(2, 2) = (imass1 + imass3)*DOT_PRODUCT(r13, f_roll2)
    1135        4096 :          amat(2, 3) = imass1*DOT_PRODUCT(r13, f_roll3)
    1136        4096 :          amat(2, 4) = imass3*DOT_PRODUCT(r13, f_roll4)
    1137        1024 :          amat(2, 5) = 0.0_dp
    1138        4096 :          amat(2, 6) = -imass3*DOT_PRODUCT(r13, f_roll6)
    1139             : 
    1140        4096 :          amat(3, 1) = imass1*DOT_PRODUCT(r14, f_roll1)
    1141        4096 :          amat(3, 2) = imass1*DOT_PRODUCT(r14, f_roll2)
    1142        4096 :          amat(3, 3) = (imass1 + imass4)*DOT_PRODUCT(r14, f_roll3)
    1143        1024 :          amat(3, 4) = 0.0_dp
    1144        4096 :          amat(3, 5) = imass4*DOT_PRODUCT(r14, f_roll5)
    1145        4096 :          amat(3, 6) = imass4*DOT_PRODUCT(r14, f_roll6)
    1146             : 
    1147        4096 :          amat(4, 1) = -imass2*DOT_PRODUCT(r23, f_roll1)
    1148        4096 :          amat(4, 2) = imass3*DOT_PRODUCT(r23, f_roll2)
    1149        1024 :          amat(4, 3) = 0.0_dp
    1150        4096 :          amat(4, 4) = (imass3 + imass2)*DOT_PRODUCT(r23, f_roll4)
    1151        4096 :          amat(4, 5) = imass2*DOT_PRODUCT(r23, f_roll5)
    1152        4096 :          amat(4, 6) = -imass3*DOT_PRODUCT(r23, f_roll6)
    1153             : 
    1154        4096 :          amat(5, 1) = -imass2*DOT_PRODUCT(r24, f_roll1)
    1155        1024 :          amat(5, 2) = 0.0_dp
    1156        4096 :          amat(5, 3) = imass4*DOT_PRODUCT(r24, f_roll3)
    1157        4096 :          amat(5, 4) = imass2*DOT_PRODUCT(r24, f_roll4)
    1158        4096 :          amat(5, 5) = (imass4 + imass2)*DOT_PRODUCT(r24, f_roll5)
    1159        4096 :          amat(5, 6) = imass4*DOT_PRODUCT(r24, f_roll6)
    1160             : 
    1161        1024 :          amat(6, 1) = 0.0_dp
    1162        4096 :          amat(6, 2) = -imass3*DOT_PRODUCT(r34, f_roll2)
    1163        4096 :          amat(6, 3) = imass4*DOT_PRODUCT(r34, f_roll3)
    1164        4096 :          amat(6, 4) = -imass3*DOT_PRODUCT(r34, f_roll4)
    1165        4096 :          amat(6, 5) = imass4*DOT_PRODUCT(r34, f_roll5)
    1166        4096 :          amat(6, 6) = (imass3 + imass4)*DOT_PRODUCT(r34, f_roll6)
    1167             : 
    1168             :          ! construct solution vector
    1169       22528 :          bvec(1, 1) = DOT_PRODUCT(r12, v12 + MATMUL(veps, r12))
    1170       22528 :          bvec(2, 1) = DOT_PRODUCT(r13, v13 + MATMUL(veps, r13))
    1171       22528 :          bvec(3, 1) = DOT_PRODUCT(r14, v14 + MATMUL(veps, r14))
    1172       22528 :          bvec(4, 1) = DOT_PRODUCT(r23, v23 + MATMUL(veps, r23))
    1173       22528 :          bvec(5, 1) = DOT_PRODUCT(r24, v24 + MATMUL(veps, r24))
    1174       22528 :          bvec(6, 1) = DOT_PRODUCT(r34, v34 + MATMUL(veps, r34))
    1175        8192 :          bvec = -bvec*2.0_dp*idt
    1176             : 
    1177             :          ! get lambda
    1178        1024 :          CALL solve_system(amat, 6, bvec)
    1179        1024 :          lambda(:) = bvec(:, 1)
    1180        7168 :          lg4x6(iconst)%lambda(:) = lambda
    1181             : 
    1182             :          fc1 = lambda(1)*f_roll1 + &
    1183             :                lambda(2)*f_roll2 + &
    1184        4096 :                lambda(3)*f_roll3
    1185             :          fc2 = -lambda(1)*f_roll1 + &
    1186             :                lambda(4)*f_roll4 + &
    1187        4096 :                lambda(5)*f_roll5
    1188             :          fc3 = -lambda(2)*f_roll2 - &
    1189             :                lambda(4)*f_roll4 + &
    1190        4096 :                lambda(6)*f_roll6
    1191             :          fc4 = -lambda(3)*f_roll3 - &
    1192             :                lambda(5)*f_roll5 - &
    1193        4096 :                lambda(6)*f_roll6
    1194        4096 :          vel(:, index_a) = vel(:, index_a) + imass1*dtby2*fc1(:)
    1195        4096 :          vel(:, index_b) = vel(:, index_b) + imass2*dtby2*fc2(:)
    1196        4096 :          vel(:, index_c) = vel(:, index_c) + imass3*dtby2*fc3(:)
    1197        6144 :          vel(:, index_d) = vel(:, index_d) + imass4*dtby2*fc4(:)
    1198             :       END DO
    1199        1024 :    END SUBROUTINE rattle_roll_4x6_low
    1200             : 
    1201        6144 : END MODULE constraint_4x6

Generated by: LCOV version 1.15