LCOV - code coverage report
Current view: top level - src/motion - helium_worm.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:9843133) Lines: 1355 1570 86.3 %
Date: 2024-05-10 06:53:45 Functions: 19 19 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief  Methods dealing with the canonical worm alogrithm
      10             : !> \author Felix Uhl [fuhl]
      11             : !> \date   2018-10-10
      12             : ! **************************************************************************************************
      13             : MODULE helium_worm
      14             : 
      15             :    USE helium_common,                   ONLY: helium_calc_plength,&
      16             :                                               helium_eval_chain,&
      17             :                                               helium_eval_expansion,&
      18             :                                               helium_pbc,&
      19             :                                               helium_update_coord_system
      20             :    USE helium_interactions,             ONLY: helium_bead_solute_e_f,&
      21             :                                               helium_calc_energy,&
      22             :                                               helium_solute_e_f
      23             :    USE helium_io,                       ONLY: helium_write_line
      24             :    USE helium_types,                    ONLY: helium_solvent_type
      25             :    USE input_constants,                 ONLY: helium_forces_average,&
      26             :                                               helium_forces_last
      27             :    USE kinds,                           ONLY: default_string_length,&
      28             :                                               dp
      29             :    USE mathconstants,                   ONLY: pi
      30             :    USE pint_types,                      ONLY: pint_env_type
      31             : #include "../base/base_uses.f90"
      32             : 
      33             :    IMPLICIT NONE
      34             : 
      35             :    PRIVATE
      36             :    LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .TRUE.
      37             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'helium_worm'
      38             : 
      39             :    PUBLIC :: helium_sample_worm
      40             : 
      41             : CONTAINS
      42             : 
      43             : ! **************************************************************************************************
      44             : !> \brief Main worm sampling routine
      45             : !> \param helium ...
      46             : !> \param pint_env ...
      47             : !> \author fuhl
      48             : ! **************************************************************************************************
      49          27 :    SUBROUTINE helium_sample_worm(helium, pint_env)
      50             : 
      51             :       TYPE(helium_solvent_type), INTENT(INOUT)           :: helium
      52             :       TYPE(pint_env_type), INTENT(IN)                    :: pint_env
      53             : 
      54             :       CHARACTER(len=default_string_length)               :: stmp
      55             :       INTEGER :: ac, iatom, ibead, icrawl, iMC, imove, ncentracc, ncentratt, ncloseacc, ncloseatt, &
      56             :          ncrawlbwdacc, ncrawlbwdatt, ncrawlfwdacc, ncrawlfwdatt, ncycle, nMC, nmoveheadacc, &
      57             :          nmoveheadatt, nmovetailacc, nmovetailatt, nopenacc, nopenatt, npswapacc, nstagacc, &
      58             :          nstagatt, nstat, nswapacc, nswapatt, ntot, staging_l
      59             :       REAL(KIND=dp)                                      :: rtmp
      60             : 
      61          27 :       CALL helium_update_coord_system(helium, pint_env)
      62             : 
      63          27 :       ncentratt = 0
      64          27 :       ncentracc = 0
      65          27 :       nstagatt = 0
      66          27 :       nstagacc = 0
      67          27 :       nopenatt = 0
      68          27 :       nopenacc = 0
      69          27 :       ncloseatt = 0
      70          27 :       ncloseacc = 0
      71          27 :       nmoveheadatt = 0
      72          27 :       nmoveheadacc = 0
      73          27 :       nmovetailatt = 0
      74          27 :       nmovetailacc = 0
      75          27 :       ncrawlfwdatt = 0
      76          27 :       ncrawlfwdacc = 0
      77          27 :       ncrawlbwdatt = 0
      78          27 :       ncrawlbwdacc = 0
      79          27 :       nswapatt = 0
      80          27 :       npswapacc = 0
      81          27 :       nswapacc = 0
      82          27 :       nstat = 0
      83          27 :       ntot = 0
      84         108 :       helium%proarea%inst(:) = 0.d0
      85         108 :       helium%prarea2%inst(:) = 0.d0
      86         108 :       helium%wnumber%inst(:) = 0.d0
      87         108 :       helium%wnmber2%inst(:) = 0.d0
      88         108 :       helium%mominer%inst(:) = 0.d0
      89        2844 :       IF (helium%solute_present) helium%force_avrg(:, :) = 0.0d0
      90         297 :       helium%energy_avrg(:) = 0.0d0
      91         831 :       helium%plength_avrg(:) = 0.0d0
      92          27 :       IF (helium%worm_max_open_cycles > 0) THEN
      93           0 :          helium%savepos(:, :, :) = helium%pos(:, :, :)
      94           0 :          helium%saveiperm(:) = helium%iperm(:)
      95           0 :          helium%savepermutation(:) = helium%permutation(:)
      96             :       END IF
      97             : 
      98          27 :       nMC = helium%iter_rot
      99          27 :       ncycle = 0
     100          27 :       IF (helium%worm_allow_open) THEN
     101             :          DO ! Exit criterion at the end of the loop
     102       24622 :             DO iMC = 1, nMC
     103       24510 :                imove = helium%rng_stream_uniform%next(1, helium%worm_all_limit)
     104       24510 :                IF (helium%worm_is_closed) THEN
     105        6436 :                   IF ((imove >= helium%worm_centroid_min) .AND. (imove <= helium%worm_centroid_max)) THEN
     106             :                      ! centroid move
     107         183 :                      iatom = helium%rng_stream_uniform%next(1, helium%atoms)
     108             :                      CALL worm_centroid_move(pint_env, helium, &
     109         183 :                                              iatom, helium%worm_centroid_drmax, ac)
     110         183 :                      ncentratt = ncentratt + 1
     111         183 :                      ncentracc = ncentracc + ac
     112             :                      ! Note: weights for open and centroid move are taken from open sampling
     113             :                      ! staging is adjusted to conserve these weights
     114        6253 :                   ELSE IF ((imove >= helium%worm_centroid_max + 1) .AND. (imove <= helium%worm_open_close_min - 1)) THEN
     115             :                      ! staging move
     116        5461 :                      iatom = helium%rng_stream_uniform%next(1, helium%atoms)
     117        5461 :                      ibead = helium%rng_stream_uniform%next(1, helium%beads)
     118        5461 :                      staging_l = helium%rng_stream_uniform%next(2, helium%worm_staging_l)
     119             :                      CALL worm_staging_move(pint_env, helium, &
     120        5461 :                                             iatom, ibead, staging_l, ac)
     121        5461 :                      nstagatt = nstagatt + 1
     122        5461 :                      nstagacc = nstagacc + ac
     123         792 :                   ELSE IF ((imove >= helium%worm_open_close_min) .AND. (imove <= helium%worm_open_close_max)) THEN
     124             :                      ! attempt opening of worm
     125         792 :                      iatom = helium%rng_stream_uniform%next(1, helium%atoms)
     126         792 :                      ibead = helium%rng_stream_uniform%next(1, helium%beads)
     127         792 :                      staging_l = helium%rng_stream_uniform%next(2, helium%worm_staging_l)
     128             :                      CALL worm_open_move(pint_env, helium, &
     129         792 :                                          iatom, ibead, staging_l, ac)
     130         792 :                      nopenatt = nopenatt + 1
     131         792 :                      nopenacc = nopenacc + ac
     132             :                   ELSE
     133             :                      ! this must not occur
     134           0 :                      CPABORT("Undefined move selected in helium worm sampling!")
     135             :                   END IF
     136             :                ELSE ! worm is open
     137       18074 :                   IF ((imove >= helium%worm_centroid_min) .AND. (imove <= helium%worm_centroid_max)) THEN
     138             :                      ! centroid move
     139         463 :                      iatom = helium%rng_stream_uniform%next(1, helium%atoms)
     140             :                      CALL worm_centroid_move(pint_env, helium, &
     141         463 :                                              iatom, helium%worm_centroid_drmax, ac)
     142         463 :                      ncentratt = ncentratt + 1
     143         463 :                      ncentracc = ncentracc + ac
     144       17611 :                   ELSE IF ((imove >= helium%worm_staging_min) .AND. (imove <= helium%worm_staging_max)) THEN
     145             :                      ! staging move
     146        1047 :                      iatom = helium%rng_stream_uniform%next(1, helium%atoms)
     147        1047 :                      ibead = helium%rng_stream_uniform%next(1, helium%beads)
     148        1047 :                      staging_l = helium%rng_stream_uniform%next(2, helium%worm_staging_l)
     149             :                      CALL worm_staging_move(pint_env, helium, &
     150        1047 :                                             iatom, ibead, staging_l, ac)
     151        1047 :                      nstagatt = nstagatt + 1
     152        1047 :                      nstagacc = nstagacc + ac
     153       16564 :                   ELSE IF ((imove >= helium%worm_fcrawl_min) .AND. (imove <= helium%worm_fcrawl_max)) THEN
     154             :                      ! crawl forward
     155        2820 :                      DO icrawl = 1, helium%worm_repeat_crawl
     156        1880 :                         staging_l = helium%rng_stream_uniform%next(2, helium%worm_staging_l)
     157             :                         CALL worm_crawl_move_forward(pint_env, helium, &
     158        1880 :                                                      staging_l, ac)
     159        1880 :                         ncrawlfwdatt = ncrawlfwdatt + 1
     160        2820 :                         ncrawlfwdacc = ncrawlfwdacc + ac
     161             :                      END DO
     162       15624 :                   ELSE IF ((imove >= helium%worm_bcrawl_min) .AND. (imove <= helium%worm_bcrawl_max)) THEN
     163             :                      ! crawl backward
     164        3099 :                      DO icrawl = 1, helium%worm_repeat_crawl
     165        2066 :                         staging_l = helium%rng_stream_uniform%next(2, helium%worm_staging_l)
     166             :                         CALL worm_crawl_move_backward(pint_env, helium, &
     167        2066 :                                                       staging_l, ac)
     168        2066 :                         ncrawlbwdatt = ncrawlbwdatt + 1
     169        3099 :                         ncrawlbwdacc = ncrawlbwdacc + ac
     170             :                      END DO
     171       14591 :                   ELSE IF ((imove >= helium%worm_head_min) .AND. (imove <= helium%worm_head_max)) THEN
     172             :                      ! move head
     173        1033 :                      staging_l = helium%rng_stream_uniform%next(2, helium%worm_staging_l)
     174             :                      CALL worm_head_move(pint_env, helium, &
     175        1033 :                                          staging_l, ac)
     176        1033 :                      nmoveheadatt = nmoveheadatt + 1
     177        1033 :                      nmoveheadacc = nmoveheadacc + ac
     178       13558 :                   ELSE IF ((imove >= helium%worm_tail_min) .AND. (imove <= helium%worm_tail_max)) THEN
     179             :                      ! move tail
     180        1041 :                      staging_l = helium%rng_stream_uniform%next(2, helium%worm_staging_l)
     181             :                      CALL worm_tail_move(pint_env, helium, &
     182        1041 :                                          staging_l, ac)
     183        1041 :                      nmovetailatt = nmovetailatt + 1
     184        1041 :                      nmovetailacc = nmovetailacc + ac
     185       12517 :                   ELSE IF ((imove >= helium%worm_swap_min) .AND. (imove <= helium%worm_swap_max)) THEN
     186       10448 :                      staging_l = helium%rng_stream_uniform%next(2, helium%worm_staging_l)
     187             :                      CALL worm_swap_move(pint_env, helium, &
     188       10448 :                                          helium%atoms, staging_l, ac)
     189       10448 :                      npswapacc = npswapacc + ac
     190       10448 :                      nswapacc = nswapacc + ac
     191       10448 :                      nswapatt = nswapatt + 1
     192        2069 :                   ELSE IF ((imove >= helium%worm_open_close_min) .AND. (imove <= helium%worm_open_close_max)) THEN
     193             :                      ! attempt closing of worm
     194        2069 :                      staging_l = helium%rng_stream_uniform%next(2, helium%worm_staging_l)
     195             :                      CALL worm_close_move(pint_env, helium, &
     196        2069 :                                           staging_l, ac)
     197        2069 :                      ncloseatt = ncloseatt + 1
     198        2069 :                      ncloseacc = ncloseacc + ac
     199             :                   ELSE
     200             :                      ! this must not occur
     201           0 :                      CPABORT("Undefined move selected in helium worm sampling!")
     202             :                   END IF
     203             :                END IF
     204             : 
     205             :                ! Accumulate statistics if we are in the Z-sector:
     206       24510 :                IF (helium%worm_is_closed) THEN
     207        6436 :                   nstat = nstat + 1
     208        6436 :                   IF (helium%solute_present) THEN
     209        6212 :                      IF (helium%get_helium_forces == helium_forces_average) THEN
     210             :                         !TODO needs proper averaging!
     211           0 :                         CALL helium_solute_e_f(pint_env, helium, rtmp)
     212           0 :                         helium%force_avrg(:, :) = helium%force_avrg(:, :) + helium%force_inst(:, :)
     213             :                      END IF
     214             :                   END IF
     215             :                END IF
     216       24622 :                ntot = ntot + 1
     217             :             END DO ! MC loop
     218             : 
     219         112 :             IF (helium%worm_is_closed) THEN
     220             :                EXIT
     221             :             ELSE
     222          85 :                ncycle = ncycle + 1
     223             :                ! reset position and permutation and start MC cycle again
     224             :                ! if stuck in open position for too long
     225          85 :                IF (helium%worm_max_open_cycles > 0 .AND. ncycle > helium%worm_max_open_cycles) THEN
     226           0 :                   nMC = helium%iter_rot
     227           0 :                   ncycle = 0
     228           0 :                   helium%pos = helium%savepos
     229           0 :                   helium%work = helium%pos
     230           0 :                   helium%permutation = helium%savepermutation
     231           0 :                   helium%iperm = helium%saveiperm
     232           0 :                   CPWARN("Trapped in open state, reset helium to closed state from last MD step.")
     233             :                ELSE
     234          85 :                   nMC = MAX(helium%iter_rot/10, 10)
     235             :                END IF
     236             :             END IF
     237             :          END DO !attempts loop
     238             :       ELSE ! only closed configurations allowed
     239           0 :          DO iMC = 1, nMC
     240           0 :             imove = helium%rng_stream_uniform%next(1, helium%worm_all_limit)
     241             : 
     242           0 :             IF ((imove >= helium%worm_centroid_min) .AND. (imove <= helium%worm_centroid_max)) THEN
     243             :                ! centroid move
     244           0 :                iatom = helium%rng_stream_uniform%next(1, helium%atoms)
     245             :                CALL worm_centroid_move(pint_env, helium, &
     246           0 :                                        iatom, helium%worm_centroid_drmax, ac)
     247           0 :                ncentratt = ncentratt + 1
     248           0 :                ncentracc = ncentracc + ac
     249           0 :             ELSE IF ((imove >= helium%worm_staging_min) .AND. (imove <= helium%worm_staging_max)) THEN
     250             :                ! staging move
     251           0 :                iatom = helium%rng_stream_uniform%next(1, helium%atoms)
     252           0 :                ibead = helium%rng_stream_uniform%next(1, helium%beads)
     253             :                CALL worm_staging_move(pint_env, helium, &
     254           0 :                                       iatom, ibead, helium%worm_staging_l, ac)
     255           0 :                nstagatt = nstagatt + 1
     256           0 :                nstagacc = nstagacc + ac
     257             :             ELSE
     258             :                ! this must not occur
     259           0 :                CPABORT("Undefined move selected in helium worm sampling!")
     260             :             END IF
     261             : 
     262             :             ! Accumulate statistics if we are in closed configurations (which we always are)
     263           0 :             nstat = nstat + 1
     264           0 :             ntot = ntot + 1
     265           0 :             IF (helium%solute_present) THEN
     266           0 :                IF (helium%get_helium_forces == helium_forces_average) THEN
     267             :                   ! TODO: needs proper averaging
     268           0 :                   CALL helium_solute_e_f(pint_env, helium, rtmp)
     269           0 :                   helium%force_avrg(:, :) = helium%force_avrg(:, :) + helium%force_inst(:, :)
     270             :                END IF
     271             :             END IF
     272             :          END DO ! MC loop
     273             :       END IF
     274             : 
     275             :       ! Save naccepted and ntot
     276             :       helium%num_accepted(1, 1) = ncentracc + nstagacc + nopenacc + ncloseacc + nswapacc + &
     277          27 :                                   nmoveheadacc + nmovetailacc + ncrawlfwdacc + ncrawlbwdacc
     278             :       helium%num_accepted(2, 1) = ncentratt + nstagatt + nopenatt + ncloseatt + nswapatt + &
     279          27 :                                   nmoveheadatt + nmovetailatt + ncrawlfwdatt + ncrawlbwdatt
     280          27 :       helium%worm_nstat = nstat
     281             : 
     282             :       ! Calculate energy and permutation path length
     283             :       ! Multiply times helium%worm_nstat for consistent averaging in helium_sampling
     284          27 :       CALL helium_calc_energy(helium, pint_env)
     285         297 :       helium%energy_avrg(:) = helium%energy_inst(:)*REAL(helium%worm_nstat, dp)
     286             : 
     287          27 :       CALL helium_calc_plength(helium)
     288         831 :       helium%plength_avrg(:) = helium%plength_inst(:)*REAL(helium%worm_nstat, dp)
     289             : 
     290             :       ! Calculate last_force
     291          27 :       IF (helium%solute_present) THEN
     292          17 :          IF (helium%get_helium_forces == helium_forces_last) THEN
     293          17 :             CALL helium_solute_e_f(pint_env, helium, rtmp)
     294        2834 :             helium%force_avrg(:, :) = helium%force_avrg(:, :) + helium%force_inst(:, :)
     295             :          END IF
     296             :       END IF
     297             : 
     298          27 :       IF (helium%worm_show_statistics) THEN
     299          27 :          WRITE (stmp, *) '--------------------------------------------------'
     300          27 :          CALL helium_write_line(stmp)
     301          27 :          WRITE (stmp, '(A10,F15.5,2I10)') 'Opening: ', &
     302          27 :             REAL(nopenacc, dp)/REAL(MAX(1, nopenatt), dp), &
     303          54 :             nopenacc, nopenatt
     304          27 :          CALL helium_write_line(stmp)
     305          27 :          WRITE (stmp, '(A10,F15.5,2I10)') 'Closing: ', &
     306          27 :             REAL(ncloseacc, dp)/REAL(MAX(1, ncloseatt), dp), &
     307          54 :             ncloseacc, ncloseatt
     308          27 :          CALL helium_write_line(stmp)
     309          27 :          WRITE (stmp, '(A10,F15.5,2I10)') 'Move Head: ', &
     310          27 :             REAL(nmoveheadacc, dp)/REAL(MAX(1, nmoveheadatt), dp), &
     311          54 :             nmoveheadacc, nmoveheadatt
     312          27 :          CALL helium_write_line(stmp)
     313          27 :          WRITE (stmp, '(A10,F15.5,2I10)') 'Move Tail: ', &
     314          27 :             REAL(nmovetailacc, dp)/REAL(MAX(1, nmovetailatt), dp), &
     315          54 :             nmovetailacc, nmovetailatt
     316          27 :          CALL helium_write_line(stmp)
     317          27 :          WRITE (stmp, '(A10,F15.5,2I10)') 'Crawl FWD: ', &
     318          27 :             REAL(ncrawlfwdacc, dp)/REAL(MAX(1, ncrawlfwdatt), dp), &
     319          54 :             ncrawlfwdacc, ncrawlfwdatt
     320          27 :          CALL helium_write_line(stmp)
     321          27 :          WRITE (stmp, '(A10,F15.5,2I10)') 'Crawl BWD: ', &
     322          27 :             REAL(ncrawlbwdacc, dp)/REAL(MAX(1, ncrawlbwdatt), dp), &
     323          54 :             ncrawlbwdacc, ncrawlbwdatt
     324          27 :          CALL helium_write_line(stmp)
     325          27 :          WRITE (stmp, '(A10,F15.5,2I10)') 'Staging: ', &
     326          27 :             REAL(nstagacc, dp)/REAL(MAX(1, nstagatt), dp), &
     327          54 :             nstagacc, nstagatt
     328          27 :          CALL helium_write_line(stmp)
     329          27 :          WRITE (stmp, '(A10,F15.5,2I10)') 'Centroid: ', &
     330          27 :             REAL(ncentracc, dp)/REAL(MAX(1, ncentratt), dp), &
     331          54 :             ncentracc, ncentratt
     332          27 :          CALL helium_write_line(stmp)
     333          27 :          WRITE (stmp, '(A10,F15.5,2I10)') 'Select: ', &
     334          27 :             REAL(npswapacc, dp)/REAL(MAX(1, nswapatt), dp), &
     335          54 :             npswapacc, nswapatt
     336          27 :          CALL helium_write_line(stmp)
     337          27 :          WRITE (stmp, '(A10,F15.5,2I10)') 'Swapping: ', &
     338          27 :             REAL(nswapacc, dp)/REAL(MAX(1, nswapatt), dp), &
     339          54 :             nswapacc, nswapatt
     340          27 :          CALL helium_write_line(stmp)
     341          27 :          WRITE (stmp, *) "Open State Probability:   ", REAL(ntot - nstat, dp)/REAL(MAX(1, ntot), dp), ntot - nstat, ntot
     342          27 :          CALL helium_write_line(stmp)
     343          27 :          WRITE (stmp, *) "Closed State Probability: ", REAL(nstat, dp)/REAL(MAX(1, ntot), dp), nstat, ntot
     344          27 :          CALL helium_write_line(stmp)
     345             :       END IF
     346             : 
     347             :       !CALL center_pos(helium)
     348             : 
     349          27 :    END SUBROUTINE helium_sample_worm
     350             : 
     351             : ! **************************************************************************************************
     352             : !> \brief Centroid Move (accounting for exchanged particles)
     353             : !> \param pint_env ...
     354             : !> \param helium ...
     355             : !> \param iatom ...
     356             : !> \param drmax ...
     357             : !> \param ac ...
     358             : !> \author fuhl
     359             : ! **************************************************************************************************
     360         646 :    SUBROUTINE worm_centroid_move(pint_env, helium, iatom, drmax, ac)
     361             : 
     362             :       TYPE(pint_env_type), INTENT(IN)                    :: pint_env
     363             :       TYPE(helium_solvent_type), INTENT(INOUT)           :: helium
     364             :       INTEGER, INTENT(IN)                                :: iatom
     365             :       REAL(KIND=dp), INTENT(IN)                          :: drmax
     366             :       INTEGER, INTENT(OUT)                               :: ac
     367             : 
     368             :       INTEGER                                            :: ia, ib, ic, jatom
     369             :       LOGICAL                                            :: should_reject, worm_in_moved_cycle
     370             :       REAL(KIND=dp)                                      :: rtmp, rtmpo, sdiff, snew, sold
     371             :       REAL(KIND=dp), DIMENSION(3)                        :: dr, dro, new_com, old_com
     372             : 
     373        2584 :       DO ic = 1, 3
     374        1938 :          rtmp = helium%rng_stream_uniform%next()
     375        2584 :          dr(ic) = (2.0_dp*rtmp - 1.0_dp)*drmax
     376             :       END DO
     377             : 
     378         646 :       IF (helium%worm_is_closed) THEN
     379         183 :          worm_in_moved_cycle = .FALSE.
     380             :          ! Perform move for first atom
     381        3210 :          DO ib = 1, helium%beads
     382       12291 :             helium%work(:, iatom, ib) = helium%work(:, iatom, ib) + dr(:)
     383             :          END DO
     384             :          ! move along permutation cycle
     385         183 :          jatom = helium%permutation(iatom)
     386         183 :          DO WHILE (jatom /= iatom)
     387           0 :             DO ib = 1, helium%beads
     388           0 :                helium%work(:, jatom, ib) = helium%work(:, jatom, ib) + dr(:)
     389             :             END DO
     390             :             ! next atom in chain
     391           0 :             jatom = helium%permutation(jatom)
     392             :          END DO
     393             :       ELSE ! worm is open
     394         463 :          worm_in_moved_cycle = (helium%worm_atom_idx == iatom)
     395             :          ! while moving, check if worm is in moved cycle
     396             :          ! Perform move for first atom
     397        7907 :          DO ib = 1, helium%beads
     398       30239 :             helium%work(:, iatom, ib) = helium%work(:, iatom, ib) + dr(:)
     399             :          END DO
     400             :          ! move along permutation cycle
     401         463 :          jatom = helium%permutation(iatom)
     402         463 :          DO WHILE (jatom /= iatom)
     403           0 :             DO ib = 1, helium%beads
     404           0 :                helium%work(:, jatom, ib) = helium%work(:, jatom, ib) + dr(:)
     405             :             END DO
     406           0 :             worm_in_moved_cycle = worm_in_moved_cycle .OR. (helium%worm_atom_idx == jatom)
     407             :             ! next atom in chain
     408           0 :             jatom = helium%permutation(jatom)
     409             :          END DO
     410             :          ! if atom contains had bead move that as well
     411         463 :          IF (worm_in_moved_cycle) THEN
     412          76 :             helium%worm_xtra_bead_work(:) = helium%worm_xtra_bead(:) + dr(:)
     413             :          END IF
     414             :       END IF
     415             : 
     416             :       sold = worm_centroid_move_action(helium, helium%pos, iatom, &
     417         646 :                                        helium%worm_xtra_bead, worm_in_moved_cycle)
     418             : 
     419             :       snew = worm_centroid_move_action(helium, helium%work, iatom, &
     420         646 :                                        helium%worm_xtra_bead_work, worm_in_moved_cycle)
     421             : 
     422         646 :       IF (helium%solute_present) THEN
     423             :          sold = sold + worm_centroid_move_inter_action(pint_env, helium, helium%pos, iatom, &
     424         631 :                                                        helium%worm_xtra_bead, worm_in_moved_cycle)
     425             :          snew = snew + worm_centroid_move_inter_action(pint_env, helium, helium%work, iatom, &
     426         631 :                                                        helium%worm_xtra_bead_work, worm_in_moved_cycle)
     427             :       END IF
     428             : 
     429             :       ! Metropolis:
     430         646 :       sdiff = sold - snew
     431         646 :       IF (sdiff < 0) THEN
     432         321 :          should_reject = .FALSE.
     433         321 :          IF (sdiff < -100.0_dp) THEN ! To protect from exponential underflow
     434             :             should_reject = .TRUE.
     435             :          ELSE
     436         321 :             rtmp = helium%rng_stream_uniform%next()
     437         321 :             IF (EXP(sdiff) < rtmp) THEN
     438             :                should_reject = .TRUE.
     439             :             END IF
     440             :          END IF
     441             :          IF (should_reject) THEN
     442             :             ! rejected !
     443             :             ! write back only changed atoms
     444         206 :             DO ib = 1, helium%beads
     445         794 :                helium%work(:, iatom, ib) = helium%pos(:, iatom, ib)
     446             :             END DO
     447             :             ! move along permutation cycle
     448          10 :             jatom = helium%permutation(iatom)
     449          10 :             DO WHILE (jatom /= iatom)
     450           0 :                DO ib = 1, helium%beads
     451           0 :                   helium%work(:, jatom, ib) = helium%pos(:, jatom, ib)
     452             :                END DO
     453             :                ! next atom in chain
     454           0 :                jatom = helium%permutation(jatom)
     455             :             END DO
     456          40 :             helium%worm_xtra_bead_work(:) = helium%worm_xtra_bead(:)
     457          10 :             ac = 0
     458          12 :             RETURN
     459             :          END IF
     460             :       END IF
     461             : 
     462             :       ! for now accepted
     463             :       ! rejection of the whole move if any centroid is farther away
     464             :       ! from the current center of gravity than HELIUM%DROPLET_RADIUS [lwalewski]
     465             :       ! AND ist not moving towards the center
     466         636 :       IF (.NOT. helium%periodic) THEN
     467         625 :          IF (helium%solute_present) THEN
     468        2500 :             new_com(:) = helium%center(:)
     469         625 :             old_com(:) = new_com(:)
     470             :          ELSE
     471           0 :             new_com(:) = 0.0_dp
     472           0 :             DO ia = 1, helium%atoms
     473           0 :                DO ib = 1, helium%beads
     474           0 :                   new_com(:) = new_com(:) + helium%work(:, ia, ib)
     475             :                END DO
     476             :             END DO
     477           0 :             new_com(:) = new_com(:)/(REAL(helium%atoms*helium%beads, dp))
     478             :             ! also compute the old center of mass (optimization potential)
     479           0 :             old_com(:) = 0.0_dp
     480           0 :             DO ia = 1, helium%atoms
     481           0 :                DO ib = 1, helium%beads
     482           0 :                   old_com(:) = old_com(:) + helium%pos(:, ia, ib)
     483             :                END DO
     484             :             END DO
     485           0 :             old_com(:) = old_com(:)/(REAL(helium%atoms*helium%beads, dp))
     486             :          END IF
     487         625 :          should_reject = .FALSE.
     488       18905 :          atom: DO ia = 1, helium%atoms
     489       18282 :             dr(:) = 0.0_dp
     490      310794 :             DO ib = 1, helium%beads
     491     1188330 :                dr(:) = dr(:) + helium%work(:, ia, ib) - new_com(:)
     492             :             END DO
     493       73128 :             dr(:) = dr(:)/REAL(helium%beads, dp)
     494       73128 :             rtmp = DOT_PRODUCT(dr, dr)
     495       18905 :             IF (rtmp >= helium%droplet_radius**2) THEN
     496           2 :                dro(:) = 0.0_dp
     497          34 :                DO ib = 1, helium%beads
     498         130 :                   dro(:) = dro(:) + helium%pos(:, ia, ib) - old_com(:)
     499             :                END DO
     500           8 :                dro(:) = dro(:)/REAL(helium%beads, dp)
     501           8 :                rtmpo = DOT_PRODUCT(dro, dro)
     502             :                ! only reject if it moves away from COM outside the droplet radius
     503           2 :                IF (rtmpo < rtmp) THEN
     504             :                   ! found - this one does not fit within R from the center
     505             :                   should_reject = .TRUE.
     506             :                   EXIT atom
     507             :                END IF
     508             :             END IF
     509             :          END DO atom
     510         625 :          IF (should_reject) THEN
     511             :             ! restore original coordinates
     512             :             ! write back only changed atoms
     513          34 :             DO ib = 1, helium%beads
     514         130 :                helium%work(:, iatom, ib) = helium%pos(:, iatom, ib)
     515             :             END DO
     516             :             ! move along permutation cycle
     517           2 :             jatom = helium%permutation(iatom)
     518           2 :             DO WHILE (jatom /= iatom)
     519           0 :                DO ib = 1, helium%beads
     520           0 :                   helium%work(:, jatom, ib) = helium%pos(:, jatom, ib)
     521             :                END DO
     522             :                ! next atom in chain
     523           0 :                jatom = helium%permutation(jatom)
     524             :             END DO
     525           8 :             helium%worm_xtra_bead_work(:) = helium%worm_xtra_bead(:)
     526           2 :             ac = 0
     527           2 :             RETURN
     528             :          END IF
     529             :       END IF
     530             : 
     531             :       ! finally accepted
     532         634 :       ac = 1
     533             :       ! write changed coordinates to position array
     534       10877 :       DO ib = 1, helium%beads
     535       41606 :          helium%pos(:, iatom, ib) = helium%work(:, iatom, ib)
     536             :       END DO
     537             :       ! move along permutation cycle
     538         634 :       jatom = helium%permutation(iatom)
     539         634 :       DO WHILE (jatom /= iatom)
     540           0 :          DO ib = 1, helium%beads
     541           0 :             helium%pos(:, jatom, ib) = helium%work(:, jatom, ib)
     542             :          END DO
     543             :          ! next atom in chain
     544           0 :          jatom = helium%permutation(jatom)
     545             :       END DO
     546        2536 :       helium%worm_xtra_bead(:) = helium%worm_xtra_bead_work(:)
     547             : 
     548             :    END SUBROUTINE worm_centroid_move
     549             : 
     550             : ! **************************************************************************************************
     551             : !> \brief Action for centroid move
     552             : !> \param helium ...
     553             : !> \param pos ...
     554             : !> \param iatom ...
     555             : !> \param xtrapos ...
     556             : !> \param winc ...
     557             : !> \return ...
     558             : !> \author fuhl
     559             : ! **************************************************************************************************
     560        1292 :    REAL(KIND=dp) FUNCTION worm_centroid_move_action(helium, pos, iatom, xtrapos, winc) &
     561             :       RESULT(partaction)
     562             : 
     563             :       TYPE(helium_solvent_type), INTENT(INOUT)           :: helium
     564             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN), &
     565             :          POINTER                                         :: pos
     566             :       INTEGER, INTENT(IN)                                :: iatom
     567             :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: xtrapos
     568             :       LOGICAL, INTENT(IN)                                :: winc
     569             : 
     570             :       INTEGER                                            :: ia, ib, jatom, katom, opatom, patom, &
     571             :                                                             wbead
     572             :       LOGICAL                                            :: incycle
     573        1292 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: work2, work3
     574        1292 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: work
     575             :       REAL(KIND=dp), DIMENSION(3)                        :: r, rp
     576             : 
     577        9044 :       ALLOCATE (work(3, helium%beads + 1), work2(helium%beads + 1), work3(SIZE(helium%uoffdiag, 1) + 1))
     578             : 
     579             :       ! compute action difference
     580             :       ! action before the move from pos array
     581        1292 :       partaction = 0.0_dp
     582             : 
     583             :       ! pair of first atom with non-in-cycle atoms
     584        1292 :       jatom = iatom
     585       39204 :       DO ia = 1, helium%atoms
     586       37912 :          IF (ia == jatom) CYCLE
     587       36620 :          incycle = .FALSE.
     588       36620 :          katom = helium%permutation(jatom)
     589       36620 :          DO WHILE (katom /= jatom)
     590           0 :             IF (katom == ia) THEN
     591             :                incycle = .TRUE.
     592             :                EXIT
     593             :             END IF
     594           0 :             katom = helium%permutation(katom)
     595             :          END DO
     596       36620 :          IF (incycle) CYCLE
     597             :          ! if not in cycle, compute pair action
     598      630910 :          DO ib = 1, helium%beads
     599     2413780 :             work(:, ib) = pos(:, ia, ib) - pos(:, jatom, ib)
     600             :          END DO
     601             :          work(:, helium%beads + 1) = pos(:, helium%permutation(ia), 1) - &
     602      146480 :                                      pos(:, helium%permutation(jatom), 1)
     603       39204 :          partaction = partaction + helium_eval_chain(helium, work, helium%beads + 1, work2, work3)
     604             :       END DO
     605             :       ! all other cycle atoms with non-in-cycle atoms
     606        1292 :       jatom = helium%permutation(iatom)
     607        1292 :       DO WHILE (jatom /= iatom)
     608           0 :          DO ia = 1, helium%atoms
     609           0 :             IF (ia == jatom) CYCLE
     610           0 :             incycle = .FALSE.
     611           0 :             katom = helium%permutation(jatom)
     612           0 :             DO WHILE (katom /= jatom)
     613           0 :                IF (katom == ia) THEN
     614             :                   incycle = .TRUE.
     615             :                   EXIT
     616             :                END IF
     617           0 :                katom = helium%permutation(katom)
     618             :             END DO
     619           0 :             IF (incycle) CYCLE
     620             :             ! if not in cycle, compute pair action
     621           0 :             DO ib = 1, helium%beads
     622           0 :                work(:, ib) = pos(:, ia, ib) - pos(:, jatom, ib)
     623             :             END DO
     624             :             work(:, helium%beads + 1) = pos(:, helium%permutation(ia), 1) - &
     625           0 :                                         pos(:, helium%permutation(jatom), 1)
     626           0 :             partaction = partaction + helium_eval_chain(helium, work, helium%beads + 1, work2, work3)
     627             :          END DO
     628           0 :          jatom = helium%permutation(jatom)
     629             :       END DO
     630             :       ! correct pair action for open worm configurations
     631        1292 :       IF (.NOT. helium%worm_is_closed) THEN
     632         926 :          wbead = helium%worm_bead_idx
     633         926 :          IF (winc) THEN
     634          38 :             IF (helium%worm_bead_idx == 1) THEN
     635             :                ! patom is the atom in front of the lone head bead
     636           8 :                patom = helium%iperm(helium%worm_atom_idx)
     637             :                ! go through all atoms, not in the cycle, and correct pair action
     638         264 :                DO ia = 1, helium%atoms
     639         256 :                   IF (ia == helium%worm_atom_idx) CYCLE
     640         248 :                   incycle = .FALSE.
     641         248 :                   katom = helium%permutation(helium%worm_atom_idx)
     642         248 :                   DO WHILE (katom /= helium%worm_atom_idx)
     643           0 :                      IF (katom == ia) THEN
     644             :                         incycle = .TRUE.
     645             :                         EXIT
     646             :                      END IF
     647           0 :                      katom = helium%permutation(katom)
     648             :                   END DO
     649         248 :                   IF (incycle) CYCLE
     650             :                   ! find other previous atom
     651             :                   ! opatom is the atom in front of the first bead of the second atom
     652         248 :                   opatom = helium%iperm(ia)
     653             :                   ! if not in cycle, compute pair action
     654             :                   ! subtract pair action for closed link
     655         992 :                   r(:) = pos(:, helium%worm_atom_idx, 1) - pos(:, ia, 1)
     656         992 :                   rp(:) = pos(:, patom, helium%beads) - pos(:, opatom, helium%beads)
     657         248 :                   partaction = partaction - helium_eval_expansion(helium, r, rp, work3)
     658             :                   ! and add corrected extra link
     659             :                   ! rp stays the same
     660         992 :                   r(:) = xtrapos(:) - pos(:, ia, 1)
     661         264 :                   partaction = partaction + helium_eval_expansion(helium, r, rp, work3)
     662             :                END DO
     663             :             ELSE ! bead index /= 1
     664             :                ! atom index is constant
     665             :                ! go through all atoms, not in the cycle, and correct pair action
     666         870 :                DO ia = 1, helium%atoms
     667         840 :                   IF (ia == helium%worm_atom_idx) CYCLE
     668         810 :                   incycle = .FALSE.
     669         810 :                   katom = helium%permutation(helium%worm_atom_idx)
     670         810 :                   DO WHILE (katom /= helium%worm_atom_idx)
     671           0 :                      IF (katom == ia) THEN
     672             :                         incycle = .TRUE.
     673             :                         EXIT
     674             :                      END IF
     675           0 :                      katom = helium%permutation(katom)
     676             :                   END DO
     677         810 :                   IF (incycle) CYCLE
     678             :                   ! if not in cycle, compute pair action
     679             :                   ! subtract pair action for closed link
     680        3240 :                   r(:) = pos(:, helium%worm_atom_idx, wbead) - pos(:, ia, wbead)
     681        3240 :                   rp(:) = pos(:, helium%worm_atom_idx, wbead - 1) - pos(:, ia, wbead - 1)
     682         810 :                   partaction = partaction - helium_eval_expansion(helium, r, rp, work3)
     683             :                   ! and add corrected extra link
     684             :                   ! rp stays the same
     685        3240 :                   r(:) = xtrapos(:) - pos(:, ia, wbead)
     686         870 :                   partaction = partaction + helium_eval_expansion(helium, r, rp, work3)
     687             :                END DO
     688             :             END IF
     689             :          ELSE ! worm is not the moved cycle
     690         888 :             IF (helium%worm_bead_idx == 1) THEN
     691             :                ! patom is the atom in front of the lone head bead
     692          60 :                patom = helium%iperm(helium%worm_atom_idx)
     693          60 :                opatom = helium%iperm(iatom)
     694             :                !correct action contribution for first atom in moved cycle
     695         240 :                r(:) = pos(:, helium%worm_atom_idx, 1) - pos(:, iatom, 1)
     696         240 :                rp(:) = pos(:, patom, helium%beads) - pos(:, opatom, helium%beads)
     697          60 :                partaction = partaction - helium_eval_expansion(helium, r, rp, work3)
     698             :                ! and add corrected extra link
     699             :                ! rp stays the same
     700         240 :                r(:) = xtrapos(:) - pos(:, iatom, 1)
     701          60 :                partaction = partaction + helium_eval_expansion(helium, r, rp, work3)
     702             :                ! go through all other atoms, not in the exchange cycle, and correct pair action
     703          60 :                ia = helium%permutation(iatom)
     704          60 :                DO WHILE (ia /= iatom)
     705           0 :                   opatom = helium%iperm(ia)
     706             :                   ! subtract pair action for closed link
     707           0 :                   r(:) = pos(:, helium%worm_atom_idx, 1) - pos(:, ia, 1)
     708           0 :                   rp(:) = pos(:, patom, helium%beads) - pos(:, opatom, helium%beads)
     709           0 :                   partaction = partaction - helium_eval_expansion(helium, r, rp, work3)
     710             :                   ! and add corrected extra link
     711             :                   ! rp stays the same
     712           0 :                   r(:) = xtrapos(:) - pos(:, ia, 1)
     713           0 :                   partaction = partaction + helium_eval_expansion(helium, r, rp, work3)
     714          60 :                   ia = helium%permutation(ia)
     715             :                END DO
     716             :             ELSE ! bead index /= 1
     717             :                ! patom is the atom in front of the lone head bead
     718             :                !correct action contribution for first atom in moved cycle
     719        3312 :                r(:) = pos(:, helium%worm_atom_idx, wbead) - pos(:, iatom, wbead)
     720        3312 :                rp(:) = pos(:, helium%worm_atom_idx, wbead - 1) - pos(:, iatom, wbead - 1)
     721         828 :                partaction = partaction - helium_eval_expansion(helium, r, rp, work3)
     722             :                ! and add corrected extra link
     723             :                ! rp stays the same
     724        3312 :                r(:) = xtrapos(:) - pos(:, iatom, wbead)
     725         828 :                partaction = partaction + helium_eval_expansion(helium, r, rp, work3)
     726             :                ! go through all other atoms, not in the exchange cycle, and correct pair action
     727         828 :                ia = helium%permutation(iatom)
     728         828 :                DO WHILE (ia /= iatom)
     729             :                   ! subtract pair action for closed link
     730           0 :                   r(:) = pos(:, helium%worm_atom_idx, wbead) - pos(:, ia, wbead)
     731           0 :                   rp(:) = pos(:, helium%worm_atom_idx, wbead - 1) - pos(:, ia, wbead - 1)
     732           0 :                   partaction = partaction - helium_eval_expansion(helium, r, rp, work3)
     733             :                   ! and add corrected extra link
     734             :                   ! rp stays the same
     735           0 :                   r(:) = xtrapos(:) - pos(:, ia, wbead)
     736           0 :                   partaction = partaction + helium_eval_expansion(helium, r, rp, work3)
     737         828 :                   ia = helium%permutation(ia)
     738             :                END DO
     739             :             END IF
     740             :          END IF
     741             :       END IF
     742        1292 :       DEALLOCATE (work, work2, work3)
     743             : 
     744        1292 :    END FUNCTION worm_centroid_move_action
     745             : 
     746             : ! **************************************************************************************************
     747             : !> \brief Centroid interaction
     748             : !> \param pint_env ...
     749             : !> \param helium ...
     750             : !> \param pos ...
     751             : !> \param iatom ...
     752             : !> \param xtrapos ...
     753             : !> \param winc ...
     754             : !> \return ...
     755             : !> \author fuhl
     756             : ! **************************************************************************************************
     757        1262 :    REAL(KIND=dp) FUNCTION worm_centroid_move_inter_action(pint_env, helium, pos, iatom, xtrapos, winc) &
     758             :       RESULT(partaction)
     759             : 
     760             :       TYPE(pint_env_type), INTENT(IN)                    :: pint_env
     761             :       TYPE(helium_solvent_type), INTENT(IN)              :: helium
     762             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN), &
     763             :          POINTER                                         :: pos
     764             :       INTEGER, INTENT(IN)                                :: iatom
     765             :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: xtrapos
     766             :       LOGICAL, INTENT(IN)                                :: winc
     767             : 
     768             :       INTEGER                                            :: jatom, jbead
     769             :       REAL(KIND=dp)                                      :: energy
     770             : 
     771        1262 :       partaction = 0.0_dp
     772             :       ! spcial treatment if worm is in moved cycle
     773        1262 :       IF (winc) THEN
     774             :          ! first atom by hand
     775          38 :          jatom = iatom
     776             :          ! if it is worm atom it gets special treatment
     777          38 :          IF (jatom == helium%worm_atom_idx) THEN
     778             :             ! up to worm intersection
     779         260 :             DO jbead = 1, helium%worm_bead_idx - 1
     780             :                CALL helium_bead_solute_e_f(pint_env, helium, &
     781         222 :                                            jatom, jbead, pos(:, jatom, jbead), energy=energy)
     782         260 :                partaction = partaction + energy
     783             :             END DO
     784             :             ! head and tail each with 1/2 weight
     785          38 :             jbead = helium%worm_bead_idx
     786             :             ! tail
     787             :             CALL helium_bead_solute_e_f(pint_env, helium, &
     788          38 :                                         jatom, jbead, pos(:, jatom, jbead), energy=energy)
     789          38 :             partaction = partaction + 0.5_dp*energy
     790             :             ! head
     791             :             CALL helium_bead_solute_e_f(pint_env, helium, &
     792          38 :                                         jatom, jbead, xtrapos, energy=energy)
     793          38 :             partaction = partaction + 0.5_dp*energy
     794             :             ! rest of ring polymer
     795         386 :             DO jbead = helium%worm_bead_idx + 1, helium%beads
     796             :                CALL helium_bead_solute_e_f(pint_env, helium, &
     797         348 :                                            jatom, jbead, pos(:, jatom, jbead), energy=energy)
     798         386 :                partaction = partaction + energy
     799             :             END DO
     800             :          ELSE
     801           0 :             DO jbead = 1, helium%beads
     802             :                CALL helium_bead_solute_e_f(pint_env, helium, &
     803           0 :                                            jatom, jbead, pos(:, jatom, jbead), energy=energy)
     804           0 :                partaction = partaction + energy
     805             :             END DO
     806             :          END IF
     807          38 :          jatom = helium%permutation(iatom)
     808          38 :          DO WHILE (jatom /= iatom)
     809           0 :             IF (jatom == helium%worm_atom_idx) THEN
     810             :                ! up to worm intersection
     811           0 :                DO jbead = 1, helium%worm_bead_idx - 1
     812             :                   CALL helium_bead_solute_e_f(pint_env, helium, &
     813           0 :                                               jatom, jbead, pos(:, jatom, jbead), energy=energy)
     814           0 :                   partaction = partaction + energy
     815             :                END DO
     816             :                ! head and tail each with 1/2 weight
     817           0 :                jbead = helium%worm_bead_idx
     818             :                ! tail
     819             :                CALL helium_bead_solute_e_f(pint_env, helium, &
     820           0 :                                            jatom, jbead, pos(:, jatom, jbead), energy=energy)
     821           0 :                partaction = partaction + 0.5_dp*energy
     822             :                ! head
     823             :                CALL helium_bead_solute_e_f(pint_env, helium, &
     824           0 :                                            jatom, jbead, xtrapos, energy=energy)
     825           0 :                partaction = partaction + 0.5_dp*energy
     826             :                ! rest of ring polymer
     827           0 :                DO jbead = helium%worm_bead_idx + 1, helium%beads
     828             :                   CALL helium_bead_solute_e_f(pint_env, helium, &
     829           0 :                                               jatom, jbead, pos(:, jatom, jbead), energy=energy)
     830           0 :                   partaction = partaction + energy
     831             :                END DO
     832             :             ELSE
     833           0 :                DO jbead = 1, helium%beads
     834             :                   CALL helium_bead_solute_e_f(pint_env, helium, &
     835           0 :                                               jatom, jbead, pos(:, jatom, jbead), energy=energy)
     836           0 :                   partaction = partaction + energy
     837             :                END DO
     838             :             END IF
     839           0 :             jatom = helium%permutation(jatom)
     840             :          END DO
     841             :       ELSE ! worm not in moved cycle
     842             :          ! first atom by hand
     843        1224 :          jatom = iatom
     844             :          ! if it is worm atom it gets special treatment
     845       20808 :          DO jbead = 1, helium%beads
     846             :             CALL helium_bead_solute_e_f(pint_env, helium, &
     847       19584 :                                         jatom, jbead, pos(:, jatom, jbead), energy=energy)
     848       20808 :             partaction = partaction + energy
     849             :          END DO
     850        1224 :          jatom = helium%permutation(iatom)
     851        1224 :          DO WHILE (jatom /= iatom)
     852           0 :             DO jbead = 1, helium%beads
     853             :                CALL helium_bead_solute_e_f(pint_env, helium, &
     854           0 :                                            jatom, jbead, pos(:, jatom, jbead), energy=energy)
     855           0 :                partaction = partaction + energy
     856             :             END DO
     857        1224 :             jatom = helium%permutation(jatom)
     858             :          END DO
     859             :       END IF
     860             : 
     861        1262 :       partaction = partaction*helium%tau
     862             : 
     863        1262 :    END FUNCTION worm_centroid_move_inter_action
     864             : 
     865             : ! **************************************************************************************************
     866             : !> \brief General path construct based on staging moves
     867             : !> \param helium ...
     868             : !> \param ri ...
     869             : !> \param rj ...
     870             : !> \param l ...
     871             : !> \param new_path ...
     872             : !> \author fuhl
     873             : ! **************************************************************************************************
     874       19011 :    SUBROUTINE path_construct(helium, ri, rj, l, new_path)
     875             : 
     876             :       !constructs a path of length l between the positions ri and rj
     877             :       TYPE(helium_solvent_type), INTENT(INOUT)           :: helium
     878             :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: ri, rj
     879             :       INTEGER, INTENT(IN)                                :: l
     880             :       REAL(KIND=dp), DIMENSION(3, l), INTENT(OUT)        :: new_path
     881             : 
     882             :       INTEGER                                            :: idim, istage
     883             :       REAL(KIND=dp)                                      :: imass, invstagemass, rk, weight
     884             :       REAL(KIND=dp), DIMENSION(3)                        :: re, rs
     885             : 
     886       19011 :       imass = 1.0_dp/helium%he_mass_au
     887             :       ! dealing with periodicity
     888       19011 :       rs(:) = ri(:)
     889       76044 :       re(:) = rj(:) - rs(:)
     890       19011 :       CALL helium_pbc(helium, re)
     891       76044 :       re(:) = re(:) + rs(:)
     892             : 
     893             :       ! first construction by hand
     894             :       ! reusable weight factor 1/(l+1)
     895       19011 :       rk = REAL(l, dp)
     896       19011 :       weight = 1.0_dp/(rk + 1.0_dp)
     897             :       ! staging mass needed for modified variance
     898       19011 :       invstagemass = rk*weight*imass
     899             :       ! proposing new positions
     900       76044 :       DO idim = 1, 3
     901       76044 :          new_path(idim, 1) = helium%rng_stream_gaussian%next(variance=helium%tau*invstagemass)
     902             :       END DO
     903       76044 :       new_path(:, 1) = new_path(:, 1) + weight*(re(:) + rk*rs(:))
     904             : 
     905       64566 :       DO istage = 2, l
     906             :          ! reusable weight factor 1/(k+1)
     907       45555 :          rk = REAL(l - istage + 1, dp)
     908       45555 :          weight = 1.0_dp/(rk + 1.0_dp)
     909             :          ! staging mass needed for modified variance
     910       45555 :          invstagemass = rk*weight*imass
     911             :          ! proposing new positions
     912      182220 :          DO idim = 1, 3
     913      182220 :             new_path(idim, istage) = helium%rng_stream_gaussian%next(variance=helium%tau*invstagemass)
     914             :          END DO
     915      201231 :          new_path(:, istage) = new_path(:, istage) + weight*(rk*new_path(:, istage - 1) + re(:))
     916             :       END DO
     917             : 
     918       19011 :    END SUBROUTINE path_construct
     919             : 
     920             : ! **************************************************************************************************
     921             : !> \brief Staging move
     922             : !> \param pint_env ...
     923             : !> \param helium ...
     924             : !> \param startatom ...
     925             : !> \param startbead ...
     926             : !> \param l ...
     927             : !> \param ac ...
     928             : !> \author fuhl
     929             : ! **************************************************************************************************
     930        6508 :    SUBROUTINE worm_staging_move(pint_env, helium, startatom, startbead, l, ac)
     931             : 
     932             :       TYPE(pint_env_type), INTENT(IN)                    :: pint_env
     933             :       TYPE(helium_solvent_type), INTENT(INOUT)           :: helium
     934             :       INTEGER, INTENT(IN)                                :: startatom, startbead, l
     935             :       INTEGER, INTENT(OUT)                               :: ac
     936             : 
     937             :       INTEGER                                            :: endatom, endbead, ia, ib, ibead, jbead
     938             :       LOGICAL                                            :: should_reject, worm_overlap
     939             :       REAL(KIND=dp)                                      :: rtmp, rtmpo, sdiff, snew, sold
     940             :       REAL(KIND=dp), DIMENSION(3)                        :: dr, dro, new_com, old_com
     941        6508 :       REAL(KIND=dp), DIMENSION(3, l)                     :: newsection
     942             : 
     943        6508 :       ac = 0
     944        6508 :       endbead = startbead + l + 1
     945             :       ! Check if the imaginary time section belongs to two atoms
     946        6508 :       IF (endbead > helium%beads) THEN
     947        1833 :          endatom = helium%permutation(startatom)
     948        1833 :          endbead = endbead - helium%beads
     949             :       ELSE
     950        4675 :          endatom = startatom
     951             :       END IF
     952             : 
     953             :       ! check if the imaginary time section overlaps with the worm opening
     954        6508 :       IF (helium%worm_is_closed) THEN
     955             :          worm_overlap = .FALSE.
     956             :       ELSE
     957             :          ! if it does give it special treatment during action evaluation
     958             :          worm_overlap = ((startbead < endbead) .AND. &
     959             :                          (helium%worm_bead_idx > startbead) .AND. &
     960             :                          (helium%worm_bead_idx <= endbead)) &
     961             :                         .OR. &
     962             :                         ((startbead > endbead) .AND. &
     963             :                          ((helium%worm_bead_idx > startbead) .OR. &
     964        1047 :                           (helium%worm_bead_idx <= endbead)))
     965             :          IF (worm_overlap) THEN
     966             :             ! if in addition the worm end is IN the reconstructed section reject immediately
     967         317 :             IF (((helium%worm_atom_idx == startatom) .AND. (helium%worm_bead_idx >= startbead)) .OR. &
     968             :                 ((helium%worm_atom_idx == endatom) .AND. (helium%worm_bead_idx <= endbead))) THEN
     969             :                ac = 0
     970             :                RETURN
     971             :             END IF
     972             :          END IF
     973             :       END IF
     974             :       ! action before the move
     975             :       IF (worm_overlap) THEN
     976             :          sold = worm_path_action_worm_corrected(helium, helium%pos, &
     977             :                                                 startatom, startbead, endatom, endbead, &
     978         303 :                                                 helium%worm_xtra_bead, helium%worm_atom_idx, helium%worm_bead_idx)
     979             :       ELSE
     980             :          sold = worm_path_action(helium, helium%pos, &
     981        6191 :                                  startatom, startbead, endatom, endbead)
     982             :       END IF
     983             : 
     984        6494 :       IF (helium%solute_present) THEN
     985             :          ! no special head treatment needed, because a swap can't go over
     986             :          ! the worm gap and due to primitive coupling no cross bead terms are considered
     987             :          sold = sold + worm_path_inter_action(pint_env, helium, helium%pos, &
     988        6291 :                                               startatom, startbead, endatom, endbead)
     989             :       END IF
     990             : 
     991             :       ! construct a new path connecting the start and endbead
     992             :       CALL path_construct(helium, &
     993             :                           helium%pos(:, startatom, startbead), &
     994             :                           helium%pos(:, endatom, endbead), l, &
     995        6494 :                           newsection)
     996             : 
     997             :       ! write new path segment to work array
     998             :       ! first the part that is guaranteed to fit on the coorinates of startatom
     999        6494 :       jbead = 1
    1000       25813 :       DO ibead = startbead + 1, MIN(helium%beads, startbead + l)
    1001       77276 :          helium%work(:, startatom, ibead) = newsection(:, jbead)
    1002       25813 :          jbead = jbead + 1
    1003             :       END DO
    1004             :       ! transfer the rest of the beads to coordinates of endatom if necessary
    1005        6494 :       IF (helium%beads < startbead + l) THEN
    1006        4918 :          DO ibead = 1, endbead - 1
    1007       13956 :             helium%work(:, endatom, ibead) = newsection(:, jbead)
    1008        4918 :             jbead = jbead + 1
    1009             :          END DO
    1010             :       END IF
    1011             : 
    1012             :       ! action after the move
    1013        6494 :       IF (worm_overlap) THEN
    1014             :          snew = worm_path_action_worm_corrected(helium, helium%work, &
    1015             :                                                 startatom, startbead, endatom, endbead, &
    1016         303 :                                                 helium%worm_xtra_bead_work, helium%worm_atom_idx_work, helium%worm_bead_idx_work)
    1017             :       ELSE
    1018             :          snew = worm_path_action(helium, helium%work, &
    1019        6191 :                                  startatom, startbead, endatom, endbead)
    1020             :       END IF
    1021             : 
    1022        6494 :       IF (helium%solute_present) THEN
    1023             :          ! no special head treatment needed, because a swap can't go over
    1024             :          ! the worm gap and due to primitive coupling no cross bead terms are considered
    1025             :          snew = snew + worm_path_inter_action(pint_env, helium, helium%work, &
    1026        6291 :                                               startatom, startbead, endatom, endbead)
    1027             :       END IF
    1028             : 
    1029             :       ! Metropolis:
    1030        6494 :       sdiff = sold - snew
    1031        6494 :       IF (sdiff < 0) THEN
    1032        3303 :          should_reject = .FALSE.
    1033        3303 :          IF (sdiff < -100.0_dp) THEN ! To protect from exponential underflow
    1034             :             should_reject = .TRUE.
    1035             :          ELSE
    1036        3302 :             rtmp = helium%rng_stream_uniform%next()
    1037        3302 :             IF (EXP(sdiff) < rtmp) THEN
    1038             :                should_reject = .TRUE.
    1039             :             END IF
    1040             :          END IF
    1041             :          IF (should_reject) THEN
    1042             :             ! rejected !
    1043             :             ! write back only changed atoms
    1044          98 :             jbead = 1
    1045         446 :             DO ibead = startbead + 1, MIN(helium%beads, startbead + l)
    1046        1392 :                helium%work(:, startatom, ibead) = helium%pos(:, startatom, ibead)
    1047         446 :                jbead = jbead + 1
    1048             :             END DO
    1049             :             ! transfer the rest of the beads to coordinates of endatom if necessary
    1050          98 :             IF (helium%beads < startbead + l) THEN
    1051          54 :                DO ibead = 1, endbead - 1
    1052         148 :                   helium%work(:, endatom, ibead) = helium%pos(:, endatom, ibead)
    1053          54 :                   jbead = jbead + 1
    1054             :                END DO
    1055             :             END IF
    1056          98 :             ac = 0
    1057          98 :             RETURN
    1058             :          END IF
    1059             :       END IF
    1060             : 
    1061             :       ! for now accepted
    1062             :       ! rejection of the whole move if any centroid is farther away
    1063             :       ! from the current center of gravity than HELIUM%DROPLET_RADIUS [lwalewski]
    1064             :       ! AND ist not moving towards the center
    1065        6396 :       IF (.NOT. helium%periodic) THEN
    1066        6231 :          IF (helium%solute_present) THEN
    1067       24924 :             new_com(:) = helium%center(:)
    1068        6231 :             old_com(:) = new_com(:)
    1069             :          ELSE
    1070           0 :             new_com(:) = 0.0_dp
    1071           0 :             DO ia = 1, helium%atoms
    1072           0 :                DO ib = 1, helium%beads
    1073           0 :                   new_com(:) = new_com(:) + helium%work(:, ia, ib)
    1074             :                END DO
    1075             :             END DO
    1076           0 :             new_com(:) = new_com(:)/(REAL(helium%atoms*helium%beads, dp))
    1077             :             ! also compute the old center of mass (optimization potential)
    1078           0 :             old_com(:) = 0.0_dp
    1079           0 :             DO ia = 1, helium%atoms
    1080           0 :                DO ib = 1, helium%beads
    1081           0 :                   old_com(:) = old_com(:) + helium%pos(:, ia, ib)
    1082             :                END DO
    1083             :             END DO
    1084           0 :             old_com(:) = old_com(:)/(REAL(helium%atoms*helium%beads, dp))
    1085             :          END IF
    1086        6231 :          should_reject = .FALSE.
    1087      182841 :          atom: DO ia = 1, helium%atoms
    1088      176640 :             dr(:) = 0.0_dp
    1089     3002880 :             DO ib = 1, helium%beads
    1090    11481600 :                dr(:) = dr(:) + helium%work(:, ia, ib) - new_com(:)
    1091             :             END DO
    1092      706560 :             dr(:) = dr(:)/REAL(helium%beads, dp)
    1093      706560 :             rtmp = DOT_PRODUCT(dr, dr)
    1094      182841 :             IF (rtmp >= helium%droplet_radius**2) THEN
    1095          30 :                dro(:) = 0.0_dp
    1096         510 :                DO ib = 1, helium%beads
    1097        1950 :                   dro(:) = dro(:) + helium%pos(:, ia, ib) - old_com(:)
    1098             :                END DO
    1099         120 :                dro(:) = dro(:)/REAL(helium%beads, dp)
    1100         120 :                rtmpo = DOT_PRODUCT(dro, dro)
    1101             :                ! only reject if it moves away from COM outside the droplet radius
    1102          30 :                IF (rtmpo < rtmp) THEN
    1103             :                   ! found - this one does not fit within R from the center
    1104             :                   should_reject = .TRUE.
    1105             :                   EXIT atom
    1106             :                END IF
    1107             :             END IF
    1108             :          END DO atom
    1109        6231 :          IF (should_reject) THEN
    1110             :             ! restore original coordinates
    1111             :             ! write back only changed atoms
    1112          30 :             jbead = 1
    1113         107 :             DO ibead = startbead + 1, MIN(helium%beads, startbead + l)
    1114         308 :                helium%work(:, startatom, ibead) = helium%pos(:, startatom, ibead)
    1115         107 :                jbead = jbead + 1
    1116             :             END DO
    1117             :             ! transfer the rest of the beads to coordinates of endatom if necessary
    1118          30 :             IF (helium%beads < startbead + l) THEN
    1119          42 :                DO ibead = 1, endbead - 1
    1120         124 :                   helium%work(:, endatom, ibead) = helium%pos(:, endatom, ibead)
    1121          42 :                   jbead = jbead + 1
    1122             :                END DO
    1123             :             END IF
    1124          30 :             ac = 0
    1125          30 :             RETURN
    1126             :          END IF
    1127             :       END IF
    1128             : 
    1129             :       ! finally accepted
    1130        6366 :       ac = 1
    1131             :       ! write changed coordinates to position array
    1132        6366 :       jbead = 1
    1133       25260 :       DO ibead = startbead + 1, MIN(helium%beads, startbead + l)
    1134       75576 :          helium%pos(:, startatom, ibead) = helium%work(:, startatom, ibead)
    1135       25260 :          jbead = jbead + 1
    1136             :       END DO
    1137             :       ! transfer the rest of the beads to coordinates of endatom if necessary
    1138        6366 :       IF (helium%beads < startbead + l) THEN
    1139        4822 :          DO ibead = 1, endbead - 1
    1140       13684 :             helium%pos(:, endatom, ibead) = helium%work(:, endatom, ibead)
    1141        4822 :             jbead = jbead + 1
    1142             :          END DO
    1143             :       END IF
    1144             : 
    1145             :    END SUBROUTINE worm_staging_move
    1146             : 
    1147             : ! **************************************************************************************************
    1148             : !> \brief Open move to off-diagonal elements of the density matrix, allows to sample permutations
    1149             : !> \param pint_env ...
    1150             : !> \param helium ...
    1151             : !> \param endatom ...
    1152             : !> \param endbead ...
    1153             : !> \param l ...
    1154             : !> \param ac ...
    1155             : !> \author fuhl
    1156             : ! **************************************************************************************************
    1157         792 :    SUBROUTINE worm_open_move(pint_env, helium, endatom, endbead, l, ac)
    1158             : 
    1159             :       TYPE(pint_env_type), INTENT(IN)                    :: pint_env
    1160             :       TYPE(helium_solvent_type), INTENT(INOUT)           :: helium
    1161             :       INTEGER, INTENT(IN)                                :: endatom, endbead, l
    1162             :       INTEGER, INTENT(OUT)                               :: ac
    1163             : 
    1164             :       INTEGER                                            :: ia, ib, idim, kbead, startatom, startbead
    1165             :       LOGICAL                                            :: should_reject
    1166             :       REAL(KIND=dp)                                      :: distsq, mass, rtmp, rtmpo, sdiff, snew, &
    1167             :                                                             sold, xr
    1168             :       REAL(KIND=dp), DIMENSION(3)                        :: distvec, dr, dro, new_com, old_com
    1169             : 
    1170         792 :       mass = helium%he_mass_au
    1171             : 
    1172             :       ! get index of the atom and bead, where the resampling of the head begins
    1173         792 :       IF (l < endbead) THEN
    1174             :          ! startbead belongs to the same atom
    1175         619 :          startatom = endatom
    1176         619 :          startbead = endbead - l
    1177             :       ELSE
    1178             :          ! startbead belongs to a different atom
    1179             :          ! find previous atom (assuming l < nbeads)
    1180         173 :          startatom = helium%iperm(endatom)
    1181         173 :          startbead = endbead + helium%beads - l
    1182             :       END IF
    1183             :       sold = worm_path_action(helium, helium%pos, &
    1184         792 :                               startatom, startbead, endatom, endbead)
    1185             : 
    1186         792 :       IF (helium%solute_present) THEN
    1187             :          ! yes this is correct, as the bead, that splits into tail and head only changes half
    1188             :          ! therefore only half of its action needs to be considred
    1189             :          ! and is cheated in here by passing it as head bead
    1190             :          sold = sold + worm_path_inter_action_head(pint_env, helium, helium%pos, &
    1191             :                                                    startatom, startbead, &
    1192         767 :                                                    helium%pos(:, endatom, endbead), endatom, endbead)
    1193             :       END IF
    1194             : 
    1195         792 :       helium%worm_is_closed = .FALSE.
    1196         792 :       helium%worm_atom_idx_work = endatom
    1197         792 :       helium%worm_bead_idx_work = endbead
    1198             : 
    1199             :       ! alternative grow with consecutive gaussians
    1200         792 :       IF (startbead < endbead) THEN
    1201             :          ! everything belongs to the same atom
    1202             :          ! gro head from startbead
    1203        2123 :          DO kbead = startbead + 1, endbead - 1
    1204        6635 :             DO idim = 1, 3
    1205        4512 :                xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    1206        6016 :                helium%work(idim, startatom, kbead) = helium%work(idim, startatom, kbead - 1) + xr
    1207             :             END DO
    1208             :          END DO
    1209             :          ! last grow head bead
    1210        2476 :          DO idim = 1, 3
    1211        1857 :             xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    1212        2476 :             helium%worm_xtra_bead_work(idim) = helium%work(idim, startatom, endbead - 1) + xr
    1213             :          END DO
    1214         173 :       ELSE IF (endbead /= 1) THEN
    1215             :          ! is distributed among two atoms
    1216             :          ! grow from startbead
    1217         269 :          DO kbead = startbead + 1, helium%beads
    1218         692 :             DO idim = 1, 3
    1219         423 :                xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    1220         564 :                helium%work(idim, startatom, kbead) = helium%work(idim, startatom, kbead - 1) + xr
    1221             :             END DO
    1222             :          END DO
    1223             :          ! bead one of endatom relative to last on startatom
    1224         512 :          DO idim = 1, 3
    1225         384 :             xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    1226         512 :             helium%work(idim, endatom, 1) = helium%work(idim, startatom, helium%beads) + xr
    1227             :          END DO
    1228             :          ! everything on endatom
    1229         243 :          DO kbead = 2, endbead - 1
    1230         588 :             DO idim = 1, 3
    1231         345 :                xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    1232         460 :                helium%work(idim, endatom, kbead) = helium%work(idim, endatom, kbead - 1) + xr
    1233             :             END DO
    1234             :          END DO
    1235         512 :          DO idim = 1, 3
    1236         384 :             xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    1237         512 :             helium%worm_xtra_bead_work(idim) = helium%work(idim, endatom, endbead - 1) + xr
    1238             :          END DO
    1239             :       ELSE ! imagtimewrap and headbead = 1
    1240             :          ! is distributed among two atoms
    1241             :          ! grow from startbead
    1242         165 :          DO kbead = startbead + 1, helium%beads
    1243         525 :             DO idim = 1, 3
    1244         360 :                xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    1245         480 :                helium%work(idim, startatom, kbead) = helium%work(idim, startatom, kbead - 1) + xr
    1246             :             END DO
    1247             :          END DO
    1248             :          ! bead one of endatom relative to last on startatom
    1249         180 :          DO idim = 1, 3
    1250         135 :             xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    1251         180 :             helium%worm_xtra_bead_work(idim) = helium%work(idim, startatom, helium%beads) + xr
    1252             :          END DO
    1253             :       END IF
    1254             : 
    1255             :       snew = worm_path_action_worm_corrected(helium, helium%work, &
    1256             :                                              startatom, startbead, endatom, endbead, &
    1257         792 :                                              helium%worm_xtra_bead_work, helium%worm_atom_idx_work, helium%worm_bead_idx_work)
    1258             : 
    1259         792 :       IF (helium%solute_present) THEN
    1260             :          snew = snew + worm_path_inter_action_head(pint_env, helium, helium%work, &
    1261             :                                                    startatom, startbead, &
    1262         767 :                                                    helium%worm_xtra_bead_work, helium%worm_atom_idx_work, helium%worm_bead_idx_work)
    1263             :       END IF
    1264             : 
    1265             :       ! Metropolis:
    1266             :       ! first compute ln of free density matrix
    1267        3168 :       distvec(:) = helium%pos(:, startatom, startbead) - helium%pos(:, endatom, endbead)
    1268         792 :       CALL helium_pbc(helium, distvec)
    1269        3168 :       distsq = DOT_PRODUCT(distvec, distvec)
    1270             :       ! action difference
    1271         792 :       sdiff = sold - snew
    1272             :       ! modify action difference due to extra bead
    1273         792 :       sdiff = sdiff + distsq/(2.0_dp*helium%hb2m*REAL(l, dp)*helium%tau)
    1274         792 :       sdiff = sdiff + 1.5_dp*LOG(REAL(l, dp)*helium%tau)
    1275         792 :       sdiff = sdiff + helium%worm_ln_openclose_scale
    1276         792 :       IF (sdiff < 0) THEN
    1277         555 :          should_reject = .FALSE.
    1278         555 :          IF (sdiff < -100.0_dp) THEN ! To protect from exponential underflow
    1279             :             should_reject = .TRUE.
    1280             :          ELSE
    1281         555 :             rtmp = helium%rng_stream_uniform%next()
    1282         555 :             IF (EXP(sdiff) < rtmp) THEN
    1283             :                should_reject = .TRUE.
    1284             :             END IF
    1285             :          END IF
    1286             :          IF (should_reject) THEN
    1287             :             ! rejected !
    1288             :             ! write back only changed atoms
    1289             :             ! transfer the new coordinates to work array
    1290         280 :             IF (startbead < endbead) THEN
    1291             :                ! everything belongs to the same atom
    1292         657 :                DO kbead = startbead + 1, endbead - 1
    1293        1953 :                   helium%work(:, endatom, kbead) = helium%pos(:, endatom, kbead)
    1294             :                END DO
    1295             :             ELSE
    1296             :                ! is distributed among two atoms
    1297             :                ! transfer to atom not containing the head bead
    1298         125 :                DO kbead = startbead + 1, helium%beads
    1299         335 :                   helium%work(:, startatom, kbead) = helium%pos(:, startatom, kbead)
    1300             :                END DO
    1301             :                ! transfer to atom containing the head bead
    1302         123 :                DO kbead = 1, endbead - 1
    1303         327 :                   helium%work(:, endatom, kbead) = helium%pos(:, endatom, kbead)
    1304             :                END DO
    1305             :             END IF
    1306         280 :             helium%worm_is_closed = .TRUE.
    1307         280 :             ac = 0
    1308         283 :             RETURN
    1309             :          END IF
    1310             :       END IF
    1311             : 
    1312             :       ! for now accepted
    1313             :       ! rejection of the whole move if any centroid is farther away
    1314             :       ! from the current center of gravity than HELIUM%DROPLET_RADIUS [lwalewski]
    1315             :       ! AND ist not moving towards the center
    1316         512 :       IF (.NOT. helium%periodic) THEN
    1317         498 :          IF (helium%solute_present) THEN
    1318        1992 :             new_com(:) = helium%center(:)
    1319         498 :             old_com(:) = new_com(:)
    1320             :          ELSE
    1321           0 :             new_com(:) = 0.0_dp
    1322           0 :             DO ia = 1, helium%atoms
    1323           0 :                DO ib = 1, helium%beads
    1324           0 :                   new_com(:) = new_com(:) + helium%work(:, ia, ib)
    1325             :                END DO
    1326             :             END DO
    1327           0 :             new_com(:) = new_com(:)/(REAL(helium%atoms*helium%beads, dp))
    1328             :             ! also compute the old center of mass (optimization potential)
    1329           0 :             old_com(:) = 0.0_dp
    1330           0 :             DO ia = 1, helium%atoms
    1331           0 :                DO ib = 1, helium%beads
    1332           0 :                   old_com(:) = old_com(:) + helium%pos(:, ia, ib)
    1333             :                END DO
    1334             :             END DO
    1335           0 :             old_com(:) = old_com(:)/(REAL(helium%atoms*helium%beads, dp))
    1336             :          END IF
    1337         498 :          should_reject = .FALSE.
    1338       14772 :          atom: DO ia = 1, helium%atoms
    1339       14277 :             dr(:) = 0.0_dp
    1340      242709 :             DO ib = 1, helium%beads
    1341      928005 :                dr(:) = dr(:) + helium%work(:, ia, ib) - new_com(:)
    1342             :             END DO
    1343       57108 :             dr(:) = dr(:)/REAL(helium%beads, dp)
    1344       57108 :             rtmp = DOT_PRODUCT(dr, dr)
    1345       14772 :             IF (rtmp >= helium%droplet_radius**2) THEN
    1346           3 :                dro(:) = 0.0_dp
    1347          51 :                DO ib = 1, helium%beads
    1348         195 :                   dro(:) = dro(:) + helium%pos(:, ia, ib) - old_com(:)
    1349             :                END DO
    1350          12 :                dro(:) = dro(:)/REAL(helium%beads, dp)
    1351          12 :                rtmpo = DOT_PRODUCT(dro, dro)
    1352             :                ! only reject if it moves away from COM outside the droplet radius
    1353           3 :                IF (rtmpo < rtmp) THEN
    1354             :                   ! found - this one does not fit within R from the center
    1355             :                   should_reject = .TRUE.
    1356             :                   EXIT atom
    1357             :                END IF
    1358             :             END IF
    1359             :          END DO atom
    1360         498 :          IF (should_reject) THEN
    1361             :             ! restore original coordinates
    1362             :             ! write back only changed atoms
    1363           3 :             IF (startbead < endbead) THEN
    1364             :                ! everything belongs to the same atom
    1365           0 :                DO kbead = startbead + 1, endbead - 1
    1366           0 :                   helium%work(:, endatom, kbead) = helium%pos(:, endatom, kbead)
    1367             :                END DO
    1368             :             ELSE
    1369             :                ! is distributed among two atoms
    1370             :                ! transfer to atom not containing the head bead
    1371           6 :                DO kbead = startbead + 1, helium%beads
    1372          15 :                   helium%work(:, startatom, kbead) = helium%pos(:, startatom, kbead)
    1373             :                END DO
    1374             :                ! transfer to atom containing the head bead
    1375           9 :                DO kbead = 1, endbead - 1
    1376          27 :                   helium%work(:, endatom, kbead) = helium%pos(:, endatom, kbead)
    1377             :                END DO
    1378             :             END IF
    1379           3 :             helium%worm_is_closed = .TRUE.
    1380             :             !helium%worm_atom_idx_work = helium%worm_atom_idx
    1381             :             !helium%worm_bead_idx_work = helium%worm_bead_idx
    1382           3 :             ac = 0
    1383           3 :             RETURN
    1384             :          END IF
    1385             :       END IF
    1386             : 
    1387             :       ! finally accepted
    1388         509 :       ac = 1
    1389             :       ! write changed coordinates to position array
    1390         509 :       IF (startbead < endbead) THEN
    1391             :          ! everything belongs to the same atom
    1392        1466 :          DO kbead = startbead + 1, endbead - 1
    1393        4682 :             helium%pos(:, endatom, kbead) = helium%work(:, endatom, kbead)
    1394             :          END DO
    1395             :       ELSE
    1396             :          ! is distributed among two atoms
    1397             :          ! transfer to atom not containing the head bead
    1398         303 :          DO kbead = startbead + 1, helium%beads
    1399         867 :             helium%pos(:, startatom, kbead) = helium%work(:, startatom, kbead)
    1400             :          END DO
    1401             :          ! transfer to atom containing the head bead
    1402         284 :          DO kbead = 1, endbead - 1
    1403         791 :             helium%pos(:, endatom, kbead) = helium%work(:, endatom, kbead)
    1404             :          END DO
    1405             :       END IF
    1406        2036 :       helium%worm_xtra_bead(:) = helium%worm_xtra_bead_work(:)
    1407         509 :       helium%worm_atom_idx = helium%worm_atom_idx_work
    1408         509 :       helium%worm_bead_idx = helium%worm_bead_idx_work
    1409             : 
    1410             :    END SUBROUTINE worm_open_move
    1411             : 
    1412             : ! **************************************************************************************************
    1413             : !> \brief Close move back to diagonal elements of density matrix, permutation fixed in closed state
    1414             : !> \param pint_env ...
    1415             : !> \param helium ...
    1416             : !> \param l ...
    1417             : !> \param ac ...
    1418             : !> \author fuhl
    1419             : ! **************************************************************************************************
    1420        2069 :    SUBROUTINE worm_close_move(pint_env, helium, l, ac)
    1421             : 
    1422             :       TYPE(pint_env_type), INTENT(IN)                    :: pint_env
    1423             :       TYPE(helium_solvent_type), INTENT(INOUT)           :: helium
    1424             :       INTEGER, INTENT(IN)                                :: l
    1425             :       INTEGER, INTENT(OUT)                               :: ac
    1426             : 
    1427             :       INTEGER                                            :: endatom, endbead, ia, ib, jbead, kbead, &
    1428             :                                                             startatom, startbead
    1429             :       LOGICAL                                            :: should_reject
    1430             :       REAL(KIND=dp)                                      :: distsq, mass, rtmp, rtmpo, sdiff, snew, &
    1431             :                                                             sold
    1432             :       REAL(KIND=dp), DIMENSION(3)                        :: distvec, dr, dro, new_com, old_com
    1433        2069 :       REAL(KIND=dp), DIMENSION(3, l-1)                   :: newsection
    1434             : 
    1435        2069 :       mass = helium%he_mass_au
    1436             : 
    1437        2069 :       endatom = helium%worm_atom_idx
    1438        2069 :       endbead = helium%worm_bead_idx
    1439             :       ! get index of the atom and bead, where the resampling of the head begins
    1440        2069 :       IF (l < endbead) THEN
    1441             :          ! startbead belongs to the same atom
    1442        1545 :          startatom = endatom
    1443        1545 :          startbead = endbead - l
    1444             :       ELSE
    1445             :          ! startbead belongs to a different atom
    1446             :          ! find previous atom (assuming l < nbeads)
    1447         524 :          startatom = helium%iperm(endatom)
    1448         524 :          startbead = endbead + helium%beads - l
    1449             :       END IF
    1450             :       sold = worm_path_action_worm_corrected(helium, helium%pos, &
    1451             :                                              startatom, startbead, endatom, endbead, &
    1452        2069 :                                              helium%worm_xtra_bead, helium%worm_atom_idx, helium%worm_bead_idx)
    1453             : 
    1454        2069 :       IF (helium%solute_present) THEN
    1455             :          sold = sold + worm_path_inter_action_head(pint_env, helium, helium%pos, &
    1456             :                                                    startatom, startbead, &
    1457        2039 :                                                    helium%worm_xtra_bead, helium%worm_atom_idx, helium%worm_bead_idx)
    1458             :       END IF
    1459             : 
    1460             :       ! close between head and tail
    1461             :       ! only l-1 beads need to be reconstructed
    1462             :       CALL path_construct(helium, &
    1463             :                           helium%pos(:, startatom, startbead), &
    1464             :                           helium%pos(:, endatom, endbead), l - 1, &
    1465        2069 :                           newsection)
    1466             : 
    1467             :       ! transfer the new coordinates to work array
    1468        2069 :       jbead = 1
    1469        2069 :       IF (startbead < endbead) THEN
    1470             :          ! everything belongs to the same atom
    1471        5304 :          DO kbead = startbead + 1, endbead - 1
    1472       15036 :             helium%work(:, endatom, kbead) = newsection(:, jbead)
    1473        5304 :             jbead = jbead + 1
    1474             :          END DO
    1475             :       ELSE
    1476             :          ! is distributed among two atoms
    1477             :          ! transfer to atom not containing the head bead
    1478        1225 :          DO kbead = startbead + 1, helium%beads
    1479        2804 :             helium%work(:, startatom, kbead) = newsection(:, jbead)
    1480        1225 :             jbead = jbead + 1
    1481             :          END DO
    1482             :          ! transfer to atom containing the head bead
    1483        1276 :          DO kbead = 1, endbead - 1
    1484        3008 :             helium%work(:, endatom, kbead) = newsection(:, jbead)
    1485        1276 :             jbead = jbead + 1
    1486             :          END DO
    1487             :       END IF
    1488             : 
    1489        2069 :       helium%worm_is_closed = .TRUE.
    1490             : 
    1491             :       snew = worm_path_action(helium, helium%work, &
    1492        2069 :                               startatom, startbead, endatom, endbead)
    1493             : 
    1494        2069 :       IF (helium%solute_present) THEN
    1495             :          ! yes this is correct, as the bead, that was split into tail and head only changes half
    1496             :          ! therefore only half of its action needs to be considred
    1497             :          ! and is cheated in here by passing it as head bead
    1498             :          snew = snew + worm_path_inter_action_head(pint_env, helium, helium%work, &
    1499             :                                                    startatom, startbead, &
    1500        2039 :                                                    helium%work(:, endatom, endbead), endatom, endbead)
    1501             :       END IF
    1502             : 
    1503             :       ! Metropolis:
    1504             :       ! first compute ln of free density matrix
    1505        8276 :       distvec(:) = helium%pos(:, startatom, startbead) - helium%pos(:, endatom, endbead)
    1506        2069 :       CALL helium_pbc(helium, distvec)
    1507        8276 :       distsq = DOT_PRODUCT(distvec, distvec)
    1508             :       ! action difference
    1509        2069 :       sdiff = sold - snew
    1510             :       ! modify action difference due to extra bead
    1511        2069 :       sdiff = sdiff - distsq/(2.0_dp*helium%hb2m*REAL(l, dp)*helium%tau)
    1512        2069 :       sdiff = sdiff - 1.5_dp*LOG(REAL(l, dp)*helium%tau)
    1513        2069 :       sdiff = sdiff - helium%worm_ln_openclose_scale
    1514        2069 :       IF (sdiff < 0) THEN
    1515        1834 :          should_reject = .FALSE.
    1516        1834 :          IF (sdiff < -100.0_dp) THEN ! To protect from exponential underflow
    1517             :             should_reject = .TRUE.
    1518             :          ELSE
    1519        1798 :             rtmp = helium%rng_stream_uniform%next()
    1520        1798 :             IF (EXP(sdiff) < rtmp) THEN
    1521             :                should_reject = .TRUE.
    1522             :             END IF
    1523             :          END IF
    1524             :          IF (should_reject) THEN
    1525             :             ! rejected !
    1526             :             ! write back only changed atoms
    1527             :             ! transfer the new coordinates to work array
    1528        1559 :             IF (startbead < endbead) THEN
    1529             :                ! everything belongs to the same atom
    1530        3881 :                DO kbead = startbead + 1, endbead - 1
    1531       12056 :                   helium%work(:, endatom, kbead) = helium%pos(:, endatom, kbead)
    1532             :                END DO
    1533             :             ELSE
    1534             :                ! is distributed among two atoms
    1535             :                ! transfer to atom not containing the head bead
    1536         916 :                DO kbead = startbead + 1, helium%beads
    1537        2455 :                   helium%work(:, startatom, kbead) = helium%pos(:, startatom, kbead)
    1538             :                END DO
    1539             :                ! transfer to atom containing the head bead
    1540         985 :                DO kbead = 1, endbead - 1
    1541        2731 :                   helium%work(:, endatom, kbead) = helium%pos(:, endatom, kbead)
    1542             :                END DO
    1543             :             END IF
    1544        1559 :             helium%worm_is_closed = .FALSE.
    1545        1559 :             ac = 0
    1546        1559 :             RETURN
    1547             :          END IF
    1548             :       END IF
    1549             : 
    1550             :       ! for now accepted
    1551             :       ! rejection of the whole move if any centroid is farther away
    1552             :       ! from the current center of gravity than HELIUM%DROPLET_RADIUS [lwalewski]
    1553             :       ! AND ist not moving towards the center
    1554         510 :       IF (.NOT. helium%periodic) THEN
    1555         496 :          IF (helium%solute_present) THEN
    1556        1984 :             new_com(:) = helium%center(:)
    1557         496 :             old_com(:) = new_com(:)
    1558             :          ELSE
    1559           0 :             new_com(:) = 0.0_dp
    1560           0 :             DO ia = 1, helium%atoms
    1561           0 :                DO ib = 1, helium%beads
    1562           0 :                   new_com(:) = new_com(:) + helium%work(:, ia, ib)
    1563             :                END DO
    1564             :             END DO
    1565           0 :             new_com(:) = new_com(:)/(REAL(helium%atoms*helium%beads, dp))
    1566             :             ! also compute the old center of mass (optimization potential)
    1567           0 :             old_com(:) = 0.0_dp
    1568           0 :             DO ia = 1, helium%atoms
    1569           0 :                DO ib = 1, helium%beads
    1570           0 :                   old_com(:) = old_com(:) + helium%pos(:, ia, ib)
    1571             :                END DO
    1572             :             END DO
    1573           0 :             old_com(:) = old_com(:)/(REAL(helium%atoms*helium%beads, dp))
    1574             :          END IF
    1575         496 :          should_reject = .FALSE.
    1576       14746 :          atom: DO ia = 1, helium%atoms
    1577       14251 :             dr(:) = 0.0_dp
    1578      242267 :             DO ib = 1, helium%beads
    1579      926315 :                dr(:) = dr(:) + helium%work(:, ia, ib) - new_com(:)
    1580             :             END DO
    1581       57004 :             dr(:) = dr(:)/REAL(helium%beads, dp)
    1582       57004 :             rtmp = DOT_PRODUCT(dr, dr)
    1583       14746 :             IF (rtmp >= helium%droplet_radius**2) THEN
    1584           1 :                dro(:) = 0.0_dp
    1585          17 :                DO ib = 1, helium%beads
    1586          65 :                   dro(:) = dro(:) + helium%pos(:, ia, ib) - old_com(:)
    1587             :                END DO
    1588           4 :                dro(:) = dro(:)/REAL(helium%beads, dp)
    1589           4 :                rtmpo = DOT_PRODUCT(dro, dro)
    1590             :                ! only reject if it moves away from COM outside the droplet radius
    1591           1 :                IF (rtmpo < rtmp) THEN
    1592             :                   ! found - this one does not fit within R from the center
    1593             :                   should_reject = .TRUE.
    1594             :                   EXIT atom
    1595             :                END IF
    1596             :             END IF
    1597             :          END DO atom
    1598         496 :          IF (should_reject) THEN
    1599             :             ! restore original coordinates
    1600             :             ! write back only changed atoms
    1601           1 :             IF (startbead < endbead) THEN
    1602             :                ! everything belongs to the same atom
    1603           5 :                DO kbead = startbead + 1, endbead - 1
    1604          17 :                   helium%work(:, endatom, kbead) = helium%pos(:, endatom, kbead)
    1605             :                END DO
    1606             :             ELSE
    1607             :                ! is distributed among two atoms
    1608             :                ! transfer to atom not containing the head bead
    1609           0 :                DO kbead = startbead + 1, helium%beads
    1610           0 :                   helium%work(:, startatom, kbead) = helium%pos(:, startatom, kbead)
    1611             :                END DO
    1612             :                ! transfer to atom containing the head bead
    1613           0 :                DO kbead = 1, endbead - 1
    1614           0 :                   helium%work(:, endatom, kbead) = helium%pos(:, endatom, kbead)
    1615             :                END DO
    1616             :             END IF
    1617           1 :             helium%worm_is_closed = .FALSE.
    1618           1 :             ac = 0
    1619           1 :             RETURN
    1620             :          END IF
    1621             :       END IF
    1622             : 
    1623             :       ! finally accepted
    1624         509 :       ac = 1
    1625             :       ! write changed coordinates to position array
    1626         509 :       IF (startbead < endbead) THEN
    1627             :          ! everything belongs to the same atom
    1628        1418 :          DO kbead = startbead + 1, endbead - 1
    1629        4508 :             helium%pos(:, endatom, kbead) = helium%work(:, endatom, kbead)
    1630             :          END DO
    1631             :       ELSE
    1632             :          ! is distributed among two atoms
    1633             :          ! transfer to atom not containing the head bead
    1634         309 :          DO kbead = startbead + 1, helium%beads
    1635         873 :             helium%pos(:, startatom, kbead) = helium%work(:, startatom, kbead)
    1636             :          END DO
    1637             :          ! transfer to atom containing the head bead
    1638         291 :          DO kbead = 1, endbead - 1
    1639         801 :             helium%pos(:, endatom, kbead) = helium%work(:, endatom, kbead)
    1640             :          END DO
    1641             :       END IF
    1642             : 
    1643             :    END SUBROUTINE worm_close_move
    1644             : 
    1645             : ! **************************************************************************************************
    1646             : !> \brief Move head in open state
    1647             : !> \param pint_env ...
    1648             : !> \param helium ...
    1649             : !> \param l ...
    1650             : !> \param ac ...
    1651             : !> \author fuhl
    1652             : ! **************************************************************************************************
    1653        1033 :    SUBROUTINE worm_head_move(pint_env, helium, l, ac)
    1654             : 
    1655             :       TYPE(pint_env_type), INTENT(IN)                    :: pint_env
    1656             :       TYPE(helium_solvent_type), INTENT(INOUT)           :: helium
    1657             :       INTEGER, INTENT(IN)                                :: l
    1658             :       INTEGER, INTENT(OUT)                               :: ac
    1659             : 
    1660             :       INTEGER                                            :: endatom, endbead, ia, ib, idim, kbead, &
    1661             :                                                             startatom, startbead
    1662             :       LOGICAL                                            :: should_reject
    1663             :       REAL(KIND=dp)                                      :: mass, rtmp, rtmpo, sdiff, snew, sold, xr
    1664             :       REAL(KIND=dp), DIMENSION(3)                        :: dr, dro, new_com, old_com
    1665             : 
    1666        1033 :       mass = helium%he_mass_au
    1667             : 
    1668             :       ! get index of the atom and bead, where the resampling of the head begins
    1669        1033 :       endatom = helium%worm_atom_idx
    1670        1033 :       endbead = helium%worm_bead_idx
    1671        1033 :       IF (l < endbead) THEN
    1672             :          ! startbead belongs to the same atom
    1673         806 :          startatom = endatom
    1674         806 :          startbead = endbead - l
    1675             :       ELSE
    1676             :          ! startbead belongs to a different atom
    1677             :          ! find previous atom (assuming l < nbeads)
    1678         227 :          startatom = helium%iperm(endatom)
    1679         227 :          startbead = endbead + helium%beads - l
    1680             :       END IF
    1681             : 
    1682             :       sold = worm_path_action_worm_corrected(helium, helium%pos, &
    1683             :                                              startatom, startbead, endatom, endbead, &
    1684        1033 :                                              helium%worm_xtra_bead, helium%worm_atom_idx, helium%worm_bead_idx)
    1685             : 
    1686        1033 :       IF (helium%solute_present) THEN
    1687             :          sold = sold + worm_path_inter_action_head(pint_env, helium, helium%pos, &
    1688             :                                                    startatom, startbead, &
    1689        1021 :                                                    helium%worm_xtra_bead, helium%worm_atom_idx, helium%worm_bead_idx)
    1690             :       END IF
    1691             : 
    1692             :       ! alternative grow with consecutive gaussians
    1693        1033 :       IF (startbead < endbead) THEN
    1694             :          ! everything belongs to the same atom
    1695             :          ! gro head from startbead
    1696        2751 :          DO kbead = startbead + 1, endbead - 1
    1697        8586 :             DO idim = 1, 3
    1698        5835 :                xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    1699        7780 :                helium%work(idim, startatom, kbead) = helium%work(idim, startatom, kbead - 1) + xr
    1700             :             END DO
    1701             :          END DO
    1702             :          ! last grow head bead
    1703        3224 :          DO idim = 1, 3
    1704        2418 :             xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    1705        3224 :             helium%worm_xtra_bead_work(idim) = helium%work(idim, startatom, endbead - 1) + xr
    1706             :          END DO
    1707         227 :       ELSE IF (endbead /= 1) THEN
    1708             :          ! is distributed among two atoms
    1709             :          ! grow from startbead
    1710         310 :          DO kbead = startbead + 1, helium%beads
    1711         781 :             DO idim = 1, 3
    1712         471 :                xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    1713         628 :                helium%work(idim, startatom, kbead) = helium%work(idim, startatom, kbead - 1) + xr
    1714             :             END DO
    1715             :          END DO
    1716             :          ! bead one of endatom relative to last on startatom
    1717         612 :          DO idim = 1, 3
    1718         459 :             xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    1719         612 :             helium%work(idim, endatom, 1) = helium%work(idim, startatom, helium%beads) + xr
    1720             :          END DO
    1721             :          ! everything on endatom
    1722         300 :          DO kbead = 2, endbead - 1
    1723         741 :             DO idim = 1, 3
    1724         441 :                xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    1725         588 :                helium%work(idim, endatom, kbead) = helium%work(idim, endatom, kbead - 1) + xr
    1726             :             END DO
    1727             :          END DO
    1728         612 :          DO idim = 1, 3
    1729         459 :             xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    1730         612 :             helium%worm_xtra_bead_work(idim) = helium%work(idim, endatom, endbead - 1) + xr
    1731             :          END DO
    1732             :       ELSE ! imagtimewrap and headbead = 1
    1733             :          ! is distributed among two atoms
    1734             :          ! grow from startbead
    1735         252 :          DO kbead = startbead + 1, helium%beads
    1736         786 :             DO idim = 1, 3
    1737         534 :                xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    1738         712 :                helium%work(idim, startatom, kbead) = helium%work(idim, startatom, kbead - 1) + xr
    1739             :             END DO
    1740             :          END DO
    1741             :          ! bead one of endatom relative to last on startatom
    1742         296 :          DO idim = 1, 3
    1743         222 :             xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    1744         296 :             helium%worm_xtra_bead_work(idim) = helium%work(idim, startatom, helium%beads) + xr
    1745             :          END DO
    1746             :       END IF
    1747             : 
    1748             :       snew = worm_path_action_worm_corrected(helium, helium%work, &
    1749             :                                              startatom, startbead, endatom, endbead, &
    1750        1033 :                                              helium%worm_xtra_bead_work, helium%worm_atom_idx_work, helium%worm_bead_idx_work)
    1751             : 
    1752        1033 :       IF (helium%solute_present) THEN
    1753             :          snew = snew + worm_path_inter_action_head(pint_env, helium, helium%work, &
    1754             :                                                    startatom, startbead, &
    1755        1021 :                                                    helium%worm_xtra_bead_work, helium%worm_atom_idx_work, helium%worm_bead_idx_work)
    1756             :       END IF
    1757             : 
    1758             :       ! Metropolis:
    1759             :       ! action difference
    1760        1033 :       sdiff = sold - snew
    1761             :       ! modify action difference due to extra bead
    1762        1033 :       IF (sdiff < 0) THEN
    1763         568 :          should_reject = .FALSE.
    1764         568 :          IF (sdiff < -100.0_dp) THEN ! To protect from exponential underflow
    1765             :             should_reject = .TRUE.
    1766             :          ELSE
    1767         561 :             rtmp = helium%rng_stream_uniform%next()
    1768         561 :             IF (EXP(sdiff) < rtmp) THEN
    1769             :                should_reject = .TRUE.
    1770             :             END IF
    1771             :          END IF
    1772             :          IF (should_reject) THEN
    1773             :             ! rejected !
    1774             :             ! write back only changed atoms
    1775             :             ! transfer the new coordinates to work array
    1776          32 :             IF (startbead < endbead) THEN
    1777             :                ! everything belongs to the same atom
    1778         110 :                DO kbead = startbead + 1, endbead - 1
    1779         353 :                   helium%work(:, endatom, kbead) = helium%pos(:, endatom, kbead)
    1780             :                END DO
    1781             :             ELSE
    1782             :                ! is distributed among two atoms
    1783             :                ! transfer to atom not containing the head bead
    1784           9 :                DO kbead = startbead + 1, helium%beads
    1785          27 :                   helium%work(:, startatom, kbead) = helium%pos(:, startatom, kbead)
    1786             :                END DO
    1787             :                ! transfer to atom containing the head bead
    1788           9 :                DO kbead = 1, endbead - 1
    1789          27 :                   helium%work(:, endatom, kbead) = helium%pos(:, endatom, kbead)
    1790             :                END DO
    1791             :             END IF
    1792         128 :             helium%worm_xtra_bead_work(:) = helium%worm_xtra_bead(:)
    1793          32 :             ac = 0
    1794          36 :             RETURN
    1795             :          END IF
    1796             :       END IF
    1797             : 
    1798             :       ! for now accepted
    1799             :       ! rejection of the whole move if any centroid is farther away
    1800             :       ! from the current center of gravity than HELIUM%DROPLET_RADIUS [lwalewski]
    1801             :       ! AND ist not moving towards the center
    1802        1001 :       IF (.NOT. helium%periodic) THEN
    1803         994 :          IF (helium%solute_present) THEN
    1804        3976 :             new_com(:) = helium%center(:)
    1805         994 :             old_com(:) = new_com(:)
    1806             :          ELSE
    1807           0 :             new_com(:) = 0.0_dp
    1808           0 :             DO ia = 1, helium%atoms
    1809           0 :                DO ib = 1, helium%beads
    1810           0 :                   new_com(:) = new_com(:) + helium%work(:, ia, ib)
    1811             :                END DO
    1812             :             END DO
    1813           0 :             new_com(:) = new_com(:)/(REAL(helium%atoms*helium%beads, dp))
    1814             :             ! also compute the old center of mass (optimization potential)
    1815           0 :             old_com(:) = 0.0_dp
    1816           0 :             DO ia = 1, helium%atoms
    1817           0 :                DO ib = 1, helium%beads
    1818           0 :                   old_com(:) = old_com(:) + helium%pos(:, ia, ib)
    1819             :                END DO
    1820             :             END DO
    1821           0 :             old_com(:) = old_com(:)/(REAL(helium%atoms*helium%beads, dp))
    1822             :          END IF
    1823         994 :          should_reject = .FALSE.
    1824       30520 :          atom: DO ia = 1, helium%atoms
    1825       29530 :             dr(:) = 0.0_dp
    1826      502010 :             DO ib = 1, helium%beads
    1827     1919450 :                dr(:) = dr(:) + helium%work(:, ia, ib) - new_com(:)
    1828             :             END DO
    1829      118120 :             dr(:) = dr(:)/REAL(helium%beads, dp)
    1830      118120 :             rtmp = DOT_PRODUCT(dr, dr)
    1831       30520 :             IF (rtmp >= helium%droplet_radius**2) THEN
    1832           4 :                dro(:) = 0.0_dp
    1833          68 :                DO ib = 1, helium%beads
    1834         260 :                   dro(:) = dro(:) + helium%pos(:, ia, ib) - old_com(:)
    1835             :                END DO
    1836          16 :                dro(:) = dro(:)/REAL(helium%beads, dp)
    1837          16 :                rtmpo = DOT_PRODUCT(dro, dro)
    1838             :                ! only reject if it moves away from COM outside the droplet radius
    1839           4 :                IF (rtmpo < rtmp) THEN
    1840             :                   ! found - this one does not fit within R from the center
    1841             :                   should_reject = .TRUE.
    1842             :                   EXIT atom
    1843             :                END IF
    1844             :             END IF
    1845             :          END DO atom
    1846         994 :          IF (should_reject) THEN
    1847             :             ! restore original coordinates
    1848             :             ! write back only changed atoms
    1849           4 :             IF (startbead < endbead) THEN
    1850             :                ! everything belongs to the same atom
    1851          13 :                DO kbead = startbead + 1, endbead - 1
    1852          43 :                   helium%work(:, endatom, kbead) = helium%pos(:, endatom, kbead)
    1853             :                END DO
    1854             :             ELSE
    1855             :                ! is distributed among two atoms
    1856             :                ! transfer to atom not containing the head bead
    1857           1 :                DO kbead = startbead + 1, helium%beads
    1858           1 :                   helium%work(:, startatom, kbead) = helium%pos(:, startatom, kbead)
    1859             :                END DO
    1860             :                ! transfer to atom containing the head bead
    1861           5 :                DO kbead = 1, endbead - 1
    1862          17 :                   helium%work(:, endatom, kbead) = helium%pos(:, endatom, kbead)
    1863             :                END DO
    1864             :             END IF
    1865          16 :             helium%worm_xtra_bead_work(:) = helium%worm_xtra_bead(:)
    1866           4 :             ac = 0
    1867           4 :             RETURN
    1868             :          END IF
    1869             :       END IF
    1870             : 
    1871             :       ! finally accepted
    1872         997 :       ac = 1
    1873             :       ! write changed coordinates to position array
    1874         997 :       IF (startbead < endbead) THEN
    1875             :          ! everything belongs to the same atom
    1876        2628 :          DO kbead = startbead + 1, endbead - 1
    1877        8190 :             helium%pos(:, endatom, kbead) = helium%work(:, endatom, kbead)
    1878             :          END DO
    1879             :       ELSE
    1880             :          ! is distributed among two atoms
    1881             :          ! transfer to atom not containing the head bead
    1882         552 :          DO kbead = startbead + 1, helium%beads
    1883        1539 :             helium%pos(:, startatom, kbead) = helium%work(:, startatom, kbead)
    1884             :          END DO
    1885             :          ! transfer to atom containing the head bead
    1886         513 :          DO kbead = 1, endbead - 1
    1887        1383 :             helium%pos(:, endatom, kbead) = helium%work(:, endatom, kbead)
    1888             :          END DO
    1889             :       END IF
    1890        3988 :       helium%worm_xtra_bead(:) = helium%worm_xtra_bead_work(:)
    1891             : 
    1892             :    END SUBROUTINE worm_head_move
    1893             : 
    1894             : ! **************************************************************************************************
    1895             : !> \brief Move tail in open state
    1896             : !> \param pint_env ...
    1897             : !> \param helium ...
    1898             : !> \param l ...
    1899             : !> \param ac ...
    1900             : !> \author fuhl
    1901             : ! **************************************************************************************************
    1902        1041 :    SUBROUTINE worm_tail_move(pint_env, helium, l, ac)
    1903             : 
    1904             :       TYPE(pint_env_type), INTENT(IN)                    :: pint_env
    1905             :       TYPE(helium_solvent_type), INTENT(INOUT)           :: helium
    1906             :       INTEGER, INTENT(IN)                                :: l
    1907             :       INTEGER, INTENT(OUT)                               :: ac
    1908             : 
    1909             :       INTEGER                                            :: endatom, endbead, ia, ib, idim, kbead, &
    1910             :                                                             startatom, startbead
    1911             :       LOGICAL                                            :: should_reject
    1912             :       REAL(KIND=dp)                                      :: mass, rtmp, rtmpo, sdiff, snew, sold, xr
    1913             :       REAL(KIND=dp), DIMENSION(3)                        :: dr, dro, new_com, old_com
    1914             : 
    1915        1041 :       mass = helium%he_mass_au
    1916             : 
    1917             :       ! get index of the atom and bead, where the resampling of the tail ends
    1918        1041 :       startatom = helium%worm_atom_idx
    1919        1041 :       startbead = helium%worm_bead_idx
    1920        1041 :       endbead = startbead + l
    1921             : 
    1922        1041 :       IF (endbead <= helium%beads) THEN
    1923             :          ! endbead belongs to the same atom
    1924         862 :          endatom = startatom
    1925             :       ELSE
    1926             :          ! endbead belongs to a different atom
    1927             :          ! find next atom (assuming l < nbeads)
    1928         179 :          endatom = helium%permutation(startatom)
    1929         179 :          endbead = endbead - helium%beads
    1930             :       END IF
    1931             : 
    1932             :       !yes this is correct, as the head does not play any role here
    1933             :       sold = worm_path_action(helium, helium%pos, &
    1934        1041 :                               startatom, startbead, endatom, endbead)
    1935             : 
    1936        1041 :       IF (helium%solute_present) THEN
    1937             :          sold = sold + worm_path_inter_action_tail(pint_env, helium, helium%pos, &
    1938             :                                                    endatom, endbead, &
    1939        1029 :                                                    helium%worm_atom_idx, helium%worm_bead_idx)
    1940             :       END IF
    1941             : 
    1942             :       ! alternative grow with consecutive gaussians
    1943        1041 :       IF (startbead < endbead) THEN
    1944             :          ! everything belongs to the same atom
    1945             :          ! gro tail from endbead to startbead (confusing eh?)
    1946        3777 :          DO kbead = endbead - 1, startbead, -1
    1947       12522 :             DO idim = 1, 3
    1948        8745 :                xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    1949       11660 :                helium%work(idim, startatom, kbead) = helium%work(idim, startatom, kbead + 1) + xr
    1950             :             END DO
    1951             :          END DO
    1952             :       ELSE
    1953             :          ! is distributed among two atoms
    1954             :          ! grow from endbead
    1955         379 :          DO kbead = endbead - 1, 1, -1
    1956         979 :             DO idim = 1, 3
    1957         600 :                xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    1958         800 :                helium%work(idim, endatom, kbead) = helium%work(idim, endatom, kbead + 1) + xr
    1959             :             END DO
    1960             :          END DO
    1961             : 
    1962             :          ! over imaginary time boundary
    1963         716 :          DO idim = 1, 3
    1964         537 :             xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    1965         716 :             helium%work(idim, startatom, helium%beads) = helium%work(idim, endatom, 1) + xr
    1966             :          END DO
    1967             : 
    1968             :          ! rest on startatom
    1969         480 :          DO kbead = helium%beads - 1, startbead, -1
    1970        1383 :             DO idim = 1, 3
    1971         903 :                xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    1972        1204 :                helium%work(idim, startatom, kbead) = helium%work(idim, startatom, kbead + 1) + xr
    1973             :             END DO
    1974             :          END DO
    1975             :       END IF
    1976             : 
    1977             :       !yes this is correct, as the head does not play any role here
    1978             :       snew = worm_path_action(helium, helium%work, &
    1979        1041 :                               startatom, startbead, endatom, endbead)
    1980             : 
    1981        1041 :       IF (helium%solute_present) THEN
    1982             :          snew = snew + worm_path_inter_action_tail(pint_env, helium, helium%work, &
    1983             :                                                    endatom, endbead, &
    1984        1029 :                                                    helium%worm_atom_idx_work, helium%worm_bead_idx_work)
    1985             :       END IF
    1986             : 
    1987             :       ! Metropolis:
    1988             :       ! action difference
    1989        1041 :       sdiff = sold - snew
    1990             :       ! modify action difference due to extra bead
    1991        1041 :       IF (sdiff < 0) THEN
    1992         526 :          should_reject = .FALSE.
    1993         526 :          IF (sdiff < -100.0_dp) THEN ! To protect from exponential underflow
    1994             :             should_reject = .TRUE.
    1995             :          ELSE
    1996         526 :             rtmp = helium%rng_stream_uniform%next()
    1997         526 :             IF (EXP(sdiff) < rtmp) THEN
    1998             :                should_reject = .TRUE.
    1999             :             END IF
    2000             :          END IF
    2001             :          IF (should_reject) THEN
    2002             :             ! rejected !
    2003             :             ! write back only changed atoms
    2004             :             ! transfer the new coordinates to work array
    2005          25 :             IF (startbead < endbead) THEN
    2006             :                ! everything belongs to the same atom
    2007         100 :                DO kbead = startbead, endbead - 1
    2008         343 :                   helium%work(:, endatom, kbead) = helium%pos(:, endatom, kbead)
    2009             :                END DO
    2010             :             ELSE
    2011             :                ! is distributed among two atoms
    2012             :                ! transfer to atom not containing the tail bead
    2013          32 :                DO kbead = startbead, helium%beads
    2014         110 :                   helium%work(:, startatom, kbead) = helium%pos(:, startatom, kbead)
    2015             :                END DO
    2016             :                ! transfer to atom containing the tail bead
    2017           8 :                DO kbead = 1, endbead - 1
    2018          14 :                   helium%work(:, endatom, kbead) = helium%pos(:, endatom, kbead)
    2019             :                END DO
    2020             :             END IF
    2021         100 :             helium%worm_xtra_bead_work(:) = helium%worm_xtra_bead(:)
    2022          25 :             ac = 0
    2023          32 :             RETURN
    2024             :          END IF
    2025             :       END IF
    2026             : 
    2027             :       ! for now accepted
    2028             :       ! rejection of the whole move if any centroid is farther away
    2029             :       ! from the current center of gravity than HELIUM%DROPLET_RADIUS [lwalewski]
    2030             :       ! AND ist not moving towards the center
    2031        1016 :       IF (.NOT. helium%periodic) THEN
    2032        1010 :          IF (helium%solute_present) THEN
    2033        4040 :             new_com(:) = helium%center(:)
    2034        1010 :             old_com(:) = new_com(:)
    2035             :          ELSE
    2036           0 :             new_com(:) = 0.0_dp
    2037           0 :             DO ia = 1, helium%atoms
    2038           0 :                DO ib = 1, helium%beads
    2039           0 :                   new_com(:) = new_com(:) + helium%work(:, ia, ib)
    2040             :                END DO
    2041             :             END DO
    2042           0 :             new_com(:) = new_com(:)/(REAL(helium%atoms*helium%beads, dp))
    2043             :             ! also compute the old center of mass (optimization potential)
    2044           0 :             old_com(:) = 0.0_dp
    2045           0 :             DO ia = 1, helium%atoms
    2046           0 :                DO ib = 1, helium%beads
    2047           0 :                   old_com(:) = old_com(:) + helium%pos(:, ia, ib)
    2048             :                END DO
    2049             :             END DO
    2050           0 :             old_com(:) = old_com(:)/(REAL(helium%atoms*helium%beads, dp))
    2051             :          END IF
    2052        1010 :          should_reject = .FALSE.
    2053       31174 :          atom: DO ia = 1, helium%atoms
    2054       30171 :             dr(:) = 0.0_dp
    2055      512907 :             DO ib = 1, helium%beads
    2056     1961115 :                dr(:) = dr(:) + helium%work(:, ia, ib) - new_com(:)
    2057             :             END DO
    2058      120684 :             dr(:) = dr(:)/REAL(helium%beads, dp)
    2059      120684 :             rtmp = DOT_PRODUCT(dr, dr)
    2060       31174 :             IF (rtmp >= helium%droplet_radius**2) THEN
    2061           7 :                dro(:) = 0.0_dp
    2062         119 :                DO ib = 1, helium%beads
    2063         455 :                   dro(:) = dro(:) + helium%pos(:, ia, ib) - old_com(:)
    2064             :                END DO
    2065          28 :                dro(:) = dro(:)/REAL(helium%beads, dp)
    2066          28 :                rtmpo = DOT_PRODUCT(dro, dro)
    2067             :                ! only reject if it moves away from COM outside the droplet radius
    2068           7 :                IF (rtmpo < rtmp) THEN
    2069             :                   ! found - this one does not fit within R from the center
    2070             :                   should_reject = .TRUE.
    2071             :                   EXIT atom
    2072             :                END IF
    2073             :             END IF
    2074             :          END DO atom
    2075        1010 :          IF (should_reject) THEN
    2076             :             ! restore original coordinates
    2077             :             ! write back only changed atoms
    2078           7 :             IF (startbead < endbead) THEN
    2079             :                ! everything belongs to the same atom
    2080          30 :                DO kbead = startbead, endbead - 1
    2081          99 :                   helium%work(:, endatom, kbead) = helium%pos(:, endatom, kbead)
    2082             :                END DO
    2083             :             ELSE
    2084             :                ! is distributed among two atoms
    2085             :                ! transfer to atom not containing the tail bead
    2086           0 :                DO kbead = startbead, helium%beads
    2087           0 :                   helium%work(:, startatom, kbead) = helium%pos(:, startatom, kbead)
    2088             :                END DO
    2089             :                ! transfer to atom containing the tail bead
    2090           0 :                DO kbead = 1, endbead - 1
    2091           0 :                   helium%work(:, endatom, kbead) = helium%pos(:, endatom, kbead)
    2092             :                END DO
    2093             :             END IF
    2094          28 :             helium%worm_xtra_bead_work(:) = helium%worm_xtra_bead(:)
    2095           7 :             ac = 0
    2096           7 :             RETURN
    2097             :          END IF
    2098             :       END IF
    2099             : 
    2100             :       ! finally accepted
    2101        1009 :       ac = 1
    2102             :       ! write changed coordinates to position array
    2103        1009 :       IF (startbead < endbead) THEN
    2104             :          ! everything belongs to the same atom
    2105        3647 :          DO kbead = startbead, endbead - 1
    2106       12080 :             helium%pos(:, endatom, kbead) = helium%work(:, endatom, kbead)
    2107             :          END DO
    2108             :       ELSE
    2109             :          ! is distributed among two atoms
    2110             :          ! transfer to atom not containing the tail bead
    2111         627 :          DO kbead = startbead, helium%beads
    2112        1989 :             helium%pos(:, startatom, kbead) = helium%work(:, startatom, kbead)
    2113             :          END DO
    2114             :          ! transfer to atom containing the tail bead
    2115         371 :          DO kbead = 1, endbead - 1
    2116         965 :             helium%pos(:, endatom, kbead) = helium%work(:, endatom, kbead)
    2117             :          END DO
    2118             :       END IF
    2119             : 
    2120             :    END SUBROUTINE worm_tail_move
    2121             : 
    2122             : ! **************************************************************************************************
    2123             : !> \brief Crawl forward in open state, can avoid being trapped in open state
    2124             : !> \param pint_env ...
    2125             : !> \param helium ...
    2126             : !> \param l ...
    2127             : !> \param ac ...
    2128             : !> \author fuhl
    2129             : ! **************************************************************************************************
    2130        1880 :    SUBROUTINE worm_crawl_move_forward(pint_env, helium, l, ac)
    2131             : 
    2132             :       TYPE(pint_env_type), INTENT(IN)                    :: pint_env
    2133             :       TYPE(helium_solvent_type), INTENT(INOUT)           :: helium
    2134             :       INTEGER, INTENT(IN)                                :: l
    2135             :       INTEGER, INTENT(OUT)                               :: ac
    2136             : 
    2137             :       INTEGER                                            :: ia, ib, idim, kbead
    2138             :       LOGICAL                                            :: should_reject
    2139             :       REAL(KIND=dp)                                      :: mass, newtailpot, oldheadpot, &
    2140             :                                                             oldtailpot, rtmp, rtmpo, sdiff, snew, &
    2141             :                                                             sold, xr
    2142             :       REAL(KIND=dp), DIMENSION(3)                        :: dr, dro, new_com, old_com
    2143             : 
    2144        1880 :       mass = helium%he_mass_au
    2145             : 
    2146             :       ! determine position of new head in imaginary time
    2147        1880 :       helium%worm_bead_idx_work = helium%worm_bead_idx + l
    2148        1880 :       IF (helium%worm_bead_idx_work > helium%beads) THEN
    2149         418 :          helium%worm_bead_idx_work = helium%worm_bead_idx_work - helium%beads
    2150         418 :          helium%worm_atom_idx_work = helium%permutation(helium%worm_atom_idx)
    2151             :       ELSE
    2152        1462 :          helium%worm_atom_idx_work = helium%worm_atom_idx
    2153             :       END IF
    2154             : 
    2155             :       ! compute action before move
    2156             :       ! head is not involved in pair action
    2157             :       sold = worm_path_action(helium, helium%pos, &
    2158             :                               helium%worm_atom_idx, helium%worm_bead_idx, &
    2159        1880 :                               helium%worm_atom_idx_work, helium%worm_bead_idx_work)
    2160        1880 :       IF (helium%solute_present) THEN
    2161             :          !this will leave out the old and new tail bead
    2162             :          ! due to efficiency reasons they are treated separately
    2163             :          sold = sold + worm_path_inter_action(pint_env, helium, helium%pos, &
    2164             :                                               helium%worm_atom_idx, helium%worm_bead_idx, &
    2165        1848 :                                               helium%worm_atom_idx_work, helium%worm_bead_idx_work)
    2166             : 
    2167             :          ! compute old/new head/tail interactions
    2168             :          ! old tail
    2169             :          CALL helium_bead_solute_e_f(pint_env, helium, &
    2170             :                                      helium%worm_atom_idx, helium%worm_bead_idx, &
    2171             :                                      helium%pos(:, helium%worm_atom_idx, helium%worm_bead_idx), &
    2172        1848 :                                      energy=oldtailpot)
    2173        1848 :          oldtailpot = oldtailpot*helium%tau
    2174             : 
    2175             :          ! new tail
    2176             :          CALL helium_bead_solute_e_f(pint_env, helium, &
    2177             :                                      helium%worm_atom_idx_work, helium%worm_bead_idx_work, &
    2178             :                                      helium%pos(:, helium%worm_atom_idx_work, helium%worm_bead_idx_work), &
    2179        1848 :                                      energy=newtailpot)
    2180        1848 :          newtailpot = newtailpot*helium%tau
    2181             : 
    2182             :          ! old head
    2183             :          CALL helium_bead_solute_e_f(pint_env, helium, &
    2184             :                                      helium%worm_atom_idx, helium%worm_bead_idx, &
    2185             :                                      helium%worm_xtra_bead, &
    2186        1848 :                                      energy=oldheadpot)
    2187        1848 :          oldheadpot = oldheadpot*helium%tau
    2188             : 
    2189             :          ! new head is not known yet
    2190             : 
    2191        1848 :          sold = sold + 0.5_dp*(oldtailpot + oldheadpot) + newtailpot
    2192             :       END IF
    2193             : 
    2194             :       ! copy over old head position to working array and grow from there
    2195        7520 :       helium%work(:, helium%worm_atom_idx, helium%worm_bead_idx) = helium%worm_xtra_bead
    2196             : 
    2197             :       ! grow head part with consecutive gaussians
    2198        1880 :       IF (helium%worm_bead_idx < helium%worm_bead_idx_work) THEN
    2199             :          ! everything belongs to the same atom
    2200             :          ! gro head from startbead
    2201        4999 :          DO kbead = helium%worm_bead_idx + 1, helium%worm_bead_idx_work - 1
    2202       15610 :             DO idim = 1, 3
    2203       10611 :                xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    2204       14148 :                helium%work(idim, helium%worm_atom_idx, kbead) = helium%work(idim, helium%worm_atom_idx, kbead - 1) + xr
    2205             :             END DO
    2206             :          END DO
    2207             :          ! last grow head bead
    2208        5848 :          DO idim = 1, 3
    2209        4386 :             xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    2210        5848 :             helium%worm_xtra_bead_work(idim) = helium%work(idim, helium%worm_atom_idx, helium%worm_bead_idx_work - 1) + xr
    2211             :          END DO
    2212         418 :       ELSE IF (helium%worm_bead_idx_work /= 1) THEN
    2213             :          ! is distributed among two atoms
    2214             :          ! grow from startbead
    2215         593 :          DO kbead = helium%worm_bead_idx + 1, helium%beads
    2216        1484 :             DO idim = 1, 3
    2217         891 :                xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    2218        1188 :                helium%work(idim, helium%worm_atom_idx, kbead) = helium%work(idim, helium%worm_atom_idx, kbead - 1) + xr
    2219             :             END DO
    2220             :          END DO
    2221             :          ! bead one of endatom relative to last on helium%worm_atom_idx
    2222        1184 :          DO idim = 1, 3
    2223         888 :             xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    2224        1184 :             helium%work(idim, helium%worm_atom_idx_work, 1) = helium%work(idim, helium%worm_atom_idx, helium%beads) + xr
    2225             :          END DO
    2226             :          ! everything on endatom
    2227         573 :          DO kbead = 2, helium%worm_bead_idx_work - 1
    2228        1404 :             DO idim = 1, 3
    2229         831 :                xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    2230        1108 :                helium%work(idim, helium%worm_atom_idx_work, kbead) = helium%work(idim, helium%worm_atom_idx_work, kbead - 1) + xr
    2231             :             END DO
    2232             :          END DO
    2233        1184 :          DO idim = 1, 3
    2234         888 :             xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    2235        1184 :             helium%worm_xtra_bead_work(idim) = helium%work(idim, helium%worm_atom_idx_work, helium%worm_bead_idx_work - 1) + xr
    2236             :          END DO
    2237             :       ELSE ! imagtimewrap and headbead = 1
    2238             :          ! is distributed among two atoms
    2239             :          ! grow from startbead
    2240         402 :          DO kbead = helium%worm_bead_idx + 1, helium%beads
    2241        1242 :             DO idim = 1, 3
    2242         840 :                xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    2243        1120 :                helium%work(idim, helium%worm_atom_idx, kbead) = helium%work(idim, helium%worm_atom_idx, kbead - 1) + xr
    2244             :             END DO
    2245             :          END DO
    2246             :          ! bead one of endatom relative to last on helium%worm_atom_idx
    2247         488 :          DO idim = 1, 3
    2248         366 :             xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    2249         488 :             helium%worm_xtra_bead_work(idim) = helium%work(idim, helium%worm_atom_idx, helium%beads) + xr
    2250             :          END DO
    2251             :       END IF
    2252             : 
    2253             :       snew = worm_path_action_worm_corrected(helium, helium%work, &
    2254             :                                              helium%worm_atom_idx, helium%worm_bead_idx, &
    2255             :                                              helium%worm_atom_idx_work, helium%worm_bead_idx_work, &
    2256        1880 :                                              helium%worm_xtra_bead_work, helium%worm_atom_idx_work, helium%worm_bead_idx_work)
    2257             : 
    2258        1880 :       IF (helium%solute_present) THEN
    2259             :          snew = snew + worm_path_inter_action_head(pint_env, helium, helium%work, &
    2260             :                                                    helium%worm_atom_idx, helium%worm_bead_idx, &
    2261        1848 :                                                    helium%worm_xtra_bead_work, helium%worm_atom_idx_work, helium%worm_bead_idx_work)
    2262        1848 :          snew = snew + 0.5_dp*newtailpot + oldheadpot
    2263             :       END IF
    2264             : 
    2265             :       ! Metropolis:
    2266             :       ! action difference
    2267        1880 :       sdiff = sold - snew
    2268             :       ! modify action difference due to extra bead
    2269        1880 :       IF (sdiff < 0) THEN
    2270         969 :          should_reject = .FALSE.
    2271         969 :          IF (sdiff < -100.0_dp) THEN ! To protect from exponential underflow
    2272             :             should_reject = .TRUE.
    2273             :          ELSE
    2274         959 :             rtmp = helium%rng_stream_uniform%next()
    2275         959 :             IF (EXP(sdiff) < rtmp) THEN
    2276             :                should_reject = .TRUE.
    2277             :             END IF
    2278             :          END IF
    2279             :          IF (should_reject) THEN
    2280             :             ! rejected !
    2281             :             ! write back only changed atoms
    2282             :             ! transfer the new coordinates to work array
    2283          95 :             IF (helium%worm_bead_idx < helium%worm_bead_idx_work) THEN
    2284             :                ! everything belongs to the same atom
    2285         328 :                DO kbead = helium%worm_bead_idx, helium%worm_bead_idx_work - 1
    2286        1099 :                   helium%work(:, helium%worm_atom_idx_work, kbead) = helium%pos(:, helium%worm_atom_idx_work, kbead)
    2287             :                END DO
    2288             :             ELSE
    2289             :                ! is distributed among two atoms
    2290             :                ! transfer to atom not containing the head bead
    2291          68 :                DO kbead = helium%worm_bead_idx, helium%beads
    2292         200 :                   helium%work(:, helium%worm_atom_idx, kbead) = helium%pos(:, helium%worm_atom_idx, kbead)
    2293             :                END DO
    2294             :                ! transfer to atom containing the head bead
    2295          69 :                DO kbead = 1, helium%worm_bead_idx_work - 1
    2296         204 :                   helium%work(:, helium%worm_atom_idx_work, kbead) = helium%pos(:, helium%worm_atom_idx_work, kbead)
    2297             :                END DO
    2298             :             END IF
    2299         380 :             helium%worm_xtra_bead_work(:) = helium%worm_xtra_bead(:)
    2300          95 :             helium%worm_bead_idx_work = helium%worm_bead_idx
    2301          95 :             helium%worm_atom_idx_work = helium%worm_atom_idx
    2302          95 :             ac = 0
    2303         108 :             RETURN
    2304             :          END IF
    2305             :       END IF
    2306             : 
    2307             :       ! for now accepted
    2308             :       ! rejection of the whole move if any centroid is farther away
    2309             :       ! from the current center of gravity than HELIUM%DROPLET_RADIUS [lwalewski]
    2310             :       ! AND ist not moving towards the center
    2311        1785 :       IF (.NOT. helium%periodic) THEN
    2312        1773 :          IF (helium%solute_present) THEN
    2313        7092 :             new_com(:) = helium%center(:)
    2314        1773 :             old_com(:) = new_com(:)
    2315             :          ELSE
    2316           0 :             new_com(:) = 0.0_dp
    2317           0 :             DO ia = 1, helium%atoms
    2318           0 :                DO ib = 1, helium%beads
    2319           0 :                   new_com(:) = new_com(:) + helium%work(:, ia, ib)
    2320             :                END DO
    2321             :             END DO
    2322           0 :             new_com(:) = new_com(:)/(REAL(helium%atoms*helium%beads, dp))
    2323             :             ! also compute the old center of mass (optimization potential)
    2324           0 :             old_com(:) = 0.0_dp
    2325           0 :             DO ia = 1, helium%atoms
    2326           0 :                DO ib = 1, helium%beads
    2327           0 :                   old_com(:) = old_com(:) + helium%pos(:, ia, ib)
    2328             :                END DO
    2329             :             END DO
    2330           0 :             old_com(:) = old_com(:)/(REAL(helium%atoms*helium%beads, dp))
    2331             :          END IF
    2332        1773 :          should_reject = .FALSE.
    2333       53384 :          atom: DO ia = 1, helium%atoms
    2334       51624 :             dr(:) = 0.0_dp
    2335      877608 :             DO ib = 1, helium%beads
    2336     3355560 :                dr(:) = dr(:) + helium%work(:, ia, ib) - new_com(:)
    2337             :             END DO
    2338      206496 :             dr(:) = dr(:)/REAL(helium%beads, dp)
    2339      206496 :             rtmp = DOT_PRODUCT(dr, dr)
    2340       53384 :             IF (rtmp >= helium%droplet_radius**2) THEN
    2341          13 :                dro(:) = 0.0_dp
    2342         221 :                DO ib = 1, helium%beads
    2343         845 :                   dro(:) = dro(:) + helium%pos(:, ia, ib) - old_com(:)
    2344             :                END DO
    2345          52 :                dro(:) = dro(:)/REAL(helium%beads, dp)
    2346          52 :                rtmpo = DOT_PRODUCT(dro, dro)
    2347             :                ! only reject if it moves away from COM outside the droplet radius
    2348          13 :                IF (rtmpo < rtmp) THEN
    2349             :                   ! found - this one does not fit within R from the center
    2350             :                   should_reject = .TRUE.
    2351             :                   EXIT atom
    2352             :                END IF
    2353             :             END IF
    2354             :          END DO atom
    2355        1773 :          IF (should_reject) THEN
    2356             :             ! restore original coordinates
    2357             :             ! write back only changed atoms
    2358          13 :             IF (helium%worm_bead_idx < helium%worm_bead_idx_work) THEN
    2359             :                ! everything belongs to the same atom
    2360          40 :                DO kbead = helium%worm_bead_idx, helium%worm_bead_idx_work - 1
    2361         133 :                   helium%work(:, helium%worm_atom_idx_work, kbead) = helium%pos(:, helium%worm_atom_idx_work, kbead)
    2362             :                END DO
    2363             :             ELSE
    2364             :                ! is distributed among two atoms
    2365             :                ! transfer to atom not containing the head bead
    2366          13 :                DO kbead = helium%worm_bead_idx, helium%beads
    2367          40 :                   helium%work(:, helium%worm_atom_idx, kbead) = helium%pos(:, helium%worm_atom_idx, kbead)
    2368             :                END DO
    2369             :                ! transfer to atom containing the head bead
    2370          12 :                DO kbead = 1, helium%worm_bead_idx_work - 1
    2371          36 :                   helium%work(:, helium%worm_atom_idx_work, kbead) = helium%pos(:, helium%worm_atom_idx_work, kbead)
    2372             :                END DO
    2373             :             END IF
    2374          52 :             helium%worm_xtra_bead_work(:) = helium%worm_xtra_bead(:)
    2375          13 :             helium%worm_bead_idx_work = helium%worm_bead_idx
    2376          13 :             helium%worm_atom_idx_work = helium%worm_atom_idx
    2377          13 :             ac = 0
    2378          13 :             RETURN
    2379             :          END IF
    2380             :       END IF
    2381             : 
    2382             :       ! finally accepted
    2383        1772 :       ac = 1
    2384             :       ! write changed coordinates to position array
    2385        1772 :       IF (helium%worm_bead_idx < helium%worm_bead_idx_work) THEN
    2386             :          ! everything belongs to the same atom
    2387        6093 :          DO kbead = helium%worm_bead_idx, helium%worm_bead_idx_work - 1
    2388       20226 :             helium%pos(:, helium%worm_atom_idx_work, kbead) = helium%work(:, helium%worm_atom_idx_work, kbead)
    2389             :          END DO
    2390             :       ELSE
    2391             :          ! is distributed among two atoms
    2392             :          ! transfer to atom not containing the head bead
    2393        1332 :          DO kbead = helium%worm_bead_idx, helium%beads
    2394        4158 :             helium%pos(:, helium%worm_atom_idx, kbead) = helium%work(:, helium%worm_atom_idx, kbead)
    2395             :          END DO
    2396             :          ! transfer to atom containing the head bead
    2397         910 :          DO kbead = 1, helium%worm_bead_idx_work - 1
    2398        2470 :             helium%pos(:, helium%worm_atom_idx_work, kbead) = helium%work(:, helium%worm_atom_idx_work, kbead)
    2399             :          END DO
    2400             :       END IF
    2401        7088 :       helium%worm_xtra_bead(:) = helium%worm_xtra_bead_work(:)
    2402        1772 :       helium%worm_bead_idx = helium%worm_bead_idx_work
    2403        1772 :       helium%worm_atom_idx = helium%worm_atom_idx_work
    2404             : 
    2405             :    END SUBROUTINE worm_crawl_move_forward
    2406             : 
    2407             : ! **************************************************************************************************
    2408             : !> \brief Crawl backwards in open state, can avoid being trapped in open state
    2409             : !> \param pint_env ...
    2410             : !> \param helium ...
    2411             : !> \param l ...
    2412             : !> \param ac ...
    2413             : !> \author fuhl
    2414             : ! **************************************************************************************************
    2415        2066 :    SUBROUTINE worm_crawl_move_backward(pint_env, helium, l, ac)
    2416             : 
    2417             :       TYPE(pint_env_type), INTENT(IN)                    :: pint_env
    2418             :       TYPE(helium_solvent_type), INTENT(INOUT)           :: helium
    2419             :       INTEGER, INTENT(IN)                                :: l
    2420             :       INTEGER, INTENT(OUT)                               :: ac
    2421             : 
    2422             :       INTEGER                                            :: ia, ib, idim, kbead
    2423             :       LOGICAL                                            :: should_reject
    2424             :       REAL(KIND=dp)                                      :: mass, newheadpot, oldheadpot, &
    2425             :                                                             oldtailpot, rtmp, rtmpo, sdiff, snew, &
    2426             :                                                             sold, xr
    2427             :       REAL(KIND=dp), DIMENSION(3)                        :: dr, dro, new_com, old_com
    2428             : 
    2429        2066 :       mass = helium%he_mass_au
    2430             : 
    2431             :       ! determine position of new head in imaginary time
    2432        2066 :       helium%worm_bead_idx_work = helium%worm_bead_idx - l
    2433        2066 :       IF (helium%worm_bead_idx_work < 1) THEN
    2434         447 :          helium%worm_bead_idx_work = helium%worm_bead_idx_work + helium%beads
    2435         447 :          helium%worm_atom_idx_work = helium%iperm(helium%worm_atom_idx)
    2436             :       ELSE
    2437        1619 :          helium%worm_atom_idx_work = helium%worm_atom_idx
    2438             :       END IF
    2439             : 
    2440             :       ! compute action before move
    2441             :       ! head is not involved in pair action
    2442             :       sold = worm_path_action_worm_corrected(helium, helium%work, &
    2443             :                                              helium%worm_atom_idx_work, helium%worm_bead_idx_work, &
    2444             :                                              helium%worm_atom_idx, helium%worm_bead_idx, &
    2445        2066 :                                              helium%worm_xtra_bead, helium%worm_atom_idx, helium%worm_bead_idx)
    2446             : 
    2447        2066 :       IF (helium%solute_present) THEN
    2448             :          !this will leave out the old and new tail bead
    2449             :          ! due to efficiency reasons they are treated separately
    2450             :          sold = sold + worm_path_inter_action(pint_env, helium, helium%pos, &
    2451             :                                               helium%worm_atom_idx_work, helium%worm_bead_idx_work, &
    2452        2032 :                                               helium%worm_atom_idx, helium%worm_bead_idx)
    2453             : 
    2454             :          ! compute old/new head/tail interactions
    2455             :          ! old tail
    2456             :          CALL helium_bead_solute_e_f(pint_env, helium, &
    2457             :                                      helium%worm_atom_idx, helium%worm_bead_idx, &
    2458             :                                      helium%pos(:, helium%worm_atom_idx, helium%worm_bead_idx), &
    2459        2032 :                                      energy=oldtailpot)
    2460        2032 :          oldtailpot = oldtailpot*helium%tau
    2461             : 
    2462             :          ! old head
    2463             :          CALL helium_bead_solute_e_f(pint_env, helium, &
    2464             :                                      helium%worm_atom_idx, helium%worm_bead_idx, &
    2465             :                                      helium%worm_xtra_bead, &
    2466        2032 :                                      energy=oldheadpot)
    2467        2032 :          oldheadpot = oldheadpot*helium%tau
    2468             : 
    2469             :          ! new head
    2470             :          CALL helium_bead_solute_e_f(pint_env, helium, &
    2471             :                                      helium%worm_atom_idx_work, helium%worm_bead_idx_work, &
    2472             :                                      helium%pos(:, helium%worm_atom_idx_work, helium%worm_bead_idx_work), &
    2473        2032 :                                      energy=newheadpot)
    2474        2032 :          newheadpot = newheadpot*helium%tau
    2475             : 
    2476             :          ! new tail not known yet
    2477             : 
    2478        2032 :          sold = sold + 0.5_dp*(oldtailpot + oldheadpot) + newheadpot
    2479             :       END IF
    2480             : 
    2481             :       ! copy position to the head bead
    2482        8264 :       helium%worm_xtra_bead_work = helium%pos(:, helium%worm_atom_idx_work, helium%worm_bead_idx_work)
    2483             : 
    2484             :       ! alternative grow with consecutive gaussians
    2485        2066 :       IF (helium%worm_bead_idx_work < helium%worm_bead_idx) THEN
    2486             :          ! everything belongs to the same atom
    2487             :          ! gro tail from endbead to startbead (confusing eh?)
    2488        7197 :          DO kbead = helium%worm_bead_idx - 1, helium%worm_bead_idx_work, -1
    2489       23931 :             DO idim = 1, 3
    2490       16734 :                xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    2491       22312 :                helium%work(idim, helium%worm_atom_idx, kbead) = helium%work(idim, helium%worm_atom_idx, kbead + 1) + xr
    2492             :             END DO
    2493             : 
    2494             :          END DO
    2495             :       ELSE
    2496             :          ! is distributed among two atoms
    2497             :          ! grow from endbead
    2498        1092 :          DO kbead = helium%worm_bead_idx - 1, 1, -1
    2499        3027 :             DO idim = 1, 3
    2500        1935 :                xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    2501        2580 :                helium%work(idim, helium%worm_atom_idx, kbead) = helium%work(idim, helium%worm_atom_idx, kbead + 1) + xr
    2502             :             END DO
    2503             :          END DO
    2504             : 
    2505             :          ! over imaginary time boundary
    2506        1788 :          DO idim = 1, 3
    2507        1341 :             xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    2508        1788 :             helium%work(idim, helium%worm_atom_idx_work, helium%beads) = helium%work(idim, helium%worm_atom_idx, 1) + xr
    2509             :          END DO
    2510             : 
    2511             :          ! rest on startatom
    2512        1075 :          DO kbead = helium%beads - 1, helium%worm_bead_idx_work, -1
    2513        2959 :             DO idim = 1, 3
    2514        1884 :                xr = helium%rng_stream_gaussian%next(variance=helium%hb2m*helium%tau)
    2515        2512 :                helium%work(idim, helium%worm_atom_idx_work, kbead) = helium%work(idim, helium%worm_atom_idx_work, kbead + 1) + xr
    2516             :             END DO
    2517             :          END DO
    2518             :       END IF
    2519             : 
    2520             :       snew = worm_path_action(helium, helium%work, &
    2521             :                               helium%worm_atom_idx_work, helium%worm_bead_idx_work, &
    2522        2066 :                               helium%worm_atom_idx, helium%worm_bead_idx)
    2523             : 
    2524        2066 :       IF (helium%solute_present) THEN
    2525             :          snew = snew + worm_path_inter_action_tail(pint_env, helium, helium%work, &
    2526             :                                                    helium%worm_atom_idx, helium%worm_bead_idx, &
    2527        2032 :                                                    helium%worm_atom_idx_work, helium%worm_bead_idx_work)
    2528        2032 :          snew = snew + 0.5_dp*newheadpot + oldtailpot
    2529             :       END IF
    2530             : 
    2531             :       ! Metropolis:
    2532             :       ! action difference
    2533        2066 :       sdiff = sold - snew
    2534             :       ! modify action difference due to extra bead
    2535        2066 :       IF (sdiff < 0) THEN
    2536        1097 :          should_reject = .FALSE.
    2537        1097 :          IF (sdiff < -100.0_dp) THEN ! To protect from exponential underflow
    2538             :             should_reject = .TRUE.
    2539             :          ELSE
    2540        1096 :             rtmp = helium%rng_stream_uniform%next()
    2541        1096 :             IF (EXP(sdiff) < rtmp) THEN
    2542             :                should_reject = .TRUE.
    2543             :             END IF
    2544             :          END IF
    2545             :          IF (should_reject) THEN
    2546             :             ! rejected !
    2547             :             ! write back only changed atoms
    2548             :             ! transfer the new coordinates to work array
    2549          83 :             IF (helium%worm_bead_idx_work < helium%worm_bead_idx) THEN
    2550             :                ! everything belongs to the same atom
    2551         316 :                DO kbead = helium%worm_bead_idx_work, helium%worm_bead_idx - 1
    2552        1066 :                   helium%work(:, helium%worm_atom_idx, kbead) = helium%pos(:, helium%worm_atom_idx, kbead)
    2553             :                END DO
    2554             :             ELSE
    2555             :                ! is distributed among two atoms
    2556             :                ! transfer to atom not containing the tail bead
    2557          50 :                DO kbead = helium%worm_bead_idx_work, helium%beads
    2558         149 :                   helium%work(:, helium%worm_atom_idx_work, kbead) = helium%pos(:, helium%worm_atom_idx_work, kbead)
    2559             :                END DO
    2560             :                ! transfer to atom containing the tail bead
    2561          55 :                DO kbead = 1, helium%worm_bead_idx - 1
    2562         169 :                   helium%work(:, helium%worm_atom_idx, kbead) = helium%pos(:, helium%worm_atom_idx, kbead)
    2563             :                END DO
    2564             :             END IF
    2565         332 :             helium%worm_xtra_bead_work(:) = helium%worm_xtra_bead(:)
    2566          83 :             helium%worm_bead_idx_work = helium%worm_bead_idx
    2567          83 :             helium%worm_atom_idx_work = helium%worm_atom_idx
    2568          83 :             ac = 0
    2569         145 :             RETURN
    2570             :          END IF
    2571             :       END IF
    2572             : 
    2573             :       ! for now accepted
    2574             :       ! rejection of the whole move if any centroid is farther away
    2575             :       ! from the current center of gravity than HELIUM%DROPLET_RADIUS [lwalewski]
    2576             :       ! AND ist not moving towards the center
    2577        1983 :       IF (.NOT. helium%periodic) THEN
    2578        1969 :          IF (helium%solute_present) THEN
    2579        7876 :             new_com(:) = helium%center(:)
    2580        1969 :             old_com(:) = new_com(:)
    2581             :          ELSE
    2582           0 :             new_com(:) = 0.0_dp
    2583           0 :             DO ia = 1, helium%atoms
    2584           0 :                DO ib = 1, helium%beads
    2585           0 :                   new_com(:) = new_com(:) + helium%work(:, ia, ib)
    2586             :                END DO
    2587             :             END DO
    2588           0 :             new_com(:) = new_com(:)/(REAL(helium%atoms*helium%beads, dp))
    2589             :             ! also compute the old center of mass (optimization potential)
    2590           0 :             old_com(:) = 0.0_dp
    2591           0 :             DO ia = 1, helium%atoms
    2592           0 :                DO ib = 1, helium%beads
    2593           0 :                   old_com(:) = old_com(:) + helium%pos(:, ia, ib)
    2594             :                END DO
    2595             :             END DO
    2596           0 :             old_com(:) = old_com(:)/(REAL(helium%atoms*helium%beads, dp))
    2597             :          END IF
    2598        1969 :          should_reject = .FALSE.
    2599       58726 :          atom: DO ia = 1, helium%atoms
    2600       56819 :             dr(:) = 0.0_dp
    2601      965923 :             DO ib = 1, helium%beads
    2602     3693235 :                dr(:) = dr(:) + helium%work(:, ia, ib) - new_com(:)
    2603             :             END DO
    2604      227276 :             dr(:) = dr(:)/REAL(helium%beads, dp)
    2605      227276 :             rtmp = DOT_PRODUCT(dr, dr)
    2606       58726 :             IF (rtmp >= helium%droplet_radius**2) THEN
    2607          62 :                dro(:) = 0.0_dp
    2608        1054 :                DO ib = 1, helium%beads
    2609        4030 :                   dro(:) = dro(:) + helium%pos(:, ia, ib) - old_com(:)
    2610             :                END DO
    2611         248 :                dro(:) = dro(:)/REAL(helium%beads, dp)
    2612         248 :                rtmpo = DOT_PRODUCT(dro, dro)
    2613             :                ! only reject if it moves away from COM outside the droplet radius
    2614          62 :                IF (rtmpo < rtmp) THEN
    2615             :                   ! found - this one does not fit within R from the center
    2616             :                   should_reject = .TRUE.
    2617             :                   EXIT atom
    2618             :                END IF
    2619             :             END IF
    2620             :          END DO atom
    2621        1969 :          IF (should_reject) THEN
    2622             :             ! restore original coordinates
    2623             :             ! write back only changed atoms
    2624             :             ! write back only changed atoms
    2625             :             ! transfer the new coordinates to work array
    2626          62 :             IF (helium%worm_bead_idx_work < helium%worm_bead_idx) THEN
    2627             :                ! everything belongs to the same atom
    2628         282 :                DO kbead = helium%worm_bead_idx_work, helium%worm_bead_idx - 1
    2629         948 :                   helium%work(:, helium%worm_atom_idx, kbead) = helium%pos(:, helium%worm_atom_idx, kbead)
    2630             :                END DO
    2631             :             ELSE
    2632             :                ! is distributed among two atoms
    2633             :                ! transfer to atom not containing the tail bead
    2634           7 :                DO kbead = helium%worm_bead_idx_work, helium%beads
    2635          22 :                   helium%work(:, helium%worm_atom_idx_work, kbead) = helium%pos(:, helium%worm_atom_idx_work, kbead)
    2636             :                END DO
    2637             :                ! transfer to atom containing the tail bead
    2638           2 :                DO kbead = 1, helium%worm_bead_idx - 1
    2639           2 :                   helium%work(:, helium%worm_atom_idx, kbead) = helium%pos(:, helium%worm_atom_idx, kbead)
    2640             :                END DO
    2641             :             END IF
    2642         248 :             helium%worm_xtra_bead_work(:) = helium%worm_xtra_bead(:)
    2643          62 :             helium%worm_bead_idx_work = helium%worm_bead_idx
    2644          62 :             helium%worm_atom_idx_work = helium%worm_atom_idx
    2645          62 :             ac = 0
    2646          62 :             RETURN
    2647             :          END IF
    2648             :       END IF
    2649             : 
    2650             :       ! finally accepted
    2651        1921 :       ac = 1
    2652             :       ! write changed coordinates to position array
    2653             :       ! write back only changed atoms
    2654        1921 :       IF (helium%worm_bead_idx_work < helium%worm_bead_idx) THEN
    2655             :          ! everything belongs to the same atom
    2656        6599 :          DO kbead = helium%worm_bead_idx_work, helium%worm_bead_idx - 1
    2657       21917 :             helium%pos(:, helium%worm_atom_idx, kbead) = helium%work(:, helium%worm_atom_idx, kbead)
    2658             :          END DO
    2659             :       ELSE
    2660             :          ! is distributed among two atoms
    2661             :          ! transfer to atom not containing the tail bead
    2662        1465 :          DO kbead = helium%worm_bead_idx_work, helium%beads
    2663        4576 :             helium%pos(:, helium%worm_atom_idx_work, kbead) = helium%work(:, helium%worm_atom_idx_work, kbead)
    2664             :          END DO
    2665             :          ! transfer to atom containing the tail bead
    2666        1035 :          DO kbead = 1, helium%worm_bead_idx - 1
    2667        2856 :             helium%pos(:, helium%worm_atom_idx, kbead) = helium%work(:, helium%worm_atom_idx, kbead)
    2668             :          END DO
    2669             :       END IF
    2670        7684 :       helium%worm_xtra_bead(:) = helium%worm_xtra_bead_work(:)
    2671        1921 :       helium%worm_bead_idx = helium%worm_bead_idx_work
    2672        1921 :       helium%worm_atom_idx = helium%worm_atom_idx_work
    2673             : 
    2674             :    END SUBROUTINE worm_crawl_move_backward
    2675             : 
    2676             : ! **************************************************************************************************
    2677             : !> \brief Free particle density matrix
    2678             : !> \param helium ...
    2679             : !> \param startpos ...
    2680             : !> \param endpos ...
    2681             : !> \param l ...
    2682             : !> \return ...
    2683             : !> \author fuhl
    2684             : ! **************************************************************************************************
    2685      596992 :    REAL(KIND=dp) FUNCTION free_density_matrix(helium, startpos, endpos, l) RESULT(rho)
    2686             : 
    2687             :       TYPE(helium_solvent_type), INTENT(IN)              :: helium
    2688             :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: startpos, endpos
    2689             :       INTEGER, INTENT(IN)                                :: l
    2690             : 
    2691             :       REAL(KIND=dp)                                      :: distsq, prefac
    2692             :       REAL(KIND=dp), DIMENSION(3)                        :: dvec
    2693             : 
    2694     2387968 :       dvec(:) = startpos(:) - endpos(:)
    2695      596992 :       CALL helium_pbc(helium, dvec)
    2696     2387968 :       distsq = DOT_PRODUCT(dvec, dvec)
    2697             : 
    2698      596992 :       prefac = 0.5_dp/(helium%hb2m*REAL(l, dp)*helium%tau)
    2699      596992 :       rho = -prefac*distsq
    2700      596992 :       rho = EXP(rho)
    2701      596992 :       rho = rho*(SQRT(prefac/pi))**3
    2702             : 
    2703      596992 :    END FUNCTION free_density_matrix
    2704             : 
    2705             : ! **************************************************************************************************
    2706             : !> \brief Swap move in open state to change permutation state
    2707             : !> \param pint_env ...
    2708             : !> \param helium ...
    2709             : !> \param natoms ...
    2710             : !> \param l ...
    2711             : !> \param ac ...
    2712             : !> \author fuhl
    2713             : ! **************************************************************************************************
    2714       10448 :    SUBROUTINE worm_swap_move(pint_env, helium, natoms, l, ac)
    2715             : 
    2716             :       TYPE(pint_env_type), INTENT(IN)                    :: pint_env
    2717             :       TYPE(helium_solvent_type), INTENT(INOUT)           :: helium
    2718             :       INTEGER, INTENT(IN)                                :: natoms, l
    2719             :       INTEGER, INTENT(OUT)                               :: ac
    2720             : 
    2721             :       INTEGER                                            :: bendatom, bstartatom, endbead, &
    2722             :                                                             excludeatom, fendatom, fstartatom, ia, &
    2723             :                                                             iatom, ib, ibead, jbead, kbead, &
    2724             :                                                             startbead, tmpi
    2725             :       LOGICAL                                            :: should_reject
    2726             :       REAL(KIND=dp)                                      :: backwarddensmatsum, forwarddensmatsum, &
    2727             :                                                             mass, newheadpotential, &
    2728             :                                                             oldheadpotential, rtmp, rtmpo, sdiff, &
    2729             :                                                             snew, sold
    2730             :       REAL(KIND=dp), DIMENSION(3)                        :: dr, dro, new_com, old_com
    2731       20896 :       REAL(KIND=dp), DIMENSION(3, l)                     :: newsection
    2732       10448 :       REAL(KIND=dp), DIMENSION(natoms)                   :: backwarddensmat, forwarddensmat
    2733             : 
    2734             :       ! first the endbead of the reconstruction is needed
    2735       10448 :       startbead = helium%worm_bead_idx
    2736       10448 :       endbead = helium%worm_bead_idx + l + 1
    2737       10448 :       fstartatom = helium%worm_atom_idx
    2738       10448 :       excludeatom = fstartatom
    2739             :       ! compute the atomwise probabilities to be the worms swap partner
    2740             :       ! Check if the imaginary time section belongs to two atoms
    2741       10448 :       IF (endbead > helium%beads) THEN
    2742        2777 :          endbead = endbead - helium%beads
    2743             :          ! exclude atom is the one not to connect to because it will result in an unnatural state
    2744        2777 :          excludeatom = helium%permutation(excludeatom)
    2745             :       END IF
    2746      155451 :       DO iatom = 1, excludeatom - 1
    2747             :          forwarddensmat(iatom) = free_density_matrix(helium, helium%worm_xtra_bead(:), &
    2748      155451 :                                                      helium%pos(:, iatom, endbead), l + 1)
    2749             :       END DO
    2750       10448 :       forwarddensmat(excludeatom) = 0.0_dp
    2751      163941 :       DO iatom = excludeatom + 1, natoms
    2752             :          forwarddensmat(iatom) = free_density_matrix(helium, helium%worm_xtra_bead(:), &
    2753      163941 :                                                      helium%pos(:, iatom, endbead), l + 1)
    2754             :       END DO
    2755      319392 :       forwarddensmatsum = SUM(forwarddensmat)
    2756       10448 :       IF (forwarddensmatsum == 0.0_dp) THEN
    2757           0 :          ac = 0
    2758           0 :          RETURN
    2759             :       END IF
    2760             : 
    2761             :       ! Select an atom with its corresponding probability
    2762       10448 :       rtmp = helium%rng_stream_uniform%next()*forwarddensmatsum
    2763       10448 :       fendatom = 1
    2764      167857 :       DO WHILE (rtmp >= forwarddensmat(fendatom))
    2765      157409 :          rtmp = rtmp - forwarddensmat(fendatom)
    2766      157409 :          fendatom = fendatom + 1
    2767             :       END DO
    2768             :       ! just for numerical safety
    2769       10448 :       fendatom = MIN(fendatom, natoms)
    2770       10448 :       IF (fendatom == excludeatom) THEN
    2771           0 :          ac = 0
    2772           0 :          RETURN
    2773             :       END IF
    2774             : 
    2775             :       ! ensure detailed balance
    2776       10448 :       IF (endbead > startbead) THEN
    2777        7671 :          bstartatom = fendatom
    2778             :       ELSE
    2779        2777 :          bstartatom = helium%iperm(fendatom)
    2780             :       END IF
    2781             :       bendatom = fendatom
    2782             : 
    2783      155451 :       DO iatom = 1, excludeatom - 1
    2784             :          backwarddensmat(iatom) = free_density_matrix(helium, &
    2785             :                                                       helium%pos(:, bstartatom, startbead), &
    2786      155451 :                                                       helium%pos(:, iatom, endbead), l + 1)
    2787             :       END DO
    2788       10448 :       backwarddensmat(excludeatom) = 0.0_dp
    2789      163941 :       DO iatom = excludeatom + 1, natoms
    2790             :          backwarddensmat(iatom) = free_density_matrix(helium, &
    2791             :                                                       helium%pos(:, bstartatom, startbead), &
    2792      163941 :                                                       helium%pos(:, iatom, endbead), l + 1)
    2793             :       END DO
    2794             : 
    2795      319392 :       backwarddensmatsum = SUM(backwarddensmat)
    2796             : 
    2797       10448 :       mass = helium%he_mass_au
    2798             : 
    2799             :       !compute action before the move
    2800             :       sold = worm_path_action(helium, helium%pos, &
    2801       10448 :                               bstartatom, startbead, fendatom, endbead)
    2802             : 
    2803       10448 :       IF (helium%solute_present) THEN
    2804             :          ! no special head treatment needed, as it will change due to swapping
    2805             :          ! the worm gap and due to primitive coupling no cross bead terms are considered
    2806             :          sold = sold + worm_path_inter_action(pint_env, helium, helium%pos, &
    2807       10268 :                                               bstartatom, startbead, fendatom, endbead)
    2808             :          ! compute potential of old and new head here (only once, as later only a rescaling is necessary)
    2809             :          CALL helium_bead_solute_e_f(pint_env, helium, &
    2810             :                                      fstartatom, startbead, helium%worm_xtra_bead, &
    2811       10268 :                                      energy=oldheadpotential)
    2812       10268 :          oldheadpotential = oldheadpotential*helium%tau
    2813             : 
    2814             :          CALL helium_bead_solute_e_f(pint_env, helium, &
    2815             :                                      bstartatom, startbead, helium%pos(:, bstartatom, startbead), &
    2816       10268 :                                      energy=newheadpotential)
    2817       10268 :          newheadpotential = newheadpotential*helium%tau
    2818             : 
    2819       10268 :          sold = sold + 0.5_dp*oldheadpotential + newheadpotential
    2820             :       END IF
    2821             : 
    2822             :       ! construct a new path connecting the start and endbead
    2823             :       ! need to be the old coordinates due to reordering of the work coordinates
    2824             :       CALL path_construct(helium, &
    2825             :                           helium%worm_xtra_bead(:), &
    2826             :                           helium%pos(:, fendatom, endbead), l, &
    2827       10448 :                           newsection)
    2828             : 
    2829             :       !write new path segment to work array
    2830             :       !first the part that is guaranteed to fit on the coorinates of startatom of the
    2831       10448 :       jbead = 1
    2832       10448 :       IF (startbead < endbead) THEN
    2833             :          ! everything belongs to the same atom
    2834       33777 :          DO kbead = startbead + 1, endbead - 1
    2835      104424 :             helium%work(:, fstartatom, kbead) = newsection(:, jbead)
    2836       33777 :             jbead = jbead + 1
    2837             :          END DO
    2838             :       ELSE
    2839             :          ! is distributed among two atoms
    2840             :          ! transfer to atom not containing the head bead
    2841        7977 :          DO kbead = startbead + 1, helium%beads
    2842       20800 :             helium%work(:, fstartatom, kbead) = newsection(:, jbead)
    2843        7977 :             jbead = jbead + 1
    2844             :          END DO
    2845             :          ! rest to the second atom
    2846        8017 :          DO ibead = 1, endbead - 1
    2847       20960 :             helium%work(:, fendatom, ibead) = newsection(:, jbead)
    2848        8017 :             jbead = jbead + 1
    2849             :          END DO
    2850             :       END IF
    2851             : 
    2852             :       !exchange coordinates head coordinate first
    2853       41792 :       helium%work(:, helium%worm_atom_idx, helium%worm_bead_idx) = helium%worm_xtra_bead(:)
    2854       41792 :       helium%worm_xtra_bead_work(:) = helium%pos(:, bstartatom, startbead)
    2855             : 
    2856             :       ! move coordinates from former worm atom tail to new worm atom tail
    2857      102032 :       DO ib = startbead, helium%beads
    2858      376784 :          helium%work(:, bstartatom, ib) = helium%pos(:, fstartatom, ib)
    2859             :       END DO
    2860             :       ! need to copy the rest of pselatom to former worm atom
    2861       10448 :       IF (endbead > startbead) THEN
    2862       57501 :          DO ib = endbead, helium%beads
    2863      206991 :             helium%work(:, fstartatom, ib) = helium%pos(:, bstartatom, ib)
    2864             :          END DO
    2865             :       END IF
    2866             : 
    2867             :       !update permtable
    2868       10448 :       tmpi = helium%permutation(bstartatom)
    2869       10448 :       helium%permutation(bstartatom) = helium%permutation(fstartatom)
    2870       10448 :       helium%permutation(fstartatom) = tmpi
    2871             :       !update inverse permtable
    2872      319392 :       DO ib = 1, SIZE(helium%permutation)
    2873      319392 :          helium%iperm(helium%permutation(ib)) = ib
    2874             :       END DO
    2875       10448 :       helium%worm_atom_idx_work = bstartatom
    2876             :       ! action after the move
    2877             : 
    2878       10448 :       IF (endbead > startbead) THEN
    2879             :          snew = worm_path_action(helium, helium%work, &
    2880        7671 :                                  fstartatom, startbead, fstartatom, endbead)
    2881        7671 :          IF (helium%solute_present) THEN
    2882             :             ! no special head treatment needed, because a swap can't go over
    2883             :             ! the worm gap and due to primitive coupling no cross bead terms are considered
    2884             :             snew = snew + worm_path_inter_action(pint_env, helium, helium%work, &
    2885        7577 :                                                  fstartatom, startbead, fstartatom, endbead)
    2886             : 
    2887             :             ! add the previously computed old and new head actions
    2888        7577 :             snew = snew + oldheadpotential + 0.5_dp*newheadpotential
    2889             :          END IF
    2890             :       ELSE
    2891             :          snew = worm_path_action(helium, helium%work, &
    2892        2777 :                                  fstartatom, startbead, helium%permutation(fstartatom), endbead)
    2893        2777 :          IF (helium%solute_present) THEN
    2894             :             ! no special head treatment needed, because a swap can't go over
    2895             :             ! the worm gap and due to primitive coupling no cross bead terms are considered
    2896             :             snew = snew + worm_path_inter_action(pint_env, helium, helium%work, &
    2897        2691 :                                                  fstartatom, startbead, helium%permutation(fstartatom), endbead)
    2898             : 
    2899             :             ! add the previously computed old and new head actions
    2900        2691 :             snew = snew + oldheadpotential + 0.5_dp*newheadpotential
    2901             :          END IF
    2902             :       END IF
    2903             : 
    2904             :       ! Metropolis:
    2905       10448 :       sdiff = sold - snew
    2906       10448 :       sdiff = sdiff + LOG(forwarddensmatsum/backwarddensmatsum)
    2907       10448 :       IF (sdiff < 0) THEN
    2908       10424 :          should_reject = .FALSE.
    2909       10424 :          IF (sdiff < -100.0_dp) THEN ! To protect from exponential underflow
    2910             :             should_reject = .TRUE.
    2911             :          ELSE
    2912        4792 :             rtmp = helium%rng_stream_uniform%next()
    2913        4792 :             IF (EXP(sdiff) < rtmp) THEN
    2914             :                should_reject = .TRUE.
    2915             :             END IF
    2916             :          END IF
    2917             :          IF (should_reject) THEN
    2918             :             ! rejected !
    2919             :             ! write back only changed atoms
    2920      101550 :             DO kbead = startbead, helium%beads
    2921      374970 :                helium%work(:, bstartatom, kbead) = helium%pos(:, bstartatom, kbead)
    2922             :             END DO
    2923      101550 :             DO kbead = startbead, helium%beads
    2924      374970 :                helium%work(:, fstartatom, kbead) = helium%pos(:, fstartatom, kbead)
    2925             :             END DO
    2926       41640 :             helium%worm_xtra_bead_work(:) = helium%worm_xtra_bead(:)
    2927       10410 :             helium%worm_atom_idx_work = helium%worm_atom_idx
    2928       10410 :             IF (startbead > endbead) THEN
    2929       10794 :                DO kbead = 1, endbead
    2930       34845 :                   helium%work(:, fendatom, kbead) = helium%pos(:, fendatom, kbead)
    2931             :                END DO
    2932             :             END IF
    2933             :             ! reset permtable
    2934       10410 :             tmpi = helium%permutation(bstartatom)
    2935       10410 :             helium%permutation(bstartatom) = helium%permutation(fstartatom)
    2936       10410 :             helium%permutation(fstartatom) = tmpi
    2937             :             !update inverse permtable
    2938      318138 :             DO ib = 1, SIZE(helium%permutation)
    2939      318138 :                helium%iperm(helium%permutation(ib)) = ib
    2940             :             END DO
    2941       10410 :             ac = 0
    2942       10410 :             RETURN
    2943             :          END IF
    2944             :       END IF
    2945             : 
    2946             :       ! for now accepted
    2947             :       ! rejection of the whole move if any centroid is farther away
    2948             :       ! from the current center of gravity than HELIUM%DROPLET_RADIUS [lwalewski]
    2949             :       ! AND ist not moving towards the center
    2950          38 :       IF (.NOT. helium%periodic) THEN
    2951          38 :          IF (helium%solute_present) THEN
    2952         152 :             new_com(:) = helium%center(:)
    2953          38 :             old_com(:) = new_com(:)
    2954             :          ELSE
    2955           0 :             new_com(:) = 0.0_dp
    2956           0 :             DO ia = 1, helium%atoms
    2957           0 :                DO ib = 1, helium%beads
    2958           0 :                   new_com(:) = new_com(:) + helium%work(:, ia, ib)
    2959             :                END DO
    2960             :             END DO
    2961           0 :             new_com(:) = new_com(:)/(REAL(helium%atoms*helium%beads, dp))
    2962             :             ! also compute the old center of mass (optimization potential)
    2963           0 :             old_com(:) = 0.0_dp
    2964           0 :             DO ia = 1, helium%atoms
    2965           0 :                DO ib = 1, helium%beads
    2966           0 :                   old_com(:) = old_com(:) + helium%pos(:, ia, ib)
    2967             :                END DO
    2968             :             END DO
    2969           0 :             old_com(:) = old_com(:)/(REAL(helium%atoms*helium%beads, dp))
    2970             :          END IF
    2971          38 :          should_reject = .FALSE.
    2972        1074 :          atom: DO ia = 1, helium%atoms
    2973        1066 :             dr(:) = 0.0_dp
    2974       18122 :             DO ib = 1, helium%beads
    2975       69290 :                dr(:) = dr(:) + helium%work(:, ia, ib) - new_com(:)
    2976             :             END DO
    2977        4264 :             dr(:) = dr(:)/REAL(helium%beads, dp)
    2978        4264 :             rtmp = DOT_PRODUCT(dr, dr)
    2979        1074 :             IF (rtmp >= helium%droplet_radius**2) THEN
    2980          30 :                dro(:) = 0.0_dp
    2981         510 :                DO ib = 1, helium%beads
    2982        1950 :                   dro(:) = dro(:) + helium%pos(:, ia, ib) - old_com(:)
    2983             :                END DO
    2984         120 :                dro(:) = dro(:)/REAL(helium%beads, dp)
    2985         120 :                rtmpo = DOT_PRODUCT(dro, dro)
    2986             :                ! only reject if it moves away from COM outside the droplet radius
    2987          30 :                IF (rtmpo < rtmp) THEN
    2988             :                   ! found - this one does not fit within R from the center
    2989             :                   should_reject = .TRUE.
    2990             :                   EXIT atom
    2991             :                END IF
    2992             :             END IF
    2993             :          END DO atom
    2994          38 :          IF (should_reject) THEN
    2995             :             ! write back only changed atoms
    2996         380 :             DO kbead = startbead, helium%beads
    2997        1430 :                helium%work(:, bstartatom, kbead) = helium%pos(:, bstartatom, kbead)
    2998             :             END DO
    2999         380 :             DO kbead = startbead, helium%beads
    3000        1430 :                helium%work(:, fstartatom, kbead) = helium%pos(:, fstartatom, kbead)
    3001             :             END DO
    3002         120 :             helium%worm_xtra_bead_work(:) = helium%worm_xtra_bead(:)
    3003          30 :             helium%worm_atom_idx_work = helium%worm_atom_idx
    3004          30 :             IF (startbead > endbead) THEN
    3005           0 :                DO kbead = 1, endbead
    3006           0 :                   helium%work(:, fendatom, kbead) = helium%pos(:, fendatom, kbead)
    3007             :                END DO
    3008             :             END IF
    3009             : 
    3010             :             ! reset permtable
    3011          30 :             tmpi = helium%permutation(bstartatom)
    3012          30 :             helium%permutation(bstartatom) = helium%permutation(fstartatom)
    3013          30 :             helium%permutation(fstartatom) = tmpi
    3014             :             !update inverse permtable
    3015         990 :             DO ib = 1, SIZE(helium%permutation)
    3016         990 :                helium%iperm(helium%permutation(ib)) = ib
    3017             :             END DO
    3018          30 :             ac = 0
    3019          30 :             RETURN
    3020             :          END IF
    3021             :       END IF
    3022             : 
    3023             :       ! finally accepted
    3024           8 :       ac = 1
    3025         102 :       DO kbead = startbead, helium%beads
    3026         384 :          helium%pos(:, bstartatom, kbead) = helium%work(:, bstartatom, kbead)
    3027             :       END DO
    3028         102 :       DO kbead = startbead, helium%beads
    3029         384 :          helium%pos(:, fstartatom, kbead) = helium%work(:, fstartatom, kbead)
    3030             :       END DO
    3031          32 :       helium%worm_xtra_bead(:) = helium%worm_xtra_bead_work(:)
    3032           8 :       helium%worm_atom_idx = helium%worm_atom_idx_work
    3033           8 :       IF (startbead > endbead) THEN
    3034           0 :          DO kbead = 1, endbead
    3035           0 :             helium%pos(:, fendatom, kbead) = helium%work(:, fendatom, kbead)
    3036             :          END DO
    3037             :       END IF
    3038             : 
    3039             :    END SUBROUTINE worm_swap_move
    3040             : 
    3041             : ! **************************************************************************************************
    3042             : !> \brief Action along path
    3043             : !> \param helium ...
    3044             : !> \param pos ...
    3045             : !> \param startatom ...
    3046             : !> \param startbead ...
    3047             : !> \param endatom ...
    3048             : !> \param endbead ...
    3049             : !> \return ...
    3050             : !> \author fuhl
    3051             : ! **************************************************************************************************
    3052       42167 :    REAL(KIND=dp) FUNCTION worm_path_action(helium, pos, &
    3053             :                                            startatom, startbead, endatom, endbead) RESULT(partaction)
    3054             : 
    3055             :       TYPE(helium_solvent_type), INTENT(INOUT)           :: helium
    3056             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN), &
    3057             :          POINTER                                         :: pos
    3058             :       INTEGER, INTENT(IN)                                :: startatom, startbead, endatom, endbead
    3059             : 
    3060             :       INTEGER                                            :: iatom, ibead
    3061       42167 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: work2, work3
    3062       42167 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: work
    3063             : 
    3064      295169 :       ALLOCATE (work(3, helium%beads + 1), work2(helium%beads + 1), work3(SIZE(helium%uoffdiag, 1) + 1))
    3065       42167 :       partaction = 0.0_dp
    3066             :       ! do action in two ways, depending
    3067             :       ! if coordinates are not wrapping
    3068       42167 :       IF (startbead < endbead) THEN
    3069             :          ! helium pair action
    3070             :          ! every atom, with the one (or two) who got a resampling
    3071      945045 :          DO iatom = 1, helium%atoms
    3072             :             ! avoid self interaction
    3073      913844 :             IF (iatom == startatom) CYCLE
    3074             :             ! first the section up to the worm gap
    3075             :             ! two less, because we need to work on the worm intersection separately
    3076     5452076 :             DO ibead = startbead, endbead
    3077    19160375 :                work(:, ibead + 1 - startbead) = pos(:, iatom, ibead) - pos(:, startatom, ibead)
    3078             :             END DO
    3079      945045 :             partaction = partaction + helium_eval_chain(helium, work, endbead - startbead + 1, work2, work3)
    3080             :          END DO
    3081             :       ELSE !(startbead > endbead)
    3082             :          ! helium pair action
    3083             :          ! every atom, with the one (or two) who got a resampling
    3084      329106 :          DO iatom = 1, helium%atoms
    3085             :             ! avoid self interaction
    3086      318140 :             IF (iatom == startatom) CYCLE
    3087             :             ! first the section up to the worm gap
    3088             :             ! two less, because we need to work on the worm intersection separately
    3089     1171913 :             DO ibead = startbead, helium%beads
    3090     3766130 :                work(:, ibead + 1 - startbead) = pos(:, iatom, ibead) - pos(:, startatom, ibead)
    3091             :             END DO
    3092             :             ! wrapping bond
    3093     1228696 :             work(:, helium%beads + 2 - startbead) = pos(:, helium%permutation(iatom), 1) - pos(:, endatom, 1)
    3094      329106 :             partaction = partaction + helium_eval_chain(helium, work, helium%beads - startbead + 2, work2, work3)
    3095             :          END DO
    3096             : 
    3097             :          ! ending atom
    3098      329106 :          DO iatom = 1, helium%atoms
    3099             :             ! avoid self interaction
    3100      318140 :             IF (iatom == endatom) CYCLE
    3101             :             !from first to endbead
    3102      318140 :             IF (endbead > 1) THEN
    3103     1021303 :                DO ibead = 1, endbead
    3104     3377137 :                   work(:, ibead) = pos(:, iatom, ibead) - pos(:, endatom, ibead)
    3105             :                END DO
    3106      236025 :                partaction = partaction + helium_eval_chain(helium, work, endbead, work2, work3)
    3107             :             END IF
    3108             :          END DO
    3109             : 
    3110             :       END IF
    3111       42167 :       DEALLOCATE (work, work2, work3)
    3112             : 
    3113       42167 :    END FUNCTION worm_path_action
    3114             : 
    3115             : ! **************************************************************************************************
    3116             : !> \brief Corrected path action for worm
    3117             : !> \param helium ...
    3118             : !> \param pos ...
    3119             : !> \param startatom ...
    3120             : !> \param startbead ...
    3121             : !> \param endatom ...
    3122             : !> \param endbead ...
    3123             : !> \param xtrapos ...
    3124             : !> \param worm_atom_idx ...
    3125             : !> \param worm_bead_idx ...
    3126             : !> \return ...
    3127             : !> \author fuhl
    3128             : ! **************************************************************************************************
    3129        9479 :    REAL(KIND=dp) FUNCTION worm_path_action_worm_corrected(helium, pos, &
    3130             :                                    startatom, startbead, endatom, endbead, xtrapos, worm_atom_idx, worm_bead_idx) RESULT(partaction)
    3131             : 
    3132             :       TYPE(helium_solvent_type), INTENT(INOUT)           :: helium
    3133             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN), &
    3134             :          POINTER                                         :: pos
    3135             :       INTEGER, INTENT(IN)                                :: startatom, startbead, endatom, endbead
    3136             :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: xtrapos
    3137             :       INTEGER, INTENT(IN)                                :: worm_atom_idx, worm_bead_idx
    3138             : 
    3139             :       INTEGER                                            :: iatom, ibead
    3140        9479 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: work2, work3
    3141        9479 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: work
    3142             :       REAL(KIND=dp), DIMENSION(3)                        :: r, rp
    3143             : 
    3144       66353 :       ALLOCATE (work(3, helium%beads + 1), work2(helium%beads + 1), work3(SIZE(helium%uoffdiag, 1) + 1))
    3145        9479 :       partaction = 0.0_dp
    3146             :       ! do action in two ways, depending
    3147             :       ! if coordinates are not wrapping
    3148        9479 :       IF (startbead < endbead) THEN
    3149             :          ! helium pair action
    3150             :          ! every atom, with the one (or two) who got a resampling
    3151      222417 :          DO iatom = 1, helium%atoms
    3152             :             ! avoid self interaction
    3153      215124 :             IF (iatom == startatom) CYCLE
    3154             :             ! first the section up to the worm gap
    3155             :             ! two less, because we need to work on the worm intersection separately
    3156      207831 :             IF (worm_bead_idx - startbead > 1) THEN
    3157      906831 :                DO ibead = startbead, worm_bead_idx - 1
    3158     3013527 :                   work(:, ibead + 1 - startbead) = pos(:, iatom, ibead) - pos(:, startatom, ibead)
    3159             :                END DO
    3160      204599 :                partaction = partaction + helium_eval_chain(helium, work, worm_bead_idx - startbead, work2, work3)
    3161             :             END IF
    3162             : 
    3163      215124 :             IF (endbead > worm_bead_idx) THEN
    3164       44200 :                DO ibead = worm_bead_idx, endbead
    3165      146452 :                   work(:, ibead + 1 - worm_bead_idx) = pos(:, iatom, ibead) - pos(:, startatom, ibead)
    3166             :                END DO
    3167       10116 :                partaction = partaction + helium_eval_chain(helium, work, endbead - worm_bead_idx + 1, work2, work3)
    3168             :             END IF
    3169             :          END DO
    3170             : 
    3171        7293 :          IF (worm_atom_idx /= startatom) THEN
    3172       13572 :             DO iatom = 1, helium%atoms
    3173       13136 :                IF (iatom == startatom) CYCLE
    3174       12700 :                IF (iatom == worm_atom_idx) CYCLE
    3175       49056 :                r(:) = pos(:, iatom, worm_bead_idx - 1) - pos(:, startatom, worm_bead_idx - 1)
    3176       49056 :                rp(:) = pos(:, iatom, worm_bead_idx) - pos(:, startatom, worm_bead_idx)
    3177       13572 :                partaction = partaction + helium_eval_expansion(helium, r, rp, work3)
    3178             :             END DO
    3179             :             ! add pair action with worm
    3180        1744 :             r(:) = pos(:, startatom, worm_bead_idx - 1) - pos(:, worm_atom_idx, worm_bead_idx - 1)
    3181        1744 :             rp(:) = pos(:, startatom, worm_bead_idx) - xtrapos(:)
    3182         436 :             partaction = partaction + helium_eval_expansion(helium, r, rp, work3)
    3183             :          ELSE
    3184             :             ! worm intersection
    3185      208845 :             DO iatom = 1, helium%atoms
    3186      201988 :                IF (iatom == startatom) CYCLE
    3187      780524 :                r(:) = pos(:, iatom, worm_bead_idx - 1) - pos(:, startatom, worm_bead_idx - 1)
    3188      780524 :                rp(:) = pos(:, iatom, worm_bead_idx) - xtrapos(:)
    3189      208845 :                partaction = partaction + helium_eval_expansion(helium, r, rp, work3)
    3190             :             END DO
    3191             :          END IF
    3192             :       ELSE !(startbead > endbead)
    3193             :          ! section wraps around the atom
    3194             :          ! two cases: worm gap is before or after wrap
    3195        2186 :          IF (worm_bead_idx > startbead) THEN
    3196             :             ! action terms up to worm gap on starting atom
    3197        1656 :             DO iatom = 1, helium%atoms
    3198             :                ! avoid self interaction
    3199        1600 :                IF (iatom == startatom) CYCLE
    3200             :                ! first the section up to the worm gap
    3201             :                ! two less, because we need to work on the worm intersection separately
    3202        1544 :                IF (worm_bead_idx - startbead > 1) THEN
    3203        2450 :                   DO ibead = startbead, worm_bead_idx - 1
    3204        7598 :                      work(:, ibead + 1 - startbead) = pos(:, iatom, ibead) - pos(:, startatom, ibead)
    3205             :                   END DO
    3206         734 :                   partaction = partaction + helium_eval_chain(helium, work, worm_bead_idx - startbead, work2, work3)
    3207             :                END IF
    3208             : 
    3209             :                ! up to the wrapping border
    3210        4374 :                DO ibead = worm_bead_idx, helium%beads
    3211       12864 :                   work(:, ibead + 1 - worm_bead_idx) = pos(:, iatom, ibead) - pos(:, startatom, ibead)
    3212             :                END DO
    3213             :                ! wrapping bond
    3214             :                work(:, helium%beads - worm_bead_idx + 2) = pos(:, helium%permutation(iatom), 1) - &
    3215        6176 :                                                            pos(:, helium%permutation(startatom), 1)
    3216        1656 :                partaction = partaction + helium_eval_chain(helium, work, helium%beads - worm_bead_idx + 2, work2, work3)
    3217             : 
    3218             :             END DO
    3219             : 
    3220             :             ! ending atom
    3221        1656 :             DO iatom = 1, helium%atoms
    3222             :                ! avoid self interaction
    3223        1600 :                IF (iatom == endatom) CYCLE
    3224             :                !from first to endbead
    3225        1600 :                IF (endbead > 1) THEN
    3226        3202 :                   DO ibead = 1, endbead
    3227       10006 :                      work(:, ibead) = pos(:, iatom, ibead) - pos(:, endatom, ibead)
    3228             :                   END DO
    3229         934 :                   partaction = partaction + helium_eval_chain(helium, work, endbead, work2, work3)
    3230             :                END IF
    3231             :             END DO
    3232             : 
    3233          56 :             IF (worm_atom_idx /= startatom) THEN
    3234        1656 :                DO iatom = 1, helium%atoms
    3235        1600 :                   IF (iatom == startatom) CYCLE
    3236        1544 :                   IF (iatom == worm_atom_idx) CYCLE
    3237        5952 :                   r(:) = pos(:, iatom, worm_bead_idx - 1) - pos(:, startatom, worm_bead_idx - 1)
    3238        5952 :                   rp(:) = pos(:, iatom, worm_bead_idx) - pos(:, startatom, worm_bead_idx)
    3239        1656 :                   partaction = partaction + helium_eval_expansion(helium, r, rp, work3)
    3240             :                END DO
    3241             :                ! add pair action with worm
    3242         224 :                r(:) = pos(:, startatom, worm_bead_idx - 1) - pos(:, worm_atom_idx, worm_bead_idx - 1)
    3243         224 :                rp(:) = pos(:, startatom, worm_bead_idx) - xtrapos(:)
    3244          56 :                partaction = partaction + helium_eval_expansion(helium, r, rp, work3)
    3245             :             ELSE
    3246             :                ! worm intersection
    3247           0 :                DO iatom = 1, helium%atoms
    3248           0 :                   IF (iatom == startatom) CYCLE
    3249           0 :                   r(:) = pos(:, iatom, worm_bead_idx - 1) - pos(:, startatom, worm_bead_idx - 1)
    3250           0 :                   rp(:) = pos(:, iatom, worm_bead_idx) - xtrapos(:)
    3251           0 :                   partaction = partaction + helium_eval_expansion(helium, r, rp, work3)
    3252             :                END DO
    3253             :             END IF
    3254             :          ELSE !(worm_bead_idx < endbead)
    3255        2130 :             IF (worm_bead_idx /= 1) THEN
    3256       44553 :                DO iatom = 1, helium%atoms
    3257             :                   ! avoid self interaction
    3258       43072 :                   IF (iatom == startatom) CYCLE
    3259             :                   ! first the section up to the end of the atom
    3260             :                   ! one less, because we need to work on the wrapping separately
    3261      124787 :                   DO ibead = startbead, helium%beads
    3262      374375 :                      work(:, ibead + 1 - startbead) = pos(:, iatom, ibead) - pos(:, startatom, ibead)
    3263             :                   END DO
    3264             :                   ! wrapping bond
    3265      166364 :              work(:, helium%beads - startbead + 2) = pos(:, helium%permutation(iatom), 1) - pos(:, helium%permutation(startatom), 1)
    3266       44553 :                   partaction = partaction + helium_eval_chain(helium, work, helium%beads - startbead + 2, work2, work3)
    3267             :                END DO
    3268             : 
    3269             :                ! ending atom
    3270       44553 :                DO iatom = 1, helium%atoms
    3271             :                   ! avoid self interaction
    3272       43072 :                   IF (iatom == endatom) CYCLE
    3273             :                   !from first to two before the worm gap
    3274       41591 :                   IF (worm_bead_idx > 2) THEN
    3275       90118 :                      DO ibead = 1, worm_bead_idx - 1
    3276      285934 :                         work(:, ibead) = pos(:, iatom, ibead) - pos(:, endatom, ibead)
    3277             :                      END DO
    3278       24846 :                      partaction = partaction + helium_eval_chain(helium, work, worm_bead_idx - 1, work2, work3)
    3279             :                   END IF
    3280             : 
    3281       43072 :                   IF (endbead > worm_bead_idx) THEN
    3282        5484 :                      DO ibead = worm_bead_idx, endbead
    3283       17358 :                         work(:, ibead - worm_bead_idx + 1) = pos(:, iatom, ibead) - pos(:, endatom, ibead)
    3284             :                      END DO
    3285        1526 :                      partaction = partaction + helium_eval_chain(helium, work, endbead - worm_bead_idx + 1, work2, work3)
    3286             :                   END IF
    3287             :                END DO
    3288             : 
    3289        1481 :                IF (worm_atom_idx /= endatom) THEN
    3290        2016 :                   DO iatom = 1, helium%atoms
    3291        1952 :                      IF (iatom == endatom) CYCLE
    3292        1888 :                      IF (iatom == worm_atom_idx) CYCLE
    3293        7296 :                      r(:) = pos(:, iatom, worm_bead_idx - 1) - pos(:, endatom, worm_bead_idx - 1)
    3294        7296 :                      rp(:) = pos(:, iatom, worm_bead_idx) - pos(:, endatom, worm_bead_idx)
    3295        2016 :                      partaction = partaction + helium_eval_expansion(helium, r, rp, work3)
    3296             :                   END DO
    3297             :                   ! add pair action with worm
    3298         256 :                   r(:) = pos(:, endatom, worm_bead_idx - 1) - pos(:, worm_atom_idx, worm_bead_idx - 1)
    3299         256 :                   rp(:) = pos(:, endatom, worm_bead_idx) - xtrapos(:)
    3300          64 :                   partaction = partaction + helium_eval_expansion(helium, r, rp, work3)
    3301             :                ELSE
    3302             :                   ! worm intersection
    3303       42537 :                   DO iatom = 1, helium%atoms
    3304       41120 :                      IF (iatom == endatom) CYCLE
    3305      158812 :                      r(:) = pos(:, iatom, worm_bead_idx - 1) - pos(:, endatom, worm_bead_idx - 1)
    3306      158812 :                      rp(:) = pos(:, iatom, worm_bead_idx) - xtrapos(:)
    3307       42537 :                      partaction = partaction + helium_eval_expansion(helium, r, rp, work3)
    3308             :                   END DO
    3309             :                END IF
    3310             :             ELSE !(worm_bead_idx == 1)
    3311             :                ! special treatment if first bead is worm bead
    3312       19917 :                DO iatom = 1, helium%atoms
    3313             :                   ! avoid self interaction
    3314       19268 :                   IF (iatom == startatom) CYCLE
    3315             :                   ! first the section up to the end of the atom
    3316             :                   ! one less, because we need to work on the wrapping separately
    3317       19268 :                   IF (helium%beads > startbead) THEN
    3318       79426 :                      DO ibead = startbead, helium%beads
    3319      263335 :                         work(:, ibead - startbead + 1) = pos(:, iatom, ibead) - pos(:, startatom, ibead)
    3320             :                      END DO
    3321       18123 :                      partaction = partaction + helium_eval_chain(helium, work, helium%beads - startbead + 1, work2, work3)
    3322             :                   END IF
    3323             :                END DO
    3324             : 
    3325             :                ! ending atom
    3326       19917 :                DO iatom = 1, helium%atoms
    3327       19917 :                   IF (endbead > 1) THEN
    3328        6144 :                      DO ibead = 1, endbead
    3329       20736 :                         work(:, ibead) = pos(:, iatom, ibead) - pos(:, endatom, ibead)
    3330             :                      END DO
    3331        1280 :                      partaction = partaction + helium_eval_chain(helium, work, endbead, work2, work3)
    3332             :                   END IF
    3333             :                END DO
    3334             : 
    3335         649 :                IF (worm_atom_idx /= endatom) THEN
    3336        1626 :                   DO iatom = 1, helium%atoms
    3337        1576 :                      IF (iatom == endatom) CYCLE
    3338        1526 :                      IF (iatom == worm_atom_idx) CYCLE
    3339        5904 :                      r(:) = pos(:, helium%iperm(iatom), helium%beads) - pos(:, startatom, helium%beads)
    3340        5904 :                      rp(:) = pos(:, iatom, 1) - pos(:, endatom, 1)
    3341        1626 :                      partaction = partaction + helium_eval_expansion(helium, r, rp, work3)
    3342             :                   END DO
    3343             :                   ! add pair action with worm
    3344         200 :                   r(:) = pos(:, startatom, helium%beads) - pos(:, helium%iperm(worm_atom_idx), helium%beads)
    3345         200 :                   rp(:) = pos(:, endatom, 1) - xtrapos(:)
    3346          50 :                   partaction = partaction + helium_eval_expansion(helium, r, rp, work3)
    3347             :                ELSE
    3348             :                   ! worm intersection
    3349       18291 :                   DO iatom = 1, helium%atoms
    3350       17692 :                      IF (iatom == endatom) CYCLE
    3351       68372 :                      r(:) = pos(:, helium%iperm(iatom), helium%beads) - pos(:, startatom, helium%beads)
    3352       68372 :                      rp(:) = pos(:, iatom, 1) - xtrapos(:)
    3353       18291 :                      partaction = partaction + helium_eval_expansion(helium, r, rp, work3)
    3354             :                   END DO
    3355             :                END IF
    3356             :             END IF
    3357             :          END IF
    3358             :       END IF
    3359        9479 :       DEALLOCATE (work, work2, work3)
    3360             : 
    3361        9479 :    END FUNCTION worm_path_action_worm_corrected
    3362             : 
    3363             : ! **************************************************************************************************
    3364             : !> \brief Path interaction
    3365             : !> \param pint_env ...
    3366             : !> \param helium ...
    3367             : !> \param pos ...
    3368             : !> \param startatom ...
    3369             : !> \param startbead ...
    3370             : !> \param endatom ...
    3371             : !> \param endbead ...
    3372             : !> \return ...
    3373             : !> \author fuhl
    3374             : ! **************************************************************************************************
    3375       36998 :    REAL(KIND=dp) FUNCTION worm_path_inter_action(pint_env, helium, pos, &
    3376             :                                                  startatom, startbead, endatom, endbead) RESULT(partaction)
    3377             : 
    3378             :       TYPE(pint_env_type), INTENT(IN)                    :: pint_env
    3379             :       TYPE(helium_solvent_type), INTENT(IN)              :: helium
    3380             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN), &
    3381             :          POINTER                                         :: pos
    3382             :       INTEGER, INTENT(IN)                                :: startatom, startbead, endatom, endbead
    3383             : 
    3384             :       INTEGER                                            :: ibead
    3385             :       REAL(KIND=dp)                                      :: energy
    3386             : 
    3387       36998 :       partaction = 0.0_dp
    3388             : 
    3389             :       ! helium interaction with the solute
    3390             :       ! do action in two ways, depending
    3391             :       ! if coordinates are not wrapping
    3392       36998 :       IF (startbead < endbead) THEN
    3393             : 
    3394             :          ! interaction is only beadwise due to primitive coupling
    3395             :          ! startatom and endatom are the same
    3396      116706 :          DO ibead = startbead + 1, endbead - 1
    3397             :             CALL helium_bead_solute_e_f(pint_env, helium, &
    3398       89515 :                                         startatom, ibead, pos(:, startatom, ibead), energy=energy)
    3399      116706 :             partaction = partaction + energy
    3400             :          END DO
    3401             : 
    3402             :       ELSE !(startbead > endbead)
    3403             : 
    3404             :          ! interaction is only beadwise due to primitive coupling
    3405             :          ! startatom and endatom are different
    3406       27909 :          DO ibead = startbead + 1, helium%beads
    3407             :             CALL helium_bead_solute_e_f(pint_env, helium, &
    3408       18102 :                                         startatom, ibead, pos(:, startatom, ibead), energy=energy)
    3409       27909 :             partaction = partaction + energy
    3410             :          END DO
    3411             :          ! second atom after imaginary time wrap
    3412       27906 :          DO ibead = 1, endbead - 1
    3413             :             CALL helium_bead_solute_e_f(pint_env, helium, &
    3414       18099 :                                         endatom, ibead, pos(:, endatom, ibead), energy=energy)
    3415       27906 :             partaction = partaction + energy
    3416             :          END DO
    3417             :       END IF
    3418             : 
    3419       36998 :       partaction = partaction*helium%tau
    3420             : 
    3421       36998 :    END FUNCTION worm_path_inter_action
    3422             : 
    3423             : ! **************************************************************************************************
    3424             : !> \brief Path interaction for head
    3425             : !> \param pint_env ...
    3426             : !> \param helium ...
    3427             : !> \param pos ...
    3428             : !> \param startatom ...
    3429             : !> \param startbead ...
    3430             : !> \param xtrapos ...
    3431             : !> \param worm_atom_idx ...
    3432             : !> \param worm_bead_idx ...
    3433             : !> \return ...
    3434             : !> \author fuhl
    3435             : ! **************************************************************************************************
    3436        9502 :    REAL(KIND=dp) FUNCTION worm_path_inter_action_head(pint_env, helium, pos, &
    3437             :                                                      startatom, startbead, xtrapos, worm_atom_idx, worm_bead_idx) RESULT(partaction)
    3438             : 
    3439             :       TYPE(pint_env_type), INTENT(IN)                    :: pint_env
    3440             :       TYPE(helium_solvent_type), INTENT(IN)              :: helium
    3441             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN), &
    3442             :          POINTER                                         :: pos
    3443             :       INTEGER, INTENT(IN)                                :: startatom, startbead
    3444             :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: xtrapos
    3445             :       INTEGER, INTENT(IN)                                :: worm_atom_idx, worm_bead_idx
    3446             : 
    3447             :       INTEGER                                            :: ibead
    3448             :       REAL(KIND=dp)                                      :: energy
    3449             : 
    3450        9502 :       partaction = 0.0_dp
    3451             : 
    3452             :       ! helium interaction with the solute
    3453             :       ! if coordinates are not wrapping
    3454        9502 :       IF (startbead < worm_bead_idx) THEN
    3455       24866 :          DO ibead = startbead + 1, worm_bead_idx - 1
    3456             :             CALL helium_bead_solute_e_f(pint_env, helium, &
    3457       17602 :                                         startatom, ibead, pos(:, startatom, ibead), energy=energy)
    3458       24866 :             partaction = partaction + energy
    3459             :          END DO
    3460             :          CALL helium_bead_solute_e_f(pint_env, helium, &
    3461        7264 :                                      startatom, ibead, xtrapos, energy=energy)
    3462        7264 :          partaction = partaction + 0.5_dp*energy
    3463             :       ELSE !(startbead > worm_bead_idx)
    3464        5378 :          DO ibead = startbead + 1, helium%beads
    3465             :             CALL helium_bead_solute_e_f(pint_env, helium, &
    3466        3140 :                                         startatom, ibead, pos(:, startatom, ibead), energy=energy)
    3467        5378 :             partaction = partaction + energy
    3468             :          END DO
    3469        5360 :          DO ibead = 1, worm_bead_idx - 1
    3470             :             CALL helium_bead_solute_e_f(pint_env, helium, &
    3471        3122 :                                         worm_atom_idx, ibead, pos(:, worm_atom_idx, ibead), energy=energy)
    3472        5360 :             partaction = partaction + energy
    3473             :          END DO
    3474             :          CALL helium_bead_solute_e_f(pint_env, helium, &
    3475        2238 :                                      worm_atom_idx, ibead, xtrapos, energy=energy)
    3476        2238 :          partaction = partaction + 0.5_dp*energy
    3477             :       END IF
    3478             : 
    3479        9502 :       partaction = partaction*helium%tau
    3480             : 
    3481        9502 :    END FUNCTION worm_path_inter_action_head
    3482             : 
    3483             : ! **************************************************************************************************
    3484             : !> \brief Path interaction for tail
    3485             : !> \param pint_env ...
    3486             : !> \param helium ...
    3487             : !> \param pos ...
    3488             : !> \param endatom ...
    3489             : !> \param endbead ...
    3490             : !> \param worm_atom_idx ...
    3491             : !> \param worm_bead_idx ...
    3492             : !> \return ...
    3493             : !> \author fuhl
    3494             : ! **************************************************************************************************
    3495        4090 :    REAL(KIND=dp) FUNCTION worm_path_inter_action_tail(pint_env, helium, pos, &
    3496             :                                                       endatom, endbead, worm_atom_idx, worm_bead_idx) RESULT(partaction)
    3497             : 
    3498             :       TYPE(pint_env_type), INTENT(IN)                    :: pint_env
    3499             :       TYPE(helium_solvent_type), INTENT(IN)              :: helium
    3500             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN), &
    3501             :          POINTER                                         :: pos
    3502             :       INTEGER, INTENT(IN)                                :: endatom, endbead, worm_atom_idx, &
    3503             :                                                             worm_bead_idx
    3504             : 
    3505             :       INTEGER                                            :: ibead
    3506             :       REAL(KIND=dp)                                      :: energy
    3507             : 
    3508        4090 :       partaction = 0.0_dp
    3509             : 
    3510             :       ! helium interaction with the solute
    3511             :       ! if coordinates are not wrapping
    3512        4090 :       IF (worm_bead_idx < endbead) THEN
    3513             :          CALL helium_bead_solute_e_f(pint_env, helium, &
    3514        3299 :                                      worm_atom_idx, worm_bead_idx, pos(:, worm_atom_idx, worm_bead_idx), energy=energy)
    3515        3299 :          partaction = partaction + 0.5_dp*energy
    3516       11260 :          DO ibead = worm_bead_idx + 1, endbead - 1
    3517             :             CALL helium_bead_solute_e_f(pint_env, helium, &
    3518        7961 :                                         endatom, ibead, pos(:, endatom, ibead), energy=energy)
    3519       11260 :             partaction = partaction + energy
    3520             :          END DO
    3521             :       ELSE !(worm_bead_idx > endbead)
    3522             :          CALL helium_bead_solute_e_f(pint_env, helium, &
    3523         791 :                                      worm_atom_idx, worm_bead_idx, pos(:, worm_atom_idx, worm_bead_idx), energy=energy)
    3524         791 :          partaction = partaction + 0.5_dp*energy
    3525        2001 :          DO ibead = worm_bead_idx + 1, helium%beads
    3526             :             CALL helium_bead_solute_e_f(pint_env, helium, &
    3527        1210 :                                         worm_atom_idx, ibead, pos(:, worm_atom_idx, ibead), energy=energy)
    3528        2001 :             partaction = partaction + energy
    3529             :          END DO
    3530        1818 :          DO ibead = 1, endbead - 1
    3531             :             CALL helium_bead_solute_e_f(pint_env, helium, &
    3532        1027 :                                         endatom, ibead, pos(:, endatom, ibead), energy=energy)
    3533        1818 :             partaction = partaction + energy
    3534             :          END DO
    3535             :       END IF
    3536             : 
    3537        4090 :       partaction = partaction*helium%tau
    3538             : 
    3539        4090 :    END FUNCTION worm_path_inter_action_tail
    3540             : 
    3541             : END MODULE helium_worm

Generated by: LCOV version 1.15