1!--------------------------------------------------------------------------------------------------! 2! CP2K: A general program to perform molecular dynamics simulations ! 3! Copyright (C) 2000 - 2020 CP2K developers group ! 4!--------------------------------------------------------------------------------------------------! 5 6! ************************************************************************************************** 7!> \brief Contains routines useful for the application of constraints during MD 8!> \par History 9!> none 10! ************************************************************************************************** 11MODULE constraint_util 12 USE cell_types, ONLY: cell_type 13 USE colvar_methods, ONLY: colvar_eval_mol_f 14 USE distribution_1d_types, ONLY: distribution_1d_type 15 USE kinds, ONLY: dp 16 USE mathlib, ONLY: matmul_3x3,& 17 transpose_3d 18 USE message_passing, ONLY: mp_sum 19 USE molecule_kind_types, ONLY: colvar_constraint_type,& 20 fixd_constraint_type,& 21 g3x3_constraint_type,& 22 g4x6_constraint_type,& 23 get_molecule_kind,& 24 molecule_kind_type 25 USE molecule_types, ONLY: get_molecule,& 26 global_constraint_type,& 27 local_colvar_constraint_type,& 28 local_constraint_type,& 29 local_g3x3_constraint_type,& 30 local_g4x6_constraint_type,& 31 molecule_type 32 USE particle_types, ONLY: particle_type 33 USE virial_types, ONLY: virial_type 34#include "./base/base_uses.f90" 35 36 IMPLICIT NONE 37 38 PRIVATE 39 PUBLIC :: getold, & 40 pv_constraint, & 41 check_tol, & 42 get_roll_matrix, & 43 restore_temporary_set, & 44 update_temporary_set 45 46 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'constraint_util' 47 48CONTAINS 49 50! ************************************************************************************************** 51!> \brief saves all of the old variables 52!> \param gci ... 53!> \param local_molecules ... 54!> \param molecule_set ... 55!> \param molecule_kind_set ... 56!> \param particle_set ... 57!> \param cell ... 58!> \par History 59!> none 60! ************************************************************************************************** 61 SUBROUTINE getold(gci, local_molecules, molecule_set, molecule_kind_set, & 62 particle_set, cell) 63 64 TYPE(global_constraint_type), POINTER :: gci 65 TYPE(distribution_1d_type), POINTER :: local_molecules 66 TYPE(molecule_type), POINTER :: molecule_set(:) 67 TYPE(molecule_kind_type), POINTER :: molecule_kind_set(:) 68 TYPE(particle_type), POINTER :: particle_set(:) 69 TYPE(cell_type), POINTER :: cell 70 71 CHARACTER(LEN=*), PARAMETER :: routineN = 'getold', routineP = moduleN//':'//routineN 72 73 INTEGER :: first_atom, i, ikind, imol, n3x3con, & 74 n4x6con, nkind, nmol_per_kind 75 TYPE(colvar_constraint_type), POINTER :: colv_list(:) 76 TYPE(fixd_constraint_type), DIMENSION(:), POINTER :: fixd_list 77 TYPE(g3x3_constraint_type), POINTER :: g3x3_list(:) 78 TYPE(g4x6_constraint_type), POINTER :: g4x6_list(:) 79 TYPE(local_colvar_constraint_type), POINTER :: lcolv(:) 80 TYPE(local_constraint_type), POINTER :: lci 81 TYPE(local_g3x3_constraint_type), POINTER :: lg3x3(:) 82 TYPE(local_g4x6_constraint_type), POINTER :: lg4x6(:) 83 TYPE(molecule_kind_type), POINTER :: molecule_kind 84 TYPE(molecule_type), POINTER :: molecule 85 86 NULLIFY (fixd_list) 87 nkind = SIZE(molecule_kind_set) 88 ! Intramolecular constraints 89 MOL: DO ikind = 1, nkind 90 nmol_per_kind = local_molecules%n_el(ikind) 91 DO imol = 1, nmol_per_kind 92 i = local_molecules%list(ikind)%array(imol) 93 molecule => molecule_set(i) 94 molecule_kind => molecule%molecule_kind 95 CALL get_molecule_kind(molecule_kind, ng3x3=n3x3con, ng4x6=n4x6con, & 96 colv_list=colv_list, g3x3_list=g3x3_list, g4x6_list=g4x6_list, & 97 fixd_list=fixd_list) 98 CALL get_molecule(molecule, lci=lci) 99 IF (.NOT. ASSOCIATED(lci)) CYCLE 100 CALL get_molecule(molecule, first_atom=first_atom, & 101 lcolv=lcolv, lg3x3=lg3x3, lg4x6=lg4x6) 102 CALL getold_low(n3x3con, n4x6con, colv_list, g3x3_list, g4x6_list, fixd_list, & 103 lcolv, lg3x3, lg4x6, first_atom, particle_set, cell) 104 END DO 105 END DO MOL 106 ! Intermolecular constraints 107 IF (gci%ntot > 0) THEN 108 n3x3con = gci%ng3x3 109 n4x6con = gci%ng4x6 110 colv_list => gci%colv_list 111 g3x3_list => gci%g3x3_list 112 g4x6_list => gci%g4x6_list 113 fixd_list => gci%fixd_list 114 lcolv => gci%lcolv 115 lg3x3 => gci%lg3x3 116 lg4x6 => gci%lg4x6 117 CALL getold_low(n3x3con, n4x6con, colv_list, g3x3_list, g4x6_list, fixd_list, & 118 lcolv, lg3x3, lg4x6, 1, particle_set, cell) 119 END IF 120 END SUBROUTINE getold 121 122! ************************************************************************************************** 123!> \brief saves all of the old variables - Low Level 124!> \param n3x3con ... 125!> \param n4x6con ... 126!> \param colv_list ... 127!> \param g3x3_list ... 128!> \param g4x6_list ... 129!> \param fixd_list ... 130!> \param lcolv ... 131!> \param lg3x3 ... 132!> \param lg4x6 ... 133!> \param first_atom ... 134!> \param particle_set ... 135!> \param cell ... 136!> \par History 137!> none 138! ************************************************************************************************** 139 SUBROUTINE getold_low(n3x3con, n4x6con, colv_list, g3x3_list, g4x6_list, fixd_list, & 140 lcolv, lg3x3, lg4x6, first_atom, particle_set, cell) 141 142 INTEGER, INTENT(IN) :: n3x3con, n4x6con 143 TYPE(colvar_constraint_type), POINTER :: colv_list(:) 144 TYPE(g3x3_constraint_type), POINTER :: g3x3_list(:) 145 TYPE(g4x6_constraint_type), POINTER :: g4x6_list(:) 146 TYPE(fixd_constraint_type), DIMENSION(:), POINTER :: fixd_list 147 TYPE(local_colvar_constraint_type), POINTER :: lcolv(:) 148 TYPE(local_g3x3_constraint_type), POINTER :: lg3x3(:) 149 TYPE(local_g4x6_constraint_type), POINTER :: lg4x6(:) 150 INTEGER, INTENT(IN) :: first_atom 151 TYPE(particle_type), POINTER :: particle_set(:) 152 TYPE(cell_type), POINTER :: cell 153 154 CHARACTER(LEN=*), PARAMETER :: routineN = 'getold_low', routineP = moduleN//':'//routineN 155 156 INTEGER :: iconst, index 157 158 IF (ASSOCIATED(colv_list)) THEN 159 ! Collective constraints 160 DO iconst = 1, SIZE(colv_list) 161 CALL colvar_eval_mol_f(lcolv(iconst)%colvar_old, cell, & 162 particles=particle_set, fixd_list=fixd_list) 163 ENDDO 164 END IF 165 ! 3x3 constraints 166 DO iconst = 1, n3x3con 167 index = g3x3_list(iconst)%a + first_atom - 1 168 lg3x3(iconst)%ra_old = particle_set(index)%r 169 index = g3x3_list(iconst)%b + first_atom - 1 170 lg3x3(iconst)%rb_old = particle_set(index)%r 171 index = g3x3_list(iconst)%c + first_atom - 1 172 lg3x3(iconst)%rc_old = particle_set(index)%r 173 ENDDO 174 ! 4x6 constraints 175 DO iconst = 1, n4x6con 176 index = g4x6_list(iconst)%a + first_atom - 1 177 lg4x6(iconst)%ra_old = particle_set(index)%r 178 index = g4x6_list(iconst)%b + first_atom - 1 179 lg4x6(iconst)%rb_old = particle_set(index)%r 180 index = g4x6_list(iconst)%c + first_atom - 1 181 lg4x6(iconst)%rc_old = particle_set(index)%r 182 index = g4x6_list(iconst)%d + first_atom - 1 183 lg4x6(iconst)%rd_old = particle_set(index)%r 184 ENDDO 185 186 END SUBROUTINE getold_low 187 188! ************************************************************************************************** 189!> \brief ... 190!> \param gci ... 191!> \param local_molecules ... 192!> \param molecule_set ... 193!> \param molecule_kind_set ... 194!> \param particle_set ... 195!> \param virial ... 196!> \param group ... 197!> \par History 198!> none 199! ************************************************************************************************** 200 SUBROUTINE pv_constraint(gci, local_molecules, molecule_set, molecule_kind_set, & 201 particle_set, virial, group) 202 203 TYPE(global_constraint_type), POINTER :: gci 204 TYPE(distribution_1d_type), POINTER :: local_molecules 205 TYPE(molecule_type), POINTER :: molecule_set(:) 206 TYPE(molecule_kind_type), POINTER :: molecule_kind_set(:) 207 TYPE(particle_type), POINTER :: particle_set(:) 208 TYPE(virial_type), INTENT(INOUT) :: virial 209 INTEGER, INTENT(IN) :: group 210 211 CHARACTER(LEN=*), PARAMETER :: routineN = 'pv_constraint', routineP = moduleN//':'//routineN 212 213 INTEGER :: first_atom, i, ikind, imol, ng3x3, & 214 ng4x6, nkind, nmol_per_kind 215 REAL(KIND=dp) :: pv(3, 3) 216 TYPE(colvar_constraint_type), POINTER :: colv_list(:) 217 TYPE(g3x3_constraint_type), POINTER :: g3x3_list(:) 218 TYPE(g4x6_constraint_type), POINTER :: g4x6_list(:) 219 TYPE(local_colvar_constraint_type), POINTER :: lcolv(:) 220 TYPE(local_constraint_type), POINTER :: lci 221 TYPE(local_g3x3_constraint_type), POINTER :: lg3x3(:) 222 TYPE(local_g4x6_constraint_type), POINTER :: lg4x6(:) 223 TYPE(molecule_kind_type), POINTER :: molecule_kind 224 TYPE(molecule_type), POINTER :: molecule 225 226 pv = 0.0_dp 227 nkind = SIZE(molecule_kind_set) 228 ! Intramolecular Constraints 229 MOL: DO ikind = 1, nkind 230 nmol_per_kind = local_molecules%n_el(ikind) 231 DO imol = 1, nmol_per_kind 232 i = local_molecules%list(ikind)%array(imol) 233 molecule => molecule_set(i) 234 molecule_kind => molecule%molecule_kind 235 CALL get_molecule_kind(molecule_kind, ng3x3=ng3x3, & 236 ng4x6=ng4x6, g3x3_list=g3x3_list, g4x6_list=g4x6_list, & 237 colv_list=colv_list) 238 CALL get_molecule(molecule, lci=lci) 239 IF (.NOT. ASSOCIATED(lci)) CYCLE 240 CALL get_molecule(molecule, first_atom=first_atom, lg3x3=lg3x3, & 241 lg4x6=lg4x6, lcolv=lcolv) 242 CALL pv_constraint_low(ng3x3, ng4x6, g3x3_list, g4x6_list, colv_list, & 243 first_atom, lg3x3, lg4x6, lcolv, particle_set, pv) 244 END DO 245 END DO MOL 246 ! Intermolecular constraints 247 IF (gci%ntot > 0) THEN 248 ng3x3 = gci%ng3x3 249 ng4x6 = gci%ng4x6 250 colv_list => gci%colv_list 251 g3x3_list => gci%g3x3_list 252 g4x6_list => gci%g4x6_list 253 lcolv => gci%lcolv 254 lg3x3 => gci%lg3x3 255 lg4x6 => gci%lg4x6 256 CALL pv_constraint_low(ng3x3, ng4x6, g3x3_list, g4x6_list, colv_list, & 257 1, lg3x3, lg4x6, lcolv, particle_set, pv) 258 END IF 259 CALL mp_sum(pv, group) 260 ! Symmetrize PV 261 pv(1, 2) = 0.5_dp*(pv(1, 2) + pv(2, 1)) 262 pv(2, 1) = pv(1, 2) 263 pv(1, 3) = 0.5_dp*(pv(1, 3) + pv(3, 1)) 264 pv(3, 1) = pv(1, 3) 265 pv(3, 2) = 0.5_dp*(pv(3, 2) + pv(2, 3)) 266 pv(2, 3) = pv(3, 2) 267 ! Store in virial type 268 virial%pv_constraint = pv 269 270 END SUBROUTINE pv_constraint 271 272! ************************************************************************************************** 273!> \brief ... 274!> \param ng3x3 ... 275!> \param ng4x6 ... 276!> \param g3x3_list ... 277!> \param g4x6_list ... 278!> \param colv_list ... 279!> \param first_atom ... 280!> \param lg3x3 ... 281!> \param lg4x6 ... 282!> \param lcolv ... 283!> \param particle_set ... 284!> \param pv ... 285!> \par History 286!> none 287! ************************************************************************************************** 288 SUBROUTINE pv_constraint_low(ng3x3, ng4x6, g3x3_list, g4x6_list, colv_list, & 289 first_atom, lg3x3, lg4x6, lcolv, particle_set, pv) 290 291 INTEGER, INTENT(IN) :: ng3x3, ng4x6 292 TYPE(g3x3_constraint_type), POINTER :: g3x3_list(:) 293 TYPE(g4x6_constraint_type), POINTER :: g4x6_list(:) 294 TYPE(colvar_constraint_type), POINTER :: colv_list(:) 295 INTEGER, INTENT(IN) :: first_atom 296 TYPE(local_g3x3_constraint_type), POINTER :: lg3x3(:) 297 TYPE(local_g4x6_constraint_type), POINTER :: lg4x6(:) 298 TYPE(local_colvar_constraint_type), POINTER :: lcolv(:) 299 TYPE(particle_type), POINTER :: particle_set(:) 300 REAL(KIND=dp), DIMENSION(3, 3), INTENT(INOUT) :: pv 301 302 CHARACTER(LEN=*), PARAMETER :: routineN = 'pv_constraint_low', & 303 routineP = moduleN//':'//routineN 304 305 INTEGER :: iconst, index_a, index_b, index_c, & 306 index_d 307 REAL(KIND=dp) :: fc1(3), fc2(3), fc3(3), fc4(3), & 308 lambda_3x3(3), lambda_4x6(6) 309 310 IF (ASSOCIATED(colv_list)) THEN 311 ! Colvar Constraints 312 DO iconst = 1, SIZE(colv_list) 313 CALL pv_colv_eval(pv, lcolv(iconst), particle_set) 314 END DO 315 END IF 316 ! 3x3 317 DO iconst = 1, ng3x3 318 ! pv gets updated with FULL multiplier 319 lambda_3x3 = lg3x3(iconst)%lambda 320 321 fc1 = lambda_3x3(1)*lg3x3(iconst)%fa + & 322 lambda_3x3(2)*lg3x3(iconst)%fb 323 fc2 = -lambda_3x3(1)*lg3x3(iconst)%fa + & 324 lambda_3x3(3)*lg3x3(iconst)%fc 325 fc3 = -lambda_3x3(2)*lg3x3(iconst)%fb - & 326 lambda_3x3(3)*lg3x3(iconst)%fc 327 index_a = g3x3_list(iconst)%a + first_atom - 1 328 index_b = g3x3_list(iconst)%b + first_atom - 1 329 index_c = g3x3_list(iconst)%c + first_atom - 1 330 331 !pv(1,1) 332 pv(1, 1) = pv(1, 1) + fc1(1)*particle_set(index_a)%r(1) 333 pv(1, 1) = pv(1, 1) + fc2(1)*particle_set(index_b)%r(1) 334 pv(1, 1) = pv(1, 1) + fc3(1)*particle_set(index_c)%r(1) 335 !pv(1,2) 336 pv(1, 2) = pv(1, 2) + fc1(1)*particle_set(index_a)%r(2) 337 pv(1, 2) = pv(1, 2) + fc2(1)*particle_set(index_b)%r(2) 338 pv(1, 2) = pv(1, 2) + fc3(1)*particle_set(index_c)%r(2) 339 !pv(1,3) 340 pv(1, 3) = pv(1, 3) + fc1(1)*particle_set(index_a)%r(3) 341 pv(1, 3) = pv(1, 3) + fc2(1)*particle_set(index_b)%r(3) 342 pv(1, 3) = pv(1, 3) + fc3(1)*particle_set(index_c)%r(3) 343 !pv(2,1) 344 pv(2, 1) = pv(2, 1) + fc1(2)*particle_set(index_a)%r(1) 345 pv(2, 1) = pv(2, 1) + fc2(2)*particle_set(index_b)%r(1) 346 pv(2, 1) = pv(2, 1) + fc3(2)*particle_set(index_c)%r(1) 347 !pv(2,2) 348 pv(2, 2) = pv(2, 2) + fc1(2)*particle_set(index_a)%r(2) 349 pv(2, 2) = pv(2, 2) + fc2(2)*particle_set(index_b)%r(2) 350 pv(2, 2) = pv(2, 2) + fc3(2)*particle_set(index_c)%r(2) 351 !pv(2,3) 352 pv(2, 3) = pv(2, 3) + fc1(2)*particle_set(index_a)%r(3) 353 pv(2, 3) = pv(2, 3) + fc2(2)*particle_set(index_b)%r(3) 354 pv(2, 3) = pv(2, 3) + fc3(2)*particle_set(index_c)%r(3) 355 !pv(3,1) 356 pv(3, 1) = pv(3, 1) + fc1(3)*particle_set(index_a)%r(1) 357 pv(3, 1) = pv(3, 1) + fc2(3)*particle_set(index_b)%r(1) 358 pv(3, 1) = pv(3, 1) + fc3(3)*particle_set(index_c)%r(1) 359 !pv(3,2) 360 pv(3, 2) = pv(3, 2) + fc1(3)*particle_set(index_a)%r(2) 361 pv(3, 2) = pv(3, 2) + fc2(3)*particle_set(index_b)%r(2) 362 pv(3, 2) = pv(3, 2) + fc3(3)*particle_set(index_c)%r(2) 363 !pv(3,3) 364 pv(3, 3) = pv(3, 3) + fc1(3)*particle_set(index_a)%r(3) 365 pv(3, 3) = pv(3, 3) + fc2(3)*particle_set(index_b)%r(3) 366 pv(3, 3) = pv(3, 3) + fc3(3)*particle_set(index_c)%r(3) 367 END DO 368 369 ! 4x6 370 DO iconst = 1, ng4x6 371 ! pv gets updated with FULL multiplier 372 lambda_4x6 = lg4x6(iconst)%lambda 373 374 fc1 = lambda_4x6(1)*lg4x6(iconst)%fa + & 375 lambda_4x6(2)*lg4x6(iconst)%fb + & 376 lambda_4x6(3)*lg4x6(iconst)%fc 377 fc2 = -lambda_4x6(1)*lg4x6(iconst)%fa + & 378 lambda_4x6(4)*lg4x6(iconst)%fd + & 379 lambda_4x6(5)*lg4x6(iconst)%fe 380 fc3 = -lambda_4x6(2)*lg4x6(iconst)%fb - & 381 lambda_4x6(4)*lg4x6(iconst)%fd + & 382 lambda_4x6(6)*lg4x6(iconst)%ff 383 fc4 = -lambda_4x6(3)*lg4x6(iconst)%fc - & 384 lambda_4x6(5)*lg4x6(iconst)%fe - & 385 lambda_4x6(6)*lg4x6(iconst)%ff 386 index_a = g4x6_list(iconst)%a + first_atom - 1 387 index_b = g4x6_list(iconst)%b + first_atom - 1 388 index_c = g4x6_list(iconst)%c + first_atom - 1 389 index_d = g4x6_list(iconst)%d + first_atom - 1 390 391 !pv(1,1) 392 pv(1, 1) = pv(1, 1) + fc1(1)*particle_set(index_a)%r(1) 393 pv(1, 1) = pv(1, 1) + fc2(1)*particle_set(index_b)%r(1) 394 pv(1, 1) = pv(1, 1) + fc3(1)*particle_set(index_c)%r(1) 395 pv(1, 1) = pv(1, 1) + fc4(1)*particle_set(index_d)%r(1) 396 !pv(1,2) 397 pv(1, 2) = pv(1, 2) + fc1(1)*particle_set(index_a)%r(2) 398 pv(1, 2) = pv(1, 2) + fc2(1)*particle_set(index_b)%r(2) 399 pv(1, 2) = pv(1, 2) + fc3(1)*particle_set(index_c)%r(2) 400 pv(1, 2) = pv(1, 2) + fc4(1)*particle_set(index_d)%r(2) 401 !pv(1,3) 402 pv(1, 3) = pv(1, 3) + fc1(1)*particle_set(index_a)%r(3) 403 pv(1, 3) = pv(1, 3) + fc2(1)*particle_set(index_b)%r(3) 404 pv(1, 3) = pv(1, 3) + fc3(1)*particle_set(index_c)%r(3) 405 pv(1, 3) = pv(1, 3) + fc4(1)*particle_set(index_d)%r(3) 406 !pv(2,1) 407 pv(2, 1) = pv(2, 1) + fc1(2)*particle_set(index_a)%r(1) 408 pv(2, 1) = pv(2, 1) + fc2(2)*particle_set(index_b)%r(1) 409 pv(2, 1) = pv(2, 1) + fc3(2)*particle_set(index_c)%r(1) 410 pv(2, 1) = pv(2, 1) + fc4(2)*particle_set(index_d)%r(1) 411 !pv(2,2) 412 pv(2, 2) = pv(2, 2) + fc1(2)*particle_set(index_a)%r(2) 413 pv(2, 2) = pv(2, 2) + fc2(2)*particle_set(index_b)%r(2) 414 pv(2, 2) = pv(2, 2) + fc3(2)*particle_set(index_c)%r(2) 415 pv(2, 2) = pv(2, 2) + fc4(2)*particle_set(index_d)%r(2) 416 !pv(2,3) 417 pv(2, 3) = pv(2, 3) + fc1(2)*particle_set(index_a)%r(3) 418 pv(2, 3) = pv(2, 3) + fc2(2)*particle_set(index_b)%r(3) 419 pv(2, 3) = pv(2, 3) + fc3(2)*particle_set(index_c)%r(3) 420 pv(2, 3) = pv(2, 3) + fc4(2)*particle_set(index_d)%r(3) 421 !pv(3,1) 422 pv(3, 1) = pv(3, 1) + fc1(3)*particle_set(index_a)%r(1) 423 pv(3, 1) = pv(3, 1) + fc2(3)*particle_set(index_b)%r(1) 424 pv(3, 1) = pv(3, 1) + fc3(3)*particle_set(index_c)%r(1) 425 pv(3, 1) = pv(3, 1) + fc4(3)*particle_set(index_d)%r(1) 426 !pv(3,2) 427 pv(3, 2) = pv(3, 2) + fc1(3)*particle_set(index_a)%r(2) 428 pv(3, 2) = pv(3, 2) + fc2(3)*particle_set(index_b)%r(2) 429 pv(3, 2) = pv(3, 2) + fc3(3)*particle_set(index_c)%r(2) 430 pv(3, 2) = pv(3, 2) + fc4(3)*particle_set(index_d)%r(2) 431 !pv(3,3) 432 pv(3, 3) = pv(3, 3) + fc1(3)*particle_set(index_a)%r(3) 433 pv(3, 3) = pv(3, 3) + fc2(3)*particle_set(index_b)%r(3) 434 pv(3, 3) = pv(3, 3) + fc3(3)*particle_set(index_c)%r(3) 435 pv(3, 3) = pv(3, 3) + fc4(3)*particle_set(index_d)%r(3) 436 END DO 437 438 END SUBROUTINE pv_constraint_low 439 440! ************************************************************************************************** 441!> \brief ... 442!> \param pv ... 443!> \param lcolv ... 444!> \param particle_set ... 445!> \par History 446!> none 447! ************************************************************************************************** 448 SUBROUTINE pv_colv_eval(pv, lcolv, particle_set) 449 REAL(KIND=dp), DIMENSION(3, 3), INTENT(INOUT) :: pv 450 TYPE(local_colvar_constraint_type), INTENT(IN) :: lcolv 451 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set 452 453 INTEGER :: i, iatm, ind, j 454 REAL(KIND=dp) :: lambda, tmp 455 REAL(KIND=dp), DIMENSION(3) :: f 456 457 DO iatm = 1, SIZE(lcolv%colvar_old%i_atom) 458 ind = lcolv%colvar_old%i_atom(iatm) 459 f = -lcolv%colvar_old%dsdr(:, iatm) 460 ! pv gets updated with FULL multiplier 461 lambda = lcolv%lambda 462 DO i = 1, 3 463 tmp = lambda*particle_set(ind)%r(i) 464 DO j = 1, 3 465 pv(j, i) = pv(j, i) + f(j)*tmp 466 END DO 467 END DO 468 END DO 469 470 END SUBROUTINE pv_colv_eval 471 472! ************************************************************************************************** 473!> \brief ... 474!> \param roll_tol ... 475!> \param iroll ... 476!> \param char ... 477!> \param matrix ... 478!> \param veps ... 479!> \par History 480!> none 481! ************************************************************************************************** 482 SUBROUTINE check_tol(roll_tol, iroll, char, matrix, veps) 483 484 REAL(KIND=dp), INTENT(OUT) :: roll_tol 485 INTEGER, INTENT(INOUT) :: iroll 486 CHARACTER(LEN=*), INTENT(IN) :: char 487 REAL(KIND=dp), DIMENSION(:, :), INTENT(IN), & 488 OPTIONAL :: matrix, veps 489 490 CHARACTER(LEN=*), PARAMETER :: routineN = 'check_tol', routineP = moduleN//':'//routineN 491 492 REAL(KIND=dp) :: local_tol 493 REAL(KIND=dp), DIMENSION(3, 3) :: diff_rattle, diff_shake 494 REAL(KIND=dp), DIMENSION(3, 3), SAVE :: matrix_old, veps_old 495 496 SELECT CASE (char) 497 CASE ('SHAKE') 498 IF (iroll == 1) THEN 499 matrix_old = matrix 500 roll_tol = -1.E10_dp 501 ELSE 502 roll_tol = 0.0_dp 503 diff_shake = ABS(matrix_old - matrix) 504 local_tol = MAXVAL(diff_shake) 505 roll_tol = MAX(roll_tol, local_tol) 506 matrix_old = matrix 507 END IF 508 iroll = iroll + 1 509 CASE ('RATTLE') 510 IF (iroll == 1) THEN 511 veps_old = veps 512 roll_tol = -1.E+10_dp 513 ELSE 514 roll_tol = 0.0_dp 515 ! compute tolerance on veps 516 diff_rattle = ABS(veps - veps_old) 517 local_tol = MAXVAL(diff_rattle) 518 roll_tol = MAX(roll_tol, local_tol) 519 veps_old = veps 520 END IF 521 iroll = iroll + 1 522 END SELECT 523 524 END SUBROUTINE check_tol 525 526! ************************************************************************************************** 527!> \brief ... 528!> \param char ... 529!> \param r_shake ... 530!> \param v_shake ... 531!> \param vector_r ... 532!> \param vector_v ... 533!> \param u ... 534!> \par History 535!> none 536! ************************************************************************************************** 537 SUBROUTINE get_roll_matrix(char, r_shake, v_shake, vector_r, vector_v, u) 538 539 CHARACTER(len=*), INTENT(IN) :: char 540 REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT), & 541 OPTIONAL :: r_shake, v_shake 542 REAL(KIND=dp), DIMENSION(:), INTENT(IN), OPTIONAL :: vector_r, vector_v 543 REAL(KIND=dp), DIMENSION(:, :), INTENT(IN), & 544 OPTIONAL :: u 545 546 CHARACTER(LEN=*), PARAMETER :: routineN = 'get_roll_matrix', & 547 routineP = moduleN//':'//routineN 548 549 INTEGER :: i 550 REAL(KIND=dp), DIMENSION(3, 3) :: diag 551 552 IF (PRESENT(r_shake)) r_shake = 0.0_dp 553 IF (PRESENT(v_shake)) v_shake = 0.0_dp 554 diag = 0.0_dp 555 556 SELECT CASE (char) 557 CASE ('SHAKE') 558 IF (PRESENT(u) .AND. PRESENT(vector_v) .AND. & 559 PRESENT(vector_r)) THEN 560 diag(1, 1) = vector_r(1) 561 diag(2, 2) = vector_r(2) 562 diag(3, 3) = vector_r(3) 563 r_shake = MATMUL_3X3(MATMUL_3X3(u, diag), TRANSPOSE_3D(u)) 564 diag(1, 1) = vector_v(1) 565 diag(2, 2) = vector_v(2) 566 diag(3, 3) = vector_v(3) 567 v_shake = MATMUL_3X3(MATMUL_3X3(u, diag), TRANSPOSE_3D(u)) 568 diag = MATMUL_3x3(r_shake, v_shake) 569 r_shake = diag 570 ELSEIF (.NOT. PRESENT(u) .AND. PRESENT(vector_v) .AND. & 571 PRESENT(vector_r)) THEN 572 DO i = 1, 3 573 r_shake(i, i) = vector_r(i)*vector_v(i) 574 v_shake(i, i) = vector_v(i) 575 END DO 576 ELSE 577 CPABORT("Not sufficient parameters") 578 END IF 579 CASE ('RATTLE') 580 IF (PRESENT(u) .AND. PRESENT(vector_v)) THEN 581 diag(1, 1) = vector_v(1) 582 diag(2, 2) = vector_v(2) 583 diag(3, 3) = vector_v(3) 584 v_shake = MATMUL_3x3(MATMUL_3X3(u, diag), TRANSPOSE_3D(u)) 585 ELSEIF (.NOT. PRESENT(u) .AND. PRESENT(vector_v)) THEN 586 DO i = 1, 3 587 v_shake(i, i) = vector_v(i) 588 END DO 589 ELSE 590 CPABORT("Not sufficient parameters") 591 END IF 592 END SELECT 593 594 END SUBROUTINE get_roll_matrix 595 596! ************************************************************************************************** 597!> \brief ... 598!> \param particle_set ... 599!> \param local_particles ... 600!> \param pos ... 601!> \param vel ... 602!> \par History 603!> Teodoro Laino [tlaino] 2007 604! ************************************************************************************************** 605 SUBROUTINE restore_temporary_set(particle_set, local_particles, pos, vel) 606 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set 607 TYPE(distribution_1d_type), POINTER :: local_particles 608 REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT), & 609 OPTIONAL :: pos, vel 610 611 CHARACTER(LEN=*), PARAMETER :: routineN = 'restore_temporary_set', & 612 routineP = moduleN//':'//routineN 613 614 INTEGER :: iparticle, iparticle_kind, & 615 iparticle_local, nparticle_local 616 LOGICAL, ALLOCATABLE, DIMENSION(:) :: wrk 617 618 ALLOCATE (wrk(SIZE(particle_set))) 619 wrk = .TRUE. 620 DO iparticle_kind = 1, SIZE(local_particles%n_el) 621 nparticle_local = local_particles%n_el(iparticle_kind) 622 DO iparticle_local = 1, nparticle_local 623 iparticle = local_particles%list(iparticle_kind)%array(iparticle_local) 624 wrk(iparticle) = .FALSE. 625 END DO 626 END DO 627 IF (PRESENT(vel)) THEN 628 DO iparticle = 1, SIZE(particle_set) 629 IF (wrk(iparticle)) THEN 630 vel(:, iparticle) = 0.0_dp 631 END IF 632 END DO 633 END IF 634 IF (PRESENT(pos)) THEN 635 DO iparticle = 1, SIZE(particle_set) 636 IF (wrk(iparticle)) THEN 637 pos(:, iparticle) = 0.0_dp 638 END IF 639 END DO 640 END IF 641 DEALLOCATE (wrk) 642 END SUBROUTINE restore_temporary_set 643 644! ************************************************************************************************** 645!> \brief ... 646!> \param group ... 647!> \param pos ... 648!> \param vel ... 649!> \par History 650!> Teodoro Laino [tlaino] 2007 651! ************************************************************************************************** 652 SUBROUTINE update_temporary_set(group, pos, vel) 653 INTEGER, INTENT(IN) :: group 654 REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT), & 655 OPTIONAL :: pos, vel 656 657 IF (PRESENT(pos)) THEN 658 CALL mp_sum(pos, group) 659 END IF 660 IF (PRESENT(vel)) THEN 661 CALL mp_sum(vel, group) 662 END IF 663 END SUBROUTINE update_temporary_set 664 665END MODULE constraint_util 666