(git:374b731)
Loading...
Searching...
No Matches
glbopt_mincrawl.F
Go to the documentation of this file.
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 Routines for the Minima Crawling global optimization scheme
10!> \author Ole Schuett
11! **************************************************************************************************
18 USE glbopt_history, ONLY: history_add,&
25 USE input_constants, ONLY: dump_xmol
29 USE kinds, ONLY: default_string_length,&
30 dp
34 USE physcon, ONLY: kelvin
38#include "../base/base_uses.f90"
39
40 IMPLICIT NONE
41 PRIVATE
42
43 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'glbopt_mincrawl'
44
45 PUBLIC :: mincrawl_type
47 PUBLIC :: mincrawl_steer
48
49 TYPE minima_type
50 INTEGER :: id = -1
51 REAL(KIND=dp), DIMENSION(:), ALLOCATABLE :: pos
52 REAL(KIND=dp), DIMENSION(:), ALLOCATABLE :: escape_hist
53 REAL(KIND=dp), DIMENSION(:), ALLOCATABLE :: tempdist
54 REAL(KIND=dp) :: epot = -1.0
55 TYPE(history_fingerprint_type) :: fp
56 LOGICAL :: disabled = .false.
57 INTEGER :: n_active = 0
58 INTEGER :: n_sampled = 0
59 END TYPE minima_type
60
61 TYPE minima_p_type
62 TYPE(minima_type), POINTER :: p => null()
63 END TYPE minima_p_type
64
65 TYPE worker_state_type
66 TYPE(minima_type), POINTER :: start_minima => null()
67 INTEGER :: tempstep = 0
68 INTEGER :: iframe = 1
69 END TYPE worker_state_type
70
72 PRIVATE
73 TYPE(history_type) :: history
74 TYPE(worker_state_type), DIMENSION(:), ALLOCATABLE :: workers
75 TYPE(minima_p_type), DIMENSION(:), ALLOCATABLE :: minimas
76 REAL(kind=dp) :: tempstep_base = 0
77 INTEGER :: tempstep_max = 0
78 REAL(kind=dp) :: tempdist_init_width = 0
79 REAL(kind=dp) :: tempdist_update_width = 0
80 REAL(kind=dp) :: tempdist_update_height = 0
81 INTEGER :: esc_hist_len = 0
82 INTEGER :: tempstep_init = 0
83 REAL(kind=dp), DIMENSION(:), ALLOCATABLE :: tempdist_init
84 INTEGER :: n_minima = 0
85 INTEGER :: n_workers = 0
86 INTEGER :: worker_per_min = 0
87 INTEGER :: iw = 0
88 INTEGER :: minima_traj_unit = 0
89 TYPE(section_vals_type), POINTER :: mincrawl_section => null()
90 TYPE(rng_stream_type) :: rng_stream
91 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set => null()
92 END TYPE mincrawl_type
93
94CONTAINS
95
96! **************************************************************************************************
97!> \brief Initializes master for Minima Crawling
98!> \param this ...
99!> \param glbopt_section ...
100!> \param n_workers ...
101!> \param iw ...
102!> \param particle_set ...
103!> \author Ole Schuett
104! **************************************************************************************************
105 SUBROUTINE mincrawl_init(this, glbopt_section, n_workers, iw, particle_set)
106 TYPE(mincrawl_type) :: this
107 TYPE(section_vals_type), POINTER :: glbopt_section
108 INTEGER, INTENT(IN) :: n_workers, iw
109 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
110
111 INTEGER :: i
112 REAL(kind=dp) :: temp_in_kelvin
113 TYPE(cp_logger_type), POINTER :: logger
114 TYPE(section_vals_type), POINTER :: history_section
115
116 NULLIFY (logger, history_section)
117
118 ! read input
119 this%mincrawl_section => section_vals_get_subs_vals(glbopt_section, "MINIMA_CRAWLING")
120 CALL section_vals_val_get(this%mincrawl_section, "TEMPSTEP_BASE", r_val=this%tempstep_base)
121 CALL section_vals_val_get(this%mincrawl_section, "TEMPSTEP_MAX", i_val=this%tempstep_max)
122 CALL section_vals_val_get(this%mincrawl_section, "TEMPDIST_INIT_WIDTH", r_val=this%tempdist_init_width)
123 CALL section_vals_val_get(this%mincrawl_section, "TEMPDIST_UPDATE_WIDTH", r_val=this%tempdist_update_width)
124 CALL section_vals_val_get(this%mincrawl_section, "TEMPDIST_UPDATE_HEIGHT", r_val=this%tempdist_update_height)
125 CALL section_vals_val_get(this%mincrawl_section, "TEMPERATURE_INIT", r_val=temp_in_kelvin)
126 this%tempstep_init = temp2tempstep(this, temp_in_kelvin/kelvin)
127 CALL section_vals_val_get(this%mincrawl_section, "WORKER_PER_MINIMA", i_val=this%worker_per_min)
128 CALL section_vals_val_get(this%mincrawl_section, "ESCAPE_HISTORY_LENGTH", i_val=this%esc_hist_len)
129
130 !init minima trajectory
131 logger => cp_get_default_logger()
132 this%minima_traj_unit = cp_print_key_unit_nr(logger, &
133 this%mincrawl_section, "MINIMA_TRAJECTORY", &
134 middle_name="minima", extension=".xyz", &
135 file_action="WRITE", file_position="REWIND")
136
137 !init history
138 history_section => section_vals_get_subs_vals(glbopt_section, "HISTORY")
139 CALL history_init(this%history, history_section, iw=iw)
140
141 !allocate data structures
142 ALLOCATE (this%minimas(1000)) !will be grown if needed
143
144 ALLOCATE (this%workers(n_workers))
145 this%n_workers = n_workers
146 this%iw = iw
147 this%particle_set => particle_set
148
149 ! call fermi-like stepfunction for initial temp-dist
150 ALLOCATE (this%tempdist_init(this%tempstep_max))
151 this%tempdist_init = 0.0
152 DO i = 1, this%tempstep_max
153 this%tempdist_init(i) = 1.0/(1.0 + exp((this%tempstep_init - i)/this%tempdist_init_width))
154 END DO
155
156 this%rng_stream = rng_stream_type(name="mincrawl")
157 END SUBROUTINE mincrawl_init
158
159! **************************************************************************************************
160!> \brief Central steering routine of Minima Crawling
161!> \param this ...
162!> \param report ...
163!> \param cmd ...
164!> \author Ole Schuett
165! **************************************************************************************************
166 SUBROUTINE mincrawl_steer(this, report, cmd)
167 TYPE(mincrawl_type) :: this
168 TYPE(swarm_message_type) :: report, cmd
169
170 CHARACTER(len=default_string_length) :: status
171 INTEGER :: wid
172 TYPE(minima_type), POINTER :: best_minima
173
174 CALL swarm_message_get(report, "status", status)
175 CALL swarm_message_get(report, "worker_id", wid)
176
177 IF (trim(status) == "initial_hello") THEN
178 this%workers(wid)%tempstep = this%tempstep_init
179 CALL swarm_message_add(cmd, "command", "md_and_gopt")
180 CALL swarm_message_add(cmd, "iframe", 1)
181 CALL swarm_message_add(cmd, "temperature", tempstep2temp(this, this%workers(wid)%tempstep))
182 RETURN
183 END IF
184
185 IF (trim(status) == "ok") &
186 CALL mincrawl_register_minima(this, report)
187
188 IF (.false.) CALL print_tempdist(best_minima)
189
190 best_minima => choose_promising_minima(this)
191
192 IF (.NOT. ASSOCIATED(best_minima)) THEN ! no suitable minima found
193 CALL swarm_message_add(cmd, "command", "wait")
194 !WRITE(this%iw,*) " MINCRAWL| Waiting until new minima become available"
195 RETURN
196 END IF
197
198 best_minima%n_active = best_minima%n_active + 1
199 best_minima%n_sampled = best_minima%n_sampled + 1
200 this%workers(wid)%start_minima => best_minima
201 this%workers(wid)%tempstep = choose_tempstep(this, best_minima)
202
203 CALL swarm_message_add(cmd, "command", "md_and_gopt")
204 CALL swarm_message_add(cmd, "iframe", this%workers(wid)%iframe)
205 CALL swarm_message_add(cmd, "temperature", tempstep2temp(this, this%workers(wid)%tempstep))
206 CALL swarm_message_add(cmd, "positions", best_minima%pos)
207
208 IF (this%iw > 0) THEN
209 WRITE (this%iw, '(1X,A,T71,I10)') &
210 "MINCRAWL| Total number of found minima", this%n_minima
211 WRITE (this%iw, '(1X,A,T71,I10)') &
212 "MINCRAWL| Sampling minima with id", best_minima%id
213 WRITE (this%iw, '(1X,A,I10,A,A,T71,F10.3)') &
214 "MINCRAWL| Temperature (step ", this%workers(wid)%tempstep, " ) ", &
215 "[Kelvin]", kelvin*tempstep2temp(this, this%workers(wid)%tempstep)
216 END IF
217
218 END SUBROUTINE mincrawl_steer
219
220! **************************************************************************************************
221!> \brief Helper routine for mincrawl_steer, choses minimum based on its score.
222!> \param this ...
223!> \return ...
224!> \author Ole Schuett
225! **************************************************************************************************
226 FUNCTION choose_promising_minima(this) RESULT(minima)
227 TYPE(mincrawl_type) :: this
228 TYPE(minima_type), POINTER :: minima
229
230 INTEGER :: i
231 REAL(kind=dp) :: score, score_best
232
233 score_best = huge(1.0)
234 NULLIFY (minima)
235
236 DO i = 1, this%n_minima
237 IF (this%minimas(i)%p%disabled) cycle
238 IF (this%minimas(i)%p%n_active > this%worker_per_min) cycle
239 score = minima_score(this%minimas(i)%p)
240! WRITE (*,*) "Minima: ", i, " active: ",this%minimas(i)%active, " E_expect: ", E_expect
241 IF (score < score_best) THEN
242 score_best = score
243 minima => this%minimas(i)%p
244 END IF
245 END DO
246 END FUNCTION choose_promising_minima
247
248! **************************************************************************************************
249!> \brief Helper routine for choose_promising_minima, calculates a minimum's score
250!> \param minima ...
251!> \return ...
252!> \author Ole Schuett
253! **************************************************************************************************
254 FUNCTION minima_score(minima) RESULT(res)
255 TYPE(minima_type), POINTER :: minima
256 REAL(kind=dp) :: res
257
258 res = sum(minima%escape_hist)/SIZE(minima%escape_hist)
259 END FUNCTION minima_score
260
261! **************************************************************************************************
262!> \brief Helper routine for mincrawl_steer, samples from a temp-dist.
263!> \param this ...
264!> \param minima ...
265!> \return ...
266!> \author Ole Schuett
267! **************************************************************************************************
268 FUNCTION choose_tempstep(this, minima) RESULT(step)
269 TYPE(mincrawl_type) :: this
270 TYPE(minima_type), POINTER :: minima
271 INTEGER :: step
272
273 REAL(kind=dp) :: a, r
274
275 DO
276 r = this%rng_stream%next()
277 step = int(r*SIZE(minima%tempdist)) + 1
278 a = 1.0 - 2.0*abs(minima%tempdist(step) - 0.5)
279 r = this%rng_stream%next()
280 IF (r < a) EXIT
281 END DO
282
283 END FUNCTION choose_tempstep
284
285! **************************************************************************************************
286!> \brief Debugging routine, prints a minimum's temp-distribution.
287!> \param minima ...
288!> \author Ole Schuett
289! **************************************************************************************************
290 SUBROUTINE print_tempdist(minima)
291 TYPE(minima_type), POINTER :: minima
292
293 INTEGER :: i
294
295!WRITE (*,*) "tempdist: ", SUM(minima%tempdist, DIM=1)
296
297 DO i = 1, SIZE(minima%tempdist)
298 WRITE (*, *) "tempstep: ", i, minima%tempdist(i)
299 END DO
300 END SUBROUTINE print_tempdist
301
302! **************************************************************************************************
303!> \brief Helper routine, convertes a discrete temp-step to a temperature.
304!> \param this ...
305!> \param step ...
306!> \return ...
307!> \author Ole Schuett
308! **************************************************************************************************
309 FUNCTION tempstep2temp(this, step) RESULT(temp_in_au)
310 TYPE(mincrawl_type) :: this
311 INTEGER :: step
312 REAL(kind=dp) :: temp_in_au
313
314 temp_in_au = (this%tempstep_base**step)/kelvin
315 END FUNCTION tempstep2temp
316
317! **************************************************************************************************
318!> \brief Helper routine, convertes a temperature to a discrete temp-step.
319!> \param this ...
320!> \param temp_in_au ...
321!> \return ...
322!> \author Ole Schuett
323! **************************************************************************************************
324 FUNCTION temp2tempstep(this, temp_in_au) RESULT(step)
325 TYPE(mincrawl_type) :: this
326 REAL(kind=dp) :: temp_in_au
327 INTEGER :: step
328
329 step = int(log(temp_in_au*kelvin)/log(this%tempstep_base))
330 !WRITE(*,*) "temp: ", temp_in_au*kelvin, this%tempstep_base
331 !WRITE(*,*) "step: ", step
332 IF (step > this%tempstep_max) cpabort("temp2tempstep: step > tempstep_max")
333 END FUNCTION temp2tempstep
334
335! **************************************************************************************************
336!> \brief Helper routine for mincrawl_steer
337!> Incorporates information of new report into history.
338!> \param this ...
339!> \param report ...
340!> \author Ole Schuett
341! **************************************************************************************************
342 SUBROUTINE mincrawl_register_minima(this, report)
343 TYPE(mincrawl_type) :: this
344 TYPE(swarm_message_type) :: report
345
346 INTEGER :: new_mid, tempstep, wid
347 LOGICAL :: minima_known
348 REAL(kind=dp) :: report_epot
349 REAL(kind=dp), DIMENSION(:), POINTER :: report_positions
350 TYPE(history_fingerprint_type) :: report_fp
351 TYPE(minima_p_type), ALLOCATABLE, DIMENSION(:) :: minimas_tmp
352 TYPE(minima_type), POINTER :: new_minima, start_minima
353
354 NULLIFY (start_minima, new_minima, report_positions)
355
356 CALL swarm_message_get(report, "worker_id", wid)
357 CALL swarm_message_get(report, "Epot", report_epot)
358 CALL swarm_message_get(report, "positions", report_positions)
359 CALL swarm_message_get(report, "iframe", this%workers(wid)%iframe)
360
361 start_minima => this%workers(wid)%start_minima
362 tempstep = this%workers(wid)%tempstep
363
364 report_fp = history_fingerprint(report_epot, report_positions)
365 CALL history_lookup(this%history, report_fp, minima_known)
366
367 IF (ASSOCIATED(start_minima)) THEN
368 start_minima%n_active = start_minima%n_active - 1
369 IF (start_minima%n_active < 0) cpabort("negative n_active")
370
371 ! update tempdist and escape_hist
372 IF (minima_known) THEN
373 CALL update_tempdist(this, start_minima%tempdist, tempstep, -1)
374 ELSE
375 CALL update_tempdist(this, start_minima%tempdist, tempstep, +1)
376 start_minima%escape_hist(:) = eoshift(start_minima%escape_hist, 1)
377 start_minima%escape_hist(1) = report_epot
378 END IF
379
380 END IF
381
382 IF (.NOT. minima_known) THEN
383 this%n_minima = this%n_minima + 1
384 IF (this%n_minima > SIZE(this%minimas)) THEN
385 ALLOCATE (minimas_tmp(SIZE(this%minimas)))
386 minimas_tmp(:) = this%minimas
387 DEALLOCATE (this%minimas)
388 ALLOCATE (this%minimas(SIZE(minimas_tmp) + 1000))
389 this%minimas(:SIZE(minimas_tmp)) = minimas_tmp
390 DEALLOCATE (minimas_tmp)
391 END IF
392
393 new_mid = this%n_minima
394 ALLOCATE (this%minimas(new_mid)%p)
395 new_minima => this%minimas(new_mid)%p
396 new_minima%id = new_mid
397 ALLOCATE (new_minima%escape_hist(this%esc_hist_len))
398 ALLOCATE (new_minima%tempdist(this%tempstep_max))
399
400 new_minima%escape_hist(:) = report_epot !init with Epot
401
402 IF (ASSOCIATED(start_minima)) THEN
403 new_minima%tempdist(:) = start_minima%tempdist ! inherit tempdist
404 ELSE
405 new_minima%tempdist(:) = this%tempdist_init
406 END IF
407
408 new_minima%Epot = report_epot
409 new_minima%fp = report_fp
410 ALLOCATE (new_minima%pos(SIZE(report_positions)))
411 new_minima%pos(:) = report_positions
412
413 IF (ASSOCIATED(start_minima)) THEN
414 IF (report_epot < start_minima%Epot) THEN
415 start_minima%disabled = .true.
416 IF (this%iw > 0) WRITE (this%iw, '(1X,A,T71,I10)') &
417 "MINCRAWL| Disabling minimum with id", start_minima%id
418 END IF
419 END IF
420
421 IF (this%iw > 0) WRITE (this%iw, '(1X,A,T71,I10)') &
422 "MINCRAWL| Adding new minima with id", new_mid
423
424 CALL history_add(this%history, report_fp, id=new_mid)
425 CALL write_minima_traj(this, wid, new_mid, report_epot, report_positions)
426 END IF
427 DEALLOCATE (report_positions)
428 END SUBROUTINE mincrawl_register_minima
429
430! **************************************************************************************************
431!> \brief Helper routine for mincrawl_register_minima.
432!> Adds or subtracts small Gaussian from a minimum's temp-distribution.
433!> \param this ...
434!> \param tempdist ...
435!> \param center ...
436!> \param direction ...
437!> \author Ole Schuett
438! **************************************************************************************************
439 SUBROUTINE update_tempdist(this, tempdist, center, direction)
440 TYPE(mincrawl_type) :: this
441 REAL(kind=dp), DIMENSION(:), INTENT(INOUT) :: tempdist
442 INTEGER :: center, direction
443
444 INTEGER :: i
445
446 DO i = 1, SIZE(tempdist)
447 tempdist(i) = tempdist(i) + this%tempdist_update_height &
448 *real(direction, kind=dp)*exp(-((center - i)/this%tempdist_update_width)**2)
449 tempdist(i) = max(0.0_dp, min(1.0_dp, tempdist(i)))
450 END DO
451 END SUBROUTINE update_tempdist
452
453! **************************************************************************************************
454!> \brief Helper routine for mincrawl_register_minima, write trajectory.
455!> \param this ...
456!> \param worker_id ...
457!> \param minimum_id ...
458!> \param Epot ...
459!> \param positions ...
460!> \author Ole Schuett
461! **************************************************************************************************
462 SUBROUTINE write_minima_traj(this, worker_id, minimum_id, Epot, positions)
463 TYPE(mincrawl_type), INTENT(INOUT) :: this
464 INTEGER, INTENT(IN) :: worker_id, minimum_id
465 REAL(kind=dp), INTENT(IN) :: epot
466 REAL(kind=dp), DIMENSION(:), POINTER :: positions
467
468 CHARACTER(len=default_string_length) :: title, unit_str
469 REAL(kind=dp) :: unit_conv
470
471 IF (this%minima_traj_unit <= 0) RETURN
472
473 WRITE (title, '(A,I8,A,I5,A,F20.10)') 'minimum_id = ', minimum_id, &
474 ' worker_id = ', worker_id, ' Epot = ', epot
475
476 !get the conversion factor for the length unit
477 CALL section_vals_val_get(this%mincrawl_section, "MINIMA_TRAJECTORY%UNIT", &
478 c_val=unit_str)
479 unit_conv = cp_unit_from_cp2k(1.0_dp, trim(unit_str))
480
481 CALL write_particle_coordinates(this%particle_set, &
482 iunit=this%minima_traj_unit, &
483 output_format=dump_xmol, &
484 content="POS", &
485 title=trim(title), &
486 array=positions, &
487 unit_conv=unit_conv)
488 END SUBROUTINE write_minima_traj
489
490! **************************************************************************************************
491!> \brief Finalizes master for Minima Crawling
492!> \param this ...
493!> \author Ole Schuett
494! **************************************************************************************************
495 SUBROUTINE mincrawl_finalize(this)
496 TYPE(mincrawl_type) :: this
497
498 INTEGER :: i
499 TYPE(cp_logger_type), POINTER :: logger
500
501 NULLIFY (logger)
502
503 DO i = 1, this%n_minima
504 !WRITE (*,*) "Minima: ", i, " n_sampled: ",this%minimas(i)%n_sampled
505 DEALLOCATE (this%minimas(i)%p)
506 END DO
507
508 logger => cp_get_default_logger()
509 CALL cp_print_key_finished_output(this%minima_traj_unit, logger, &
510 this%mincrawl_section, "MINIMA_TRAJECTORY")
511
512 CALL history_finalize(this%history)
513 END SUBROUTINE mincrawl_finalize
514
515END MODULE glbopt_mincrawl
516
Adds an entry from a swarm-message.
Returns an entry from a swarm-message.
various routines to log and control the output. The idea is that decisions about where to log should ...
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
routines to handle the output, The idea is to remove the decision of wheter to output and what to out...
integer function, public cp_print_key_unit_nr(logger, basis_section, print_key_path, extension, middle_name, local, log_filename, ignore_should_output, file_form, file_position, file_action, file_status, do_backup, on_file, is_new_file, mpi_io, fout)
...
subroutine, public cp_print_key_finished_output(unit_nr, logger, basis_section, print_key_path, local, ignore_should_output, on_file, mpi_io)
should be called after you finish working with a unit obtained with cp_print_key_unit_nr,...
unit conversion facility
Definition cp_units.F:30
real(kind=dp) function, public cp_unit_from_cp2k(value, unit_str, defaults, power)
converts from the internal cp2k units to the given unit
Definition cp_units.F:1179
History of minima, calculates, stores and compares fingerprints of minima. Used by Minima Hopping and...
subroutine, public history_init(history, history_section, iw)
Initializes a history.
type(history_fingerprint_type) function, public history_fingerprint(epot, pos)
Calculates a fingerprint for a given configuration.
subroutine, public history_lookup(history, fingerprint, found, id)
Checks if a given fingerprints is contained in the history.
subroutine, public history_finalize(history)
Finalizes a history.
subroutine, public history_add(history, fingerprint, id)
Addes a new fingerprints to the history. Optionally, an abitrary id can be stored alongside the finge...
Routines for the Minima Crawling global optimization scheme.
subroutine, public mincrawl_init(this, glbopt_section, n_workers, iw, particle_set)
Initializes master for Minima Crawling.
subroutine, public mincrawl_finalize(this)
Finalizes master for Minima Crawling.
subroutine, public mincrawl_steer(this, report, cmd)
Central steering routine of Minima Crawling.
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public dump_xmol
objects that represent the structure of input sections and the data contained in an input section
recursive type(section_vals_type) function, pointer, public section_vals_get_subs_vals(section_vals, subsection_name, i_rep_section, can_return_null)
returns the values of the requested subsection
subroutine, public section_vals_val_get(section_vals, keyword_name, i_rep_section, i_rep_val, n_rep_val, val, l_val, i_val, r_val, c_val, l_vals, i_vals, r_vals, c_vals, explicit)
returns the requested value
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
integer, parameter, public default_string_length
Definition kinds.F:57
Parallel (pseudo)random number generator (RNG) for multiple streams and substreams of random numbers.
Define methods related to particle_type.
subroutine, public write_particle_coordinates(particle_set, iunit, output_format, content, title, cell, array, unit_conv, charge_occup, charge_beta, charge_extended, print_kind)
Should be able to write a few formats e.g. xmol, and some binary format (dcd) some format can be used...
Define the data structure for the particle information.
Definition of physical constants:
Definition physcon.F:68
real(kind=dp), parameter, public kelvin
Definition physcon.F:165
Swarm-message, a convenient data-container for with build-in serialization.
type of a logger, at the moment it contains just a print level starting at which level it should be l...