1!--------------------------------------------------------------------------------------------------!
2!   CP2K: A general program to perform molecular dynamics simulations                              !
3!   Copyright (C) 2000 - 2019  CP2K developers group                                               !
4!--------------------------------------------------------------------------------------------------!
5
6! **************************************************************************************************
7!> \brief perform biased molecular dynamics (H= k H1 + (1-k) H2 [linear or general mixing)
8!> \author fschiff 11.06
9! **************************************************************************************************
10MODULE mixed_main
11   USE cp_files,                        ONLY: open_file
12   USE cp_log_handling,                 ONLY: cp_get_default_logger,&
13                                              cp_logger_create,&
14                                              cp_logger_set,&
15                                              cp_logger_type,&
16                                              cp_to_string
17   USE cp_output_handling,              ONLY: cp_print_key_unit_nr
18   USE cp_para_env,                     ONLY: cp_para_env_create
19   USE cp_para_types,                   ONLY: cp_para_env_type
20   USE input_section_types,             ONLY: section_vals_type,&
21                                              section_vals_val_get
22   USE kinds,                           ONLY: default_path_length
23   USE message_passing,                 ONLY: mp_comm_split
24   USE mixed_environment,               ONLY: mixed_init
25   USE mixed_environment_types,         ONLY: mixed_env_create,&
26                                              mixed_environment_type,&
27                                              set_mixed_env
28#include "./base/base_uses.f90"
29
30   IMPLICIT NONE
31
32   PRIVATE
33
34! *** Global parameters ***
35   CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'mixed_main'
36
37   PUBLIC :: mixed_create_force_env
38
39CONTAINS
40! **************************************************************************************************
41!> \brief Controls program flow for mixed calculations
42!> \param mixed_env ...
43!> \param root_section ...
44!> \param para_env ...
45!> \param force_env_section ...
46!> \param n_subforce_eval ...
47!> \param use_motion_section ...
48!> \author fschiff
49! **************************************************************************************************
50   SUBROUTINE mixed_create_force_env(mixed_env, root_section, para_env, &
51                                     force_env_section, n_subforce_eval, use_motion_section)
52
53      TYPE(mixed_environment_type), POINTER              :: mixed_env
54      TYPE(section_vals_type), POINTER                   :: root_section
55      TYPE(cp_para_env_type), POINTER                    :: para_env
56      TYPE(section_vals_type), POINTER                   :: force_env_section
57      INTEGER, INTENT(IN)                                :: n_subforce_eval
58      LOGICAL, INTENT(IN)                                :: use_motion_section
59
60      CHARACTER(LEN=*), PARAMETER :: routineN = 'mixed_create_force_env', &
61         routineP = moduleN//':'//routineN
62
63      CHARACTER(len=default_path_length)                 :: c_val, input_file_path, output_file_path
64      INTEGER                                            :: group_size_wish, handle, i, lp, &
65                                                            n_rep_val, ngroup_wish, output_unit, &
66                                                            unit_nr
67      INTEGER, DIMENSION(:), POINTER                     :: group_partition, i_vals
68      LOGICAL                                            :: group_size_wish_set, ngroup_wish_set
69      TYPE(cp_logger_type), POINTER                      :: logger
70
71      CALL timeset(routineN, handle)
72      logger => cp_get_default_logger()
73      output_unit = cp_print_key_unit_nr(logger, force_env_section, "MIXED%PRINT%PROGRAM_RUN_INFO", &
74                                         extension=".log")
75
76      CALL mixed_env_create(mixed_env, para_env=para_env)
77      ! Setup the new parallel env
78      NULLIFY (group_partition)
79      group_size_wish_set = .FALSE.
80      ngroup_wish_set = .FALSE.
81      CALL section_vals_val_get(force_env_section, "MIXED%GROUP_PARTITION", n_rep_val=n_rep_val)
82      IF (n_rep_val > 0) THEN
83         CALL section_vals_val_get(force_env_section, "MIXED%GROUP_PARTITION", i_vals=i_vals)
84         ALLOCATE (group_partition(0:SIZE(i_vals) - 1))
85         group_partition(:) = i_vals
86         ngroup_wish_set = .TRUE.
87         ngroup_wish = SIZE(i_vals)
88      ELSE
89         CALL section_vals_val_get(force_env_section, "MIXED%NGROUPS", n_rep_val=n_rep_val)
90         IF (n_rep_val > 0) THEN
91            CALL section_vals_val_get(force_env_section, "MIXED%NGROUPS", i_val=ngroup_wish)
92         ELSE
93            ngroup_wish = n_subforce_eval
94         END IF
95         group_size_wish_set = .TRUE.
96         group_size_wish = MAX(1, para_env%num_pe/ngroup_wish)
97      END IF
98
99      ! Split the current communicator
100      ALLOCATE (mixed_env%group_distribution(0:para_env%num_pe - 1))
101      IF (group_size_wish_set) THEN
102         CALL mp_comm_split(para_env%group, mixed_env%new_group, mixed_env%ngroups, mixed_env%group_distribution, &
103                            subgroup_min_size=group_size_wish)
104      ELSE IF (ngroup_wish_set) THEN
105         CALL mp_comm_split(para_env%group, mixed_env%new_group, mixed_env%ngroups, mixed_env%group_distribution, &
106                            n_subgroups=ngroup_wish, &
107                            group_partition=group_partition)
108      ENDIF
109      IF (output_unit > 0) THEN
110         WRITE (output_unit, FMT="(T2,A,T71,I10)") "MIXED_ENV| Number of created MPI groups:", mixed_env%ngroups
111         WRITE (output_unit, FMT="(T2,A)", ADVANCE="NO") "MIXED_ENV| Task to group correspondence:"
112         DO i = 0, para_env%num_pe - 1
113            IF (MODULO(i, 4) == 0) WRITE (output_unit, *)
114            WRITE (output_unit, FMT='(A3,I4,A3,I4,A1)', ADVANCE="NO") &
115               "  (", i, " : ", mixed_env%group_distribution(i), ")"
116         END DO
117         WRITE (output_unit, *)
118      ENDIF
119      IF (ASSOCIATED(group_partition)) THEN
120         DEALLOCATE (group_partition)
121      END IF
122      ! Allocate para_env and handle the several loggers
123      ALLOCATE (mixed_env%sub_para_env(mixed_env%ngroups))
124      ALLOCATE (mixed_env%sub_logger(mixed_env%ngroups))
125      ALLOCATE (mixed_env%energies(n_subforce_eval))
126      !
127      DO i = 1, mixed_env%ngroups
128         NULLIFY (mixed_env%sub_para_env(i)%para_env, logger)
129         IF (MODULO(i - 1, mixed_env%ngroups) == mixed_env%group_distribution(para_env%mepos)) THEN
130            ! Create sub_para_env
131            CALL cp_para_env_create(mixed_env%sub_para_env(i)%para_env, &
132                                    group=mixed_env%new_group, &
133                                    owns_group=.TRUE.)
134            ! Create sub_logger
135            IF (mixed_env%sub_para_env(i)%para_env%ionode) THEN
136               ! Redirecting output of subforce_eval to file..
137               CALL section_vals_val_get(root_section, "GLOBAL%PROJECT_NAME", &
138                                         c_val=input_file_path)
139               lp = LEN_TRIM(input_file_path)
140               input_file_path(lp + 1:LEN(input_file_path)) = "-r-"// &
141                                                              ADJUSTL(cp_to_string(i))
142               lp = LEN_TRIM(input_file_path)
143               output_file_path = input_file_path(1:lp)//".out"
144               CALL open_file(file_name=output_file_path, file_status="UNKNOWN", &
145                              file_action="WRITE", file_position="APPEND", &
146                              unit_number=unit_nr)
147            ELSE
148               unit_nr = -1
149            END IF
150            CALL cp_logger_create(mixed_env%sub_logger(i)%p, &
151                                  para_env=mixed_env%sub_para_env(i)%para_env, &
152                                  default_global_unit_nr=unit_nr, &
153                                  close_global_unit_on_dealloc=.FALSE.)
154            ! Try to use better names for the local log if it is not too late
155            CALL section_vals_val_get(root_section, "GLOBAL%OUTPUT_FILE_NAME", &
156                                      c_val=c_val)
157            IF (c_val /= "") THEN
158               CALL cp_logger_set(mixed_env%sub_logger(i)%p, &
159                                  local_filename=TRIM(c_val)//"_localLog")
160            END IF
161            CALL section_vals_val_get(root_section, "GLOBAL%PROJECT", c_val=c_val)
162            IF (c_val /= "") THEN
163               CALL cp_logger_set(mixed_env%sub_logger(i)%p, &
164                                  local_filename=TRIM(c_val)//"_localLog")
165            END IF
166            mixed_env%sub_logger(i)%p%iter_info%project_name = c_val
167            CALL section_vals_val_get(root_section, "GLOBAL%PRINT_LEVEL", &
168                                      i_val=mixed_env%sub_logger(i)%p%iter_info%print_level)
169
170         END IF
171      END DO
172
173      ! *** initializations for the setup of the MIXED environment ***
174      CALL set_mixed_env(mixed_env)
175      CALL mixed_init(mixed_env, root_section, para_env, force_env_section, &
176                      use_motion_section)
177      CALL timestop(handle)
178
179   END SUBROUTINE mixed_create_force_env
180
181END MODULE mixed_main
182