LCOV - code coverage report
Current view: top level - src/motion/mc - mc_moves.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:71c3ab0) Lines: 69.6 % 1001 697
Test Date: 2026-07-25 06:35:44 Functions: 81.8 % 11 9

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief the various moves in Monte Carlo (MC) simulations, including
      10              : !>      change of internal conformation, translation of a molecule, rotation
      11              : !>      of a molecule, and changing the size of the simulation box
      12              : !> \par History
      13              : !>      none
      14              : !> \author Matthew J. McGrath  (10.16.2003)
      15              : ! **************************************************************************************************
      16              : MODULE mc_moves
      17              :    USE atomic_kind_types,               ONLY: get_atomic_kind
      18              :    USE cell_methods,                    ONLY: cell_create
      19              :    USE cell_types,                      ONLY: cell_clone,&
      20              :                                               cell_release,&
      21              :                                               cell_type,&
      22              :                                               get_cell
      23              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      24              :                                               cp_logger_get_default_io_unit,&
      25              :                                               cp_logger_type
      26              :    USE cp_subsys_types,                 ONLY: cp_subsys_get,&
      27              :                                               cp_subsys_set,&
      28              :                                               cp_subsys_type
      29              :    USE force_env_methods,               ONLY: force_env_calc_energy_force
      30              :    USE force_env_types,                 ONLY: force_env_get,&
      31              :                                               force_env_type,&
      32              :                                               use_fist_force
      33              :    USE global_types,                    ONLY: global_environment_type
      34              :    USE kinds,                           ONLY: default_string_length,&
      35              :                                               dp
      36              :    USE mathconstants,                   ONLY: pi
      37              :    USE mc_coordinates,                  ONLY: check_for_overlap,&
      38              :                                               cluster_search,&
      39              :                                               create_discrete_array,&
      40              :                                               generate_cbmc_swap_config,&
      41              :                                               get_center_of_mass
      42              :    USE mc_types,                        ONLY: get_mc_molecule_info,&
      43              :                                               get_mc_par,&
      44              :                                               mc_ekin_type,&
      45              :                                               mc_molecule_info_type,&
      46              :                                               mc_moves_type,&
      47              :                                               mc_simpar_type
      48              :    USE md_run,                          ONLY: qs_mol_dyn
      49              :    USE message_passing,                 ONLY: mp_comm_type
      50              :    USE molecule_kind_list_types,        ONLY: molecule_kind_list_type
      51              :    USE molecule_kind_types,             ONLY: bend_type,&
      52              :                                               bond_type,&
      53              :                                               get_molecule_kind,&
      54              :                                               molecule_kind_type,&
      55              :                                               torsion_type
      56              :    USE parallel_rng_types,              ONLY: rng_stream_type
      57              :    USE particle_list_types,             ONLY: particle_list_type
      58              :    USE physcon,                         ONLY: angstrom
      59              : #include "../../base/base_uses.f90"
      60              : 
      61              :    IMPLICIT NONE
      62              : 
      63              :    PRIVATE
      64              : 
      65              :    PRIVATE  :: change_bond_angle, change_bond_length, depth_first_search, &
      66              :                change_dihedral
      67              : 
      68              : ! *** Global parameters ***
      69              : 
      70              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'mc_moves'
      71              : 
      72              :    PUBLIC :: mc_conformation_change, mc_molecule_translation, &
      73              :              mc_molecule_rotation, mc_volume_move, mc_avbmc_move, &
      74              :              mc_hmc_move, mc_cluster_translation
      75              : 
      76              : CONTAINS
      77              : 
      78              : ! **************************************************************************************************
      79              : !> \brief essentially performs a depth-first search of the molecule structure
      80              : !>      to find all atoms connected to a specific atom excluding one branch...
      81              : !>      for instance, if water is labelled 1-2-3 for O-H-H, calling this
      82              : !>      routine with current_atom=1,avoid_atom=2 returns the array
      83              : !>      atom=(0,0,1)
      84              : !> \param current_atom the atom whose connections we're looking at
      85              : !> \param avoid_atom the atom whose direction the search is not supposed to go
      86              : !> \param connectivity an array telling us the neighbors of all atoms
      87              : !> \param atom the array that tells us if one can get to a given atom by
      88              : !>        starting at current_atom and not going through avoid_atom...0 is no,
      89              : !>        1 is yes
      90              : !> \author MJM
      91              : ! **************************************************************************************************
      92         1324 :    RECURSIVE SUBROUTINE depth_first_search(current_atom, avoid_atom, &
      93         1324 :                                            connectivity, atom)
      94              : 
      95              :       INTEGER, INTENT(IN)                                :: current_atom, avoid_atom
      96              :       INTEGER, DIMENSION(:, :), INTENT(IN)               :: connectivity
      97              :       INTEGER, DIMENSION(:), INTENT(INOUT)               :: atom
      98              : 
      99              :       INTEGER                                            :: iatom
     100              : 
     101         2960 :       DO iatom = 1, 6
     102         2960 :          IF (connectivity(iatom, current_atom) /= 0) THEN
     103         1636 :             IF (connectivity(iatom, current_atom) /= avoid_atom) THEN
     104          312 :                atom(connectivity(iatom, current_atom)) = 1
     105              :                CALL depth_first_search(connectivity(iatom, current_atom), &
     106          312 :                                        current_atom, connectivity, atom)
     107              :             END IF
     108              :          ELSE
     109              :             RETURN
     110              :          END IF
     111              :       END DO
     112              : 
     113              :    END SUBROUTINE depth_first_search
     114              : 
     115              : ! **************************************************************************************************
     116              : !> \brief performs either a bond or angle change move for a given molecule
     117              : !> \param mc_par the mc parameters for the force env
     118              : !> \param force_env the force environment used in the move
     119              : !> \param bias_env the force environment used to bias the move, if any (it may
     120              : !>            be null if lbias=.false. in mc_par)
     121              : !> \param moves the structure that keeps track of how many moves have been
     122              : !>               accepted/rejected
     123              : !> \param move_updates the structure that keeps track of how many moves have
     124              : !>               been accepted/rejected since the last time the displacements
     125              : !>               were updated
     126              : !> \param start_atom the number of the molecule's first atom, assuming the rest
     127              : !>        of the atoms follow sequentially
     128              : !> \param molecule_type the type of the molecule we're moving
     129              : !> \param box_number the box the molecule is in
     130              : !> \param bias_energy the biased energy of the system before the move
     131              : !> \param move_type dictates what kind of conformational change we do
     132              : !> \param lreject set to .true. if there is an overlap
     133              : !> \param rng_stream the random number stream that we draw from
     134              : !> \author MJM
     135              : ! **************************************************************************************************
     136          506 :    SUBROUTINE mc_conformation_change(mc_par, force_env, bias_env, moves, &
     137              :                                      move_updates, start_atom, molecule_type, box_number, &
     138              :                                      bias_energy, move_type, lreject, &
     139              :                                      rng_stream)
     140              : 
     141              :       TYPE(mc_simpar_type), POINTER                      :: mc_par
     142              :       TYPE(force_env_type), POINTER                      :: force_env, bias_env
     143              :       TYPE(mc_moves_type), POINTER                       :: moves, move_updates
     144              :       INTEGER, INTENT(IN)                                :: start_atom, molecule_type, box_number
     145              :       REAL(KIND=dp), INTENT(INOUT)                       :: bias_energy
     146              :       CHARACTER(LEN=*), INTENT(IN)                       :: move_type
     147              :       LOGICAL, INTENT(OUT)                               :: lreject
     148              :       TYPE(rng_stream_type), INTENT(INOUT)               :: rng_stream
     149              : 
     150              :       CHARACTER(len=*), PARAMETER :: routineN = 'mc_conformation_change'
     151              : 
     152              :       CHARACTER(default_string_length)                   :: name
     153              :       CHARACTER(default_string_length), DIMENSION(:), &
     154          506 :          POINTER                                         :: names
     155              :       INTEGER :: atom_number, end_atom, end_mol, handle, imol_type, imolecule, ipart, jbox, &
     156              :          molecule_number, nunits_mol, source, start_mol
     157          506 :       INTEGER, DIMENSION(:), POINTER                     :: mol_type, nunits
     158          506 :       INTEGER, DIMENSION(:, :), POINTER                  :: nchains
     159              :       LOGICAL                                            :: ionode, lbias, loverlap
     160              :       REAL(KIND=dp)                                      :: BETA, bias_energy_new, bias_energy_old, &
     161              :                                                             dis_length, exp_max_val, exp_min_val, &
     162              :                                                             rand, value, w
     163              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: r_new, r_old
     164              :       TYPE(cp_subsys_type), POINTER                      :: subsys
     165              :       TYPE(mc_molecule_info_type), POINTER               :: mc_molecule_info
     166              :       TYPE(molecule_kind_list_type), POINTER             :: molecule_kinds
     167              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind, molecule_kind_test
     168              :       TYPE(mp_comm_type)                                 :: group
     169              :       TYPE(particle_list_type), POINTER                  :: particles
     170              : 
     171              : ! begin the timing of the subroutine
     172              : 
     173          506 :       CALL timeset(routineN, handle)
     174              : 
     175              : ! nullify some pointers
     176          506 :       NULLIFY (particles, subsys, molecule_kinds, molecule_kind, &
     177          506 :                molecule_kind_test)
     178              : 
     179              : ! get a bunch of stuff from mc_par
     180              :       CALL get_mc_par(mc_par, lbias=lbias, mc_molecule_info=mc_molecule_info, &
     181              :                       BETA=BETA, exp_max_val=exp_max_val, &
     182          506 :                       exp_min_val=exp_min_val, group=group, source=source, ionode=ionode)
     183              :       CALL get_mc_molecule_info(mc_molecule_info, nchains=nchains, nunits=nunits, &
     184          506 :                                 mol_type=mol_type, names=names)
     185              : 
     186              : ! do some allocation
     187          506 :       nunits_mol = nunits(molecule_type)
     188         1518 :       ALLOCATE (r_old(1:3, 1:nunits_mol))
     189         1012 :       ALLOCATE (r_new(1:3, 1:nunits_mol))
     190              : 
     191              : ! find out some bounds for mol_type
     192          506 :       start_mol = 1
     193          506 :       DO jbox = 1, box_number - 1
     194          506 :          start_mol = start_mol + SUM(nchains(:, jbox))
     195              :       END DO
     196         1518 :       end_mol = start_mol + SUM(nchains(:, box_number)) - 1
     197              : 
     198              : ! figure out which molecule number we are
     199          506 :       end_atom = start_atom + nunits_mol - 1
     200          506 :       molecule_number = 0
     201          506 :       atom_number = 1
     202         2974 :       DO imolecule = 1, SUM(nchains(:, box_number))
     203         1962 :          IF (atom_number == start_atom) THEN
     204          506 :             molecule_number = imolecule
     205          506 :             EXIT
     206              :          END IF
     207         1456 :          atom_number = atom_number + nunits(mol_type(imolecule + start_mol - 1))
     208              :       END DO
     209          506 :       IF (molecule_number == 0) CPABORT('Cannot find the molecule number')
     210              : 
     211              : ! are we biasing this move?
     212          506 :       IF (lbias) THEN
     213              : 
     214              : ! grab the coordinates
     215          420 :          CALL force_env_get(bias_env, subsys=subsys)
     216              : ! save the energy
     217          420 :          bias_energy_old = bias_energy
     218              : 
     219              :       ELSE
     220              : 
     221              : ! grab the coordinates
     222           86 :          CALL force_env_get(force_env, subsys=subsys)
     223              :       END IF
     224              : 
     225              : ! now find the molecule type associated with this guy
     226              :       CALL cp_subsys_get(subsys, &
     227          506 :                          particles=particles, molecule_kinds=molecule_kinds)
     228          506 :       DO imol_type = 1, SIZE(molecule_kinds%els(:))
     229          506 :          molecule_kind_test => molecule_kinds%els(imol_type)
     230          506 :          CALL get_molecule_kind(molecule_kind_test, name=name)
     231          506 :          IF (TRIM(ADJUSTL(name)) == TRIM(ADJUSTL(names(molecule_type)))) THEN
     232          506 :             molecule_kind => molecule_kinds%els(imol_type)
     233          506 :             EXIT
     234              :          END IF
     235              :       END DO
     236              : 
     237              : ! save the coordinates
     238         2024 :       DO ipart = start_atom, end_atom
     239         6578 :          r_old(1:3, ipart - start_atom + 1) = particles%els(ipart)%r(1:3)
     240              :       END DO
     241              : 
     242          506 :       IF (.NOT. ASSOCIATED(molecule_kind)) CPABORT('Cannot find the molecule type')
     243              : ! do the move
     244          506 :       IF (move_type == 'bond') THEN
     245              : 
     246              : ! record the attempt
     247          312 :          moves%bond%attempts = moves%bond%attempts + 1
     248          312 :          move_updates%bond%attempts = move_updates%bond%attempts + 1
     249          312 :          moves%bias_bond%attempts = moves%bias_bond%attempts + 1
     250          312 :          move_updates%bias_bond%attempts = move_updates%bias_bond%attempts + 1
     251          312 :          IF (.NOT. lbias) THEN
     252           48 :             moves%bond%qsuccesses = moves%bond%qsuccesses + 1
     253              :             move_updates%bond%qsuccesses = &
     254           48 :                move_updates%bond%qsuccesses + 1
     255           48 :             moves%bias_bond%qsuccesses = moves%bias_bond%qsuccesses + 1
     256              :             move_updates%bias_bond%qsuccesses = &
     257           48 :                move_updates%bias_bond%qsuccesses + 1
     258              :          END IF
     259              : 
     260              : ! do the move
     261              :          CALL change_bond_length(r_old, r_new, mc_par, molecule_type, &
     262          312 :                                  molecule_kind, dis_length, particles, rng_stream)
     263              : 
     264          194 :       ELSE IF (move_type == 'angle') THEN
     265              : 
     266              : ! record the attempt
     267          194 :          moves%angle%attempts = moves%angle%attempts + 1
     268          194 :          move_updates%angle%attempts = move_updates%angle%attempts + 1
     269          194 :          moves%bias_angle%attempts = moves%bias_angle%attempts + 1
     270          194 :          move_updates%bias_angle%attempts = move_updates%bias_angle%attempts + 1
     271          194 :          IF (.NOT. lbias) THEN
     272           38 :             moves%angle%qsuccesses = moves%angle%qsuccesses + 1
     273              :             move_updates%angle%qsuccesses = &
     274           38 :                move_updates%angle%qsuccesses + 1
     275           38 :             moves%bias_angle%qsuccesses = moves%bias_angle%qsuccesses + 1
     276              :             move_updates%bias_angle%qsuccesses = &
     277           38 :                move_updates%bias_angle%qsuccesses + 1
     278              :          END IF
     279              : 
     280              : ! do the move
     281              :          CALL change_bond_angle(r_old, r_new, mc_par, molecule_type, &
     282          194 :                                 molecule_kind, particles, rng_stream)
     283          194 :          dis_length = 1.0E0_dp
     284              :       ELSE
     285              : ! record the attempt
     286            0 :          moves%dihedral%attempts = moves%dihedral%attempts + 1
     287            0 :          move_updates%dihedral%attempts = move_updates%dihedral%attempts + 1
     288            0 :          moves%bias_dihedral%attempts = moves%bias_dihedral%attempts + 1
     289            0 :          move_updates%bias_dihedral%attempts = move_updates%bias_dihedral%attempts + 1
     290            0 :          IF (.NOT. lbias) THEN
     291            0 :             moves%dihedral%qsuccesses = moves%dihedral%qsuccesses + 1
     292              :             move_updates%dihedral%qsuccesses = &
     293            0 :                move_updates%dihedral%qsuccesses + 1
     294            0 :             moves%bias_dihedral%qsuccesses = moves%bias_dihedral%qsuccesses + 1
     295              :             move_updates%bias_dihedral%qsuccesses = &
     296            0 :                move_updates%bias_dihedral%qsuccesses + 1
     297              :          END IF
     298              : 
     299              : ! do the move
     300              :          CALL change_dihedral(r_old, r_new, mc_par, molecule_type, &
     301            0 :                               molecule_kind, particles, rng_stream)
     302            0 :          dis_length = 1.0E0_dp
     303              : 
     304              :       END IF
     305              : 
     306              : ! set the coordinates
     307         2024 :       DO ipart = start_atom, end_atom
     308         6578 :          particles%els(ipart)%r(1:3) = r_new(1:3, ipart - start_atom + 1)
     309              :       END DO
     310              : 
     311              : ! check for overlap
     312          506 :       lreject = .FALSE.
     313          506 :       IF (lbias) THEN
     314              :          CALL check_for_overlap(bias_env, nchains(:, box_number), &
     315              :                                 nunits(:), loverlap, mol_type(start_mol:end_mol), &
     316          420 :                                 molecule_number=molecule_number)
     317              :       ELSE
     318              :          CALL check_for_overlap(force_env, nchains(:, box_number), &
     319              :                                 nunits(:), loverlap, mol_type(start_mol:end_mol), &
     320           86 :                                 molecule_number=molecule_number)
     321           86 :          IF (loverlap) lreject = .TRUE.
     322              :       END IF
     323              : 
     324              : ! if we're biasing classical, check for acceptance
     325          506 :       IF (lbias) THEN
     326              : 
     327              : ! here's where we bias the moves
     328              : 
     329          420 :          IF (loverlap) THEN
     330              :             w = 0.0E0_dp
     331              :          ELSE
     332          420 :             CALL force_env_calc_energy_force(bias_env, calc_force=.FALSE.)
     333              :             CALL force_env_get(bias_env, &
     334          420 :                                potential_energy=bias_energy_new)
     335              : ! accept or reject the move based on the Metropolis rule with a
     336              : ! correction factor for the change in phase space...dis_length is
     337              : ! made unitless in change_bond_length
     338          420 :             value = -BETA*(bias_energy_new - bias_energy_old)
     339          420 :             IF (value > exp_max_val) THEN
     340              :                w = 10.0_dp
     341          420 :             ELSE IF (value < exp_min_val) THEN
     342              :                w = 0.0_dp
     343              :             ELSE
     344          420 :                w = EXP(value)*dis_length**2
     345              :             END IF
     346              : 
     347              :          END IF
     348              : 
     349          420 :          IF (w >= 1.0E0_dp) THEN
     350          194 :             w = 1.0E0_dp
     351          194 :             rand = 0.0E0_dp
     352              :          ELSE
     353          226 :             IF (ionode) THEN
     354          113 :                rand = rng_stream%next()
     355              :             END IF
     356          226 :             CALL group%bcast(rand, source)
     357              :          END IF
     358              : 
     359          420 :          IF (rand < w) THEN
     360              : 
     361              : ! accept the move
     362          252 :             IF (move_type == 'bond') THEN
     363          140 :                moves%bond%qsuccesses = moves%bond%qsuccesses + 1
     364              :                move_updates%bond%successes = &
     365          140 :                   move_updates%bond%successes + 1
     366          140 :                moves%bias_bond%successes = moves%bias_bond%successes + 1
     367              :                move_updates%bias_bond%successes = &
     368          140 :                   move_updates%bias_bond%successes + 1
     369          112 :             ELSE IF (move_type == 'angle') THEN
     370          112 :                moves%angle%qsuccesses = moves%angle%qsuccesses + 1
     371              :                move_updates%angle%successes = &
     372          112 :                   move_updates%angle%successes + 1
     373          112 :                moves%bias_angle%successes = moves%bias_angle%successes + 1
     374              :                move_updates%bias_angle%successes = &
     375          112 :                   move_updates%bias_angle%successes + 1
     376              :             ELSE
     377            0 :                moves%dihedral%qsuccesses = moves%dihedral%qsuccesses + 1
     378              :                move_updates%dihedral%successes = &
     379            0 :                   move_updates%dihedral%successes + 1
     380            0 :                moves%bias_dihedral%successes = moves%bias_dihedral%successes + 1
     381              :                move_updates%bias_dihedral%successes = &
     382            0 :                   move_updates%bias_dihedral%successes + 1
     383              :             END IF
     384              : 
     385              :             bias_energy = bias_energy + bias_energy_new - &
     386          252 :                           bias_energy_old
     387              : 
     388              :          ELSE
     389              : 
     390              : ! reject the move
     391              : ! restore the coordinates
     392          168 :             CALL force_env_get(bias_env, subsys=subsys)
     393          168 :             CALL cp_subsys_get(subsys, particles=particles)
     394          672 :             DO ipart = start_atom, end_atom
     395         2184 :                particles%els(ipart)%r(1:3) = r_old(1:3, ipart - start_atom + 1)
     396              :             END DO
     397          168 :             CALL cp_subsys_set(subsys, particles=particles)
     398              : 
     399              :          END IF
     400              : 
     401              :       END IF
     402              : 
     403              : ! deallocate some stuff
     404          506 :       DEALLOCATE (r_old)
     405          506 :       DEALLOCATE (r_new)
     406              : 
     407              : ! end the timing
     408          506 :       CALL timestop(handle)
     409              : 
     410          506 :    END SUBROUTINE mc_conformation_change
     411              : 
     412              : ! **************************************************************************************************
     413              : !> \brief translates the given molecule randomly in either the x,y, or z direction
     414              : !> \param mc_par the mc parameters for the force env
     415              : !> \param force_env the force environment used in the move
     416              : !> \param bias_env the force environment used to bias the move, if any (it may
     417              : !>            be null if lbias=.false. in mc_par)
     418              : !> \param moves the structure that keeps track of how many moves have been
     419              : !>               accepted/rejected
     420              : !> \param move_updates the structure that keeps track of how many moves have
     421              : !>               been accepted/rejected since the last time the displacements
     422              : !>               were updated
     423              : !> \param start_atom the number of the molecule's first atom, assuming the rest of
     424              : !>        the atoms follow sequentially
     425              : !> \param box_number the box the molecule is in
     426              : !> \param bias_energy the biased energy of the system before the move
     427              : !> \param molecule_type the type of molecule we're moving
     428              : !> \param lreject set to .true. if there is an overlap
     429              : !> \param rng_stream the random number stream that we draw from
     430              : !> \author MJM
     431              : ! **************************************************************************************************
     432          624 :    SUBROUTINE mc_molecule_translation(mc_par, force_env, bias_env, moves, &
     433              :                                       move_updates, start_atom, box_number, &
     434              :                                       bias_energy, molecule_type, &
     435              :                                       lreject, rng_stream)
     436              : 
     437              :       TYPE(mc_simpar_type), POINTER                      :: mc_par
     438              :       TYPE(force_env_type), POINTER                      :: force_env, bias_env
     439              :       TYPE(mc_moves_type), POINTER                       :: moves, move_updates
     440              :       INTEGER, INTENT(IN)                                :: start_atom, box_number
     441              :       REAL(KIND=dp), INTENT(INOUT)                       :: bias_energy
     442              :       INTEGER, INTENT(IN)                                :: molecule_type
     443              :       LOGICAL, INTENT(OUT)                               :: lreject
     444              :       TYPE(rng_stream_type), INTENT(INOUT)               :: rng_stream
     445              : 
     446              :       CHARACTER(len=*), PARAMETER :: routineN = 'mc_molecule_translation'
     447              : 
     448              :       INTEGER :: atom_number, end_atom, end_mol, handle, imolecule, ipart, iparticle, jbox, &
     449              :          molecule_number, move_direction, nunits_mol, source, start_mol
     450          624 :       INTEGER, DIMENSION(:), POINTER                     :: mol_type, nunits, nunits_tot
     451          624 :       INTEGER, DIMENSION(:, :), POINTER                  :: nchains
     452              :       LOGICAL                                            :: ionode, lbias, loverlap
     453          624 :       REAL(dp), DIMENSION(:), POINTER                    :: rmtrans
     454              :       REAL(KIND=dp)                                      :: BETA, bias_energy_new, bias_energy_old, &
     455              :                                                             dis_mol, exp_max_val, exp_min_val, &
     456              :                                                             rand, value, w
     457          624 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: r_old
     458              :       TYPE(cp_subsys_type), POINTER                      :: subsys
     459              :       TYPE(mc_molecule_info_type), POINTER               :: mc_molecule_info
     460              :       TYPE(mp_comm_type)                                 :: group
     461              :       TYPE(particle_list_type), POINTER                  :: particles
     462              : 
     463              : !   *** Local Counters ***
     464              : ! begin the timing of the subroutine
     465              : 
     466          624 :       CALL timeset(routineN, handle)
     467              : 
     468              : ! nullify some pointers
     469          624 :       NULLIFY (particles, subsys)
     470              : 
     471              : ! get a bunch of stuff from mc_par
     472              :       CALL get_mc_par(mc_par, lbias=lbias, &
     473              :                       BETA=BETA, exp_max_val=exp_max_val, &
     474              :                       exp_min_val=exp_min_val, rmtrans=rmtrans, ionode=ionode, source=source, &
     475          624 :                       group=group, mc_molecule_info=mc_molecule_info)
     476              :       CALL get_mc_molecule_info(mc_molecule_info, nunits_tot=nunits_tot, &
     477          624 :                                 nchains=nchains, nunits=nunits, mol_type=mol_type)
     478              : 
     479              : ! find out some bounds for mol_type
     480          624 :       start_mol = 1
     481          640 :       DO jbox = 1, box_number - 1
     482          672 :          start_mol = start_mol + SUM(nchains(:, jbox))
     483              :       END DO
     484         1872 :       end_mol = start_mol + SUM(nchains(:, box_number)) - 1
     485              : 
     486              : ! do some allocation
     487         1872 :       ALLOCATE (r_old(1:3, 1:nunits_tot(box_number)))
     488              : 
     489              : ! find the index of the last atom of this molecule, and the molecule number
     490          624 :       nunits_mol = nunits(molecule_type)
     491          624 :       end_atom = start_atom + nunits_mol - 1
     492          624 :       molecule_number = 0
     493          624 :       atom_number = 1
     494         5770 :       DO imolecule = 1, SUM(nchains(:, box_number))
     495         4522 :          IF (atom_number == start_atom) THEN
     496          624 :             molecule_number = imolecule
     497          624 :             EXIT
     498              :          END IF
     499         3898 :          atom_number = atom_number + nunits(mol_type(imolecule + start_mol - 1))
     500              :       END DO
     501          624 :       IF (molecule_number == 0) CPABORT('Cannot find the molecule number')
     502              : 
     503              : ! are we biasing this move?
     504          624 :       IF (lbias) THEN
     505              : 
     506              : ! grab the coordinates
     507          528 :          CALL force_env_get(bias_env, subsys=subsys)
     508          528 :          CALL cp_subsys_get(subsys, particles=particles)
     509              : 
     510              : ! save the coordinates
     511        14710 :          DO ipart = 1, nunits_tot(box_number)
     512        57256 :             r_old(1:3, ipart) = particles%els(ipart)%r(1:3)
     513              :          END DO
     514              : 
     515              : ! save the energy
     516          528 :          bias_energy_old = bias_energy
     517              : 
     518              :       ELSE
     519              : 
     520              : ! grab the coordinates
     521           96 :          CALL force_env_get(force_env, subsys=subsys)
     522           96 :          CALL cp_subsys_get(subsys, particles=particles)
     523              :       END IF
     524              : 
     525              : ! record the attempt
     526          624 :       moves%trans%attempts = moves%trans%attempts + 1
     527          624 :       move_updates%trans%attempts = move_updates%trans%attempts + 1
     528          624 :       moves%bias_trans%attempts = moves%bias_trans%attempts + 1
     529          624 :       move_updates%bias_trans%attempts = move_updates%bias_trans%attempts + 1
     530          624 :       IF (.NOT. lbias) THEN
     531           96 :          moves%trans%qsuccesses = moves%trans%qsuccesses + 1
     532           96 :          move_updates%trans%qsuccesses = move_updates%trans%qsuccesses + 1
     533           96 :          moves%bias_trans%qsuccesses = moves%bias_trans%qsuccesses + 1
     534           96 :          move_updates%bias_trans%qsuccesses = move_updates%bias_trans%qsuccesses + 1
     535              :       END IF
     536              : 
     537              : ! move one molecule in the system
     538              : 
     539              : ! call a random number to figure out which direction we're moving
     540          624 :       IF (ionode) rand = rng_stream%next()
     541          624 :       CALL group%bcast(rand, source)
     542              :       ! 1,2,3 with equal prob
     543          624 :       move_direction = INT(3*rand) + 1
     544              : 
     545              : ! call a random number to figure out how far we're moving
     546          624 :       IF (ionode) rand = rng_stream%next()
     547          624 :       CALL group%bcast(rand, source)
     548          624 :       dis_mol = rmtrans(molecule_type)*(rand - 0.5E0_dp)*2.0E0_dp
     549              : 
     550              : ! do the move
     551         1896 :       DO iparticle = start_atom, end_atom
     552              :          particles%els(iparticle)%r(move_direction) = &
     553         1896 :             particles%els(iparticle)%r(move_direction) + dis_mol
     554              :       END DO
     555          624 :       CALL cp_subsys_set(subsys, particles=particles)
     556              : 
     557              : ! figure out if there is any overlap...need the number of the molecule
     558          624 :       lreject = .FALSE.
     559          624 :       IF (lbias) THEN
     560              :          CALL check_for_overlap(bias_env, nchains(:, box_number), &
     561              :                                 nunits(:), loverlap, mol_type(start_mol:end_mol), &
     562          528 :                                 molecule_number=molecule_number)
     563              :       ELSE
     564              :          CALL check_for_overlap(force_env, nchains(:, box_number), &
     565              :                                 nunits(:), loverlap, mol_type(start_mol:end_mol), &
     566           96 :                                 molecule_number=molecule_number)
     567           96 :          IF (loverlap) lreject = .TRUE.
     568              :       END IF
     569              : 
     570              : ! if we're biasing with a cheaper potential, check for acceptance
     571          624 :       IF (lbias) THEN
     572              : 
     573              : ! here's where we bias the moves
     574          528 :          IF (loverlap) THEN
     575              :             w = 0.0E0_dp
     576              :          ELSE
     577          528 :             CALL force_env_calc_energy_force(bias_env, calc_force=.FALSE.)
     578              :             CALL force_env_get(bias_env, &
     579          528 :                                potential_energy=bias_energy_new)
     580              : ! accept or reject the move based on the Metropolis rule
     581          528 :             value = -BETA*(bias_energy_new - bias_energy_old)
     582          528 :             IF (value > exp_max_val) THEN
     583              :                w = 10.0_dp
     584          528 :             ELSE IF (value < exp_min_val) THEN
     585              :                w = 0.0_dp
     586              :             ELSE
     587          528 :                w = EXP(value)
     588              :             END IF
     589              : 
     590              :          END IF
     591              : 
     592          528 :          IF (w >= 1.0E0_dp) THEN
     593          258 :             w = 1.0E0_dp
     594          258 :             rand = 0.0E0_dp
     595              :          ELSE
     596          270 :             IF (ionode) rand = rng_stream%next()
     597          270 :             CALL group%bcast(rand, source)
     598              :          END IF
     599              : 
     600          528 :          IF (rand < w) THEN
     601              : 
     602              : ! accept the move
     603          454 :             moves%bias_trans%successes = moves%bias_trans%successes + 1
     604          454 :             move_updates%bias_trans%successes = move_updates%bias_trans%successes + 1
     605          454 :             moves%trans%qsuccesses = moves%trans%qsuccesses + 1
     606              :             move_updates%trans%successes = &
     607          454 :                move_updates%trans%successes + 1
     608          454 :             moves%qtrans_dis = moves%qtrans_dis + ABS(dis_mol)
     609              :             bias_energy = bias_energy + bias_energy_new - &
     610          454 :                           bias_energy_old
     611              : 
     612              :          ELSE
     613              : 
     614              : ! reject the move
     615              : ! restore the coordinates
     616           74 :             CALL force_env_get(bias_env, subsys=subsys)
     617           74 :             CALL cp_subsys_get(subsys, particles=particles)
     618         2072 :             DO ipart = 1, nunits_tot(box_number)
     619         8066 :                particles%els(ipart)%r(1:3) = r_old(1:3, ipart)
     620              :             END DO
     621           74 :             CALL cp_subsys_set(subsys, particles=particles)
     622              : 
     623              :          END IF
     624              : 
     625              :       END IF
     626              : 
     627              : ! deallocate some stuff
     628          624 :       DEALLOCATE (r_old)
     629              : 
     630              : ! end the timing
     631          624 :       CALL timestop(handle)
     632              : 
     633          624 :    END SUBROUTINE mc_molecule_translation
     634              : 
     635              : ! **************************************************************************************************
     636              : !> \brief rotates the given molecule randomly around the x,y, or z axis...
     637              : !>      only works for water at the moment
     638              : !> \param mc_par the mc parameters for the force env
     639              : !> \param force_env the force environment used in the move
     640              : !> \param bias_env the force environment used to bias the move, if any (it may
     641              : !>            be null if lbias=.false. in mc_par)
     642              : !> \param moves the structure that keeps track of how many moves have been
     643              : !>               accepted/rejected
     644              : !> \param move_updates the structure that keeps track of how many moves have
     645              : !>               been accepted/rejected since the last time the displacements
     646              : !>               were updated
     647              : !> \param box_number the box the molecule is in
     648              : !> \param start_atom the number of the molecule's first atom, assuming the rest of
     649              : !>        the atoms follow sequentially
     650              : !> \param molecule_type the type of molecule we're moving
     651              : !> \param bias_energy the biased energy of the system before the move
     652              : !> \param lreject set to .true. if there is an overlap
     653              : !> \param rng_stream the random number stream that we draw from
     654              : !> \author MJM
     655              : ! **************************************************************************************************
     656          502 :    SUBROUTINE mc_molecule_rotation(mc_par, force_env, bias_env, moves, &
     657              :                                    move_updates, box_number, &
     658              :                                    start_atom, molecule_type, bias_energy, lreject, &
     659              :                                    rng_stream)
     660              : 
     661              :       TYPE(mc_simpar_type), POINTER                      :: mc_par
     662              :       TYPE(force_env_type), POINTER                      :: force_env, bias_env
     663              :       TYPE(mc_moves_type), POINTER                       :: moves, move_updates
     664              :       INTEGER, INTENT(IN)                                :: box_number, start_atom, molecule_type
     665              :       REAL(KIND=dp), INTENT(INOUT)                       :: bias_energy
     666              :       LOGICAL, INTENT(OUT)                               :: lreject
     667              :       TYPE(rng_stream_type), INTENT(INOUT)               :: rng_stream
     668              : 
     669              :       CHARACTER(len=*), PARAMETER :: routineN = 'mc_molecule_rotation'
     670              : 
     671              :       INTEGER :: atom_number, dir, end_atom, end_mol, handle, ii, imolecule, ipart, iunit, jbox, &
     672              :          molecule_number, nunits_mol, source, start_mol
     673          502 :       INTEGER, DIMENSION(:), POINTER                     :: mol_type, nunits, nunits_tot
     674          502 :       INTEGER, DIMENSION(:, :), POINTER                  :: nchains
     675              :       LOGICAL                                            :: ionode, lbias, loverlap, lx, ly
     676          502 :       REAL(dp), DIMENSION(:), POINTER                    :: rmrot
     677          502 :       REAL(dp), DIMENSION(:, :), POINTER                 :: mass
     678              :       REAL(KIND=dp) :: BETA, bias_energy_new, bias_energy_old, cosdg, dgamma, exp_max_val, &
     679              :          exp_min_val, masstot, nxcm, nycm, nzcm, rand, rx, rxnew, ry, rynew, rz, rznew, sindg, &
     680              :          value, w
     681          502 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: r_old
     682              :       TYPE(cp_subsys_type), POINTER                      :: subsys
     683              :       TYPE(mc_molecule_info_type), POINTER               :: mc_molecule_info
     684              :       TYPE(mp_comm_type)                                 :: group
     685              :       TYPE(particle_list_type), POINTER                  :: particles
     686              : 
     687              : ! begin the timing of the subroutine
     688              : 
     689          502 :       CALL timeset(routineN, handle)
     690              : 
     691          502 :       NULLIFY (rmrot, subsys, particles)
     692              : 
     693              : ! get a bunch of stuff from mc_par
     694              :       CALL get_mc_par(mc_par, lbias=lbias, &
     695              :                       BETA=BETA, exp_max_val=exp_max_val, &
     696              :                       exp_min_val=exp_min_val, rmrot=rmrot, mc_molecule_info=mc_molecule_info, &
     697          502 :                       ionode=ionode, group=group, source=source)
     698              :       CALL get_mc_molecule_info(mc_molecule_info, nunits=nunits, &
     699              :                                 nunits_tot=nunits_tot, nchains=nchains, mass=mass, &
     700          502 :                                 mol_type=mol_type)
     701              : 
     702              : ! figure out some bounds for mol_type
     703          502 :       start_mol = 1
     704          516 :       DO jbox = 1, box_number - 1
     705          544 :          start_mol = start_mol + SUM(nchains(:, jbox))
     706              :       END DO
     707         1506 :       end_mol = start_mol + SUM(nchains(:, box_number)) - 1
     708              : 
     709          502 :       nunits_mol = nunits(molecule_type)
     710              : 
     711              : ! nullify some pointers
     712          502 :       NULLIFY (particles, subsys)
     713              : 
     714              : ! do some allocation
     715         1506 :       ALLOCATE (r_old(1:3, 1:nunits_tot(box_number)))
     716              : 
     717              : ! initialize some stuff
     718          502 :       lx = .FALSE.
     719          502 :       ly = .FALSE.
     720              : 
     721              : ! determine what the final atom in the molecule is numbered, and which
     722              : ! molecule number this is
     723          502 :       end_atom = start_atom + nunits_mol - 1
     724          502 :       molecule_number = 0
     725          502 :       atom_number = 1
     726         2956 :       DO imolecule = 1, SUM(nchains(:, box_number))
     727         1952 :          IF (atom_number == start_atom) THEN
     728          502 :             molecule_number = imolecule
     729          502 :             EXIT
     730              :          END IF
     731         1450 :          atom_number = atom_number + nunits(mol_type(imolecule + start_mol - 1))
     732              :       END DO
     733          502 :       IF (molecule_number == 0) CPABORT('Cannot find the molecule number')
     734              : 
     735              : ! are we biasing this move?
     736          502 :       IF (lbias) THEN
     737              : 
     738              : ! grab the coordinates
     739          424 :          CALL force_env_get(bias_env, subsys=subsys)
     740          424 :          CALL cp_subsys_get(subsys, particles=particles)
     741              : 
     742              : ! save the coordinates
     743        11808 :          DO ipart = 1, nunits_tot(box_number)
     744        45960 :             r_old(1:3, ipart) = particles%els(ipart)%r(1:3)
     745              :          END DO
     746              : 
     747              : ! save the energy
     748          424 :          bias_energy_old = bias_energy
     749              : 
     750              :       ELSE
     751              : 
     752              : ! grab the coordinates
     753           78 :          CALL force_env_get(force_env, subsys=subsys)
     754           78 :          CALL cp_subsys_get(subsys, particles=particles)
     755              :       END IF
     756              : 
     757              : ! grab the masses
     758         2008 :       masstot = SUM(mass(1:nunits(molecule_type), molecule_type))
     759              : 
     760              : ! record the attempt
     761          502 :       moves%bias_rot%attempts = moves%bias_rot%attempts + 1
     762          502 :       move_updates%bias_rot%attempts = move_updates%bias_rot%attempts + 1
     763          502 :       moves%rot%attempts = moves%rot%attempts + 1
     764          502 :       move_updates%rot%attempts = move_updates%rot%attempts + 1
     765          502 :       IF (.NOT. lbias) THEN
     766           78 :          moves%rot%qsuccesses = moves%rot%qsuccesses + 1
     767           78 :          move_updates%rot%qsuccesses = move_updates%rot%qsuccesses + 1
     768           78 :          moves%bias_rot%qsuccesses = moves%bias_rot%qsuccesses + 1
     769           78 :          move_updates%bias_rot%qsuccesses = move_updates%bias_rot%qsuccesses + 1
     770              :       END IF
     771              : 
     772              : ! rotate one molecule in the system
     773              : 
     774              : ! call a random number to figure out which direction we're moving
     775          502 :       IF (ionode) rand = rng_stream%next()
     776              : !      CALL RANDOM_NUMBER(rand)
     777          502 :       CALL group%bcast(rand, source)
     778              :       ! 1,2,3 with equal prob
     779          502 :       dir = INT(3*rand) + 1
     780              : 
     781          502 :       IF (dir == 1) THEN
     782              :          lx = .TRUE.
     783          334 :       ELSE IF (dir == 2) THEN
     784          176 :          ly = .TRUE.
     785              :       END IF
     786              : 
     787              : ! Determine new center of mass for chain i by finding the sum
     788              : ! of m*r for each unit, then dividing by the total mass of the chain
     789          502 :       nxcm = 0.0E0_dp
     790          502 :       nycm = 0.0E0_dp
     791          502 :       nzcm = 0.0E0_dp
     792         2008 :       DO ii = 1, nunits_mol
     793         1506 :          nxcm = nxcm + particles%els(start_atom - 1 + ii)%r(1)*mass(ii, molecule_type)
     794         1506 :          nycm = nycm + particles%els(start_atom - 1 + ii)%r(2)*mass(ii, molecule_type)
     795         2008 :          nzcm = nzcm + particles%els(start_atom - 1 + ii)%r(3)*mass(ii, molecule_type)
     796              :       END DO
     797          502 :       nxcm = nxcm/masstot
     798          502 :       nycm = nycm/masstot
     799          502 :       nzcm = nzcm/masstot
     800              : 
     801              : ! call a random number to figure out how far we're moving
     802          502 :       IF (ionode) rand = rng_stream%next()
     803          502 :       CALL group%bcast(rand, source)
     804          502 :       dgamma = rmrot(molecule_type)*(rand - 0.5E0_dp)*2.0E0_dp
     805              : 
     806              : ! *** set up the rotation matrix ***
     807              : 
     808          502 :       cosdg = COS(dgamma)
     809          502 :       sindg = SIN(dgamma)
     810              : 
     811          502 :       IF (lx) THEN
     812              : 
     813              : ! ***    ROTATE UNITS OF I AROUND X-AXIS ***
     814              : 
     815          672 :          DO iunit = start_atom, end_atom
     816          504 :             ry = particles%els(iunit)%r(2) - nycm
     817          504 :             rz = particles%els(iunit)%r(3) - nzcm
     818          504 :             rynew = cosdg*ry - sindg*rz
     819          504 :             rznew = cosdg*rz + sindg*ry
     820              : 
     821          504 :             particles%els(iunit)%r(2) = rynew + nycm
     822          672 :             particles%els(iunit)%r(3) = rznew + nzcm
     823              : 
     824              :          END DO
     825          334 :       ELSE IF (ly) THEN
     826              : 
     827              : ! ***    ROTATE UNITS OF I AROUND y-AXIS ***
     828              : 
     829          704 :          DO iunit = start_atom, end_atom
     830          528 :             rx = particles%els(iunit)%r(1) - nxcm
     831          528 :             rz = particles%els(iunit)%r(3) - nzcm
     832          528 :             rxnew = cosdg*rx + sindg*rz
     833          528 :             rznew = cosdg*rz - sindg*rx
     834              : 
     835          528 :             particles%els(iunit)%r(1) = rxnew + nxcm
     836          704 :             particles%els(iunit)%r(3) = rznew + nzcm
     837              : 
     838              :          END DO
     839              : 
     840              :       ELSE
     841              : 
     842              : ! ***    ROTATE UNITS OF I AROUND z-AXIS ***
     843              : 
     844          632 :          DO iunit = start_atom, end_atom
     845          474 :             rx = particles%els(iunit)%r(1) - nxcm
     846          474 :             ry = particles%els(iunit)%r(2) - nycm
     847              : 
     848          474 :             rxnew = cosdg*rx - sindg*ry
     849          474 :             rynew = cosdg*ry + sindg*rx
     850              : 
     851          474 :             particles%els(iunit)%r(1) = rxnew + nxcm
     852          632 :             particles%els(iunit)%r(2) = rynew + nycm
     853              : 
     854              :          END DO
     855              : 
     856              :       END IF
     857          502 :       CALL cp_subsys_set(subsys, particles=particles)
     858              : 
     859              : ! check for overlap
     860          502 :       lreject = .FALSE.
     861          502 :       IF (lbias) THEN
     862              :          CALL check_for_overlap(bias_env, nchains(:, box_number), &
     863              :                                 nunits(:), loverlap, mol_type(start_mol:end_mol), &
     864          424 :                                 molecule_number=molecule_number)
     865              :       ELSE
     866              :          CALL check_for_overlap(force_env, nchains(:, box_number), &
     867              :                                 nunits(:), loverlap, mol_type(start_mol:end_mol), &
     868           78 :                                 molecule_number=molecule_number)
     869           78 :          IF (loverlap) lreject = .TRUE.
     870              :       END IF
     871              : 
     872              : ! if we're biasing classical, check for acceptance
     873          502 :       IF (lbias) THEN
     874              : 
     875              : ! here's where we bias the moves
     876              : 
     877          424 :          IF (loverlap) THEN
     878              :             w = 0.0E0_dp
     879              :          ELSE
     880          424 :             CALL force_env_calc_energy_force(bias_env, calc_force=.FALSE.)
     881              :             CALL force_env_get(bias_env, &
     882          424 :                                potential_energy=bias_energy_new)
     883              : ! accept or reject the move based on the Metropolis rule
     884          424 :             value = -BETA*(bias_energy_new - bias_energy_old)
     885          424 :             IF (value > exp_max_val) THEN
     886              :                w = 10.0_dp
     887          424 :             ELSE IF (value < exp_min_val) THEN
     888              :                w = 0.0_dp
     889              :             ELSE
     890          424 :                w = EXP(value)
     891              :             END IF
     892              : 
     893              :          END IF
     894              : 
     895          424 :          IF (w >= 1.0E0_dp) THEN
     896          180 :             w = 1.0E0_dp
     897          180 :             rand = 0.0E0_dp
     898              :          ELSE
     899          244 :             IF (ionode) rand = rng_stream%next()
     900          244 :             CALL group%bcast(rand, source)
     901              :          END IF
     902              : 
     903          424 :          IF (rand < w) THEN
     904              : 
     905              : ! accept the move
     906          340 :             moves%bias_rot%successes = moves%bias_rot%successes + 1
     907          340 :             move_updates%bias_rot%successes = move_updates%bias_rot%successes + 1
     908          340 :             moves%rot%qsuccesses = moves%rot%qsuccesses + 1
     909          340 :             move_updates%rot%successes = move_updates%rot%successes + 1
     910              :             bias_energy = bias_energy + bias_energy_new - &
     911          340 :                           bias_energy_old
     912              : 
     913              :          ELSE
     914              : 
     915              : ! reject the move
     916              : ! restore the coordinates
     917           84 :             CALL force_env_get(bias_env, subsys=subsys)
     918           84 :             CALL cp_subsys_get(subsys, particles=particles)
     919         2316 :             DO ipart = 1, nunits_tot(box_number)
     920         9012 :                particles%els(ipart)%r(1:3) = r_old(1:3, ipart)
     921              :             END DO
     922           84 :             CALL cp_subsys_set(subsys, particles=particles)
     923              : 
     924              :          END IF
     925              : 
     926              :       END IF
     927              : 
     928              : ! deallocate some stuff
     929          502 :       DEALLOCATE (r_old)
     930              : 
     931              : ! end the timing
     932          502 :       CALL timestop(handle)
     933              : 
     934          502 :    END SUBROUTINE mc_molecule_rotation
     935              : 
     936              : ! **************************************************************************************************
     937              : !> \brief performs a Monte Carlo move that alters the volume of the simulation box
     938              : !> \param mc_par the mc parameters for the force env
     939              : !> \param force_env the force environment whose cell we're changing
     940              : !> \param moves the structure that keeps track of how many moves have been
     941              : !>               accepted/rejected
     942              : !> \param move_updates the structure that keeps track of how many moves have
     943              : !>               been accepted/rejected since the last time the displacements
     944              : !>               were updated
     945              : !> \param old_energy the energy of the last accepted move involving an
     946              : !>                    unbiased calculation
     947              : !> \param box_number the box we're changing the volume of
     948              : !> \param energy_check the running total of how much the energy has changed
     949              : !>                      since the initial configuration
     950              : !> \param r_old the coordinates of the last accepted move involving an
     951              : !>               unbiased calculation
     952              : !> \param iw the unit number that writes to the screen
     953              : !> \param discrete_array tells use which volumes we can do for the discrete
     954              : !>            case
     955              : !> \param rng_stream the random number stream that we draw from
     956              : !> \author MJM
     957              : !> \note     Designed for parallel use.
     958              : ! **************************************************************************************************
     959           34 :    SUBROUTINE mc_volume_move(mc_par, force_env, moves, move_updates, &
     960              :                              old_energy, box_number, &
     961           34 :                              energy_check, r_old, iw, discrete_array, rng_stream)
     962              : 
     963              :       TYPE(mc_simpar_type), POINTER                      :: mc_par
     964              :       TYPE(force_env_type), POINTER                      :: force_env
     965              :       TYPE(mc_moves_type), POINTER                       :: moves, move_updates
     966              :       REAL(KIND=dp), INTENT(INOUT)                       :: old_energy
     967              :       INTEGER, INTENT(IN)                                :: box_number
     968              :       REAL(KIND=dp), INTENT(INOUT)                       :: energy_check
     969              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT)      :: r_old
     970              :       INTEGER, INTENT(IN)                                :: iw
     971              :       INTEGER, DIMENSION(1:3, 1:2), INTENT(INOUT)        :: discrete_array
     972              :       TYPE(rng_stream_type), INTENT(INOUT)               :: rng_stream
     973              : 
     974              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'mc_volume_move'
     975              : 
     976              :       CHARACTER(LEN=200)                                 :: fft_lib
     977              :       CHARACTER(LEN=40)                                  :: dat_file
     978              :       INTEGER :: cl, end_atom, end_mol, handle, iatom, idim, imolecule, iside, iside_change, &
     979              :          iunit, jbox, nunits_mol, output_unit, print_level, source, start_atom, start_mol
     980           34 :       INTEGER, DIMENSION(:), POINTER                     :: mol_type, nunits, nunits_tot
     981           34 :       INTEGER, DIMENSION(:, :), POINTER                  :: nchains
     982              :       LOGICAL                                            :: ionode, ldiscrete, lincrease, loverlap, &
     983              :                                                             ltoo_small
     984           34 :       REAL(dp), DIMENSION(:, :), POINTER                 :: mass
     985              :       REAL(KIND=dp) :: BETA, discrete_step, energy_term, exp_max_val, exp_min_val, new_energy, &
     986              :          pressure, pressure_term, rand, rcut, rmvolume, temp_var, value, vol_dis, volume_term, w
     987           34 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: r
     988              :       REAL(KIND=dp), DIMENSION(1:3)                      :: abc, center_of_mass, center_of_mass_new, &
     989              :                                                             diff, new_cell_length, old_cell_length
     990              :       REAL(KIND=dp), DIMENSION(1:3, 1:3)                 :: hmat_test
     991              :       TYPE(cell_type), POINTER                           :: cell, cell_old, cell_test
     992              :       TYPE(cp_logger_type), POINTER                      :: logger
     993              :       TYPE(cp_subsys_type), POINTER                      :: oldsys
     994              :       TYPE(mc_molecule_info_type), POINTER               :: mc_molecule_info
     995              :       TYPE(mp_comm_type)                                 :: group
     996              :       TYPE(particle_list_type), POINTER                  :: particles_old
     997              : 
     998              : ! begin the timing of the subroutine
     999              : 
    1000           34 :       CALL timeset(routineN, handle)
    1001              : 
    1002              : ! get a bunch of stuff from mc_par
    1003              :       CALL get_mc_par(mc_par, ionode=ionode, &
    1004              :                       BETA=BETA, exp_max_val=exp_max_val, &
    1005              :                       exp_min_val=exp_min_val, source=source, group=group, &
    1006              :                       dat_file=dat_file, rmvolume=rmvolume, pressure=pressure, cl=cl, &
    1007              :                       fft_lib=fft_lib, discrete_step=discrete_step, &
    1008           34 :                       ldiscrete=ldiscrete, mc_molecule_info=mc_molecule_info)
    1009              :       CALL get_mc_molecule_info(mc_molecule_info, nchains=nchains, &
    1010              :                                 nunits=nunits, nunits_tot=nunits_tot, mol_type=mol_type, &
    1011           34 :                                 mass=mass)
    1012              : ! figure out some bounds for mol_type
    1013           34 :       start_mol = 1
    1014           46 :       DO jbox = 1, box_number - 1
    1015           70 :          start_mol = start_mol + SUM(nchains(:, jbox))
    1016              :       END DO
    1017           94 :       end_mol = start_mol + SUM(nchains(:, box_number)) - 1
    1018              : 
    1019           34 :       print_level = 1 ! hack, printlevel is for print_keys
    1020              : 
    1021              : ! nullify some pointers
    1022           34 :       NULLIFY (particles_old, cell_old, oldsys, cell_test, cell)
    1023              : 
    1024              : ! do some allocation
    1025          102 :       ALLOCATE (r(1:3, 1:nunits_tot(box_number)))
    1026              : 
    1027              : ! record the attempt
    1028           34 :       moves%volume%attempts = moves%volume%attempts + 1
    1029           34 :       move_updates%volume%attempts = move_updates%volume%attempts + 1
    1030              : 
    1031              : ! now let's grab the cell length and particle positions
    1032           34 :       CALL force_env_get(force_env, subsys=oldsys, cell=cell)
    1033           34 :       CALL get_cell(cell, abc=abc)
    1034           34 :       CALL cell_create(cell_old)
    1035           34 :       CALL cell_clone(cell, cell_old, tag="CELL_OLD")
    1036           34 :       CALL cp_subsys_get(oldsys, particles=particles_old)
    1037              : 
    1038              : ! find the old cell length
    1039           34 :       old_cell_length(1) = abc(1)
    1040           34 :       old_cell_length(2) = abc(2)
    1041           34 :       old_cell_length(3) = abc(3)
    1042              : 
    1043              : ! save the old coordinates
    1044          760 :       DO iatom = 1, nunits_tot(box_number)
    1045         2938 :          r(1:3, iatom) = particles_old%els(iatom)%r(1:3)
    1046              :       END DO
    1047              : 
    1048              : ! now do the move
    1049              : 
    1050              : ! call a random number to figure out how far we're moving
    1051           34 :       IF (ionode) rand = rng_stream%next()
    1052           34 :       CALL group%bcast(rand, source)
    1053              : 
    1054              : ! find the test cell lengths for the discrete volume move
    1055           34 :       IF (ldiscrete) THEN
    1056            0 :          IF (rand < 0.5_dp) THEN
    1057              :             lincrease = .TRUE.
    1058              :          ELSE
    1059            0 :             lincrease = .FALSE.
    1060              :          END IF
    1061              : 
    1062            0 :          new_cell_length(1:3) = old_cell_length(1:3)
    1063              : 
    1064              : ! if we're increasing the volume, we need to find a side we can increase
    1065            0 :          IF (lincrease) THEN
    1066              :             DO
    1067            0 :                IF (ionode) rand = rng_stream%next()
    1068            0 :                CALL group%bcast(rand, source)
    1069            0 :                iside_change = CEILING(3.0_dp*rand)
    1070            0 :                IF (discrete_array(iside_change, 1) == 1) THEN
    1071              :                   new_cell_length(iside_change) = &
    1072            0 :                      new_cell_length(iside_change) + discrete_step
    1073              :                   EXIT
    1074              :                END IF
    1075              :             END DO
    1076              :          ELSE
    1077              :             DO
    1078            0 :                IF (ionode) rand = rng_stream%next()
    1079            0 :                CALL group%bcast(rand, source)
    1080            0 :                iside_change = CEILING(3.0_dp*rand)
    1081            0 :                IF (discrete_array(iside_change, 2) == 1) THEN
    1082              :                   new_cell_length(iside_change) = &
    1083            0 :                      new_cell_length(iside_change) - discrete_step
    1084            0 :                   EXIT
    1085              :                END IF
    1086              :             END DO
    1087              :          END IF
    1088              :          vol_dis = (new_cell_length(1)*new_cell_length(2)*new_cell_length(3)) &
    1089            0 :                    - old_cell_length(1)*old_cell_length(2)*old_cell_length(3)
    1090              :       ELSE
    1091              : ! now for the not discrete volume move
    1092              : !!!!!!!!!!!!!!!! for E_V curves
    1093           34 :          vol_dis = rmvolume*(rand - 0.5E0_dp)*2.0E0_dp
    1094              : !         WRITE(output_unit,*) '************************ be sure to change back!',&
    1095              : !                 old_cell_length(1),14.64_dp/angstrom
    1096              : !         vol_dis=-56.423592_dp/angstrom**3
    1097              : !         IF(old_cell_length(1) <= 14.64_dp/angstrom) THEN
    1098              : !            vol_dis=0.0_dp
    1099              : !            WRITE(output_unit,*) 'Found the correct box length!'
    1100              : !         ENDIF
    1101              : 
    1102              :          temp_var = vol_dis + &
    1103              :                     old_cell_length(1)*old_cell_length(2)* &
    1104           34 :                     old_cell_length(3)
    1105              : 
    1106           34 :          IF (temp_var <= 0.0E0_dp) THEN
    1107            0 :             loverlap = .TRUE. ! cannot have a negative volume
    1108              :          ELSE
    1109           34 :             new_cell_length(1) = (temp_var)**(1.0E0_dp/3.0E0_dp)
    1110           34 :             new_cell_length(2) = new_cell_length(1)
    1111           34 :             new_cell_length(3) = new_cell_length(1)
    1112           34 :             loverlap = .FALSE.
    1113              :          END IF
    1114              :       END IF
    1115           34 :       CALL group%bcast(loverlap, source)
    1116              : 
    1117           34 :       IF (loverlap) THEN
    1118              : ! deallocate some stuff
    1119            0 :          DEALLOCATE (r)
    1120            0 :          logger => cp_get_default_logger()
    1121            0 :          output_unit = cp_logger_get_default_io_unit(logger)
    1122            0 :          IF (output_unit > 0) WRITE (output_unit, *) &
    1123            0 :             "Volume move rejected because we tried to make too small of box.", vol_dis
    1124              : !     end the timing
    1125            0 :          CALL timestop(handle)
    1126            0 :          RETURN
    1127              :       END IF
    1128              : 
    1129              : ! now we need to make the new cell
    1130           34 :       hmat_test(:, :) = 0.0e0_dp
    1131           34 :       hmat_test(1, 1) = new_cell_length(1)
    1132           34 :       hmat_test(2, 2) = new_cell_length(2)
    1133           34 :       hmat_test(3, 3) = new_cell_length(3)
    1134           34 :       CALL cell_create(cell_test, hmat=hmat_test(:, :), periodic=cell%perd)
    1135           34 :       CALL cp_subsys_set(oldsys, cell=cell_test)
    1136              : 
    1137              : ! now we need to scale the coordinates of all the molecules by the
    1138              : ! center of mass, using the minimum image (not all molecules are in
    1139              : ! the central box)
    1140              : 
    1141              : ! now we need to scale the coordinates of all the molecules by the
    1142              : ! center of mass
    1143           34 :       end_atom = 0
    1144          432 :       DO imolecule = 1, SUM(nchains(:, box_number))
    1145          338 :          nunits_mol = nunits(mol_type(imolecule + start_mol - 1))
    1146          338 :          start_atom = end_atom + 1
    1147          338 :          end_atom = start_atom + nunits_mol - 1
    1148              : ! now find the center of mass
    1149              :          CALL get_center_of_mass(r(:, start_atom:end_atom), nunits_mol, &
    1150          338 :                                  center_of_mass(:), mass(:, mol_type(imolecule + start_mol - 1)))
    1151              : 
    1152              : ! scale the center of mass and determine the vector that points from the
    1153              : !    old COM to the new one
    1154         1352 :          DO iside = 1, 3
    1155              :             center_of_mass_new(iside) = center_of_mass(iside)* &
    1156         1352 :                                         new_cell_length(iside)/old_cell_length(iside)
    1157              :          END DO
    1158              : 
    1159         1386 :          DO idim = 1, 3
    1160         1014 :             diff(idim) = center_of_mass_new(idim) - center_of_mass(idim)
    1161              : ! now change the particle positions
    1162         3530 :             DO iunit = start_atom, end_atom
    1163              :                particles_old%els(iunit)%r(idim) = &
    1164         3192 :                   particles_old%els(iunit)%r(idim) + diff(idim)
    1165              :             END DO
    1166              :          END DO
    1167              :       END DO
    1168              : 
    1169              : ! check for overlap
    1170              :       CALL check_for_overlap(force_env, nchains(:, box_number), &
    1171              :                              nunits(:), loverlap, mol_type(start_mol:end_mol), &
    1172           34 :                              cell_length=new_cell_length)
    1173              : 
    1174              : ! figure out if we have overlap problems
    1175           34 :       CALL group%bcast(loverlap, source)
    1176           34 :       IF (loverlap) THEN
    1177              : ! deallocate some stuff
    1178            0 :          DEALLOCATE (r)
    1179              : 
    1180            0 :          logger => cp_get_default_logger()
    1181            0 :          output_unit = cp_logger_get_default_io_unit(logger)
    1182            0 :          IF (output_unit > 0) WRITE (output_unit, *) &
    1183            0 :             "Volume move rejected due to overlap.", vol_dis
    1184              : !     end the timing
    1185            0 :          CALL timestop(handle)
    1186              : ! reset the cell and particle positions
    1187            0 :          CALL cp_subsys_set(oldsys, cell=cell_old)
    1188            0 :          DO iatom = 1, nunits_tot(box_number)
    1189            0 :             particles_old%els(iatom)%r(1:3) = r_old(1:3, iatom)
    1190              :          END DO
    1191              :          RETURN
    1192              :       END IF
    1193              : 
    1194              : ! stop if we're trying to change a box to a boxlength smaller than rcut
    1195           34 :       IF (ionode) THEN
    1196           17 :          ltoo_small = .FALSE.
    1197           17 :          IF (force_env%in_use == use_fist_force) THEN
    1198           13 :             CALL get_mc_par(mc_par, rcut=rcut)
    1199           13 :             IF (new_cell_length(1) < 2.0_dp*rcut) ltoo_small = .TRUE.
    1200           13 :             IF (new_cell_length(2) < 2.0_dp*rcut) ltoo_small = .TRUE.
    1201           13 :             IF (new_cell_length(3) < 2.0_dp*rcut) ltoo_small = .TRUE.
    1202              : 
    1203           13 :             IF (ltoo_small) THEN
    1204            0 :                WRITE (iw, *) 'new_cell_lengths ', &
    1205            0 :                   new_cell_length(1:3)/angstrom
    1206            0 :                WRITE (iw, *) 'rcut ', rcut/angstrom
    1207              :             END IF
    1208              :          END IF
    1209              :       END IF
    1210           34 :       CALL group%bcast(ltoo_small, source)
    1211           34 :       IF (ltoo_small) THEN
    1212            0 :          CPABORT("Attempted a volume move where box size got too small.")
    1213              :       END IF
    1214              : 
    1215              : ! now compute the energy
    1216           34 :       CALL force_env_calc_energy_force(force_env, calc_force=.FALSE.)
    1217              :       CALL force_env_get(force_env, &
    1218           34 :                          potential_energy=new_energy)
    1219              : 
    1220              : ! accept or reject the move
    1221              : ! to prevent overflows
    1222           34 :       energy_term = new_energy - old_energy
    1223              :       volume_term = -REAL(SUM(nchains(:, box_number)), dp)/BETA* &
    1224              :                     LOG(new_cell_length(1)*new_cell_length(2)*new_cell_length(3)/ &
    1225           94 :                         (old_cell_length(1)*old_cell_length(2)*old_cell_length(3)))
    1226           34 :       pressure_term = pressure*vol_dis
    1227              : 
    1228           34 :       value = -BETA*(energy_term + volume_term + pressure_term)
    1229           34 :       IF (value > exp_max_val) THEN
    1230              :          w = 10.0_dp
    1231           34 :       ELSE IF (value < exp_min_val) THEN
    1232              :          w = 0.0_dp
    1233              :       ELSE
    1234           34 :          w = EXP(value)
    1235              :       END IF
    1236              : 
    1237              : !!!!!!!!!!!!!!!! for E_V curves
    1238              : !         w=1.0E0_dp
    1239              : !         w=0.0E0_dp
    1240              : 
    1241           34 :       IF (w >= 1.0E0_dp) THEN
    1242           18 :          w = 1.0E0_dp
    1243           18 :          rand = 0.0E0_dp
    1244              :       ELSE
    1245           16 :          IF (ionode) rand = rng_stream%next()
    1246           16 :          CALL group%bcast(rand, source)
    1247              :       END IF
    1248              : 
    1249           34 :       IF (rand < w) THEN
    1250              : 
    1251              : ! accept the move
    1252           30 :          moves%volume%successes = moves%volume%successes + 1
    1253           30 :          move_updates%volume%successes = move_updates%volume%successes + 1
    1254              : 
    1255              : ! update energies
    1256           30 :          energy_check = energy_check + (new_energy - old_energy)
    1257           30 :          old_energy = new_energy
    1258              : 
    1259          720 :          DO iatom = 1, nunits_tot(box_number)
    1260         2790 :             r_old(1:3, iatom) = particles_old%els(iatom)%r(1:3)
    1261              :          END DO
    1262              : 
    1263              : ! update discrete_array if we're doing a discrete volume move
    1264           30 :          IF (ldiscrete) THEN
    1265              :             CALL create_discrete_array(new_cell_length(:), &
    1266            0 :                                        discrete_array(:, :), discrete_step)
    1267              :          END IF
    1268              : 
    1269              :       ELSE
    1270              : 
    1271              : ! reset the cell and particle positions
    1272            4 :          CALL cp_subsys_set(oldsys, cell=cell_old)
    1273           40 :          DO iatom = 1, nunits_tot(box_number)
    1274          148 :             particles_old%els(iatom)%r(1:3) = r_old(1:3, iatom)
    1275              :          END DO
    1276              : 
    1277              :       END IF
    1278              : 
    1279              : ! deallocate some stuff
    1280           34 :       DEALLOCATE (r)
    1281           34 :       CALL cell_release(cell_test)
    1282           34 :       CALL cell_release(cell_old)
    1283              : 
    1284              : ! end the timing
    1285           34 :       CALL timestop(handle)
    1286              : 
    1287           68 :    END SUBROUTINE mc_volume_move
    1288              : 
    1289              : ! **************************************************************************************************
    1290              : !> \brief alters the length of a random bond for the given molecule, using
    1291              : !>      a mass weighted scheme so the lightest atoms move the most
    1292              : !> \param r_old the initial coordinates of all molecules in the system
    1293              : !> \param r_new the new coordinates of all molecules in the system
    1294              : !> \param mc_par the mc parameters for the force env
    1295              : !> \param molecule_type the molecule type that we're moving
    1296              : !> \param molecule_kind the structure containing the molecule information
    1297              : !> \param dis_length the ratio of the new bond length to the old bond length,
    1298              : !>                    used in the acceptance rule
    1299              : !> \param particles the particle_list_type for all particles in the force_env..
    1300              : !>             used to grab the mass of each atom
    1301              : !> \param rng_stream the random number stream that we draw from
    1302              : !>
    1303              : !>    This subroutine is written to be parallel.
    1304              : !> \author MJM
    1305              : ! **************************************************************************************************
    1306          312 :    SUBROUTINE change_bond_length(r_old, r_new, mc_par, molecule_type, molecule_kind, &
    1307              :                                  dis_length, particles, rng_stream)
    1308              : 
    1309              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: r_old
    1310              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT)        :: r_new
    1311              :       TYPE(mc_simpar_type), POINTER                      :: mc_par
    1312              :       INTEGER, INTENT(IN)                                :: molecule_type
    1313              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind
    1314              :       REAL(KIND=dp), INTENT(OUT)                         :: dis_length
    1315              :       TYPE(particle_list_type), POINTER                  :: particles
    1316              :       TYPE(rng_stream_type), INTENT(INOUT)               :: rng_stream
    1317              : 
    1318              :       CHARACTER(len=*), PARAMETER :: routineN = 'change_bond_length'
    1319              : 
    1320              :       INTEGER                                            :: bond_number, handle, i, iatom, ibond, &
    1321              :                                                             ipart, natom, nbond, source
    1322          312 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_a, atom_b, counter
    1323          312 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: connection, connectivity
    1324          312 :       INTEGER, DIMENSION(:), POINTER                     :: nunits
    1325              :       LOGICAL                                            :: ionode
    1326          312 :       REAL(dp), DIMENSION(:), POINTER                    :: rmbond
    1327              :       REAL(KIND=dp)                                      :: atom_mass, mass_a, mass_b, new_length_a, &
    1328              :                                                             new_length_b, old_length, rand
    1329              :       REAL(KIND=dp), DIMENSION(1:3)                      :: bond_a, bond_b
    1330          312 :       TYPE(bond_type), DIMENSION(:), POINTER             :: bond_list
    1331              :       TYPE(mc_molecule_info_type), POINTER               :: mc_molecule_info
    1332              :       TYPE(mp_comm_type)                                 :: group
    1333              : 
    1334              : ! begin the timing of the subroutine
    1335              : 
    1336          312 :       CALL timeset(routineN, handle)
    1337              : 
    1338          312 :       NULLIFY (rmbond, mc_molecule_info)
    1339              : 
    1340              : ! get some stuff from mc_par
    1341              :       CALL get_mc_par(mc_par, mc_molecule_info=mc_molecule_info, source=source, &
    1342          312 :                       group=group, rmbond=rmbond, ionode=ionode)
    1343          312 :       CALL get_mc_molecule_info(mc_molecule_info, nunits=nunits)
    1344              : 
    1345              : ! copy the incoming coordinates so we can change them
    1346         1248 :       DO ipart = 1, nunits(molecule_type)
    1347         4056 :          r_new(1:3, ipart) = r_old(1:3, ipart)
    1348              :       END DO
    1349              : 
    1350              : ! pick which bond in the molecule at random
    1351          312 :       IF (ionode) THEN
    1352          156 :          rand = rng_stream%next()
    1353              :       END IF
    1354          312 :       CALL group%bcast(rand, source)
    1355              :       CALL get_molecule_kind(molecule_kind, natom=natom, nbond=nbond, &
    1356          312 :                              bond_list=bond_list)
    1357          312 :       bond_number = CEILING(rand*REAL(nbond, dp))
    1358              : 
    1359          936 :       ALLOCATE (connection(1:natom, 1:2))
    1360              : ! assume at most six bonds per atom
    1361          936 :       ALLOCATE (connectivity(1:6, 1:natom))
    1362          936 :       ALLOCATE (counter(1:natom))
    1363          624 :       ALLOCATE (atom_a(1:natom))
    1364          624 :       ALLOCATE (atom_b(1:natom))
    1365          312 :       connection(:, :) = 0
    1366          312 :       connectivity(:, :) = 0
    1367          312 :       counter(:) = 0
    1368          312 :       atom_a(:) = 0
    1369          312 :       atom_b(:) = 0
    1370              : 
    1371              : ! now we need to find a list of atoms that each atom in this bond is connected
    1372              : ! to
    1373         1248 :       DO iatom = 1, natom
    1374         3120 :          DO ibond = 1, nbond
    1375         2808 :             IF (bond_list(ibond)%a == iatom) THEN
    1376          624 :                counter(iatom) = counter(iatom) + 1
    1377          624 :                connectivity(counter(iatom), iatom) = bond_list(ibond)%b
    1378         1248 :             ELSE IF (bond_list(ibond)%b == iatom) THEN
    1379          624 :                counter(iatom) = counter(iatom) + 1
    1380          624 :                connectivity(counter(iatom), iatom) = bond_list(ibond)%a
    1381              :             END IF
    1382              :          END DO
    1383              :       END DO
    1384              : 
    1385              : ! now I need to do a depth first search to figure out which atoms are on atom a's
    1386              : ! side and which are on atom b's
    1387          312 :       atom_a(:) = 0
    1388          312 :       atom_a(bond_list(bond_number)%a) = 1
    1389              :       CALL depth_first_search(bond_list(bond_number)%a, bond_list(bond_number)%b, &
    1390          312 :                               connectivity(:, :), atom_a(:))
    1391          312 :       atom_b(:) = 0
    1392          312 :       atom_b(bond_list(bond_number)%b) = 1
    1393              :       CALL depth_first_search(bond_list(bond_number)%b, bond_list(bond_number)%a, &
    1394          312 :                               connectivity(:, :), atom_b(:))
    1395              : 
    1396              : ! now figure out the masses of the various sides, so we can weight how far we move each
    1397              : ! group of atoms
    1398          312 :       mass_a = 0.0_dp
    1399          312 :       mass_b = 0.0_dp
    1400         1248 :       DO iatom = 1, natom
    1401              :          CALL get_atomic_kind(particles%els(iatom)%atomic_kind, &
    1402          936 :                               mass=atom_mass)
    1403         1248 :          IF (atom_a(iatom) == 1) THEN
    1404          624 :             mass_a = mass_a + atom_mass
    1405              :          ELSE
    1406          312 :             mass_b = mass_b + atom_mass
    1407              :          END IF
    1408              :       END DO
    1409              : 
    1410              : ! choose a displacement
    1411          312 :       IF (ionode) rand = rng_stream%next()
    1412          312 :       CALL group%bcast(rand, source)
    1413              : 
    1414          312 :       dis_length = rmbond(molecule_type)*2.0E0_dp*(rand - 0.5E0_dp)
    1415              : 
    1416              : ! find the bond vector that atom a will be moving
    1417         1248 :       DO i = 1, 3
    1418              :          bond_a(i) = r_new(i, bond_list(bond_number)%a) - &
    1419          936 :                      r_new(i, bond_list(bond_number)%b)
    1420         1248 :          bond_b(i) = -bond_a(i)
    1421              :       END DO
    1422              : 
    1423              : ! notice we weight by the opposite masses...therefore lighter segments
    1424              : ! will move further
    1425         1248 :       old_length = NORM2(bond_a)
    1426          312 :       new_length_a = dis_length*mass_b/(mass_a + mass_b)
    1427          312 :       new_length_b = dis_length*mass_a/(mass_a + mass_b)
    1428              : 
    1429         1248 :       DO i = 1, 3
    1430          936 :          bond_a(i) = bond_a(i)/old_length*new_length_a
    1431         1248 :          bond_b(i) = bond_b(i)/old_length*new_length_b
    1432              :       END DO
    1433              : 
    1434         1248 :       DO iatom = 1, natom
    1435         1248 :          IF (atom_a(iatom) == 1) THEN
    1436          624 :             r_new(1, iatom) = r_new(1, iatom) + bond_a(1)
    1437          624 :             r_new(2, iatom) = r_new(2, iatom) + bond_a(2)
    1438          624 :             r_new(3, iatom) = r_new(3, iatom) + bond_a(3)
    1439              :          ELSE
    1440          312 :             r_new(1, iatom) = r_new(1, iatom) + bond_b(1)
    1441          312 :             r_new(2, iatom) = r_new(2, iatom) + bond_b(2)
    1442          312 :             r_new(3, iatom) = r_new(3, iatom) + bond_b(3)
    1443              :          END IF
    1444              :       END DO
    1445              : 
    1446              : ! correct the value of dis_length for the acceptance rule
    1447          312 :       dis_length = (old_length + dis_length)/old_length
    1448              : 
    1449          312 :       DEALLOCATE (connection)
    1450          312 :       DEALLOCATE (connectivity)
    1451          312 :       DEALLOCATE (counter)
    1452          312 :       DEALLOCATE (atom_a)
    1453          312 :       DEALLOCATE (atom_b)
    1454              : ! end the timing
    1455          312 :       CALL timestop(handle)
    1456              : 
    1457          624 :    END SUBROUTINE change_bond_length
    1458              : 
    1459              : ! **************************************************************************************************
    1460              : !> \brief Alters the magnitude of a random angle in a molecule centered on atom C
    1461              : !>      (connected to atoms A and B).  Atoms A and B are moved amounts related
    1462              : !>      to their masses (and masses of all connecting atoms), so that heavier
    1463              : !>      segments are moved less.
    1464              : !> \param r_old the initial coordinates of all molecules in the system
    1465              : !> \param r_new the new coordinates of all molecules in the system
    1466              : !> \param mc_par the mc parameters for the force env
    1467              : !> \param molecule_type the type of molecule we're playing with
    1468              : !> \param molecule_kind the structure containing the molecule information
    1469              : !> \param particles the particle_list_type for all particles in the force_env...
    1470              : !>             used to grab the mass of each atom
    1471              : !> \param rng_stream the random number stream that we draw from
    1472              : !> \author MJM
    1473              : ! **************************************************************************************************
    1474          194 :    SUBROUTINE change_bond_angle(r_old, r_new, mc_par, molecule_type, molecule_kind, &
    1475              :                                 particles, rng_stream)
    1476              : 
    1477              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: r_old
    1478              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT)        :: r_new
    1479              :       TYPE(mc_simpar_type), POINTER                      :: mc_par
    1480              :       INTEGER, INTENT(IN)                                :: molecule_type
    1481              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind
    1482              :       TYPE(particle_list_type), POINTER                  :: particles
    1483              :       TYPE(rng_stream_type), INTENT(INOUT)               :: rng_stream
    1484              : 
    1485              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'change_bond_angle'
    1486              : 
    1487              :       INTEGER                                            :: bend_number, handle, i, iatom, ibond, &
    1488              :                                                             ipart, natom, nbend, nbond, source
    1489          194 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_a, atom_c, counter
    1490          194 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: connection, connectivity
    1491          194 :       INTEGER, DIMENSION(:), POINTER                     :: nunits
    1492              :       LOGICAL                                            :: ionode
    1493          194 :       REAL(dp), DIMENSION(:), POINTER                    :: rmangle
    1494              :       REAL(KIND=dp) :: atom_mass, bis_length, dis_angle, dis_angle_a, dis_angle_c, mass_a, mass_c, &
    1495              :          new_angle_a, new_angle_c, old_angle, old_length_a, old_length_c, rand, temp_length
    1496              :       REAL(KIND=dp), DIMENSION(1:3)                      :: bisector, bond_a, bond_c, cross_prod, &
    1497              :                                                             cross_prod_plane, temp
    1498          194 :       TYPE(bend_type), DIMENSION(:), POINTER             :: bend_list
    1499          194 :       TYPE(bond_type), DIMENSION(:), POINTER             :: bond_list
    1500              :       TYPE(mc_molecule_info_type), POINTER               :: mc_molecule_info
    1501              :       TYPE(mp_comm_type)                                 :: group
    1502              : 
    1503              : ! begin the timing of the subroutine
    1504              : 
    1505          194 :       CALL timeset(routineN, handle)
    1506              : 
    1507          194 :       NULLIFY (bend_list, bond_list, rmangle, mc_molecule_info)
    1508              : 
    1509              : ! get some stuff from mc_par
    1510              :       CALL get_mc_par(mc_par, rmangle=rmangle, source=source, &
    1511          194 :                       group=group, ionode=ionode, mc_molecule_info=mc_molecule_info)
    1512          194 :       CALL get_mc_molecule_info(mc_molecule_info, nunits=nunits)
    1513              : 
    1514              : ! copy the incoming coordinates so we can change them
    1515          776 :       DO ipart = 1, nunits(molecule_type)
    1516         2522 :          r_new(1:3, ipart) = r_old(1:3, ipart)
    1517              :       END DO
    1518              : 
    1519              : ! pick which bond in the molecule at random
    1520          194 :       IF (ionode) THEN
    1521           97 :          rand = rng_stream%next()
    1522              :       END IF
    1523          194 :       CALL group%bcast(rand, source)
    1524              :       CALL get_molecule_kind(molecule_kind, natom=natom, nbend=nbend, &
    1525          194 :                              bend_list=bend_list, bond_list=bond_list, nbond=nbond)
    1526          194 :       bend_number = CEILING(rand*REAL(nbend, dp))
    1527              : 
    1528          582 :       ALLOCATE (connection(1:natom, 1:2))
    1529              : ! assume at most six bonds per atom
    1530          582 :       ALLOCATE (connectivity(1:6, 1:natom))
    1531          582 :       ALLOCATE (counter(1:natom))
    1532          388 :       ALLOCATE (atom_a(1:natom))
    1533          388 :       ALLOCATE (atom_c(1:natom))
    1534          194 :       connection(:, :) = 0
    1535          194 :       connectivity(:, :) = 0
    1536          194 :       counter(:) = 0
    1537          194 :       atom_a(:) = 0
    1538          194 :       atom_c(:) = 0
    1539              : 
    1540              : ! now we need to find a list of atoms that each atom in this bond is connected
    1541              : ! to
    1542          776 :       DO iatom = 1, natom
    1543         1940 :          DO ibond = 1, nbond
    1544         1746 :             IF (bond_list(ibond)%a == iatom) THEN
    1545          388 :                counter(iatom) = counter(iatom) + 1
    1546          388 :                connectivity(counter(iatom), iatom) = bond_list(ibond)%b
    1547          776 :             ELSE IF (bond_list(ibond)%b == iatom) THEN
    1548          388 :                counter(iatom) = counter(iatom) + 1
    1549          388 :                connectivity(counter(iatom), iatom) = bond_list(ibond)%a
    1550              :             END IF
    1551              :          END DO
    1552              :       END DO
    1553              : 
    1554              : ! now I need to do a depth first search to figure out which atoms are on atom a's
    1555              : ! side and which are on atom c's
    1556          194 :       atom_a(:) = 0
    1557          194 :       atom_a(bend_list(bend_number)%a) = 1
    1558              :       CALL depth_first_search(bend_list(bend_number)%a, bend_list(bend_number)%b, &
    1559          194 :                               connectivity(:, :), atom_a(:))
    1560          194 :       atom_c(:) = 0
    1561          194 :       atom_c(bend_list(bend_number)%c) = 1
    1562              :       CALL depth_first_search(bend_list(bend_number)%c, bend_list(bend_number)%b, &
    1563          194 :                               connectivity(:, :), atom_c(:))
    1564              : 
    1565              : ! now figure out the masses of the various sides, so we can weight how far we move each
    1566              : ! group of atoms
    1567          194 :       mass_a = 0.0_dp
    1568          194 :       mass_c = 0.0_dp
    1569          776 :       DO iatom = 1, natom
    1570              :          CALL get_atomic_kind(particles%els(iatom)%atomic_kind, &
    1571          582 :                               mass=atom_mass)
    1572          582 :          IF (atom_a(iatom) == 1) mass_a = mass_a + atom_mass
    1573         1358 :          IF (atom_c(iatom) == 1) mass_c = mass_c + atom_mass
    1574              :       END DO
    1575              : 
    1576              : ! choose a displacement
    1577          194 :       IF (ionode) rand = rng_stream%next()
    1578          194 :       CALL group%bcast(rand, source)
    1579              : 
    1580          194 :       dis_angle = rmangle(molecule_type)*2.0E0_dp*(rand - 0.5E0_dp)
    1581              : 
    1582              : ! need to find the A-B-C bisector
    1583              : 
    1584              : ! this going to be tough...we need to find the plane of the A-B-C bond and only shift
    1585              : ! that component for all atoms connected to A and C...otherwise we change other
    1586              : ! internal degrees of freedom
    1587              : 
    1588              : ! find the bond vectors
    1589          776 :       DO i = 1, 3
    1590              :          bond_a(i) = r_new(i, bend_list(bend_number)%a) - &
    1591          582 :                      r_new(i, bend_list(bend_number)%b)
    1592              :          bond_c(i) = r_new(i, bend_list(bend_number)%c) - &
    1593          776 :                      r_new(i, bend_list(bend_number)%b)
    1594              :       END DO
    1595          776 :       old_length_a = NORM2(bond_a)
    1596          776 :       old_length_c = NORM2(bond_c)
    1597          776 :       old_angle = ACOS(DOT_PRODUCT(bond_a, bond_c)/(old_length_a*old_length_c))
    1598              : 
    1599          776 :       DO i = 1, 3
    1600              :          bisector(i) = bond_a(i)/old_length_a + & ! not yet normalized
    1601          776 :                        bond_c(i)/old_length_c
    1602              :       END DO
    1603          776 :       bis_length = NORM2(bisector)
    1604          776 :       bisector(1:3) = bisector(1:3)/bis_length
    1605              : 
    1606              : ! now we need to find the cross product of the B-A and B-C vectors and normalize
    1607              : ! it, so we have a vector that defines the bend plane
    1608          194 :       cross_prod(1) = bond_a(2)*bond_c(3) - bond_a(3)*bond_c(2)
    1609          194 :       cross_prod(2) = bond_a(3)*bond_c(1) - bond_a(1)*bond_c(3)
    1610          194 :       cross_prod(3) = bond_a(1)*bond_c(2) - bond_a(2)*bond_c(1)
    1611         1358 :       cross_prod(1:3) = cross_prod(1:3)/NORM2(cross_prod)
    1612              : 
    1613              : ! we have two axis of a coordinate system...let's get the third
    1614          194 :       cross_prod_plane(1) = cross_prod(2)*bisector(3) - cross_prod(3)*bisector(2)
    1615          194 :       cross_prod_plane(2) = cross_prod(3)*bisector(1) - cross_prod(1)*bisector(3)
    1616          194 :       cross_prod_plane(3) = cross_prod(1)*bisector(2) - cross_prod(2)*bisector(1)
    1617              :       cross_prod_plane(1:3) = cross_prod_plane(1:3)/ &
    1618         1358 :                               NORM2(cross_prod_plane)
    1619              : 
    1620              : ! now bisector is x, cross_prod_plane is the y vector (pointing towards c),
    1621              : ! and cross_prod is z
    1622              : ! shift the molecule so that atom b is at the origin
    1623          776 :       DO iatom = 1, natom
    1624              :          r_new(1:3, iatom) = r_new(1:3, iatom) - &
    1625         2522 :                              r_old(1:3, bend_list(bend_number)%b)
    1626              :       END DO
    1627              : 
    1628              : ! figure out how much we move each side, since we're mass-weighting, by the
    1629              : ! opposite masses, so lighter moves farther..this angle is the angle between
    1630              : ! the bond vector BA or BC and the bisector
    1631          194 :       dis_angle_a = dis_angle*mass_c/(mass_a + mass_c)
    1632          194 :       dis_angle_c = dis_angle*mass_a/(mass_a + mass_c)
    1633              : 
    1634              : ! now loop through all the atoms, moving the ones that are connected to a or c
    1635          776 :       DO iatom = 1, natom
    1636              : ! subtract out the z component (perpendicular to the angle plane)
    1637              :          temp(1:3) = r_new(1:3, iatom) - &
    1638              :                      DOT_PRODUCT(cross_prod(1:3), r_new(1:3, iatom))* &
    1639         4074 :                      cross_prod(1:3)
    1640         2328 :          temp_length = NORM2(temp)
    1641              : 
    1642              : ! we can now compute all three components of the new bond vector along the
    1643              : ! axis defined above
    1644          776 :          IF (atom_a(iatom) == 1) THEN
    1645              : 
    1646              : ! if the y-coordinate is less than zero, we need to switch the sign when we make the vector,
    1647              : ! as the angle computed by the dot product can't distinguish between that
    1648          776 :             IF (DOT_PRODUCT(cross_prod_plane(1:3), r_new(1:3, iatom)) &
    1649              :                 < 0.0_dp) THEN
    1650              : 
    1651              : ! need to figure out the current iatom-B-bisector angle, so we know what the new angle is
    1652              :                new_angle_a = ACOS(DOT_PRODUCT(bisector, temp(1:3))/ &
    1653          776 :                                   (temp_length)) + dis_angle_a
    1654              : 
    1655              :                r_new(1:3, iatom) = COS(new_angle_a)*temp_length*bisector(1:3) - &
    1656              :                                    SIN(new_angle_a)*temp_length*cross_prod_plane(1:3) + &
    1657              :                                    DOT_PRODUCT(cross_prod(1:3), r_new(1:3, iatom))* &
    1658         1358 :                                    cross_prod(1:3)
    1659              :             ELSE
    1660              : 
    1661              : ! need to figure out the current iatom-B-bisector angle, so we know what the new angle is
    1662              :                new_angle_a = ACOS(DOT_PRODUCT(bisector, temp(1:3))/ &
    1663            0 :                                   (temp_length)) - dis_angle_a
    1664              : 
    1665              :                r_new(1:3, iatom) = COS(new_angle_a)*temp_length*bisector(1:3) + &
    1666              :                                    SIN(new_angle_a)*temp_length*cross_prod_plane(1:3) + &
    1667              :                                    DOT_PRODUCT(cross_prod(1:3), r_new(1:3, iatom))* &
    1668            0 :                                    cross_prod(1:3)
    1669              :             END IF
    1670              : 
    1671          388 :          ELSE IF (atom_c(iatom) == 1) THEN
    1672              : 
    1673              : ! if the y-coordinate is less than zero, we need to switch the sign when we make the vector,
    1674              : ! as the angle computed by the dot product can't distinguish between that
    1675          776 :             IF (DOT_PRODUCT(cross_prod_plane(1:3), r_new(1:3, iatom)) &
    1676              :                 < 0.0_dp) THEN
    1677              : ! need to figure out the current iatom-B-bisector angle, so we know what the new angle is
    1678              :                new_angle_c = ACOS(DOT_PRODUCT(bisector(1:3), temp(1:3))/ &
    1679            0 :                                   (temp_length)) - dis_angle_c
    1680              : 
    1681              :                r_new(1:3, iatom) = COS(new_angle_c)*temp_length*bisector(1:3) - &
    1682              :                                    SIN(new_angle_c)*temp_length*cross_prod_plane(1:3) + &
    1683              :                                    DOT_PRODUCT(cross_prod(1:3), r_new(1:3, iatom))* &
    1684            0 :                                    cross_prod(1:3)
    1685              :             ELSE
    1686              :                new_angle_c = ACOS(DOT_PRODUCT(bisector(1:3), temp(1:3))/ &
    1687          776 :                                   (temp_length)) + dis_angle_c
    1688              : 
    1689              :                r_new(1:3, iatom) = COS(new_angle_c)*temp_length*bisector(1:3) + &
    1690              :                                    SIN(new_angle_c)*temp_length*cross_prod_plane(1:3) + &
    1691              :                                    DOT_PRODUCT(cross_prod(1:3), r_new(1:3, iatom))* &
    1692         1358 :                                    cross_prod(1:3)
    1693              :             END IF
    1694              :          END IF
    1695              : 
    1696              :       END DO
    1697              : 
    1698          776 :       DO iatom = 1, natom
    1699              :          r_new(1:3, iatom) = r_new(1:3, iatom) + &
    1700         2522 :                              r_old(1:3, bend_list(bend_number)%b)
    1701              :       END DO
    1702              : 
    1703              : ! deallocate some stuff
    1704          194 :       DEALLOCATE (connection)
    1705          194 :       DEALLOCATE (connectivity)
    1706          194 :       DEALLOCATE (counter)
    1707          194 :       DEALLOCATE (atom_a)
    1708          194 :       DEALLOCATE (atom_c)
    1709              : 
    1710              : ! end the timing
    1711          194 :       CALL timestop(handle)
    1712              : 
    1713          388 :    END SUBROUTINE change_bond_angle
    1714              : 
    1715              : ! **************************************************************************************************
    1716              : !> \brief Alters a dihedral (A-B-C-D) in the molecule so that all other internal
    1717              : !>      degrees of freedom remain the same.  If other dihedrals are centered
    1718              : !>      on B-C, they rotate as well to keep the relationship between the
    1719              : !>      dihedrals the same.  Atoms A and D are moved amounts related to their
    1720              : !>      masses (and masses of all connecting atoms), so that heavier segments
    1721              : !>      are moved less.  All atoms except B and C are rotated around the
    1722              : !>      B-C bond vector (B and C are not moved).
    1723              : !> \param r_old the initial coordinates of all molecules in the system
    1724              : !> \param r_new the new coordinates of all molecules in the system
    1725              : !> \param mc_par the mc parameters for the force env
    1726              : !> \param molecule_type the type of molecule we're playing with
    1727              : !> \param molecule_kind the structure containing the molecule information
    1728              : !> \param particles the particle_list_type for all particles in the force_env..
    1729              : !>             used to grab the mass of each atom
    1730              : !> \param rng_stream the random number stream that we draw from
    1731              : !> \author MJM
    1732              : ! **************************************************************************************************
    1733            0 :    SUBROUTINE change_dihedral(r_old, r_new, mc_par, molecule_type, molecule_kind, &
    1734              :                               particles, rng_stream)
    1735              : 
    1736              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: r_old
    1737              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT)        :: r_new
    1738              :       TYPE(mc_simpar_type), POINTER                      :: mc_par
    1739              :       INTEGER, INTENT(IN)                                :: molecule_type
    1740              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind
    1741              :       TYPE(particle_list_type), POINTER                  :: particles
    1742              :       TYPE(rng_stream_type), INTENT(INOUT)               :: rng_stream
    1743              : 
    1744              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'change_dihedral'
    1745              : 
    1746              :       INTEGER                                            :: handle, i, iatom, ibond, ipart, natom, &
    1747              :                                                             nbond, ntorsion, source, torsion_number
    1748            0 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_a, atom_d, counter
    1749            0 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: connection, connectivity
    1750            0 :       INTEGER, DIMENSION(:), POINTER                     :: nunits
    1751              :       LOGICAL                                            :: ionode
    1752            0 :       REAL(dp), DIMENSION(:), POINTER                    :: rmdihedral
    1753              :       REAL(KIND=dp)                                      :: atom_mass, dis_angle, dis_angle_a, &
    1754              :                                                             dis_angle_d, mass_a, mass_d, &
    1755              :                                                             old_length_a, rand, u, v, w, x, y, z
    1756              :       REAL(KIND=dp), DIMENSION(1:3)                      :: bond_a, temp
    1757            0 :       TYPE(bond_type), DIMENSION(:), POINTER             :: bond_list
    1758              :       TYPE(mc_molecule_info_type), POINTER               :: mc_molecule_info
    1759              :       TYPE(mp_comm_type)                                 :: group
    1760            0 :       TYPE(torsion_type), DIMENSION(:), POINTER          :: torsion_list
    1761              : 
    1762              : ! begin the timing of the subroutine
    1763              : 
    1764            0 :       CALL timeset(routineN, handle)
    1765              : 
    1766            0 :       NULLIFY (rmdihedral, torsion_list, bond_list, mc_molecule_info)
    1767              : 
    1768              : ! get some stuff from mc_par
    1769              :       CALL get_mc_par(mc_par, rmdihedral=rmdihedral, &
    1770              :                       source=source, group=group, ionode=ionode, &
    1771            0 :                       mc_molecule_info=mc_molecule_info)
    1772            0 :       CALL get_mc_molecule_info(mc_molecule_info, nunits=nunits)
    1773              : 
    1774              : ! copy the incoming coordinates so we can change them
    1775            0 :       DO ipart = 1, nunits(molecule_type)
    1776            0 :          r_new(1:3, ipart) = r_old(1:3, ipart)
    1777              :       END DO
    1778              : 
    1779              : ! pick which bond in the molecule at random
    1780            0 :       IF (ionode) THEN
    1781            0 :          rand = rng_stream%next()
    1782              : !      CALL RANDOM_NUMBER(rand)
    1783              :       END IF
    1784            0 :       CALL group%bcast(rand, source)
    1785              :       CALL get_molecule_kind(molecule_kind, natom=natom, &
    1786              :                              bond_list=bond_list, nbond=nbond, &
    1787            0 :                              ntorsion=ntorsion, torsion_list=torsion_list)
    1788            0 :       torsion_number = CEILING(rand*REAL(ntorsion, dp))
    1789              : 
    1790            0 :       ALLOCATE (connection(1:natom, 1:2))
    1791              : ! assume at most six bonds per atom
    1792            0 :       ALLOCATE (connectivity(1:6, 1:natom))
    1793            0 :       ALLOCATE (counter(1:natom))
    1794            0 :       ALLOCATE (atom_a(1:natom))
    1795            0 :       ALLOCATE (atom_d(1:natom))
    1796            0 :       connection(:, :) = 0
    1797            0 :       connectivity(:, :) = 0
    1798            0 :       counter(:) = 0
    1799            0 :       atom_a(:) = 0
    1800            0 :       atom_d(:) = 0
    1801              : 
    1802              : ! now we need to find a list of atoms that each atom in this bond is connected
    1803              : ! to
    1804            0 :       DO iatom = 1, natom
    1805            0 :          DO ibond = 1, nbond
    1806            0 :             IF (bond_list(ibond)%a == iatom) THEN
    1807            0 :                counter(iatom) = counter(iatom) + 1
    1808            0 :                connectivity(counter(iatom), iatom) = bond_list(ibond)%b
    1809            0 :             ELSE IF (bond_list(ibond)%b == iatom) THEN
    1810            0 :                counter(iatom) = counter(iatom) + 1
    1811            0 :                connectivity(counter(iatom), iatom) = bond_list(ibond)%a
    1812              :             END IF
    1813              :          END DO
    1814              :       END DO
    1815              : 
    1816              : ! now I need to do a depth first search to figure out which atoms are on atom
    1817              : ! a's side and which are on atom d's, but remember we're moving all atoms on a's
    1818              : ! side of b, including atoms not in a's branch
    1819            0 :       atom_a(:) = 0
    1820            0 :       atom_a(torsion_list(torsion_number)%a) = 1
    1821              :       CALL depth_first_search(torsion_list(torsion_number)%b, &
    1822            0 :                               torsion_list(torsion_number)%c, connectivity(:, :), atom_a(:))
    1823            0 :       atom_d(:) = 0
    1824            0 :       atom_d(torsion_list(torsion_number)%d) = 1
    1825              :       CALL depth_first_search(torsion_list(torsion_number)%c, &
    1826            0 :                               torsion_list(torsion_number)%b, connectivity(:, :), atom_d(:))
    1827              : 
    1828              : ! now figure out the masses of the various sides, so we can weight how far we
    1829              : ! move each group of atoms
    1830            0 :       mass_a = 0.0_dp
    1831            0 :       mass_d = 0.0_dp
    1832            0 :       DO iatom = 1, natom
    1833              :          CALL get_atomic_kind(particles%els(iatom)%atomic_kind, &
    1834            0 :                               mass=atom_mass)
    1835            0 :          IF (atom_a(iatom) == 1) mass_a = mass_a + atom_mass
    1836            0 :          IF (atom_d(iatom) == 1) mass_d = mass_d + atom_mass
    1837              :       END DO
    1838              : 
    1839              : ! choose a displacement
    1840            0 :       IF (ionode) rand = rng_stream%next()
    1841            0 :       CALL group%bcast(rand, source)
    1842              : 
    1843            0 :       dis_angle = rmdihedral(molecule_type)*2.0E0_dp*(rand - 0.5E0_dp)
    1844              : 
    1845              : ! find the bond vectors, B-C, so we know what to rotate around
    1846            0 :       DO i = 1, 3
    1847              :          bond_a(i) = r_new(i, torsion_list(torsion_number)%c) - &
    1848            0 :                      r_new(i, torsion_list(torsion_number)%b)
    1849              :       END DO
    1850            0 :       old_length_a = NORM2(bond_a)
    1851            0 :       bond_a(1:3) = bond_a(1:3)/old_length_a
    1852              : 
    1853              : ! figure out how much we move each side, since we're mass-weighting, by the
    1854              : ! opposite masses, so lighter moves farther...we take the opposite sign of d
    1855              : ! so we're not rotating both angles in the same direction
    1856            0 :       dis_angle_a = dis_angle*mass_d/(mass_a + mass_d)
    1857            0 :       dis_angle_d = -dis_angle*mass_a/(mass_a + mass_d)
    1858              : 
    1859            0 :       DO iatom = 1, natom
    1860              : 
    1861            0 :          IF (atom_a(iatom) == 1) THEN
    1862              : ! shift the coords so b is at the origin
    1863              :             r_new(1:3, iatom) = r_new(1:3, iatom) - &
    1864            0 :                                 r_new(1:3, torsion_list(torsion_number)%b)
    1865              : 
    1866              : ! multiply by the rotation matrix
    1867            0 :             u = bond_a(1)
    1868            0 :             v = bond_a(2)
    1869            0 :             w = bond_a(3)
    1870            0 :             x = r_new(1, iatom)
    1871            0 :             y = r_new(2, iatom)
    1872            0 :             z = r_new(3, iatom)
    1873              :             temp(1) = (u*(u*x + v*y + w*z) + (x*(v**2 + w**2) - u*(v*y + w*z))*COS(dis_angle_a) + &
    1874            0 :                        SQRT(u**2 + v**2 + w**2)*(v*z - w*y)*SIN(dis_angle_a))/(u**2 + v**2 + w**2)
    1875              :             temp(2) = (v*(u*x + v*y + w*z) + (y*(u**2 + w**2) - v*(u*x + w*z))*COS(dis_angle_a) + &
    1876            0 :                        SQRT(u**2 + v**2 + w**2)*(w*x - u*z)*SIN(dis_angle_a))/(u**2 + v**2 + w**2)
    1877              :             temp(3) = (w*(u*x + v*y + w*z) + (z*(v**2 + u**2) - w*(u*x + v*y))*COS(dis_angle_a) + &
    1878            0 :                        SQRT(u**2 + v**2 + w**2)*(u*y - v*x)*SIN(dis_angle_a))/(u**2 + v**2 + w**2)
    1879              : 
    1880              : ! shift back to the original position
    1881            0 :             temp(1:3) = temp(1:3) + r_new(1:3, torsion_list(torsion_number)%b)
    1882            0 :             r_new(1:3, iatom) = temp(1:3)
    1883              : 
    1884            0 :          ELSE IF (atom_d(iatom) == 1) THEN
    1885              : 
    1886              : ! shift the coords so c is at the origin
    1887              :             r_new(1:3, iatom) = r_new(1:3, iatom) - &
    1888            0 :                                 r_new(1:3, torsion_list(torsion_number)%c)
    1889              : 
    1890              : ! multiply by the rotation matrix
    1891            0 :             u = bond_a(1)
    1892            0 :             v = bond_a(2)
    1893            0 :             w = bond_a(3)
    1894            0 :             x = r_new(1, iatom)
    1895            0 :             y = r_new(2, iatom)
    1896            0 :             z = r_new(3, iatom)
    1897              :             temp(1) = (u*(u*x + v*y + w*z) + (x*(v**2 + w**2) - u*(v*y + w*z))*COS(dis_angle_d) + &
    1898            0 :                        SQRT(u**2 + v**2 + w**2)*(v*z - w*y)*SIN(dis_angle_d))/(u**2 + v**2 + w**2)
    1899              :             temp(2) = (v*(u*x + v*y + w*z) + (y*(u**2 + w**2) - v*(u*x + w*z))*COS(dis_angle_d) + &
    1900            0 :                        SQRT(u**2 + v**2 + w**2)*(w*x - u*z)*SIN(dis_angle_d))/(u**2 + v**2 + w**2)
    1901              :             temp(3) = (w*(u*x + v*y + w*z) + (z*(v**2 + u**2) - w*(u*x + v*y))*COS(dis_angle_d) + &
    1902            0 :                        SQRT(u**2 + v**2 + w**2)*(u*y - v*x)*SIN(dis_angle_d))/(u**2 + v**2 + w**2)
    1903              : 
    1904              : ! shift back to the original position
    1905            0 :             temp(1:3) = temp(1:3) + r_new(1:3, torsion_list(torsion_number)%c)
    1906            0 :             r_new(1:3, iatom) = temp(1:3)
    1907              :          END IF
    1908              :       END DO
    1909              : 
    1910              : ! deallocate some stuff
    1911            0 :       DEALLOCATE (connection)
    1912            0 :       DEALLOCATE (connectivity)
    1913            0 :       DEALLOCATE (counter)
    1914            0 :       DEALLOCATE (atom_a)
    1915            0 :       DEALLOCATE (atom_d)
    1916              : 
    1917              : ! end the timing
    1918            0 :       CALL timestop(handle)
    1919              : 
    1920            0 :    END SUBROUTINE change_dihedral
    1921              : 
    1922              : ! **************************************************************************************************
    1923              : !> \brief performs either a bond or angle change move for a given molecule
    1924              : !> \param mc_par the mc parameters for the force env
    1925              : !> \param force_env the force environment used in the move
    1926              : !> \param bias_env the force environment used to bias the move, if any (it may
    1927              : !>            be null if lbias=.false. in mc_par)
    1928              : !> \param moves the structure that keeps track of how many moves have been
    1929              : !>               accepted/rejected
    1930              : !> \param energy_check the running energy difference between now and the initial
    1931              : !>        energy
    1932              : !> \param r_old the coordinates of force_env before the move
    1933              : !> \param old_energy the energy of the force_env before the move
    1934              : !> \param start_atom_swap the number of the swap molecule's first atom, assuming the rest of
    1935              : !>        the atoms follow sequentially
    1936              : !> \param target_atom the number of the target atom for swapping
    1937              : !> \param molecule_type the molecule type for the atom we're swapping
    1938              : !> \param box_number the number of the box we're doing this move in
    1939              : !> \param bias_energy_old the biased energy of the system before the move
    1940              : !> \param last_bias_energy the last biased energy of the system
    1941              : !> \param move_type dictates if we're moving to an "in" or "out" region
    1942              : !> \param rng_stream the random number stream that we draw from
    1943              : !> \author MJM
    1944              : !> \note     Designed for parallel.
    1945              : ! **************************************************************************************************
    1946            0 :    SUBROUTINE mc_avbmc_move(mc_par, force_env, bias_env, moves, &
    1947            0 :                             energy_check, r_old, old_energy, start_atom_swap, &
    1948              :                             target_atom, &
    1949              :                             molecule_type, box_number, bias_energy_old, last_bias_energy, &
    1950              :                             move_type, rng_stream)
    1951              : 
    1952              :       TYPE(mc_simpar_type), POINTER                      :: mc_par
    1953              :       TYPE(force_env_type), POINTER                      :: force_env, bias_env
    1954              :       TYPE(mc_moves_type), POINTER                       :: moves
    1955              :       REAL(KIND=dp), INTENT(INOUT)                       :: energy_check
    1956              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT)      :: r_old
    1957              :       REAL(KIND=dp), INTENT(INOUT)                       :: old_energy
    1958              :       INTEGER, INTENT(IN)                                :: start_atom_swap, target_atom, &
    1959              :                                                             molecule_type, box_number
    1960              :       REAL(KIND=dp), INTENT(INOUT)                       :: bias_energy_old, last_bias_energy
    1961              :       CHARACTER(LEN=*), INTENT(IN)                       :: move_type
    1962              :       TYPE(rng_stream_type), INTENT(INOUT)               :: rng_stream
    1963              : 
    1964              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'mc_avbmc_move'
    1965              : 
    1966              :       INTEGER                                            :: end_mol, handle, ipart, jbox, natom, &
    1967              :                                                             nswapmoves, source, start_mol
    1968            0 :       INTEGER, DIMENSION(:), POINTER                     :: avbmc_atom, mol_type, nunits, nunits_tot
    1969            0 :       INTEGER, DIMENSION(:, :), POINTER                  :: nchains
    1970              :       LOGICAL                                            :: ionode, lbias, ldum, lin, loverlap
    1971            0 :       REAL(dp), DIMENSION(:), POINTER                    :: avbmc_rmax, avbmc_rmin, pbias
    1972            0 :       REAL(dp), DIMENSION(:, :), POINTER                 :: mass
    1973              :       REAL(KIND=dp) :: BETA, bias_energy_new, del_quickstep_energy, distance, exp_max_val, &
    1974              :          exp_min_val, max_val, min_val, new_energy, prefactor, rand, rdum, volume_in, volume_out, &
    1975              :          w, weight_new, weight_old
    1976            0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: r_new
    1977              :       REAL(KIND=dp), DIMENSION(1:3)                      :: abc, RIJ
    1978              :       TYPE(cell_type), POINTER                           :: cell
    1979              :       TYPE(cp_subsys_type), POINTER                      :: subsys, subsys_force
    1980              :       TYPE(mc_molecule_info_type), POINTER               :: mc_molecule_info
    1981              :       TYPE(molecule_kind_list_type), POINTER             :: molecule_kinds
    1982              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind
    1983              :       TYPE(mp_comm_type)                                 :: group
    1984              :       TYPE(particle_list_type), POINTER                  :: particles, particles_force
    1985              : 
    1986            0 :       rdum = 1.0_dp
    1987              : 
    1988              : ! begin the timing of the subroutine
    1989            0 :       CALL timeset(routineN, handle)
    1990              : 
    1991              : ! get a bunch of stuff from mc_par
    1992              :       CALL get_mc_par(mc_par, lbias=lbias, &
    1993              :                       BETA=BETA, max_val=max_val, min_val=min_val, exp_max_val=exp_max_val, &
    1994              :                       exp_min_val=exp_min_val, avbmc_atom=avbmc_atom, &
    1995              :                       avbmc_rmin=avbmc_rmin, avbmc_rmax=avbmc_rmax, &
    1996              :                       nswapmoves=nswapmoves, ionode=ionode, source=source, &
    1997            0 :                       group=group, pbias=pbias, mc_molecule_info=mc_molecule_info)
    1998              :       CALL get_mc_molecule_info(mc_molecule_info, nchains=nchains, &
    1999            0 :                                 mass=mass, nunits=nunits, nunits_tot=nunits_tot, mol_type=mol_type)
    2000              : ! figure out some bounds for mol_type
    2001            0 :       start_mol = 1
    2002            0 :       DO jbox = 1, box_number - 1
    2003            0 :          start_mol = start_mol + SUM(nchains(:, jbox))
    2004              :       END DO
    2005            0 :       end_mol = start_mol + SUM(nchains(:, box_number)) - 1
    2006              : 
    2007              : ! nullify some pointers
    2008            0 :       NULLIFY (particles, subsys, molecule_kinds, molecule_kind, &
    2009            0 :                particles_force, subsys_force)
    2010              : 
    2011              : ! do some allocation
    2012            0 :       ALLOCATE (r_new(1:3, 1:nunits_tot(box_number)))
    2013              : 
    2014              : ! now we need to grab and save coordinates, in case we reject
    2015              : ! are we biasing this move?
    2016            0 :       IF (lbias) THEN
    2017              : 
    2018              : ! grab the coordinates
    2019            0 :          CALL force_env_get(bias_env, cell=cell, subsys=subsys)
    2020              :          CALL cp_subsys_get(subsys, &
    2021            0 :                             particles=particles, molecule_kinds=molecule_kinds)
    2022            0 :          molecule_kind => molecule_kinds%els(1)
    2023            0 :          CALL get_molecule_kind(molecule_kind, natom=natom)
    2024            0 :          CALL get_cell(cell, abc=abc)
    2025              : 
    2026              : ! save the energy
    2027              : !         bias_energy_old=bias_energy
    2028              : 
    2029              :       ELSE
    2030              : 
    2031              : ! grab the coordinates
    2032            0 :          CALL force_env_get(force_env, cell=cell, subsys=subsys)
    2033              :          CALL cp_subsys_get(subsys, &
    2034            0 :                             particles=particles, molecule_kinds=molecule_kinds)
    2035            0 :          molecule_kind => molecule_kinds%els(1)
    2036            0 :          CALL get_molecule_kind(molecule_kind, natom=natom)
    2037            0 :          CALL get_cell(cell, abc=abc)
    2038              : 
    2039              :       END IF
    2040              : 
    2041              : ! let's determine if the molecule to be moved is in the "in" region or the
    2042              : ! "out" region of the target
    2043              :       RIJ(1) = particles%els(start_atom_swap + avbmc_atom(molecule_type) - 1)%r(1) - &
    2044              :                particles%els(target_atom)%r(1) - abc(1)*ANINT( &
    2045              :                (particles%els(start_atom_swap + avbmc_atom(molecule_type) - 1)%r(1) - &
    2046            0 :                 particles%els(target_atom)%r(1))/abc(1))
    2047              :       RIJ(2) = particles%els(start_atom_swap + avbmc_atom(molecule_type) - 1)%r(2) - &
    2048              :                particles%els(target_atom)%r(2) - abc(2)*ANINT( &
    2049              :                (particles%els(start_atom_swap + avbmc_atom(molecule_type) - 1)%r(2) - &
    2050            0 :                 particles%els(target_atom)%r(2))/abc(2))
    2051              :       RIJ(3) = particles%els(start_atom_swap + avbmc_atom(molecule_type) - 1)%r(3) - &
    2052              :                particles%els(target_atom)%r(3) - abc(3)*ANINT( &
    2053              :                (particles%els(start_atom_swap + avbmc_atom(molecule_type) - 1)%r(3) - &
    2054            0 :                 particles%els(target_atom)%r(3))/abc(3))
    2055            0 :       distance = SQRT(RIJ(1)**2 + RIJ(2)**2 + RIJ(3)**2)
    2056            0 :       IF (distance <= avbmc_rmax(molecule_type) .AND. distance >= avbmc_rmin(molecule_type)) THEN
    2057              :          lin = .TRUE.
    2058              :       ELSE
    2059              :          lin = .FALSE.
    2060              :       END IF
    2061              : 
    2062              : ! increment the counter of the particular move we've done
    2063              : !     swapping into the "in" region of mol_target
    2064              :       IF (lin) THEN
    2065            0 :          IF (move_type == 'in') THEN
    2066              :             moves%avbmc_inin%attempts = &
    2067            0 :                moves%avbmc_inin%attempts + 1
    2068              :          ELSE
    2069              :             moves%avbmc_inout%attempts = &
    2070            0 :                moves%avbmc_inout%attempts + 1
    2071              :          END IF
    2072              :       ELSE
    2073            0 :          IF (move_type == 'in') THEN
    2074              :             moves%avbmc_outin%attempts = &
    2075            0 :                moves%avbmc_outin%attempts + 1
    2076              :          ELSE
    2077              :             moves%avbmc_outout%attempts = &
    2078            0 :                moves%avbmc_outout%attempts + 1
    2079              :          END IF
    2080              :       END IF
    2081              : 
    2082            0 :       IF (lbias) THEN
    2083              : 
    2084            0 :          IF (move_type == 'in') THEN
    2085              : 
    2086              : ! do CBMC for the old config
    2087              :             CALL generate_cbmc_swap_config(bias_env, BETA, max_val, min_val, exp_max_val, &
    2088              :                                            exp_min_val, nswapmoves, &
    2089              :                                            weight_old, start_atom_swap, nunits_tot(box_number), nunits, nunits(molecule_type), &
    2090              :                                            mass(:, molecule_type), ldum, rdum, &
    2091              :                                            bias_energy_old, ionode, .TRUE., mol_type(start_mol:end_mol), nchains(:, box_number), &
    2092              :                                            source, group, rng_stream, &
    2093              :                                            avbmc_atom=avbmc_atom(molecule_type), &
    2094              :                                            rmin=avbmc_rmin(molecule_type), rmax=avbmc_rmax(molecule_type), move_type='out', &
    2095            0 :                                            target_atom=target_atom)
    2096              : 
    2097              :          ELSE
    2098              : 
    2099              : ! do CBMC for the old config
    2100              :             CALL generate_cbmc_swap_config(bias_env, BETA, max_val, min_val, exp_max_val, &
    2101              :                                            exp_min_val, nswapmoves, &
    2102              :                                            weight_old, start_atom_swap, nunits_tot(box_number), nunits, nunits(molecule_type), &
    2103              :                                            mass(:, molecule_type), ldum, rdum, &
    2104              :                                            bias_energy_old, ionode, .TRUE., mol_type(start_mol:end_mol), nchains(:, box_number), &
    2105              :                                            source, group, rng_stream, &
    2106              :                                            avbmc_atom=avbmc_atom(molecule_type), &
    2107              :                                            rmin=avbmc_rmin(molecule_type), rmax=avbmc_rmax(molecule_type), move_type='in', &
    2108            0 :                                            target_atom=target_atom)
    2109              : 
    2110              :          END IF
    2111              : 
    2112              : ! generate the new config
    2113              :          CALL generate_cbmc_swap_config(bias_env, BETA, max_val, min_val, exp_max_val, &
    2114              :                                         exp_min_val, nswapmoves, &
    2115              :                                         weight_new, start_atom_swap, nunits_tot(box_number), nunits, nunits(molecule_type), &
    2116              :                                         mass(:, molecule_type), loverlap, bias_energy_new, &
    2117              :                                         bias_energy_old, ionode, .FALSE., mol_type(start_mol:end_mol), nchains(:, box_number), &
    2118              :                                         source, group, rng_stream, &
    2119              :                                         avbmc_atom=avbmc_atom(molecule_type), &
    2120              :                                         rmin=avbmc_rmin(molecule_type), rmax=avbmc_rmax(molecule_type), move_type=move_type, &
    2121            0 :                                         target_atom=target_atom)
    2122              : 
    2123              : ! the energy that comes out of the above routine is the difference...we want
    2124              : ! the real energy for the acceptance rule...we don't do this for the
    2125              : ! lbias=.false. case because it doesn't appear in the acceptance rule, and
    2126              : ! we compensate in case of acceptance
    2127            0 :          bias_energy_new = bias_energy_new + bias_energy_old
    2128              : 
    2129              :       ELSE
    2130              : 
    2131            0 :          IF (move_type == 'in') THEN
    2132              : 
    2133              : ! find the weight of the old config
    2134              :             CALL generate_cbmc_swap_config(force_env, BETA, max_val, min_val, exp_max_val, &
    2135              :                                            exp_min_val, nswapmoves, &
    2136              :                                            weight_old, start_atom_swap, nunits_tot(box_number), nunits, nunits(molecule_type), &
    2137              :                                            mass(:, molecule_type), ldum, rdum, old_energy, &
    2138              :                                            ionode, .TRUE., mol_type(start_mol:end_mol), nchains(:, box_number), &
    2139              :                                            source, group, rng_stream, &
    2140              :                                            avbmc_atom=avbmc_atom(molecule_type), &
    2141              :                                            rmin=avbmc_rmin(molecule_type), rmax=avbmc_rmax(molecule_type), move_type='out', &
    2142            0 :                                            target_atom=target_atom)
    2143              : 
    2144              :          ELSE
    2145              : 
    2146              : ! find the weight of the old config
    2147              :             CALL generate_cbmc_swap_config(force_env, BETA, max_val, min_val, exp_max_val, &
    2148              :                                            exp_min_val, nswapmoves, &
    2149              :                                            weight_old, start_atom_swap, nunits_tot(box_number), nunits, nunits(molecule_type), &
    2150              :                                            mass(:, molecule_type), ldum, rdum, old_energy, &
    2151              :                                            ionode, .TRUE., mol_type(start_mol:end_mol), nchains(:, box_number), &
    2152              :                                            source, group, rng_stream, &
    2153              :                                            avbmc_atom=avbmc_atom(molecule_type), &
    2154              :                                            rmin=avbmc_rmin(molecule_type), rmax=avbmc_rmax(molecule_type), move_type='in', &
    2155            0 :                                            target_atom=target_atom)
    2156              : 
    2157              :          END IF
    2158              : 
    2159              :          ! generate the new config...do this after, because it changes the force_env
    2160              :          CALL generate_cbmc_swap_config(force_env, BETA, max_val, min_val, exp_max_val, &
    2161              :                                         exp_min_val, nswapmoves, &
    2162              :                                         weight_new, start_atom_swap, nunits_tot(box_number), nunits, nunits(molecule_type), &
    2163              :                                         mass(:, molecule_type), loverlap, new_energy, old_energy, &
    2164              :                                         ionode, .FALSE., mol_type(start_mol:end_mol), nchains(:, box_number), &
    2165              :                                         source, group, rng_stream, &
    2166              :                                         avbmc_atom=avbmc_atom(molecule_type), &
    2167              :                                         rmin=avbmc_rmin(molecule_type), rmax=avbmc_rmax(molecule_type), move_type=move_type, &
    2168            0 :                                         target_atom=target_atom)
    2169              : 
    2170              :       END IF
    2171              : 
    2172            0 :       IF (loverlap) THEN
    2173            0 :          DEALLOCATE (r_new)
    2174              : 
    2175              : ! need to reset the old coordinates
    2176            0 :          IF (lbias) THEN
    2177            0 :             CALL force_env_get(bias_env, subsys=subsys)
    2178            0 :             CALL cp_subsys_get(subsys, particles=particles)
    2179              :          ELSE
    2180            0 :             CALL force_env_get(force_env, subsys=subsys)
    2181            0 :             CALL cp_subsys_get(subsys, particles=particles)
    2182              :          END IF
    2183            0 :          DO ipart = 1, nunits_tot(box_number)
    2184            0 :             particles%els(ipart)%r(1:3) = r_old(1:3, ipart)
    2185              :          END DO
    2186              : 
    2187            0 :          CALL timestop(handle)
    2188              : 
    2189              :          RETURN
    2190              :       END IF
    2191              : 
    2192              : ! if we're biasing, we need to compute the new energy with the full
    2193              : ! potential
    2194            0 :       IF (lbias) THEN
    2195              : ! need to give the force_env the coords from the bias_env
    2196            0 :          CALL force_env_get(force_env, subsys=subsys_force)
    2197            0 :          CALL cp_subsys_get(subsys_force, particles=particles_force)
    2198            0 :          CALL force_env_get(bias_env, subsys=subsys)
    2199            0 :          CALL cp_subsys_get(subsys, particles=particles)
    2200            0 :          DO ipart = 1, nunits_tot(box_number)
    2201            0 :             particles_force%els(ipart)%r(1:3) = particles%els(ipart)%r(1:3)
    2202              :          END DO
    2203              : 
    2204              :          CALL force_env_calc_energy_force(force_env, &
    2205            0 :                                           calc_force=.FALSE.)
    2206              :          CALL force_env_get(force_env, &
    2207            0 :                             potential_energy=new_energy)
    2208              : 
    2209              :       END IF
    2210              : 
    2211            0 :       volume_in = 4.0_dp/3.0_dp*pi*(avbmc_rmax(molecule_type)**3 - avbmc_rmin(molecule_type)**3)
    2212            0 :       volume_out = abc(1)*abc(2)*abc(3) - volume_in
    2213              : 
    2214            0 :       IF (lin .AND. move_type == 'in' .OR. &
    2215              :           .NOT. lin .AND. move_type == 'out') THEN
    2216              : ! standard Metropolis rule
    2217              :          prefactor = 1.0_dp
    2218            0 :       ELSE IF (.NOT. lin .AND. move_type == 'in') THEN
    2219            0 :          prefactor = (1.0_dp - pbias(molecule_type))*volume_in/(pbias(molecule_type)*volume_out)
    2220              :       ELSE
    2221            0 :          prefactor = pbias(molecule_type)*volume_out/((1.0_dp - pbias(molecule_type))*volume_in)
    2222              :       END IF
    2223              : 
    2224            0 :       IF (lbias) THEN
    2225              : ! AVBMC with CBMC and a biasing potential...notice that if the biasing
    2226              : ! potential equals the quickstep potential, this cancels out to the
    2227              : ! acceptance below
    2228              :          del_quickstep_energy = (-BETA)*(new_energy - old_energy - &
    2229            0 :                                          (bias_energy_new - bias_energy_old))
    2230              : 
    2231            0 :          IF (del_quickstep_energy > exp_max_val) THEN
    2232            0 :             del_quickstep_energy = max_val
    2233            0 :          ELSE IF (del_quickstep_energy < exp_min_val) THEN
    2234              :             del_quickstep_energy = 0.0_dp
    2235              :          ELSE
    2236            0 :             del_quickstep_energy = EXP(del_quickstep_energy)
    2237              :          END IF
    2238              : 
    2239            0 :          w = prefactor*del_quickstep_energy*weight_new/weight_old
    2240              : 
    2241              :       ELSE
    2242              : 
    2243              : ! AVBMC with CBMC
    2244            0 :          w = prefactor*weight_new/weight_old
    2245              :       END IF
    2246              : 
    2247              : ! check if the move is accepted
    2248            0 :       IF (w >= 1.0E0_dp) THEN
    2249            0 :          rand = 0.0E0_dp
    2250              :       ELSE
    2251            0 :          IF (ionode) rand = rng_stream%next()
    2252            0 :          CALL group%bcast(rand, source)
    2253              :       END IF
    2254              : 
    2255            0 :       IF (rand < w) THEN
    2256              : 
    2257              : ! accept the move
    2258              : 
    2259            0 :          IF (lin) THEN
    2260            0 :             IF (move_type == 'in') THEN
    2261              :                moves%avbmc_inin%successes = &
    2262            0 :                   moves%avbmc_inin%successes + 1
    2263              :             ELSE
    2264              :                moves%avbmc_inout%successes = &
    2265            0 :                   moves%avbmc_inout%successes + 1
    2266              :             END IF
    2267              :          ELSE
    2268            0 :             IF (move_type == 'in') THEN
    2269              :                moves%avbmc_outin%successes = &
    2270            0 :                   moves%avbmc_outin%successes + 1
    2271              :             ELSE
    2272              :                moves%avbmc_outout%successes = &
    2273            0 :                   moves%avbmc_outout%successes + 1
    2274              :             END IF
    2275              :          END IF
    2276              : 
    2277              : ! we need to compensate for the fact that we take the difference in
    2278              : ! generate_cbmc_config to keep the exponetials small
    2279            0 :          IF (.NOT. lbias) THEN
    2280            0 :             new_energy = new_energy + old_energy
    2281              :          END IF
    2282              : 
    2283              : ! update energies
    2284            0 :          energy_check = energy_check + (new_energy - old_energy)
    2285            0 :          old_energy = new_energy
    2286              : 
    2287              : ! if we're biasing the update the biasing energy
    2288            0 :          IF (lbias) THEN
    2289              : ! need to do this outside of the routine
    2290            0 :             last_bias_energy = bias_energy_new
    2291            0 :             bias_energy_old = bias_energy_new
    2292              :          END IF
    2293              : 
    2294              : ! update coordinates
    2295            0 :          CALL force_env_get(force_env, subsys=subsys)
    2296            0 :          CALL cp_subsys_get(subsys, particles=particles)
    2297            0 :          DO ipart = 1, nunits_tot(box_number)
    2298            0 :             r_old(1:3, ipart) = particles%els(ipart)%r(1:3)
    2299              :          END DO
    2300              :       ELSE
    2301              : ! reject the move...need to restore the old coordinates
    2302            0 :          IF (lbias) THEN
    2303            0 :             CALL force_env_get(bias_env, subsys=subsys)
    2304            0 :             CALL cp_subsys_get(subsys, particles=particles)
    2305            0 :             DO ipart = 1, nunits_tot(box_number)
    2306            0 :                particles%els(ipart)%r(1:3) = r_old(1:3, ipart)
    2307              :             END DO
    2308            0 :             CALL cp_subsys_set(subsys, particles=particles)
    2309              :          END IF
    2310            0 :          CALL force_env_get(force_env, subsys=subsys)
    2311            0 :          CALL cp_subsys_get(subsys, particles=particles)
    2312            0 :          DO ipart = 1, nunits_tot(box_number)
    2313            0 :             particles%els(ipart)%r(1:3) = r_old(1:3, ipart)
    2314              :          END DO
    2315            0 :          CALL cp_subsys_set(subsys, particles=particles)
    2316              : 
    2317              :       END IF
    2318              : 
    2319              : ! deallocate some stuff
    2320            0 :       DEALLOCATE (r_new)
    2321              : ! end the timing
    2322            0 :       CALL timestop(handle)
    2323              : 
    2324            0 :    END SUBROUTINE mc_avbmc_move
    2325              : 
    2326              : ! **************************************************************************************************
    2327              : !> \brief performs a hybrid Monte Carlo move that runs a short MD sequence
    2328              : !> \param mc_par the mc parameters for the force env
    2329              : !> \param force_env the force environment whose cell we're changing
    2330              : !> \param globenv ...
    2331              : !> \param moves the structure that keeps track of how many moves have been
    2332              : !>               accepted/rejected
    2333              : !> \param move_updates the structure that keeps track of how many moves have
    2334              : !>               been accepted/rejected since the last time the displacements
    2335              : !>               were updated
    2336              : !> \param old_energy the energy of the last accepted move involving an
    2337              : !>                    unbiased calculation
    2338              : !> \param box_number the box we're changing the volume of
    2339              : !> \param energy_check the running total of how much the energy has changed
    2340              : !>                      since the initial configuration
    2341              : !> \param r_old the coordinates of the last accepted move involving an
    2342              : !>               unbiased calculation
    2343              : !> \param rng_stream the random number stream that we draw from
    2344              : !> \author MJM
    2345              : !> \note     Designed for parallel use.
    2346              : ! **************************************************************************************************
    2347           20 :    SUBROUTINE mc_hmc_move(mc_par, force_env, globenv, moves, move_updates, &
    2348              :                           old_energy, box_number, &
    2349           20 :                           energy_check, r_old, rng_stream)
    2350              : 
    2351              :       TYPE(mc_simpar_type), POINTER                      :: mc_par
    2352              :       TYPE(force_env_type), POINTER                      :: force_env
    2353              :       TYPE(global_environment_type), POINTER             :: globenv
    2354              :       TYPE(mc_moves_type), POINTER                       :: moves, move_updates
    2355              :       REAL(KIND=dp), INTENT(INOUT)                       :: old_energy
    2356              :       INTEGER, INTENT(IN)                                :: box_number
    2357              :       REAL(KIND=dp), INTENT(INOUT)                       :: energy_check
    2358              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT)      :: r_old
    2359              :       TYPE(rng_stream_type), INTENT(INOUT)               :: rng_stream
    2360              : 
    2361              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'mc_hmc_move'
    2362              : 
    2363              :       INTEGER                                            :: handle, iatom, source
    2364           20 :       INTEGER, DIMENSION(:), POINTER                     :: nunits_tot
    2365              :       LOGICAL                                            :: ionode
    2366              :       REAL(KIND=dp)                                      :: BETA, energy_term, exp_max_val, &
    2367              :                                                             exp_min_val, new_energy, rand, value, w
    2368           20 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: r
    2369              :       TYPE(cp_subsys_type), POINTER                      :: oldsys
    2370              :       TYPE(mc_ekin_type), POINTER                        :: hmc_ekin
    2371              :       TYPE(mc_molecule_info_type), POINTER               :: mc_molecule_info
    2372              :       TYPE(mp_comm_type)                                 :: group
    2373              :       TYPE(particle_list_type), POINTER                  :: particles_old
    2374              : 
    2375              : ! begin the timing of the subroutine
    2376              : 
    2377           20 :       CALL timeset(routineN, handle)
    2378              : 
    2379              : ! get a bunch of stuff from mc_par
    2380              :       CALL get_mc_par(mc_par, ionode=ionode, &
    2381              :                       BETA=BETA, exp_max_val=exp_max_val, &
    2382              :                       exp_min_val=exp_min_val, source=source, group=group, &
    2383           20 :                       mc_molecule_info=mc_molecule_info)
    2384           20 :       CALL get_mc_molecule_info(mc_molecule_info, nunits_tot=nunits_tot)
    2385              : 
    2386              : ! nullify some pointers
    2387           20 :       NULLIFY (particles_old, oldsys, hmc_ekin)
    2388              : 
    2389              : ! do some allocation
    2390           60 :       ALLOCATE (r(1:3, 1:nunits_tot(box_number)))
    2391           20 :       ALLOCATE (hmc_ekin)
    2392              : 
    2393              : ! record the attempt
    2394           20 :       moves%hmc%attempts = moves%hmc%attempts + 1
    2395           20 :       move_updates%hmc%attempts = move_updates%hmc%attempts + 1
    2396              : 
    2397              : ! now let's grab the particle positions
    2398           20 :       CALL force_env_get(force_env, subsys=oldsys)
    2399           20 :       CALL cp_subsys_get(oldsys, particles=particles_old)
    2400              : 
    2401              : ! save the old coordinates
    2402        21700 :       DO iatom = 1, nunits_tot(box_number)
    2403        86740 :          r(1:3, iatom) = particles_old%els(iatom)%r(1:3)
    2404              :       END DO
    2405              : 
    2406              : ! now run the MD simulation
    2407           20 :       CALL qs_mol_dyn(force_env, globenv, hmc_e_initial=hmc_ekin%initial_ekin, hmc_e_final=hmc_ekin%final_ekin)
    2408              : 
    2409              : ! get the energy
    2410              :       CALL force_env_get(force_env, &
    2411           20 :                          potential_energy=new_energy)
    2412              : 
    2413              : ! accept or reject the move
    2414              : ! to prevent overflows
    2415           20 :       energy_term = new_energy + hmc_ekin%final_ekin - old_energy - hmc_ekin%initial_ekin
    2416              : 
    2417           20 :       value = -BETA*(energy_term)
    2418           20 :       IF (value > exp_max_val) THEN
    2419              :          w = 10.0_dp
    2420           20 :       ELSE IF (value < exp_min_val) THEN
    2421              :          w = 0.0_dp
    2422              :       ELSE
    2423           20 :          w = EXP(value)
    2424              :       END IF
    2425              : 
    2426           20 :       IF (w >= 1.0E0_dp) THEN
    2427           10 :          w = 1.0E0_dp
    2428           10 :          rand = 0.0E0_dp
    2429              :       ELSE
    2430           10 :          IF (ionode) rand = rng_stream%next()
    2431           10 :          CALL group%bcast(rand, source)
    2432              :       END IF
    2433              : 
    2434           20 :       IF (rand < w) THEN
    2435              : 
    2436              : ! accept the move
    2437           14 :          moves%hmc%successes = moves%hmc%successes + 1
    2438           14 :          move_updates%hmc%successes = move_updates%hmc%successes + 1
    2439              : 
    2440              : ! update energies
    2441           14 :          energy_check = energy_check + (new_energy - old_energy)
    2442           14 :          old_energy = new_energy
    2443              : 
    2444        15190 :          DO iatom = 1, nunits_tot(box_number)
    2445        60718 :             r_old(1:3, iatom) = particles_old%els(iatom)%r(1:3)
    2446              :          END DO
    2447              : 
    2448              :       ELSE
    2449              : 
    2450              : ! reset the cell and particle positions
    2451         6510 :          DO iatom = 1, nunits_tot(box_number)
    2452        26022 :             particles_old%els(iatom)%r(1:3) = r_old(1:3, iatom)
    2453              :          END DO
    2454              : 
    2455              :       END IF
    2456              : 
    2457              : ! deallocate some stuff
    2458           20 :       DEALLOCATE (r)
    2459           20 :       DEALLOCATE (hmc_ekin)
    2460              : 
    2461              : ! end the timing
    2462           20 :       CALL timestop(handle)
    2463              : 
    2464           40 :    END SUBROUTINE mc_hmc_move
    2465              : 
    2466              : ! *****************************************************************************
    2467              : !> \brief translates the cluster randomly in either the x,y, or z
    2468              : !>direction
    2469              : !> \param mc_par the mc parameters for the force env
    2470              : !> \param force_env the force environment used in the move
    2471              : !> \param bias_env the force environment used to bias the move, if any (it may
    2472              : !>            be null if lbias=.false. in mc_par)
    2473              : !> \param moves the structure that keeps track of how many moves have been
    2474              : !>               accepted/rejected
    2475              : !> \param move_updates the structure that keeps track of how many moves have
    2476              : !>               been accepted/rejected since the last time the displacements
    2477              : !>               were updated
    2478              : !> \param box_number ...
    2479              : !> \param bias_energy the biased energy of the system before the move
    2480              : !> \param lreject set to .true. if there is an overlap
    2481              : !> \param rng_stream the random number stream that we draw from
    2482              : !> \author Himanshu Goel
    2483              : !> \note     Designed for parallel use.
    2484              : ! **************************************************************************************************
    2485              : 
    2486           10 :    SUBROUTINE mc_cluster_translation(mc_par, force_env, bias_env, moves, &
    2487              :                                      move_updates, box_number, bias_energy, lreject, rng_stream)
    2488              : 
    2489              :       TYPE(mc_simpar_type), POINTER                      :: mc_par
    2490              :       TYPE(force_env_type), POINTER                      :: force_env, bias_env
    2491              :       TYPE(mc_moves_type), POINTER                       :: moves, move_updates
    2492              :       INTEGER, INTENT(IN)                                :: box_number
    2493              :       REAL(KIND=dp), INTENT(INOUT)                       :: bias_energy
    2494              :       LOGICAL, INTENT(OUT)                               :: lreject
    2495              :       TYPE(rng_stream_type), INTENT(INOUT)               :: rng_stream
    2496              : 
    2497              :       CHARACTER(len=*), PARAMETER :: routineN = 'mc_cluster_translation'
    2498              : 
    2499              :       INTEGER :: cstart, end_mol, handle, imol, ipart, iparticle, iunit, jbox, jpart, junit, &
    2500              :          move_direction, nend, nunit, source, start_mol, total_clus, total_clusafmo
    2501              :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: cluster
    2502           10 :       INTEGER, DIMENSION(:), POINTER                     :: mol_type, nunits, nunits_tot
    2503           10 :       INTEGER, DIMENSION(:, :), POINTER                  :: nchains
    2504              :       LOGICAL                                            :: ionode, lbias, loverlap
    2505              :       REAL(KIND=dp)                                      :: BETA, bias_energy_new, bias_energy_old, &
    2506              :                                                             dis_mol, exp_max_val, exp_min_val, &
    2507              :                                                             rand, rmcltrans, value, w
    2508           10 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: r_old
    2509              :       TYPE(cp_subsys_type), POINTER                      :: subsys
    2510              :       TYPE(mc_molecule_info_type), POINTER               :: mc_molecule_info
    2511              :       TYPE(mp_comm_type)                                 :: group
    2512              :       TYPE(particle_list_type), POINTER                  :: particles
    2513              : 
    2514              : !   *** Local Counters ***
    2515              : ! begin the timing of the subroutine
    2516              : 
    2517           10 :       CALL timeset(routineN, handle)
    2518              : 
    2519              : ! nullify some pointers
    2520           10 :       NULLIFY (particles, subsys)
    2521              : 
    2522              : ! get a bunch of stuff from mc_par
    2523              :       CALL get_mc_par(mc_par, lbias=lbias, &
    2524              :                       BETA=BETA, exp_max_val=exp_max_val, &
    2525              :                       exp_min_val=exp_min_val, rmcltrans=rmcltrans, ionode=ionode, source=source, &
    2526           10 :                       group=group, mc_molecule_info=mc_molecule_info)
    2527              :       CALL get_mc_molecule_info(mc_molecule_info, nunits_tot=nunits_tot, &
    2528           10 :                                 nchains=nchains, nunits=nunits, mol_type=mol_type)
    2529              : 
    2530              : ! find out some bounds for mol_type
    2531           10 :       start_mol = 1
    2532           10 :       DO jbox = 1, box_number - 1
    2533           10 :          start_mol = start_mol + SUM(nchains(:, jbox))
    2534              :       END DO
    2535           20 :       end_mol = start_mol + SUM(nchains(:, box_number)) - 1
    2536              : 
    2537              : ! do some allocation
    2538           30 :       ALLOCATE (r_old(1:3, 1:nunits_tot(box_number)))
    2539              : 
    2540              : ! Allocating cluster matrix size
    2541           20 :       nend = SUM(nchains(:, box_number))
    2542           40 :       ALLOCATE (cluster(nend, nend))
    2543           60 :       DO ipart = 1, nend
    2544          310 :          DO jpart = 1, nend
    2545          300 :             cluster(ipart, jpart) = 0
    2546              :          END DO
    2547              :       END DO
    2548              : 
    2549              : ! Get cluster information in cluster matrix from cluster_search subroutine
    2550           10 :       IF (lbias) THEN
    2551              :          CALL cluster_search(mc_par, bias_env, cluster, nchains(:, box_number), &
    2552            0 :                              nunits, mol_type(start_mol:end_mol), total_clus)
    2553              :       ELSE
    2554              :          CALL cluster_search(mc_par, force_env, cluster, nchains(:, box_number), &
    2555           10 :                              nunits, mol_type(start_mol:end_mol), total_clus)
    2556              :       END IF
    2557              : 
    2558           10 :       IF (lbias) THEN
    2559              : 
    2560              : ! grab the coordinates
    2561            0 :          CALL force_env_get(bias_env, subsys=subsys)
    2562            0 :          CALL cp_subsys_get(subsys, particles=particles)
    2563              : 
    2564              : ! save the coordinates
    2565            0 :          DO ipart = 1, nunits_tot(box_number)
    2566            0 :             r_old(1:3, ipart) = particles%els(ipart)%r(1:3)
    2567              :          END DO
    2568              : 
    2569              : ! save the energy
    2570            0 :          bias_energy_old = bias_energy
    2571              :       ELSE
    2572              : 
    2573              : ! grab the coordinates
    2574           10 :          CALL force_env_get(force_env, subsys=subsys)
    2575           10 :          CALL cp_subsys_get(subsys, particles=particles)
    2576              :       END IF
    2577              : 
    2578              : ! record the attempt
    2579           10 :       moves%cltrans%attempts = moves%cltrans%attempts + 1
    2580           10 :       move_updates%cltrans%attempts = move_updates%cltrans%attempts + 1
    2581           10 :       moves%bias_cltrans%attempts = moves%bias_cltrans%attempts + 1
    2582           10 :       move_updates%bias_cltrans%attempts = move_updates%bias_cltrans%attempts + 1
    2583           10 :       IF (.NOT. lbias) THEN
    2584           10 :          moves%cltrans%qsuccesses = moves%cltrans%qsuccesses + 1
    2585           10 :          move_updates%cltrans%qsuccesses = move_updates%cltrans%qsuccesses + 1
    2586           10 :          moves%bias_cltrans%qsuccesses = moves%bias_cltrans%qsuccesses + 1
    2587           10 :          move_updates%bias_cltrans%qsuccesses = move_updates%bias_cltrans%qsuccesses + 1
    2588              :       END IF
    2589              : 
    2590              : ! call a random number to figure out which direction we're moving
    2591           10 :       IF (ionode) rand = rng_stream%next()
    2592           10 :       CALL group%bcast(rand, source)
    2593           10 :       move_direction = INT(3*rand) + 1
    2594              : 
    2595              : ! call a random number to figure out how far we're moving
    2596           10 :       IF (ionode) rand = rng_stream%next()
    2597           10 :       CALL group%bcast(rand, source)
    2598           10 :       dis_mol = rmcltrans*(rand - 0.5E0_dp)*2.0E0_dp
    2599              : 
    2600              : ! choosing cluster
    2601           10 :       IF (ionode) rand = rng_stream%next()
    2602           10 :       CALL group%bcast(rand, source)
    2603           10 :       jpart = INT(1 + rand*total_clus)
    2604              : 
    2605              : ! do the cluster move
    2606           60 :       DO cstart = 1, nend
    2607           50 :          imol = 0
    2608           60 :          IF (cluster(jpart, cstart) /= 0) THEN
    2609           34 :             imol = cluster(jpart, cstart)
    2610              :             iunit = 1
    2611           34 :             DO ipart = 1, imol - 1
    2612           24 :                nunit = nunits(mol_type(ipart + start_mol - 1))
    2613           34 :                iunit = iunit + nunit
    2614              :             END DO
    2615           10 :             nunit = nunits(mol_type(imol + start_mol - 1))
    2616           10 :             junit = iunit + nunit - 1
    2617           30 :             DO iparticle = iunit, junit
    2618              :                particles%els(iparticle)%r(move_direction) = &
    2619           30 :                   particles%els(iparticle)%r(move_direction) + dis_mol
    2620              :             END DO
    2621              :          END IF
    2622              :       END DO
    2623           10 :       CALL cp_subsys_set(subsys, particles=particles)
    2624              : 
    2625              : !Make cluster matrix null
    2626           60 :       DO ipart = 1, nend
    2627          310 :          DO jpart = 1, nend
    2628          300 :             cluster(ipart, jpart) = 0
    2629              :          END DO
    2630              :       END DO
    2631              : 
    2632              : ! checking the number of cluster are same or got changed after cluster translation move
    2633           10 :       IF (lbias) THEN
    2634              :          CALL cluster_search(mc_par, bias_env, cluster, nchains(:, box_number), &
    2635            0 :                              nunits, mol_type(start_mol:end_mol), total_clusafmo)
    2636              :       ELSE
    2637              :          CALL cluster_search(mc_par, force_env, cluster, nchains(:, box_number), &
    2638           10 :                              nunits, mol_type(start_mol:end_mol), total_clusafmo)
    2639              :       END IF
    2640              : 
    2641              : ! figure out if there is any overlap...need the number of the molecule
    2642           10 :       lreject = .FALSE.
    2643           10 :       IF (lbias) THEN
    2644              :          CALL check_for_overlap(bias_env, nchains(:, box_number), &
    2645            0 :                                 nunits(:), loverlap, mol_type(start_mol:end_mol))
    2646              :       ELSE
    2647              :          CALL check_for_overlap(force_env, nchains(:, box_number), &
    2648           10 :                                 nunits(:), loverlap, mol_type(start_mol:end_mol))
    2649           10 :          IF (loverlap) lreject = .TRUE.
    2650              :       END IF
    2651              : 
    2652              : ! check if cluster size changes then reject the move
    2653           10 :       IF (lbias) THEN
    2654            0 :          IF (total_clusafmo /= total_clus) THEN
    2655            0 :             loverlap = .TRUE.
    2656              :          END IF
    2657              :       ELSE
    2658           10 :          IF (total_clusafmo /= total_clus) THEN
    2659            0 :             loverlap = .TRUE.
    2660            0 :             lreject = .TRUE.
    2661              :          END IF
    2662              :       END IF
    2663              : 
    2664              : ! if we're biasing with a cheaper potential, check for acceptance
    2665           10 :       IF (lbias) THEN
    2666              : 
    2667              : ! here's where we bias the moves
    2668            0 :          IF (loverlap) THEN
    2669              :             w = 0.0E0_dp
    2670              :          ELSE
    2671            0 :             CALL force_env_calc_energy_force(bias_env, calc_force=.FALSE.)
    2672              :             CALL force_env_get(bias_env, &
    2673            0 :                                potential_energy=bias_energy_new)
    2674              : ! accept or reject the move based on the Metropolis rule
    2675            0 :             value = -BETA*(bias_energy_new - bias_energy_old)
    2676            0 :             IF (value > exp_max_val) THEN
    2677              :                w = 10.0_dp
    2678            0 :             ELSE IF (value < exp_min_val) THEN
    2679              :                w = 0.0_dp
    2680              :             ELSE
    2681            0 :                w = EXP(value)
    2682              :             END IF
    2683              : 
    2684              :          END IF
    2685              : 
    2686            0 :          IF (w >= 1.0E0_dp) THEN
    2687            0 :             w = 1.0E0_dp
    2688            0 :             rand = 0.0E0_dp
    2689              :          ELSE
    2690            0 :             IF (ionode) rand = rng_stream%next()
    2691            0 :             CALL group%bcast(rand, source)
    2692              :          END IF
    2693            0 :          IF (rand < w) THEN
    2694              : 
    2695              : ! accept the move
    2696            0 :             moves%bias_cltrans%successes = moves%bias_cltrans%successes + 1
    2697            0 :             move_updates%bias_cltrans%successes = move_updates%bias_cltrans%successes + 1
    2698            0 :             moves%cltrans%qsuccesses = moves%cltrans%qsuccesses + 1
    2699              :             move_updates%cltrans%successes = &
    2700            0 :                move_updates%cltrans%successes + 1
    2701            0 :             moves%qcltrans_dis = moves%qcltrans_dis + ABS(dis_mol)
    2702              :             bias_energy = bias_energy + bias_energy_new - &
    2703            0 :                           bias_energy_old
    2704              : 
    2705              :          ELSE
    2706              : 
    2707              : ! reject the move
    2708              : ! restore the coordinates
    2709            0 :             CALL force_env_get(bias_env, subsys=subsys)
    2710            0 :             CALL cp_subsys_get(subsys, particles=particles)
    2711            0 :             DO ipart = 1, nunits_tot(box_number)
    2712            0 :                particles%els(ipart)%r(1:3) = r_old(1:3, ipart)
    2713              :             END DO
    2714            0 :             CALL cp_subsys_set(subsys, particles=particles)
    2715              : 
    2716              :          END IF
    2717              : 
    2718              :       END IF
    2719              : 
    2720              : ! deallocate some stuff
    2721           10 :       DEALLOCATE (cluster)
    2722           10 :       DEALLOCATE (r_old)
    2723              : 
    2724              : ! end the timing
    2725           10 :       CALL timestop(handle)
    2726              : 
    2727           10 :    END SUBROUTINE mc_cluster_translation
    2728              : 
    2729              : END MODULE mc_moves
        

Generated by: LCOV version 2.0-1