LCOV - code coverage report
Current view: top level - src/motion/mc - mc_moves.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:4dc10b3) Lines: 697 1001 69.6 %
Date: 2024-11-21 06:45:46 Functions: 9 11 81.8 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief 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) .NE. 0) THEN
     103        1636 :             IF (connectivity(iatom, current_atom) .NE. 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 :       ELSEIF (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 .GT. exp_max_val) THEN
     340             :                w = 10.0_dp
     341         420 :             ELSEIF (value .LT. 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 .GE. 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 .LT. 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 :             ELSEIF (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 .GT. exp_max_val) THEN
     583             :                w = 10.0_dp
     584         528 :             ELSEIF (value .LT. 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 .GE. 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 .LT. 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 .EQ. 1) THEN
     782             :          lx = .TRUE.
     783         334 :       ELSEIF (dir .EQ. 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 :       ELSEIF (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 .GT. exp_max_val) THEN
     886             :                w = 10.0_dp
     887         424 :             ELSEIF (value .LT. 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 .GE. 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 .LT. 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 .LT. 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) .EQ. 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) .EQ. 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) .LE. 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 .LE. 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 .EQ. use_fist_force) THEN
    1198          13 :             CALL get_mc_par(mc_par, rcut=rcut)
    1199          13 :             IF (new_cell_length(1) .LT. 2.0_dp*rcut) ltoo_small = .TRUE.
    1200          13 :             IF (new_cell_length(2) .LT. 2.0_dp*rcut) ltoo_small = .TRUE.
    1201          13 :             IF (new_cell_length(3) .LT. 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) &
    1212           0 :          CPABORT("Attempted a volume move where box size got too small.")
    1213             : 
    1214             : ! now compute the energy
    1215          34 :       CALL force_env_calc_energy_force(force_env, calc_force=.FALSE.)
    1216             :       CALL force_env_get(force_env, &
    1217          34 :                          potential_energy=new_energy)
    1218             : 
    1219             : ! accept or reject the move
    1220             : ! to prevent overflows
    1221          34 :       energy_term = new_energy - old_energy
    1222             :       volume_term = -REAL(SUM(nchains(:, box_number)), dp)/BETA* &
    1223             :                     LOG(new_cell_length(1)*new_cell_length(2)*new_cell_length(3)/ &
    1224          94 :                         (old_cell_length(1)*old_cell_length(2)*old_cell_length(3)))
    1225          34 :       pressure_term = pressure*vol_dis
    1226             : 
    1227          34 :       value = -BETA*(energy_term + volume_term + pressure_term)
    1228          34 :       IF (value .GT. exp_max_val) THEN
    1229             :          w = 10.0_dp
    1230          34 :       ELSEIF (value .LT. exp_min_val) THEN
    1231             :          w = 0.0_dp
    1232             :       ELSE
    1233          34 :          w = EXP(value)
    1234             :       END IF
    1235             : 
    1236             : !!!!!!!!!!!!!!!! for E_V curves
    1237             : !         w=1.0E0_dp
    1238             : !         w=0.0E0_dp
    1239             : 
    1240          34 :       IF (w .GE. 1.0E0_dp) THEN
    1241          18 :          w = 1.0E0_dp
    1242          18 :          rand = 0.0E0_dp
    1243             :       ELSE
    1244          16 :          IF (ionode) rand = rng_stream%next()
    1245          16 :          CALL group%bcast(rand, source)
    1246             :       END IF
    1247             : 
    1248          34 :       IF (rand .LT. w) THEN
    1249             : 
    1250             : ! accept the move
    1251          30 :          moves%volume%successes = moves%volume%successes + 1
    1252          30 :          move_updates%volume%successes = move_updates%volume%successes + 1
    1253             : 
    1254             : ! update energies
    1255          30 :          energy_check = energy_check + (new_energy - old_energy)
    1256          30 :          old_energy = new_energy
    1257             : 
    1258         720 :          DO iatom = 1, nunits_tot(box_number)
    1259        2790 :             r_old(1:3, iatom) = particles_old%els(iatom)%r(1:3)
    1260             :          END DO
    1261             : 
    1262             : ! update discrete_array if we're doing a discrete volume move
    1263          30 :          IF (ldiscrete) THEN
    1264             :             CALL create_discrete_array(new_cell_length(:), &
    1265           0 :                                        discrete_array(:, :), discrete_step)
    1266             :          END IF
    1267             : 
    1268             :       ELSE
    1269             : 
    1270             : ! reset the cell and particle positions
    1271           4 :          CALL cp_subsys_set(oldsys, cell=cell_old)
    1272          40 :          DO iatom = 1, nunits_tot(box_number)
    1273         148 :             particles_old%els(iatom)%r(1:3) = r_old(1:3, iatom)
    1274             :          END DO
    1275             : 
    1276             :       END IF
    1277             : 
    1278             : ! deallocate some stuff
    1279          34 :       DEALLOCATE (r)
    1280          34 :       CALL cell_release(cell_test)
    1281          34 :       CALL cell_release(cell_old)
    1282             : 
    1283             : ! end the timing
    1284          34 :       CALL timestop(handle)
    1285             : 
    1286          68 :    END SUBROUTINE mc_volume_move
    1287             : 
    1288             : ! **************************************************************************************************
    1289             : !> \brief alters the length of a random bond for the given molecule, using
    1290             : !>      a mass weighted scheme so the lightest atoms move the most
    1291             : !> \param r_old the initial coordinates of all molecules in the system
    1292             : !> \param r_new the new coordinates of all molecules in the system
    1293             : !> \param mc_par the mc parameters for the force env
    1294             : !> \param molecule_type the molecule type that we're moving
    1295             : !> \param molecule_kind the structure containing the molecule information
    1296             : !> \param dis_length the ratio of the new bond length to the old bond length,
    1297             : !>                    used in the acceptance rule
    1298             : !> \param particles the particle_list_type for all particles in the force_env..
    1299             : !>             used to grab the mass of each atom
    1300             : !> \param rng_stream the random number stream that we draw from
    1301             : !>
    1302             : !>    This subroutine is written to be parallel.
    1303             : !> \author MJM
    1304             : ! **************************************************************************************************
    1305         312 :    SUBROUTINE change_bond_length(r_old, r_new, mc_par, molecule_type, molecule_kind, &
    1306             :                                  dis_length, particles, rng_stream)
    1307             : 
    1308             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: r_old
    1309             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT)        :: r_new
    1310             :       TYPE(mc_simpar_type), POINTER                      :: mc_par
    1311             :       INTEGER, INTENT(IN)                                :: molecule_type
    1312             :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind
    1313             :       REAL(KIND=dp), INTENT(OUT)                         :: dis_length
    1314             :       TYPE(particle_list_type), POINTER                  :: particles
    1315             :       TYPE(rng_stream_type), INTENT(INOUT)               :: rng_stream
    1316             : 
    1317             :       CHARACTER(len=*), PARAMETER :: routineN = 'change_bond_length'
    1318             : 
    1319             :       INTEGER                                            :: bond_number, handle, i, iatom, ibond, &
    1320             :                                                             ipart, natom, nbond, source
    1321         312 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_a, atom_b, counter
    1322         312 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: connection, connectivity
    1323         312 :       INTEGER, DIMENSION(:), POINTER                     :: nunits
    1324             :       LOGICAL                                            :: ionode
    1325         312 :       REAL(dp), DIMENSION(:), POINTER                    :: rmbond
    1326             :       REAL(KIND=dp)                                      :: atom_mass, mass_a, mass_b, new_length_a, &
    1327             :                                                             new_length_b, old_length, rand
    1328             :       REAL(KIND=dp), DIMENSION(1:3)                      :: bond_a, bond_b
    1329         312 :       TYPE(bond_type), DIMENSION(:), POINTER             :: bond_list
    1330             :       TYPE(mc_molecule_info_type), POINTER               :: mc_molecule_info
    1331             :       TYPE(mp_comm_type)                                 :: group
    1332             : 
    1333             : ! begin the timing of the subroutine
    1334             : 
    1335         312 :       CALL timeset(routineN, handle)
    1336             : 
    1337         312 :       NULLIFY (rmbond, mc_molecule_info)
    1338             : 
    1339             : ! get some stuff from mc_par
    1340             :       CALL get_mc_par(mc_par, mc_molecule_info=mc_molecule_info, source=source, &
    1341         312 :                       group=group, rmbond=rmbond, ionode=ionode)
    1342         312 :       CALL get_mc_molecule_info(mc_molecule_info, nunits=nunits)
    1343             : 
    1344             : ! copy the incoming coordinates so we can change them
    1345        1248 :       DO ipart = 1, nunits(molecule_type)
    1346        4056 :          r_new(1:3, ipart) = r_old(1:3, ipart)
    1347             :       END DO
    1348             : 
    1349             : ! pick which bond in the molecule at random
    1350         312 :       IF (ionode) THEN
    1351         156 :          rand = rng_stream%next()
    1352             :       END IF
    1353         312 :       CALL group%bcast(rand, source)
    1354             :       CALL get_molecule_kind(molecule_kind, natom=natom, nbond=nbond, &
    1355         312 :                              bond_list=bond_list)
    1356         312 :       bond_number = CEILING(rand*REAL(nbond, dp))
    1357             : 
    1358         936 :       ALLOCATE (connection(1:natom, 1:2))
    1359             : ! assume at most six bonds per atom
    1360         936 :       ALLOCATE (connectivity(1:6, 1:natom))
    1361         936 :       ALLOCATE (counter(1:natom))
    1362         624 :       ALLOCATE (atom_a(1:natom))
    1363         624 :       ALLOCATE (atom_b(1:natom))
    1364        2808 :       connection(:, :) = 0
    1365        6864 :       connectivity(:, :) = 0
    1366        1248 :       counter(:) = 0
    1367        1248 :       atom_a(:) = 0
    1368        1248 :       atom_b(:) = 0
    1369             : 
    1370             : ! now we need to find a list of atoms that each atom in this bond is connected
    1371             : ! to
    1372        1248 :       DO iatom = 1, natom
    1373        3120 :          DO ibond = 1, nbond
    1374        2808 :             IF (bond_list(ibond)%a == iatom) THEN
    1375         624 :                counter(iatom) = counter(iatom) + 1
    1376         624 :                connectivity(counter(iatom), iatom) = bond_list(ibond)%b
    1377        1248 :             ELSEIF (bond_list(ibond)%b == iatom) THEN
    1378         624 :                counter(iatom) = counter(iatom) + 1
    1379         624 :                connectivity(counter(iatom), iatom) = bond_list(ibond)%a
    1380             :             END IF
    1381             :          END DO
    1382             :       END DO
    1383             : 
    1384             : ! now I need to do a depth first search to figure out which atoms are on atom a's
    1385             : ! side and which are on atom b's
    1386        1248 :       atom_a(:) = 0
    1387         312 :       atom_a(bond_list(bond_number)%a) = 1
    1388             :       CALL depth_first_search(bond_list(bond_number)%a, bond_list(bond_number)%b, &
    1389         312 :                               connectivity(:, :), atom_a(:))
    1390        1248 :       atom_b(:) = 0
    1391         312 :       atom_b(bond_list(bond_number)%b) = 1
    1392             :       CALL depth_first_search(bond_list(bond_number)%b, bond_list(bond_number)%a, &
    1393         312 :                               connectivity(:, :), atom_b(:))
    1394             : 
    1395             : ! now figure out the masses of the various sides, so we can weight how far we move each
    1396             : ! group of atoms
    1397         312 :       mass_a = 0.0_dp
    1398         312 :       mass_b = 0.0_dp
    1399        1248 :       DO iatom = 1, natom
    1400             :          CALL get_atomic_kind(particles%els(iatom)%atomic_kind, &
    1401         936 :                               mass=atom_mass)
    1402        1248 :          IF (atom_a(iatom) == 1) THEN
    1403         624 :             mass_a = mass_a + atom_mass
    1404             :          ELSE
    1405         312 :             mass_b = mass_b + atom_mass
    1406             :          END IF
    1407             :       END DO
    1408             : 
    1409             : ! choose a displacement
    1410         312 :       IF (ionode) rand = rng_stream%next()
    1411         312 :       CALL group%bcast(rand, source)
    1412             : 
    1413         312 :       dis_length = rmbond(molecule_type)*2.0E0_dp*(rand - 0.5E0_dp)
    1414             : 
    1415             : ! find the bond vector that atom a will be moving
    1416        1248 :       DO i = 1, 3
    1417             :          bond_a(i) = r_new(i, bond_list(bond_number)%a) - &
    1418         936 :                      r_new(i, bond_list(bond_number)%b)
    1419        1248 :          bond_b(i) = -bond_a(i)
    1420             :       END DO
    1421             : 
    1422             : ! notice we weight by the opposite masses...therefore lighter segments
    1423             : ! will move further
    1424        1248 :       old_length = SQRT(DOT_PRODUCT(bond_a, bond_a))
    1425         312 :       new_length_a = dis_length*mass_b/(mass_a + mass_b)
    1426         312 :       new_length_b = dis_length*mass_a/(mass_a + mass_b)
    1427             : 
    1428        1248 :       DO i = 1, 3
    1429         936 :          bond_a(i) = bond_a(i)/old_length*new_length_a
    1430        1248 :          bond_b(i) = bond_b(i)/old_length*new_length_b
    1431             :       END DO
    1432             : 
    1433        1248 :       DO iatom = 1, natom
    1434        1248 :          IF (atom_a(iatom) == 1) THEN
    1435         624 :             r_new(1, iatom) = r_new(1, iatom) + bond_a(1)
    1436         624 :             r_new(2, iatom) = r_new(2, iatom) + bond_a(2)
    1437         624 :             r_new(3, iatom) = r_new(3, iatom) + bond_a(3)
    1438             :          ELSE
    1439         312 :             r_new(1, iatom) = r_new(1, iatom) + bond_b(1)
    1440         312 :             r_new(2, iatom) = r_new(2, iatom) + bond_b(2)
    1441         312 :             r_new(3, iatom) = r_new(3, iatom) + bond_b(3)
    1442             :          END IF
    1443             :       END DO
    1444             : 
    1445             : ! correct the value of dis_length for the acceptance rule
    1446         312 :       dis_length = (old_length + dis_length)/old_length
    1447             : 
    1448         312 :       DEALLOCATE (connection)
    1449         312 :       DEALLOCATE (connectivity)
    1450         312 :       DEALLOCATE (counter)
    1451         312 :       DEALLOCATE (atom_a)
    1452         312 :       DEALLOCATE (atom_b)
    1453             : ! end the timing
    1454         312 :       CALL timestop(handle)
    1455             : 
    1456         624 :    END SUBROUTINE change_bond_length
    1457             : 
    1458             : ! **************************************************************************************************
    1459             : !> \brief Alters the magnitude of a random angle in a molecule centered on atom C
    1460             : !>      (connected to atoms A and B).  Atoms A and B are moved amounts related
    1461             : !>      to their masses (and masses of all connecting atoms), so that heavier
    1462             : !>      segments are moved less.
    1463             : !> \param r_old the initial coordinates of all molecules in the system
    1464             : !> \param r_new the new coordinates of all molecules in the system
    1465             : !> \param mc_par the mc parameters for the force env
    1466             : !> \param molecule_type the type of molecule we're playing with
    1467             : !> \param molecule_kind the structure containing the molecule information
    1468             : !> \param particles the particle_list_type for all particles in the force_env...
    1469             : !>             used to grab the mass of each atom
    1470             : !> \param rng_stream the random number stream that we draw from
    1471             : !> \author MJM
    1472             : ! **************************************************************************************************
    1473         194 :    SUBROUTINE change_bond_angle(r_old, r_new, mc_par, molecule_type, molecule_kind, &
    1474             :                                 particles, rng_stream)
    1475             : 
    1476             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: r_old
    1477             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT)        :: r_new
    1478             :       TYPE(mc_simpar_type), POINTER                      :: mc_par
    1479             :       INTEGER, INTENT(IN)                                :: molecule_type
    1480             :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind
    1481             :       TYPE(particle_list_type), POINTER                  :: particles
    1482             :       TYPE(rng_stream_type), INTENT(INOUT)               :: rng_stream
    1483             : 
    1484             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'change_bond_angle'
    1485             : 
    1486             :       INTEGER                                            :: bend_number, handle, i, iatom, ibond, &
    1487             :                                                             ipart, natom, nbend, nbond, source
    1488         194 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_a, atom_c, counter
    1489         194 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: connection, connectivity
    1490         194 :       INTEGER, DIMENSION(:), POINTER                     :: nunits
    1491             :       LOGICAL                                            :: ionode
    1492         194 :       REAL(dp), DIMENSION(:), POINTER                    :: rmangle
    1493             :       REAL(KIND=dp) :: atom_mass, bis_length, dis_angle, dis_angle_a, dis_angle_c, mass_a, mass_c, &
    1494             :          new_angle_a, new_angle_c, old_angle, old_length_a, old_length_c, rand, temp_length
    1495             :       REAL(KIND=dp), DIMENSION(1:3)                      :: bisector, bond_a, bond_c, cross_prod, &
    1496             :                                                             cross_prod_plane, temp
    1497         194 :       TYPE(bend_type), DIMENSION(:), POINTER             :: bend_list
    1498         194 :       TYPE(bond_type), DIMENSION(:), POINTER             :: bond_list
    1499             :       TYPE(mc_molecule_info_type), POINTER               :: mc_molecule_info
    1500             :       TYPE(mp_comm_type)                                 :: group
    1501             : 
    1502             : ! begin the timing of the subroutine
    1503             : 
    1504         194 :       CALL timeset(routineN, handle)
    1505             : 
    1506         194 :       NULLIFY (bend_list, bond_list, rmangle, mc_molecule_info)
    1507             : 
    1508             : ! get some stuff from mc_par
    1509             :       CALL get_mc_par(mc_par, rmangle=rmangle, source=source, &
    1510         194 :                       group=group, ionode=ionode, mc_molecule_info=mc_molecule_info)
    1511         194 :       CALL get_mc_molecule_info(mc_molecule_info, nunits=nunits)
    1512             : 
    1513             : ! copy the incoming coordinates so we can change them
    1514         776 :       DO ipart = 1, nunits(molecule_type)
    1515        2522 :          r_new(1:3, ipart) = r_old(1:3, ipart)
    1516             :       END DO
    1517             : 
    1518             : ! pick which bond in the molecule at random
    1519         194 :       IF (ionode) THEN
    1520          97 :          rand = rng_stream%next()
    1521             :       END IF
    1522         194 :       CALL group%bcast(rand, source)
    1523             :       CALL get_molecule_kind(molecule_kind, natom=natom, nbend=nbend, &
    1524         194 :                              bend_list=bend_list, bond_list=bond_list, nbond=nbond)
    1525         194 :       bend_number = CEILING(rand*REAL(nbend, dp))
    1526             : 
    1527         582 :       ALLOCATE (connection(1:natom, 1:2))
    1528             : ! assume at most six bonds per atom
    1529         582 :       ALLOCATE (connectivity(1:6, 1:natom))
    1530         582 :       ALLOCATE (counter(1:natom))
    1531         388 :       ALLOCATE (atom_a(1:natom))
    1532         388 :       ALLOCATE (atom_c(1:natom))
    1533        1746 :       connection(:, :) = 0
    1534        4268 :       connectivity(:, :) = 0
    1535         776 :       counter(:) = 0
    1536         776 :       atom_a(:) = 0
    1537         776 :       atom_c(:) = 0
    1538             : 
    1539             : ! now we need to find a list of atoms that each atom in this bond is connected
    1540             : ! to
    1541         776 :       DO iatom = 1, natom
    1542        1940 :          DO ibond = 1, nbond
    1543        1746 :             IF (bond_list(ibond)%a == iatom) THEN
    1544         388 :                counter(iatom) = counter(iatom) + 1
    1545         388 :                connectivity(counter(iatom), iatom) = bond_list(ibond)%b
    1546         776 :             ELSEIF (bond_list(ibond)%b == iatom) THEN
    1547         388 :                counter(iatom) = counter(iatom) + 1
    1548         388 :                connectivity(counter(iatom), iatom) = bond_list(ibond)%a
    1549             :             END IF
    1550             :          END DO
    1551             :       END DO
    1552             : 
    1553             : ! now I need to do a depth first search to figure out which atoms are on atom a's
    1554             : ! side and which are on atom c's
    1555         776 :       atom_a(:) = 0
    1556         194 :       atom_a(bend_list(bend_number)%a) = 1
    1557             :       CALL depth_first_search(bend_list(bend_number)%a, bend_list(bend_number)%b, &
    1558         194 :                               connectivity(:, :), atom_a(:))
    1559         776 :       atom_c(:) = 0
    1560         194 :       atom_c(bend_list(bend_number)%c) = 1
    1561             :       CALL depth_first_search(bend_list(bend_number)%c, bend_list(bend_number)%b, &
    1562         194 :                               connectivity(:, :), atom_c(:))
    1563             : 
    1564             : ! now figure out the masses of the various sides, so we can weight how far we move each
    1565             : ! group of atoms
    1566         194 :       mass_a = 0.0_dp
    1567         194 :       mass_c = 0.0_dp
    1568         776 :       DO iatom = 1, natom
    1569             :          CALL get_atomic_kind(particles%els(iatom)%atomic_kind, &
    1570         582 :                               mass=atom_mass)
    1571         582 :          IF (atom_a(iatom) == 1) mass_a = mass_a + atom_mass
    1572        1358 :          IF (atom_c(iatom) == 1) mass_c = mass_c + atom_mass
    1573             :       END DO
    1574             : 
    1575             : ! choose a displacement
    1576         194 :       IF (ionode) rand = rng_stream%next()
    1577         194 :       CALL group%bcast(rand, source)
    1578             : 
    1579         194 :       dis_angle = rmangle(molecule_type)*2.0E0_dp*(rand - 0.5E0_dp)
    1580             : 
    1581             : ! need to find the A-B-C bisector
    1582             : 
    1583             : ! this going to be tough...we need to find the plane of the A-B-C bond and only shift
    1584             : ! that component for all atoms connected to A and C...otherwise we change other
    1585             : ! internal degrees of freedom
    1586             : 
    1587             : ! find the bond vectors
    1588         776 :       DO i = 1, 3
    1589             :          bond_a(i) = r_new(i, bend_list(bend_number)%a) - &
    1590         582 :                      r_new(i, bend_list(bend_number)%b)
    1591             :          bond_c(i) = r_new(i, bend_list(bend_number)%c) - &
    1592         776 :                      r_new(i, bend_list(bend_number)%b)
    1593             :       END DO
    1594         776 :       old_length_a = SQRT(DOT_PRODUCT(bond_a, bond_a))
    1595         776 :       old_length_c = SQRT(DOT_PRODUCT(bond_c, bond_c))
    1596         776 :       old_angle = ACOS(DOT_PRODUCT(bond_a, bond_c)/(old_length_a*old_length_c))
    1597             : 
    1598         776 :       DO i = 1, 3
    1599             :          bisector(i) = bond_a(i)/old_length_a + & ! not yet normalized
    1600         776 :                        bond_c(i)/old_length_c
    1601             :       END DO
    1602         776 :       bis_length = SQRT(DOT_PRODUCT(bisector, bisector))
    1603         776 :       bisector(1:3) = bisector(1:3)/bis_length
    1604             : 
    1605             : ! now we need to find the cross product of the B-A and B-C vectors and normalize
    1606             : ! it, so we have a vector that defines the bend plane
    1607         194 :       cross_prod(1) = bond_a(2)*bond_c(3) - bond_a(3)*bond_c(2)
    1608         194 :       cross_prod(2) = bond_a(3)*bond_c(1) - bond_a(1)*bond_c(3)
    1609         194 :       cross_prod(3) = bond_a(1)*bond_c(2) - bond_a(2)*bond_c(1)
    1610        1358 :       cross_prod(1:3) = cross_prod(1:3)/SQRT(DOT_PRODUCT(cross_prod, cross_prod))
    1611             : 
    1612             : ! we have two axis of a coordinate system...let's get the third
    1613         194 :       cross_prod_plane(1) = cross_prod(2)*bisector(3) - cross_prod(3)*bisector(2)
    1614         194 :       cross_prod_plane(2) = cross_prod(3)*bisector(1) - cross_prod(1)*bisector(3)
    1615         194 :       cross_prod_plane(3) = cross_prod(1)*bisector(2) - cross_prod(2)*bisector(1)
    1616             :       cross_prod_plane(1:3) = cross_prod_plane(1:3)/ &
    1617        1358 :                               SQRT(DOT_PRODUCT(cross_prod_plane, cross_prod_plane))
    1618             : 
    1619             : ! now bisector is x, cross_prod_plane is the y vector (pointing towards c),
    1620             : ! and cross_prod is z
    1621             : ! shift the molecule so that atom b is at the origin
    1622         776 :       DO iatom = 1, natom
    1623             :          r_new(1:3, iatom) = r_new(1:3, iatom) - &
    1624        2522 :                              r_old(1:3, bend_list(bend_number)%b)
    1625             :       END DO
    1626             : 
    1627             : ! figure out how much we move each side, since we're mass-weighting, by the
    1628             : ! opposite masses, so lighter moves farther..this angle is the angle between
    1629             : ! the bond vector BA or BC and the bisector
    1630         194 :       dis_angle_a = dis_angle*mass_c/(mass_a + mass_c)
    1631         194 :       dis_angle_c = dis_angle*mass_a/(mass_a + mass_c)
    1632             : 
    1633             : ! now loop through all the atoms, moving the ones that are connected to a or c
    1634         776 :       DO iatom = 1, natom
    1635             : ! subtract out the z component (perpendicular to the angle plane)
    1636             :          temp(1:3) = r_new(1:3, iatom) - &
    1637             :                      DOT_PRODUCT(cross_prod(1:3), r_new(1:3, iatom))* &
    1638        4074 :                      cross_prod(1:3)
    1639        2328 :          temp_length = SQRT(DOT_PRODUCT(temp, temp))
    1640             : 
    1641             : ! we can now compute all three components of the new bond vector along the
    1642             : ! axis defined above
    1643         776 :          IF (atom_a(iatom) == 1) THEN
    1644             : 
    1645             : ! if the y-coordinate is less than zero, we need to switch the sign when we make the vector,
    1646             : ! as the angle computed by the dot product can't distinguish between that
    1647         776 :             IF (DOT_PRODUCT(cross_prod_plane(1:3), r_new(1:3, iatom)) &
    1648             :                 .LT. 0.0_dp) THEN
    1649             : 
    1650             : ! need to figure out the current iatom-B-bisector angle, so we know what the new angle is
    1651             :                new_angle_a = ACOS(DOT_PRODUCT(bisector, temp(1:3))/ &
    1652         776 :                                   (temp_length)) + dis_angle_a
    1653             : 
    1654             :                r_new(1:3, iatom) = COS(new_angle_a)*temp_length*bisector(1:3) - &
    1655             :                                    SIN(new_angle_a)*temp_length*cross_prod_plane(1:3) + &
    1656             :                                    DOT_PRODUCT(cross_prod(1:3), r_new(1:3, iatom))* &
    1657        1358 :                                    cross_prod(1:3)
    1658             :             ELSE
    1659             : 
    1660             : ! need to figure out the current iatom-B-bisector angle, so we know what the new angle is
    1661             :                new_angle_a = ACOS(DOT_PRODUCT(bisector, temp(1:3))/ &
    1662           0 :                                   (temp_length)) - dis_angle_a
    1663             : 
    1664             :                r_new(1:3, iatom) = COS(new_angle_a)*temp_length*bisector(1:3) + &
    1665             :                                    SIN(new_angle_a)*temp_length*cross_prod_plane(1:3) + &
    1666             :                                    DOT_PRODUCT(cross_prod(1:3), r_new(1:3, iatom))* &
    1667           0 :                                    cross_prod(1:3)
    1668             :             END IF
    1669             : 
    1670         388 :          ELSEIF (atom_c(iatom) == 1) THEN
    1671             : 
    1672             : ! if the y-coordinate is less than zero, we need to switch the sign when we make the vector,
    1673             : ! as the angle computed by the dot product can't distinguish between that
    1674         776 :             IF (DOT_PRODUCT(cross_prod_plane(1:3), r_new(1:3, iatom)) &
    1675             :                 .LT. 0.0_dp) THEN
    1676             : ! need to figure out the current iatom-B-bisector angle, so we know what the new angle is
    1677             :                new_angle_c = ACOS(DOT_PRODUCT(bisector(1:3), temp(1:3))/ &
    1678           0 :                                   (temp_length)) - dis_angle_c
    1679             : 
    1680             :                r_new(1:3, iatom) = COS(new_angle_c)*temp_length*bisector(1:3) - &
    1681             :                                    SIN(new_angle_c)*temp_length*cross_prod_plane(1:3) + &
    1682             :                                    DOT_PRODUCT(cross_prod(1:3), r_new(1:3, iatom))* &
    1683           0 :                                    cross_prod(1:3)
    1684             :             ELSE
    1685             :                new_angle_c = ACOS(DOT_PRODUCT(bisector(1:3), temp(1:3))/ &
    1686         776 :                                   (temp_length)) + dis_angle_c
    1687             : 
    1688             :                r_new(1:3, iatom) = COS(new_angle_c)*temp_length*bisector(1:3) + &
    1689             :                                    SIN(new_angle_c)*temp_length*cross_prod_plane(1:3) + &
    1690             :                                    DOT_PRODUCT(cross_prod(1:3), r_new(1:3, iatom))* &
    1691        1358 :                                    cross_prod(1:3)
    1692             :             END IF
    1693             :          END IF
    1694             : 
    1695             :       END DO
    1696             : 
    1697         776 :       DO iatom = 1, natom
    1698             :          r_new(1:3, iatom) = r_new(1:3, iatom) + &
    1699        2522 :                              r_old(1:3, bend_list(bend_number)%b)
    1700             :       END DO
    1701             : 
    1702             : ! deallocate some stuff
    1703         194 :       DEALLOCATE (connection)
    1704         194 :       DEALLOCATE (connectivity)
    1705         194 :       DEALLOCATE (counter)
    1706         194 :       DEALLOCATE (atom_a)
    1707         194 :       DEALLOCATE (atom_c)
    1708             : 
    1709             : ! end the timing
    1710         194 :       CALL timestop(handle)
    1711             : 
    1712         388 :    END SUBROUTINE change_bond_angle
    1713             : 
    1714             : ! **************************************************************************************************
    1715             : !> \brief Alters a dihedral (A-B-C-D) in the molecule so that all other internal
    1716             : !>      degrees of freedom remain the same.  If other dihedrals are centered
    1717             : !>      on B-C, they rotate as well to keep the relationship between the
    1718             : !>      dihedrals the same.  Atoms A and D are moved amounts related to their
    1719             : !>      masses (and masses of all connecting atoms), so that heavier segments
    1720             : !>      are moved less.  All atoms except B and C are rotated around the
    1721             : !>      B-C bond vector (B and C are not moved).
    1722             : !> \param r_old the initial coordinates of all molecules in the system
    1723             : !> \param r_new the new coordinates of all molecules in the system
    1724             : !> \param mc_par the mc parameters for the force env
    1725             : !> \param molecule_type the type of molecule we're playing with
    1726             : !> \param molecule_kind the structure containing the molecule information
    1727             : !> \param particles the particle_list_type for all particles in the force_env..
    1728             : !>             used to grab the mass of each atom
    1729             : !> \param rng_stream the random number stream that we draw from
    1730             : !> \author MJM
    1731             : ! **************************************************************************************************
    1732           0 :    SUBROUTINE change_dihedral(r_old, r_new, mc_par, molecule_type, molecule_kind, &
    1733             :                               particles, rng_stream)
    1734             : 
    1735             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: r_old
    1736             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT)        :: r_new
    1737             :       TYPE(mc_simpar_type), POINTER                      :: mc_par
    1738             :       INTEGER, INTENT(IN)                                :: molecule_type
    1739             :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind
    1740             :       TYPE(particle_list_type), POINTER                  :: particles
    1741             :       TYPE(rng_stream_type), INTENT(INOUT)               :: rng_stream
    1742             : 
    1743             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'change_dihedral'
    1744             : 
    1745             :       INTEGER                                            :: handle, i, iatom, ibond, ipart, natom, &
    1746             :                                                             nbond, ntorsion, source, torsion_number
    1747           0 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_a, atom_d, counter
    1748           0 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: connection, connectivity
    1749           0 :       INTEGER, DIMENSION(:), POINTER                     :: nunits
    1750             :       LOGICAL                                            :: ionode
    1751           0 :       REAL(dp), DIMENSION(:), POINTER                    :: rmdihedral
    1752             :       REAL(KIND=dp)                                      :: atom_mass, dis_angle, dis_angle_a, &
    1753             :                                                             dis_angle_d, mass_a, mass_d, &
    1754             :                                                             old_length_a, rand, u, v, w, x, y, z
    1755             :       REAL(KIND=dp), DIMENSION(1:3)                      :: bond_a, temp
    1756           0 :       TYPE(bond_type), DIMENSION(:), POINTER             :: bond_list
    1757             :       TYPE(mc_molecule_info_type), POINTER               :: mc_molecule_info
    1758             :       TYPE(mp_comm_type)                                 :: group
    1759           0 :       TYPE(torsion_type), DIMENSION(:), POINTER          :: torsion_list
    1760             : 
    1761             : ! begin the timing of the subroutine
    1762             : 
    1763           0 :       CALL timeset(routineN, handle)
    1764             : 
    1765           0 :       NULLIFY (rmdihedral, torsion_list, bond_list, mc_molecule_info)
    1766             : 
    1767             : ! get some stuff from mc_par
    1768             :       CALL get_mc_par(mc_par, rmdihedral=rmdihedral, &
    1769             :                       source=source, group=group, ionode=ionode, &
    1770           0 :                       mc_molecule_info=mc_molecule_info)
    1771           0 :       CALL get_mc_molecule_info(mc_molecule_info, nunits=nunits)
    1772             : 
    1773             : ! copy the incoming coordinates so we can change them
    1774           0 :       DO ipart = 1, nunits(molecule_type)
    1775           0 :          r_new(1:3, ipart) = r_old(1:3, ipart)
    1776             :       END DO
    1777             : 
    1778             : ! pick which bond in the molecule at random
    1779           0 :       IF (ionode) THEN
    1780           0 :          rand = rng_stream%next()
    1781             : !      CALL RANDOM_NUMBER(rand)
    1782             :       END IF
    1783           0 :       CALL group%bcast(rand, source)
    1784             :       CALL get_molecule_kind(molecule_kind, natom=natom, &
    1785             :                              bond_list=bond_list, nbond=nbond, &
    1786           0 :                              ntorsion=ntorsion, torsion_list=torsion_list)
    1787           0 :       torsion_number = CEILING(rand*REAL(ntorsion, dp))
    1788             : 
    1789           0 :       ALLOCATE (connection(1:natom, 1:2))
    1790             : ! assume at most six bonds per atom
    1791           0 :       ALLOCATE (connectivity(1:6, 1:natom))
    1792           0 :       ALLOCATE (counter(1:natom))
    1793           0 :       ALLOCATE (atom_a(1:natom))
    1794           0 :       ALLOCATE (atom_d(1:natom))
    1795           0 :       connection(:, :) = 0
    1796           0 :       connectivity(:, :) = 0
    1797           0 :       counter(:) = 0
    1798           0 :       atom_a(:) = 0
    1799           0 :       atom_d(:) = 0
    1800             : 
    1801             : ! now we need to find a list of atoms that each atom in this bond is connected
    1802             : ! to
    1803           0 :       DO iatom = 1, natom
    1804           0 :          DO ibond = 1, nbond
    1805           0 :             IF (bond_list(ibond)%a == iatom) THEN
    1806           0 :                counter(iatom) = counter(iatom) + 1
    1807           0 :                connectivity(counter(iatom), iatom) = bond_list(ibond)%b
    1808           0 :             ELSEIF (bond_list(ibond)%b == iatom) THEN
    1809           0 :                counter(iatom) = counter(iatom) + 1
    1810           0 :                connectivity(counter(iatom), iatom) = bond_list(ibond)%a
    1811             :             END IF
    1812             :          END DO
    1813             :       END DO
    1814             : 
    1815             : ! now I need to do a depth first search to figure out which atoms are on atom
    1816             : ! a's side and which are on atom d's, but remember we're moving all atoms on a's
    1817             : ! side of b, including atoms not in a's branch
    1818           0 :       atom_a(:) = 0
    1819           0 :       atom_a(torsion_list(torsion_number)%a) = 1
    1820             :       CALL depth_first_search(torsion_list(torsion_number)%b, &
    1821           0 :                               torsion_list(torsion_number)%c, connectivity(:, :), atom_a(:))
    1822           0 :       atom_d(:) = 0
    1823           0 :       atom_d(torsion_list(torsion_number)%d) = 1
    1824             :       CALL depth_first_search(torsion_list(torsion_number)%c, &
    1825           0 :                               torsion_list(torsion_number)%b, connectivity(:, :), atom_d(:))
    1826             : 
    1827             : ! now figure out the masses of the various sides, so we can weight how far we
    1828             : ! move each group of atoms
    1829           0 :       mass_a = 0.0_dp
    1830           0 :       mass_d = 0.0_dp
    1831           0 :       DO iatom = 1, natom
    1832             :          CALL get_atomic_kind(particles%els(iatom)%atomic_kind, &
    1833           0 :                               mass=atom_mass)
    1834           0 :          IF (atom_a(iatom) == 1) mass_a = mass_a + atom_mass
    1835           0 :          IF (atom_d(iatom) == 1) mass_d = mass_d + atom_mass
    1836             :       END DO
    1837             : 
    1838             : ! choose a displacement
    1839           0 :       IF (ionode) rand = rng_stream%next()
    1840           0 :       CALL group%bcast(rand, source)
    1841             : 
    1842           0 :       dis_angle = rmdihedral(molecule_type)*2.0E0_dp*(rand - 0.5E0_dp)
    1843             : 
    1844             : ! find the bond vectors, B-C, so we know what to rotate around
    1845           0 :       DO i = 1, 3
    1846             :          bond_a(i) = r_new(i, torsion_list(torsion_number)%c) - &
    1847           0 :                      r_new(i, torsion_list(torsion_number)%b)
    1848             :       END DO
    1849           0 :       old_length_a = SQRT(DOT_PRODUCT(bond_a, bond_a))
    1850           0 :       bond_a(1:3) = bond_a(1:3)/old_length_a
    1851             : 
    1852             : ! figure out how much we move each side, since we're mass-weighting, by the
    1853             : ! opposite masses, so lighter moves farther...we take the opposite sign of d
    1854             : ! so we're not rotating both angles in the same direction
    1855           0 :       dis_angle_a = dis_angle*mass_d/(mass_a + mass_d)
    1856           0 :       dis_angle_d = -dis_angle*mass_a/(mass_a + mass_d)
    1857             : 
    1858           0 :       DO iatom = 1, natom
    1859             : 
    1860           0 :          IF (atom_a(iatom) == 1) THEN
    1861             : ! shift the coords so b is at the origin
    1862             :             r_new(1:3, iatom) = r_new(1:3, iatom) - &
    1863           0 :                                 r_new(1:3, torsion_list(torsion_number)%b)
    1864             : 
    1865             : ! multiply by the rotation matrix
    1866           0 :             u = bond_a(1)
    1867           0 :             v = bond_a(2)
    1868           0 :             w = bond_a(3)
    1869           0 :             x = r_new(1, iatom)
    1870           0 :             y = r_new(2, iatom)
    1871           0 :             z = r_new(3, iatom)
    1872             :             temp(1) = (u*(u*x + v*y + w*z) + (x*(v**2 + w**2) - u*(v*y + w*z))*COS(dis_angle_a) + &
    1873           0 :                        SQRT(u**2 + v**2 + w**2)*(v*z - w*y)*SIN(dis_angle_a))/(u**2 + v**2 + w**2)
    1874             :             temp(2) = (v*(u*x + v*y + w*z) + (y*(u**2 + w**2) - v*(u*x + w*z))*COS(dis_angle_a) + &
    1875           0 :                        SQRT(u**2 + v**2 + w**2)*(w*x - u*z)*SIN(dis_angle_a))/(u**2 + v**2 + w**2)
    1876             :             temp(3) = (w*(u*x + v*y + w*z) + (z*(v**2 + u**2) - w*(u*x + v*y))*COS(dis_angle_a) + &
    1877           0 :                        SQRT(u**2 + v**2 + w**2)*(u*y - v*x)*SIN(dis_angle_a))/(u**2 + v**2 + w**2)
    1878             : 
    1879             : ! shift back to the original position
    1880           0 :             temp(1:3) = temp(1:3) + r_new(1:3, torsion_list(torsion_number)%b)
    1881           0 :             r_new(1:3, iatom) = temp(1:3)
    1882             : 
    1883           0 :          ELSEIF (atom_d(iatom) == 1) THEN
    1884             : 
    1885             : ! shift the coords so c is at the origin
    1886             :             r_new(1:3, iatom) = r_new(1:3, iatom) - &
    1887           0 :                                 r_new(1:3, torsion_list(torsion_number)%c)
    1888             : 
    1889             : ! multiply by the rotation matrix
    1890           0 :             u = bond_a(1)
    1891           0 :             v = bond_a(2)
    1892           0 :             w = bond_a(3)
    1893           0 :             x = r_new(1, iatom)
    1894           0 :             y = r_new(2, iatom)
    1895           0 :             z = r_new(3, iatom)
    1896             :             temp(1) = (u*(u*x + v*y + w*z) + (x*(v**2 + w**2) - u*(v*y + w*z))*COS(dis_angle_d) + &
    1897           0 :                        SQRT(u**2 + v**2 + w**2)*(v*z - w*y)*SIN(dis_angle_d))/(u**2 + v**2 + w**2)
    1898             :             temp(2) = (v*(u*x + v*y + w*z) + (y*(u**2 + w**2) - v*(u*x + w*z))*COS(dis_angle_d) + &
    1899           0 :                        SQRT(u**2 + v**2 + w**2)*(w*x - u*z)*SIN(dis_angle_d))/(u**2 + v**2 + w**2)
    1900             :             temp(3) = (w*(u*x + v*y + w*z) + (z*(v**2 + u**2) - w*(u*x + v*y))*COS(dis_angle_d) + &
    1901           0 :                        SQRT(u**2 + v**2 + w**2)*(u*y - v*x)*SIN(dis_angle_d))/(u**2 + v**2 + w**2)
    1902             : 
    1903             : ! shift back to the original position
    1904           0 :             temp(1:3) = temp(1:3) + r_new(1:3, torsion_list(torsion_number)%c)
    1905           0 :             r_new(1:3, iatom) = temp(1:3)
    1906             :          END IF
    1907             :       END DO
    1908             : 
    1909             : ! deallocate some stuff
    1910           0 :       DEALLOCATE (connection)
    1911           0 :       DEALLOCATE (connectivity)
    1912           0 :       DEALLOCATE (counter)
    1913           0 :       DEALLOCATE (atom_a)
    1914           0 :       DEALLOCATE (atom_d)
    1915             : 
    1916             : ! end the timing
    1917           0 :       CALL timestop(handle)
    1918             : 
    1919           0 :    END SUBROUTINE change_dihedral
    1920             : 
    1921             : ! **************************************************************************************************
    1922             : !> \brief performs either a bond or angle change move for a given molecule
    1923             : !> \param mc_par the mc parameters for the force env
    1924             : !> \param force_env the force environment used in the move
    1925             : !> \param bias_env the force environment used to bias the move, if any (it may
    1926             : !>            be null if lbias=.false. in mc_par)
    1927             : !> \param moves the structure that keeps track of how many moves have been
    1928             : !>               accepted/rejected
    1929             : !> \param energy_check the running energy difference between now and the initial
    1930             : !>        energy
    1931             : !> \param r_old the coordinates of force_env before the move
    1932             : !> \param old_energy the energy of the force_env before the move
    1933             : !> \param start_atom_swap the number of the swap molecule's first atom, assuming the rest of
    1934             : !>        the atoms follow sequentially
    1935             : !> \param target_atom the number of the target atom for swapping
    1936             : !> \param molecule_type the molecule type for the atom we're swapping
    1937             : !> \param box_number the number of the box we're doing this move in
    1938             : !> \param bias_energy_old the biased energy of the system before the move
    1939             : !> \param last_bias_energy the last biased energy of the system
    1940             : !> \param move_type dictates if we're moving to an "in" or "out" region
    1941             : !> \param rng_stream the random number stream that we draw from
    1942             : !> \author MJM
    1943             : !> \note     Designed for parallel.
    1944             : ! **************************************************************************************************
    1945           0 :    SUBROUTINE mc_avbmc_move(mc_par, force_env, bias_env, moves, &
    1946           0 :                             energy_check, r_old, old_energy, start_atom_swap, &
    1947             :                             target_atom, &
    1948             :                             molecule_type, box_number, bias_energy_old, last_bias_energy, &
    1949             :                             move_type, rng_stream)
    1950             : 
    1951             :       TYPE(mc_simpar_type), POINTER                      :: mc_par
    1952             :       TYPE(force_env_type), POINTER                      :: force_env, bias_env
    1953             :       TYPE(mc_moves_type), POINTER                       :: moves
    1954             :       REAL(KIND=dp), INTENT(INOUT)                       :: energy_check
    1955             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT)      :: r_old
    1956             :       REAL(KIND=dp), INTENT(INOUT)                       :: old_energy
    1957             :       INTEGER, INTENT(IN)                                :: start_atom_swap, target_atom, &
    1958             :                                                             molecule_type, box_number
    1959             :       REAL(KIND=dp), INTENT(INOUT)                       :: bias_energy_old, last_bias_energy
    1960             :       CHARACTER(LEN=*), INTENT(IN)                       :: move_type
    1961             :       TYPE(rng_stream_type), INTENT(INOUT)               :: rng_stream
    1962             : 
    1963             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'mc_avbmc_move'
    1964             : 
    1965             :       INTEGER                                            :: end_mol, handle, ipart, jbox, natom, &
    1966             :                                                             nswapmoves, source, start_mol
    1967           0 :       INTEGER, DIMENSION(:), POINTER                     :: avbmc_atom, mol_type, nunits, nunits_tot
    1968           0 :       INTEGER, DIMENSION(:, :), POINTER                  :: nchains
    1969             :       LOGICAL                                            :: ionode, lbias, ldum, lin, loverlap
    1970           0 :       REAL(dp), DIMENSION(:), POINTER                    :: avbmc_rmax, avbmc_rmin, pbias
    1971           0 :       REAL(dp), DIMENSION(:, :), POINTER                 :: mass
    1972             :       REAL(KIND=dp) :: BETA, bias_energy_new, del_quickstep_energy, distance, exp_max_val, &
    1973             :          exp_min_val, max_val, min_val, new_energy, prefactor, rand, rdum, volume_in, volume_out, &
    1974             :          w, weight_new, weight_old
    1975           0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: r_new
    1976             :       REAL(KIND=dp), DIMENSION(1:3)                      :: abc, RIJ
    1977             :       TYPE(cell_type), POINTER                           :: cell
    1978             :       TYPE(cp_subsys_type), POINTER                      :: subsys, subsys_force
    1979             :       TYPE(mc_molecule_info_type), POINTER               :: mc_molecule_info
    1980             :       TYPE(molecule_kind_list_type), POINTER             :: molecule_kinds
    1981             :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind
    1982             :       TYPE(mp_comm_type)                                 :: group
    1983             :       TYPE(particle_list_type), POINTER                  :: particles, particles_force
    1984             : 
    1985           0 :       rdum = 1.0_dp
    1986             : 
    1987             : ! begin the timing of the subroutine
    1988           0 :       CALL timeset(routineN, handle)
    1989             : 
    1990             : ! get a bunch of stuff from mc_par
    1991             :       CALL get_mc_par(mc_par, lbias=lbias, &
    1992             :                       BETA=BETA, max_val=max_val, min_val=min_val, exp_max_val=exp_max_val, &
    1993             :                       exp_min_val=exp_min_val, avbmc_atom=avbmc_atom, &
    1994             :                       avbmc_rmin=avbmc_rmin, avbmc_rmax=avbmc_rmax, &
    1995             :                       nswapmoves=nswapmoves, ionode=ionode, source=source, &
    1996           0 :                       group=group, pbias=pbias, mc_molecule_info=mc_molecule_info)
    1997             :       CALL get_mc_molecule_info(mc_molecule_info, nchains=nchains, &
    1998           0 :                                 mass=mass, nunits=nunits, nunits_tot=nunits_tot, mol_type=mol_type)
    1999             : ! figure out some bounds for mol_type
    2000           0 :       start_mol = 1
    2001           0 :       DO jbox = 1, box_number - 1
    2002           0 :          start_mol = start_mol + SUM(nchains(:, jbox))
    2003             :       END DO
    2004           0 :       end_mol = start_mol + SUM(nchains(:, box_number)) - 1
    2005             : 
    2006             : ! nullify some pointers
    2007           0 :       NULLIFY (particles, subsys, molecule_kinds, molecule_kind, &
    2008           0 :                particles_force, subsys_force)
    2009             : 
    2010             : ! do some allocation
    2011           0 :       ALLOCATE (r_new(1:3, 1:nunits_tot(box_number)))
    2012             : 
    2013             : ! now we need to grab and save coordinates, in case we reject
    2014             : ! are we biasing this move?
    2015           0 :       IF (lbias) THEN
    2016             : 
    2017             : ! grab the coordinates
    2018           0 :          CALL force_env_get(bias_env, cell=cell, subsys=subsys)
    2019             :          CALL cp_subsys_get(subsys, &
    2020           0 :                             particles=particles, molecule_kinds=molecule_kinds)
    2021           0 :          molecule_kind => molecule_kinds%els(1)
    2022           0 :          CALL get_molecule_kind(molecule_kind, natom=natom)
    2023           0 :          CALL get_cell(cell, abc=abc)
    2024             : 
    2025             : ! save the energy
    2026             : !         bias_energy_old=bias_energy
    2027             : 
    2028             :       ELSE
    2029             : 
    2030             : ! grab the coordinates
    2031           0 :          CALL force_env_get(force_env, cell=cell, subsys=subsys)
    2032             :          CALL cp_subsys_get(subsys, &
    2033           0 :                             particles=particles, molecule_kinds=molecule_kinds)
    2034           0 :          molecule_kind => molecule_kinds%els(1)
    2035           0 :          CALL get_molecule_kind(molecule_kind, natom=natom)
    2036           0 :          CALL get_cell(cell, abc=abc)
    2037             : 
    2038             :       END IF
    2039             : 
    2040             : ! let's determine if the molecule to be moved is in the "in" region or the
    2041             : ! "out" region of the target
    2042             :       RIJ(1) = particles%els(start_atom_swap + avbmc_atom(molecule_type) - 1)%r(1) - &
    2043             :                particles%els(target_atom)%r(1) - abc(1)*ANINT( &
    2044             :                (particles%els(start_atom_swap + avbmc_atom(molecule_type) - 1)%r(1) - &
    2045           0 :                 particles%els(target_atom)%r(1))/abc(1))
    2046             :       RIJ(2) = particles%els(start_atom_swap + avbmc_atom(molecule_type) - 1)%r(2) - &
    2047             :                particles%els(target_atom)%r(2) - abc(2)*ANINT( &
    2048             :                (particles%els(start_atom_swap + avbmc_atom(molecule_type) - 1)%r(2) - &
    2049           0 :                 particles%els(target_atom)%r(2))/abc(2))
    2050             :       RIJ(3) = particles%els(start_atom_swap + avbmc_atom(molecule_type) - 1)%r(3) - &
    2051             :                particles%els(target_atom)%r(3) - abc(3)*ANINT( &
    2052             :                (particles%els(start_atom_swap + avbmc_atom(molecule_type) - 1)%r(3) - &
    2053           0 :                 particles%els(target_atom)%r(3))/abc(3))
    2054           0 :       distance = SQRT(RIJ(1)**2 + RIJ(2)**2 + RIJ(3)**2)
    2055           0 :       IF (distance .LE. avbmc_rmax(molecule_type) .AND. distance .GE. avbmc_rmin(molecule_type)) THEN
    2056             :          lin = .TRUE.
    2057             :       ELSE
    2058             :          lin = .FALSE.
    2059             :       END IF
    2060             : 
    2061             : ! increment the counter of the particular move we've done
    2062             : !     swapping into the "in" region of mol_target
    2063             :       IF (lin) THEN
    2064           0 :          IF (move_type == 'in') THEN
    2065             :             moves%avbmc_inin%attempts = &
    2066           0 :                moves%avbmc_inin%attempts + 1
    2067             :          ELSE
    2068             :             moves%avbmc_inout%attempts = &
    2069           0 :                moves%avbmc_inout%attempts + 1
    2070             :          END IF
    2071             :       ELSE
    2072           0 :          IF (move_type == 'in') THEN
    2073             :             moves%avbmc_outin%attempts = &
    2074           0 :                moves%avbmc_outin%attempts + 1
    2075             :          ELSE
    2076             :             moves%avbmc_outout%attempts = &
    2077           0 :                moves%avbmc_outout%attempts + 1
    2078             :          END IF
    2079             :       END IF
    2080             : 
    2081           0 :       IF (lbias) THEN
    2082             : 
    2083           0 :          IF (move_type == 'in') THEN
    2084             : 
    2085             : ! do CBMC for the old config
    2086             :             CALL generate_cbmc_swap_config(bias_env, BETA, max_val, min_val, exp_max_val, &
    2087             :                                            exp_min_val, nswapmoves, &
    2088             :                                            weight_old, start_atom_swap, nunits_tot(box_number), nunits, nunits(molecule_type), &
    2089             :                                            mass(:, molecule_type), ldum, rdum, &
    2090             :                                            bias_energy_old, ionode, .TRUE., mol_type(start_mol:end_mol), nchains(:, box_number), &
    2091             :                                            source, group, rng_stream, &
    2092             :                                            avbmc_atom=avbmc_atom(molecule_type), &
    2093             :                                            rmin=avbmc_rmin(molecule_type), rmax=avbmc_rmax(molecule_type), move_type='out', &
    2094           0 :                                            target_atom=target_atom)
    2095             : 
    2096             :          ELSE
    2097             : 
    2098             : ! do CBMC for the old config
    2099             :             CALL generate_cbmc_swap_config(bias_env, BETA, max_val, min_val, exp_max_val, &
    2100             :                                            exp_min_val, nswapmoves, &
    2101             :                                            weight_old, start_atom_swap, nunits_tot(box_number), nunits, nunits(molecule_type), &
    2102             :                                            mass(:, molecule_type), ldum, rdum, &
    2103             :                                            bias_energy_old, ionode, .TRUE., mol_type(start_mol:end_mol), nchains(:, box_number), &
    2104             :                                            source, group, rng_stream, &
    2105             :                                            avbmc_atom=avbmc_atom(molecule_type), &
    2106             :                                            rmin=avbmc_rmin(molecule_type), rmax=avbmc_rmax(molecule_type), move_type='in', &
    2107           0 :                                            target_atom=target_atom)
    2108             : 
    2109             :          END IF
    2110             : 
    2111             : ! generate the new config
    2112             :          CALL generate_cbmc_swap_config(bias_env, BETA, max_val, min_val, exp_max_val, &
    2113             :                                         exp_min_val, nswapmoves, &
    2114             :                                         weight_new, start_atom_swap, nunits_tot(box_number), nunits, nunits(molecule_type), &
    2115             :                                         mass(:, molecule_type), loverlap, bias_energy_new, &
    2116             :                                         bias_energy_old, ionode, .FALSE., mol_type(start_mol:end_mol), nchains(:, box_number), &
    2117             :                                         source, group, rng_stream, &
    2118             :                                         avbmc_atom=avbmc_atom(molecule_type), &
    2119             :                                         rmin=avbmc_rmin(molecule_type), rmax=avbmc_rmax(molecule_type), move_type=move_type, &
    2120           0 :                                         target_atom=target_atom)
    2121             : 
    2122             : ! the energy that comes out of the above routine is the difference...we want
    2123             : ! the real energy for the acceptance rule...we don't do this for the
    2124             : ! lbias=.false. case because it doesn't appear in the acceptance rule, and
    2125             : ! we compensate in case of acceptance
    2126           0 :          bias_energy_new = bias_energy_new + bias_energy_old
    2127             : 
    2128             :       ELSE
    2129             : 
    2130           0 :          IF (move_type == 'in') THEN
    2131             : 
    2132             : ! find the weight of the old config
    2133             :             CALL generate_cbmc_swap_config(force_env, BETA, max_val, min_val, exp_max_val, &
    2134             :                                            exp_min_val, nswapmoves, &
    2135             :                                            weight_old, start_atom_swap, nunits_tot(box_number), nunits, nunits(molecule_type), &
    2136             :                                            mass(:, molecule_type), ldum, rdum, old_energy, &
    2137             :                                            ionode, .TRUE., mol_type(start_mol:end_mol), nchains(:, box_number), &
    2138             :                                            source, group, rng_stream, &
    2139             :                                            avbmc_atom=avbmc_atom(molecule_type), &
    2140             :                                            rmin=avbmc_rmin(molecule_type), rmax=avbmc_rmax(molecule_type), move_type='out', &
    2141           0 :                                            target_atom=target_atom)
    2142             : 
    2143             :          ELSE
    2144             : 
    2145             : ! find the weight of the old config
    2146             :             CALL generate_cbmc_swap_config(force_env, BETA, max_val, min_val, exp_max_val, &
    2147             :                                            exp_min_val, nswapmoves, &
    2148             :                                            weight_old, start_atom_swap, nunits_tot(box_number), nunits, nunits(molecule_type), &
    2149             :                                            mass(:, molecule_type), ldum, rdum, old_energy, &
    2150             :                                            ionode, .TRUE., mol_type(start_mol:end_mol), nchains(:, box_number), &
    2151             :                                            source, group, rng_stream, &
    2152             :                                            avbmc_atom=avbmc_atom(molecule_type), &
    2153             :                                            rmin=avbmc_rmin(molecule_type), rmax=avbmc_rmax(molecule_type), move_type='in', &
    2154           0 :                                            target_atom=target_atom)
    2155             : 
    2156             :          END IF
    2157             : 
    2158             :          ! generate the new config...do this after, because it changes the force_env
    2159             :          CALL generate_cbmc_swap_config(force_env, BETA, max_val, min_val, exp_max_val, &
    2160             :                                         exp_min_val, nswapmoves, &
    2161             :                                         weight_new, start_atom_swap, nunits_tot(box_number), nunits, nunits(molecule_type), &
    2162             :                                         mass(:, molecule_type), loverlap, new_energy, old_energy, &
    2163             :                                         ionode, .FALSE., mol_type(start_mol:end_mol), nchains(:, box_number), &
    2164             :                                         source, group, rng_stream, &
    2165             :                                         avbmc_atom=avbmc_atom(molecule_type), &
    2166             :                                         rmin=avbmc_rmin(molecule_type), rmax=avbmc_rmax(molecule_type), move_type=move_type, &
    2167           0 :                                         target_atom=target_atom)
    2168             : 
    2169             :       END IF
    2170             : 
    2171           0 :       IF (loverlap) THEN
    2172           0 :          DEALLOCATE (r_new)
    2173             : 
    2174             : ! need to reset the old coordinates
    2175           0 :          IF (lbias) THEN
    2176           0 :             CALL force_env_get(bias_env, subsys=subsys)
    2177           0 :             CALL cp_subsys_get(subsys, particles=particles)
    2178             :          ELSE
    2179           0 :             CALL force_env_get(force_env, subsys=subsys)
    2180           0 :             CALL cp_subsys_get(subsys, particles=particles)
    2181             :          END IF
    2182           0 :          DO ipart = 1, nunits_tot(box_number)
    2183           0 :             particles%els(ipart)%r(1:3) = r_old(1:3, ipart)
    2184             :          END DO
    2185             : 
    2186           0 :          CALL timestop(handle)
    2187             : 
    2188             :          RETURN
    2189             :       END IF
    2190             : 
    2191             : ! if we're biasing, we need to compute the new energy with the full
    2192             : ! potential
    2193           0 :       IF (lbias) THEN
    2194             : ! need to give the force_env the coords from the bias_env
    2195           0 :          CALL force_env_get(force_env, subsys=subsys_force)
    2196           0 :          CALL cp_subsys_get(subsys_force, particles=particles_force)
    2197           0 :          CALL force_env_get(bias_env, subsys=subsys)
    2198           0 :          CALL cp_subsys_get(subsys, particles=particles)
    2199           0 :          DO ipart = 1, nunits_tot(box_number)
    2200           0 :             particles_force%els(ipart)%r(1:3) = particles%els(ipart)%r(1:3)
    2201             :          END DO
    2202             : 
    2203             :          CALL force_env_calc_energy_force(force_env, &
    2204           0 :                                           calc_force=.FALSE.)
    2205             :          CALL force_env_get(force_env, &
    2206           0 :                             potential_energy=new_energy)
    2207             : 
    2208             :       END IF
    2209             : 
    2210           0 :       volume_in = 4.0_dp/3.0_dp*pi*(avbmc_rmax(molecule_type)**3 - avbmc_rmin(molecule_type)**3)
    2211           0 :       volume_out = abc(1)*abc(2)*abc(3) - volume_in
    2212             : 
    2213           0 :       IF (lin .AND. move_type == 'in' .OR. &
    2214             :           .NOT. lin .AND. move_type == 'out') THEN
    2215             : ! standard Metropolis rule
    2216             :          prefactor = 1.0_dp
    2217           0 :       ELSEIF (.NOT. lin .AND. move_type == 'in') THEN
    2218           0 :          prefactor = (1.0_dp - pbias(molecule_type))*volume_in/(pbias(molecule_type)*volume_out)
    2219             :       ELSE
    2220           0 :          prefactor = pbias(molecule_type)*volume_out/((1.0_dp - pbias(molecule_type))*volume_in)
    2221             :       END IF
    2222             : 
    2223           0 :       IF (lbias) THEN
    2224             : ! AVBMC with CBMC and a biasing potential...notice that if the biasing
    2225             : ! potential equals the quickstep potential, this cancels out to the
    2226             : ! acceptance below
    2227             :          del_quickstep_energy = (-BETA)*(new_energy - old_energy - &
    2228           0 :                                          (bias_energy_new - bias_energy_old))
    2229             : 
    2230           0 :          IF (del_quickstep_energy .GT. exp_max_val) THEN
    2231           0 :             del_quickstep_energy = max_val
    2232           0 :          ELSEIF (del_quickstep_energy .LT. exp_min_val) THEN
    2233             :             del_quickstep_energy = 0.0_dp
    2234             :          ELSE
    2235           0 :             del_quickstep_energy = EXP(del_quickstep_energy)
    2236             :          END IF
    2237             : 
    2238           0 :          w = prefactor*del_quickstep_energy*weight_new/weight_old
    2239             : 
    2240             :       ELSE
    2241             : 
    2242             : ! AVBMC with CBMC
    2243           0 :          w = prefactor*weight_new/weight_old
    2244             :       END IF
    2245             : 
    2246             : ! check if the move is accepted
    2247           0 :       IF (w .GE. 1.0E0_dp) THEN
    2248           0 :          rand = 0.0E0_dp
    2249             :       ELSE
    2250           0 :          IF (ionode) rand = rng_stream%next()
    2251           0 :          CALL group%bcast(rand, source)
    2252             :       END IF
    2253             : 
    2254           0 :       IF (rand .LT. w) THEN
    2255             : 
    2256             : ! accept the move
    2257             : 
    2258           0 :          IF (lin) THEN
    2259           0 :             IF (move_type == 'in') THEN
    2260             :                moves%avbmc_inin%successes = &
    2261           0 :                   moves%avbmc_inin%successes + 1
    2262             :             ELSE
    2263             :                moves%avbmc_inout%successes = &
    2264           0 :                   moves%avbmc_inout%successes + 1
    2265             :             END IF
    2266             :          ELSE
    2267           0 :             IF (move_type == 'in') THEN
    2268             :                moves%avbmc_outin%successes = &
    2269           0 :                   moves%avbmc_outin%successes + 1
    2270             :             ELSE
    2271             :                moves%avbmc_outout%successes = &
    2272           0 :                   moves%avbmc_outout%successes + 1
    2273             :             END IF
    2274             :          END IF
    2275             : 
    2276             : ! we need to compensate for the fact that we take the difference in
    2277             : ! generate_cbmc_config to keep the exponetials small
    2278           0 :          IF (.NOT. lbias) THEN
    2279           0 :             new_energy = new_energy + old_energy
    2280             :          END IF
    2281             : 
    2282             : ! update energies
    2283           0 :          energy_check = energy_check + (new_energy - old_energy)
    2284           0 :          old_energy = new_energy
    2285             : 
    2286             : ! if we're biasing the update the biasing energy
    2287           0 :          IF (lbias) THEN
    2288             : ! need to do this outside of the routine
    2289           0 :             last_bias_energy = bias_energy_new
    2290           0 :             bias_energy_old = bias_energy_new
    2291             :          END IF
    2292             : 
    2293             : ! update coordinates
    2294           0 :          CALL force_env_get(force_env, subsys=subsys)
    2295           0 :          CALL cp_subsys_get(subsys, particles=particles)
    2296           0 :          DO ipart = 1, nunits_tot(box_number)
    2297           0 :             r_old(1:3, ipart) = particles%els(ipart)%r(1:3)
    2298             :          END DO
    2299             :       ELSE
    2300             : ! reject the move...need to restore the old coordinates
    2301           0 :          IF (lbias) THEN
    2302           0 :             CALL force_env_get(bias_env, subsys=subsys)
    2303           0 :             CALL cp_subsys_get(subsys, particles=particles)
    2304           0 :             DO ipart = 1, nunits_tot(box_number)
    2305           0 :                particles%els(ipart)%r(1:3) = r_old(1:3, ipart)
    2306             :             END DO
    2307           0 :             CALL cp_subsys_set(subsys, particles=particles)
    2308             :          END IF
    2309           0 :          CALL force_env_get(force_env, subsys=subsys)
    2310           0 :          CALL cp_subsys_get(subsys, particles=particles)
    2311           0 :          DO ipart = 1, nunits_tot(box_number)
    2312           0 :             particles%els(ipart)%r(1:3) = r_old(1:3, ipart)
    2313             :          END DO
    2314           0 :          CALL cp_subsys_set(subsys, particles=particles)
    2315             : 
    2316             :       END IF
    2317             : 
    2318             : ! deallocate some stuff
    2319           0 :       DEALLOCATE (r_new)
    2320             : ! end the timing
    2321           0 :       CALL timestop(handle)
    2322             : 
    2323           0 :    END SUBROUTINE mc_avbmc_move
    2324             : 
    2325             : ! **************************************************************************************************
    2326             : !> \brief performs a hybrid Monte Carlo move that runs a short MD sequence
    2327             : !> \param mc_par the mc parameters for the force env
    2328             : !> \param force_env the force environment whose cell we're changing
    2329             : !> \param globenv ...
    2330             : !> \param moves the structure that keeps track of how many moves have been
    2331             : !>               accepted/rejected
    2332             : !> \param move_updates the structure that keeps track of how many moves have
    2333             : !>               been accepted/rejected since the last time the displacements
    2334             : !>               were updated
    2335             : !> \param old_energy the energy of the last accepted move involving an
    2336             : !>                    unbiased calculation
    2337             : !> \param box_number the box we're changing the volume of
    2338             : !> \param energy_check the running total of how much the energy has changed
    2339             : !>                      since the initial configuration
    2340             : !> \param r_old the coordinates of the last accepted move involving an
    2341             : !>               unbiased calculation
    2342             : !> \param rng_stream the random number stream that we draw from
    2343             : !> \author MJM
    2344             : !> \note     Designed for parallel use.
    2345             : ! **************************************************************************************************
    2346          20 :    SUBROUTINE mc_hmc_move(mc_par, force_env, globenv, moves, move_updates, &
    2347             :                           old_energy, box_number, &
    2348          20 :                           energy_check, r_old, rng_stream)
    2349             : 
    2350             :       TYPE(mc_simpar_type), POINTER                      :: mc_par
    2351             :       TYPE(force_env_type), POINTER                      :: force_env
    2352             :       TYPE(global_environment_type), POINTER             :: globenv
    2353             :       TYPE(mc_moves_type), POINTER                       :: moves, move_updates
    2354             :       REAL(KIND=dp), INTENT(INOUT)                       :: old_energy
    2355             :       INTEGER, INTENT(IN)                                :: box_number
    2356             :       REAL(KIND=dp), INTENT(INOUT)                       :: energy_check
    2357             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT)      :: r_old
    2358             :       TYPE(rng_stream_type), INTENT(INOUT)               :: rng_stream
    2359             : 
    2360             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'mc_hmc_move'
    2361             : 
    2362             :       INTEGER                                            :: handle, iatom, source
    2363          20 :       INTEGER, DIMENSION(:), POINTER                     :: nunits_tot
    2364             :       LOGICAL                                            :: ionode
    2365             :       REAL(KIND=dp)                                      :: BETA, energy_term, exp_max_val, &
    2366             :                                                             exp_min_val, new_energy, rand, value, w
    2367          20 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: r
    2368             :       TYPE(cp_subsys_type), POINTER                      :: oldsys
    2369             :       TYPE(mc_ekin_type), POINTER                        :: hmc_ekin
    2370             :       TYPE(mc_molecule_info_type), POINTER               :: mc_molecule_info
    2371             :       TYPE(mp_comm_type)                                 :: group
    2372             :       TYPE(particle_list_type), POINTER                  :: particles_old
    2373             : 
    2374             : ! begin the timing of the subroutine
    2375             : 
    2376          20 :       CALL timeset(routineN, handle)
    2377             : 
    2378             : ! get a bunch of stuff from mc_par
    2379             :       CALL get_mc_par(mc_par, ionode=ionode, &
    2380             :                       BETA=BETA, exp_max_val=exp_max_val, &
    2381             :                       exp_min_val=exp_min_val, source=source, group=group, &
    2382          20 :                       mc_molecule_info=mc_molecule_info)
    2383          20 :       CALL get_mc_molecule_info(mc_molecule_info, nunits_tot=nunits_tot)
    2384             : 
    2385             : ! nullify some pointers
    2386          20 :       NULLIFY (particles_old, oldsys, hmc_ekin)
    2387             : 
    2388             : ! do some allocation
    2389          60 :       ALLOCATE (r(1:3, 1:nunits_tot(box_number)))
    2390          20 :       ALLOCATE (hmc_ekin)
    2391             : 
    2392             : ! record the attempt
    2393          20 :       moves%hmc%attempts = moves%hmc%attempts + 1
    2394          20 :       move_updates%hmc%attempts = move_updates%hmc%attempts + 1
    2395             : 
    2396             : ! now let's grab the particle positions
    2397          20 :       CALL force_env_get(force_env, subsys=oldsys)
    2398          20 :       CALL cp_subsys_get(oldsys, particles=particles_old)
    2399             : 
    2400             : ! save the old coordinates
    2401       21700 :       DO iatom = 1, nunits_tot(box_number)
    2402       86740 :          r(1:3, iatom) = particles_old%els(iatom)%r(1:3)
    2403             :       END DO
    2404             : 
    2405             : ! now run the MD simulation
    2406          20 :       CALL qs_mol_dyn(force_env, globenv, hmc_e_initial=hmc_ekin%initial_ekin, hmc_e_final=hmc_ekin%final_ekin)
    2407             : 
    2408             : ! get the energy
    2409             :       CALL force_env_get(force_env, &
    2410          20 :                          potential_energy=new_energy)
    2411             : 
    2412             : ! accept or reject the move
    2413             : ! to prevent overflows
    2414          20 :       energy_term = new_energy + hmc_ekin%final_ekin - old_energy - hmc_ekin%initial_ekin
    2415             : 
    2416          20 :       value = -BETA*(energy_term)
    2417          20 :       IF (value .GT. exp_max_val) THEN
    2418             :          w = 10.0_dp
    2419          20 :       ELSEIF (value .LT. exp_min_val) THEN
    2420             :          w = 0.0_dp
    2421             :       ELSE
    2422          20 :          w = EXP(value)
    2423             :       END IF
    2424             : 
    2425          20 :       IF (w .GE. 1.0E0_dp) THEN
    2426          10 :          w = 1.0E0_dp
    2427          10 :          rand = 0.0E0_dp
    2428             :       ELSE
    2429          10 :          IF (ionode) rand = rng_stream%next()
    2430          10 :          CALL group%bcast(rand, source)
    2431             :       END IF
    2432             : 
    2433          20 :       IF (rand .LT. w) THEN
    2434             : 
    2435             : ! accept the move
    2436          14 :          moves%hmc%successes = moves%hmc%successes + 1
    2437          14 :          move_updates%hmc%successes = move_updates%hmc%successes + 1
    2438             : 
    2439             : ! update energies
    2440          14 :          energy_check = energy_check + (new_energy - old_energy)
    2441          14 :          old_energy = new_energy
    2442             : 
    2443       15190 :          DO iatom = 1, nunits_tot(box_number)
    2444       60718 :             r_old(1:3, iatom) = particles_old%els(iatom)%r(1:3)
    2445             :          END DO
    2446             : 
    2447             :       ELSE
    2448             : 
    2449             : ! reset the cell and particle positions
    2450        6510 :          DO iatom = 1, nunits_tot(box_number)
    2451       26022 :             particles_old%els(iatom)%r(1:3) = r_old(1:3, iatom)
    2452             :          END DO
    2453             : 
    2454             :       END IF
    2455             : 
    2456             : ! deallocate some stuff
    2457          20 :       DEALLOCATE (r)
    2458          20 :       DEALLOCATE (hmc_ekin)
    2459             : 
    2460             : ! end the timing
    2461          20 :       CALL timestop(handle)
    2462             : 
    2463          40 :    END SUBROUTINE mc_hmc_move
    2464             : 
    2465             : ! *****************************************************************************
    2466             : !> \brief translates the cluster randomly in either the x,y, or z
    2467             : !>direction
    2468             : !> \param mc_par the mc parameters for the force env
    2469             : !> \param force_env the force environment used in the move
    2470             : !> \param bias_env the force environment used to bias the move, if any (it may
    2471             : !>            be null if lbias=.false. in mc_par)
    2472             : !> \param moves the structure that keeps track of how many moves have been
    2473             : !>               accepted/rejected
    2474             : !> \param move_updates the structure that keeps track of how many moves have
    2475             : !>               been accepted/rejected since the last time the displacements
    2476             : !>               were updated
    2477             : !> \param box_number ...
    2478             : !> \param bias_energy the biased energy of the system before the move
    2479             : !> \param lreject set to .true. if there is an overlap
    2480             : !> \param rng_stream the random number stream that we draw from
    2481             : !> \author Himanshu Goel
    2482             : !> \note     Designed for parallel use.
    2483             : ! **************************************************************************************************
    2484             : 
    2485          10 :    SUBROUTINE mc_cluster_translation(mc_par, force_env, bias_env, moves, &
    2486             :                                      move_updates, box_number, bias_energy, lreject, rng_stream)
    2487             : 
    2488             :       TYPE(mc_simpar_type), POINTER                      :: mc_par
    2489             :       TYPE(force_env_type), POINTER                      :: force_env, bias_env
    2490             :       TYPE(mc_moves_type), POINTER                       :: moves, move_updates
    2491             :       INTEGER, INTENT(IN)                                :: box_number
    2492             :       REAL(KIND=dp), INTENT(INOUT)                       :: bias_energy
    2493             :       LOGICAL, INTENT(OUT)                               :: lreject
    2494             :       TYPE(rng_stream_type), INTENT(INOUT)               :: rng_stream
    2495             : 
    2496             :       CHARACTER(len=*), PARAMETER :: routineN = 'mc_cluster_translation'
    2497             : 
    2498             :       INTEGER :: cstart, end_mol, handle, imol, ipart, iparticle, iunit, jbox, jpart, junit, &
    2499             :          move_direction, nend, nunit, source, start_mol, total_clus, total_clusafmo
    2500             :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: cluster
    2501          10 :       INTEGER, DIMENSION(:), POINTER                     :: mol_type, nunits, nunits_tot
    2502          10 :       INTEGER, DIMENSION(:, :), POINTER                  :: nchains
    2503             :       LOGICAL                                            :: ionode, lbias, loverlap
    2504             :       REAL(KIND=dp)                                      :: BETA, bias_energy_new, bias_energy_old, &
    2505             :                                                             dis_mol, exp_max_val, exp_min_val, &
    2506             :                                                             rand, rmcltrans, value, w
    2507          10 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: r_old
    2508             :       TYPE(cp_subsys_type), POINTER                      :: subsys
    2509             :       TYPE(mc_molecule_info_type), POINTER               :: mc_molecule_info
    2510             :       TYPE(mp_comm_type)                                 :: group
    2511             :       TYPE(particle_list_type), POINTER                  :: particles
    2512             : 
    2513             : !   *** Local Counters ***
    2514             : ! begin the timing of the subroutine
    2515             : 
    2516          10 :       CALL timeset(routineN, handle)
    2517             : 
    2518             : ! nullify some pointers
    2519          10 :       NULLIFY (particles, subsys)
    2520             : 
    2521             : ! get a bunch of stuff from mc_par
    2522             :       CALL get_mc_par(mc_par, lbias=lbias, &
    2523             :                       BETA=BETA, exp_max_val=exp_max_val, &
    2524             :                       exp_min_val=exp_min_val, rmcltrans=rmcltrans, ionode=ionode, source=source, &
    2525          10 :                       group=group, mc_molecule_info=mc_molecule_info)
    2526             :       CALL get_mc_molecule_info(mc_molecule_info, nunits_tot=nunits_tot, &
    2527          10 :                                 nchains=nchains, nunits=nunits, mol_type=mol_type)
    2528             : 
    2529             : ! find out some bounds for mol_type
    2530          10 :       start_mol = 1
    2531          10 :       DO jbox = 1, box_number - 1
    2532          10 :          start_mol = start_mol + SUM(nchains(:, jbox))
    2533             :       END DO
    2534          20 :       end_mol = start_mol + SUM(nchains(:, box_number)) - 1
    2535             : 
    2536             : ! do some allocation
    2537          30 :       ALLOCATE (r_old(1:3, 1:nunits_tot(box_number)))
    2538             : 
    2539             : ! Allocating cluster matrix size
    2540          20 :       nend = SUM(nchains(:, box_number))
    2541          40 :       ALLOCATE (cluster(nend, nend))
    2542          60 :       DO ipart = 1, nend
    2543         310 :          DO jpart = 1, nend
    2544         300 :             cluster(ipart, jpart) = 0
    2545             :          END DO
    2546             :       END DO
    2547             : 
    2548             : ! Get cluster information in cluster matrix from cluster_search subroutine
    2549          10 :       IF (lbias) THEN
    2550             :          CALL cluster_search(mc_par, bias_env, cluster, nchains(:, box_number), &
    2551           0 :                              nunits, mol_type(start_mol:end_mol), total_clus)
    2552             :       ELSE
    2553             :          CALL cluster_search(mc_par, force_env, cluster, nchains(:, box_number), &
    2554          10 :                              nunits, mol_type(start_mol:end_mol), total_clus)
    2555             :       END IF
    2556             : 
    2557          10 :       IF (lbias) THEN
    2558             : 
    2559             : ! grab the coordinates
    2560           0 :          CALL force_env_get(bias_env, subsys=subsys)
    2561           0 :          CALL cp_subsys_get(subsys, particles=particles)
    2562             : 
    2563             : ! save the coordinates
    2564           0 :          DO ipart = 1, nunits_tot(box_number)
    2565           0 :             r_old(1:3, ipart) = particles%els(ipart)%r(1:3)
    2566             :          END DO
    2567             : 
    2568             : ! save the energy
    2569           0 :          bias_energy_old = bias_energy
    2570             :       ELSE
    2571             : 
    2572             : ! grab the coordinates
    2573          10 :          CALL force_env_get(force_env, subsys=subsys)
    2574          10 :          CALL cp_subsys_get(subsys, particles=particles)
    2575             :       END IF
    2576             : 
    2577             : ! record the attempt
    2578          10 :       moves%cltrans%attempts = moves%cltrans%attempts + 1
    2579          10 :       move_updates%cltrans%attempts = move_updates%cltrans%attempts + 1
    2580          10 :       moves%bias_cltrans%attempts = moves%bias_cltrans%attempts + 1
    2581          10 :       move_updates%bias_cltrans%attempts = move_updates%bias_cltrans%attempts + 1
    2582          10 :       IF (.NOT. lbias) THEN
    2583          10 :          moves%cltrans%qsuccesses = moves%cltrans%qsuccesses + 1
    2584          10 :          move_updates%cltrans%qsuccesses = move_updates%cltrans%qsuccesses + 1
    2585          10 :          moves%bias_cltrans%qsuccesses = moves%bias_cltrans%qsuccesses + 1
    2586          10 :          move_updates%bias_cltrans%qsuccesses = move_updates%bias_cltrans%qsuccesses + 1
    2587             :       END IF
    2588             : 
    2589             : ! call a random number to figure out which direction we're moving
    2590          10 :       IF (ionode) rand = rng_stream%next()
    2591          10 :       CALL group%bcast(rand, source)
    2592          10 :       move_direction = INT(3*rand) + 1
    2593             : 
    2594             : ! call a random number to figure out how far we're moving
    2595          10 :       IF (ionode) rand = rng_stream%next()
    2596          10 :       CALL group%bcast(rand, source)
    2597          10 :       dis_mol = rmcltrans*(rand - 0.5E0_dp)*2.0E0_dp
    2598             : 
    2599             : ! choosing cluster
    2600          10 :       IF (ionode) rand = rng_stream%next()
    2601          10 :       CALL group%bcast(rand, source)
    2602          10 :       jpart = INT(1 + rand*total_clus)
    2603             : 
    2604             : ! do the cluster move
    2605          60 :       DO cstart = 1, nend
    2606          50 :          imol = 0
    2607          60 :          IF (cluster(jpart, cstart) .NE. 0) THEN
    2608          34 :             imol = cluster(jpart, cstart)
    2609             :             iunit = 1
    2610          34 :             DO ipart = 1, imol - 1
    2611          24 :                nunit = nunits(mol_type(ipart + start_mol - 1))
    2612          34 :                iunit = iunit + nunit
    2613             :             END DO
    2614          10 :             nunit = nunits(mol_type(imol + start_mol - 1))
    2615          10 :             junit = iunit + nunit - 1
    2616          30 :             DO iparticle = iunit, junit
    2617             :                particles%els(iparticle)%r(move_direction) = &
    2618          30 :                   particles%els(iparticle)%r(move_direction) + dis_mol
    2619             :             END DO
    2620             :          END IF
    2621             :       END DO
    2622          10 :       CALL cp_subsys_set(subsys, particles=particles)
    2623             : 
    2624             : !Make cluster matrix null
    2625          60 :       DO ipart = 1, nend
    2626         310 :          DO jpart = 1, nend
    2627         300 :             cluster(ipart, jpart) = 0
    2628             :          END DO
    2629             :       END DO
    2630             : 
    2631             : ! checking the number of cluster are same or got changed after cluster translation move
    2632          10 :       IF (lbias) THEN
    2633             :          CALL cluster_search(mc_par, bias_env, cluster, nchains(:, box_number), &
    2634           0 :                              nunits, mol_type(start_mol:end_mol), total_clusafmo)
    2635             :       ELSE
    2636             :          CALL cluster_search(mc_par, force_env, cluster, nchains(:, box_number), &
    2637          10 :                              nunits, mol_type(start_mol:end_mol), total_clusafmo)
    2638             :       END IF
    2639             : 
    2640             : ! figure out if there is any overlap...need the number of the molecule
    2641          10 :       lreject = .FALSE.
    2642          10 :       IF (lbias) THEN
    2643             :          CALL check_for_overlap(bias_env, nchains(:, box_number), &
    2644           0 :                                 nunits(:), loverlap, mol_type(start_mol:end_mol))
    2645             :       ELSE
    2646             :          CALL check_for_overlap(force_env, nchains(:, box_number), &
    2647          10 :                                 nunits(:), loverlap, mol_type(start_mol:end_mol))
    2648          10 :          IF (loverlap) lreject = .TRUE.
    2649             :       END IF
    2650             : 
    2651             : ! check if cluster size changes then reject the move
    2652          10 :       IF (lbias) THEN
    2653           0 :          IF (total_clusafmo .NE. total_clus) THEN
    2654           0 :             loverlap = .TRUE.
    2655             :          END IF
    2656             :       ELSE
    2657          10 :          IF (total_clusafmo .NE. total_clus) THEN
    2658           0 :             loverlap = .TRUE.
    2659           0 :             lreject = .TRUE.
    2660             :          END IF
    2661             :       END IF
    2662             : 
    2663             : ! if we're biasing with a cheaper potential, check for acceptance
    2664          10 :       IF (lbias) THEN
    2665             : 
    2666             : ! here's where we bias the moves
    2667           0 :          IF (loverlap) THEN
    2668             :             w = 0.0E0_dp
    2669             :          ELSE
    2670           0 :             CALL force_env_calc_energy_force(bias_env, calc_force=.FALSE.)
    2671             :             CALL force_env_get(bias_env, &
    2672           0 :                                potential_energy=bias_energy_new)
    2673             : ! accept or reject the move based on the Metropolis rule
    2674           0 :             value = -BETA*(bias_energy_new - bias_energy_old)
    2675           0 :             IF (value .GT. exp_max_val) THEN
    2676             :                w = 10.0_dp
    2677           0 :             ELSEIF (value .LT. exp_min_val) THEN
    2678             :                w = 0.0_dp
    2679             :             ELSE
    2680           0 :                w = EXP(value)
    2681             :             END IF
    2682             : 
    2683             :          END IF
    2684             : 
    2685           0 :          IF (w .GE. 1.0E0_dp) THEN
    2686           0 :             w = 1.0E0_dp
    2687           0 :             rand = 0.0E0_dp
    2688             :          ELSE
    2689           0 :             IF (ionode) rand = rng_stream%next()
    2690           0 :             CALL group%bcast(rand, source)
    2691             :          END IF
    2692           0 :          IF (rand .LT. w) THEN
    2693             : 
    2694             : ! accept the move
    2695           0 :             moves%bias_cltrans%successes = moves%bias_cltrans%successes + 1
    2696           0 :             move_updates%bias_cltrans%successes = move_updates%bias_cltrans%successes + 1
    2697           0 :             moves%cltrans%qsuccesses = moves%cltrans%qsuccesses + 1
    2698             :             move_updates%cltrans%successes = &
    2699           0 :                move_updates%cltrans%successes + 1
    2700           0 :             moves%qcltrans_dis = moves%qcltrans_dis + ABS(dis_mol)
    2701             :             bias_energy = bias_energy + bias_energy_new - &
    2702           0 :                           bias_energy_old
    2703             : 
    2704             :          ELSE
    2705             : 
    2706             : ! reject the move
    2707             : ! restore the coordinates
    2708           0 :             CALL force_env_get(bias_env, subsys=subsys)
    2709           0 :             CALL cp_subsys_get(subsys, particles=particles)
    2710           0 :             DO ipart = 1, nunits_tot(box_number)
    2711           0 :                particles%els(ipart)%r(1:3) = r_old(1:3, ipart)
    2712             :             END DO
    2713           0 :             CALL cp_subsys_set(subsys, particles=particles)
    2714             : 
    2715             :          END IF
    2716             : 
    2717             :       END IF
    2718             : 
    2719             : ! deallocate some stuff
    2720          10 :       DEALLOCATE (cluster)
    2721          10 :       DEALLOCATE (r_old)
    2722             : 
    2723             : ! end the timing
    2724          10 :       CALL timestop(handle)
    2725             : 
    2726          10 :    END SUBROUTINE mc_cluster_translation
    2727             : 
    2728             : END MODULE mc_moves

Generated by: LCOV version 1.15