LCOV - code coverage report
Current view: top level - src/motion/mc - mc_ensembles.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:71c3ab0) Lines: 85.4 % 588 502
Test Date: 2026-07-25 06:35:44 Functions: 100.0 % 2 2

            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 Used to run the bulk of the MC simulation, doing things like
      10              : !>      choosing move types and writing data to files
      11              : !> \author Matthew J. McGrath  (09.26.2003)
      12              : !>
      13              : !>    REVISIONS
      14              : !>      09.10.05  MJM combined the two subroutines in this module into one
      15              : ! **************************************************************************************************
      16              : MODULE mc_ensembles
      17              :    USE cell_types,                      ONLY: cell_p_type,&
      18              :                                               get_cell
      19              :    USE cp_external_control,             ONLY: external_control
      20              :    USE cp_files,                        ONLY: close_file,&
      21              :                                               open_file
      22              :    USE cp_log_handling,                 ONLY: cp_logger_get_default_io_unit
      23              :    USE cp_subsys_types,                 ONLY: cp_subsys_get,&
      24              :                                               cp_subsys_p_type,&
      25              :                                               cp_subsys_type
      26              :    USE cp_units,                        ONLY: cp_unit_from_cp2k
      27              :    USE force_env_methods,               ONLY: force_env_calc_energy_force
      28              :    USE force_env_types,                 ONLY: force_env_get,&
      29              :                                               force_env_p_type,&
      30              :                                               force_env_release
      31              :    USE global_types,                    ONLY: global_environment_type
      32              :    USE input_constants,                 ONLY: dump_xmol
      33              :    USE input_section_types,             ONLY: section_type,&
      34              :                                               section_vals_type,&
      35              :                                               section_vals_val_get
      36              :    USE kinds,                           ONLY: default_string_length,&
      37              :                                               dp
      38              :    USE machine,                         ONLY: m_flush
      39              :    USE mathconstants,                   ONLY: pi
      40              :    USE mc_control,                      ONLY: mc_create_bias_force_env,&
      41              :                                               write_mc_restart
      42              :    USE mc_coordinates,                  ONLY: check_for_overlap,&
      43              :                                               create_discrete_array,&
      44              :                                               find_mc_test_molecule,&
      45              :                                               get_center_of_mass,&
      46              :                                               mc_coordinate_fold,&
      47              :                                               rotate_molecule
      48              :    USE mc_environment_types,            ONLY: get_mc_env,&
      49              :                                               mc_environment_p_type,&
      50              :                                               set_mc_env
      51              :    USE mc_ge_moves,                     ONLY: mc_ge_swap_move,&
      52              :                                               mc_ge_volume_move,&
      53              :                                               mc_quickstep_move
      54              :    USE mc_misc,                         ONLY: final_mc_write,&
      55              :                                               mc_averages_create,&
      56              :                                               mc_averages_release
      57              :    USE mc_move_control,                 ONLY: init_mc_moves,&
      58              :                                               mc_move_update,&
      59              :                                               mc_moves_release,&
      60              :                                               write_move_stats
      61              :    USE mc_moves,                        ONLY: mc_avbmc_move,&
      62              :                                               mc_cluster_translation,&
      63              :                                               mc_conformation_change,&
      64              :                                               mc_hmc_move,&
      65              :                                               mc_molecule_rotation,&
      66              :                                               mc_molecule_translation,&
      67              :                                               mc_volume_move
      68              :    USE mc_types,                        ONLY: get_mc_molecule_info,&
      69              :                                               get_mc_par,&
      70              :                                               mc_averages_p_type,&
      71              :                                               mc_input_file_type,&
      72              :                                               mc_molecule_info_type,&
      73              :                                               mc_moves_p_type,&
      74              :                                               mc_simulation_parameters_p_type,&
      75              :                                               set_mc_par
      76              :    USE message_passing,                 ONLY: mp_comm_type,&
      77              :                                               mp_para_env_type
      78              :    USE parallel_rng_types,              ONLY: rng_stream_type
      79              :    USE particle_list_types,             ONLY: particle_list_p_type,&
      80              :                                               particle_list_type
      81              :    USE particle_methods,                ONLY: write_particle_coordinates
      82              :    USE physcon,                         ONLY: angstrom,&
      83              :                                               boltzmann,&
      84              :                                               joule,&
      85              :                                               n_avogadro
      86              : #include "../../base/base_uses.f90"
      87              : 
      88              :    IMPLICIT NONE
      89              : 
      90              :    PRIVATE
      91              : 
      92              : ! *** Global parameters ***
      93              : 
      94              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'mc_ensembles'
      95              :    LOGICAL, PARAMETER, PRIVATE :: debug_this_module = .FALSE.
      96              : 
      97              :    PUBLIC :: mc_run_ensemble, mc_compute_virial
      98              : 
      99              : CONTAINS
     100              : 
     101              : ! **************************************************************************************************
     102              : !> \brief directs the program in running one or two box MC simulations
     103              : !> \param mc_env a pointer that contains all mc_env for all the simulation
     104              : !>          boxes
     105              : !> \param para_env ...
     106              : !> \param globenv the global environment for the simulation
     107              : !> \param input_declaration ...
     108              : !> \param nboxes the number of simulation boxes
     109              : !> \param rng_stream the stream we pull random numbers from
     110              : !>
     111              : !>    Suitable for parallel.
     112              : !> \author MJM
     113              : ! **************************************************************************************************
     114           18 :    SUBROUTINE mc_run_ensemble(mc_env, para_env, globenv, input_declaration, nboxes, rng_stream)
     115              : 
     116              :       TYPE(mc_environment_p_type), DIMENSION(:), POINTER :: mc_env
     117              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     118              :       TYPE(global_environment_type), POINTER             :: globenv
     119              :       TYPE(section_type), POINTER                        :: input_declaration
     120              :       INTEGER, INTENT(IN)                                :: nboxes
     121              :       TYPE(rng_stream_type), INTENT(INOUT)               :: rng_stream
     122              : 
     123              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'mc_run_ensemble'
     124              : 
     125              :       CHARACTER(default_string_length), ALLOCATABLE, &
     126           18 :          DIMENSION(:)                                    :: atom_names_box
     127              :       CHARACTER(default_string_length), &
     128           18 :          DIMENSION(:, :), POINTER                        :: atom_names
     129              :       CHARACTER(LEN=20)                                  :: ensemble
     130              :       CHARACTER(LEN=40)                                  :: cbox, cstep, fft_lib, move_type, &
     131              :                                                             move_type_avbmc
     132           18 :       INTEGER, DIMENSION(:, :), POINTER                  :: nchains
     133           18 :       INTEGER, DIMENSION(:), POINTER                     :: avbmc_atom, mol_type, nchains_box, &
     134           18 :                                                             nunits, nunits_tot
     135           36 :       INTEGER, DIMENSION(1:nboxes)                       :: box_flag, cl, data_unit, diff, istep, &
     136           54 :                                                             move_unit, rm
     137              :       INTEGER, DIMENSION(1:3, 1:2)                       :: discrete_array
     138              :       INTEGER :: atom_number, box_number, cell_unit, com_crd, com_ene, com_mol, end_mol, handle, &
     139              :          ibox, idum, imol_type, imolecule, imove, iparticle, iprint, itype, iunit, iuptrans, &
     140              :          iupvolume, iw, jbox, jdum, molecule_type, molecule_type_swap, molecule_type_target, &
     141              :          nchain_total, nmol_types, nmoves, nnstep, nstart, nstep, source, start_atom, &
     142              :          start_atom_swap, start_atom_target, start_mol
     143              :       CHARACTER(LEN=default_string_length)               :: unit_str
     144           36 :       CHARACTER(LEN=40), DIMENSION(1:nboxes)             :: cell_file, coords_file, data_file, &
     145           36 :                                                             displacement_file, energy_file, &
     146           36 :                                                             molecules_file, moves_file
     147              :       LOGICAL                                            :: ionode, lbias, ldiscrete, lhmc, &
     148              :                                                             lnew_bias_env, loverlap, lreject, &
     149              :                                                             lstop, print_kind, should_stop
     150           18 :       REAL(dp), DIMENSION(:), POINTER                    :: pbias, pmavbmc_mol, pmclus_box, &
     151           18 :                                                             pmhmc_box, pmrot_mol, pmtraion_mol, &
     152           18 :                                                             pmtrans_mol, pmvol_box
     153           18 :       REAL(dp), DIMENSION(:, :), POINTER                 :: conf_prob, mass
     154              :       REAL(KIND=dp)                                      :: discrete_step, pmavbmc, pmcltrans, &
     155              :                                                             pmhmc, pmswap, pmtraion, pmtrans, &
     156              :                                                             pmvolume, rand, test_energy, unit_conv
     157           18 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: r_temp
     158           18 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: r_old
     159           36 :       REAL(KIND=dp), DIMENSION(1:3, 1:nboxes)            :: abc
     160           36 :       REAL(KIND=dp), DIMENSION(1:nboxes)                 :: bias_energy, energy_check, final_energy, &
     161           36 :                                                             initial_energy, last_bias_energy, &
     162           36 :                                                             old_energy
     163           18 :       TYPE(cell_p_type), DIMENSION(:), POINTER           :: cell
     164           18 :       TYPE(cp_subsys_p_type), DIMENSION(:), POINTER      :: oldsys
     165              :       TYPE(cp_subsys_type), POINTER                      :: biassys
     166           18 :       TYPE(force_env_p_type), DIMENSION(:), POINTER      :: bias_env, force_env
     167           18 :       TYPE(mc_averages_p_type), DIMENSION(:), POINTER    :: averages
     168              :       TYPE(mc_input_file_type), POINTER                  :: mc_bias_file
     169              :       TYPE(mc_molecule_info_type), POINTER               :: mc_molecule_info
     170           18 :       TYPE(mc_moves_p_type), DIMENSION(:), POINTER       :: test_moves
     171           18 :       TYPE(mc_moves_p_type), DIMENSION(:, :), POINTER    :: move_updates, moves
     172              :       TYPE(mc_simulation_parameters_p_type), &
     173           18 :          DIMENSION(:), POINTER                           :: mc_par
     174              :       TYPE(mp_comm_type)                                 :: group
     175           18 :       TYPE(particle_list_p_type), DIMENSION(:), POINTER  :: particles_old
     176              :       TYPE(particle_list_type), POINTER                  :: particles_bias
     177              :       TYPE(section_vals_type), POINTER                   :: root_section
     178              : 
     179           18 :       CALL timeset(routineN, handle)
     180              : 
     181              :       ! nullify some pointers
     182           18 :       NULLIFY (moves, move_updates, test_moves, root_section)
     183              : 
     184              :       ! allocate a whole bunch of stuff based on how many boxes we have
     185           96 :       ALLOCATE (force_env(1:nboxes))
     186           60 :       ALLOCATE (bias_env(1:nboxes))
     187           60 :       ALLOCATE (cell(1:nboxes))
     188           60 :       ALLOCATE (particles_old(1:nboxes))
     189           60 :       ALLOCATE (oldsys(1:nboxes))
     190           60 :       ALLOCATE (averages(1:nboxes))
     191           60 :       ALLOCATE (mc_par(1:nboxes))
     192           36 :       ALLOCATE (pmvol_box(1:nboxes))
     193           36 :       ALLOCATE (pmclus_box(1:nboxes))
     194           36 :       ALLOCATE (pmhmc_box(1:nboxes))
     195              : 
     196           42 :       DO ibox = 1, nboxes
     197              :          CALL get_mc_env(mc_env(ibox)%mc_env, &
     198              :                          mc_par=mc_par(ibox)%mc_par, &
     199           42 :                          force_env=force_env(ibox)%force_env)
     200              :       END DO
     201              : 
     202              :       ! Gather units of measure for output (if available)
     203           18 :       root_section => force_env(1)%force_env%root_section
     204              :       CALL section_vals_val_get(root_section, "MOTION%PRINT%TRAJECTORY%UNIT", &
     205           18 :                                 c_val=unit_str)
     206           18 :       unit_conv = cp_unit_from_cp2k(1.0_dp, TRIM(unit_str))
     207              :       CALL section_vals_val_get(root_section, "MOTION%PRINT%TRAJECTORY%PRINT_ATOM_KIND", &
     208           18 :                                 l_val=print_kind)
     209              : 
     210              :       ! get some data out of mc_par
     211              :       CALL get_mc_par(mc_par(1)%mc_par, &
     212              :                       ionode=ionode, source=source, group=group, &
     213              :                       data_file=data_file(1), moves_file=moves_file(1), &
     214              :                       cell_file=cell_file(1), coords_file=coords_file(1), &
     215              :                       energy_file=energy_file(1), displacement_file=displacement_file(1), &
     216              :                       lstop=lstop, nstep=nstep, nstart=nstart, pmvolume=pmvolume, pmhmc=pmhmc, &
     217              :                       molecules_file=molecules_file(1), pmswap=pmswap, nmoves=nmoves, &
     218              :                       pmtraion=pmtraion, pmtrans=pmtrans, pmcltrans=pmcltrans, iuptrans=iuptrans, &
     219              :                       iupvolume=iupvolume, ldiscrete=ldiscrete, pmtraion_mol=pmtraion_mol, &
     220              :                       lbias=lbias, iprint=iprint, pmavbmc_mol=pmavbmc_mol, &
     221              :                       discrete_step=discrete_step, fft_lib=fft_lib, avbmc_atom=avbmc_atom, &
     222              :                       pmavbmc=pmavbmc, pbias=pbias, mc_molecule_info=mc_molecule_info, &
     223              :                       pmrot_mol=pmrot_mol, pmtrans_mol=pmtrans_mol, pmvol_box=pmvol_box(1), &
     224           18 :                       pmclus_box=pmclus_box(1), ensemble=ensemble, pmhmc_box=pmhmc_box(1), lhmc=lhmc)
     225              : 
     226              :       ! get some data from the molecule types
     227              :       CALL get_mc_molecule_info(mc_molecule_info, conf_prob=conf_prob, &
     228              :                                 nchains=nchains, nmol_types=nmol_types, nunits_tot=nunits_tot, &
     229              :                                 mol_type=mol_type, nchain_total=nchain_total, nunits=nunits, &
     230           18 :                                 atom_names=atom_names, mass=mass)
     231              : 
     232              :       ! allocate some stuff based on the number of molecule types we have
     233          136 :       ALLOCATE (moves(1:nmol_types, 1:nboxes))
     234          118 :       ALLOCATE (move_updates(1:nmol_types, 1:nboxes))
     235              : 
     236           18 :       IF (nboxes > 1) THEN
     237           12 :          DO ibox = 2, nboxes
     238              :             CALL get_mc_par(mc_par(ibox)%mc_par, &
     239              :                             data_file=data_file(ibox), &
     240              :                             moves_file=moves_file(ibox), &
     241              :                             cell_file=cell_file(ibox), coords_file=coords_file(ibox), &
     242              :                             energy_file=energy_file(ibox), &
     243              :                             displacement_file=displacement_file(ibox), &
     244              :                             molecules_file=molecules_file(ibox), pmvol_box=pmvol_box(ibox), &
     245           12 :                             pmclus_box=pmclus_box(ibox), pmhmc_box=pmhmc_box(ibox))
     246              :          END DO
     247              :       END IF
     248              : 
     249              :       ! this is a check we can't do in the input checking
     250           18 :       IF (pmvol_box(nboxes) < 1.0E0_dp) THEN
     251            0 :          CPABORT('The last value of PMVOL_BOX needs to be 1.0')
     252              :       END IF
     253           18 :       IF (pmclus_box(nboxes) < 1.0E0_dp) THEN
     254            0 :          CPABORT('The last value of PMVOL_BOX needs to be 1.0')
     255              :       END IF
     256           18 :       IF (pmhmc_box(nboxes) < 1.0E0_dp) THEN
     257            0 :          CPABORT('The last value of PMHMC_BOX needs to be 1.0')
     258              :       END IF
     259              : 
     260              :       ! allocate the particle positions array for broadcasting
     261           96 :       ALLOCATE (r_old(3, SUM(nunits_tot), 1:nboxes))
     262              : 
     263              :       ! figure out what the default write unit is
     264           18 :       iw = cp_logger_get_default_io_unit()
     265              : 
     266           18 :       IF (iw > 0) THEN
     267            9 :          WRITE (iw, *)
     268            9 :          WRITE (iw, *)
     269            9 :          WRITE (iw, *) 'Beginning the Monte Carlo calculation.'
     270            9 :          WRITE (iw, *)
     271            9 :          WRITE (iw, *)
     272              :       END IF
     273              : 
     274              :       ! initialize running average variables
     275           42 :       energy_check(:) = 0.0E0_dp
     276           42 :       box_flag(:) = 0
     277           42 :       istep(:) = 0
     278              : 
     279           42 :       DO ibox = 1, nboxes
     280              :          ! initialize the moves array, the arrays for updating maximum move
     281              :          ! displacements, and the averages array
     282           64 :          DO itype = 1, nmol_types
     283           40 :             CALL init_mc_moves(moves(itype, ibox)%moves)
     284           64 :             CALL init_mc_moves(move_updates(itype, ibox)%moves)
     285              :          END DO
     286           24 :          CALL mc_averages_create(averages(ibox)%averages)
     287              : 
     288              :          ! find the energy of the initial configuration
     289           64 :          IF (SUM(nchains(:, ibox)) /= 0) THEN
     290              :             CALL force_env_calc_energy_force(force_env(ibox)%force_env, &
     291           24 :                                              calc_force=.FALSE.)
     292              :             CALL force_env_get(force_env(ibox)%force_env, &
     293           24 :                                potential_energy=old_energy(ibox))
     294              :          ELSE
     295            0 :             old_energy(ibox) = 0.0E0_dp
     296              :          END IF
     297           24 :          initial_energy(ibox) = old_energy(ibox)
     298              : 
     299              : ! don't care about overlaps if we're only doing HMC
     300              : 
     301           24 :          IF (.NOT. lhmc) THEN
     302              :             ! check for overlaps
     303              :             start_mol = 1
     304           28 :             DO jbox = 1, ibox - 1
     305           40 :                start_mol = start_mol + SUM(nchains(:, jbox))
     306              :             END DO
     307           60 :             end_mol = start_mol + SUM(nchains(:, ibox)) - 1
     308              :             CALL check_for_overlap(force_env(ibox)%force_env, nchains(:, ibox), &
     309           22 :                                    nunits, loverlap, mol_type(start_mol:end_mol))
     310           22 :             IF (loverlap) CPABORT("overlap in an initial configuration")
     311              :          END IF
     312              : 
     313              :          ! get the subsystems and the cell information
     314              :          CALL force_env_get(force_env(ibox)%force_env, &
     315           24 :                             subsys=oldsys(ibox)%subsys, cell=cell(ibox)%cell)
     316           24 :          CALL get_cell(cell(ibox)%cell, abc=abc(:, ibox))
     317              :          CALL cp_subsys_get(oldsys(ibox)%subsys, &
     318           24 :                             particles=particles_old(ibox)%list)
     319              :          ! record the old coordinates, in case a move is rejected
     320         2656 :          DO iparticle = 1, nunits_tot(ibox)
     321              :             r_old(1:3, iparticle, ibox) = &
     322        10552 :                particles_old(ibox)%list%els(iparticle)%r(1:3)
     323              :          END DO
     324              : 
     325              :          ! find the bias energy of the initial run
     326           24 :          IF (lbias) THEN
     327              :             ! determine the atom names of every particle
     328           42 :             ALLOCATE (atom_names_box(1:nunits_tot(ibox)))
     329              : 
     330           14 :             atom_number = 1
     331          212 :             DO imolecule = 1, SUM(nchains(:, ibox))
     332          538 :                DO iunit = 1, nunits(mol_type(imolecule + start_mol - 1))
     333              :                   atom_names_box(atom_number) = &
     334          354 :                      atom_names(iunit, mol_type(imolecule + start_mol - 1))
     335          524 :                   atom_number = atom_number + 1
     336              :                END DO
     337              :             END DO
     338              : 
     339           14 :             CALL get_mc_par(mc_par(ibox)%mc_par, mc_bias_file=mc_bias_file)
     340           14 :             nchains_box => nchains(:, ibox)
     341              :             CALL mc_create_bias_force_env(bias_env(ibox)%force_env, &
     342              :                                           r_old(:, :, ibox), atom_names_box(:), nunits_tot(ibox), &
     343              :                                           para_env, abc(:, ibox), nchains_box, input_declaration, mc_bias_file, &
     344           14 :                                           ionode)
     345           42 :             IF (SUM(nchains(:, ibox)) /= 0) THEN
     346              :                CALL force_env_calc_energy_force(bias_env(ibox)%force_env, &
     347           14 :                                                 calc_force=.FALSE.)
     348              :                CALL force_env_get(bias_env(ibox)%force_env, &
     349           14 :                                   potential_energy=last_bias_energy(ibox))
     350              : 
     351              :             ELSE
     352            0 :                last_bias_energy(ibox) = 0.0E0_dp
     353              :             END IF
     354           14 :             bias_energy(ibox) = last_bias_energy(ibox)
     355           14 :             DEALLOCATE (atom_names_box)
     356              :          END IF
     357           42 :          lnew_bias_env = .FALSE.
     358              : 
     359              :       END DO
     360              : 
     361              :       ! back to seriel for a bunch of I/O stuff
     362           18 :       IF (ionode) THEN
     363              : 
     364              :          ! record the combined energies,coordinates, and cell lengths
     365              :          CALL open_file(file_name='mc_cell_length', &
     366              :                         unit_number=cell_unit, file_position='APPEND', &
     367            9 :                         file_action='WRITE', file_status='UNKNOWN')
     368              :          CALL open_file(file_name='mc_energies', &
     369              :                         unit_number=com_ene, file_position='APPEND', &
     370            9 :                         file_action='WRITE', file_status='UNKNOWN')
     371              :          CALL open_file(file_name='mc_coordinates', &
     372              :                         unit_number=com_crd, file_position='APPEND', &
     373            9 :                         file_action='WRITE', file_status='UNKNOWN')
     374              :          CALL open_file(file_name='mc_molecules', &
     375              :                         unit_number=com_mol, file_position='APPEND', &
     376            9 :                         file_action='WRITE', file_status='UNKNOWN')
     377            9 :          WRITE (com_ene, *) 'Initial Energies:       ', &
     378           18 :             old_energy(1:nboxes)
     379           21 :          DO ibox = 1, nboxes
     380           12 :             WRITE (com_mol, *) 'Initial Molecules:       ', &
     381           53 :                nchains(:, ibox)
     382              :          END DO
     383           21 :          DO ibox = 1, nboxes
     384           12 :             WRITE (cell_unit, *) 'Initial: ', &
     385           60 :                abc(1:3, ibox)*angstrom
     386           12 :             WRITE (cbox, '(I4)') ibox
     387              :             CALL open_file(file_name='energy_differences_box'// &
     388              :                            TRIM(ADJUSTL(cbox)), &
     389              :                            unit_number=diff(ibox), file_position='APPEND', &
     390           12 :                            file_action='WRITE', file_status='UNKNOWN')
     391           32 :             IF (SUM(nchains(:, ibox)) == 0) THEN
     392            0 :                WRITE (com_crd, *) ' 0'
     393            0 :                WRITE (com_crd, *) 'INITIAL BOX '//TRIM(ADJUSTL(cbox))
     394              :             ELSE
     395              :                CALL write_particle_coordinates(particles_old(ibox)%list%els, &
     396              :                                                com_crd, dump_xmol, 'POS', 'INITIAL BOX '//TRIM(ADJUSTL(cbox)), &
     397           12 :                                                unit_conv=unit_conv, print_kind=print_kind)
     398              :             END IF
     399              :             CALL open_file(file_name=data_file(ibox), &
     400              :                            unit_number=data_unit(ibox), file_position='APPEND', &
     401           12 :                            file_action='WRITE', file_status='UNKNOWN')
     402              :             CALL open_file(file_name=moves_file(ibox), &
     403              :                            unit_number=move_unit(ibox), file_position='APPEND', &
     404           12 :                            file_action='WRITE', file_status='UNKNOWN')
     405              :             CALL open_file(file_name=displacement_file(ibox), &
     406              :                            unit_number=rm(ibox), file_position='APPEND', &
     407           12 :                            file_action='WRITE', file_status='UNKNOWN')
     408              :             CALL open_file(file_name=cell_file(ibox), &
     409              :                            unit_number=cl(ibox), file_position='APPEND', &
     410           21 :                            file_action='WRITE', file_status='UNKNOWN')
     411              : 
     412              :          END DO
     413              : 
     414              :          ! back to parallel mode
     415              :       END IF
     416              : 
     417           42 :       DO ibox = 1, nboxes
     418           24 :          CALL group%bcast(cl(ibox), source)
     419           24 :          CALL group%bcast(rm(ibox), source)
     420           24 :          CALL group%bcast(diff(ibox), source)
     421              :          ! set all the units numbers that we just opened in the respective mc_par
     422              :          CALL set_mc_par(mc_par(ibox)%mc_par, cl=cl(ibox), rm=rm(ibox), &
     423           42 :                          diff=diff(ibox))
     424              :       END DO
     425              : 
     426              :       ! if we're doing a discrete volume move, we need to set up the array
     427              :       ! that keeps track of which direction we can move in
     428           18 :       IF (ldiscrete) THEN
     429            0 :          IF (nboxes /= 1) THEN
     430            0 :             CPABORT('ldiscrete=.true. ONLY for systems with 1 box')
     431              :          END IF
     432              :          CALL create_discrete_array(abc(:, 1), discrete_array(:, :), &
     433            0 :                                     discrete_step)
     434              :       END IF
     435              : 
     436              :       ! find out how many steps we're doing...change the updates to be in cycles
     437              :       ! if the total number of steps is measured in cycles
     438           18 :       IF (.NOT. lstop) THEN
     439           10 :          nstep = nstep*nchain_total
     440           10 :          iuptrans = iuptrans*nchain_total
     441           10 :          iupvolume = iupvolume*nchain_total
     442              :       END IF
     443              : 
     444          486 :       DO nnstep = nstart + 1, nstart + nstep
     445              : 
     446          468 :          IF (MOD(nnstep, iprint) == 0 .AND. (iw > 0)) THEN
     447           15 :             WRITE (iw, *)
     448           15 :             WRITE (iw, *) "------- On Monte Carlo Step ", nnstep
     449              :          END IF
     450              : 
     451          468 :          IF (ionode) rand = rng_stream%next()
     452              :          ! broadcast the random number, to make sure we're on the same move
     453          468 :          CALL group%bcast(rand, source)
     454              : 
     455          468 :          IF (rand < pmvolume) THEN
     456              : 
     457           58 :             IF (MOD(nnstep, iprint) == 0 .AND. (iw > 0)) THEN
     458            1 :                WRITE (iw, *) "Attempting a volume move"
     459            1 :                WRITE (iw, *)
     460              :             END IF
     461              : 
     462            8 :             SELECT CASE (ensemble)
     463              :             CASE ("TRADITIONAL")
     464              :                CALL mc_volume_move(mc_par(1)%mc_par, &
     465              :                                    force_env(1)%force_env, &
     466              :                                    moves(1, 1)%moves, move_updates(1, 1)%moves, &
     467              :                                    old_energy(1), 1, &
     468              :                                    energy_check(1), r_old(:, :, 1), iw, discrete_array(:, :), &
     469            8 :                                    rng_stream)
     470              :             CASE ("GEMC_NVT")
     471              :                CALL mc_ge_volume_move(mc_par, force_env, moves, &
     472              :                                       move_updates, nnstep, old_energy, energy_check, &
     473           24 :                                       r_old, rng_stream)
     474              :             CASE ("GEMC_NPT")
     475              :                ! we need to select a box based on the probability given in the input file
     476           26 :                IF (ionode) rand = rng_stream%next()
     477           26 :                CALL group%bcast(rand, source)
     478              : 
     479           38 :                DO ibox = 1, nboxes
     480           38 :                   IF (rand <= pmvol_box(ibox)) THEN
     481           26 :                      box_number = ibox
     482           26 :                      EXIT
     483              :                   END IF
     484              :                END DO
     485              : 
     486              :                CALL mc_volume_move(mc_par(box_number)%mc_par, &
     487              :                                    force_env(box_number)%force_env, &
     488              :                                    moves(1, box_number)%moves, &
     489              :                                    move_updates(1, box_number)%moves, &
     490              :                                    old_energy(box_number), box_number, &
     491              :                                    energy_check(box_number), r_old(:, :, box_number), iw, &
     492              :                                    discrete_array(:, :), &
     493           84 :                                    rng_stream)
     494              :             END SELECT
     495              : 
     496              : ! update all the pointers here, because otherwise we may pass wrong information when we're making a bias environment
     497          166 :             DO ibox = 1, nboxes
     498              :                CALL force_env_get(force_env(ibox)%force_env, &
     499          108 :                                   subsys=oldsys(ibox)%subsys, cell=cell(ibox)%cell)
     500          108 :                CALL get_cell(cell(ibox)%cell, abc=abc(:, ibox))
     501              :                CALL cp_subsys_get(oldsys(ibox)%subsys, &
     502          166 :                                   particles=particles_old(ibox)%list)
     503              :             END DO
     504              : 
     505              :             ! we need a new biasing environment now, if we're into that sort of thing
     506           58 :             IF (lbias) THEN
     507          150 :                DO ibox = 1, nboxes
     508          100 :                   CALL force_env_release(bias_env(ibox)%force_env)
     509              :                   ! determine the atom names of every particle
     510          300 :                   ALLOCATE (atom_names_box(1:nunits_tot(ibox)))
     511          150 :                   start_mol = 1
     512          150 :                   DO jbox = 1, ibox - 1
     513          250 :                      start_mol = start_mol + SUM(nchains(:, jbox))
     514              :                   END DO
     515          300 :                   end_mol = start_mol + SUM(nchains(:, ibox)) - 1
     516          300 :                   atom_number = 1
     517         1500 :                   DO imolecule = 1, SUM(nchains(:, ibox))
     518         3800 :                      DO iunit = 1, nunits(mol_type(imolecule + start_mol - 1))
     519              :                         atom_names_box(atom_number) = &
     520         2500 :                            atom_names(iunit, mol_type(imolecule + start_mol - 1))
     521         3700 :                         atom_number = atom_number + 1
     522              :                      END DO
     523              :                   END DO
     524              : 
     525              : ! need to find out what the cell lengths are
     526              :                   CALL force_env_get(force_env(ibox)%force_env, &
     527          100 :                                      subsys=oldsys(ibox)%subsys, cell=cell(ibox)%cell)
     528          100 :                   CALL get_cell(cell(ibox)%cell, abc=abc(:, ibox))
     529              : 
     530              :                   CALL get_mc_par(mc_par(ibox)%mc_par, &
     531          100 :                                   mc_bias_file=mc_bias_file)
     532          100 :                   nchains_box => nchains(:, ibox)
     533              : 
     534              :                   CALL mc_create_bias_force_env(bias_env(ibox)%force_env, &
     535              :                                                 r_old(:, :, ibox), atom_names_box(:), nunits_tot(ibox), &
     536              :                                                 para_env, abc(:, ibox), nchains_box, input_declaration, &
     537          100 :                                                 mc_bias_file, ionode)
     538              : 
     539          300 :                   IF (SUM(nchains(:, ibox)) /= 0) THEN
     540              :                      CALL force_env_calc_energy_force( &
     541              :                         bias_env(ibox)%force_env, &
     542          100 :                         calc_force=.FALSE.)
     543              :                      CALL force_env_get(bias_env(ibox)%force_env, &
     544          100 :                                         potential_energy=last_bias_energy(ibox))
     545              :                   ELSE
     546            0 :                      last_bias_energy(ibox) = 0.0E0_dp
     547              :                   END IF
     548          100 :                   bias_energy(ibox) = last_bias_energy(ibox)
     549          150 :                   DEALLOCATE (atom_names_box)
     550              :                END DO
     551              :             END IF
     552              : 
     553          410 :          ELSE IF (rand < pmswap) THEN
     554              : 
     555              :             ! try a swap move
     556           22 :             IF (MOD(nnstep, iprint) == 0 .AND. (iw > 0)) THEN
     557            0 :                WRITE (iw, *) "Attempting a swap move"
     558            0 :                WRITE (iw, *)
     559              :             END IF
     560              : 
     561              :             CALL mc_ge_swap_move(mc_par, force_env, bias_env, moves, &
     562              :                                  energy_check(:), r_old(:, :, :), old_energy(:), input_declaration, &
     563           22 :                                  para_env, bias_energy(:), last_bias_energy(:), rng_stream)
     564              : 
     565              :             ! the number of molecules may have changed, which deallocated the whole
     566              :             ! mc_molecule_info structure
     567           22 :             CALL get_mc_par(mc_par(1)%mc_par, mc_molecule_info=mc_molecule_info)
     568              :             CALL get_mc_molecule_info(mc_molecule_info, conf_prob=conf_prob, &
     569              :                                       nchains=nchains, nmol_types=nmol_types, nunits_tot=nunits_tot, &
     570              :                                       mol_type=mol_type, nchain_total=nchain_total, nunits=nunits, &
     571           22 :                                       atom_names=atom_names, mass=mass)
     572              : 
     573          388 :          ELSE IF (rand < pmhmc) THEN
     574              : ! try hybrid Monte Carlo
     575           20 :             IF (MOD(nnstep, iprint) == 0 .AND. (iw > 0)) THEN
     576            2 :                WRITE (iw, *) "Attempting a hybrid Monte Carlo move"
     577            2 :                WRITE (iw, *)
     578              :             END IF
     579              : 
     580              : ! pick a box at random
     581           20 :             IF (ionode) rand = rng_stream%next()
     582           20 :             CALL group%bcast(rand, source)
     583              : 
     584           20 :             DO ibox = 1, nboxes
     585           20 :                IF (rand <= pmhmc_box(ibox)) THEN
     586           20 :                   box_number = ibox
     587           20 :                   EXIT
     588              :                END IF
     589              :             END DO
     590              : 
     591              :             CALL mc_hmc_move(mc_par(box_number)%mc_par, &
     592              :                              force_env(box_number)%force_env, globenv, &
     593              :                              moves(1, box_number)%moves, &
     594              :                              move_updates(1, box_number)%moves, &
     595              :                              old_energy(box_number), box_number, &
     596              :                              energy_check(box_number), r_old(:, :, box_number), &
     597           20 :                              rng_stream)
     598              : 
     599          368 :          ELSE IF (rand < pmavbmc) THEN
     600              :             ! try an AVBMC move
     601            0 :             IF (MOD(nnstep, iprint) == 0 .AND. (iw > 0)) THEN
     602            0 :                WRITE (iw, *) "Attempting an AVBMC1 move"
     603            0 :                WRITE (iw, *)
     604              :             END IF
     605              : 
     606              :             ! first, pick a box to do it for
     607            0 :             IF (ionode) rand = rng_stream%next()
     608            0 :             CALL group%bcast(rand, source)
     609              : 
     610            0 :             IF (nboxes == 2) THEN
     611            0 :                IF (rand < 0.1E0_dp) THEN
     612            0 :                   box_number = 1
     613              :                ELSE
     614            0 :                   box_number = 2
     615              :                END IF
     616              :             ELSE
     617            0 :                box_number = 1
     618              :             END IF
     619              : 
     620              :             ! now pick a molecule type to do it for
     621            0 :             IF (ionode) rand = rng_stream%next()
     622            0 :             CALL group%bcast(rand, source)
     623            0 :             molecule_type_swap = 0
     624            0 :             DO imol_type = 1, nmol_types
     625            0 :                IF (rand < pmavbmc_mol(imol_type)) THEN
     626            0 :                   molecule_type_swap = imol_type
     627            0 :                   EXIT
     628              :                END IF
     629              :             END DO
     630            0 :             IF (molecule_type_swap == 0) THEN
     631            0 :                CPABORT('Did not choose a molecule type to swap...check AVBMC input')
     632              :             END IF
     633              : 
     634              :             ! now pick a molecule, automatically rejecting the move if the
     635              :             ! box is empty or only has one molecule
     636            0 :             IF (SUM(nchains(:, box_number)) <= 1) THEN
     637              :                ! indicate that we tried a move
     638              :                moves(molecule_type_swap, box_number)%moves%empty_avbmc = &
     639            0 :                   moves(molecule_type_swap, box_number)%moves%empty_avbmc + 1
     640              :             ELSE
     641              : 
     642              :                ! pick a molecule to be swapped in the box
     643            0 :                IF (ionode) THEN
     644              :                   CALL find_mc_test_molecule(mc_molecule_info, &
     645              :                                              start_atom_swap, idum, jdum, rng_stream, &
     646            0 :                                              box=box_number, molecule_type_old=molecule_type_swap)
     647              : 
     648              :                   ! pick a molecule to act as the target in the box...we don't care what type
     649            0 :                   DO
     650              :                      CALL find_mc_test_molecule(mc_molecule_info, &
     651              :                                                 start_atom_target, idum, molecule_type_target, &
     652            0 :                                                 rng_stream, box=box_number)
     653            0 :                      IF (start_atom_swap /= start_atom_target) THEN
     654              :                         start_atom_target = start_atom_target + &
     655            0 :                                             avbmc_atom(molecule_type_target) - 1
     656              :                         EXIT
     657              :                      END IF
     658              :                   END DO
     659              : 
     660              :                   ! choose if we're swapping into the bonded region of mol_target, or
     661              :                   ! into the nonbonded region
     662            0 :                   rand = rng_stream%next()
     663              : 
     664              :                END IF
     665            0 :                CALL group%bcast(start_atom_swap, source)
     666            0 :                CALL group%bcast(box_number, source)
     667            0 :                CALL group%bcast(start_atom_target, source)
     668            0 :                CALL group%bcast(rand, source)
     669              : 
     670            0 :                IF (rand < pbias(molecule_type_swap)) THEN
     671            0 :                   move_type_avbmc = 'in'
     672              :                ELSE
     673            0 :                   move_type_avbmc = 'out'
     674              :                END IF
     675              : 
     676              :                CALL mc_avbmc_move(mc_par(box_number)%mc_par, &
     677              :                                   force_env(box_number)%force_env, &
     678              :                                   bias_env(box_number)%force_env, &
     679              :                                   moves(molecule_type_swap, box_number)%moves, &
     680              :                                   energy_check(box_number), &
     681              :                                   r_old(:, :, box_number), old_energy(box_number), &
     682              :                                   start_atom_swap, start_atom_target, molecule_type_swap, &
     683              :                                   box_number, bias_energy(box_number), &
     684              :                                   last_bias_energy(box_number), &
     685            0 :                                   move_type_avbmc, rng_stream)
     686              : 
     687              :             END IF
     688              : 
     689              :          ELSE
     690              : 
     691          368 :             IF (MOD(nnstep, iprint) == 0 .AND. (iw > 0)) THEN
     692           12 :                WRITE (iw, *) "Attempting an inner move"
     693           12 :                WRITE (iw, *)
     694              :             END IF
     695              : 
     696         2010 :             DO imove = 1, nmoves
     697              : 
     698         1642 :                IF (ionode) rand = rng_stream%next()
     699         1642 :                CALL group%bcast(rand, source)
     700         2010 :                IF (rand < pmtraion) THEN
     701              :                   ! change molecular conformation
     702              :                   ! first, pick a box to do it for
     703          506 :                   IF (ionode) rand = rng_stream%next()
     704          506 :                   CALL group%bcast(rand, source)
     705          506 :                   IF (nboxes == 2) THEN
     706            0 :                      IF (rand < 0.75E0_dp) THEN
     707            0 :                         box_number = 1
     708              :                      ELSE
     709            0 :                         box_number = 2
     710              :                      END IF
     711              :                   ELSE
     712          506 :                      box_number = 1
     713              :                   END IF
     714              : 
     715              :                   ! figure out which molecule type we're looking for
     716          506 :                   IF (ionode) rand = rng_stream%next()
     717          506 :                   CALL group%bcast(rand, source)
     718          506 :                   molecule_type = 0
     719          506 :                   DO imol_type = 1, nmol_types
     720          506 :                      IF (rand < pmtraion_mol(imol_type)) THEN
     721          506 :                         molecule_type = imol_type
     722          506 :                         EXIT
     723              :                      END IF
     724              :                   END DO
     725          506 :                   IF (molecule_type == 0) CALL cp_abort( &
     726              :                      __LOCATION__, &
     727            0 :                      'Did not choose a molecule type to conf change...PMTRAION_MOL should not be all 0.0')
     728              : 
     729              :                   ! now pick a molecule, automatically rejecting the move if the
     730              :                   ! box is empty
     731          506 :                   IF (nchains(molecule_type, box_number) == 0) THEN
     732              :                      ! indicate that we tried a move
     733              :                      moves(molecule_type, box_number)%moves%empty_conf = &
     734            0 :                         moves(molecule_type, box_number)%moves%empty_conf + 1
     735              :                   ELSE
     736              :                      ! pick a molecule in the box
     737          506 :                      IF (ionode) THEN
     738              :                         CALL find_mc_test_molecule(mc_molecule_info, &
     739              :                                                    start_atom, idum, &
     740              :                                                    jdum, rng_stream, &
     741          253 :                                                    box=box_number, molecule_type_old=molecule_type)
     742              : 
     743              :                         ! choose if we're changing a bond length or an angle
     744          253 :                         rand = rng_stream%next()
     745              :                      END IF
     746          506 :                      CALL group%bcast(rand, source)
     747          506 :                      CALL group%bcast(start_atom, source)
     748          506 :                      CALL group%bcast(box_number, source)
     749          506 :                      CALL group%bcast(molecule_type, source)
     750              : 
     751              :                      ! figure out what kind of move we're doing
     752          506 :                      IF (rand < conf_prob(1, molecule_type)) THEN
     753          312 :                         move_type = 'bond'
     754          194 :                      ELSE IF (rand < (conf_prob(1, molecule_type) + &
     755              :                                       conf_prob(2, molecule_type))) THEN
     756          194 :                         move_type = 'angle'
     757              :                      ELSE
     758            0 :                         move_type = 'dihedral'
     759              :                      END IF
     760          506 :                      box_flag(box_number) = 1
     761              :                      CALL mc_conformation_change(mc_par(box_number)%mc_par, &
     762              :                                                  force_env(box_number)%force_env, &
     763              :                                                  bias_env(box_number)%force_env, &
     764              :                                                  moves(molecule_type, box_number)%moves, &
     765              :                                                  move_updates(molecule_type, box_number)%moves, &
     766              :                                                  start_atom, molecule_type, box_number, &
     767              :                                                  bias_energy(box_number), &
     768          506 :                                                  move_type, lreject, rng_stream)
     769          506 :                      IF (lreject) EXIT
     770              :                   END IF
     771         1136 :                ELSE IF (rand < pmtrans) THEN
     772              :                   ! translate a whole molecule in the system
     773              :                   ! pick a molecule type
     774          624 :                   IF (ionode) rand = rng_stream%next()
     775          624 :                   CALL group%bcast(rand, source)
     776          624 :                   molecule_type = 0
     777          924 :                   DO imol_type = 1, nmol_types
     778          924 :                      IF (rand < pmtrans_mol(imol_type)) THEN
     779          624 :                         molecule_type = imol_type
     780          624 :                         EXIT
     781              :                      END IF
     782              :                   END DO
     783          624 :                   IF (molecule_type == 0) CALL cp_abort( &
     784              :                      __LOCATION__, &
     785            0 :                      'Did not choose a molecule type to translate...PMTRANS_MOL should not be all 0.0')
     786              : 
     787              :                   ! now pick a molecule of that type
     788          624 :                   IF (ionode) THEN
     789              :                      CALL find_mc_test_molecule(mc_molecule_info, &
     790              :                                                 start_atom, box_number, idum, rng_stream, &
     791          312 :                                                 molecule_type_old=molecule_type)
     792              :                   END IF
     793          624 :                   CALL group%bcast(start_atom, source)
     794          624 :                   CALL group%bcast(box_number, source)
     795          624 :                   box_flag(box_number) = 1
     796              :                   CALL mc_molecule_translation(mc_par(box_number)%mc_par, &
     797              :                                                force_env(box_number)%force_env, &
     798              :                                                bias_env(box_number)%force_env, &
     799              :                                                moves(molecule_type, box_number)%moves, &
     800              :                                                move_updates(molecule_type, box_number)%moves, &
     801              :                                                start_atom, box_number, bias_energy(box_number), &
     802          624 :                                                molecule_type, lreject, rng_stream)
     803          624 :                   IF (lreject) EXIT
     804          512 :                ELSE IF (rand < pmcltrans) THEN
     805              :                   ! translate a whole cluster in the system
     806              :                   ! first, pick a box to do it for
     807           10 :                   IF (ionode) rand = rng_stream%next()
     808           10 :                   CALL group%bcast(rand, source)
     809              : 
     810           10 :                   DO ibox = 1, nboxes
     811           10 :                   IF (rand <= pmclus_box(ibox)) THEN
     812           10 :                      box_number = ibox
     813           10 :                      EXIT
     814              :                   END IF
     815              :                   END DO
     816           10 :                   box_flag(box_number) = 1
     817              :                   CALL mc_cluster_translation(mc_par(box_number)%mc_par, &
     818              :                                               force_env(box_number)%force_env, &
     819              :                                               bias_env(box_number)%force_env, &
     820              :                                               moves(1, box_number)%moves, &
     821              :                                               move_updates(1, box_number)%moves, &
     822              :                                               box_number, bias_energy(box_number), &
     823           10 :                                               lreject, rng_stream)
     824           10 :                   IF (lreject) EXIT
     825              :                ELSE
     826              :                   !     rotate a whole molecule in the system
     827              :                   ! pick a molecule type
     828          502 :                   IF (ionode) rand = rng_stream%next()
     829          502 :                   CALL group%bcast(rand, source)
     830          502 :                   molecule_type = 0
     831          502 :                   DO imol_type = 1, nmol_types
     832          502 :                      IF (rand < pmrot_mol(imol_type)) THEN
     833          502 :                         molecule_type = imol_type
     834          502 :                         EXIT
     835              :                      END IF
     836              :                   END DO
     837          502 :                   IF (molecule_type == 0) CALL cp_abort( &
     838              :                      __LOCATION__, &
     839            0 :                      'Did not choose a molecule type to rotate...PMROT_MOL should not be all 0.0')
     840              : 
     841          502 :                   IF (ionode) THEN
     842              :                      CALL find_mc_test_molecule(mc_molecule_info, &
     843              :                                                 start_atom, box_number, idum, rng_stream, &
     844          251 :                                                 molecule_type_old=molecule_type)
     845              :                   END IF
     846          502 :                   CALL group%bcast(start_atom, source)
     847          502 :                   CALL group%bcast(box_number, source)
     848          502 :                   box_flag(box_number) = 1
     849              :                   CALL mc_molecule_rotation(mc_par(box_number)%mc_par, &
     850              :                                             force_env(box_number)%force_env, &
     851              :                                             bias_env(box_number)%force_env, &
     852              :                                             moves(molecule_type, box_number)%moves, &
     853              :                                             move_updates(molecule_type, box_number)%moves, &
     854              :                                             box_number, start_atom, &
     855              :                                             molecule_type, bias_energy(box_number), &
     856          502 :                                             lreject, rng_stream)
     857          502 :                   IF (lreject) EXIT
     858              :                END IF
     859              : 
     860              :             END DO
     861              : 
     862              :             ! now do a Quickstep calculation to see if we accept the sequence
     863              :             CALL mc_Quickstep_move(mc_par, force_env, bias_env, &
     864              :                                    moves, lreject, move_updates, energy_check(:), r_old(:, :, :), &
     865              :                                    nnstep, old_energy(:), bias_energy(:), last_bias_energy(:), &
     866              :                                    nboxes, box_flag(:), oldsys, particles_old, &
     867          368 :                                    rng_stream, unit_conv)
     868              : 
     869              :          END IF
     870              : 
     871              :          ! make sure the pointers are pointing correctly since the subsys may
     872              :          ! have changed
     873         1080 :          DO ibox = 1, nboxes
     874              :             CALL force_env_get(force_env(ibox)%force_env, &
     875          612 :                                subsys=oldsys(ibox)%subsys, cell=cell(ibox)%cell)
     876          612 :             CALL get_cell(cell(ibox)%cell, abc=abc(:, ibox))
     877              :             CALL cp_subsys_get(oldsys(ibox)%subsys, &
     878         1080 :                                particles=particles_old(ibox)%list)
     879              :          END DO
     880              : 
     881          468 :          IF (ionode) THEN
     882              : 
     883          234 :             IF (MOD(nnstep, iprint) == 0) THEN
     884           15 :                WRITE (com_ene, *) nnstep, old_energy(1:nboxes)
     885              : 
     886           33 :                DO ibox = 1, nboxes
     887              : 
     888              :                   ! write the molecule information
     889           47 :                   WRITE (com_mol, *) nnstep, nchains(:, ibox)
     890              : 
     891              :                   ! write the move statistics to file
     892           47 :                   DO itype = 1, nmol_types
     893              :                      CALL write_move_stats(moves(itype, ibox)%moves, &
     894           47 :                                            nnstep, move_unit(ibox))
     895              :                   END DO
     896              : 
     897              :                   ! write a restart file
     898              :                   CALL write_mc_restart(nnstep, mc_par(ibox)%mc_par, &
     899           18 :                                         nchains(:, ibox), force_env(ibox)%force_env)
     900              : 
     901              :                   ! write cell lengths
     902           72 :                   WRITE (cell_unit, *) nnstep, abc(1:3, ibox)*angstrom
     903              : 
     904              :                   ! write particle coordinates
     905           18 :                   WRITE (cbox, '(I4)') ibox
     906           18 :                   WRITE (cstep, '(I8)') nnstep
     907           62 :                   IF (SUM(nchains(:, ibox)) == 0) THEN
     908            0 :                      WRITE (com_crd, *) ' 0'
     909              :                      WRITE (com_crd, *) 'BOX '//TRIM(ADJUSTL(cbox))// &
     910            0 :                         ',  STEP '//TRIM(ADJUSTL(cstep))
     911              :                   ELSE
     912              :                      CALL write_particle_coordinates( &
     913              :                         particles_old(ibox)%list%els, &
     914              :                         com_crd, dump_xmol, 'POS', &
     915              :                         'BOX '//TRIM(ADJUSTL(cbox))// &
     916              :                         ',  STEP '//TRIM(ADJUSTL(cstep)), &
     917           18 :                         unit_conv=unit_conv)
     918              :                   END IF
     919              :                END DO
     920              :             END IF ! end the things we only do every iprint moves
     921              : 
     922          540 :             DO ibox = 1, nboxes
     923              :                ! compute some averages
     924              :                averages(ibox)%averages%ave_energy = &
     925              :                   averages(ibox)%averages%ave_energy*REAL(nnstep - &
     926              :                                                           nstart - 1, dp)/REAL(nnstep - nstart, dp) + &
     927          306 :                   old_energy(ibox)/REAL(nnstep - nstart, dp)
     928              :                averages(ibox)%averages%molecules = &
     929              :                   averages(ibox)%averages%molecules*REAL(nnstep - &
     930              :                                                          nstart - 1, dp)/REAL(nnstep - nstart, dp) + &
     931          899 :                   REAL(SUM(nchains(:, ibox)), dp)/REAL(nnstep - nstart, dp)
     932              :                averages(ibox)%averages%ave_volume = &
     933              :                   averages(ibox)%averages%ave_volume* &
     934              :                   REAL(nnstep - nstart - 1, dp)/REAL(nnstep - nstart, dp) + &
     935              :                   abc(1, ibox)*abc(2, ibox)*abc(3, ibox)/ &
     936          306 :                   REAL(nnstep - nstart, dp)
     937              : 
     938              :                ! flush the buffers to the files
     939          306 :                CALL m_flush(data_unit(ibox))
     940          306 :                CALL m_flush(diff(ibox))
     941          306 :                CALL m_flush(move_unit(ibox))
     942          306 :                CALL m_flush(cl(ibox))
     943          540 :                CALL m_flush(rm(ibox))
     944              : 
     945              :             END DO
     946              : 
     947              :             ! flush more buffers to the files
     948          234 :             CALL m_flush(cell_unit)
     949          234 :             CALL m_flush(com_ene)
     950          234 :             CALL m_flush(com_crd)
     951          234 :             CALL m_flush(com_mol)
     952              : 
     953              :          END IF
     954              : 
     955              :          ! reset the box flags
     956         1080 :          box_flag(:) = 0
     957              : 
     958              :          ! check to see if EXIT file exists...if so, end the calculation
     959          468 :          CALL external_control(should_stop, "MC", globenv=globenv)
     960          468 :          IF (should_stop) EXIT
     961              : 
     962              :          ! update the move displacements, if necessary
     963         1080 :          DO ibox = 1, nboxes
     964          612 :             IF (MOD(nnstep - nstart, iuptrans) == 0) THEN
     965            0 :                DO itype = 1, nmol_types
     966              :                   CALL mc_move_update(mc_par(ibox)%mc_par, &
     967              :                                       move_updates(itype, ibox)%moves, itype, &
     968            0 :                                       "trans", nnstep, ionode)
     969              :                END DO
     970              :             END IF
     971              : 
     972         1080 :             IF (MOD(nnstep - nstart, iupvolume) == 0) THEN
     973              :                CALL mc_move_update(mc_par(ibox)%mc_par, &
     974              :                                    move_updates(1, ibox)%moves, 1337, &
     975            0 :                                    "volume", nnstep, ionode)
     976              :             END IF
     977              :          END DO
     978              : 
     979              :          ! check to see if there are any overlaps in the boxes, and fold coordinates
     980              : ! don't care about overlaps if we're only doing HMC
     981          468 :          IF (.NOT. lhmc) THEN
     982         1040 :             DO ibox = 1, nboxes
     983         2206 :                IF (SUM(nchains(:, ibox)) /= 0) THEN
     984              :                   start_mol = 1
     985          736 :                   DO jbox = 1, ibox - 1
     986         1024 :                      start_mol = start_mol + SUM(nchains(:, jbox))
     987              :                   END DO
     988         1758 :                   end_mol = start_mol + SUM(nchains(:, ibox)) - 1
     989              :                   CALL check_for_overlap(force_env(ibox)%force_env, &
     990              :                                          nchains(:, ibox), nunits, loverlap, &
     991          592 :                                          mol_type(start_mol:end_mol))
     992          592 :                   IF (loverlap) THEN
     993            0 :                      IF (iw > 0) WRITE (iw, *) nnstep
     994            0 :                      CPABORT('coordinate overlap at the end of the above step')
     995              :                      ! now fold the coordinates...don't do this anywhere but here, because
     996              :                      ! we can get screwed up with the mc_molecule_info stuff (like in swap move)...
     997              :                      ! this is kind of ugly, with allocated and deallocating every time
     998            0 :                      ALLOCATE (r_temp(1:3, 1:nunits_tot(ibox)))
     999              : 
    1000            0 :                      DO iunit = 1, nunits_tot(ibox)
    1001              :                         r_temp(1:3, iunit) = &
    1002            0 :                            particles_old(ibox)%list%els(iunit)%r(1:3)
    1003              :                      END DO
    1004              : 
    1005              :                      CALL mc_coordinate_fold(r_temp(:, :), &
    1006              :                                              SUM(nchains(:, ibox)), mol_type(start_mol:end_mol), &
    1007            0 :                                              mass, nunits, abc(1:3, ibox))
    1008              : 
    1009              :                      ! save the folded coordinates
    1010            0 :                      DO iunit = 1, nunits_tot(ibox)
    1011            0 :                         r_old(1:3, iunit, ibox) = r_temp(1:3, iunit)
    1012              :                         particles_old(ibox)%list%els(iunit)%r(1:3) = &
    1013            0 :                            r_temp(1:3, iunit)
    1014              :                      END DO
    1015              : 
    1016              :                      ! if we're biasing, we need to do the same
    1017            0 :                      IF (lbias) THEN
    1018              :                         CALL force_env_get(bias_env(ibox)%force_env, &
    1019            0 :                                            subsys=biassys)
    1020              :                         CALL cp_subsys_get(biassys, &
    1021            0 :                                            particles=particles_bias)
    1022              : 
    1023            0 :                         DO iunit = 1, nunits_tot(ibox)
    1024              :                            particles_bias%els(iunit)%r(1:3) = &
    1025            0 :                               r_temp(1:3, iunit)
    1026              :                         END DO
    1027              :                      END IF
    1028              : 
    1029            0 :                      DEALLOCATE (r_temp)
    1030              :                   END IF
    1031              :                END IF
    1032              :             END DO
    1033              :          END IF
    1034              : 
    1035              :          !debug code
    1036          486 :          IF (debug_this_module) THEN
    1037              :             DO ibox = 1, nboxes
    1038              :                IF (SUM(nchains(:, ibox)) /= 0) THEN
    1039              :                   CALL force_env_calc_energy_force(force_env(ibox)%force_env, &
    1040              :                                                    calc_force=.FALSE.)
    1041              :                   CALL force_env_get(force_env(ibox)%force_env, &
    1042              :                                      potential_energy=test_energy)
    1043              :                ELSE
    1044              :                   test_energy = 0.0E0_dp
    1045              :                END IF
    1046              : 
    1047              :                IF (ABS(initial_energy(ibox) + energy_check(ibox) - &
    1048              :                        test_energy) > 0.0000001E0_dp) THEN
    1049              :                   IF (iw > 0) THEN
    1050              :                      WRITE (iw, *) '!!!!!!! We have an energy problem. !!!!!!!!'
    1051              :                      WRITE (iw, '(A,T64,F16.10)') 'Final Energy = ', test_energy
    1052              :                      WRITE (iw, '(A,T64,F16.10)') 'Initial Energy+energy_check=', &
    1053              :                         initial_energy(ibox) + energy_check(ibox)
    1054              :                      WRITE (iw, *) 'Box ', ibox
    1055              :                      WRITE (iw, *) 'nchains ', nchains(:, ibox)
    1056              :                   END IF
    1057              :                   CPABORT('!!!!!!! We have an energy problem. !!!!!!!!')
    1058              :                END IF
    1059              :             END DO
    1060              :          END IF
    1061              :       END DO
    1062              : 
    1063              :       ! write a restart file
    1064           18 :       IF (ionode) THEN
    1065           21 :          DO ibox = 1, nboxes
    1066              :             CALL write_mc_restart(nnstep, mc_par(ibox)%mc_par, &
    1067           21 :                                   nchains(:, ibox), force_env(ibox)%force_env)
    1068              :          END DO
    1069              :       END IF
    1070              : 
    1071              :       ! calculate the final energy
    1072           42 :       DO ibox = 1, nboxes
    1073           64 :          IF (SUM(nchains(:, ibox)) /= 0) THEN
    1074              :             CALL force_env_calc_energy_force(force_env(ibox)%force_env, &
    1075           24 :                                              calc_force=.FALSE.)
    1076              :             CALL force_env_get(force_env(ibox)%force_env, &
    1077           24 :                                potential_energy=final_energy(ibox))
    1078              :          ELSE
    1079            0 :             final_energy(ibox) = 0.0E0_dp
    1080              :          END IF
    1081           42 :          IF (lbias) THEN
    1082           14 :             CALL force_env_release(bias_env(ibox)%force_env)
    1083              :          END IF
    1084              :       END DO
    1085              : 
    1086              :       ! do some stuff in serial
    1087           18 :       IF (ionode .OR. (iw > 0)) THEN
    1088              : 
    1089            9 :          WRITE (com_ene, *) 'Final Energies:                      ', &
    1090           18 :             final_energy(1:nboxes)
    1091              : 
    1092           21 :          DO ibox = 1, nboxes
    1093           12 :             WRITE (cbox, '(I4)') ibox
    1094           32 :             IF (SUM(nchains(:, ibox)) == 0) THEN
    1095            0 :                WRITE (com_crd, *) ' 0'
    1096            0 :                WRITE (com_crd, *) 'BOX '//TRIM(ADJUSTL(cbox))
    1097              :             ELSE
    1098              :                CALL write_particle_coordinates( &
    1099              :                   particles_old(ibox)%list%els, &
    1100              :                   com_crd, dump_xmol, 'POS', &
    1101           12 :                   'FINAL BOX '//TRIM(ADJUSTL(cbox)), unit_conv=unit_conv)
    1102              :             END IF
    1103              : 
    1104              :             ! write a bunch of data to the screen
    1105              :             WRITE (iw, '(A)') &
    1106           12 :                '------------------------------------------------'
    1107              :             WRITE (iw, '(A,I1,A)') &
    1108           12 :                '|                   BOX ', ibox, &
    1109           24 :                '                      |'
    1110              :             WRITE (iw, '(A)') &
    1111           12 :                '------------------------------------------------'
    1112           12 :             test_moves => moves(:, ibox)
    1113              :             CALL final_mc_write(mc_par(ibox)%mc_par, test_moves, &
    1114              :                                 iw, energy_check(ibox), &
    1115              :                                 initial_energy(ibox), final_energy(ibox), &
    1116           12 :                                 averages(ibox)%averages)
    1117              : 
    1118              :             ! close any open files
    1119           12 :             CALL close_file(unit_number=diff(ibox))
    1120           12 :             CALL close_file(unit_number=data_unit(ibox))
    1121           12 :             CALL close_file(unit_number=move_unit(ibox))
    1122           12 :             CALL close_file(unit_number=cl(ibox))
    1123           21 :             CALL close_file(unit_number=rm(ibox))
    1124              :          END DO
    1125              : 
    1126              :          ! close some more files
    1127            9 :          CALL close_file(unit_number=cell_unit)
    1128            9 :          CALL close_file(unit_number=com_ene)
    1129            9 :          CALL close_file(unit_number=com_crd)
    1130            9 :          CALL close_file(unit_number=com_mol)
    1131              :       END IF
    1132              : 
    1133           42 :       DO ibox = 1, nboxes
    1134              :          CALL set_mc_env(mc_env(ibox)%mc_env, &
    1135              :                          mc_par=mc_par(ibox)%mc_par, &
    1136           24 :                          force_env=force_env(ibox)%force_env)
    1137              : 
    1138              :          ! deallocate some stuff
    1139           64 :          DO itype = 1, nmol_types
    1140           40 :             CALL mc_moves_release(move_updates(itype, ibox)%moves)
    1141           64 :             CALL mc_moves_release(moves(itype, ibox)%moves)
    1142              :          END DO
    1143           42 :          CALL mc_averages_release(averages(ibox)%averages)
    1144              :       END DO
    1145              : 
    1146           18 :       DEALLOCATE (pmhmc_box)
    1147           18 :       DEALLOCATE (pmvol_box)
    1148           18 :       DEALLOCATE (pmclus_box)
    1149           18 :       DEALLOCATE (r_old)
    1150           18 :       DEALLOCATE (force_env)
    1151           18 :       DEALLOCATE (bias_env)
    1152           18 :       DEALLOCATE (cell)
    1153           18 :       DEALLOCATE (particles_old)
    1154           18 :       DEALLOCATE (oldsys)
    1155           18 :       DEALLOCATE (averages)
    1156           18 :       DEALLOCATE (moves)
    1157           18 :       DEALLOCATE (move_updates)
    1158           18 :       DEALLOCATE (mc_par)
    1159              : 
    1160              :       ! end the timing
    1161           18 :       CALL timestop(handle)
    1162              : 
    1163           54 :    END SUBROUTINE mc_run_ensemble
    1164              : 
    1165              : ! **************************************************************************************************
    1166              : !> \brief Computes the second virial coefficient of a molecule by using the integral form
    1167              : !>      of the second virial coefficient found in McQuarrie "Statistical Thermodynamics",
    1168              : !>      B2(T) = -2Pi Int 0toInf [ Exp[-beta*u(r)] -1] r^2 dr     Eq. 15-25
    1169              : !>      I use trapazoidal integration with various step sizes
    1170              : !>      (the integral is broken up into three parts, currently, but that's easily
    1171              : !>      changed by the first variables found below).  It generates nvirial configurations,
    1172              : !>      doing the integration for each one, and then averages all the B2(T) to produce
    1173              : !>      the final answer.
    1174              : !> \param mc_env a pointer that contains all mc_env for all the simulation
    1175              : !>          boxes
    1176              : !> \param rng_stream the stream we pull random numbers from
    1177              : !>
    1178              : !>    Suitable for parallel.
    1179              : !> \author MJM
    1180              : ! **************************************************************************************************
    1181            2 :    SUBROUTINE mc_compute_virial(mc_env, rng_stream)
    1182              : 
    1183              :       TYPE(mc_environment_p_type), DIMENSION(:), POINTER :: mc_env
    1184              :       TYPE(rng_stream_type), INTENT(INOUT)               :: rng_stream
    1185              : 
    1186              :       INTEGER :: current_division, end_atom, ibin, idivision, iparticle, iprint, itemp, iunit, &
    1187              :          ivirial, iw, nbins, nchain_total, nintegral_divisions, nmol_types, nvirial, &
    1188              :          nvirial_temps, source, start_atom
    1189            2 :       INTEGER, DIMENSION(:), POINTER                     :: mol_type, nunits, nunits_tot
    1190            2 :       INTEGER, DIMENSION(:, :), POINTER                  :: nchains
    1191              :       LOGICAL                                            :: ionode, loverlap
    1192            2 :       REAL(dp), DIMENSION(:), POINTER                    :: BETA, virial_cutoffs, virial_stepsize, &
    1193            2 :                                                             virial_temps
    1194            2 :       REAL(dp), DIMENSION(:, :), POINTER                 :: mass, mayer, r_old
    1195              :       REAL(KIND=dp) :: ave_virial, current_value, distance, exp_max_val, exp_min_val, exponent, &
    1196              :          integral, previous_value, square_value, trial_energy, triangle_value
    1197              :       REAL(KIND=dp), DIMENSION(1:3)                      :: abc, center_of_mass
    1198            2 :       TYPE(cell_p_type), DIMENSION(:), POINTER           :: cell
    1199            2 :       TYPE(cp_subsys_p_type), DIMENSION(:), POINTER      :: subsys
    1200            2 :       TYPE(force_env_p_type), DIMENSION(:), POINTER      :: force_env
    1201              :       TYPE(mc_molecule_info_type), POINTER               :: mc_molecule_info
    1202              :       TYPE(mc_simulation_parameters_p_type), &
    1203            2 :          DIMENSION(:), POINTER                           :: mc_par
    1204              :       TYPE(mp_comm_type)                                 :: group
    1205            2 :       TYPE(particle_list_p_type), DIMENSION(:), POINTER  :: particles
    1206              : 
    1207              : ! these are current magic numbers for how we compute the virial...
    1208              : ! we break it up into three parts to integrate the function so provide
    1209              : ! better statistics
    1210              : 
    1211            2 :       nintegral_divisions = 3
    1212            0 :       ALLOCATE (virial_cutoffs(1:nintegral_divisions))
    1213            2 :       ALLOCATE (virial_stepsize(1:nintegral_divisions))
    1214            2 :       virial_cutoffs(1) = 8.0 ! first distance, in bohr
    1215            2 :       virial_cutoffs(2) = 13.0 ! second distance, in bohr
    1216            2 :       virial_cutoffs(3) = 22.0 ! maximum distance, in bohr
    1217            2 :       virial_stepsize(1) = 0.04 ! stepsize from 0 to virial_cutoffs(1)
    1218            2 :       virial_stepsize(2) = 0.1
    1219            2 :       virial_stepsize(3) = 0.2
    1220              : 
    1221              :       nbins = CEILING(virial_cutoffs(1)/virial_stepsize(1) + (virial_cutoffs(2) - virial_cutoffs(1))/ &
    1222              :                       virial_stepsize(2) + (virial_cutoffs(3) - virial_cutoffs(2))/virial_stepsize(3))
    1223              : 
    1224              :       ! figure out what the default write unit is
    1225            2 :       iw = cp_logger_get_default_io_unit()
    1226              : 
    1227              :       ! allocate a whole bunch of stuff based on how many boxes we have
    1228            4 :       ALLOCATE (force_env(1:1))
    1229            4 :       ALLOCATE (cell(1:1))
    1230            4 :       ALLOCATE (particles(1:1))
    1231            4 :       ALLOCATE (subsys(1:1))
    1232            4 :       ALLOCATE (mc_par(1:1))
    1233              : 
    1234              :       CALL get_mc_env(mc_env(1)%mc_env, &
    1235              :                       mc_par=mc_par(1)%mc_par, &
    1236            2 :                       force_env=force_env(1)%force_env)
    1237              : 
    1238              :       ! get some data out of mc_par
    1239              :       CALL get_mc_par(mc_par(1)%mc_par, &
    1240              :                       exp_max_val=exp_max_val, &
    1241              :                       exp_min_val=exp_min_val, nvirial=nvirial, &
    1242              :                       ionode=ionode, source=source, group=group, &
    1243            2 :                       mc_molecule_info=mc_molecule_info, virial_temps=virial_temps)
    1244              : 
    1245            2 :       IF (iw > 0) THEN
    1246            1 :          WRITE (iw, *)
    1247            1 :          WRITE (iw, *)
    1248            1 :          WRITE (iw, *) 'Beginning the calculation of the second virial coefficient'
    1249            1 :          WRITE (iw, *)
    1250            1 :          WRITE (iw, *)
    1251              :       END IF
    1252              : 
    1253              :       ! get some data from the molecule types
    1254              :       CALL get_mc_molecule_info(mc_molecule_info, &
    1255              :                                 nchains=nchains, nmol_types=nmol_types, nunits_tot=nunits_tot, &
    1256              :                                 mol_type=mol_type, nchain_total=nchain_total, nunits=nunits, &
    1257            2 :                                 mass=mass)
    1258              : 
    1259            2 :       nvirial_temps = SIZE(virial_temps)
    1260            6 :       ALLOCATE (BETA(1:nvirial_temps))
    1261              : 
    1262            6 :       DO itemp = 1, nvirial_temps
    1263            6 :          BETA(itemp) = 1/virial_temps(itemp)/boltzmann*joule
    1264              :       END DO
    1265              : 
    1266              :       ! get the subsystems and the cell information
    1267              :       CALL force_env_get(force_env(1)%force_env, &
    1268            2 :                          subsys=subsys(1)%subsys, cell=cell(1)%cell)
    1269            2 :       CALL get_cell(cell(1)%cell, abc=abc(:))
    1270              :       CALL cp_subsys_get(subsys(1)%subsys, &
    1271            2 :                          particles=particles(1)%list)
    1272              : 
    1273              :       ! check and make sure the box is big enough
    1274            2 :       IF (abc(1) /= abc(2) .OR. abc(2) /= abc(3)) THEN
    1275            0 :          CPABORT('The box needs to be cubic for a virial calculation (it is easiest).')
    1276              :       END IF
    1277            2 :       IF (virial_cutoffs(nintegral_divisions) > abc(1)/2.0E0_dp) THEN
    1278            0 :          IF (iw > 0) THEN
    1279            0 :             WRITE (iw, *) "Box length ", abc(1)*angstrom, " virial cutoff ", &
    1280            0 :                virial_cutoffs(nintegral_divisions)*angstrom
    1281              :          END IF
    1282            0 :          CPABORT('You need a bigger box to deal with this virial cutoff (see above).')
    1283              :       END IF
    1284              : 
    1285              :       ! store the coordinates of the molecules in an array so we can work with it
    1286            6 :       ALLOCATE (r_old(1:3, 1:nunits_tot(1)))
    1287              : 
    1288           14 :       DO iparticle = 1, nunits_tot(1)
    1289              :          r_old(1:3, iparticle) = &
    1290           50 :             particles(1)%list%els(iparticle)%r(1:3)
    1291              :       END DO
    1292              : 
    1293              :       ! move the center of mass of molecule 1 to the origin
    1294            2 :       start_atom = 1
    1295            2 :       end_atom = nunits(mol_type(1))
    1296              :       CALL get_center_of_mass(r_old(:, start_atom:end_atom), nunits(mol_type(1)), &
    1297            2 :                               center_of_mass(:), mass(1:nunits(mol_type(1)), mol_type(1)))
    1298            8 :       DO iunit = start_atom, end_atom
    1299           26 :          r_old(:, iunit) = r_old(:, iunit) - center_of_mass(:)
    1300              :       END DO
    1301              :       ! set them in the force_env, so the first molecule is ready for the energy calc
    1302            8 :       DO iparticle = start_atom, end_atom
    1303           44 :          particles(1)%list%els(iparticle)%r(1:3) = r_old(1:3, iparticle)
    1304              :       END DO
    1305              : 
    1306              :       ! print out a notice every 1%
    1307            2 :       iprint = FLOOR(REAL(nvirial, KIND=dp)/100.0_dp)
    1308            2 :       IF (iprint == 0) iprint = 1
    1309              : 
    1310              :       ! we'll compute the average potential, and then integrate that, as opposed to
    1311              :       ! integrating every orientation and then averaging
    1312            8 :       ALLOCATE (mayer(1:nvirial_temps, 1:nbins))
    1313              : 
    1314         1778 :       mayer(:, :) = 0.0_dp
    1315              : 
    1316              :       ! loop over all nvirial random configurations
    1317           22 :       DO ivirial = 1, nvirial
    1318              : 
    1319              :          ! move molecule two back to the origin
    1320           20 :          start_atom = nunits(mol_type(1)) + 1
    1321           20 :          end_atom = nunits_tot(1)
    1322              :          CALL get_center_of_mass(r_old(:, start_atom:end_atom), nunits(mol_type(2)), &
    1323           20 :                                  center_of_mass(:), mass(1:nunits(mol_type(2)), mol_type(2)))
    1324           80 :          DO iunit = start_atom, end_atom
    1325          260 :             r_old(:, iunit) = r_old(:, iunit) - center_of_mass(:)
    1326              :          END DO
    1327              : 
    1328              :          ! now we need a random orientation for molecule 2...this routine is
    1329              :          ! only done in serial since it calls a random number
    1330           20 :          IF (ionode) THEN
    1331              :             CALL rotate_molecule(r_old(:, start_atom:end_atom), &
    1332              :                                  mass(1:nunits(mol_type(2)), mol_type(2)), &
    1333           10 :                                  nunits(mol_type(2)), rng_stream)
    1334              :          END IF
    1335          980 :          CALL group%bcast(r_old(:, :), source)
    1336              : 
    1337           20 :          distance = 0.0E0_dp
    1338           20 :          ibin = 1
    1339         5900 :          DO
    1340              :             ! find out what our stepsize is
    1341         5920 :             current_division = 0
    1342         8780 :             DO idivision = 1, nintegral_divisions
    1343         8780 :                IF (distance < virial_cutoffs(idivision) - virial_stepsize(idivision)/2.0E0_dp) THEN
    1344              :                   current_division = idivision
    1345              :                   EXIT
    1346              :                END IF
    1347              :             END DO
    1348         5920 :             IF (current_division == 0) EXIT
    1349         5900 :             distance = distance + virial_stepsize(current_division)
    1350              : 
    1351              :             ! move the second molecule only along the x direction
    1352        23600 :             DO iparticle = start_atom, end_atom
    1353        17700 :                particles(1)%list%els(iparticle)%r(1) = r_old(1, iparticle) + distance
    1354        17700 :                particles(1)%list%els(iparticle)%r(2) = r_old(2, iparticle)
    1355        23600 :                particles(1)%list%els(iparticle)%r(3) = r_old(3, iparticle)
    1356              :             END DO
    1357              : 
    1358              :             ! check for overlaps
    1359         5900 :             CALL check_for_overlap(force_env(1)%force_env, nchains(:, 1), nunits, loverlap, mol_type)
    1360              : 
    1361              :             ! compute the energy if there is no overlap
    1362              :             ! exponent is exp(-beta*energy)-1, also called the Mayer term
    1363         5900 :             IF (loverlap) THEN
    1364         2202 :                DO itemp = 1, nvirial_temps
    1365         2202 :                   mayer(itemp, ibin) = mayer(itemp, ibin) - 1.0_dp
    1366              :                END DO
    1367              :             ELSE
    1368              :                CALL force_env_calc_energy_force(force_env(1)%force_env, &
    1369         5166 :                                                 calc_force=.FALSE.)
    1370              :                CALL force_env_get(force_env(1)%force_env, &
    1371         5166 :                                   potential_energy=trial_energy)
    1372              : 
    1373        15498 :                DO itemp = 1, nvirial_temps
    1374              : 
    1375        10332 :                   exponent = -BETA(itemp)*trial_energy
    1376              : 
    1377        10332 :                   IF (exponent > exp_max_val) THEN
    1378              :                      exponent = exp_max_val
    1379        10332 :                   ELSE IF (exponent < exp_min_val) THEN
    1380              :                      exponent = exp_min_val
    1381              :                   END IF
    1382        15498 :                   mayer(itemp, ibin) = mayer(itemp, ibin) + EXP(exponent) - 1.0_dp
    1383              :                END DO
    1384              :             END IF
    1385              : 
    1386         5900 :             ibin = ibin + 1
    1387              :          END DO
    1388              :          ! write out some info that keeps track of where we are
    1389           22 :          IF (iw > 0) THEN
    1390           10 :             IF (MOD(ivirial, iprint) == 0) THEN
    1391           10 :                WRITE (iw, '(A,I6,A,I6)') ' Done with config ', ivirial, ' out of ', nvirial
    1392              :             END IF
    1393              :          END IF
    1394              :       END DO
    1395              : 
    1396              :       ! now we integrate this average potential
    1397         1778 :       mayer(:, :) = mayer(:, :)/REAL(nvirial, dp)
    1398              : 
    1399            6 :       DO itemp = 1, nvirial_temps
    1400              :          integral = 0.0_dp
    1401              :          previous_value = 0.0_dp
    1402              :          distance = 0.0E0_dp
    1403              :          ibin = 1
    1404         1180 :          DO
    1405         1184 :             current_division = 0
    1406         1756 :             DO idivision = 1, nintegral_divisions
    1407         1756 :                IF (distance < virial_cutoffs(idivision) - virial_stepsize(idivision)/2.0E0_dp) THEN
    1408              :                   current_division = idivision
    1409              :                   EXIT
    1410              :                END IF
    1411              :             END DO
    1412         1184 :             IF (current_division == 0) EXIT
    1413         1180 :             distance = distance + virial_stepsize(current_division)
    1414              : 
    1415              :             ! now we need to integrate, using the trapazoidal method
    1416              :             ! first, find the value of the square
    1417         1180 :             current_value = mayer(itemp, ibin)*distance**2
    1418         1180 :             square_value = previous_value*virial_stepsize(current_division)
    1419              :             ! now the triangle that sits on top of it, which is half the size of this square...
    1420              :             ! notice this is negative if the current value is less than the previous value
    1421         1180 :             triangle_value = 0.5E0_dp*((current_value - previous_value)*virial_stepsize(current_division))
    1422              : 
    1423         1180 :             integral = integral + square_value + triangle_value
    1424         1180 :             previous_value = current_value
    1425         1180 :             ibin = ibin + 1
    1426              :          END DO
    1427              : 
    1428              :          ! now that the integration is done, compute the second virial that results
    1429            4 :          ave_virial = -2.0E0_dp*pi*integral
    1430              : 
    1431              :          ! convert from CP2K units to something else
    1432            4 :          ave_virial = ave_virial*n_avogadro*angstrom**3/1.0E8_dp**3
    1433              : 
    1434            6 :          IF (iw > 0) THEN
    1435            2 :             WRITE (iw, *)
    1436            2 :             WRITE (iw, *) '*********************************************************************'
    1437            2 :             WRITE (iw, '(A,F12.6,A)') ' ***                Temperature = ', virial_temps(itemp), &
    1438            4 :                '                     ***'
    1439            2 :             WRITE (iw, *) '***                                                               ***'
    1440            2 :             WRITE (iw, '(A,E12.6,A)') ' ***                  B2(T) = ', ave_virial, &
    1441            4 :                ' cm**3/mol               ***'
    1442            2 :             WRITE (iw, *) '*********************************************************************'
    1443            2 :             WRITE (iw, *)
    1444              :          END IF
    1445              :       END DO
    1446              : 
    1447              :       ! deallocate some stuff
    1448            2 :       DEALLOCATE (mc_par)
    1449            2 :       DEALLOCATE (subsys)
    1450            2 :       DEALLOCATE (force_env)
    1451            2 :       DEALLOCATE (particles)
    1452            2 :       DEALLOCATE (cell)
    1453            2 :       DEALLOCATE (virial_cutoffs)
    1454            2 :       DEALLOCATE (virial_stepsize)
    1455            2 :       DEALLOCATE (r_old)
    1456            2 :       DEALLOCATE (mayer)
    1457            2 :       DEALLOCATE (BETA)
    1458              : 
    1459            6 :    END SUBROUTINE mc_compute_virial
    1460              : 
    1461              : END MODULE mc_ensembles
    1462              : 
        

Generated by: LCOV version 2.0-1