Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief Master's routines for global optimization
10 : !> \author Ole Schuett
11 : ! **************************************************************************************************
12 : MODULE glbopt_master
13 : USE atomic_kind_types, ONLY: atomic_kind_type,&
14 : deallocate_atomic_kind_set
15 : USE colvar_types, ONLY: colvar_p_release,&
16 : colvar_p_type
17 : USE cp_log_handling, ONLY: cp_get_default_logger,&
18 : cp_logger_type
19 : USE cp_output_handling, ONLY: cp_print_key_finished_output,&
20 : cp_print_key_unit_nr
21 : USE cp_units, ONLY: cp_unit_from_cp2k
22 : USE exclusion_types, ONLY: exclusion_release,&
23 : exclusion_type
24 : USE glbopt_mincrawl, ONLY: mincrawl_finalize,&
25 : mincrawl_init,&
26 : mincrawl_steer,&
27 : mincrawl_type
28 : USE glbopt_minhop, ONLY: minhop_finalize,&
29 : minhop_init,&
30 : minhop_steer,&
31 : minhop_type
32 : USE input_constants, ONLY: dump_xmol,&
33 : glbopt_do_mincrawl,&
34 : glbopt_do_minhop
35 : USE input_section_types, ONLY: section_vals_get_subs_vals,&
36 : section_vals_release,&
37 : section_vals_retain,&
38 : section_vals_type,&
39 : section_vals_val_get
40 : USE kinds, ONLY: default_string_length,&
41 : dp,&
42 : int_8
43 : USE message_passing, ONLY: mp_para_env_type
44 : USE molecule_kind_types, ONLY: deallocate_molecule_kind_set,&
45 : molecule_kind_type
46 : USE molecule_types, ONLY: deallocate_global_constraint,&
47 : deallocate_molecule_set,&
48 : global_constraint_type,&
49 : molecule_type
50 : USE particle_methods, ONLY: write_particle_coordinates
51 : USE particle_types, ONLY: deallocate_particle_set,&
52 : particle_type
53 : USE swarm_message, ONLY: swarm_message_get,&
54 : swarm_message_type
55 : USE topology, ONLY: topology_control
56 : #include "../base/base_uses.f90"
57 :
58 : IMPLICIT NONE
59 : PRIVATE
60 :
61 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'glbopt_master'
62 :
63 : PUBLIC :: glbopt_master_type
64 : PUBLIC :: glbopt_master_init, glbopt_master_finalize
65 : PUBLIC :: glbopt_master_steer
66 :
67 : TYPE glbopt_master_type
68 : PRIVATE
69 : REAL(KIND=dp) :: E_lowest = HUGE(1.0_dp)
70 : REAL(KIND=dp) :: E_target = TINY(1.0_dp)
71 : INTEGER :: iw = 0
72 : INTEGER :: progress_traj_unit = 0
73 : INTEGER(int_8) :: total_md_steps = 0
74 : INTEGER(int_8) :: total_gopt_steps = 0
75 : INTEGER(int_8) :: count_reports = 0
76 : INTEGER :: method = glbopt_do_minhop
77 : TYPE(minhop_type), POINTER :: minhop => NULL()
78 : TYPE(mincrawl_type), POINTER :: mincrawl => NULL()
79 : INTEGER :: i_iteration = 0
80 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set => Null()
81 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set => Null()
82 : TYPE(section_vals_type), POINTER :: glbopt_section => Null()
83 : END TYPE glbopt_master_type
84 :
85 : CONTAINS
86 :
87 : ! **************************************************************************************************
88 : !> \brief Initializes the master of the global optimizer
89 : !> \param this ...
90 : !> \param para_env ...
91 : !> \param root_section ...
92 : !> \param n_walkers ...
93 : !> \param iw ...
94 : !> \author Ole Schuett
95 : ! **************************************************************************************************
96 3 : SUBROUTINE glbopt_master_init(this, para_env, root_section, n_walkers, iw)
97 : TYPE(glbopt_master_type), INTENT(INOUT) :: this
98 : TYPE(mp_para_env_type), POINTER :: para_env
99 : TYPE(section_vals_type), POINTER :: root_section
100 : INTEGER, INTENT(IN) :: n_walkers, iw
101 :
102 : TYPE(cp_logger_type), POINTER :: logger
103 :
104 3 : NULLIFY (logger)
105 :
106 3 : this%iw = iw
107 :
108 3 : this%glbopt_section => section_vals_get_subs_vals(root_section, "SWARM%GLOBAL_OPT")
109 3 : CALL section_vals_retain(this%glbopt_section)
110 :
111 3 : CALL section_vals_val_get(this%glbopt_section, "E_TARGET", r_val=this%E_target)
112 3 : CALL section_vals_val_get(this%glbopt_section, "METHOD", i_val=this%method)
113 :
114 3 : CALL glbopt_read_particle_set(this, para_env, root_section)
115 :
116 3 : logger => cp_get_default_logger()
117 : this%progress_traj_unit = cp_print_key_unit_nr(logger, &
118 : this%glbopt_section, "PROGRESS_TRAJECTORY", &
119 : middle_name="progress", extension=".xyz", &
120 3 : file_action="WRITE", file_position="REWIND")
121 :
122 5 : SELECT CASE (this%method)
123 : CASE (glbopt_do_minhop)
124 2 : ALLOCATE (this%minhop)
125 2 : CALL minhop_init(this%minhop, this%glbopt_section, n_walkers, iw)
126 : CASE (glbopt_do_mincrawl)
127 27 : ALLOCATE (this%mincrawl)
128 1 : CALL mincrawl_init(this%mincrawl, this%glbopt_section, n_walkers, iw, this%particle_set)
129 : CASE DEFAULT
130 3 : CPABORT("Unknown glbopt_method")
131 : END SELECT
132 3 : END SUBROUTINE glbopt_master_init
133 :
134 : ! **************************************************************************************************
135 : !> \brief Helper-routine for glbopt_master_init, reads part of SUBSYS-section
136 : !> \param this ...
137 : !> \param para_env ...
138 : !> \param root_section ...
139 : !> \author Ole Schuett
140 : ! **************************************************************************************************
141 3 : SUBROUTINE glbopt_read_particle_set(this, para_env, root_section)
142 : TYPE(glbopt_master_type), INTENT(INOUT) :: this
143 : TYPE(mp_para_env_type), POINTER :: para_env
144 : TYPE(section_vals_type), POINTER :: root_section
145 :
146 3 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
147 3 : TYPE(colvar_p_type), DIMENSION(:), POINTER :: colvar_p
148 3 : TYPE(exclusion_type), DIMENSION(:), POINTER :: exclusions
149 : TYPE(global_constraint_type), POINTER :: gci
150 3 : TYPE(molecule_kind_type), DIMENSION(:), POINTER :: molecule_kind_set
151 3 : TYPE(molecule_type), DIMENSION(:), POINTER :: molecule_set
152 3 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
153 : TYPE(section_vals_type), POINTER :: force_env_section, subsys_section
154 :
155 3 : NULLIFY (atomic_kind_set, particle_set, molecule_kind_set, molecule_set)
156 3 : NULLIFY (colvar_p, gci, exclusions, force_env_section, subsys_section)
157 :
158 6 : force_env_section => section_vals_get_subs_vals(root_section, "FORCE_EVAL")
159 3 : subsys_section => section_vals_get_subs_vals(root_section, "FORCE_EVAL%SUBSYS")
160 :
161 : CALL topology_control(atomic_kind_set, &
162 : particle_set, &
163 : molecule_kind_set, &
164 : molecule_set, &
165 : colvar_p, &
166 : gci, &
167 : root_section=root_section, &
168 : para_env=para_env, &
169 : force_env_section=force_env_section, &
170 : subsys_section=subsys_section, &
171 : use_motion_section=.FALSE., &
172 3 : exclusions=exclusions)
173 :
174 : !This is the only thing we need to write trajectories.
175 3 : this%atomic_kind_set => atomic_kind_set
176 3 : this%particle_set => particle_set
177 3 : CALL exclusion_release(exclusions)
178 3 : CALL deallocate_molecule_set(molecule_set)
179 3 : CALL deallocate_molecule_kind_set(molecule_kind_set)
180 3 : CALL deallocate_global_constraint(gci)
181 3 : CALL colvar_p_release(colvar_p)
182 :
183 3 : END SUBROUTINE glbopt_read_particle_set
184 :
185 : ! **************************************************************************************************
186 : !> \brief Central steering routine of global optimizer
187 : !> \param this ...
188 : !> \param report ...
189 : !> \param cmd ...
190 : !> \param should_stop ...
191 : !> \author Ole Schuett
192 : ! **************************************************************************************************
193 54 : SUBROUTINE glbopt_master_steer(this, report, cmd, should_stop)
194 : TYPE(glbopt_master_type), INTENT(INOUT) :: this
195 : TYPE(swarm_message_type) :: report, cmd
196 : LOGICAL, INTENT(INOUT) :: should_stop
197 :
198 54 : CALL progress_report(this, report)
199 :
200 67 : SELECT CASE (this%method)
201 : CASE (glbopt_do_minhop)
202 13 : CALL minhop_steer(this%minhop, report, cmd)
203 : CASE (glbopt_do_mincrawl)
204 41 : CALL mincrawl_steer(this%mincrawl, report, cmd)
205 : CASE DEFAULT
206 54 : CPABORT("Unknown glbopt_method")
207 : END SELECT
208 :
209 54 : IF (this%E_lowest < this%E_target) THEN
210 2 : IF (this%iw > 0) WRITE (this%iw, "(A,I8,A)") &
211 2 : " GLBOPT| Reached E_pot < E_target after ", this%i_iteration, " iterations. Quitting."
212 2 : should_stop = .TRUE.
213 : END IF
214 54 : END SUBROUTINE glbopt_master_steer
215 :
216 : ! **************************************************************************************************
217 : !> \brief Helper routine for glbopt_master_steer(), updates stats, etc.
218 : !> \param this ...
219 : !> \param report ...
220 : !> \author Ole Schuett
221 : ! **************************************************************************************************
222 54 : SUBROUTINE progress_report(this, report)
223 : TYPE(glbopt_master_type), INTENT(INOUT) :: this
224 : TYPE(swarm_message_type) :: report
225 :
226 : CHARACTER(len=default_string_length) :: status
227 : INTEGER :: gopt_steps, md_steps, report_worker_id
228 : REAL(KIND=dp) :: report_Epot
229 :
230 54 : this%i_iteration = this%i_iteration + 1
231 :
232 54 : CALL swarm_message_get(report, "worker_id", report_worker_id)
233 54 : CALL swarm_message_get(report, "status", status)
234 :
235 54 : IF (TRIM(status) == "ok") THEN
236 51 : CALL swarm_message_get(report, "Epot", report_Epot)
237 51 : CALL swarm_message_get(report, "md_steps", md_steps)
238 51 : CALL swarm_message_get(report, "gopt_steps", gopt_steps)
239 51 : this%total_md_steps = this%total_md_steps + md_steps
240 51 : this%total_gopt_steps = this%total_gopt_steps + gopt_steps
241 51 : this%count_reports = this%count_reports + 1
242 :
243 51 : IF (report_Epot < this%E_lowest) THEN
244 14 : this%E_lowest = report_Epot
245 14 : CALL write_progress_traj(this, report)
246 : END IF
247 :
248 51 : IF (this%iw > 0) THEN
249 : WRITE (this%iw, '(A,46X,I8)') &
250 51 : " GLBOPT| Reporting worker ", report_worker_id
251 : WRITE (this%iw, '(A,20X,E15.8)') &
252 51 : " GLBOPT| Reported potential energy [Hartree] ", report_Epot
253 : WRITE (this%iw, '(A,13X,E15.8)') &
254 51 : " GLBOPT| Lowest reported potential energy [Hartree] ", this%E_lowest
255 : WRITE (this%iw, '(A,T71,F10.1)') &
256 51 : " GLBOPT| Average number of MD steps", REAL(this%total_md_steps, KIND=dp)/this%count_reports
257 : WRITE (this%iw, '(A,T71,F10.1)') &
258 51 : " GLBOPT| Average number of Geo-Opt steps", REAL(this%total_gopt_steps, KIND=dp)/this%count_reports
259 : END IF
260 : END IF
261 54 : END SUBROUTINE progress_report
262 :
263 : ! **************************************************************************************************
264 : !> \brief Helper routine for progress_report(), write frames to trajectory.
265 : !> \param this ...
266 : !> \param report ...
267 : !> \author Ole Schuett
268 : ! **************************************************************************************************
269 42 : SUBROUTINE write_progress_traj(this, report)
270 : TYPE(glbopt_master_type), INTENT(INOUT) :: this
271 : TYPE(swarm_message_type), INTENT(IN) :: report
272 :
273 : CHARACTER(len=default_string_length) :: title, unit_str
274 : INTEGER :: report_worker_id
275 : REAL(KIND=dp) :: report_Epot, unit_conv
276 14 : REAL(KIND=dp), DIMENSION(:), POINTER :: report_positions
277 :
278 14 : NULLIFY (report_positions)
279 :
280 0 : IF (this%progress_traj_unit <= 0) RETURN
281 :
282 14 : CALL swarm_message_get(report, "worker_id", report_worker_id)
283 14 : CALL swarm_message_get(report, "positions", report_positions)
284 14 : CALL swarm_message_get(report, "Epot", report_Epot)
285 :
286 14 : WRITE (title, '(A,I8,A,I5,A,F20.10)') 'i = ', this%i_iteration, &
287 28 : ' worker_id = ', report_worker_id, ' Epot = ', report_Epot
288 :
289 : !get the conversion factor for the length unit
290 : CALL section_vals_val_get(this%glbopt_section, "PROGRESS_TRAJECTORY%UNIT", &
291 14 : c_val=unit_str)
292 14 : unit_conv = cp_unit_from_cp2k(1.0_dp, TRIM(unit_str))
293 : CALL write_particle_coordinates(this%particle_set, &
294 : iunit=this%progress_traj_unit, &
295 : output_format=dump_xmol, &
296 : content="POS", &
297 : title=TRIM(title), &
298 : array=report_positions, &
299 14 : unit_conv=unit_conv)
300 14 : DEALLOCATE (report_positions)
301 14 : END SUBROUTINE write_progress_traj
302 :
303 : ! **************************************************************************************************
304 : !> \brief Finalized the master of the global optimizer
305 : !> \param this ...
306 : !> \author Ole
307 : ! **************************************************************************************************
308 3 : SUBROUTINE glbopt_master_finalize(this)
309 : TYPE(glbopt_master_type), INTENT(INOUT) :: this
310 :
311 : TYPE(cp_logger_type), POINTER :: logger
312 :
313 3 : NULLIFY (logger)
314 :
315 5 : SELECT CASE (this%method)
316 : CASE (glbopt_do_minhop)
317 2 : CALL minhop_finalize(this%minhop)
318 4 : DEALLOCATE (this%minhop)
319 : CASE (glbopt_do_mincrawl)
320 1 : CALL mincrawl_finalize(this%mincrawl)
321 1 : DEALLOCATE (this%mincrawl)
322 : CASE DEFAULT
323 3 : CPABORT("Unknown glbopt_method")
324 : END SELECT
325 :
326 3 : logger => cp_get_default_logger()
327 : CALL cp_print_key_finished_output(this%progress_traj_unit, logger, &
328 3 : this%glbopt_section, "PROGRESS_TRAJECTORY")
329 :
330 3 : CALL section_vals_release(this%glbopt_section)
331 3 : CALL deallocate_particle_set(this%particle_set)
332 3 : CALL deallocate_atomic_kind_set(this%atomic_kind_set)
333 :
334 3 : END SUBROUTINE glbopt_master_finalize
335 :
336 0 : END MODULE glbopt_master
337 :
|