LCOV - code coverage report
Current view: top level - src/motion/mc - mc_ge_moves.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:9ccafda) Lines: 87.0 % 562 489
Test Date: 2026-10-15 00:55:44 Functions: 100.0 % 3 3

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief contains the Monte Carlo moves that can handle more than one
      10              : !>      box, including the Quickstep move, a volume swap between boxes,
      11              : !>       and a particle swap between boxes
      12              : !> \par History
      13              : !>      MJM (07.28.2005): make the Quickstep move general, and changed
      14              : !>                        the swap and volume moves to work with the
      15              : !>                        CP2K classical routines
      16              : !> \author Matthew J. McGrath  (01.25.2004)
      17              : ! **************************************************************************************************
      18              : MODULE mc_ge_moves
      19              :    USE cell_methods,                    ONLY: cell_create
      20              :    USE cell_types,                      ONLY: cell_clone,&
      21              :                                               cell_p_type,&
      22              :                                               cell_release,&
      23              :                                               cell_type,&
      24              :                                               get_cell
      25              :    USE cp_subsys_types,                 ONLY: cp_subsys_get,&
      26              :                                               cp_subsys_p_type,&
      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_p_type,&
      32              :                                               force_env_release
      33              :    USE input_constants,                 ONLY: dump_xmol
      34              :    USE input_section_types,             ONLY: section_type
      35              :    USE kinds,                           ONLY: default_string_length,&
      36              :                                               dp
      37              :    USE mc_control,                      ONLY: mc_create_force_env
      38              :    USE mc_coordinates,                  ONLY: check_for_overlap,&
      39              :                                               generate_cbmc_swap_config,&
      40              :                                               get_center_of_mass
      41              :    USE mc_misc,                         ONLY: mc_make_dat_file_new
      42              :    USE mc_move_control,                 ONLY: move_q_reinit,&
      43              :                                               q_move_accept
      44              :    USE mc_types,                        ONLY: &
      45              :         get_mc_molecule_info, get_mc_par, mc_determine_molecule_info, mc_input_file_type, &
      46              :         mc_molecule_info_destroy, mc_molecule_info_type, mc_moves_p_type, &
      47              :         mc_simulation_parameters_p_type, set_mc_par
      48              :    USE message_passing,                 ONLY: mp_comm_type,&
      49              :                                               mp_para_env_type
      50              :    USE parallel_rng_types,              ONLY: rng_stream_type
      51              :    USE particle_list_types,             ONLY: particle_list_p_type,&
      52              :                                               particle_list_type
      53              :    USE particle_methods,                ONLY: write_particle_coordinates
      54              :    USE physcon,                         ONLY: angstrom
      55              : #include "../../base/base_uses.f90"
      56              : 
      57              :    IMPLICIT NONE
      58              : 
      59              :    PRIVATE
      60              : 
      61              : ! *** Global parameters ***
      62              : 
      63              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'mc_ge_moves'
      64              : 
      65              :    PUBLIC :: mc_ge_volume_move, mc_ge_swap_move, &
      66              :              mc_quickstep_move
      67              : 
      68              : CONTAINS
      69              : 
      70              : ! **************************************************************************************************
      71              : !> \brief computes the acceptance of a series of biased or unbiased moves
      72              : !>      (translation, rotation, conformational changes)
      73              : !> \param mc_par the mc parameters for the force envs of the boxes
      74              : !> \param force_env the force environments for the boxes
      75              : !> \param bias_env the force environments with the biasing potential for the boxes
      76              : !> \param moves the structure that keeps track of how many moves have been
      77              : !>               accepted/rejected for both boxes
      78              : !> \param lreject automatically rejects the move (used when an overlap occurs in
      79              : !>                the sequence of moves)
      80              : !> \param move_updates the structure that keeps track of how many moves have
      81              : !>               been accepted/rejected since the last time the displacements
      82              : !>               were updated for both boxes
      83              : !> \param energy_check the running total of how much the energy has changed
      84              : !>                      since the initial configuration
      85              : !> \param r_old the coordinates of the last accepted move before the sequence
      86              : !>         whose acceptance is determined by this call
      87              : !> \param nnstep the Monte Carlo step we're on
      88              : !> \param old_energy the energy of the last accepted move involving the full potential
      89              : !> \param bias_energy_new the energy of the current configuration involving the bias potential
      90              : !> \param last_bias_energy ...
      91              : !> \param nboxes the number of boxes (force environments) in the system
      92              : !> \param box_flag indicates if a move has been tried in a given box..if not, we don't
      93              : !>        recompute the energy
      94              : !> \param subsys the pointers for the particle subsystems of both boxes
      95              : !> \param particles the pointers for the particle sets
      96              : !> \param rng_stream the stream we pull random numbers from
      97              : !> \param unit_conv ...
      98              : !> \author MJM
      99              : ! **************************************************************************************************
     100          368 :    SUBROUTINE mc_Quickstep_move(mc_par, force_env, bias_env, moves, &
     101          368 :                                 lreject, move_updates, energy_check, r_old, &
     102          368 :                                 nnstep, old_energy, bias_energy_new, last_bias_energy, &
     103          368 :                                 nboxes, box_flag, subsys, particles, rng_stream, &
     104              :                                 unit_conv)
     105              : 
     106              :       TYPE(mc_simulation_parameters_p_type), &
     107              :          DIMENSION(:), POINTER                           :: mc_par
     108              :       TYPE(force_env_p_type), DIMENSION(:), POINTER      :: force_env, bias_env
     109              :       TYPE(mc_moves_p_type), DIMENSION(:, :), POINTER    :: moves
     110              :       LOGICAL, INTENT(IN)                                :: lreject
     111              :       TYPE(mc_moves_p_type), DIMENSION(:, :), POINTER    :: move_updates
     112              :       REAL(KIND=dp), DIMENSION(:), INTENT(INOUT)         :: energy_check
     113              :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT)   :: r_old
     114              :       INTEGER, INTENT(IN)                                :: nnstep
     115              :       REAL(KIND=dp), DIMENSION(:), INTENT(INOUT)         :: old_energy, bias_energy_new, &
     116              :                                                             last_bias_energy
     117              :       INTEGER, INTENT(IN)                                :: nboxes
     118              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: box_flag
     119              :       TYPE(cp_subsys_p_type), DIMENSION(:), POINTER      :: subsys
     120              :       TYPE(particle_list_p_type), DIMENSION(:), POINTER  :: particles
     121              :       TYPE(rng_stream_type), INTENT(INOUT)               :: rng_stream
     122              :       REAL(KIND=dp), INTENT(IN)                          :: unit_conv
     123              : 
     124              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'mc_Quickstep_move'
     125              :       REAL(KIND=dp), PARAMETER                           :: eps_energies = -1.0E-08_dp
     126              : 
     127              :       INTEGER                                            :: end_mol, handle, ibox, iparticle, &
     128              :                                                             iprint, itype, jbox, nmol_types, &
     129              :                                                             source, start_mol
     130          368 :       INTEGER, DIMENSION(:, :), POINTER                  :: nchains
     131          368 :       INTEGER, DIMENSION(:), POINTER                     :: mol_type, nunits, nunits_tot
     132          736 :       INTEGER, DIMENSION(1:nboxes)                       :: diff
     133              :       LOGICAL                                            :: ionode, lbias, loverlap
     134              :       REAL(KIND=dp)                                      :: BETA, energies, rand, w
     135          736 :       REAL(KIND=dp), DIMENSION(1:nboxes)                 :: bias_energy_old, new_energy
     136          368 :       TYPE(cp_subsys_p_type), DIMENSION(:), POINTER      :: subsys_bias
     137              :       TYPE(mc_molecule_info_type), POINTER               :: mc_molecule_info
     138              :       TYPE(mp_comm_type)                                 :: group
     139          368 :       TYPE(particle_list_p_type), DIMENSION(:), POINTER  :: particles_bias
     140              : 
     141              : ! begin the timing of the subroutine
     142              : 
     143          368 :       CALL timeset(routineN, handle)
     144              : 
     145          368 :       NULLIFY (subsys_bias, particles_bias)
     146              : 
     147              : ! get a bunch of data from mc_par
     148              :       CALL get_mc_par(mc_par(1)%mc_par, ionode=ionode, lbias=lbias, &
     149              :                       BETA=BETA, diff=diff(1), source=source, group=group, &
     150              :                       iprint=iprint, &
     151          368 :                       mc_molecule_info=mc_molecule_info)
     152              :       CALL get_mc_molecule_info(mc_molecule_info, nmol_types=nmol_types, &
     153          368 :                                 nchains=nchains, nunits_tot=nunits_tot, nunits=nunits, mol_type=mol_type)
     154              : 
     155          368 :       IF (nboxes > 1) THEN
     156          144 :          DO ibox = 2, nboxes
     157          144 :             CALL get_mc_par(mc_par(ibox)%mc_par, diff=diff(ibox))
     158              :          END DO
     159              :       END IF
     160              : 
     161              : ! allocate some stuff
     162         1912 :       ALLOCATE (subsys_bias(1:nboxes))
     163         1176 :       ALLOCATE (particles_bias(1:nboxes))
     164              : 
     165              : ! record the attempt...we really only care about molecule type 1 and box
     166              : ! type 1, since the acceptance will be identical for all boxes and molecules
     167              :       moves(1, 1)%moves%Quickstep%attempts = &
     168          368 :          moves(1, 1)%moves%Quickstep%attempts + 1
     169              : 
     170              : ! grab the coordinates for the force_env
     171          808 :       DO ibox = 1, nboxes
     172              :          CALL force_env_get(force_env(ibox)%force_env, &
     173          440 :                             subsys=subsys(ibox)%subsys)
     174              :          CALL cp_subsys_get(subsys(ibox)%subsys, &
     175          808 :                             particles=particles(ibox)%list)
     176              :       END DO
     177              : 
     178              : ! calculate the new energy of the system...if we're biasing,
     179              : ! force_env hasn't changed but bias_env has
     180          808 :       DO ibox = 1, nboxes
     181          808 :          IF (box_flag(ibox) == 1) THEN
     182          368 :             IF (lbias) THEN
     183              : ! grab the coords from bias_env and put them into force_env
     184              :                CALL force_env_get(bias_env(ibox)%force_env, &
     185           98 :                                   subsys=subsys_bias(ibox)%subsys)
     186              :                CALL cp_subsys_get(subsys_bias(ibox)%subsys, &
     187           98 :                                   particles=particles_bias(ibox)%list)
     188              : 
     189         2606 :                DO iparticle = 1, nunits_tot(ibox)
     190              :                   particles(ibox)%list%els(iparticle)%r(1:3) = &
     191        17654 :                      particles_bias(ibox)%list%els(iparticle)%r(1:3)
     192              :                END DO
     193              : 
     194              :                CALL force_env_calc_energy_force(force_env(ibox)%force_env, &
     195           98 :                                                 calc_force=.FALSE.)
     196              :                CALL force_env_get(force_env(ibox)%force_env, &
     197           98 :                                   potential_energy=new_energy(ibox))
     198              :             ELSE
     199          270 :                IF (.NOT. lreject) THEN
     200              :                   CALL force_env_calc_energy_force(force_env(ibox)%force_env, &
     201          270 :                                                    calc_force=.FALSE.)
     202              :                   CALL force_env_get(force_env(ibox)%force_env, &
     203          270 :                                      potential_energy=new_energy(ibox))
     204              :                END IF
     205              :             END IF
     206              :          ELSE
     207           72 :             new_energy(ibox) = old_energy(ibox)
     208              :          END IF
     209              : 
     210              :       END DO
     211              : 
     212              : ! accept or reject the move based on Metropolis or the Iftimie rule
     213          368 :       IF (ionode) THEN
     214              : 
     215              : ! write them out in case something bad happens
     216          184 :          IF (MOD(nnstep, iprint) == 0) THEN
     217           26 :             DO ibox = 1, nboxes
     218           49 :                IF (SUM(nchains(:, ibox)) == 0) THEN
     219            0 :                   WRITE (diff(ibox), *) nnstep
     220            0 :                   WRITE (diff(ibox), *) nchains(:, ibox)
     221              :                ELSE
     222           14 :                   WRITE (diff(ibox), *) nnstep
     223              :                   CALL write_particle_coordinates( &
     224              :                      particles(ibox)%list%els, &
     225              :                      diff(ibox), dump_xmol, 'POS', 'TRIAL', &
     226           14 :                      unit_conv=unit_conv)
     227              :                END IF
     228              :             END DO
     229              :          END IF
     230              :       END IF
     231              : 
     232          368 :       IF (.NOT. lreject) THEN
     233          368 :          IF (lbias) THEN
     234              : 
     235          268 :             DO ibox = 1, nboxes
     236              : ! look for overlap
     237          510 :                IF (SUM(nchains(:, ibox)) /= 0) THEN
     238              : ! find the molecule bounds
     239              :                   start_mol = 1
     240          242 :                   DO jbox = 1, ibox - 1
     241          386 :                      start_mol = start_mol + SUM(nchains(:, jbox))
     242              :                   END DO
     243          510 :                   end_mol = start_mol + SUM(nchains(:, ibox)) - 1
     244              :                   CALL check_for_overlap(bias_env(ibox)%force_env, &
     245          170 :                                          nchains(:, ibox), nunits(:), loverlap, mol_type(start_mol:end_mol))
     246          170 :                   IF (loverlap) THEN
     247            0 :                      CPABORT('Quickstep move found an overlap in the old config')
     248              :                   END IF
     249              :                END IF
     250          268 :                bias_energy_old(ibox) = last_bias_energy(ibox)
     251              :             END DO
     252              : 
     253              :             energies = -BETA*((SUM(new_energy(:)) - SUM(bias_energy_new(:))) &
     254          778 :                               - (SUM(old_energy(:)) - SUM(bias_energy_old(:))))
     255              : 
     256              : ! used to prevent over and underflows
     257           98 :             IF (energies >= eps_energies) THEN
     258              :                w = 1.0_dp
     259           34 :             ELSE IF (energies <= -500.0_dp) THEN
     260              :                w = 0.0_dp
     261              :             ELSE
     262           34 :                w = EXP(energies)
     263              :             END IF
     264              : 
     265           98 :             IF (ionode) THEN
     266          134 :                DO ibox = 1, nboxes
     267           85 :                   WRITE (diff(ibox), *) nnstep, new_energy(ibox) - &
     268           85 :                      old_energy(ibox), &
     269          219 :                      bias_energy_new(ibox) - bias_energy_old(ibox)
     270              :                END DO
     271              :             END IF
     272              :          ELSE
     273          810 :             energies = -BETA*(SUM(new_energy(:)) - SUM(old_energy(:)))
     274              : ! used to prevent over and underflows
     275          270 :             IF (energies >= 0.0_dp) THEN
     276              :                w = 1.0_dp
     277          156 :             ELSE IF (energies <= -500.0_dp) THEN
     278              :                w = 0.0_dp
     279              :             ELSE
     280          156 :                w = EXP(energies)
     281              :             END IF
     282              :          END IF
     283              :       ELSE
     284              :          w = 0.0E0_dp
     285              :       END IF
     286          254 :       IF (w >= 1.0E0_dp) THEN
     287          178 :          w = 1.0E0_dp
     288          178 :          rand = 0.0E0_dp
     289              :       ELSE
     290          190 :          IF (ionode) rand = rng_stream%next()
     291          190 :          CALL group%bcast(rand, source)
     292              :       END IF
     293              : 
     294          368 :       IF (rand < w) THEN
     295              : 
     296              : ! accept the move
     297              :          moves(1, 1)%moves%Quickstep%successes = &
     298          286 :             moves(1, 1)%moves%Quickstep%successes + 1
     299              : 
     300          644 :          DO ibox = 1, nboxes
     301              : ! remember what kind of move we did for lbias=.false.
     302          358 :             IF (.NOT. lbias) THEN
     303          554 :                DO itype = 1, nmol_types
     304          366 :                   CALL q_move_accept(moves(itype, ibox)%moves, .TRUE.)
     305          366 :                   CALL q_move_accept(move_updates(itype, ibox)%moves, .TRUE.)
     306              : 
     307              : ! reset the counters
     308          366 :                   CALL move_q_reinit(moves(itype, ibox)%moves, .TRUE.)
     309          554 :                   CALL move_q_reinit(move_updates(itype, ibox)%moves, .TRUE.)
     310              :                END DO
     311              :             END IF
     312              : 
     313         1064 :             DO itype = 1, nmol_types
     314              : ! we need to record all accepted moves since last Quickstep calculation
     315          706 :                CALL q_move_accept(moves(itype, ibox)%moves, .FALSE.)
     316          706 :                CALL q_move_accept(move_updates(itype, ibox)%moves, .FALSE.)
     317              : 
     318              : ! reset the counters
     319          706 :                CALL move_q_reinit(moves(itype, ibox)%moves, .FALSE.)
     320         1064 :                CALL move_q_reinit(move_updates(itype, ibox)%moves, .FALSE.)
     321              :             END DO
     322              : 
     323              : ! update energies
     324              :             energy_check(ibox) = energy_check(ibox) + &
     325          358 :                                  (new_energy(ibox) - old_energy(ibox))
     326          644 :             old_energy(ibox) = new_energy(ibox)
     327              : 
     328              :          END DO
     329              : 
     330          286 :          IF (lbias) THEN
     331          268 :             DO ibox = 1, nboxes
     332          268 :                last_bias_energy(ibox) = bias_energy_new(ibox)
     333              :             END DO
     334              :          END IF
     335              : 
     336              : ! update coordinates
     337          644 :          DO ibox = 1, nboxes
     338          644 :             IF (nunits_tot(ibox) /= 0) THEN
     339         9566 :                DO iparticle = 1, nunits_tot(ibox)
     340              :                   r_old(1:3, iparticle, ibox) = &
     341        37190 :                      particles(ibox)%list%els(iparticle)%r(1:3)
     342              :                END DO
     343              :             END IF
     344              :          END DO
     345              : 
     346              :       ELSE
     347              : 
     348              :          ! reject the move
     349          164 :          DO ibox = 1, nboxes
     350          328 :             DO itype = 1, nmol_types
     351          164 :                CALL move_q_reinit(moves(itype, ibox)%moves, .FALSE.)
     352          164 :                CALL move_q_reinit(move_updates(itype, ibox)%moves, .FALSE.)
     353          246 :                IF (.NOT. lbias) THEN
     354              : ! reset the counters
     355          164 :                   CALL move_q_reinit(moves(itype, ibox)%moves, .TRUE.)
     356          164 :                   CALL move_q_reinit(move_updates(itype, ibox)%moves, .TRUE.)
     357              :                END IF
     358              :             END DO
     359              : 
     360              :          END DO
     361              : 
     362         4551 :          IF (.NOT. ionode) r_old(:, :, :) = 0.0E0_dp
     363              : 
     364              : ! coodinates changed, so we need to broadcast those, even for the lbias
     365              : ! case since bias_env needs to have the same coords as force_env
     366        17958 :          CALL group%bcast(r_old, source)
     367              : 
     368          164 :          DO ibox = 1, nboxes
     369         2378 :             DO iparticle = 1, nunits_tot(ibox)
     370              :                particles(ibox)%list%els(iparticle)%r(1:3) = &
     371         8856 :                   r_old(1:3, iparticle, ibox)
     372         2296 :                IF (lbias .AND. box_flag(ibox) == 1) THEN
     373              :                   particles_bias(ibox)%list%els(iparticle)%r(1:3) = &
     374            0 :                      r_old(1:3, iparticle, ibox)
     375              :                END IF
     376              :             END DO
     377              :          END DO
     378              : 
     379              : ! need to reset the energies of the biasing potential
     380           82 :          IF (lbias) THEN
     381            0 :             DO ibox = 1, nboxes
     382            0 :                bias_energy_new(ibox) = last_bias_energy(ibox)
     383              :             END DO
     384              :          END IF
     385              : 
     386              :       END IF
     387              : 
     388              : ! make sure the coordinates are transferred
     389          808 :       DO ibox = 1, nboxes
     390              :          CALL cp_subsys_set(subsys(ibox)%subsys, &
     391          440 :                             particles=particles(ibox)%list)
     392          808 :          IF (lbias .AND. box_flag(ibox) == 1) THEN
     393              :             CALL cp_subsys_set(subsys_bias(ibox)%subsys, &
     394           98 :                                particles=particles_bias(ibox)%list)
     395              :          END IF
     396              :       END DO
     397              : 
     398              :       ! deallocate some stuff
     399          368 :       DEALLOCATE (subsys_bias)
     400          368 :       DEALLOCATE (particles_bias)
     401              : 
     402              : ! end the timing
     403          368 :       CALL timestop(handle)
     404              : 
     405          368 :    END SUBROUTINE mc_Quickstep_move
     406              : 
     407              : ! **************************************************************************************************
     408              : !> \brief attempts a swap move between two simulation boxes
     409              : !> \param mc_par the mc parameters for the force envs of the boxes
     410              : !> \param force_env the force environments for the boxes
     411              : !> \param bias_env the force environments used to bias moves for the boxes
     412              : !> \param moves the structure that keeps track of how many moves have been
     413              : !>               accepted/rejected for both boxes
     414              : !> \param energy_check the running total of how much the energy has changed
     415              : !>                      since the initial configuration
     416              : !> \param r_old the coordinates of the last accepted move involving a
     417              : !>               full potential calculation for both boxes
     418              : !> \param old_energy the energy of the last accepted move involving a
     419              : !>                    a full potential calculation
     420              : !> \param input_declaration ...
     421              : !> \param para_env the parallel environment for this simulation
     422              : !> \param bias_energy_old the energies of both boxes computed using the biasing
     423              : !>        potential
     424              : !> \param last_bias_energy the energy for the biased simulations
     425              : !> \param rng_stream the stream we pull random numbers from
     426              : !> \author MJM
     427              : ! **************************************************************************************************
     428           22 :    SUBROUTINE mc_ge_swap_move(mc_par, force_env, bias_env, moves, &
     429           22 :                               energy_check, r_old, old_energy, input_declaration, &
     430              :                               para_env, bias_energy_old, last_bias_energy, &
     431              :                               rng_stream)
     432              : 
     433              :       TYPE(mc_simulation_parameters_p_type), &
     434              :          DIMENSION(:), POINTER                           :: mc_par
     435              :       TYPE(force_env_p_type), DIMENSION(:), POINTER      :: force_env, bias_env
     436              :       TYPE(mc_moves_p_type), DIMENSION(:, :), POINTER    :: moves
     437              :       REAL(KIND=dp), DIMENSION(1:2), INTENT(INOUT)       :: energy_check
     438              :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT)   :: r_old
     439              :       REAL(KIND=dp), DIMENSION(1:2), INTENT(INOUT)       :: old_energy
     440              :       TYPE(section_type), POINTER                        :: input_declaration
     441              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     442              :       REAL(KIND=dp), DIMENSION(1:2), INTENT(INOUT)       :: bias_energy_old, last_bias_energy
     443              :       TYPE(rng_stream_type), INTENT(INOUT)               :: rng_stream
     444              : 
     445              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'mc_ge_swap_move'
     446              : 
     447              :       CHARACTER(default_string_length), ALLOCATABLE, &
     448           22 :          DIMENSION(:)                                    :: atom_names_insert, atom_names_remove
     449              :       CHARACTER(default_string_length), &
     450           22 :          DIMENSION(:, :), POINTER                        :: atom_names
     451              :       CHARACTER(LEN=200)                                 :: fft_lib
     452              :       CHARACTER(LEN=40), DIMENSION(1:2)                  :: dat_file
     453              :       INTEGER :: end_mol, handle, iatom, ibox, idim, iiatom, imolecule, ins_atoms, insert_box, &
     454              :          ipart, itype, jbox, molecule_type, nmol_types, nswapmoves, print_level, rem_atoms, &
     455              :          remove_box, source, start_atom_ins, start_atom_rem, start_mol
     456           22 :       INTEGER, DIMENSION(:), POINTER                     :: mol_type, mol_type_test, nunits, &
     457           22 :                                                             nunits_tot
     458           22 :       INTEGER, DIMENSION(:, :), POINTER                  :: nchains, nchains_test
     459              :       LOGICAL                                            :: ionode, lbias, loverlap, loverlap_ins, &
     460              :                                                             loverlap_rem
     461           22 :       REAL(dp), DIMENSION(:), POINTER                    :: eta_insert, eta_remove, pmswap_mol
     462           22 :       REAL(dp), DIMENSION(:, :), POINTER                 :: insert_coords, remove_coords
     463              :       REAL(KIND=dp) :: BETA, del_quickstep_energy, exp_max_val, exp_min_val, max_val, min_val, &
     464              :          prefactor, rand, rdum, vol_insert, vol_remove, w, weight_new, weight_old
     465           22 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: cbmc_energies, r_cbmc, r_insert_mol
     466              :       REAL(KIND=dp), DIMENSION(1:2)                      :: bias_energy_new, new_energy
     467              :       REAL(KIND=dp), DIMENSION(1:3)                      :: abc_insert, abc_remove, center_of_mass, &
     468              :                                                             displace_molecule, pos_insert
     469           22 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: mass
     470              :       TYPE(cell_type), POINTER                           :: cell_insert, cell_remove
     471           22 :       TYPE(cp_subsys_p_type), DIMENSION(:), POINTER      :: oldsys
     472              :       TYPE(cp_subsys_type), POINTER                      :: insert_sys, remove_sys
     473           22 :       TYPE(force_env_p_type), DIMENSION(:), POINTER      :: test_env, test_env_bias
     474              :       TYPE(mc_input_file_type), POINTER                  :: mc_bias_file, mc_input_file
     475              :       TYPE(mc_molecule_info_type), POINTER               :: mc_molecule_info, mc_molecule_info_test
     476              :       TYPE(mp_comm_type)                                 :: group
     477           22 :       TYPE(particle_list_p_type), DIMENSION(:), POINTER  :: particles_old
     478              :       TYPE(particle_list_type), POINTER                  :: particles_insert, particles_remove
     479              : 
     480              : ! begin the timing of the subroutine
     481              : 
     482           22 :       CALL timeset(routineN, handle)
     483              : 
     484              : ! reset the overlap flag
     485              :       loverlap = .FALSE.
     486              : 
     487              : ! nullify some pointers
     488           22 :       NULLIFY (particles_old, mol_type, mol_type_test, mc_input_file, mc_bias_file)
     489           22 :       NULLIFY (oldsys, atom_names, pmswap_mol, insert_coords, remove_coords)
     490           22 :       NULLIFY (eta_insert, eta_remove)
     491              : 
     492              : ! grab some stuff from mc_par
     493              :       CALL get_mc_par(mc_par(1)%mc_par, ionode=ionode, BETA=BETA, &
     494              :                       max_val=max_val, min_val=min_val, exp_max_val=exp_max_val, &
     495              :                       exp_min_val=exp_min_val, nswapmoves=nswapmoves, group=group, source=source, &
     496              :                       lbias=lbias, dat_file=dat_file(1), fft_lib=fft_lib, &
     497           22 :                       mc_molecule_info=mc_molecule_info, pmswap_mol=pmswap_mol)
     498              :       CALL get_mc_molecule_info(mc_molecule_info, nchains=nchains, &
     499              :                                 nunits=nunits, nunits_tot=nunits_tot, nmol_types=nmol_types, &
     500           22 :                                 atom_names=atom_names, mass=mass, mol_type=mol_type)
     501              : 
     502           22 :       print_level = 1
     503              : 
     504           22 :       CALL get_mc_par(mc_par(2)%mc_par, dat_file=dat_file(2))
     505              : 
     506              : ! allocate some stuff
     507           66 :       ALLOCATE (oldsys(1:2))
     508           66 :       ALLOCATE (particles_old(1:2))
     509              : 
     510              : ! get the old coordinates
     511           66 :       DO ibox = 1, 2
     512              :          CALL force_env_get(force_env(ibox)%force_env, &
     513           44 :                             subsys=oldsys(ibox)%subsys)
     514              :          CALL cp_subsys_get(oldsys(ibox)%subsys, &
     515           66 :                             particles=particles_old(ibox)%list)
     516              :       END DO
     517              : 
     518              : !     choose a direction to swap
     519           22 :       IF (ionode) rand = rng_stream%next()
     520           22 :       CALL group%bcast(rand, source)
     521              : 
     522           22 :       IF (rand <= 0.50E0_dp) THEN
     523           12 :          remove_box = 1
     524           12 :          insert_box = 2
     525              :       ELSE
     526           10 :          remove_box = 2
     527           10 :          insert_box = 1
     528              :       END IF
     529              : 
     530              : ! now assign the eta values for the insert and remove boxes
     531           22 :       CALL get_mc_par(mc_par(remove_box)%mc_par, eta=eta_remove)
     532           22 :       CALL get_mc_par(mc_par(insert_box)%mc_par, eta=eta_insert)
     533              : 
     534              : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! testing
     535              : !      remove_box=2
     536              : !      insert_box=1
     537              : 
     538              : ! now choose a molecule type at random
     539           22 :       IF (ionode) rand = rng_stream%next()
     540           22 :       CALL group%bcast(rand, source)
     541           34 :       DO itype = 1, nmol_types
     542           34 :          IF (rand < pmswap_mol(itype)) THEN
     543              :             molecule_type = itype
     544              :             EXIT
     545              :          END IF
     546              :       END DO
     547              : 
     548              : ! record the attempt for the box the particle is to be inserted into
     549              :       moves(molecule_type, insert_box)%moves%swap%attempts = &
     550           22 :          moves(molecule_type, insert_box)%moves%swap%attempts + 1
     551              : 
     552              : ! now choose a random molecule to remove from the removal box, checking
     553              : ! to make sure the box isn't empty
     554           22 :       IF (nchains(molecule_type, remove_box) == 0) THEN
     555            0 :          loverlap = .TRUE.
     556              :          moves(molecule_type, insert_box)%moves%empty = &
     557            0 :             moves(molecule_type, insert_box)%moves%empty + 1
     558              :       ELSE
     559              : 
     560           22 :          IF (ionode) rand = rng_stream%next()
     561           22 :          CALL group%bcast(rand, source)
     562           22 :          imolecule = CEILING(rand*nchains(molecule_type, remove_box))
     563              : ! figure out the atom number this molecule starts on
     564           22 :          start_atom_rem = 1
     565           34 :          DO itype = 1, nmol_types
     566           34 :             IF (itype == molecule_type) THEN
     567           22 :                start_atom_rem = start_atom_rem + (imolecule - 1)*nunits(itype)
     568           22 :                EXIT
     569              :             ELSE
     570           12 :                start_atom_rem = start_atom_rem + nchains(itype, remove_box)*nunits(itype)
     571              :             END IF
     572              :          END DO
     573              : 
     574              : ! check for overlap
     575           22 :          start_mol = 1
     576           32 :          DO jbox = 1, remove_box - 1
     577           52 :             start_mol = start_mol + SUM(nchains(:, jbox))
     578              :          END DO
     579           66 :          end_mol = start_mol + SUM(nchains(:, remove_box)) - 1
     580              :          CALL check_for_overlap(force_env(remove_box)%force_env, &
     581           22 :                                 nchains(:, remove_box), nunits, loverlap, mol_type(start_mol:end_mol))
     582           22 :          IF (loverlap) CALL cp_abort(__LOCATION__, &
     583            0 :                                      'CBMC swap move found an overlap in the old remove config')
     584           22 :          start_mol = 1
     585           34 :          DO jbox = 1, insert_box - 1
     586           58 :             start_mol = start_mol + SUM(nchains(:, jbox))
     587              :          END DO
     588           66 :          end_mol = start_mol + SUM(nchains(:, insert_box)) - 1
     589              :          CALL check_for_overlap(force_env(insert_box)%force_env, &
     590           22 :                                 nchains(:, insert_box), nunits, loverlap, mol_type(start_mol:end_mol))
     591           22 :          IF (loverlap) CALL cp_abort(__LOCATION__, &
     592            0 :                                      'CBMC swap move found an overlap in the old insert config')
     593              :       END IF
     594              : 
     595           22 :       IF (loverlap) THEN
     596            0 :          DEALLOCATE (oldsys)
     597            0 :          DEALLOCATE (particles_old)
     598            0 :          CALL timestop(handle)
     599            0 :          RETURN
     600              :       END IF
     601              : 
     602              : ! figure out how many atoms will be in each box after the move
     603           22 :       ins_atoms = nunits_tot(insert_box) + nunits(molecule_type)
     604           22 :       rem_atoms = nunits_tot(remove_box) - nunits(molecule_type)
     605              : ! now allocate the arrays that will hold the coordinates and the
     606              : ! atom name, for writing to the dat file
     607           22 :       IF (rem_atoms == 0) THEN
     608            0 :          ALLOCATE (remove_coords(1:3, 1:nunits(1)))
     609            0 :          ALLOCATE (atom_names_remove(1:nunits(1)))
     610              :       ELSE
     611           66 :          ALLOCATE (remove_coords(1:3, 1:rem_atoms))
     612           66 :          ALLOCATE (atom_names_remove(1:rem_atoms))
     613              :       END IF
     614           66 :       ALLOCATE (insert_coords(1:3, 1:ins_atoms))
     615           66 :       ALLOCATE (atom_names_insert(1:ins_atoms))
     616              : 
     617              : ! grab the cells for later...acceptance and insertion
     618           22 :       IF (lbias) THEN
     619              :          CALL force_env_get(bias_env(insert_box)%force_env, &
     620           22 :                             cell=cell_insert)
     621              :          CALL force_env_get(bias_env(remove_box)%force_env, &
     622           22 :                             cell=cell_remove)
     623              :       ELSE
     624              :          CALL force_env_get(force_env(insert_box)%force_env, &
     625            0 :                             cell=cell_insert)
     626              :          CALL force_env_get(force_env(remove_box)%force_env, &
     627            0 :                             cell=cell_remove)
     628              :       END IF
     629           22 :       CALL get_cell(cell_remove, abc=abc_remove, deth=vol_remove)
     630           22 :       CALL get_cell(cell_insert, abc=abc_insert, deth=vol_insert)
     631              : 
     632           22 :       IF (ionode) THEN
     633              : ! choose an insertion point
     634           44 :          DO idim = 1, 3
     635           33 :             rand = rng_stream%next()
     636           44 :             pos_insert(idim) = rand*abc_insert(idim)
     637              :          END DO
     638              :       END IF
     639           22 :       CALL group%bcast(pos_insert, source)
     640              : 
     641              : ! allocate some arrays we'll be using
     642           66 :       ALLOCATE (r_insert_mol(1:3, 1:nunits(molecule_type)))
     643              : 
     644           22 :       iiatom = 1
     645           64 :       DO iatom = start_atom_rem, start_atom_rem + nunits(molecule_type) - 1
     646              :          r_insert_mol(1:3, iiatom) = &
     647          168 :             particles_old(remove_box)%list%els(iatom)%r(1:3)
     648           64 :          iiatom = iiatom + 1
     649              :       END DO
     650              : 
     651              : !     find the center of mass of the molecule
     652              :       CALL get_center_of_mass(r_insert_mol(:, :), nunits(molecule_type), &
     653           22 :                               center_of_mass(:), mass(:, molecule_type))
     654              : 
     655              : !     move the center of mass to the insertion point
     656           88 :       displace_molecule(1:3) = pos_insert(1:3) - center_of_mass(1:3)
     657           64 :       DO iatom = 1, nunits(molecule_type)
     658              :          r_insert_mol(1:3, iatom) = r_insert_mol(1:3, iatom) + &
     659          190 :                                     displace_molecule(1:3)
     660              :       END DO
     661              : 
     662              : ! prepare the insertion coordinates to be written to the .dat file so
     663              : ! we can create a new force environment...remember there is still a particle
     664              : ! in the box even if nchain=0
     665           66 :       IF (SUM(nchains(:, insert_box)) == 0) THEN
     666            0 :          DO iatom = 1, nunits(molecule_type)
     667            0 :             insert_coords(1:3, iatom) = r_insert_mol(1:3, iatom)
     668              :             atom_names_insert(iatom) = &
     669            0 :                particles_old(remove_box)%list%els(start_atom_rem + iatom - 1)%atomic_kind%name
     670              :          END DO
     671            0 :          start_atom_ins = 1
     672              :       ELSE
     673              : ! the problem is I can't just tack the new molecule on to the end,
     674              : ! because of reading in the dat_file...the topology stuff will crash
     675              : ! if the molecules aren't all grouped together, so I have to insert it
     676              : ! at the end of the section of molecules with the same type, then
     677              : ! remember the start number for the CBMC stuff
     678           22 :          start_atom_ins = 1
     679           34 :          DO itype = 1, nmol_types
     680              :             start_atom_ins = start_atom_ins + &
     681           34 :                              nchains(itype, insert_box)*nunits(itype)
     682           34 :             IF (itype == molecule_type) EXIT
     683              :          END DO
     684              : 
     685          504 :          DO iatom = 1, start_atom_ins - 1
     686              :             insert_coords(1:3, iatom) = &
     687         1928 :                particles_old(insert_box)%list%els(iatom)%r(1:3)
     688              :             atom_names_insert(iatom) = &
     689          504 :                particles_old(insert_box)%list%els(iatom)%atomic_kind%name
     690              :          END DO
     691           22 :          iiatom = 1
     692           64 :          DO iatom = start_atom_ins, start_atom_ins + nunits(molecule_type) - 1
     693          168 :             insert_coords(1:3, iatom) = r_insert_mol(1:3, iiatom)
     694           42 :             atom_names_insert(iatom) = atom_names(iiatom, molecule_type)
     695           64 :             iiatom = iiatom + 1
     696              :          END DO
     697           76 :          DO iatom = start_atom_ins + nunits(molecule_type), ins_atoms
     698              :             insert_coords(1:3, iatom) = &
     699          216 :                particles_old(insert_box)%list%els(iatom - nunits(molecule_type))%r(1:3)
     700              :             atom_names_insert(iatom) = &
     701           76 :                particles_old(insert_box)%list%els(iatom - nunits(molecule_type))%atomic_kind%name
     702              :          END DO
     703              :       END IF
     704              : 
     705              : ! fold the coordinates into the box and check for overlaps
     706           22 :       start_mol = 1
     707           34 :       DO jbox = 1, insert_box - 1
     708           58 :          start_mol = start_mol + SUM(nchains(:, jbox))
     709              :       END DO
     710           66 :       end_mol = start_mol + SUM(nchains(:, insert_box)) - 1
     711              : 
     712              : ! make the .dat file
     713           22 :       IF (ionode) THEN
     714              : 
     715           11 :          nchains(molecule_type, insert_box) = nchains(molecule_type, insert_box) + 1
     716           11 :          IF (lbias) THEN
     717           11 :             CALL get_mc_par(mc_par(insert_box)%mc_par, mc_bias_file=mc_bias_file)
     718              :             CALL mc_make_dat_file_new(insert_coords(:, :), atom_names_insert(:), ins_atoms, &
     719              :                                       abc_insert(:), dat_file(insert_box), nchains(:, insert_box), &
     720           11 :                                       mc_bias_file)
     721              :          ELSE
     722            0 :             CALL get_mc_par(mc_par(insert_box)%mc_par, mc_input_file=mc_input_file)
     723              :             CALL mc_make_dat_file_new(insert_coords(:, :), atom_names_insert(:), ins_atoms, &
     724              :                                       abc_insert(:), dat_file(insert_box), nchains(:, insert_box), &
     725            0 :                                       mc_input_file)
     726              :          END IF
     727           11 :          nchains(molecule_type, insert_box) = nchains(molecule_type, insert_box) - 1
     728              : 
     729              :       END IF
     730              : 
     731              : ! now do the same for the removal box...be careful not to make an empty box
     732           22 :       IF (rem_atoms == 0) THEN
     733            0 :          DO iatom = 1, nunits(molecule_type)
     734            0 :             remove_coords(1:3, iatom) = r_insert_mol(1:3, iatom)
     735            0 :             atom_names_remove(iatom) = atom_names(iatom, molecule_type)
     736              :          END DO
     737              : 
     738              : ! need to adjust nchains, because otherwise if we are removing a molecule type
     739              : ! that is not the first molecule, the dat file will have two molecules in it but
     740              : ! only the coordinates for one
     741            0 :          nchains(molecule_type, remove_box) = nchains(molecule_type, remove_box) - 1
     742            0 :          IF (ionode) THEN
     743            0 :             IF (lbias) THEN
     744            0 :                CALL get_mc_par(mc_par(remove_box)%mc_par, mc_bias_file=mc_bias_file)
     745              :                CALL mc_make_dat_file_new(remove_coords(:, :), atom_names_remove(:), rem_atoms, &
     746              :                                          abc_remove(:), dat_file(remove_box), nchains(:, remove_box), &
     747            0 :                                          mc_bias_file)
     748              :             ELSE
     749            0 :                CALL get_mc_par(mc_par(remove_box)%mc_par, mc_input_file=mc_input_file)
     750              :                CALL mc_make_dat_file_new(remove_coords(:, :), atom_names_remove(:), rem_atoms, &
     751              :                                          abc_remove(:), dat_file(remove_box), nchains(:, remove_box), &
     752            0 :                                          mc_input_file)
     753              :             END IF
     754              : 
     755              :          END IF
     756            0 :          nchains(molecule_type, remove_box) = nchains(molecule_type, remove_box) + 1
     757              : 
     758              :       ELSE
     759          368 :          DO iatom = 1, start_atom_rem - 1
     760              :             remove_coords(1:3, iatom) = &
     761         1384 :                particles_old(remove_box)%list%els(iatom)%r(1:3)
     762              :             atom_names_remove(iatom) = &
     763          368 :                particles_old(remove_box)%list%els(iatom)%atomic_kind%name
     764              :          END DO
     765          198 :          DO iatom = start_atom_rem + nunits(molecule_type), nunits_tot(remove_box)
     766              :             remove_coords(1:3, iatom - nunits(molecule_type)) = &
     767          704 :                particles_old(remove_box)%list%els(iatom)%r(1:3)
     768              :             atom_names_remove(iatom - nunits(molecule_type)) = &
     769          198 :                particles_old(remove_box)%list%els(iatom)%atomic_kind%name
     770              :          END DO
     771              : 
     772              : ! make the .dat file
     773           22 :          IF (ionode) THEN
     774           11 :             nchains(molecule_type, remove_box) = nchains(molecule_type, remove_box) - 1
     775           11 :             IF (lbias) THEN
     776           11 :                CALL get_mc_par(mc_par(remove_box)%mc_par, mc_bias_file=mc_bias_file)
     777              :                CALL mc_make_dat_file_new(remove_coords(:, :), atom_names_remove(:), rem_atoms, &
     778              :                                          abc_remove(:), dat_file(remove_box), nchains(:, remove_box), &
     779           11 :                                          mc_bias_file)
     780              :             ELSE
     781            0 :                CALL get_mc_par(mc_par(remove_box)%mc_par, mc_input_file=mc_input_file)
     782              :                CALL mc_make_dat_file_new(remove_coords(:, :), atom_names_remove(:), rem_atoms, &
     783              :                                          abc_remove(:), dat_file(remove_box), nchains(:, remove_box), &
     784            0 :                                          mc_input_file)
     785              :             END IF
     786           11 :             nchains(molecule_type, remove_box) = nchains(molecule_type, remove_box) + 1
     787              : 
     788              :          END IF
     789              :       END IF
     790              : 
     791              : ! deallocate r_insert_mol
     792           22 :       DEALLOCATE (r_insert_mol)
     793              : 
     794              : ! now let's create the two new environments with the different number
     795              : ! of molecules
     796           66 :       ALLOCATE (test_env(1:2))
     797              :       CALL mc_create_force_env(test_env(insert_box)%force_env, input_declaration, &
     798           22 :                                para_env, dat_file(insert_box))
     799              :       CALL mc_create_force_env(test_env(remove_box)%force_env, input_declaration, &
     800           22 :                                para_env, dat_file(remove_box))
     801              : 
     802              : ! allocate an array we'll need
     803           44 :       ALLOCATE (r_cbmc(1:3, 1:ins_atoms))
     804           66 :       ALLOCATE (cbmc_energies(1:nswapmoves, 1:2))
     805              : 
     806              :       loverlap_ins = .FALSE.
     807           22 :       loverlap_rem = .FALSE.
     808              : 
     809              : ! compute the new molecule information...we need this for the CBMC part
     810           22 :       IF (rem_atoms == 0) THEN
     811              :          CALL mc_determine_molecule_info(test_env, mc_molecule_info_test, &
     812            0 :                                          box_number=remove_box)
     813              :       ELSE
     814           22 :          CALL mc_determine_molecule_info(test_env, mc_molecule_info_test)
     815              :       END IF
     816              :       CALL get_mc_molecule_info(mc_molecule_info_test, nchains=nchains_test, &
     817           22 :                                 mol_type=mol_type_test)
     818              : 
     819              : ! figure out the position of the molecule we're inserting, and the
     820              : ! Rosenbluth weight
     821           22 :       start_mol = 1
     822           34 :       DO jbox = 1, insert_box - 1
     823           58 :          start_mol = start_mol + SUM(nchains_test(:, jbox))
     824              :       END DO
     825           66 :       end_mol = start_mol + SUM(nchains_test(:, insert_box)) - 1
     826              : 
     827           22 :       IF (lbias) THEN
     828              :          CALL generate_cbmc_swap_config(test_env(insert_box)%force_env, &
     829              :                                         BETA, max_val, min_val, exp_max_val, &
     830              :                                         exp_min_val, nswapmoves, weight_new, start_atom_ins, ins_atoms, nunits(:), &
     831              :                                         nunits(molecule_type), mass(:, molecule_type), loverlap_ins, bias_energy_new(insert_box), &
     832              :                                         bias_energy_old(insert_box), ionode, .FALSE., mol_type_test(start_mol:end_mol), &
     833           22 :                                         nchains_test(:, insert_box), source, group, rng_stream)
     834              : 
     835              : ! the energy that comes out of the above routine is the difference...we want
     836              : ! the real energy for the acceptance rule...we don't do this for the
     837              : ! lbias=.false. case because it doesn't appear in the acceptance rule, and
     838              : ! we compensate in case of acceptance
     839              :          bias_energy_new(insert_box) = bias_energy_new(insert_box) + &
     840           22 :                                        bias_energy_old(insert_box)
     841              :       ELSE
     842              :          CALL generate_cbmc_swap_config(test_env(insert_box)%force_env, &
     843              :                                         BETA, max_val, min_val, exp_max_val, &
     844              :                                         exp_min_val, nswapmoves, weight_new, start_atom_ins, ins_atoms, nunits(:), &
     845              :                                         nunits(molecule_type), mass(:, molecule_type), loverlap_ins, new_energy(insert_box), &
     846              :                                         old_energy(insert_box), ionode, .FALSE., mol_type_test(start_mol:end_mol), &
     847            0 :                                         nchains_test(:, insert_box), source, group, rng_stream)
     848              :       END IF
     849              : 
     850              :       CALL force_env_get(test_env(insert_box)%force_env, &
     851           22 :                          subsys=insert_sys)
     852              :       CALL cp_subsys_get(insert_sys, &
     853           22 :                          particles=particles_insert)
     854              : 
     855          600 :       DO iatom = 1, ins_atoms
     856         2334 :          r_cbmc(1:3, iatom) = particles_insert%els(iatom)%r(1:3)
     857              :       END DO
     858              : 
     859              : ! make sure there is no overlap
     860              : 
     861           22 :       IF (loverlap_ins .OR. loverlap_rem) THEN
     862              : ! deallocate some stuff
     863            0 :          CALL mc_molecule_info_destroy(mc_molecule_info_test)
     864            0 :          CALL force_env_release(test_env(insert_box)%force_env)
     865            0 :          CALL force_env_release(test_env(remove_box)%force_env)
     866            0 :          DEALLOCATE (insert_coords)
     867            0 :          DEALLOCATE (remove_coords)
     868            0 :          DEALLOCATE (r_cbmc)
     869            0 :          DEALLOCATE (cbmc_energies)
     870            0 :          DEALLOCATE (oldsys)
     871            0 :          DEALLOCATE (particles_old)
     872            0 :          DEALLOCATE (test_env)
     873            0 :          CALL timestop(handle)
     874            0 :          RETURN
     875              :       END IF
     876              : 
     877              : ! broadcast the chosen coordinates to all processors
     878              : 
     879              :       CALL force_env_get(test_env(insert_box)%force_env, &
     880           22 :                          subsys=insert_sys)
     881              :       CALL cp_subsys_get(insert_sys, &
     882           22 :                          particles=particles_insert)
     883              : 
     884          600 :       DO iatom = 1, ins_atoms
     885              :          particles_insert%els(iatom)%r(1:3) = &
     886         2334 :             r_cbmc(1:3, iatom)
     887              :       END DO
     888              : 
     889              : ! if we made it this far, we have no overlaps
     890              :       moves(molecule_type, insert_box)%moves%grown = &
     891           22 :          moves(molecule_type, insert_box)%moves%grown + 1
     892              : 
     893              : ! if we're biasing, we need to make environments with the non-biasing
     894              : ! potentials, and calculate the energies
     895           22 :       IF (lbias) THEN
     896              : 
     897           66 :          ALLOCATE (test_env_bias(1:2))
     898              : 
     899              : ! first, the environment to which we added a molecule
     900           22 :          CALL get_mc_par(mc_par(insert_box)%mc_par, mc_input_file=mc_input_file)
     901           22 :          IF (ionode) CALL mc_make_dat_file_new(r_cbmc(:, :), atom_names_insert(:), ins_atoms, &
     902              :                                                abc_insert(:), dat_file(insert_box), nchains_test(:, insert_box), &
     903           11 :                                                mc_input_file)
     904           22 :          test_env_bias(insert_box)%force_env => test_env(insert_box)%force_env
     905           22 :          NULLIFY (test_env(insert_box)%force_env)
     906              :          CALL mc_create_force_env(test_env(insert_box)%force_env, input_declaration, &
     907           22 :                                   para_env, dat_file(insert_box))
     908              : 
     909              :          CALL force_env_calc_energy_force(test_env(insert_box)%force_env, &
     910           22 :                                           calc_force=.FALSE.)
     911              :          CALL force_env_get(test_env(insert_box)%force_env, &
     912           22 :                             potential_energy=new_energy(insert_box))
     913              : 
     914              : ! now the environment that has one less molecule
     915           66 :          IF (SUM(nchains_test(:, remove_box)) == 0) THEN
     916            0 :             CALL get_mc_par(mc_par(remove_box)%mc_par, mc_input_file=mc_input_file)
     917            0 :             IF (ionode) CALL mc_make_dat_file_new(remove_coords(:, :), atom_names_remove(:), rem_atoms, &
     918              :                                                   abc_remove(:), dat_file(remove_box), nchains_test(:, remove_box), &
     919            0 :                                                   mc_input_file)
     920            0 :             test_env_bias(remove_box)%force_env => test_env(remove_box)%force_env
     921            0 :             NULLIFY (test_env(remove_box)%force_env)
     922              :             CALL mc_create_force_env(test_env(remove_box)%force_env, input_declaration, &
     923            0 :                                      para_env, dat_file(remove_box))
     924            0 :             new_energy(remove_box) = 0.0E0_dp
     925            0 :             bias_energy_new(remove_box) = 0.0E0_dp
     926              :          ELSE
     927           22 :             CALL get_mc_par(mc_par(remove_box)%mc_par, mc_input_file=mc_input_file)
     928           22 :             IF (ionode) CALL mc_make_dat_file_new(remove_coords(:, :), atom_names_remove(:), rem_atoms, &
     929              :                                                   abc_remove(:), dat_file(remove_box), nchains_test(:, remove_box), &
     930           11 :                                                   mc_input_file)
     931           22 :             test_env_bias(remove_box)%force_env => test_env(remove_box)%force_env
     932           22 :             NULLIFY (test_env(remove_box)%force_env)
     933              :             CALL mc_create_force_env(test_env(remove_box)%force_env, input_declaration, &
     934           22 :                                      para_env, dat_file(remove_box))
     935              :             CALL force_env_calc_energy_force(test_env(remove_box)%force_env, &
     936           22 :                                              calc_force=.FALSE.)
     937              :             CALL force_env_get(test_env(remove_box)%force_env, &
     938           22 :                                potential_energy=new_energy(remove_box))
     939              :             CALL force_env_calc_energy_force(test_env_bias(remove_box)%force_env, &
     940           22 :                                              calc_force=.FALSE.)
     941              :             CALL force_env_get(test_env_bias(remove_box)%force_env, &
     942           22 :                                potential_energy=bias_energy_new(remove_box))
     943              :          END IF
     944              :       ELSE
     945            0 :          IF (SUM(nchains_test(:, remove_box)) == 0) THEN
     946            0 :             new_energy(remove_box) = 0.0E0_dp
     947              :          ELSE
     948              :             CALL force_env_calc_energy_force(test_env(remove_box)%force_env, &
     949            0 :                                              calc_force=.FALSE.)
     950              :             CALL force_env_get(test_env(remove_box)%force_env, &
     951            0 :                                potential_energy=new_energy(remove_box))
     952              :          END IF
     953              :       END IF
     954              : 
     955              : ! now we need to figure out the rosenbluth weight for the old configuration...
     956              : ! we wait until now to do that because we need the energy of the box that
     957              : ! has had a molecule removed...notice we use the environment that has not
     958              : ! had a molecule removed for the CBMC configurations, and therefore nchains
     959              : ! and mol_type instead of nchains_test and mol_type_test
     960           22 :       start_mol = 1
     961           32 :       DO jbox = 1, remove_box - 1
     962           52 :          start_mol = start_mol + SUM(nchains(:, jbox))
     963              :       END DO
     964           66 :       end_mol = start_mol + SUM(nchains(:, remove_box)) - 1
     965           22 :       IF (lbias) THEN
     966              :          CALL generate_cbmc_swap_config(bias_env(remove_box)%force_env, &
     967              :                                         BETA, max_val, min_val, exp_max_val, &
     968              :                                         exp_min_val, nswapmoves, weight_old, start_atom_rem, nunits_tot(remove_box), &
     969              :                                         nunits(:), nunits(molecule_type), mass(:, molecule_type), loverlap_rem, rdum, &
     970              :                                         bias_energy_new(remove_box), ionode, .TRUE., mol_type(start_mol:end_mol), &
     971           22 :                                         nchains(:, remove_box), source, group, rng_stream)
     972              :       ELSE
     973              :          CALL generate_cbmc_swap_config(force_env(remove_box)%force_env, &
     974              :                                         BETA, max_val, min_val, exp_max_val, &
     975              :                                         exp_min_val, nswapmoves, weight_old, start_atom_rem, nunits_tot(remove_box), &
     976              :                                         nunits(:), nunits(molecule_type), mass(:, molecule_type), loverlap_rem, rdum, &
     977              :                                         new_energy(remove_box), ionode, .TRUE., mol_type(start_mol:end_mol), &
     978            0 :                                         nchains(:, remove_box), source, group, rng_stream)
     979              :       END IF
     980              : 
     981              : ! figure out the prefactor to the boltzmann weight in the acceptance
     982              : ! rule, based on numbers of particles and volumes
     983              : 
     984              :       prefactor = REAL(nchains(molecule_type, remove_box), dp)/ &
     985              :                   REAL(nchains(molecule_type, insert_box) + 1, dp)* &
     986           22 :                   vol_insert/vol_remove
     987              : 
     988           22 :       IF (lbias) THEN
     989              : 
     990              :          del_quickstep_energy = (-BETA)*(new_energy(insert_box) - &
     991              :                                          old_energy(insert_box) + new_energy(remove_box) - &
     992              :                                          old_energy(remove_box) - (bias_energy_new(insert_box) + &
     993              :                                                                    bias_energy_new(remove_box) - bias_energy_old(insert_box) &
     994           22 :                                                                    - bias_energy_old(remove_box)))
     995              : 
     996           22 :          IF (del_quickstep_energy > exp_max_val) THEN
     997            0 :             del_quickstep_energy = max_val
     998           22 :          ELSE IF (del_quickstep_energy < exp_min_val) THEN
     999            0 :             del_quickstep_energy = min_val
    1000              :          ELSE
    1001           22 :             del_quickstep_energy = EXP(del_quickstep_energy)
    1002              :          END IF
    1003              :          w = prefactor*del_quickstep_energy*weight_new/weight_old &
    1004           22 :              *EXP(BETA*(eta_remove(molecule_type) - eta_insert(molecule_type)))
    1005              : 
    1006              :       ELSE
    1007              :          w = prefactor*weight_new/weight_old &
    1008            0 :              *EXP(BETA*(eta_remove(molecule_type) - eta_insert(molecule_type)))
    1009              : 
    1010              :       END IF
    1011              : 
    1012              : ! check if the move is accepted
    1013           22 :       IF (w >= 1.0E0_dp) THEN
    1014            8 :          rand = 0.0E0_dp
    1015              :       ELSE
    1016           14 :          IF (ionode) rand = rng_stream%next()
    1017           14 :          CALL group%bcast(rand, source)
    1018              :       END IF
    1019              : 
    1020              : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    1021           22 :       IF (rand < w) THEN
    1022              : 
    1023              : ! accept the move
    1024              : 
    1025              : !     accept the move
    1026              :          moves(molecule_type, insert_box)%moves%swap%successes = &
    1027           14 :             moves(molecule_type, insert_box)%moves%swap%successes + 1
    1028              : 
    1029              : ! we need to compensate for the fact that we take the difference in
    1030              : ! generate_cbmc_config to keep the exponetials small
    1031           14 :          IF (.NOT. lbias) THEN
    1032              :             new_energy(insert_box) = new_energy(insert_box) + &
    1033            0 :                                      old_energy(insert_box)
    1034              :          END IF
    1035              : 
    1036           42 :          DO ibox = 1, 2
    1037              : ! update energies
    1038              :             energy_check(ibox) = energy_check(ibox) + (new_energy(ibox) - &
    1039           28 :                                                        old_energy(ibox))
    1040           28 :             old_energy(ibox) = new_energy(ibox)
    1041              : ! if we're biasing the update the biasing energy
    1042           42 :             IF (lbias) THEN
    1043           28 :                last_bias_energy(ibox) = bias_energy_new(ibox)
    1044           28 :                bias_energy_old(ibox) = bias_energy_new(ibox)
    1045              :             END IF
    1046              : 
    1047              :          END DO
    1048              : 
    1049              : ! change particle numbers...basically destroy the old mc_molecule_info and attach
    1050              : ! the new stuff to the mc_pars
    1051              : ! figure out the molecule information for the new environments
    1052           14 :          CALL mc_molecule_info_destroy(mc_molecule_info)
    1053           14 :          CALL set_mc_par(mc_par(insert_box)%mc_par, mc_molecule_info=mc_molecule_info_test)
    1054           14 :          CALL set_mc_par(mc_par(remove_box)%mc_par, mc_molecule_info=mc_molecule_info_test)
    1055              : 
    1056              : ! update coordinates
    1057              :          CALL force_env_get(test_env(insert_box)%force_env, &
    1058           14 :                             subsys=insert_sys)
    1059              :          CALL cp_subsys_get(insert_sys, &
    1060           14 :                             particles=particles_insert)
    1061          376 :          DO ipart = 1, ins_atoms
    1062         1462 :             r_old(1:3, ipart, insert_box) = particles_insert%els(ipart)%r(1:3)
    1063              :          END DO
    1064              :          CALL force_env_get(test_env(remove_box)%force_env, &
    1065           14 :                             subsys=remove_sys)
    1066              :          CALL cp_subsys_get(remove_sys, &
    1067           14 :                             particles=particles_remove)
    1068          352 :          DO ipart = 1, rem_atoms
    1069         1366 :             r_old(1:3, ipart, remove_box) = particles_remove%els(ipart)%r(1:3)
    1070              :          END DO
    1071              : 
    1072              :          ! insertion box
    1073           14 :          CALL force_env_release(force_env(insert_box)%force_env)
    1074           14 :          force_env(insert_box)%force_env => test_env(insert_box)%force_env
    1075              : 
    1076              :          ! removal box
    1077           14 :          CALL force_env_release(force_env(remove_box)%force_env)
    1078           14 :          force_env(remove_box)%force_env => test_env(remove_box)%force_env
    1079              : 
    1080              : ! if we're biasing, update the bias_env
    1081           14 :          IF (lbias) THEN
    1082           14 :             CALL force_env_release(bias_env(insert_box)%force_env)
    1083           14 :             bias_env(insert_box)%force_env => test_env_bias(insert_box)%force_env
    1084           14 :             CALL force_env_release(bias_env(remove_box)%force_env)
    1085           14 :             bias_env(remove_box)%force_env => test_env_bias(remove_box)%force_env
    1086           14 :             DEALLOCATE (test_env_bias)
    1087              :          END IF
    1088              : 
    1089              :       ELSE
    1090              : 
    1091              : ! reject the move
    1092            8 :          CALL mc_molecule_info_destroy(mc_molecule_info_test)
    1093            8 :          CALL force_env_release(test_env(insert_box)%force_env)
    1094            8 :          CALL force_env_release(test_env(remove_box)%force_env)
    1095            8 :          IF (lbias) THEN
    1096            8 :             CALL force_env_release(test_env_bias(insert_box)%force_env)
    1097            8 :             CALL force_env_release(test_env_bias(remove_box)%force_env)
    1098            8 :             DEALLOCATE (test_env_bias)
    1099              :          END IF
    1100              :       END IF
    1101              : 
    1102              : ! deallocate some stuff
    1103           22 :       DEALLOCATE (insert_coords)
    1104           22 :       DEALLOCATE (remove_coords)
    1105           22 :       DEALLOCATE (test_env)
    1106           22 :       DEALLOCATE (cbmc_energies)
    1107           22 :       DEALLOCATE (r_cbmc)
    1108           22 :       DEALLOCATE (oldsys)
    1109           22 :       DEALLOCATE (particles_old)
    1110              : 
    1111              : ! end the timing
    1112           22 :       CALL timestop(handle)
    1113              : 
    1114           66 :    END SUBROUTINE mc_ge_swap_move
    1115              : 
    1116              : ! **************************************************************************************************
    1117              : !> \brief performs a Monte Carlo move that alters the volume of the simulation boxes,
    1118              : !>      keeping the total volume of the two boxes the same
    1119              : !> \param mc_par the mc parameters for the force env
    1120              : !> \param force_env the force environments used in the move
    1121              : !> \param moves the structure that keeps track of how many moves have been
    1122              : !>               accepted/rejected
    1123              : !> \param move_updates the structure that keeps track of how many moves have
    1124              : !>               been accepted/rejected since the last time the displacements
    1125              : !>               were updated
    1126              : !> \param nnstep the total number of Monte Carlo moves already performed
    1127              : !> \param old_energy the energy of the last accepted move involving an
    1128              : !>                    unbiased potential calculation
    1129              : !> \param energy_check the running total of how much the energy has changed
    1130              : !>                      since the initial configuration
    1131              : !> \param r_old the coordinates of the last accepted move involving a
    1132              : !>               Quickstep calculation
    1133              : !> \param rng_stream the stream we pull random numbers from
    1134              : !> \author MJM
    1135              : ! **************************************************************************************************
    1136           24 :    SUBROUTINE mc_ge_volume_move(mc_par, force_env, moves, move_updates, &
    1137           24 :                                 nnstep, old_energy, energy_check, r_old, rng_stream)
    1138              : 
    1139              :       TYPE(mc_simulation_parameters_p_type), &
    1140              :          DIMENSION(:), POINTER                           :: mc_par
    1141              :       TYPE(force_env_p_type), DIMENSION(:), POINTER      :: force_env
    1142              :       TYPE(mc_moves_p_type), DIMENSION(:, :), POINTER    :: moves, move_updates
    1143              :       INTEGER, INTENT(IN)                                :: nnstep
    1144              :       REAL(KIND=dp), DIMENSION(:), INTENT(INOUT)         :: old_energy, energy_check
    1145              :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT)   :: r_old
    1146              :       TYPE(rng_stream_type), INTENT(INOUT)               :: rng_stream
    1147              : 
    1148              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'mc_ge_volume_move'
    1149              : 
    1150              :       CHARACTER(LEN=200)                                 :: fft_lib
    1151              :       CHARACTER(LEN=40), DIMENSION(1:2)                  :: dat_file
    1152              :       INTEGER :: cl, end_atom, end_mol, handle, iatom, ibox, imolecule, iside, j, jatom, jbox, &
    1153              :          max_atoms, molecule_index, molecule_type, print_level, source, start_atom, start_mol
    1154           24 :       INTEGER, DIMENSION(:), POINTER                     :: mol_type, nunits, nunits_tot
    1155           24 :       INTEGER, DIMENSION(:, :), POINTER                  :: nchains
    1156              :       LOGICAL                                            :: ionode
    1157           24 :       LOGICAL, ALLOCATABLE, DIMENSION(:)                 :: loverlap
    1158              :       LOGICAL, DIMENSION(1:2)                            :: lempty
    1159           24 :       REAL(dp), DIMENSION(:, :), POINTER                 :: mass
    1160              :       REAL(KIND=dp)                                      :: BETA, prefactor, rand, rmvolume, &
    1161              :                                                             vol_dis, w
    1162           24 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: r
    1163              :       REAL(KIND=dp), DIMENSION(1:2)                      :: new_energy, volume_new, volume_old
    1164              :       REAL(KIND=dp), DIMENSION(1:3)                      :: center_of_mass, center_of_mass_new, diff
    1165              :       REAL(KIND=dp), DIMENSION(1:3, 1:2)                 :: abc, new_cell_length, old_cell_length
    1166              :       REAL(KIND=dp), DIMENSION(1:3, 1:3, 1:2)            :: hmat_test
    1167           24 :       TYPE(cell_p_type), DIMENSION(:), POINTER           :: cell, cell_old, cell_test
    1168           24 :       TYPE(cp_subsys_p_type), DIMENSION(:), POINTER      :: oldsys
    1169              :       TYPE(cp_subsys_type), POINTER                      :: subsys
    1170              :       TYPE(mc_molecule_info_type), POINTER               :: mc_molecule_info
    1171              :       TYPE(mp_comm_type)                                 :: group
    1172           24 :       TYPE(particle_list_p_type), DIMENSION(:), POINTER  :: particles_old
    1173              : 
    1174              : ! begin the timing of the subroutine
    1175              : 
    1176           24 :       CALL timeset(routineN, handle)
    1177              : 
    1178              : ! nullify some pointers
    1179           24 :       NULLIFY (particles_old, cell, oldsys, cell_old, cell_test, subsys)
    1180              : 
    1181              : ! get some data from mc_par
    1182              :       CALL get_mc_par(mc_par(1)%mc_par, ionode=ionode, source=source, &
    1183              :                       group=group, dat_file=dat_file(1), rmvolume=rmvolume, &
    1184              :                       BETA=BETA, cl=cl, fft_lib=fft_lib, &
    1185           24 :                       mc_molecule_info=mc_molecule_info)
    1186              :       CALL get_mc_molecule_info(mc_molecule_info, nunits_tot=nunits_tot, &
    1187           24 :                                 mass=mass, nchains=nchains, nunits=nunits, mol_type=mol_type)
    1188              : 
    1189           24 :       print_level = 1
    1190           24 :       CALL get_mc_par(mc_par(2)%mc_par, dat_file=dat_file(2))
    1191              : 
    1192              : ! allocate some stuff
    1193           24 :       max_atoms = MAX(nunits_tot(1), nunits_tot(2))
    1194           96 :       ALLOCATE (r(1:3, max_atoms, 1:2))
    1195           72 :       ALLOCATE (oldsys(1:2))
    1196           72 :       ALLOCATE (particles_old(1:2))
    1197           72 :       ALLOCATE (cell(1:2))
    1198           72 :       ALLOCATE (cell_test(1:2))
    1199           72 :       ALLOCATE (cell_old(1:2))
    1200           24 :       ALLOCATE (loverlap(1:2))
    1201              : 
    1202              : ! check for empty boxes...need to be careful because we can't build
    1203              : ! a force_env with no particles
    1204           72 :       DO ibox = 1, 2
    1205           48 :          lempty(ibox) = .FALSE.
    1206          168 :          IF (SUM(nchains(:, ibox)) == 0) THEN
    1207            0 :             lempty(ibox) = .TRUE.
    1208              :          END IF
    1209              :       END DO
    1210              : 
    1211              : ! record the attempt
    1212           72 :       DO ibox = 1, 2
    1213              :          moves(1, ibox)%moves%volume%attempts = &
    1214           48 :             moves(1, ibox)%moves%volume%attempts + 1
    1215              :          move_updates(1, ibox)%moves%volume%attempts = &
    1216           72 :             move_updates(1, ibox)%moves%volume%attempts + 1
    1217              :       END DO
    1218              : 
    1219              : ! now let's grab the cell length and particle positions
    1220           72 :       DO ibox = 1, 2
    1221              :          CALL force_env_get(force_env(ibox)%force_env, &
    1222           48 :                             subsys=oldsys(ibox)%subsys, cell=cell(ibox)%cell)
    1223           48 :          CALL get_cell(cell(ibox)%cell, abc=abc(:, ibox))
    1224           48 :          NULLIFY (cell_old(ibox)%cell)
    1225           48 :          CALL cell_create(cell_old(ibox)%cell)
    1226           48 :          CALL cell_clone(cell(ibox)%cell, cell_old(ibox)%cell, tag="CELL_OLD")
    1227              :          CALL cp_subsys_get(oldsys(ibox)%subsys, &
    1228           48 :                             particles=particles_old(ibox)%list)
    1229              : 
    1230              : ! find the old cell length
    1231          216 :          old_cell_length(1:3, ibox) = abc(1:3, ibox)
    1232              : 
    1233              :       END DO
    1234              : 
    1235           72 :       DO ibox = 1, 2
    1236              : 
    1237              : ! save the old coordinates
    1238         1272 :          DO iatom = 1, nunits_tot(ibox)
    1239         4848 :             r(1:3, iatom, ibox) = particles_old(ibox)%list%els(iatom)%r(1:3)
    1240              :          END DO
    1241              : 
    1242              :       END DO
    1243              : 
    1244              : ! call a random number to figure out how far we're moving
    1245           24 :       IF (ionode) rand = rng_stream%next()
    1246           24 :       CALL group%bcast(rand, source)
    1247              : 
    1248           24 :       vol_dis = rmvolume*(rand - 0.5E0_dp)*2.0E0_dp
    1249              : 
    1250              : ! add to one box, subtract from the other
    1251           24 :       IF (old_cell_length(1, 1)*old_cell_length(2, 1)* &
    1252              :           old_cell_length(3, 1) + vol_dis <= (3.0E0_dp/angstrom)**3) THEN
    1253            0 :          CPABORT('GE_volume moves are trying to make box 1 smaller than 3')
    1254              :       END IF
    1255           24 :       IF (old_cell_length(1, 2)*old_cell_length(2, 2)* &
    1256              :           old_cell_length(3, 2) + vol_dis <= (3.0E0_dp/angstrom)**3) THEN
    1257            0 :          CPABORT('GE_volume moves are trying to make box 2 smaller than 3')
    1258              :       END IF
    1259              : 
    1260           96 :       DO iside = 1, 3
    1261              :          new_cell_length(iside, 1) = (old_cell_length(1, 1)**3 + &
    1262           72 :                                       vol_dis)**(1.0E0_dp/3.0E0_dp)
    1263              :          new_cell_length(iside, 2) = (old_cell_length(1, 2)**3 - &
    1264           96 :                                       vol_dis)**(1.0E0_dp/3.0E0_dp)
    1265              :       END DO
    1266              : 
    1267              : ! now we need to make the new cells
    1268           72 :       DO ibox = 1, 2
    1269          624 :          hmat_test(:, :, ibox) = 0.0e0_dp
    1270           48 :          hmat_test(1, 1, ibox) = new_cell_length(1, ibox)
    1271           48 :          hmat_test(2, 2, ibox) = new_cell_length(2, ibox)
    1272           48 :          hmat_test(3, 3, ibox) = new_cell_length(3, ibox)
    1273           48 :          NULLIFY (cell_test(ibox)%cell)
    1274              :          CALL cell_create(cell_test(ibox)%cell, hmat=hmat_test(:, :, ibox), &
    1275           48 :                           periodic=cell(ibox)%cell%perd)
    1276           48 :          CALL force_env_get(force_env(ibox)%force_env, subsys=subsys)
    1277           72 :          CALL cp_subsys_set(subsys, cell=cell_test(ibox)%cell)
    1278              :       END DO
    1279              : 
    1280           72 :       DO ibox = 1, 2
    1281              : 
    1282              : ! save the coords
    1283         1248 :          DO iatom = 1, nunits_tot(ibox)
    1284         4848 :             r(1:3, iatom, ibox) = particles_old(ibox)%list%els(iatom)%r(1:3)
    1285              :          END DO
    1286              : 
    1287              : ! now we need to scale the coordinates of all the molecules by the
    1288              : ! center of mass
    1289           72 :          start_atom = 1
    1290              :          molecule_index = 1
    1291           72 :          DO jbox = 1, ibox - 1
    1292              :             IF (jbox == ibox) EXIT
    1293          120 :             molecule_index = molecule_index + SUM(nchains(:, jbox))
    1294              :          END DO
    1295          720 :          DO imolecule = 1, SUM(nchains(:, ibox))
    1296          576 :             molecule_type = mol_type(imolecule + molecule_index - 1)
    1297          576 :             IF (imolecule /= 1) THEN
    1298          528 :                start_atom = start_atom + nunits(mol_type(imolecule + molecule_index - 2))
    1299              :             END IF
    1300          576 :             end_atom = start_atom + nunits(molecule_type) - 1
    1301              : 
    1302              : ! now find the center of mass
    1303              :             CALL get_center_of_mass(r(:, start_atom:end_atom, ibox), &
    1304          576 :                                     nunits(molecule_type), center_of_mass(:), mass(:, molecule_type))
    1305              : 
    1306              : ! scale the center of mass and determine the vector that points from the
    1307              : !    old COM to the new one
    1308              :             center_of_mass_new(1:3) = center_of_mass(1:3)* &
    1309         2304 :                                       new_cell_length(1:3, ibox)/old_cell_length(1:3, ibox)
    1310         2352 :             DO j = 1, 3
    1311         1728 :                diff(j) = center_of_mass_new(j) - center_of_mass(j)
    1312              : ! now change the particle positions
    1313         5904 :                DO jatom = start_atom, end_atom
    1314              :                   particles_old(ibox)%list%els(jatom)%r(j) = &
    1315         5328 :                      particles_old(ibox)%list%els(jatom)%r(j) + diff(j)
    1316              :                END DO
    1317              : 
    1318              :             END DO
    1319              :          END DO
    1320              : 
    1321              : ! check for any overlaps we might have
    1322              :          start_mol = 1
    1323           72 :          DO jbox = 1, ibox - 1
    1324          120 :             start_mol = start_mol + SUM(nchains(:, jbox))
    1325              :          END DO
    1326          144 :          end_mol = start_mol + SUM(nchains(:, ibox)) - 1
    1327              :          CALL check_for_overlap(force_env(ibox)%force_env, &
    1328              :                                 nchains(:, ibox), nunits, loverlap(ibox), mol_type(start_mol:end_mol), &
    1329           72 :                                 cell_length=new_cell_length(:, ibox))
    1330              : 
    1331              :       END DO
    1332              : 
    1333              : ! determine the overall energy difference
    1334              : 
    1335           72 :       DO ibox = 1, 2
    1336           48 :          IF (loverlap(ibox)) CYCLE
    1337              : ! remake the force environment and calculate the energy
    1338           72 :          IF (lempty(ibox)) THEN
    1339            0 :             new_energy(ibox) = 0.0E0_dp
    1340              :          ELSE
    1341              : 
    1342              :             CALL force_env_calc_energy_force(force_env(ibox)%force_env, &
    1343           48 :                                              calc_force=.FALSE.)
    1344              :             CALL force_env_get(force_env(ibox)%force_env, &
    1345           48 :                                potential_energy=new_energy(ibox))
    1346              : 
    1347              :          END IF
    1348              :       END DO
    1349              : 
    1350              : ! accept or reject the move
    1351           72 :       DO ibox = 1, 2
    1352              :          volume_new(ibox) = new_cell_length(1, ibox)* &
    1353           48 :                             new_cell_length(2, ibox)*new_cell_length(3, ibox)
    1354              :          volume_old(ibox) = old_cell_length(1, ibox)* &
    1355           72 :                             old_cell_length(2, ibox)*old_cell_length(3, ibox)
    1356              :       END DO
    1357              :       prefactor = (volume_new(1)/volume_old(1))**(SUM(nchains(:, 1)))* &
    1358          120 :                   (volume_new(2)/volume_old(2))**(SUM(nchains(:, 2)))
    1359              : 
    1360           24 :       IF (loverlap(1) .OR. loverlap(2)) THEN
    1361            0 :          w = 0.0E0_dp
    1362              :       ELSE
    1363              :          w = prefactor*EXP(-BETA* &
    1364              :                            (new_energy(1) + new_energy(2) - &
    1365           24 :                             old_energy(1) - old_energy(2)))
    1366              : 
    1367              :       END IF
    1368              : 
    1369           24 :       IF (w >= 1.0E0_dp) THEN
    1370            6 :          w = 1.0E0_dp
    1371            6 :          rand = 0.0E0_dp
    1372              :       ELSE
    1373           18 :          IF (ionode) rand = rng_stream%next()
    1374           18 :          CALL group%bcast(rand, source)
    1375              :       END IF
    1376              : 
    1377           24 :       IF (rand < w) THEN
    1378              : 
    1379              : ! write cell length, volume, density, and trial displacement to a file
    1380           18 :          IF (ionode) THEN
    1381              : 
    1382            9 :             WRITE (cl, *) nnstep, new_cell_length(1, 1)* &
    1383            9 :                angstrom, vol_dis*(angstrom)**3, new_cell_length(1, 2)* &
    1384           18 :                angstrom
    1385            9 :             WRITE (cl, *) nnstep, new_energy(1), &
    1386           18 :                old_energy(1), new_energy(2), old_energy(2)
    1387            9 :             WRITE (cl, *) prefactor, w
    1388              :          END IF
    1389              : 
    1390           54 :          DO ibox = 1, 2
    1391              : ! accept the move
    1392              :             moves(1, ibox)%moves%volume%successes = &
    1393           36 :                moves(1, ibox)%moves%volume%successes + 1
    1394              :             move_updates(1, ibox)%moves%volume%successes = &
    1395           36 :                move_updates(1, ibox)%moves%volume%successes + 1
    1396              : 
    1397              : ! update energies
    1398              :             energy_check(ibox) = energy_check(ibox) + (new_energy(ibox) - &
    1399           36 :                                                        old_energy(ibox))
    1400           36 :             old_energy(ibox) = new_energy(ibox)
    1401              : 
    1402              : ! and the new "old" coordinates
    1403          954 :             DO iatom = 1, nunits_tot(ibox)
    1404              :                r_old(1:3, iatom, ibox) = &
    1405         3636 :                   particles_old(ibox)%list%els(iatom)%r(1:3)
    1406              :             END DO
    1407              : 
    1408              :          END DO
    1409              :       ELSE
    1410              : 
    1411              : ! reject the move
    1412              : ! write cell length, volume, density, and trial displacement to a file
    1413            6 :          IF (ionode) THEN
    1414              : 
    1415            3 :             WRITE (cl, *) nnstep, new_cell_length(1, 1)* &
    1416            3 :                angstrom, vol_dis*(angstrom)**3, new_cell_length(1, 2)* &
    1417            6 :                angstrom
    1418            3 :             WRITE (cl, *) nnstep, new_energy(1), &
    1419            6 :                old_energy(1), new_energy(2), old_energy(2)
    1420            3 :             WRITE (cl, *) prefactor, w
    1421              : 
    1422              :          END IF
    1423              : 
    1424              : ! reset the cell and particle positions
    1425           18 :          DO ibox = 1, 2
    1426           12 :             CALL force_env_get(force_env(ibox)%force_env, subsys=subsys)
    1427           12 :             CALL cp_subsys_set(subsys, cell=cell_old(ibox)%cell)
    1428          318 :             DO iatom = 1, nunits_tot(ibox)
    1429         1212 :                particles_old(ibox)%list%els(iatom)%r(1:3) = r_old(1:3, iatom, ibox)
    1430              :             END DO
    1431              :          END DO
    1432              : 
    1433              :       END IF
    1434              : 
    1435              : ! free up some memory
    1436           72 :       DO ibox = 1, 2
    1437           48 :          CALL cell_release(cell_test(ibox)%cell)
    1438           72 :          CALL cell_release(cell_old(ibox)%cell)
    1439              :       END DO
    1440           24 :       DEALLOCATE (r)
    1441           24 :       DEALLOCATE (oldsys)
    1442           24 :       DEALLOCATE (particles_old)
    1443           24 :       DEALLOCATE (cell)
    1444           24 :       DEALLOCATE (cell_old)
    1445           24 :       DEALLOCATE (cell_test)
    1446           24 :       DEALLOCATE (loverlap)
    1447              : 
    1448              : ! end the timing
    1449           24 :       CALL timestop(handle)
    1450              : 
    1451           24 :    END SUBROUTINE mc_ge_volume_move
    1452              : 
    1453              : END MODULE mc_ge_moves
    1454              : 
        

Generated by: LCOV version 2.0-1