LCOV - code coverage report
Current view: top level - src/tmc - tmc_calculations.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:71c3ab0) Lines: 48.9 % 180 88
Test Date: 2026-07-25 06:35:44 Functions: 46.2 % 13 6

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief 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         4521 :    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         4521 :       rnd = 0.0_dp
      78              : 
      79         4521 :       CPASSERT(ASSOCIATED(conf))
      80         4521 :       CPASSERT(env_id > 0)
      81         4521 :       CPASSERT(ASSOCIATED(tmc_env))
      82              : 
      83         9042 :       SELECT CASE (tmc_env%params%task_type)
      84              :       CASE (task_type_gaussian_adaptation)
      85              :          !CALL gaussian_adaptation_energy(, )
      86              :       CASE (task_type_MC)
      87         4521 :          IF (tmc_env%params%pressure >= 0.0_dp) THEN
      88        53682 :             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 == 0)
      93          778 :             DEALLOCATE (tmp_cell)
      94              :          END IF
      95              : 
      96              :          ! TODO check for minimal distances
      97         4521 :          flag = .TRUE.
      98            0 :          IF (flag .EQV. .TRUE.) THEN
      99         4521 :             IF (tmc_env%params%print_forces .OR. &
     100              :                 conf%move_type == 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         3923 :                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         4521 :                        cp_to_string(tmc_env%params%task_type))
     119              :       END SELECT
     120              : 
     121              :       ! ---     wait a bit
     122         4521 :       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         4521 :       IF (exact_approx_pot) THEN
     134         4324 :          conf%potential = e_pot
     135              :       ELSE
     136          197 :          conf%e_pot_approx = e_pot
     137              :       END IF
     138         4521 :    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     15013848 :          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)) THEN
     182         5096 :          scaled_hmat(:, :) = tmp_cell%hmat
     183              :       END IF
     184              : 
     185       218382 :       IF (PRESENT(vec)) THEN
     186       862448 :          vec = pbc(r=vec, cell=tmp_cell)
     187              :       END IF
     188              : 
     189       218382 :       IF (PRESENT(vol)) CALL get_cell(cell=tmp_cell, deth=vol)
     190       218382 :       IF (PRESENT(abc)) CALL get_cell(cell=tmp_cell, abc=abc)
     191       218382 :       IF (new_scaled_cell) DEALLOCATE (tmp_cell)
     192              : 
     193       218382 :    END SUBROUTINE get_scaled_cell
     194              : 
     195              : ! **************************************************************************************************
     196              : !> \brief handles properties and calculations of a scaled cell
     197              : !> \param cell original cell
     198              : !> \param scaled_hmat returns the scaled h matrix (matrix of cell vectors)
     199              : !> \param box_scale scaling factors for each direction
     200              : !> \author Mandes 11.2012
     201              : ! **************************************************************************************************
     202         1206 :    SUBROUTINE get_cell_scaling(cell, scaled_hmat, box_scale)
     203              :       TYPE(cell_type), INTENT(IN), POINTER               :: cell
     204              :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN)         :: scaled_hmat
     205              :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: box_scale
     206              : 
     207              :       REAL(KIND=dp), DIMENSION(3)                        :: abc_new, abc_orig
     208              :       TYPE(cell_type), POINTER                           :: tmp_cell
     209              : 
     210         1206 :       CPASSERT(ASSOCIATED(cell))
     211              : 
     212        83214 :       ALLOCATE (tmp_cell)
     213         1206 :       CALL cell_copy(cell_in=cell, cell_out=tmp_cell)
     214        15678 :       tmp_cell%hmat(:, :) = scaled_hmat(:, :)
     215         1206 :       CALL init_cell(cell=tmp_cell)
     216         1206 :       CALL get_cell(cell=cell, abc=abc_orig)
     217         1206 :       CALL get_cell(cell=tmp_cell, abc=abc_new)
     218              : 
     219         4824 :       box_scale(:) = abc_new(:)/abc_orig(:)
     220              : 
     221         1206 :       DEALLOCATE (tmp_cell)
     222         1206 :    END SUBROUTINE get_cell_scaling
     223              : 
     224              : ! **************************************************************************************************
     225              : !> \brief neares distance of atoms within the periodic boundary condition
     226              : !> \param x1 ...
     227              : !> \param x2 ...
     228              : !> \param cell ...
     229              : !> \param box_scale ...
     230              : !> \return ...
     231              : !> \author Mandes 11.2012
     232              : ! **************************************************************************************************
     233       187940 :    FUNCTION nearest_distance(x1, x2, cell, box_scale) RESULT(res)
     234              :       REAL(KIND=dp), DIMENSION(:)                        :: x1, x2
     235              :       TYPE(cell_type), POINTER                           :: cell
     236              :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: box_scale
     237              :       REAL(KIND=dp)                                      :: res
     238              : 
     239              :       REAL(KIND=dp), DIMENSION(3)                        :: dist_vec
     240       187940 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: tmp_box_scale
     241              : 
     242       187940 :       NULLIFY (tmp_box_scale)
     243              : 
     244            0 :       CPASSERT(ASSOCIATED(cell))
     245       187940 :       CPASSERT(SIZE(x1) == 3)
     246       187940 :       CPASSERT(SIZE(x2) == 3)
     247              : 
     248       751760 :       dist_vec(:) = x2(:) - x1(:) ! distance vector between atoms
     249       187940 :       ALLOCATE (tmp_box_scale(3))
     250       187940 :       IF (PRESENT(box_scale)) THEN
     251       187940 :          CPASSERT(SIZE(box_scale) == 3)
     252      1315580 :          tmp_box_scale(:) = box_scale
     253              :       ELSE
     254            0 :          tmp_box_scale(:) = 1.0_dp
     255              :       END IF
     256       187940 :       CALL get_scaled_cell(cell=cell, box_scale=box_scale, vec=dist_vec)
     257       751760 :       res = SQRT(SUM(dist_vec(:)*dist_vec(:)))
     258       187940 :       DEALLOCATE (tmp_box_scale)
     259       187940 :    END FUNCTION nearest_distance
     260              : 
     261              : ! **************************************************************************************************
     262              : !> \brief calculate the geometrical center of an amount of atoms
     263              : !>        array size should be multiple of dim_per_elem
     264              : !> \param pos list of atoms
     265              : !> \param center return value, the geometrical center
     266              : !> \author Mandes 11.2012
     267              : ! **************************************************************************************************
     268         7760 :    SUBROUTINE geometrical_center(pos, center)
     269              :       REAL(KIND=dp), DIMENSION(:)                        :: pos
     270              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: center
     271              : 
     272              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'geometrical_center'
     273              : 
     274              :       INTEGER                                            :: handle, i
     275              : 
     276         7760 :       CPASSERT(ASSOCIATED(center))
     277         7760 :       CPASSERT(SIZE(pos) >= SIZE(center))
     278              : 
     279              :       ! start the timing
     280         7760 :       CALL timeset(routineN, handle)
     281              : 
     282        31040 :       center = 0.0_dp
     283        31138 :       DO i = 1, SIZE(pos), SIZE(center)
     284              :          center(:) = center(:) + &
     285       101272 :                      pos(i:i + SIZE(center) - 1)/(SIZE(pos)/REAL(SIZE(center), KIND=dp))
     286              :       END DO
     287              :       ! end the timing
     288         7760 :       CALL timestop(handle)
     289         7760 :    END SUBROUTINE geometrical_center
     290              : 
     291              : ! **************************************************************************************************
     292              : !> \brief calculate the center of mass of an amount of atoms
     293              : !>        array size should be multiple of dim_per_elem
     294              : !> \param pos ...
     295              : !> \param atoms ...
     296              : !> \param center ...
     297              : !> \param
     298              : !> \param
     299              : !> \author Mandes 11.2012
     300              : ! **************************************************************************************************
     301            0 :    SUBROUTINE center_of_mass(pos, atoms, center)
     302              :       REAL(KIND=dp), DIMENSION(:)                        :: pos
     303              :       TYPE(tmc_atom_type), DIMENSION(:), OPTIONAL        :: atoms
     304              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: center
     305              : 
     306              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'center_of_mass'
     307              : 
     308              :       INTEGER                                            :: handle, i
     309              :       REAL(KIND=dp)                                      :: mass_sum, mass_tmp
     310              : 
     311            0 :       CPASSERT(ASSOCIATED(center))
     312            0 :       CPASSERT(SIZE(pos) >= SIZE(center))
     313              : 
     314              :       ! start the timing
     315            0 :       CALL timeset(routineN, handle)
     316              : 
     317            0 :       center = 0.0_dp
     318            0 :       mass_sum = 0.0_dp
     319            0 :       DO i = 1, SIZE(pos), SIZE(center)
     320            0 :          IF (PRESENT(atoms)) THEN
     321            0 :             CPASSERT(SIZE(atoms) == SIZE(pos)/SIZE(center))
     322            0 :             mass_tmp = atoms(INT(i/REAL(SIZE(center), KIND=dp)) + 1)%mass
     323              :             center(:) = center(:) + pos(i:i + SIZE(center) - 1)/ &
     324            0 :                         (SIZE(pos)/REAL(SIZE(center), KIND=dp))*mass_tmp
     325            0 :             mass_sum = mass_sum + mass_tmp
     326              :          ELSE
     327            0 :             CPWARN("try to calculate center of mass without any mass.")
     328              :             center(:) = center(:) + pos(i:i + SIZE(center) - 1)/ &
     329            0 :                         (SIZE(pos)/REAL(SIZE(center), KIND=dp))
     330            0 :             mass_sum = 1.0_dp
     331              :          END IF
     332              :       END DO
     333            0 :       center(:) = center(:)/mass_sum
     334              :       ! end the timing
     335            0 :       CALL timestop(handle)
     336            0 :    END SUBROUTINE center_of_mass
     337              : 
     338              : ! **************************************************************************************************
     339              : !> \brief routine sets initial velocity, using the Box-Muller Method for Normal
     340              : !>         (Gaussian) Deviates
     341              : !> \param vel ...
     342              : !> \param atoms ...
     343              : !> \param temerature ...
     344              : !> \param rng_stream ...
     345              : !> \param rnd_seed ...
     346              : !> \author Mandes 11.2012
     347              : ! **************************************************************************************************
     348            0 :    SUBROUTINE init_vel(vel, atoms, temerature, rng_stream, rnd_seed)
     349              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: vel
     350              :       TYPE(tmc_atom_type), DIMENSION(:), POINTER         :: atoms
     351              :       REAL(KIND=dp)                                      :: temerature
     352              :       TYPE(rng_stream_type), INTENT(INOUT)               :: rng_stream
     353              :       REAL(KIND=dp), DIMENSION(3, 2, 3)                  :: rnd_seed
     354              : 
     355              :       INTEGER                                            :: i
     356              :       REAL(KIND=dp)                                      :: kB, mass_tmp, rnd1, rnd2
     357              : 
     358            0 :       kB = boltzmann/joule
     359              : 
     360            0 :       CPASSERT(ASSOCIATED(vel))
     361            0 :       CPASSERT(ASSOCIATED(atoms))
     362              : 
     363            0 :       CALL rng_stream%set(bg=rnd_seed(:, :, 1), cg=rnd_seed(:, :, 2), ig=rnd_seed(:, :, 3))
     364            0 :       DO i = 1, SIZE(vel)
     365            0 :          rnd1 = rng_stream%next()
     366            0 :          rnd2 = rng_stream%next()
     367              : 
     368            0 :          mass_tmp = atoms(INT(i/REAL(3, KIND=dp)) + 1)%mass
     369              : 
     370              :          vel(i) = SQRT(-2.0_dp*LOG(rnd1))*COS(2.0_dp*PI*rnd2)* &
     371            0 :                   SQRT(kB*temerature/mass_tmp)
     372              :       END DO
     373            0 :       CALL rng_stream%get(bg=rnd_seed(:, :, 1), cg=rnd_seed(:, :, 2), ig=rnd_seed(:, :, 3))
     374              : 
     375            0 :    END SUBROUTINE init_vel
     376              : 
     377              : ! **************************************************************************************************
     378              : !> \brief routine calculates the kinetic energy, using the velocities
     379              : !>        and atom mass, both in atomic units
     380              : !> \param vel ...
     381              : !> \param atoms ...
     382              : !> \return ...
     383              : !> \author Mandes 11.2012
     384              : ! **************************************************************************************************
     385            0 :    FUNCTION calc_e_kin(vel, atoms) RESULT(ekin)
     386              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: vel
     387              :       TYPE(tmc_atom_type), DIMENSION(:), POINTER         :: atoms
     388              :       REAL(KIND=dp)                                      :: ekin
     389              : 
     390              :       INTEGER                                            :: i
     391              :       REAL(KIND=dp)                                      :: mass_tmp
     392              : 
     393            0 :       CPASSERT(ASSOCIATED(vel))
     394            0 :       CPASSERT(ASSOCIATED(atoms))
     395            0 :       ekin = 0.0_dp
     396              : 
     397            0 :       DO i = 1, SIZE(vel)
     398            0 :          mass_tmp = atoms(INT(i/REAL(3, KIND=dp)) + 1)%mass
     399            0 :          ekin = ekin + 0.5_dp*mass_tmp*vel(i)*vel(i)
     400              :       END DO
     401            0 :    END FUNCTION calc_e_kin
     402              : 
     403              : ! **************************************************************************************************
     404              : !> \brief assuming an (exponential) decreasing function, this function
     405              : !>        extrapolate the converged value
     406              : !> \param v1 function values
     407              : !> \param v2 function values
     408              : !> \param v3 function values
     409              : !> \param extrapolate extrapolated final value (result)
     410              : !> \param res_err error of the result
     411              : !> \author Mandes 12.2012
     412              : ! **************************************************************************************************
     413            0 :    SUBROUTINE three_point_extrapolate(v1, v2, v3, extrapolate, res_err)
     414              :       REAL(KIND=dp)                            :: v1, v2, v3
     415              :       REAL(KIND=dp), INTENT(OUT)               :: extrapolate, res_err
     416              : 
     417              :       REAL(KIND=dp)                            :: e1, e2, e3
     418              :       REAL(KIND=dp)                            :: a, b, c, d12, d23, ddd
     419              : 
     420              :       extrapolate = HUGE(extrapolate)
     421              : 
     422              :       !> solve({exp(a+b)+c = e1, exp(2*a+b)+c = e2, exp(3*a+b)+c = e3}, [a, b, c])
     423              :       !> solve({a*b+c = e1, a^2*b+c = e2, a^3*b+c = e3}, [a, b, c]);
     424              :       !   [[                                   3                   2         ]]
     425              :       !   [[    -e3 + e2              (e1 - e2)                 -e2  + e1 e3 ]]
     426              :       !   [[a = --------, b = ---------------------------, c = --------------]]
     427              :       !   [[    e1 - e2       (-e3 + e2) (e3 - 2 e2 + e1)      e3 - 2 e2 + e1]]
     428              : 
     429              :       ! sort so that e1>=e2>=e3
     430            0 :       e1 = v1; e2 = v2; e3 = v3
     431            0 :       CALL swap(e1, e2)
     432            0 :       CALL swap(e1, e3)
     433            0 :       CALL swap(e2, e3)
     434              :       ! we need extra care if some of the difference e1-e2, e3-e2 are nearly zero,
     435              :       !  since the formulae suffer from sever loss of precision
     436            0 :       d12 = e1 - e2
     437            0 :       d23 = e2 - e3
     438            0 :       ddd = d12 - d23
     439            0 :       IF (d12 == 0 .OR. d23 == 0 .OR. ABS(ddd) == 0) THEN
     440              :          ! a degenerate case, we do no extrapolation
     441            0 :          extrapolate = e3
     442            0 :          res_err = e1 - e3
     443              :       ELSE
     444            0 :          a = d23/d12
     445            0 :          b = (d12**3/(d23*ddd))
     446            0 :          c = e2 - (d12*d23)/ddd
     447              :          ! extrapolation, let's only look 4 iterations ahead, more is presumably anyway not accurate
     448              :          ! fewer is maybe more stable
     449            0 :          extrapolate = a**7*b + c
     450            0 :          res_err = e3 - extrapolate
     451              :       END IF
     452            0 :       CPASSERT(extrapolate /= HUGE(extrapolate))
     453              :    CONTAINS
     454              : ! **************************************************************************************************
     455              : !> \brief ...
     456              : !> \param x1 ...
     457              : !> \param x2 ...
     458              : ! **************************************************************************************************
     459            0 :       SUBROUTINE swap(x1, x2)
     460              :       REAL(KIND=dp)                                      :: x1, x2
     461              : 
     462              :       REAL(KIND=dp)                                      :: tmp
     463              : 
     464            0 :          IF (x2 > x1) THEN
     465            0 :             tmp = x2
     466            0 :             x2 = x1
     467            0 :             x1 = tmp
     468              :          END IF
     469            0 :       END SUBROUTINE swap
     470              :    END SUBROUTINE three_point_extrapolate
     471              : 
     472              : ! **************************************************************************************************
     473              : !> \brief calculates the probability of acceptance for given intervals of the
     474              : !>        exact energy
     475              : !> \param E_n_mu energy distribution of new configuration
     476              : !> \param E_n_sigma energy distribution of new configuration
     477              : !> \param E_o_mu energy distribution of old configuration
     478              : !> \param E_o_sigma energy distribution of old configuration
     479              : !> \param E_classical_diff the difference in approximated energies for the
     480              : !>        old and new configuration (E_o-E_n)
     481              : !> \param prior_mu energy distribution of the already converged
     482              : !>         energies
     483              : !> \param prior_sigma energy distribution of the already converged
     484              : !>         energies
     485              : !> \param p the random number, the criteria has to be smaller than this
     486              : !> \param beta ...
     487              : !> \return return probability of acceptance
     488              : !> \author Mandes 12.2012
     489              : ! **************************************************************************************************
     490            0 :    FUNCTION compute_prob(E_n_mu, E_n_sigma, E_o_mu, E_o_sigma, E_classical_diff, &
     491              :                          prior_mu, prior_sigma, p, beta) RESULT(prob)
     492              :       REAL(KIND=dp)                                      :: E_n_mu, E_n_sigma, E_o_mu, E_o_sigma, &
     493              :                                                             E_classical_diff, prior_mu, &
     494              :                                                             prior_sigma, p, beta, prob
     495              : 
     496              : !    INTEGER       :: io,in
     497              : !    REAL(KIND=dp) :: diff,E_n,E_o,surface,lower_bound,upper_bound,delta
     498              : 
     499              :       prob = 0.5_dp*ERFC(-0.5_dp*SQRT(2.0_dp)*( &
     500              :                          (-prior_sigma**2 - E_o_sigma**2 - E_n_sigma**2)*LOG(p) + &
     501              :                          ((E_classical_diff - E_n_mu + E_o_mu)*prior_sigma**2 - prior_mu*(E_n_sigma**2 + E_o_sigma**2))*beta)/ &
     502            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))
     503              : 
     504            0 :       prob = MIN(1.0_dp - EPSILON(1.0_dp), MAX(EPSILON(1.0_dp), prob))
     505              : 
     506            0 :    END FUNCTION compute_prob
     507              : 
     508              : ! **************************************************************************************************
     509              : !> \brief extimates the probability of acceptance considering the intermetiate
     510              : !>        step energies
     511              : !> \param elem_old old/parent sub tree element
     512              : !> \param elem_new new/actual sub tree element, which schould be checked
     513              : !> \param E_classical_diff difference in the classical energy of the old and
     514              : !>        new configuration
     515              : !> \param rnd_nr random number acceptance check will be done with
     516              : !> \param beta 1/(kB*T) can differ for different acceptance checks
     517              : !> \param tmc_params TMC environment parameters
     518              : !> \return estimated acceptance probability
     519              : !> \author Mandes 12.2012
     520              : ! **************************************************************************************************
     521            0 :    FUNCTION compute_estimated_prob(elem_old, elem_new, E_classical_diff, &
     522              :                                    rnd_nr, beta, tmc_params) RESULT(prob)
     523              :       TYPE(tree_type), POINTER                           :: elem_old, elem_new
     524              :       REAL(KIND=dp)                                      :: E_classical_diff, rnd_nr, beta
     525              :       TYPE(tmc_param_type), POINTER                      :: tmc_params
     526              :       REAL(KIND=dp)                                      :: prob
     527              : 
     528              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_estimated_prob'
     529              : 
     530              :       INTEGER                                            :: handle
     531              :       REAL(KIND=dp)                                      :: E_mu_tmp, E_n_mu, E_n_sigma, E_o_mu, &
     532              :                                                             E_o_sigma, E_sigma_tmp, prior_sigma
     533              : 
     534            0 :       CPASSERT(ASSOCIATED(elem_old))
     535            0 :       CPASSERT(ASSOCIATED(elem_new))
     536            0 :       CPASSERT(rnd_nr > 0.0_dp)
     537              : 
     538              :       ! start the timing
     539            0 :       CALL timeset(routineN, handle)
     540              : 
     541            0 :       prob = -1.0_dp
     542              :       IF ((elem_new%scf_energies_count >= 3) .AND. &
     543            0 :           (elem_old%scf_energies_count >= 3) .AND. &
     544              :           tmc_params%prior_NMC_acc%counter >= 10) THEN
     545              :          !-- first the new element energy estimation
     546              :          ! using 3 point extrapolation of two different intervals -> more stable estimation
     547              :          ! the energies are sorted in the three_point_extrapolate routine !
     548              :          ! But with array of length 4 we have to select the 3 connected ones
     549              :          CALL three_point_extrapolate(v1=elem_new%scf_energies(MOD(elem_new%scf_energies_count - 3, 4) + 1), &
     550              :                                       v2=elem_new%scf_energies(MOD(elem_new%scf_energies_count - 2, 4) + 1), &
     551              :                                       v3=elem_new%scf_energies(MOD(elem_new%scf_energies_count - 1, 4) + 1), &
     552            0 :                                       extrapolate=E_mu_tmp, res_err=E_sigma_tmp)
     553            0 :          IF ((elem_new%scf_energies_count > 3)) THEN
     554              :             CALL three_point_extrapolate(v1=elem_new%scf_energies(MOD(elem_new%scf_energies_count - 4, 4) + 1), &
     555              :                                          v2=elem_new%scf_energies(MOD(elem_new%scf_energies_count - 3, 4) + 1), &
     556              :                                          v3=elem_new%scf_energies(MOD(elem_new%scf_energies_count - 2, 4) + 1), &
     557            0 :                                          extrapolate=E_n_mu, res_err=E_n_sigma)
     558            0 :             E_n_sigma = MAX(E_n_sigma, ABS(E_n_mu - E_mu_tmp))
     559              :          ELSE
     560            0 :             E_n_sigma = E_sigma_tmp
     561            0 :             E_n_mu = E_mu_tmp
     562              :          END IF
     563              : 
     564              :          !-- the old/parent element energy estimation
     565              :          CALL three_point_extrapolate(v1=elem_old%scf_energies(MOD(elem_old%scf_energies_count - 3, 4) + 1), &
     566              :                                       v2=elem_old%scf_energies(MOD(elem_old%scf_energies_count - 2, 4) + 1), &
     567              :                                       v3=elem_old%scf_energies(MOD(elem_old%scf_energies_count - 1, 4) + 1), &
     568            0 :                                       extrapolate=E_mu_tmp, res_err=E_sigma_tmp)
     569            0 :          IF ((elem_old%scf_energies_count > 3)) THEN
     570              :             CALL three_point_extrapolate(v1=elem_old%scf_energies(MOD(elem_old%scf_energies_count - 4, 4) + 1), &
     571              :                                          v2=elem_old%scf_energies(MOD(elem_old%scf_energies_count - 3, 4) + 1), &
     572              :                                          v3=elem_old%scf_energies(MOD(elem_old%scf_energies_count - 2, 4) + 1), &
     573            0 :                                          extrapolate=E_o_mu, res_err=E_o_sigma)
     574            0 :             E_o_sigma = MAX(E_o_sigma, ABS(E_o_mu - E_mu_tmp))
     575              :          ELSE
     576            0 :             E_o_sigma = E_sigma_tmp
     577            0 :             E_o_mu = E_mu_tmp
     578              :          END IF
     579              : 
     580              :          ! calculate the estimation for the average of the trajectory elements
     581              :          prior_sigma = SQRT(ABS(tmc_params%prior_NMC_acc%aver_2 &
     582            0 :                                 - tmc_params%prior_NMC_acc%aver**2))
     583              : 
     584              :          ! calculate the probability of acceptance for those two elements with their energy
     585              :          ! swap and 2 potential moves are distinguished using the difference in classical energy and different betas
     586              :          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, &
     587              :                              E_classical_diff=E_classical_diff, &
     588              :                              prior_mu=tmc_params%prior_NMC_acc%aver, prior_sigma=prior_sigma, &
     589            0 :                              p=rnd_nr, beta=beta)
     590              :       END IF
     591              :       ! end the timing
     592            0 :       CALL timestop(handle)
     593            0 :    END FUNCTION compute_estimated_prob
     594              : 
     595              : ! **************************************************************************************************
     596              : !> \brief calculated the rate of used tree elements to created tree elements
     597              : !>        for every temperature
     598              : !> \param tmc_env TMC environment variables
     599              : !> \param eff result efficiency
     600              : !> \author Mandes 01.2013
     601              : ! **************************************************************************************************
     602           14 :    SUBROUTINE get_subtree_efficiency(tmc_env, eff)
     603              :       TYPE(tmc_env_type), POINTER                        :: tmc_env
     604              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eff
     605              : 
     606              :       INTEGER                                            :: i
     607              : 
     608           14 :       CPASSERT(ASSOCIATED(tmc_env))
     609           14 :       CPASSERT(ASSOCIATED(tmc_env%params))
     610           14 :       CPASSERT(ASSOCIATED(tmc_env%m_env))
     611              : 
     612           54 :       eff(:) = 0.0_dp
     613              : 
     614           40 :       DO i = 1, tmc_env%params%nr_temp
     615           26 :          IF (tmc_env%m_env%tree_node_count(i) > 0) THEN
     616              :             eff(i) = tmc_env%params%move_types%mv_count(0, i)/ &
     617           24 :                      (tmc_env%m_env%tree_node_count(i)*1.0_dp)
     618              :          END IF
     619              :          eff(0) = eff(0) + tmc_env%params%move_types%mv_count(0, i)/ &
     620          102 :                   (SUM(tmc_env%m_env%tree_node_count(1:))*1.0_dp)
     621              :       END DO
     622           14 :    END SUBROUTINE get_subtree_efficiency
     623              : END MODULE tmc_calculations
        

Generated by: LCOV version 2.0-1