LCOV - code coverage report
Current view: top level - src/tmc - tmc_tree_search.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:936074a) Lines: 83.0 % 247 205
Test Date: 2025-12-04 06:27:48 Functions: 92.3 % 13 12

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief tree nodes search etc.
      10              : !> \par History
      11              : !>      11.2012 created [Mandes Schoenherr]
      12              : !> \author Mandes
      13              : ! **************************************************************************************************
      14              : 
      15              : MODULE tmc_tree_search
      16              :    USE cp_log_handling,                 ONLY: cp_to_string
      17              :    USE kinds,                           ONLY: dp
      18              :    USE tmc_stati,                       ONLY: TMC_STATUS_WAIT_FOR_NEW_TASK
      19              :    USE tmc_tree_references,             ONLY: add_to_references,&
      20              :                                               search_and_remove_reference_in_list
      21              :    USE tmc_tree_types,                  ONLY: &
      22              :         elem_array_type, global_tree_type, status_accepted, status_accepted_result, &
      23              :         status_calc_approx_ener, status_calculate_MD, status_calculate_NMC_steps, &
      24              :         status_calculate_energy, status_calculated, status_cancel_ener, status_cancel_nmc, &
      25              :         status_canceled_ener, status_canceled_nmc, status_created, status_deleted, &
      26              :         status_deleted_result, status_rejected, status_rejected_result, tree_type
      27              :    USE tmc_types,                       ONLY: tmc_env_type
      28              : #include "../base/base_uses.f90"
      29              : 
      30              :    IMPLICIT NONE
      31              : 
      32              :    PRIVATE
      33              : 
      34              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'tmc_tree_search'
      35              : 
      36              :    PUBLIC :: most_prob_end
      37              :    PUBLIC :: search_next_energy_calc
      38              :    PUBLIC :: search_canceling_elements
      39              :    PUBLIC :: search_parent_element, get_subtree_elements_to_check
      40              :    PUBLIC :: search_next_gt_element_to_check
      41              :    PUBLIC :: search_end_of_clean_g_tree, search_end_of_clean_tree
      42              :    PUBLIC :: count_prepared_nodes_in_trees, count_nodes_in_trees
      43              : CONTAINS
      44              : 
      45              :    !============================================================================
      46              :    ! search tree node
      47              :    !============================================================================
      48              : ! **************************************************************************************************
      49              : !> \brief search most probable end in global tree to create a new tree node
      50              : !>         using the acceptance probabilities for each move type
      51              : !>          of each temperature
      52              : !>        routine distinguishes the search for most probable node
      53              : !>         for energy and most probable node with open end
      54              : !>         for new configuration
      55              : !>        In case of searching open end:
      56              : !>         routine stops in branch with canceled NMC,
      57              : !>         using this a one possibility
      58              : !> \param global_tree_elem starting point for search
      59              : !> \param prob return value, the probability of reaching the tree node
      60              : !> \param n_acc drection of branch the next tree node should extend
      61              : !> \param search_energy_node ...
      62              : !> \parma search_energy_node flag if configuration for calculating exact
      63              : !>        energy should be searched
      64              : !> \author Mandes 12.2012
      65              : ! **************************************************************************************************
      66       357506 :    RECURSIVE SUBROUTINE most_prob_end(global_tree_elem, prob, n_acc, &
      67              :                                       search_energy_node)
      68              :       TYPE(global_tree_type), POINTER                    :: global_tree_elem
      69              :       REAL(KIND=dp), INTENT(OUT)                         :: prob
      70              :       LOGICAL, INTENT(INOUT)                             :: n_acc
      71              :       LOGICAL, OPTIONAL                                  :: search_energy_node
      72              : 
      73              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'most_prob_end'
      74              : 
      75              :       INTEGER                                            :: handle
      76              :       LOGICAL                                            :: check_accepted, check_rejected, keep_on, &
      77              :                                                             tmp_acc, tmp_nacc
      78              :       REAL(KIND=dp)                                      :: prob_n_acc, prob_n_nacc
      79              :       TYPE(global_tree_type), POINTER                    :: ptr_acc, ptr_nacc
      80              :       TYPE(tree_type), POINTER                           :: st_elem
      81              : 
      82       178753 :       NULLIFY (st_elem, ptr_acc, ptr_nacc)
      83              : 
      84       178753 :       prob_n_acc = -100000
      85       178753 :       prob_n_nacc = -100000
      86       178753 :       check_accepted = .FALSE.
      87       178753 :       check_rejected = .FALSE.
      88       178753 :       keep_on = .TRUE.
      89              : 
      90       178753 :       CPASSERT(ASSOCIATED(global_tree_elem))
      91       178753 :       st_elem => global_tree_elem%conf(global_tree_elem%mv_conf)%elem
      92       178753 :       CPASSERT(ASSOCIATED(st_elem))
      93              : 
      94              :       ! start the timing
      95       178753 :       CALL timeset(routineN, handle)
      96              : 
      97              :       !-- follow trajectory until end
      98              :       !-- evaluate following elements using status, and probabilites
      99       178753 :       SELECT CASE (global_tree_elem%stat)
     100              :       CASE (status_accepted, status_accepted_result)
     101       169495 :          check_accepted = .TRUE.
     102              :       CASE (status_rejected, status_rejected_result)
     103       169495 :          check_rejected = .TRUE.
     104              :       CASE DEFAULT
     105              :          !-- set directions of searching
     106       178753 :          SELECT CASE (st_elem%stat)
     107              :          CASE (status_created, status_canceled_ener)
     108              :             ! just for searching next element to calculate energy for (found)
     109           21 :             IF (PRESENT(search_energy_node)) THEN
     110           21 :                prob = 0.0_dp ! = log(1)
     111           21 :                n_acc = .FALSE. ! not needed, but maybe for initialisation
     112           21 :                keep_on = .FALSE.
     113              :             ELSE
     114              :                check_accepted = .TRUE.
     115              :                check_rejected = .TRUE.
     116              :             END IF
     117              :          CASE (status_canceled_nmc)
     118              :             ! just for search new element to create (found)
     119              :             ! canceled elements can be reactivated
     120              :             ! the parent element is returned,
     121              :             !  the create_new_pt_tree_node check for existing of this node
     122            0 :             IF (.NOT. PRESENT(search_energy_node)) THEN
     123            0 :                prob = 0.0_dp
     124            0 :                n_acc = ASSOCIATED(global_tree_elem%parent%acc, global_tree_elem)
     125            0 :                global_tree_elem => global_tree_elem%parent
     126            0 :                keep_on = .FALSE.
     127              :             END IF
     128              :          CASE (status_calculated, status_calculate_energy, &
     129              :                status_accepted_result, status_accepted, &
     130              :                status_rejected, status_rejected_result)
     131              :             ! status accepted and rejection needed for swapped
     132              :             !  configurations in parallel tempering
     133            0 :             check_accepted = .TRUE.
     134            0 :             check_rejected = .TRUE.
     135              :          CASE (status_calculate_MD, status_calculate_NMC_steps, &
     136              :                status_calc_approx_ener)
     137              :             ! just for searching next element to create
     138            0 :             IF (.NOT. PRESENT(search_energy_node)) THEN
     139            0 :                check_rejected = .TRUE.
     140              :             END IF
     141              :          CASE (status_cancel_nmc, status_cancel_ener)
     142              :          CASE DEFAULT
     143              :             CALL cp_abort(__LOCATION__, &
     144              :                           "unknown sub tree element status "// &
     145           21 :                           cp_to_string(st_elem%stat))
     146              :          END SELECT
     147              :       END SELECT
     148              : 
     149       178753 :       IF (keep_on) THEN
     150              :          !-- recursive search, remembering lowest element (tree end),
     151              :          !     and multiply probabilities to go there
     152              :          !-- search in ACCEPTED branch
     153       178732 :          IF (check_accepted) THEN
     154              :             ! test if probable accepted child exist and is not rejected
     155         9237 :             IF (ASSOCIATED(global_tree_elem%acc)) THEN
     156         7607 :                ptr_acc => global_tree_elem%acc
     157         7607 :                IF (PRESENT(search_energy_node)) THEN
     158              :                   CALL most_prob_end(global_tree_elem=ptr_acc, prob=prob_n_acc, &
     159              :                                      n_acc=tmp_acc, &
     160         3808 :                                      search_energy_node=search_energy_node)
     161              :                ELSE
     162              :                   CALL most_prob_end(global_tree_elem=ptr_acc, prob=prob_n_acc, &
     163         3799 :                                      n_acc=tmp_acc)
     164              :                END IF
     165              :                !-- do probability multiplication
     166              :                !    (in logscale because of really small probabilities)
     167         7607 :                prob_n_acc = prob_n_acc + LOG(global_tree_elem%prob_acc)
     168              :             ELSE
     169              :                ! prob of going in acc or rej direction is
     170              :                !   calculated in parent element
     171         1630 :                prob_n_acc = LOG(global_tree_elem%prob_acc)
     172         1630 :                IF (PRESENT(search_energy_node)) prob_n_acc = -100000
     173         1630 :                ptr_acc => global_tree_elem
     174         1630 :                tmp_acc = .TRUE.
     175              :             END IF
     176              :          END IF
     177              : 
     178              :          !-- search in REJECTED branch
     179       178732 :          IF (check_rejected) THEN
     180              :             ! test if probabliy rejected child exist
     181       169495 :             IF (ASSOCIATED(global_tree_elem%nacc)) THEN
     182       161897 :                ptr_nacc => global_tree_elem%nacc
     183       161897 :                IF (PRESENT(search_energy_node)) THEN
     184              :                   CALL most_prob_end(global_tree_elem=ptr_nacc, prob=prob_n_nacc, &
     185              :                                      n_acc=tmp_nacc, &
     186        80957 :                                      search_energy_node=search_energy_node)
     187              :                ELSE
     188              :                   CALL most_prob_end(global_tree_elem=ptr_nacc, prob=prob_n_nacc, &
     189        80940 :                                      n_acc=tmp_nacc)
     190              :                END IF
     191              :                !-- do probability multiplication
     192              :                !     (in logscale because of really small probabilities)
     193       161897 :                prob_n_nacc = prob_n_nacc + LOG(1 - global_tree_elem%prob_acc)
     194              :             ELSE
     195              :                ! prob of going in acc or rej direction is
     196              :                !   calculated in parent element
     197         7598 :                prob_n_nacc = LOG(1 - global_tree_elem%prob_acc)
     198         7598 :                IF (PRESENT(search_energy_node)) prob_n_nacc = -100000
     199         7598 :                ptr_nacc => global_tree_elem
     200         7598 :                tmp_nacc = .FALSE.
     201              :             END IF
     202              :          END IF
     203              :          ! test which direction is more likely
     204              :          !   and set result pointer and probability,
     205              :          ! remembering the direction
     206       178732 :          IF (prob_n_acc >= prob_n_nacc) THEN
     207        93976 :             prob = prob_n_acc
     208        93976 :             global_tree_elem => ptr_acc
     209        93976 :             n_acc = tmp_acc
     210              :          ELSE
     211        84756 :             prob = prob_n_nacc
     212        84756 :             global_tree_elem => ptr_nacc
     213        84756 :             n_acc = tmp_nacc
     214              :          END IF
     215              :       END IF
     216              :       ! end the timing
     217       178753 :       CALL timestop(handle)
     218       178753 :    END SUBROUTINE most_prob_end
     219              : 
     220              : ! **************************************************************************************************
     221              : !> \brief gt_head head of the global tree
     222              : !> \param gt_head ...
     223              : !> \param new_gt_elem return value the energy should be calculated for
     224              : !> \param stat routine status return value
     225              : !> \param react_count reactivation counter
     226              : !> \author Mandes 12.2012
     227              : ! **************************************************************************************************
     228         9270 :    SUBROUTINE search_next_energy_calc(gt_head, new_gt_elem, stat, react_count)
     229              :       TYPE(global_tree_type), POINTER                    :: gt_head, new_gt_elem
     230              :       INTEGER                                            :: stat, react_count
     231              : 
     232              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'search_next_energy_calc'
     233              : 
     234              :       INTEGER                                            :: handle
     235              :       LOGICAL                                            :: flag
     236              :       REAL(KIND=dp)                                      :: prob
     237              : 
     238              :       prob = 0.0_dp
     239         4635 :       flag = .FALSE.
     240         4635 :       CPASSERT(ASSOCIATED(gt_head))
     241              : 
     242              :       ! start the timing
     243         4635 :       CALL timeset(routineN, handle)
     244              : 
     245         4635 :       new_gt_elem => gt_head
     246              : 
     247              :       CALL most_prob_end(global_tree_elem=new_gt_elem, prob=prob, n_acc=flag, &
     248         4635 :                          search_energy_node=.TRUE.)
     249              : 
     250         4635 :       stat = status_created
     251              :       ! set status for master
     252              :       !   (if TMC_STATUS_WAIT_FOR_NEW_TASK, no calculation necessary)
     253         4635 :       IF (.NOT. ASSOCIATED(new_gt_elem) .OR. (EXP(prob) < 1.0E-10)) THEN
     254         4614 :          stat = TMC_STATUS_WAIT_FOR_NEW_TASK
     255              :       ELSE
     256              :          ! reactivate canceled elements
     257           21 :          IF (new_gt_elem%conf(new_gt_elem%mv_conf)%elem%stat == &
     258              :              status_canceled_ener) THEN
     259            0 :             CALL add_to_references(gt_elem=new_gt_elem)
     260            0 :             react_count = react_count + 1
     261            0 :             new_gt_elem%conf(new_gt_elem%mv_conf)%elem%stat = status_created
     262              :          END IF
     263              :          ! if elem status is not status_created
     264           21 :          IF (new_gt_elem%conf(new_gt_elem%mv_conf)%elem%stat /= status_created) THEN
     265            0 :             stat = TMC_STATUS_WAIT_FOR_NEW_TASK
     266              :          END IF
     267              :       END IF
     268              :       ! end the timing
     269         4635 :       CALL timestop(handle)
     270         4635 :    END SUBROUTINE search_next_energy_calc
     271              : 
     272              : ! **************************************************************************************************
     273              : !> \brief searching the parent element (last accepted configuration before)
     274              : !> \param current actual tree element
     275              : !> \return parent tree element (last accepted one)
     276              : !> \author Mandes 12.2012
     277              : !> \note routine searches last (assumed) accepted element in subtree
     278              : ! **************************************************************************************************
     279      3026868 :    RECURSIVE FUNCTION search_parent_element(current) RESULT(parent)
     280              :       TYPE(tree_type), POINTER                           :: current, parent
     281              : 
     282              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'search_parent_element'
     283              : 
     284              :       INTEGER                                            :: handle
     285              : 
     286      1513434 :       CPASSERT(ASSOCIATED(current))
     287              : 
     288              :       ! start the timing
     289      1513434 :       CALL timeset(routineN, handle)
     290              : 
     291      1513434 :       IF (ASSOCIATED(current%parent)) THEN
     292              :          ! the result value if the child (we came from) is in acc direction
     293      1497200 :          parent => current%parent
     294      1497200 :          IF (ASSOCIATED(parent%nacc, current)) THEN
     295      1221603 :             parent => search_parent_element(parent)
     296              :          END IF
     297              :       ELSE
     298              :          ! if parent not exist, we are at the head of the tree
     299        16234 :          parent => current
     300              :       END IF
     301              :       ! end the timing
     302      1513434 :       CALL timestop(handle)
     303      1513434 :       CPASSERT(ASSOCIATED(parent))
     304      1513434 :    END FUNCTION search_parent_element
     305              : 
     306              : ! **************************************************************************************************
     307              : !> \brief search the next global element in the Markov Chain to check
     308              : !> \param ptr start point for search, should be on the known Markov Chain
     309              : !> \param found flag if routine was successful
     310              : !> \author Mandes 12.2012
     311              : ! **************************************************************************************************
     312      3032008 :    RECURSIVE SUBROUTINE search_next_gt_element_to_check(ptr, found)
     313              :       TYPE(global_tree_type), POINTER                    :: ptr
     314              :       LOGICAL                                            :: found
     315              : 
     316              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'search_next_gt_element_to_check'
     317              : 
     318              :       INTEGER                                            :: handle
     319              : 
     320      1516004 :       found = .FALSE.
     321              : 
     322      1516004 :       CPASSERT(ASSOCIATED(ptr))
     323              : 
     324              :       ! start the timing
     325      1516004 :       CALL timeset(routineN, handle)
     326              : 
     327              :       ! -- global tree status is not updated after receiving calculations
     328              :       !    (not intrinsically), hence try to check elements with could be ready
     329      1778985 :       SELECT CASE (ptr%stat)
     330              :       CASE (status_accepted_result)
     331       262981 :          IF (ASSOCIATED(ptr%acc)) THEN
     332       262153 :             ptr => ptr%acc
     333       262153 :             CALL search_next_gt_element_to_check(ptr, found)
     334              :          END IF
     335              :       CASE (status_rejected_result)
     336       974636 :          IF (ASSOCIATED(ptr%nacc)) THEN
     337       970837 :             ptr => ptr%nacc
     338       970837 :             CALL search_next_gt_element_to_check(ptr, found)
     339              :          END IF
     340              :       CASE (status_calculate_energy, status_created, &
     341              :             status_calculate_MD, status_calculated, status_calculate_NMC_steps, &
     342              :             status_calc_approx_ener, status_accepted, status_rejected)
     343       278387 :          found = .TRUE.
     344              :       CASE (status_cancel_nmc, status_cancel_ener, status_canceled_nmc, &
     345              :             status_canceled_ener)
     346              :          ! nothing to do
     347              :       CASE DEFAULT
     348              :          CALL cp_abort(__LOCATION__, &
     349              :                        "unexpected status "//cp_to_string(ptr%stat)// &
     350      1516004 :                        "of global tree elem "//cp_to_string(ptr%nr))
     351              :       END SELECT
     352              :       ! end the timing
     353      1516004 :       CALL timestop(handle)
     354              : 
     355      1516004 :       CPASSERT(ASSOCIATED(ptr))
     356      1516004 :    END SUBROUTINE search_next_gt_element_to_check
     357              : 
     358              : ! **************************************************************************************************
     359              : !> \brief get the changed element of the actual global tree element and its
     360              : !>        related last accepted parent
     361              : !> \param gt_act_elem actual global tree element
     362              : !> \param elem1 two subtree elements which should be compared
     363              : !> \param elem2 two subtree elements which should be compared
     364              : !> \author Mandes 12.2012
     365              : ! **************************************************************************************************
     366       566000 :    SUBROUTINE get_subtree_elements_to_check(gt_act_elem, elem1, elem2)
     367              :       TYPE(global_tree_type), POINTER                    :: gt_act_elem
     368              :       TYPE(tree_type), INTENT(OUT), POINTER              :: elem1, elem2
     369              : 
     370              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'get_subtree_elements_to_check'
     371              : 
     372              :       INTEGER                                            :: handle
     373              : 
     374       283000 :       CPASSERT(ASSOCIATED(gt_act_elem))
     375              : 
     376              :       ! start the timing
     377       283000 :       CALL timeset(routineN, handle)
     378              : 
     379       283000 :       IF (gt_act_elem%swaped) THEN
     380              :          !------------------------------------------------------------
     381              :          !-- take the last accepted configurations for check of both configurations, because
     382              :          !-- in case of swapping, the last accepted elements have to be compared
     383          336 :          IF (gt_act_elem%conf_n_acc(gt_act_elem%conf(gt_act_elem%mv_conf)%elem%sub_tree_nr)) THEN
     384          184 :             elem1 => gt_act_elem%conf(gt_act_elem%mv_conf)%elem
     385              :          ELSE
     386          152 :             elem1 => search_parent_element(gt_act_elem%conf(gt_act_elem%mv_conf)%elem)
     387              :          END IF
     388              :          ! second element
     389          336 :          IF (gt_act_elem%conf_n_acc(gt_act_elem%conf(gt_act_elem%mv_conf + 1)%elem%sub_tree_nr)) THEN
     390          212 :             elem2 => gt_act_elem%conf(gt_act_elem%mv_conf + 1)%elem
     391              :          ELSE
     392          124 :             elem2 => search_parent_element(gt_act_elem%conf(gt_act_elem%mv_conf + 1)%elem)
     393              :          END IF
     394              :       ELSE
     395       282664 :          elem1 => gt_act_elem%conf(gt_act_elem%mv_conf)%elem
     396       282664 :          elem2 => search_parent_element(elem1)
     397              :       END IF
     398              : 
     399              :       ! end the timing
     400       283000 :       CALL timestop(handle)
     401              : 
     402       283000 :       CPASSERT(ASSOCIATED(gt_act_elem))
     403       283000 :       CPASSERT(ASSOCIATED(elem1))
     404       283000 :       CPASSERT(ASSOCIATED(elem2))
     405       283000 :    END SUBROUTINE get_subtree_elements_to_check
     406              : 
     407              : ! **************************************************************************************************
     408              : !> \brief searches last element on trajectory,
     409              : !>        until where the sides of the tree are deleted (of global tree)
     410              : !>        also found the last accepted element before
     411              : !> \param last_acc returns last accepted element in cleaned tree part
     412              : !> \param tree_ptr end point of search
     413              : !> \author Mandes 12.2012
     414              : ! **************************************************************************************************
     415       196454 :    RECURSIVE SUBROUTINE search_end_of_clean_g_tree(last_acc, tree_ptr)
     416              :       TYPE(global_tree_type), POINTER                    :: last_acc, tree_ptr
     417              : 
     418              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'search_end_of_clean_g_tree'
     419              : 
     420              :       INTEGER                                            :: handle
     421              : 
     422        98227 :       CPASSERT(ASSOCIATED(last_acc))
     423        98227 :       CPASSERT(ASSOCIATED(tree_ptr))
     424              : 
     425              :       ! start the timing
     426        98227 :       CALL timeset(routineN, handle)
     427              : 
     428       104424 :       SELECT CASE (tree_ptr%stat)
     429              :       CASE (status_accepted_result)
     430         6197 :          IF (ASSOCIATED(tree_ptr%acc) .AND. .NOT. ASSOCIATED(tree_ptr%nacc)) THEN
     431         5396 :             last_acc => tree_ptr
     432         5396 :             tree_ptr => tree_ptr%acc
     433         5396 :             CALL search_end_of_clean_g_tree(last_acc, tree_ptr)
     434              :          END IF
     435              :       CASE (status_rejected_result)
     436        92030 :          IF (ASSOCIATED(tree_ptr%nacc) .AND. .NOT. ASSOCIATED(tree_ptr%acc)) THEN
     437        88231 :             tree_ptr => tree_ptr%nacc
     438        88231 :             CALL search_end_of_clean_g_tree(last_acc, tree_ptr)
     439              :          END IF
     440              :       CASE (status_calculated, status_calculate_energy, status_created, status_accepted, status_rejected, &
     441              :             status_calculate_MD, status_calculate_NMC_steps, status_calc_approx_ener, &
     442              :             status_canceled_ener, status_canceled_nmc, &
     443              :             status_cancel_nmc, status_cancel_ener)
     444              :          ! nothing to do
     445              :       CASE DEFAULT
     446              :          CALL cp_abort(__LOCATION__, &
     447              :                        "the global tree element "//cp_to_string(tree_ptr%nr)// &
     448        98227 :                        " stat "//cp_to_string(tree_ptr%stat)//" is UNknown")
     449              :       END SELECT
     450              :       ! end the timing
     451        98227 :       CALL timestop(handle)
     452        98227 :       CPASSERT(ASSOCIATED(last_acc))
     453        98227 :       CPASSERT(ASSOCIATED(tree_ptr))
     454        98227 :    END SUBROUTINE search_end_of_clean_g_tree
     455              : 
     456              : ! **************************************************************************************************
     457              : !> \brief searches last element on trajectory,
     458              : !>        until where the sides of the tree are deleted (in sub tree)
     459              : !>        also found the last accepted element before.
     460              : !>        searches the last element which at least have ONE (not calculated)
     461              : !>        node in the tree branch
     462              : !> \param tree_ptr  ...
     463              : !> \param last_acc ...
     464              : !> \author Mandes 12.2012
     465              : ! **************************************************************************************************
     466        21362 :    RECURSIVE SUBROUTINE search_end_of_clean_tree(tree_ptr, last_acc)
     467              :       TYPE(tree_type), POINTER                           :: tree_ptr
     468              :       TYPE(tree_type), INTENT(IN), POINTER               :: last_acc
     469              : 
     470              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'search_end_of_clean_tree'
     471              : 
     472              :       INTEGER                                            :: handle
     473              : 
     474        10681 :       CPASSERT(ASSOCIATED(tree_ptr))
     475        10681 :       CPASSERT(ASSOCIATED(last_acc))
     476              : 
     477              :       ! start the timing
     478        10681 :       CALL timeset(routineN, handle)
     479              : 
     480        10681 :       IF (.NOT. ASSOCIATED(last_acc, tree_ptr)) THEN
     481         4279 :          IF (ASSOCIATED(tree_ptr%acc) .AND. .NOT. ASSOCIATED(tree_ptr%nacc)) THEN
     482          675 :             tree_ptr => tree_ptr%acc
     483          675 :             CALL search_end_of_clean_tree(tree_ptr, last_acc)
     484         3604 :          ELSE IF (ASSOCIATED(tree_ptr%nacc) .AND. .NOT. ASSOCIATED(tree_ptr%acc)) THEN
     485         3604 :             tree_ptr => tree_ptr%nacc
     486         3604 :             CALL search_end_of_clean_tree(tree_ptr, last_acc)
     487              :          END IF
     488              :       END IF
     489              :       ! end the timing
     490        10681 :       CALL timestop(handle)
     491        10681 :       CPASSERT(ASSOCIATED(tree_ptr))
     492        10681 :       CPASSERT(ASSOCIATED(last_acc))
     493        10681 :    END SUBROUTINE search_end_of_clean_tree
     494              : 
     495              : ! **************************************************************************************************
     496              : !> \brief searches in all branches down below the entered global tree element
     497              : !>        for elements to cancel, if prob is present start searching at the
     498              : !>        related tree child node
     499              : !> \param pt_elem_in start search point
     500              : !> \param prob the acceptance probability of the tree element to define
     501              : !>        the direction to start with
     502              : !> \param tmc_env TMC environment
     503              : !> \author Mandes 12.2012
     504              : ! **************************************************************************************************
     505            0 :    RECURSIVE SUBROUTINE search_canceling_elements(pt_elem_in, prob, tmc_env)
     506              :       TYPE(global_tree_type), INTENT(IN), POINTER        :: pt_elem_in
     507              :       REAL(KIND=dp), OPTIONAL                            :: prob
     508              :       TYPE(tmc_env_type), POINTER                        :: tmc_env
     509              : 
     510              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'search_canceling_elements'
     511              : 
     512              :       INTEGER                                            :: handle
     513              :       LOGICAL                                            :: ready
     514              :       TYPE(global_tree_type), POINTER                    :: act_pt_ptr, pt_elem
     515              : 
     516            0 :       NULLIFY (pt_elem, act_pt_ptr)
     517            0 :       CPASSERT(ASSOCIATED(pt_elem_in))
     518            0 :       CPASSERT(ASSOCIATED(tmc_env))
     519              : 
     520              :       ! start the timing
     521            0 :       CALL timeset(routineN, handle)
     522              : 
     523            0 :       ready = .TRUE.
     524              :       ! if prob present select the related branch
     525            0 :       IF (PRESENT(prob)) THEN
     526            0 :          IF (prob < 1.0E-10 .AND. ASSOCIATED(pt_elem_in%acc)) THEN
     527            0 :             pt_elem => pt_elem_in%acc
     528            0 :          ELSE IF (prob > (1.0_dp - 1.0E-10) .AND. ASSOCIATED(pt_elem_in%nacc)) THEN
     529            0 :             pt_elem => pt_elem_in%nacc
     530              :          ELSE
     531              :             ready = .FALSE.
     532              :          END IF
     533              :       ELSE
     534            0 :          pt_elem => pt_elem_in
     535              :       END IF
     536              : 
     537              :       IF (ready) THEN
     538            0 :          IF (ASSOCIATED(pt_elem%conf(pt_elem%mv_conf)%elem)) THEN
     539            0 :             SELECT CASE (pt_elem%conf(pt_elem%mv_conf)%elem%stat)
     540              :             CASE (status_accepted_result, status_accepted, status_rejected_result, &
     541              :                   status_rejected, status_created, status_cancel_nmc, &
     542              :                   status_cancel_ener, status_canceled_nmc, status_canceled_ener, &
     543              :                   status_calculated, status_deleted, status_deleted_result, &
     544              :                   status_calc_approx_ener) ! no canceling
     545              :             CASE (status_calculate_NMC_steps, status_calculate_MD, &
     546              :                   status_calculate_energy)
     547              :                CALL search_and_remove_reference_in_list(gt_ptr=pt_elem, &
     548            0 :                                                         elem=pt_elem%conf(pt_elem%mv_conf)%elem, tmc_env=tmc_env)
     549              : 
     550              :             CASE DEFAULT
     551              :                CALL cp_abort(__LOCATION__, &
     552              :                              "unknown status of subtree element"// &
     553            0 :                              cp_to_string(pt_elem%conf(pt_elem%mv_conf)%elem%stat))
     554              :             END SELECT
     555              :          END IF
     556              :          !-- go until the ends ot he tree, to search for elements to cancel
     557              :          !-- check if child nodes exist
     558            0 :          IF (ASSOCIATED(pt_elem%acc)) THEN
     559            0 :             act_pt_ptr => pt_elem%acc
     560            0 :             CALL search_canceling_elements(pt_elem_in=act_pt_ptr, tmc_env=tmc_env)
     561              :          END IF
     562            0 :          IF (ASSOCIATED(pt_elem%nacc)) THEN
     563            0 :             act_pt_ptr => pt_elem%nacc
     564            0 :             CALL search_canceling_elements(pt_elem_in=act_pt_ptr, tmc_env=tmc_env)
     565              :          END IF
     566              :       END IF
     567              :       ! end the timing
     568            0 :       CALL timestop(handle)
     569            0 :       CPASSERT(ASSOCIATED(pt_elem_in))
     570            0 :    END SUBROUTINE search_canceling_elements
     571              : 
     572              : ! **************************************************************************************************
     573              : !> \brief searches for created configurations in all subtrees
     574              : !> \param global_tree_ptr pointer to one global tree element
     575              : !> \param counters array returning the counters for each subtree
     576              : !> \author Mandes 01.2013
     577              : ! **************************************************************************************************
     578           56 :    SUBROUTINE count_prepared_nodes_in_trees(global_tree_ptr, counters)
     579              :       TYPE(global_tree_type), INTENT(IN), POINTER        :: global_tree_ptr
     580              :       INTEGER, DIMENSION(:), POINTER                     :: counters
     581              : 
     582              :       CHARACTER(len=*), PARAMETER :: routineN = 'count_prepared_nodes_in_trees'
     583              : 
     584              :       INTEGER                                            :: handle, i
     585              :       TYPE(tree_type), POINTER                           :: begin_ptr
     586              : 
     587              :       NULLIFY (begin_ptr)
     588              : 
     589           28 :       CPASSERT(ASSOCIATED(global_tree_ptr))
     590           28 :       CPASSERT(ASSOCIATED(counters))
     591           28 :       CPASSERT(SIZE(counters(1:)) == SIZE(global_tree_ptr%conf(:)))
     592              : 
     593              :       ! start the timing
     594           28 :       CALL timeset(routineN, handle)
     595              : 
     596           86 :       counters(:) = 0
     597           58 :       DO i = 1, SIZE(global_tree_ptr%conf(:))
     598           30 :          begin_ptr => global_tree_ptr%conf(i)%elem
     599              :          CALL count_prepared_nodes_in_subtree(tree_ptr=begin_ptr, &
     600           58 :                                               counter=counters(i))
     601              :       END DO
     602              : 
     603              :       ! end the timing
     604           28 :       CALL timestop(handle)
     605           28 :    END SUBROUTINE count_prepared_nodes_in_trees
     606              : 
     607              : ! **************************************************************************************************
     608              : !> \brief counts the prepared tree nodes in subtrees
     609              : !> \param tree_ptr pointer to one subtree element
     610              : !> \param counter returning the amount of prepared
     611              : !>        (ready for energy calculation) elements ind certain sub tree
     612              : !> \author Mandes 01.2013
     613              : ! **************************************************************************************************
     614           54 :    RECURSIVE SUBROUTINE count_prepared_nodes_in_subtree(tree_ptr, counter)
     615              :       TYPE(tree_type), POINTER                           :: tree_ptr
     616              :       INTEGER                                            :: counter
     617              : 
     618              :       TYPE(tree_type), POINTER                           :: tmp_ptr
     619              : 
     620           54 :       NULLIFY (tmp_ptr)
     621              : 
     622           54 :       CPASSERT(ASSOCIATED(tree_ptr))
     623              : 
     624           77 :       SELECT CASE (tree_ptr%stat)
     625              :       CASE (status_accepted, status_accepted_result)
     626           23 :          IF (ASSOCIATED(tree_ptr%acc)) THEN
     627           23 :             tmp_ptr => tree_ptr%acc
     628           23 :             CALL count_prepared_nodes_in_subtree(tmp_ptr, counter)
     629              :          END IF
     630              :       CASE (status_rejected, status_rejected_result)
     631            1 :          IF (ASSOCIATED(tree_ptr%nacc)) THEN
     632            1 :             tmp_ptr => tree_ptr%nacc
     633            1 :             CALL count_prepared_nodes_in_subtree(tmp_ptr, counter)
     634              :          END IF
     635              :       CASE (status_created, status_calculate_MD, status_calculate_NMC_steps, &
     636              :             status_calc_approx_ener, status_calculated, status_calculate_energy)
     637           30 :          IF (tree_ptr%stat == status_created) counter = counter + 1
     638           30 :          IF (ASSOCIATED(tree_ptr%acc)) THEN
     639            0 :             tmp_ptr => tree_ptr%acc
     640            0 :             CALL count_prepared_nodes_in_subtree(tmp_ptr, counter)
     641              :          END IF
     642           30 :          IF (ASSOCIATED(tree_ptr%nacc)) THEN
     643            0 :             tmp_ptr => tree_ptr%nacc
     644            0 :             CALL count_prepared_nodes_in_subtree(tmp_ptr, counter)
     645              :          END IF
     646              :       CASE (status_cancel_nmc, status_cancel_ener, status_canceled_nmc, &
     647              :             status_canceled_ener)
     648              :          !TODO maybe also count caneled confs for debug output
     649              :       CASE DEFAULT
     650              :          CALL cp_abort(__LOCATION__, &
     651              :                        "stat "//cp_to_string(tree_ptr%stat)// &
     652              :                        "of elem "//cp_to_string(tree_ptr%nr)// &
     653           54 :                        "unknown.")
     654              :       END SELECT
     655           54 :    END SUBROUTINE count_prepared_nodes_in_subtree
     656              : 
     657              : ! **************************************************************************************************
     658              : !> \brief counts the number of existing nodes in global and subtrees
     659              : !> \param global_tree_ptr pointer to one global tree element
     660              : !> \param end_of_clean_trees points to the last elements of the clean sub trees
     661              : !> \param counters array returning the counters for each subtree
     662              : !> \param head_elements_nr node number of the existing
     663              : !>        global and sub tree heads
     664              : !> \author Mandes 01.2013
     665              : ! **************************************************************************************************
     666          364 :    SUBROUTINE count_nodes_in_trees(global_tree_ptr, end_of_clean_trees, &
     667              :                                    counters, head_elements_nr)
     668              :       TYPE(global_tree_type), POINTER                    :: global_tree_ptr
     669              :       TYPE(elem_array_type), DIMENSION(:), POINTER       :: end_of_clean_trees
     670              :       INTEGER, DIMENSION(:), POINTER                     :: counters, head_elements_nr
     671              : 
     672              :       CHARACTER(len=*), PARAMETER :: routineN = 'count_nodes_in_trees'
     673              : 
     674              :       INTEGER                                            :: handle, i
     675              :       TYPE(global_tree_type), POINTER                    :: begin_gt_ptr
     676              :       TYPE(tree_type), POINTER                           :: begin_ptr
     677              : 
     678              :       NULLIFY (begin_gt_ptr, begin_ptr)
     679              : 
     680          182 :       CPASSERT(ASSOCIATED(global_tree_ptr))
     681          182 :       CPASSERT(ASSOCIATED(end_of_clean_trees))
     682          182 :       CPASSERT(ASSOCIATED(counters))
     683          182 :       CPASSERT(SIZE(counters(1:)) == SIZE(global_tree_ptr%conf(:)))
     684              : 
     685              :       ! start the timing
     686          182 :       CALL timeset(routineN, handle)
     687              : 
     688          182 :       begin_gt_ptr => global_tree_ptr
     689          782 :       counters(:) = 0
     690          135 :       DO
     691          317 :          IF (.NOT. ASSOCIATED(begin_gt_ptr%parent)) EXIT
     692          135 :          begin_gt_ptr => begin_gt_ptr%parent
     693              :       END DO
     694          182 :       head_elements_nr(0) = begin_gt_ptr%nr
     695          182 :       CALL count_nodes_in_global_tree(begin_gt_ptr, counters(0))
     696          600 :       DO i = 1, SIZE(end_of_clean_trees(:))
     697          418 :          begin_ptr => end_of_clean_trees(i)%elem
     698           61 :          DO
     699          479 :             IF (.NOT. ASSOCIATED(begin_ptr%parent)) EXIT
     700           61 :             begin_ptr => begin_ptr%parent
     701              :          END DO
     702          418 :          head_elements_nr(i) = begin_ptr%nr
     703          600 :          CALL count_nodes_in_tree(begin_ptr, counters(i))
     704              :       END DO
     705              : 
     706              :       ! end the timing
     707          182 :       CALL timestop(handle)
     708          182 :    END SUBROUTINE count_nodes_in_trees
     709              : 
     710              : ! **************************************************************************************************
     711              : !> \brief counts existing nodes in global tree
     712              : !> \param ptr global tree head
     713              : !> \param counter return value with the amount of existing global tree elements
     714              : !> \author Mandes 01.2013
     715              : ! **************************************************************************************************
     716         1284 :    RECURSIVE SUBROUTINE count_nodes_in_global_tree(ptr, counter)
     717              :       TYPE(global_tree_type), INTENT(IN), POINTER        :: ptr
     718              :       INTEGER, INTENT(INOUT)                             :: counter
     719              : 
     720         1284 :       CPASSERT(ASSOCIATED(ptr))
     721              : 
     722         1284 :       counter = counter + 1
     723              : 
     724         1284 :       IF (ASSOCIATED(ptr%acc)) &
     725          262 :          CALL count_nodes_in_global_tree(ptr%acc, counter)
     726         1284 :       IF (ASSOCIATED(ptr%nacc)) &
     727          840 :          CALL count_nodes_in_global_tree(ptr%nacc, counter)
     728         1284 :    END SUBROUTINE count_nodes_in_global_tree
     729              : 
     730              : ! **************************************************************************************************
     731              : !> \brief counts existing nodes in certain sub tree
     732              : !> \param ptr subtree tree head
     733              : !> \param counter return value with the amount of existing sub tree elements
     734              : !> \author Mandes 01.2013
     735              : ! **************************************************************************************************
     736         1601 :    RECURSIVE SUBROUTINE count_nodes_in_tree(ptr, counter)
     737              :       TYPE(tree_type), POINTER                           :: ptr
     738              :       INTEGER                                            :: counter
     739              : 
     740         1601 :       CPASSERT(ASSOCIATED(ptr))
     741              : 
     742         1601 :       counter = counter + 1
     743              : 
     744         1601 :       IF (ASSOCIATED(ptr%acc)) &
     745          297 :          CALL count_nodes_in_tree(ptr%acc, counter)
     746         1601 :       IF (ASSOCIATED(ptr%nacc)) &
     747          886 :          CALL count_nodes_in_tree(ptr%nacc, counter)
     748         1601 :    END SUBROUTINE count_nodes_in_tree
     749              : END MODULE tmc_tree_search
        

Generated by: LCOV version 2.0-1