LCOV - code coverage report
Current view: top level - src/tmc - tmc_calculations.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 88 180 48.9 %
Date: 2024-12-21 06:28:57 Functions: 6 13 46.2 %

          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 calculation section for TreeMonteCarlo
      10             : !> \par History
      11             : !>      11.2012 created [Mandes Schoenherr]
      12             : !> \author Mandes
      13             : ! **************************************************************************************************
      14             : 
      15             : MODULE tmc_calculations
      16             :    USE cell_methods,                    ONLY: init_cell
      17             :    USE cell_types,                      ONLY: cell_copy,&
      18             :                                               cell_type,&
      19             :                                               get_cell,&
      20             :                                               pbc
      21             :    USE cp_log_handling,                 ONLY: cp_to_string
      22             :    USE f77_interface,                   ONLY: calc_energy,&
      23             :                                               calc_force,&
      24             :                                               set_cell
      25             :    USE kinds,                           ONLY: dp
      26             :    USE mathconstants,                   ONLY: pi
      27             :    USE parallel_rng_types,              ONLY: rng_stream_type
      28             :    USE physcon,                         ONLY: boltzmann,&
      29             :                                               joule
      30             :    USE tmc_move_types,                  ONLY: mv_type_MD
      31             :    USE tmc_stati,                       ONLY: task_type_MC,&
      32             :                                               task_type_gaussian_adaptation,&
      33             :                                               task_type_ideal_gas
      34             :    USE tmc_tree_types,                  ONLY: tree_type
      35             :    USE tmc_types,                       ONLY: tmc_atom_type,&
      36             :                                               tmc_env_type,&
      37             :                                               tmc_param_type
      38             : #include "../base/base_uses.f90"
      39             : 
      40             :    IMPLICIT NONE
      41             : 
      42             :    PRIVATE
      43             : 
      44             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'tmc_calculations'
      45             : 
      46             :    PUBLIC :: calc_potential_energy
      47             :    PUBLIC :: get_scaled_cell, get_cell_scaling
      48             :    PUBLIC :: nearest_distance
      49             :    PUBLIC :: geometrical_center, center_of_mass
      50             :    PUBLIC :: init_vel, calc_e_kin
      51             :    PUBLIC :: compute_estimated_prob
      52             :    PUBLIC :: get_subtree_efficiency
      53             : CONTAINS
      54             : 
      55             : ! **************************************************************************************************
      56             : !> \brief start the calculation of the energy
      57             : !>        (distinguish between exact and approximate)
      58             : !> \param conf actual configurations to calculate potential energy
      59             : !> \param env_id f77_interface env id
      60             : !> \param exact_approx_pot flag if result should be stores in exact or approx
      61             : !>        energy variable
      62             : !> \param tmc_env TMC environment parameters
      63             : !> \author Mandes 01.2013
      64             : ! **************************************************************************************************
      65        4739 :    SUBROUTINE calc_potential_energy(conf, env_id, exact_approx_pot, &
      66             :                                     tmc_env)
      67             :       TYPE(tree_type), POINTER                           :: conf
      68             :       INTEGER                                            :: env_id
      69             :       LOGICAL                                            :: exact_approx_pot
      70             :       TYPE(tmc_env_type), POINTER                        :: tmc_env
      71             : 
      72             :       INTEGER                                            :: ierr
      73             :       LOGICAL                                            :: flag
      74             :       REAL(KIND=dp)                                      :: e_pot, rnd
      75             :       TYPE(cell_type), POINTER                           :: tmp_cell
      76             : 
      77        4739 :       rnd = 0.0_dp
      78             : 
      79        4739 :       CPASSERT(ASSOCIATED(conf))
      80        4739 :       CPASSERT(env_id .GT. 0)
      81        4739 :       CPASSERT(ASSOCIATED(tmc_env))
      82             : 
      83        9478 :       SELECT CASE (tmc_env%params%task_type)
      84             :       CASE (task_type_gaussian_adaptation)
      85             :          !CALL gaussian_adaptation_energy(, )
      86             :       CASE (task_type_MC)
      87        4739 :          IF (tmc_env%params%pressure .GE. 0.0_dp) THEN
      88       23340 :             ALLOCATE (tmp_cell)
      89             :             CALL get_scaled_cell(cell=tmc_env%params%cell, box_scale=conf%box_scale, &
      90         778 :                                  scaled_cell=tmp_cell)
      91         778 :             CALL set_cell(env_id=env_id, new_cell=tmp_cell%hmat, ierr=ierr)
      92         778 :             CPASSERT(ierr .EQ. 0)
      93         778 :             DEALLOCATE (tmp_cell)
      94             :          END IF
      95             : 
      96             :          ! TODO check for minimal distances
      97        4739 :          flag = .TRUE.
      98           0 :          IF (flag .EQV. .TRUE.) THEN
      99        4739 :             IF (tmc_env%params%print_forces .OR. &
     100             :                 conf%move_type .EQ. mv_type_MD) THEN
     101             :                e_pot = 0.0_dp
     102       38272 :                conf%frc(:) = 0.0_dp
     103             :                CALL calc_force(env_id=env_id, pos=conf%pos, n_el_pos=SIZE(conf%pos), &
     104             :                                e_pot=e_pot, force=conf%frc, &
     105         598 :                                n_el_force=SIZE(conf%frc), ierr=ierr)
     106             :             ELSE
     107             :                e_pot = 0.0_dp
     108        4141 :                CALL calc_energy(env_id=env_id, pos=conf%pos, n_el=SIZE(conf%pos), e_pot=e_pot, ierr=ierr)
     109             :             END IF
     110             :          ELSE
     111             :             e_pot = HUGE(e_pot)
     112             :          END IF
     113             :       CASE (task_type_ideal_gas)
     114           0 :          e_pot = 0.0_dp
     115             :       CASE DEFAULT
     116             :          CALL cp_abort(__LOCATION__, &
     117             :                        "worker task typ is unknown "// &
     118        4739 :                        cp_to_string(tmc_env%params%task_type))
     119             :       END SELECT
     120             : 
     121             :       ! ---     wait a bit
     122        4739 :       rnd = tmc_env%rng_stream%next()
     123             :       !rnd = 0.5
     124             : !TODO    IF(worker_random_wait.AND.exact_approx_pot)THEN
     125             : !      CALL SYSTEM_CLOCK(time0, time_rate, time_max)
     126             : !      wait_end=time0+(1.0+rnd)*worker_wait_msec*time_rate/1000.0
     127             : !      !wait_end=time0+((worker_wait_msec*time_rate+999)/1000)
     128             : !      time_wait: DO
     129             : !        CALL SYSTEM_CLOCK(time1, time_rate, time_max)
     130             : !        IF(time1<time0.OR.time1>wait_end) exit time_wait
     131             : !      END DO time_wait
     132             : !    END IF
     133        4739 :       IF (exact_approx_pot) THEN
     134        4542 :          conf%potential = e_pot
     135             :       ELSE
     136         197 :          conf%e_pot_approx = e_pot
     137             :       END IF
     138        4739 :    END SUBROUTINE calc_potential_energy
     139             : 
     140             : ! **************************************************************************************************
     141             : !> \brief handles properties and calculations of a scaled cell
     142             : !> \param cell original cell
     143             : !> \param box_scale scaling factors for each direction
     144             : !> \param scaled_hmat returns the scaled h matrix (matrix of cell vectors)
     145             : !> \param scaled_cell ...
     146             : !> \param vol returns the cell volume
     147             : !> \param abc ...
     148             : !> \param vec a vector, which will be folded (pbc) in the cell
     149             : !> \author Mandes 11.2012
     150             : ! **************************************************************************************************
     151      218382 :    SUBROUTINE get_scaled_cell(cell, box_scale, scaled_hmat, scaled_cell, vol, &
     152             :                               abc, vec)
     153             :       TYPE(cell_type), INTENT(IN), POINTER               :: cell
     154             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: box_scale
     155             :       REAL(KIND=dp), DIMENSION(3, 3), OPTIONAL           :: scaled_hmat
     156             :       TYPE(cell_type), OPTIONAL, POINTER                 :: scaled_cell
     157             :       REAL(KIND=dp), OPTIONAL                            :: vol
     158             :       REAL(KIND=dp), DIMENSION(3), INTENT(OUT), OPTIONAL :: abc
     159             :       REAL(KIND=dp), DIMENSION(3), OPTIONAL              :: vec
     160             : 
     161             :       LOGICAL                                            :: new_scaled_cell
     162             :       TYPE(cell_type), POINTER                           :: tmp_cell
     163             : 
     164      218382 :       CPASSERT(ASSOCIATED(cell))
     165      218382 :       CPASSERT(ASSOCIATED(box_scale))
     166             : 
     167      218382 :       new_scaled_cell = .FALSE.
     168             : 
     169      218382 :       IF (.NOT. PRESENT(scaled_cell)) THEN
     170     6527760 :          ALLOCATE (tmp_cell)
     171      217592 :          new_scaled_cell = .TRUE.
     172             :       ELSE
     173         790 :          tmp_cell => scaled_cell
     174             :       END IF
     175      218382 :       CALL cell_copy(cell_in=cell, cell_out=tmp_cell)
     176      873528 :       tmp_cell%hmat(:, 1) = tmp_cell%hmat(:, 1)*box_scale(1)
     177      873528 :       tmp_cell%hmat(:, 2) = tmp_cell%hmat(:, 2)*box_scale(2)
     178      873528 :       tmp_cell%hmat(:, 3) = tmp_cell%hmat(:, 3)*box_scale(3)
     179      218382 :       CALL init_cell(cell=tmp_cell)
     180             : 
     181      218382 :       IF (PRESENT(scaled_hmat)) &
     182        5096 :          scaled_hmat(:, :) = tmp_cell%hmat
     183             : 
     184      218382 :       IF (PRESENT(vec)) THEN
     185      862448 :          vec = pbc(r=vec, cell=tmp_cell)
     186             :       END IF
     187             : 
     188      218382 :       IF (PRESENT(vol)) CALL get_cell(cell=tmp_cell, deth=vol)
     189      218382 :       IF (PRESENT(abc)) CALL get_cell(cell=tmp_cell, abc=abc)
     190      218382 :       IF (new_scaled_cell) DEALLOCATE (tmp_cell)
     191             : 
     192      218382 :    END SUBROUTINE get_scaled_cell
     193             : 
     194             : ! **************************************************************************************************
     195             : !> \brief handles properties and calculations of a scaled cell
     196             : !> \param cell original cell
     197             : !> \param scaled_hmat returns the scaled h matrix (matrix of cell vectors)
     198             : !> \param box_scale scaling factors for each direction
     199             : !> \author Mandes 11.2012
     200             : ! **************************************************************************************************
     201        1206 :    SUBROUTINE get_cell_scaling(cell, scaled_hmat, box_scale)
     202             :       TYPE(cell_type), INTENT(IN), POINTER               :: cell
     203             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN)         :: scaled_hmat
     204             :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: box_scale
     205             : 
     206             :       REAL(KIND=dp), DIMENSION(3)                        :: abc_new, abc_orig
     207             :       TYPE(cell_type), POINTER                           :: tmp_cell
     208             : 
     209        1206 :       CPASSERT(ASSOCIATED(cell))
     210             : 
     211       36180 :       ALLOCATE (tmp_cell)
     212        1206 :       CALL cell_copy(cell_in=cell, cell_out=tmp_cell)
     213       15678 :       tmp_cell%hmat(:, :) = scaled_hmat(:, :)
     214        1206 :       CALL init_cell(cell=tmp_cell)
     215        1206 :       CALL get_cell(cell=cell, abc=abc_orig)
     216        1206 :       CALL get_cell(cell=tmp_cell, abc=abc_new)
     217             : 
     218        4824 :       box_scale(:) = abc_new(:)/abc_orig(:)
     219             : 
     220        1206 :       DEALLOCATE (tmp_cell)
     221        1206 :    END SUBROUTINE get_cell_scaling
     222             : 
     223             : ! **************************************************************************************************
     224             : !> \brief neares distance of atoms within the periodic boundary condition
     225             : !> \param x1 ...
     226             : !> \param x2 ...
     227             : !> \param cell ...
     228             : !> \param box_scale ...
     229             : !> \return ...
     230             : !> \author Mandes 11.2012
     231             : ! **************************************************************************************************
     232      187940 :    FUNCTION nearest_distance(x1, x2, cell, box_scale) RESULT(res)
     233             :       REAL(KIND=dp), DIMENSION(:)                        :: x1, x2
     234             :       TYPE(cell_type), POINTER                           :: cell
     235             :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: box_scale
     236             :       REAL(KIND=dp)                                      :: res
     237             : 
     238             :       REAL(KIND=dp), DIMENSION(3)                        :: dist_vec
     239      187940 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: tmp_box_scale
     240             : 
     241      187940 :       NULLIFY (tmp_box_scale)
     242             : 
     243           0 :       CPASSERT(ASSOCIATED(cell))
     244      187940 :       CPASSERT(SIZE(x1) .EQ. 3)
     245      187940 :       CPASSERT(SIZE(x2) .EQ. 3)
     246             : 
     247      751760 :       dist_vec(:) = x2(:) - x1(:) ! distance vector between atoms
     248      187940 :       ALLOCATE (tmp_box_scale(3))
     249      187940 :       IF (PRESENT(box_scale)) THEN
     250      187940 :          CPASSERT(SIZE(box_scale) .EQ. 3)
     251     1315580 :          tmp_box_scale(:) = box_scale
     252             :       ELSE
     253           0 :          tmp_box_scale(:) = 1.0_dp
     254             :       END IF
     255      187940 :       CALL get_scaled_cell(cell=cell, box_scale=box_scale, vec=dist_vec)
     256      751760 :       res = SQRT(SUM(dist_vec(:)*dist_vec(:)))
     257      187940 :       DEALLOCATE (tmp_box_scale)
     258      187940 :    END FUNCTION nearest_distance
     259             : 
     260             : ! **************************************************************************************************
     261             : !> \brief calculate the geometrical center of an amount of atoms
     262             : !>        array size should be multiple of dim_per_elem
     263             : !> \param pos list of atoms
     264             : !> \param center return value, the geometrical center
     265             : !> \author Mandes 11.2012
     266             : ! **************************************************************************************************
     267        7760 :    SUBROUTINE geometrical_center(pos, center)
     268             :       REAL(KIND=dp), DIMENSION(:)                        :: pos
     269             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: center
     270             : 
     271             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'geometrical_center'
     272             : 
     273             :       INTEGER                                            :: handle, i
     274             : 
     275        7760 :       CPASSERT(ASSOCIATED(center))
     276        7760 :       CPASSERT(SIZE(pos) .GE. SIZE(center))
     277             : 
     278             :       ! start the timing
     279        7760 :       CALL timeset(routineN, handle)
     280             : 
     281       31040 :       center = 0.0_dp
     282       31138 :       DO i = 1, SIZE(pos), SIZE(center)
     283             :          center(:) = center(:) + &
     284      101272 :                      pos(i:i + SIZE(center) - 1)/(SIZE(pos)/REAL(SIZE(center), KIND=dp))
     285             :       END DO
     286             :       ! end the timing
     287        7760 :       CALL timestop(handle)
     288        7760 :    END SUBROUTINE geometrical_center
     289             : 
     290             : ! **************************************************************************************************
     291             : !> \brief calculate the center of mass of an amount of atoms
     292             : !>        array size should be multiple of dim_per_elem
     293             : !> \param pos ...
     294             : !> \param atoms ...
     295             : !> \param center ...
     296             : !> \param
     297             : !> \param
     298             : !> \author Mandes 11.2012
     299             : ! **************************************************************************************************
     300           0 :    SUBROUTINE center_of_mass(pos, atoms, center)
     301             :       REAL(KIND=dp), DIMENSION(:)                        :: pos
     302             :       TYPE(tmc_atom_type), DIMENSION(:), OPTIONAL        :: atoms
     303             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: center
     304             : 
     305             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'center_of_mass'
     306             : 
     307             :       INTEGER                                            :: handle, i
     308             :       REAL(KIND=dp)                                      :: mass_sum, mass_tmp
     309             : 
     310           0 :       CPASSERT(ASSOCIATED(center))
     311           0 :       CPASSERT(SIZE(pos) .GE. SIZE(center))
     312             : 
     313             :       ! start the timing
     314           0 :       CALL timeset(routineN, handle)
     315             : 
     316           0 :       center = 0.0_dp
     317           0 :       mass_sum = 0.0_dp
     318           0 :       DO i = 1, SIZE(pos), SIZE(center)
     319           0 :          IF (PRESENT(atoms)) THEN
     320           0 :             CPASSERT(SIZE(atoms) .EQ. SIZE(pos)/SIZE(center))
     321           0 :             mass_tmp = atoms(INT(i/REAL(SIZE(center), KIND=dp)) + 1)%mass
     322             :             center(:) = center(:) + pos(i:i + SIZE(center) - 1)/ &
     323           0 :                         (SIZE(pos)/REAL(SIZE(center), KIND=dp))*mass_tmp
     324           0 :             mass_sum = mass_sum + mass_tmp
     325             :          ELSE
     326           0 :             CPWARN("try to calculate center of mass without any mass.")
     327             :             center(:) = center(:) + pos(i:i + SIZE(center) - 1)/ &
     328           0 :                         (SIZE(pos)/REAL(SIZE(center), KIND=dp))
     329           0 :             mass_sum = 1.0_dp
     330             :          END IF
     331             :       END DO
     332           0 :       center(:) = center(:)/mass_sum
     333             :       ! end the timing
     334           0 :       CALL timestop(handle)
     335           0 :    END SUBROUTINE center_of_mass
     336             : 
     337             : ! **************************************************************************************************
     338             : !> \brief routine sets initial velocity, using the Box-Muller Method for Normal
     339             : !>         (Gaussian) Deviates
     340             : !> \param vel ...
     341             : !> \param atoms ...
     342             : !> \param temerature ...
     343             : !> \param rng_stream ...
     344             : !> \param rnd_seed ...
     345             : !> \author Mandes 11.2012
     346             : ! **************************************************************************************************
     347           0 :    SUBROUTINE init_vel(vel, atoms, temerature, rng_stream, rnd_seed)
     348             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: vel
     349             :       TYPE(tmc_atom_type), DIMENSION(:), POINTER         :: atoms
     350             :       REAL(KIND=dp)                                      :: temerature
     351             :       TYPE(rng_stream_type), INTENT(INOUT)               :: rng_stream
     352             :       REAL(KIND=dp), DIMENSION(3, 2, 3)                  :: rnd_seed
     353             : 
     354             :       INTEGER                                            :: i
     355             :       REAL(KIND=dp)                                      :: kB, mass_tmp, rnd1, rnd2
     356             : 
     357           0 :       kB = boltzmann/joule
     358             : 
     359           0 :       CPASSERT(ASSOCIATED(vel))
     360           0 :       CPASSERT(ASSOCIATED(atoms))
     361             : 
     362           0 :       CALL rng_stream%set(bg=rnd_seed(:, :, 1), cg=rnd_seed(:, :, 2), ig=rnd_seed(:, :, 3))
     363           0 :       DO i = 1, SIZE(vel)
     364           0 :          rnd1 = rng_stream%next()
     365           0 :          rnd2 = rng_stream%next()
     366             : 
     367           0 :          mass_tmp = atoms(INT(i/REAL(3, KIND=dp)) + 1)%mass
     368             : 
     369             :          vel(i) = SQRT(-2.0_dp*LOG(rnd1))*COS(2.0_dp*PI*rnd2)* &
     370           0 :                   SQRT(kB*temerature/mass_tmp)
     371             :       END DO
     372           0 :       CALL rng_stream%get(bg=rnd_seed(:, :, 1), cg=rnd_seed(:, :, 2), ig=rnd_seed(:, :, 3))
     373             : 
     374           0 :    END SUBROUTINE init_vel
     375             : 
     376             : ! **************************************************************************************************
     377             : !> \brief routine calculates the kinetic energy, using the velocities
     378             : !>        and atom mass, both in atomic units
     379             : !> \param vel ...
     380             : !> \param atoms ...
     381             : !> \return ...
     382             : !> \author Mandes 11.2012
     383             : ! **************************************************************************************************
     384           0 :    FUNCTION calc_e_kin(vel, atoms) RESULT(ekin)
     385             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: vel
     386             :       TYPE(tmc_atom_type), DIMENSION(:), POINTER         :: atoms
     387             :       REAL(KIND=dp)                                      :: ekin
     388             : 
     389             :       INTEGER                                            :: i
     390             :       REAL(KIND=dp)                                      :: mass_tmp
     391             : 
     392           0 :       CPASSERT(ASSOCIATED(vel))
     393           0 :       CPASSERT(ASSOCIATED(atoms))
     394           0 :       ekin = 0.0_dp
     395             : 
     396           0 :       DO i = 1, SIZE(vel)
     397           0 :          mass_tmp = atoms(INT(i/REAL(3, KIND=dp)) + 1)%mass
     398           0 :          ekin = ekin + 0.5_dp*mass_tmp*vel(i)*vel(i)
     399             :       END DO
     400           0 :    END FUNCTION calc_e_kin
     401             : 
     402             : ! **************************************************************************************************
     403             : !> \brief assuming an (exponential) decreasing function, this function
     404             : !>        extrapolate the converged value
     405             : !> \param v1 function values
     406             : !> \param v2 function values
     407             : !> \param v3 function values
     408             : !> \param extrapolate extrapolated final value (result)
     409             : !> \param res_err error of the result
     410             : !> \author Mandes 12.2012
     411             : ! **************************************************************************************************
     412           0 :    SUBROUTINE three_point_extrapolate(v1, v2, v3, extrapolate, res_err)
     413             :       REAL(KIND=dp)                            :: v1, v2, v3
     414             :       REAL(KIND=dp), INTENT(OUT)               :: extrapolate, res_err
     415             : 
     416             :       REAL(KIND=dp)                            :: e1, e2, e3
     417             :       REAL(KIND=dp)                            :: a, b, c, d12, d23, ddd
     418             : 
     419             :       extrapolate = HUGE(extrapolate)
     420             : 
     421             :       !> solve({exp(a+b)+c = e1, exp(2*a+b)+c = e2, exp(3*a+b)+c = e3}, [a, b, c])
     422             :       !> solve({a*b+c = e1, a^2*b+c = e2, a^3*b+c = e3}, [a, b, c]);
     423             :       !   [[                                   3                   2         ]]
     424             :       !   [[    -e3 + e2              (e1 - e2)                 -e2  + e1 e3 ]]
     425             :       !   [[a = --------, b = ---------------------------, c = --------------]]
     426             :       !   [[    e1 - e2       (-e3 + e2) (e3 - 2 e2 + e1)      e3 - 2 e2 + e1]]
     427             : 
     428             :       ! sort so that e1>=e2>=e3
     429           0 :       e1 = v1; e2 = v2; e3 = v3
     430           0 :       CALL swap(e1, e2)
     431           0 :       CALL swap(e1, e3)
     432           0 :       CALL swap(e2, e3)
     433             :       ! we need extra care if some of the difference e1-e2, e3-e2 are nearly zero,
     434             :       !  since the formulae suffer from sever loss of precision
     435           0 :       d12 = e1 - e2
     436           0 :       d23 = e2 - e3
     437           0 :       ddd = d12 - d23
     438           0 :       IF (d12 == 0 .OR. d23 == 0 .OR. ABS(ddd) == 0) THEN
     439             :          ! a degenerate case, we do no extrapolation
     440           0 :          extrapolate = e3
     441           0 :          res_err = e1 - e3
     442             :       ELSE
     443           0 :          a = d23/d12
     444           0 :          b = (d12**3/(d23*ddd))
     445           0 :          c = e2 - (d12*d23)/ddd
     446             :          ! extrapolation, let's only look 4 iterations ahead, more is presumably anyway not accurate
     447             :          ! fewer is maybe more stable
     448           0 :          extrapolate = a**7*b + c
     449           0 :          res_err = e3 - extrapolate
     450             :       END IF
     451           0 :       CPASSERT(extrapolate .NE. HUGE(extrapolate))
     452             :    CONTAINS
     453             : ! **************************************************************************************************
     454             : !> \brief ...
     455             : !> \param x1 ...
     456             : !> \param x2 ...
     457             : ! **************************************************************************************************
     458           0 :       SUBROUTINE swap(x1, x2)
     459             :       REAL(KIND=dp)                                      :: x1, x2
     460             : 
     461             :       REAL(KIND=dp)                                      :: tmp
     462             : 
     463           0 :          IF (x2 > x1) THEN
     464           0 :             tmp = x2
     465           0 :             x2 = x1
     466           0 :             x1 = tmp
     467             :          END IF
     468           0 :       END SUBROUTINE swap
     469             :    END SUBROUTINE three_point_extrapolate
     470             : 
     471             : ! **************************************************************************************************
     472             : !> \brief calculates the probability of acceptance for given intervals of the
     473             : !>        exact energy
     474             : !> \param E_n_mu energy distribution of new configuration
     475             : !> \param E_n_sigma energy distribution of new configuration
     476             : !> \param E_o_mu energy distribution of old configuration
     477             : !> \param E_o_sigma energy distribution of old configuration
     478             : !> \param E_classical_diff the difference in approximated energies for the
     479             : !>        old and new configuration (E_o-E_n)
     480             : !> \param prior_mu energy distribution of the already converged
     481             : !>         energies
     482             : !> \param prior_sigma energy distribution of the already converged
     483             : !>         energies
     484             : !> \param p the random number, the criteria has to be smaller than this
     485             : !> \param beta ...
     486             : !> \return return probability of acceptance
     487             : !> \author Mandes 12.2012
     488             : ! **************************************************************************************************
     489           0 :    FUNCTION compute_prob(E_n_mu, E_n_sigma, E_o_mu, E_o_sigma, E_classical_diff, &
     490             :                          prior_mu, prior_sigma, p, beta) RESULT(prob)
     491             :       REAL(KIND=dp)                                      :: E_n_mu, E_n_sigma, E_o_mu, E_o_sigma, &
     492             :                                                             E_classical_diff, prior_mu, &
     493             :                                                             prior_sigma, p, beta, prob
     494             : 
     495             : !    INTEGER       :: io,in
     496             : !    REAL(KIND=dp) :: diff,E_n,E_o,surface,lower_bound,upper_bound,delta
     497             : 
     498             :       prob = 0.5_dp*ERFC(-0.5_dp*SQRT(2.0_dp)*( &
     499             :                          (-prior_sigma**2 - E_o_sigma**2 - E_n_sigma**2)*LOG(p) + &
     500             :                          ((E_classical_diff - E_n_mu + E_o_mu)*prior_sigma**2 - prior_mu*(E_n_sigma**2 + E_o_sigma**2))*beta)/ &
     501           0 :                          (SQRT(E_o_sigma**2 + E_n_sigma**2)*SQRT(prior_sigma**2 + E_o_sigma**2 + E_n_sigma**2)*prior_sigma*beta))
     502             : 
     503           0 :       prob = MIN(1.0_dp - EPSILON(1.0_dp), MAX(EPSILON(1.0_dp), prob))
     504             : 
     505           0 :    END FUNCTION compute_prob
     506             : 
     507             : ! **************************************************************************************************
     508             : !> \brief extimates the probability of acceptance considering the intermetiate
     509             : !>        step energies
     510             : !> \param elem_old old/parent sub tree element
     511             : !> \param elem_new new/actual sub tree element, which schould be checked
     512             : !> \param E_classical_diff difference in the classical energy of the old and
     513             : !>        new configuration
     514             : !> \param rnd_nr random number acceptance check will be done with
     515             : !> \param beta 1/(kB*T) can differ for different acceptance checks
     516             : !> \param tmc_params TMC environment parameters
     517             : !> \return estimated acceptance probability
     518             : !> \author Mandes 12.2012
     519             : ! **************************************************************************************************
     520           0 :    FUNCTION compute_estimated_prob(elem_old, elem_new, E_classical_diff, &
     521             :                                    rnd_nr, beta, tmc_params) RESULT(prob)
     522             :       TYPE(tree_type), POINTER                           :: elem_old, elem_new
     523             :       REAL(KIND=dp)                                      :: E_classical_diff, rnd_nr, beta
     524             :       TYPE(tmc_param_type), POINTER                      :: tmc_params
     525             :       REAL(KIND=dp)                                      :: prob
     526             : 
     527             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_estimated_prob'
     528             : 
     529             :       INTEGER                                            :: handle
     530             :       REAL(KIND=dp)                                      :: E_mu_tmp, E_n_mu, E_n_sigma, E_o_mu, &
     531             :                                                             E_o_sigma, E_sigma_tmp, prior_sigma
     532             : 
     533           0 :       CPASSERT(ASSOCIATED(elem_old))
     534           0 :       CPASSERT(ASSOCIATED(elem_new))
     535           0 :       CPASSERT(rnd_nr .GT. 0.0_dp)
     536             : 
     537             :       ! start the timing
     538           0 :       CALL timeset(routineN, handle)
     539             : 
     540           0 :       prob = -1.0_dp
     541             :       IF ((elem_new%scf_energies_count .GE. 3) .AND. &
     542           0 :           (elem_old%scf_energies_count .GE. 3) .AND. &
     543             :           tmc_params%prior_NMC_acc%counter .GE. 10) THEN
     544             :          !-- first the new element energy estimation
     545             :          ! using 3 point extrapolation of two different intervals -> more stable estimation
     546             :          ! the energies are sorted in the three_point_extrapolate routine !
     547             :          ! But with array of length 4 we have to select the 3 connected ones
     548             :          CALL three_point_extrapolate(v1=elem_new%scf_energies(MOD(elem_new%scf_energies_count - 3, 4) + 1), &
     549             :                                       v2=elem_new%scf_energies(MOD(elem_new%scf_energies_count - 2, 4) + 1), &
     550             :                                       v3=elem_new%scf_energies(MOD(elem_new%scf_energies_count - 1, 4) + 1), &
     551           0 :                                       extrapolate=E_mu_tmp, res_err=E_sigma_tmp)
     552           0 :          IF ((elem_new%scf_energies_count .GT. 3)) THEN
     553             :             CALL three_point_extrapolate(v1=elem_new%scf_energies(MOD(elem_new%scf_energies_count - 4, 4) + 1), &
     554             :                                          v2=elem_new%scf_energies(MOD(elem_new%scf_energies_count - 3, 4) + 1), &
     555             :                                          v3=elem_new%scf_energies(MOD(elem_new%scf_energies_count - 2, 4) + 1), &
     556           0 :                                          extrapolate=E_n_mu, res_err=E_n_sigma)
     557           0 :             E_n_sigma = MAX(E_n_sigma, ABS(E_n_mu - E_mu_tmp))
     558             :          ELSE
     559           0 :             E_n_sigma = E_sigma_tmp
     560           0 :             E_n_mu = E_mu_tmp
     561             :          END IF
     562             : 
     563             :          !-- the old/parent element energy estimation
     564             :          CALL three_point_extrapolate(v1=elem_old%scf_energies(MOD(elem_old%scf_energies_count - 3, 4) + 1), &
     565             :                                       v2=elem_old%scf_energies(MOD(elem_old%scf_energies_count - 2, 4) + 1), &
     566             :                                       v3=elem_old%scf_energies(MOD(elem_old%scf_energies_count - 1, 4) + 1), &
     567           0 :                                       extrapolate=E_mu_tmp, res_err=E_sigma_tmp)
     568           0 :          IF ((elem_old%scf_energies_count .GT. 3)) THEN
     569             :             CALL three_point_extrapolate(v1=elem_old%scf_energies(MOD(elem_old%scf_energies_count - 4, 4) + 1), &
     570             :                                          v2=elem_old%scf_energies(MOD(elem_old%scf_energies_count - 3, 4) + 1), &
     571             :                                          v3=elem_old%scf_energies(MOD(elem_old%scf_energies_count - 2, 4) + 1), &
     572           0 :                                          extrapolate=E_o_mu, res_err=E_o_sigma)
     573           0 :             E_o_sigma = MAX(E_o_sigma, ABS(E_o_mu - E_mu_tmp))
     574             :          ELSE
     575           0 :             E_o_sigma = E_sigma_tmp
     576           0 :             E_o_mu = E_mu_tmp
     577             :          END IF
     578             : 
     579             :          ! calculate the estimation for the average of the trajectory elements
     580             :          prior_sigma = SQRT(ABS(tmc_params%prior_NMC_acc%aver_2 &
     581           0 :                                 - tmc_params%prior_NMC_acc%aver**2))
     582             : 
     583             :          ! calculate the probability of acceptance for those two elements with their energy
     584             :          ! swap and 2 potential moves are distinguished using the difference in classical energy and different betas
     585             :          prob = compute_prob(E_n_mu=E_n_mu, E_n_sigma=E_n_sigma, E_o_mu=E_o_mu, E_o_sigma=E_o_sigma, &
     586             :                              E_classical_diff=E_classical_diff, &
     587             :                              prior_mu=tmc_params%prior_NMC_acc%aver, prior_sigma=prior_sigma, &
     588           0 :                              p=rnd_nr, beta=beta)
     589             :       END IF
     590             :       ! end the timing
     591           0 :       CALL timestop(handle)
     592           0 :    END FUNCTION compute_estimated_prob
     593             : 
     594             : ! **************************************************************************************************
     595             : !> \brief calculated the rate of used tree elements to created tree elements
     596             : !>        for every temperature
     597             : !> \param tmc_env TMC environment variables
     598             : !> \param eff result efficiency
     599             : !> \author Mandes 01.2013
     600             : ! **************************************************************************************************
     601          14 :    SUBROUTINE get_subtree_efficiency(tmc_env, eff)
     602             :       TYPE(tmc_env_type), POINTER                        :: tmc_env
     603             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eff
     604             : 
     605             :       INTEGER                                            :: i
     606             : 
     607          14 :       CPASSERT(ASSOCIATED(tmc_env))
     608          14 :       CPASSERT(ASSOCIATED(tmc_env%params))
     609          14 :       CPASSERT(ASSOCIATED(tmc_env%m_env))
     610             : 
     611          54 :       eff(:) = 0.0_dp
     612             : 
     613          40 :       DO i = 1, tmc_env%params%nr_temp
     614          26 :          IF (tmc_env%m_env%tree_node_count(i) > 0) &
     615             :             eff(i) = tmc_env%params%move_types%mv_count(0, i)/ &
     616          24 :                      (tmc_env%m_env%tree_node_count(i)*1.0_dp)
     617             :          eff(0) = eff(0) + tmc_env%params%move_types%mv_count(0, i)/ &
     618         102 :                   (SUM(tmc_env%m_env%tree_node_count(1:))*1.0_dp)
     619             :       END DO
     620          14 :    END SUBROUTINE get_subtree_efficiency
     621             : END MODULE tmc_calculations

Generated by: LCOV version 1.15