(git:e8f5963)
Loading...
Searching...
No Matches
cp_lbfgs_optimizer_gopt.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \brief routines that optimize a functional using the limited memory bfgs
10!> quasi-newton method.
11!> The process set up so that a master runs the real optimizer and the
12!> others help then to calculate the objective function.
13!> The arguments for the objective function are physically present in
14!> every processor (nedeed in the actual implementation of pao).
15!> In the future tha arguments themselves could be distributed.
16!> \par History
17!> 09.2003 globenv->para_env, retain/release, better parallel behaviour
18!> 01.2020 Space Group Symmetry introduced by Pierre-André Cazade [pcazade]
19!> \author Fawzi Mohamed
20!> @version 2.2002
21! **************************************************************************************************
23 USE cp_lbfgs, ONLY: setulb
32 USE force_env_types, ONLY: force_env_get, &
34 USE gopt_f_methods, ONLY: gopt_f_io
35 USE gopt_f_types, ONLY: gopt_f_release, &
40 USE kinds, ONLY: dp
41 USE machine, ONLY: m_walltime
45#include "../base/base_uses.f90"
46
47 IMPLICIT NONE
48 PRIVATE
49
50
51! **************************************************************************************************
52!> \brief evaluate the potential energy and its gradients using an array
53!> with same dimension as the particle_set
54!> \param gopt_env the geometry optimization environment
55!> \param x the position where the function should be evaluated
56!> \param f the function value
57!> \param gradient the value of its gradient
58!> \par History
59!> none
60!> \author Teodoro Laino [tlaino] - University of Zurich - 01.2008
61! **************************************************************************************************
62INTERFACE
63
64 SUBROUTINE cp_eval_at(gopt_env, x, f, gradient, master, &
65 final_evaluation, para_env)
66
68 USE gopt_f_types, ONLY: gopt_f_type
69 USE kinds, ONLY: dp
70
71 TYPE(gopt_f_type), POINTER :: gopt_env
72 REAL(KIND=dp), DIMENSION(:), POINTER :: x
73 REAL(KIND=dp), INTENT(out), OPTIONAL :: f
74 REAL(KIND=dp), DIMENSION(:), OPTIONAL, &
75 POINTER :: gradient
76 INTEGER, INTENT(IN) :: master
77 LOGICAL, INTENT(IN), OPTIONAL :: final_evaluation
78 TYPE(mp_para_env_type), POINTER :: para_env
79
80 END SUBROUTINE cp_eval_at
81
82END INTERFACE
83
84 LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .true.
85 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cp_lbfgs_optimizer_gopt'
86
87 ! types
89
90 ! core methods
91
92 ! special methos
93
94 ! underlying functions
98
99! **************************************************************************************************
100!> \brief info for the optimizer (see the description of this module)
101!> \param task the actual task of the optimizer (in the master it is up to
102!> date, in case of error also the minions one get updated.
103!> \param csave internal character string used by the lbfgs optimizer,
104!> meaningful only in the master
105!> \param lsave logical array used by the lbfgs optimizer, updated only
106!> in the master
107!> On exit with task = 'NEW_X', the following information is
108!> available:
109!> lsave(1) = .true. the initial x did not satisfy the bounds;
110!> lsave(2) = .true. the problem contains bounds;
111!> lsave(3) = .true. each variable has upper and lower bounds.
112!> \param ref_count reference count (see doc/ReferenceCounting.html)
113!> \param m the dimension of the subspace used to approximate the second
114!> derivative
115!> \param print_every every how many iterations output should be written.
116!> if 0 only at end, if print_every<0 never
117!> \param master the pid of the master processor
118!> \param max_f_per_iter the maximum number of function evaluations per
119!> iteration
120!> \param status 0: just initialized, 1: f g calculation,
121!> 2: begin new iteration, 3: ended iteration,
122!> 4: normal (converged) exit, 5: abnormal (error) exit,
123!> 6: daellocated
124!> \param n_iter the actual iteration number
125!> \param kind_of_bound an array with 0 (no bound), 1 (lower bound),
126!> 2 (both bounds), 3 (upper bound), to describe the bounds
127!> of every variable
128!> \param i_work_array an integer workarray of dimension 3*n, present only
129!> in the master
130!> \param isave is an INTEGER working array of dimension 44.
131!> On exit with task = 'NEW_X', it contains information that
132!> the user may want to access:
133!> \param isave (30) = the current iteration number;
134!> \param isave (34) = the total number of function and gradient
135!> evaluations;
136!> \param isave (36) = the number of function value or gradient
137!> evaluations in the current iteration;
138!> \param isave (38) = the number of free variables in the current
139!> iteration;
140!> \param isave (39) = the number of active constraints at the current
141!> iteration;
142!> \param f the actual best value of the object function
143!> \param wanted_relative_f_delta the wanted relative error on f
144!> (to be multiplied by epsilon), 0.0 -> no check
145!> \param wanted_projected_gradient the wanted error on the projected
146!> gradient (hessian times the gradient), 0.0 -> no check
147!> \param last_f the value of f in the last iteration
148!> \param projected_gradient the value of the sup norm of the projected
149!> gradient
150!> \param x the actual evaluation point (best one if converged or stopped)
151!> \param lower_bound the lower bounds
152!> \param upper_bound the upper bounds
153!> \param gradient the actual gradient
154!> \param dsave info date for lbfgs (master only)
155!> \param work_array a work array for lbfgs (master only)
156!> \param para_env the parallel environment for this optimizer
157!> \param obj_funct the objective function to be optimized
158!> \par History
159!> none
160!> \author Fawzi Mohamed
161!> @version 2.2002
162! **************************************************************************************************
164 CHARACTER(len=60) :: task = ""
165 CHARACTER(len=60) :: csave = ""
166 LOGICAL :: lsave(4) = .false.
167 INTEGER :: m = 0, print_every = 0, master = 0, max_f_per_iter = 0, status = 0, n_iter = 0
168 INTEGER, DIMENSION(:), POINTER :: kind_of_bound => null(), i_work_array => null(), isave => null()
169 REAL(kind=dp) :: f = 0.0_dp, wanted_relative_f_delta = 0.0_dp, wanted_projected_gradient = 0.0_dp, &
170 last_f = 0.0_dp, projected_gradient = 0.0_dp, eold = 0.0_dp, emin = 0.0_dp, trust_radius = 0.0_dp
171 REAL(kind=dp), DIMENSION(:), POINTER :: x => null(), lower_bound => null(), upper_bound => null(), &
172 gradient => null(), dsave => null(), work_array => null()
173 TYPE(mp_para_env_type), POINTER :: para_env => null()
174 TYPE(gopt_f_type), POINTER :: obj_funct => null()
176
177CONTAINS
178
179! **************************************************************************************************
180!> \brief initializes the optimizer
181!> \param optimizer ...
182!> \param para_env ...
183!> \param obj_funct ...
184!> \param x0 ...
185!> \param m ...
186!> \param print_every ...
187!> \param wanted_relative_f_delta ...
188!> \param wanted_projected_gradient ...
189!> \param lower_bound ...
190!> \param upper_bound ...
191!> \param kind_of_bound ...
192!> \param master ...
193!> \param max_f_per_iter ...
194!> \param trust_radius ...
195!> \par History
196!> 02.2002 created [fawzi]
197!> 09.2003 refactored (retain/release,para_env) [fawzi]
198!> \author Fawzi Mohamed
199!> \note
200!> redirects the lbfgs output the the default unit
201! **************************************************************************************************
202 SUBROUTINE cp_opt_gopt_create(optimizer, para_env, obj_funct, x0, m, print_every, &
203 wanted_relative_f_delta, wanted_projected_gradient, lower_bound, upper_bound, &
204 kind_of_bound, master, max_f_per_iter, trust_radius)
205 TYPE(cp_lbfgs_opt_gopt_type), INTENT(OUT) :: optimizer
206 TYPE(mp_para_env_type), POINTER :: para_env
207 TYPE(gopt_f_type), POINTER :: obj_funct
208 REAL(kind=dp), DIMENSION(:), INTENT(in) :: x0
209 INTEGER, INTENT(in), OPTIONAL :: m, print_every
210 REAL(kind=dp), INTENT(in), OPTIONAL :: wanted_relative_f_delta, &
211 wanted_projected_gradient
212 REAL(kind=dp), DIMENSION(SIZE(x0)), INTENT(in), &
213 OPTIONAL :: lower_bound, upper_bound
214 INTEGER, DIMENSION(SIZE(x0)), INTENT(in), OPTIONAL :: kind_of_bound
215 INTEGER, INTENT(in), OPTIONAL :: master, max_f_per_iter
216 REAL(kind=dp), INTENT(in), OPTIONAL :: trust_radius
217
218 CHARACTER(len=*), PARAMETER :: routinen = 'cp_opt_gopt_create'
219
220 INTEGER :: handle, lenwa, n
221
222 CALL timeset(routinen, handle)
223
224 NULLIFY (optimizer%kind_of_bound, &
225 optimizer%i_work_array, &
226 optimizer%isave, &
227 optimizer%x, &
228 optimizer%lower_bound, &
229 optimizer%upper_bound, &
230 optimizer%gradient, &
231 optimizer%dsave, &
232 optimizer%work_array, &
233 optimizer%para_env, &
234 optimizer%obj_funct)
235 n = SIZE(x0)
236 optimizer%m = 4
237 IF (PRESENT(m)) optimizer%m = m
238 optimizer%master = para_env%source
239 optimizer%para_env => para_env
240 CALL para_env%retain()
241 optimizer%obj_funct => obj_funct
242 CALL gopt_f_retain(obj_funct)
243 optimizer%max_f_per_iter = 20
244 IF (PRESENT(max_f_per_iter)) optimizer%max_f_per_iter = max_f_per_iter
245 optimizer%print_every = -1
246 optimizer%n_iter = 0
247 optimizer%f = -1.0_dp
248 optimizer%last_f = -1.0_dp
249 optimizer%projected_gradient = -1.0_dp
250 IF (PRESENT(print_every)) optimizer%print_every = print_every
251 IF (PRESENT(master)) optimizer%master = master
252 IF (optimizer%master == optimizer%para_env%mepos) THEN
253 !MK This has to be adapted for a new L-BFGS version possibly
254 lenwa = 2*optimizer%m*n + 5*n + 11*optimizer%m*optimizer%m + 8*optimizer%m
255 ALLOCATE (optimizer%kind_of_bound(n), optimizer%i_work_array(3*n), &
256 optimizer%isave(44))
257 ALLOCATE (optimizer%x(n), optimizer%lower_bound(n), &
258 optimizer%upper_bound(n), optimizer%gradient(n), &
259 optimizer%dsave(29), optimizer%work_array(lenwa))
260 optimizer%x = x0
261 optimizer%task = 'START'
262 optimizer%i_work_array = 0
263 optimizer%isave = 0
264 optimizer%lower_bound = 0.0_dp
265 optimizer%upper_bound = 0.0_dp
266 optimizer%gradient = 0.0_dp
267 optimizer%dsave = 0.0_dp
268 optimizer%work_array = 0.0_dp
269 IF (PRESENT(wanted_relative_f_delta)) &
270 optimizer%wanted_relative_f_delta = wanted_relative_f_delta
271 IF (PRESENT(wanted_projected_gradient)) &
272 optimizer%wanted_projected_gradient = wanted_projected_gradient
273 optimizer%kind_of_bound = 0
274 IF (PRESENT(kind_of_bound)) optimizer%kind_of_bound = kind_of_bound
275 IF (PRESENT(lower_bound)) optimizer%lower_bound = lower_bound
276 IF (PRESENT(upper_bound)) optimizer%upper_bound = upper_bound
277 IF (PRESENT(trust_radius)) optimizer%trust_radius = trust_radius
278
279 CALL setulb(SIZE(optimizer%x), optimizer%m, optimizer%x, &
280 optimizer%lower_bound, optimizer%upper_bound, &
281 optimizer%kind_of_bound, optimizer%f, optimizer%gradient, &
282 optimizer%wanted_relative_f_delta, &
283 optimizer%wanted_projected_gradient, optimizer%work_array, &
284 optimizer%i_work_array, optimizer%task, optimizer%print_every, &
285 optimizer%csave, optimizer%lsave, optimizer%isave, &
286 optimizer%dsave, optimizer%trust_radius)
287 ELSE
288 NULLIFY ( &
289 optimizer%kind_of_bound, optimizer%i_work_array, optimizer%isave, &
290 optimizer%lower_bound, optimizer%upper_bound, optimizer%gradient, &
291 optimizer%dsave, optimizer%work_array)
292 ALLOCATE (optimizer%x(n))
293 optimizer%x(:) = 0.0_dp
294 ALLOCATE (optimizer%gradient(n))
295 optimizer%gradient(:) = 0.0_dp
296 END IF
297 CALL optimizer%para_env%bcast(optimizer%x, optimizer%master)
298 optimizer%status = 0
299
300 CALL timestop(handle)
301
302 END SUBROUTINE cp_opt_gopt_create
303
304! **************************************************************************************************
305!> \brief releases the optimizer (see doc/ReferenceCounting.html)
306!> \param optimizer the object that should be released
307!> \par History
308!> 02.2002 created [fawzi]
309!> 09.2003 dealloc_ref->release [fawzi]
310!> \author Fawzi Mohamed
311! **************************************************************************************************
312 SUBROUTINE cp_opt_gopt_release(optimizer)
313 TYPE(cp_lbfgs_opt_gopt_type), INTENT(INOUT) :: optimizer
314
315 CHARACTER(len=*), PARAMETER :: routinen = 'cp_opt_gopt_release'
316
317 INTEGER :: handle
318
319 CALL timeset(routinen, handle)
320
321 IF (ASSOCIATED(optimizer%kind_of_bound)) THEN
322 DEALLOCATE (optimizer%kind_of_bound)
323 END IF
324 IF (ASSOCIATED(optimizer%i_work_array)) THEN
325 DEALLOCATE (optimizer%i_work_array)
326 END IF
327 IF (ASSOCIATED(optimizer%isave)) THEN
328 DEALLOCATE (optimizer%isave)
329 END IF
330 IF (ASSOCIATED(optimizer%x)) THEN
331 DEALLOCATE (optimizer%x)
332 END IF
333 IF (ASSOCIATED(optimizer%lower_bound)) THEN
334 DEALLOCATE (optimizer%lower_bound)
335 END IF
336 IF (ASSOCIATED(optimizer%upper_bound)) THEN
337 DEALLOCATE (optimizer%upper_bound)
338 END IF
339 IF (ASSOCIATED(optimizer%gradient)) THEN
340 DEALLOCATE (optimizer%gradient)
341 END IF
342 IF (ASSOCIATED(optimizer%dsave)) THEN
343 DEALLOCATE (optimizer%dsave)
344 END IF
345 IF (ASSOCIATED(optimizer%work_array)) THEN
346 DEALLOCATE (optimizer%work_array)
347 END IF
348 CALL mp_para_env_release(optimizer%para_env)
349 CALL gopt_f_release(optimizer%obj_funct)
350
351 CALL timestop(handle)
352 END SUBROUTINE cp_opt_gopt_release
353
354! **************************************************************************************************
355!> \brief takes different valuse from the optimizer
356!> \param optimizer ...
357!> \param para_env ...
358!> \param obj_funct ...
359!> \param m ...
360!> \param print_every ...
361!> \param wanted_relative_f_delta ...
362!> \param wanted_projected_gradient ...
363!> \param x ...
364!> \param lower_bound ...
365!> \param upper_bound ...
366!> \param kind_of_bound ...
367!> \param master ...
368!> \param actual_projected_gradient ...
369!> \param n_var ...
370!> \param n_iter ...
371!> \param status ...
372!> \param max_f_per_iter ...
373!> \param at_end ...
374!> \param is_master ...
375!> \param last_f ...
376!> \param f ...
377!> \par History
378!> none
379!> \author Fawzi Mohamed
380!> @version 2.2002
381! **************************************************************************************************
382 SUBROUTINE cp_opt_gopt_get(optimizer, para_env, &
383 obj_funct, m, print_every, &
384 wanted_relative_f_delta, wanted_projected_gradient, &
385 x, lower_bound, upper_bound, kind_of_bound, master, &
386 actual_projected_gradient, &
387 n_var, n_iter, status, max_f_per_iter, at_end, &
388 is_master, last_f, f)
389 TYPE(cp_lbfgs_opt_gopt_type), INTENT(IN) :: optimizer
390 TYPE(mp_para_env_type), OPTIONAL, POINTER :: para_env
391 TYPE(gopt_f_type), OPTIONAL, POINTER :: obj_funct
392 INTEGER, INTENT(out), OPTIONAL :: m, print_every
393 REAL(kind=dp), INTENT(out), OPTIONAL :: wanted_relative_f_delta, &
394 wanted_projected_gradient
395 REAL(kind=dp), DIMENSION(:), OPTIONAL, POINTER :: x, lower_bound, upper_bound
396 INTEGER, DIMENSION(:), OPTIONAL, POINTER :: kind_of_bound
397 INTEGER, INTENT(out), OPTIONAL :: master
398 REAL(kind=dp), INTENT(out), OPTIONAL :: actual_projected_gradient
399 INTEGER, INTENT(out), OPTIONAL :: n_var, n_iter, status, max_f_per_iter
400 LOGICAL, INTENT(out), OPTIONAL :: at_end, is_master
401 REAL(kind=dp), INTENT(out), OPTIONAL :: last_f, f
402
403 IF (PRESENT(is_master)) is_master = optimizer%master == optimizer%para_env%mepos
404 IF (PRESENT(master)) master = optimizer%master
405 IF (PRESENT(status)) status = optimizer%status
406 IF (PRESENT(para_env)) para_env => optimizer%para_env
407 IF (PRESENT(obj_funct)) obj_funct = optimizer%obj_funct
408 IF (PRESENT(m)) m = optimizer%m
409 IF (PRESENT(max_f_per_iter)) max_f_per_iter = optimizer%max_f_per_iter
410 IF (PRESENT(wanted_projected_gradient)) &
411 wanted_projected_gradient = optimizer%wanted_projected_gradient
412 IF (PRESENT(wanted_relative_f_delta)) &
413 wanted_relative_f_delta = optimizer%wanted_relative_f_delta
414 IF (PRESENT(print_every)) print_every = optimizer%print_every
415 IF (PRESENT(x)) x => optimizer%x
416 IF (PRESENT(n_var)) n_var = SIZE(x)
417 IF (PRESENT(lower_bound)) lower_bound => optimizer%lower_bound
418 IF (PRESENT(upper_bound)) upper_bound => optimizer%upper_bound
419 IF (PRESENT(kind_of_bound)) kind_of_bound => optimizer%kind_of_bound
420 IF (PRESENT(n_iter)) n_iter = optimizer%n_iter
421 IF (PRESENT(last_f)) last_f = optimizer%last_f
422 IF (PRESENT(f)) f = optimizer%f
423 IF (PRESENT(at_end)) at_end = optimizer%status > 3
424 IF (PRESENT(actual_projected_gradient)) &
425 actual_projected_gradient = optimizer%projected_gradient
426 IF (optimizer%master == optimizer%para_env%mepos) THEN
427 IF (optimizer%isave(30) > 1 .AND. (optimizer%task(1:5) == "NEW_X" .OR. &
428 optimizer%task(1:4) == "STOP" .AND. optimizer%task(7:9) == "CPU")) THEN
429 ! nr iterations >1 .and. dsave contains the wanted data
430 IF (PRESENT(last_f)) last_f = optimizer%dsave(2)
431 IF (PRESENT(actual_projected_gradient)) &
432 actual_projected_gradient = optimizer%dsave(13)
433 ELSE
434 cpassert(.NOT. PRESENT(last_f))
435 cpassert(.NOT. PRESENT(actual_projected_gradient))
436 END IF
437 ELSE IF (PRESENT(lower_bound) .OR. PRESENT(upper_bound) .OR. PRESENT(kind_of_bound)) THEN
438 cpwarn("asked undefined types")
439 END IF
440
441 END SUBROUTINE cp_opt_gopt_get
442
443! **************************************************************************************************
444!> \brief does one optimization step
445!> \param optimizer ...
446!> \param n_iter ...
447!> \param f ...
448!> \param last_f ...
449!> \param projected_gradient ...
450!> \param converged ...
451!> \param geo_section ...
452!> \param force_env ...
453!> \param gopt_param ...
454!> \param spgr ...
455!> \par History
456!> 01.2020 modified [pcazade]
457!> \author Fawzi Mohamed
458!> @version 2.2002
459!> \note
460!> use directly mainlb in place of setulb ??
461! **************************************************************************************************
462 SUBROUTINE cp_opt_gopt_step(optimizer, n_iter, f, last_f, &
463 projected_gradient, converged, geo_section, force_env, &
464 gopt_param, spgr)
465 TYPE(cp_lbfgs_opt_gopt_type), INTENT(INOUT) :: optimizer
466 INTEGER, INTENT(out), OPTIONAL :: n_iter
467 REAL(kind=dp), INTENT(out), OPTIONAL :: f, last_f, projected_gradient
468 LOGICAL, INTENT(out), OPTIONAL :: converged
469 TYPE(section_vals_type), POINTER :: geo_section
470 TYPE(force_env_type), POINTER :: force_env
471 TYPE(gopt_param_type), POINTER :: gopt_param
472 TYPE(spgr_type), OPTIONAL, POINTER :: spgr
473
474 CHARACTER(len=*), PARAMETER :: routinen = 'cp_opt_gopt_step'
475
476 CHARACTER(LEN=5) :: wildcard
477 INTEGER :: dataunit, handle, its
478 LOGICAL :: conv, is_master, justentred, &
479 keep_space_group
480 REAL(kind=dp) :: t_diff, t_now, t_old
481 REAL(kind=dp), DIMENSION(:), POINTER :: xold
482 TYPE(cp_logger_type), POINTER :: logger
483 TYPE(cp_subsys_type), POINTER :: subsys
484
485 NULLIFY (logger, xold)
486 logger => cp_get_default_logger()
487 CALL timeset(routinen, handle)
488 justentred = .true.
489 is_master = optimizer%master == optimizer%para_env%mepos
490 IF (PRESENT(converged)) converged = optimizer%status == 4
491 ALLOCATE (xold(SIZE(optimizer%x)))
492
493 ! collecting subsys
494 CALL force_env_get(force_env, subsys=subsys)
495
496 keep_space_group = .false.
497 IF (PRESENT(spgr)) THEN
498 IF (ASSOCIATED(spgr)) keep_space_group = spgr%keep_space_group
499 END IF
500
501 ! applies rotation matrices to coordinates
502 IF (keep_space_group) THEN
503 CALL spgr_apply_rotations_coord(spgr, optimizer%x)
504 END IF
505
506 xold = optimizer%x
507 t_old = m_walltime()
508
509 IF (optimizer%status >= 4) THEN
510 cpwarn("status>=4, trying to restart")
511 optimizer%status = 0
512 dataunit = cp_print_key_unit_nr(logger, geo_section, &
513 "PRINT%PROGRAM_RUN_INFO", extension=".geoLog")
514 IF (is_master) THEN
515 optimizer%task = 'START'
516 CALL setulb(SIZE(optimizer%x), optimizer%m, optimizer%x, &
517 optimizer%lower_bound, optimizer%upper_bound, &
518 optimizer%kind_of_bound, optimizer%f, optimizer%gradient, &
519 optimizer%wanted_relative_f_delta, &
520 optimizer%wanted_projected_gradient, optimizer%work_array, &
521 optimizer%i_work_array, optimizer%task, optimizer%print_every, &
522 optimizer%csave, optimizer%lsave, optimizer%isave, &
523 optimizer%dsave, optimizer%trust_radius, spgr=spgr, iwunit=dataunit)
524 END IF
525 CALL cp_print_key_finished_output(dataunit, logger, geo_section, &
526 "PRINT%PROGRAM_RUN_INFO")
527 END IF
528
529 DO
530 dataunit = cp_print_key_unit_nr(logger, geo_section, &
531 "PRINT%PROGRAM_RUN_INFO", extension=".geoLog")
532 ifmaster: IF (is_master) THEN
533 IF (optimizer%task(1:7) == 'RESTART') THEN
534 ! restart the optimizer
535 optimizer%status = 0
536 optimizer%task = 'START'
537 ! applies rotation matrices to coordinates and forces
538 IF (keep_space_group) THEN
539 CALL spgr_apply_rotations_coord(spgr, optimizer%x)
540 CALL spgr_apply_rotations_force(spgr, optimizer%gradient)
541 END IF
542 CALL setulb(SIZE(optimizer%x), optimizer%m, optimizer%x, &
543 optimizer%lower_bound, optimizer%upper_bound, &
544 optimizer%kind_of_bound, optimizer%f, optimizer%gradient, &
545 optimizer%wanted_relative_f_delta, &
546 optimizer%wanted_projected_gradient, optimizer%work_array, &
547 optimizer%i_work_array, optimizer%task, optimizer%print_every, &
548 optimizer%csave, optimizer%lsave, optimizer%isave, &
549 optimizer%dsave, optimizer%trust_radius, spgr=spgr, iwunit=dataunit)
550 IF (keep_space_group) THEN
551 CALL spgr_apply_rotations_coord(spgr, optimizer%x)
552 CALL spgr_apply_rotations_force(spgr, optimizer%gradient)
553 END IF
554 END IF
555 IF (optimizer%task(1:2) == 'FG') THEN
556 IF (optimizer%isave(36) > optimizer%max_f_per_iter) THEN
557 optimizer%task = 'STOP: CPU, hit max f eval in iter'
558 optimizer%status = 5 ! anormal exit
559 CALL setulb(SIZE(optimizer%x), optimizer%m, optimizer%x, &
560 optimizer%lower_bound, optimizer%upper_bound, &
561 optimizer%kind_of_bound, optimizer%f, optimizer%gradient, &
562 optimizer%wanted_relative_f_delta, &
563 optimizer%wanted_projected_gradient, optimizer%work_array, &
564 optimizer%i_work_array, optimizer%task, optimizer%print_every, &
565 optimizer%csave, optimizer%lsave, optimizer%isave, &
566 optimizer%dsave, optimizer%trust_radius, spgr=spgr, iwunit=dataunit)
567 ELSE
568 optimizer%status = 1
569 END IF
570 ELSE IF (optimizer%task(1:5) == 'NEW_X') THEN
571 IF (justentred) THEN
572 optimizer%status = 2
573 ! applies rotation matrices to coordinates and forces
574 IF (keep_space_group) THEN
575 CALL spgr_apply_rotations_coord(spgr, optimizer%x)
576 CALL spgr_apply_rotations_force(spgr, optimizer%gradient)
577 END IF
578 CALL setulb(SIZE(optimizer%x), optimizer%m, optimizer%x, &
579 optimizer%lower_bound, optimizer%upper_bound, &
580 optimizer%kind_of_bound, optimizer%f, optimizer%gradient, &
581 optimizer%wanted_relative_f_delta, &
582 optimizer%wanted_projected_gradient, optimizer%work_array, &
583 optimizer%i_work_array, optimizer%task, optimizer%print_every, &
584 optimizer%csave, optimizer%lsave, optimizer%isave, &
585 optimizer%dsave, optimizer%trust_radius, spgr=spgr, iwunit=dataunit)
586 IF (keep_space_group) THEN
587 CALL spgr_apply_rotations_coord(spgr, optimizer%x)
588 CALL spgr_apply_rotations_force(spgr, optimizer%gradient)
589 END IF
590 ELSE
591 ! applies rotation matrices to coordinates and forces
592 IF (keep_space_group) THEN
593 CALL spgr_apply_rotations_coord(spgr, optimizer%x)
594 CALL spgr_apply_rotations_force(spgr, optimizer%gradient)
595 END IF
596 optimizer%status = 3
597 END IF
598 ELSE IF (optimizer%task(1:4) == 'CONV') THEN
599 optimizer%status = 4
600 ELSE IF (optimizer%task(1:4) == 'STOP') THEN
601 optimizer%status = 5
602 cpwarn("task became stop in an unknown way")
603 ELSE IF (optimizer%task(1:5) == 'ERROR') THEN
604 optimizer%status = 5
605 ELSE
606 cpwarn("unknown task '"//optimizer%task//"'")
607 END IF
608 END IF ifmaster
609 CALL cp_print_key_finished_output(dataunit, logger, geo_section, &
610 "PRINT%PROGRAM_RUN_INFO")
611 CALL optimizer%para_env%bcast(optimizer%status, optimizer%master)
612 ! Dump info
613 IF (optimizer%status == 3) THEN
614 its = 0
615 IF (is_master) THEN
616 ! Iteration level is taken into account in the optimizer external loop
617 its = optimizer%isave(30)
618 END IF
619 END IF
620 !
621 SELECT CASE (optimizer%status)
622 CASE (1)
623 !op=1 evaluate f and g
624 CALL cp_eval_at(optimizer%obj_funct, x=optimizer%x, &
625 f=optimizer%f, &
626 gradient=optimizer%gradient, &
627 final_evaluation=.false., &
628 master=optimizer%master, para_env=optimizer%para_env)
629 ! do not use keywords?
630 dataunit = cp_print_key_unit_nr(logger, geo_section, &
631 "PRINT%PROGRAM_RUN_INFO", extension=".geoLog")
632 IF (is_master) THEN
633 ! applies rotation matrices to coordinates and forces
634 IF (keep_space_group) THEN
635 CALL spgr_apply_rotations_coord(spgr, optimizer%x)
636 CALL spgr_apply_rotations_force(spgr, optimizer%gradient)
637 END IF
638 CALL setulb(SIZE(optimizer%x), optimizer%m, optimizer%x, &
639 optimizer%lower_bound, optimizer%upper_bound, &
640 optimizer%kind_of_bound, optimizer%f, optimizer%gradient, &
641 optimizer%wanted_relative_f_delta, &
642 optimizer%wanted_projected_gradient, optimizer%work_array, &
643 optimizer%i_work_array, optimizer%task, optimizer%print_every, &
644 optimizer%csave, optimizer%lsave, optimizer%isave, &
645 optimizer%dsave, optimizer%trust_radius, spgr=spgr, iwunit=dataunit)
646 IF (keep_space_group) THEN
647 CALL spgr_apply_rotations_coord(spgr, optimizer%x)
648 CALL spgr_apply_rotations_force(spgr, optimizer%gradient)
649 END IF
650 END IF
651 CALL cp_print_key_finished_output(dataunit, logger, geo_section, &
652 "PRINT%PROGRAM_RUN_INFO")
653 CALL optimizer%para_env%bcast(optimizer%x, optimizer%master)
654 CASE (2)
655 !op=2 begin new iter
656 CALL optimizer%para_env%bcast(optimizer%x, optimizer%master)
657 t_old = m_walltime()
658 CASE (3)
659 !op=3 ended iter
660 wildcard = "LBFGS"
661 dataunit = cp_print_key_unit_nr(logger, geo_section, &
662 "PRINT%PROGRAM_RUN_INFO", extension=".geoLog")
663 IF (is_master) its = optimizer%isave(30)
664 CALL optimizer%para_env%bcast(its, optimizer%master)
665
666 ! Some IO and Convergence check
667 t_now = m_walltime()
668 t_diff = t_now - t_old
669 t_old = t_now
670 CALL gopt_f_io(optimizer%obj_funct, force_env, force_env%root_section, &
671 its, optimizer%f, dataunit, optimizer%eold, optimizer%emin, wildcard, gopt_param, &
672 SIZE(optimizer%x), optimizer%x - xold, optimizer%gradient, conv, used_time=t_diff)
673 CALL optimizer%para_env%bcast(conv, optimizer%master)
674 CALL cp_print_key_finished_output(dataunit, logger, geo_section, &
675 "PRINT%PROGRAM_RUN_INFO")
676 optimizer%eold = optimizer%f
677 optimizer%emin = min(optimizer%emin, optimizer%eold)
678 xold = optimizer%x
679 IF (PRESENT(converged)) converged = conv
680 EXIT
681 CASE (4)
682 !op=4 (convergence - normal exit)
683 ! Specific L-BFGS convergence criteria.. overrides the convergence criteria on
684 ! stepsize and gradients
685 dataunit = cp_print_key_unit_nr(logger, geo_section, &
686 "PRINT%PROGRAM_RUN_INFO", extension=".geoLog")
687 IF (dataunit > 0) THEN
688 WRITE (dataunit, '(T2,A)') ""
689 WRITE (dataunit, '(T2,A)') "************************************************"
690 WRITE (dataunit, '(T2,A)') "* Specific L-BFGS convergence criteria *"
691 WRITE (dataunit, '(T2,A)') "* WANTED_PROJ_GRADIENT and WANTED_REL_F_ERROR *"
692 WRITE (dataunit, '(T2,A)') "* satisfied .... run CONVERGED! *"
693 WRITE (dataunit, '(T2,A)') "* * * * *"
694 WRITE (dataunit, '(T2,A)') "* General convergence criteria on stepsize and *"
695 WRITE (dataunit, '(T2,A)') "* gradients may or may not have been satisfied *"
696 WRITE (dataunit, '(T2,A)') "* yet; if unsatisfactory, try tightening the *"
697 WRITE (dataunit, '(T2,A)') "* L-BFGS convergence criteria and restart run. *"
698 WRITE (dataunit, '(T2,A)') "************************************************"
699 WRITE (dataunit, '(T2,A)') ""
700 END IF
701 CALL cp_print_key_finished_output(dataunit, logger, geo_section, &
702 "PRINT%PROGRAM_RUN_INFO")
703 IF (PRESENT(converged)) converged = .true.
704 EXIT
705 CASE (5)
706 ! op=5 abnormal exit ()
707 CALL optimizer%para_env%bcast(optimizer%task, optimizer%master)
708 CASE (6)
709 ! deallocated
710 cpabort("step on a deallocated opt structure ")
711 CASE default
712 CALL cp_abort(__location__, &
713 "unknown status "//cp_to_string(optimizer%status))
714 optimizer%status = 5
715 EXIT
716 END SELECT
717 IF (optimizer%status == 1 .AND. justentred) THEN
718 optimizer%eold = optimizer%f
719 optimizer%emin = optimizer%eold
720 END IF
721 justentred = .false.
722 END DO
723
724 CALL optimizer%para_env%bcast(optimizer%x, optimizer%master)
725 CALL cp_opt_gopt_bcast_res(optimizer, &
726 n_iter=optimizer%n_iter, &
727 f=optimizer%f, last_f=optimizer%last_f, &
728 projected_gradient=optimizer%projected_gradient)
729
730 DEALLOCATE (xold)
731 IF (PRESENT(f)) f = optimizer%f
732 IF (PRESENT(last_f)) last_f = optimizer%last_f
733 IF (PRESENT(projected_gradient)) &
734 projected_gradient = optimizer%projected_gradient
735 IF (PRESENT(n_iter)) n_iter = optimizer%n_iter
736 CALL timestop(handle)
737
738 END SUBROUTINE cp_opt_gopt_step
739
740! **************************************************************************************************
741!> \brief returns the results (and broadcasts them)
742!> \param optimizer the optimizer object the info is taken from
743!> \param n_iter the number of iterations
744!> \param f the actual value of the objective function (f)
745!> \param last_f the last value of f
746!> \param projected_gradient the infinity norm of the projected gradient
747!> \par History
748!> none
749!> \author Fawzi Mohamed
750!> @version 2.2002
751!> \note
752!> private routine
753! **************************************************************************************************
754 SUBROUTINE cp_opt_gopt_bcast_res(optimizer, n_iter, f, last_f, &
755 projected_gradient)
756 TYPE(cp_lbfgs_opt_gopt_type), INTENT(IN) :: optimizer
757 INTEGER, INTENT(out), OPTIONAL :: n_iter
758 REAL(kind=dp), INTENT(inout), OPTIONAL :: f, last_f, projected_gradient
759
760 REAL(kind=dp), DIMENSION(4) :: results
761
762 IF (optimizer%master == optimizer%para_env%mepos) THEN
763 results = [real(optimizer%isave(30), kind=dp), &
764 optimizer%f, optimizer%dsave(2), optimizer%dsave(13)]
765 END IF
766 CALL optimizer%para_env%bcast(results, optimizer%master)
767 IF (PRESENT(n_iter)) n_iter = nint(results(1))
768 IF (PRESENT(f)) f = results(2)
769 IF (PRESENT(last_f)) last_f = results(3)
770 IF (PRESENT(projected_gradient)) &
771 projected_gradient = results(4)
772
773 END SUBROUTINE cp_opt_gopt_bcast_res
774
775! **************************************************************************************************
776!> \brief goes to the next optimal point (after an optimizer iteration)
777!> returns true if converged
778!> \param optimizer the optimizer that goes to the next point
779!> \param n_iter ...
780!> \param f ...
781!> \param last_f ...
782!> \param projected_gradient ...
783!> \param converged ...
784!> \param geo_section ...
785!> \param force_env ...
786!> \param gopt_param ...
787!> \param spgr ...
788!> \return ...
789!> \par History
790!> 01.2020 modified [pcazade]
791!> \author Fawzi Mohamed
792!> @version 2.2002
793!> \note
794!> if you deactivate convergence control it returns never false
795! **************************************************************************************************
796 FUNCTION cp_opt_gopt_next(optimizer, n_iter, f, last_f, &
797 projected_gradient, converged, geo_section, force_env, &
798 gopt_param, spgr) RESULT(res)
799 TYPE(cp_lbfgs_opt_gopt_type), INTENT(INOUT) :: optimizer
800 INTEGER, INTENT(out), OPTIONAL :: n_iter
801 REAL(kind=dp), INTENT(out), OPTIONAL :: f, last_f, projected_gradient
802 LOGICAL, INTENT(out) :: converged
803 TYPE(section_vals_type), POINTER :: geo_section
804 TYPE(force_env_type), POINTER :: force_env
805 TYPE(gopt_param_type), POINTER :: gopt_param
806 TYPE(spgr_type), OPTIONAL, POINTER :: spgr
807 LOGICAL :: res
808
809 ! passes spgr structure if present
810 CALL cp_opt_gopt_step(optimizer, n_iter=n_iter, f=f, &
811 last_f=last_f, projected_gradient=projected_gradient, &
812 converged=converged, geo_section=geo_section, &
813 force_env=force_env, gopt_param=gopt_param, spgr=spgr)
814 res = (optimizer%status < 40) .AND. .NOT. converged
815
816 END FUNCTION cp_opt_gopt_next
817
818! **************************************************************************************************
819!> \brief stops the optimization
820!> \param optimizer ...
821!> \par History
822!> none
823!> \author Fawzi Mohamed
824!> @version 2.2002
825! **************************************************************************************************
826 SUBROUTINE cp_opt_gopt_stop(optimizer)
827 TYPE(cp_lbfgs_opt_gopt_type), INTENT(INOUT) :: optimizer
828
829 optimizer%task = 'STOPPED on user request'
830 optimizer%status = 4 ! normal exit
831 IF (optimizer%master == optimizer%para_env%mepos) THEN
832 CALL setulb(SIZE(optimizer%x), optimizer%m, optimizer%x, &
833 optimizer%lower_bound, optimizer%upper_bound, &
834 optimizer%kind_of_bound, optimizer%f, optimizer%gradient, &
835 optimizer%wanted_relative_f_delta, &
836 optimizer%wanted_projected_gradient, optimizer%work_array, &
837 optimizer%i_work_array, optimizer%task, optimizer%print_every, &
838 optimizer%csave, optimizer%lsave, optimizer%isave, &
839 optimizer%dsave, optimizer%trust_radius)
840 END IF
841
842 END SUBROUTINE cp_opt_gopt_stop
843
subroutine cp_eval_at(gopt_env, x, f, gradient, master, final_evaluation, para_env)
evaluete the potential energy and its gradients using an array with same dimension as the particle_se...
routines that optimize a functional using the limited memory bfgs quasi-newton method....
subroutine, public cp_opt_gopt_create(optimizer, para_env, obj_funct, x0, m, print_every, wanted_relative_f_delta, wanted_projected_gradient, lower_bound, upper_bound, kind_of_bound, master, max_f_per_iter, trust_radius)
initializes the optimizer
logical function, public cp_opt_gopt_next(optimizer, n_iter, f, last_f, projected_gradient, converged, geo_section, force_env, gopt_param, spgr)
goes to the next optimal point (after an optimizer iteration) returns true if converged
subroutine, public cp_opt_gopt_stop(optimizer)
stops the optimization
subroutine, public cp_opt_gopt_release(optimizer)
releases the optimizer (see doc/ReferenceCounting.html)
LBFGS-B routine (version 3.0, April 25, 2011)
Definition cp_lbfgs.F:19
subroutine, public setulb(n, m, x, lower_bound, upper_bound, nbd, f, g, factr, pgtol, wa, iwa, task, iprint, csave, lsave, isave, dsave, trust_radius, spgr, iwunit)
This subroutine partitions the working arrays wa and iwa, and then uses the limited memory BFGS metho...
Definition cp_lbfgs.F:188
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,...
types that represent a subsys, i.e. a part of the system
Interface for the force calculations.
recursive subroutine, public force_env_get(force_env, in_use, fist_env, qs_env, meta_env, fp_env, subsys, para_env, potential_energy, additional_potential, kinetic_energy, harmonic_shell, kinetic_shell, cell, sub_force_env, qmmm_env, qmmmx_env, eip_env, pwdft_env, globenv, input, force_env_section, method_name_id, root_section, mixed_env, nnp_env, embed_env, ipi_env)
returns various attributes about the force environment
contains a functional that calculates the energy and its derivatives for the geometry optimizer
subroutine, public gopt_f_io(gopt_env, force_env, root_section, its, opt_energy, output_unit, eold, emin, wildcard, gopt_param, ndf, dx, xi, conv, pred, rat, step, rad, used_time)
Handles the Output during an optimization run.
contains a functional that calculates the energy and its derivatives for the geometry optimizer
subroutine, public gopt_f_retain(gopt_env)
...
recursive subroutine, public gopt_f_release(gopt_env)
...
contains typo and related routines to handle parameters controlling the GEO_OPT module
objects that represent the structure of input sections and the data contained in an input section
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Machine interface based on Fortran 2003 and POSIX.
Definition machine.F:17
real(kind=dp) function, public m_walltime()
returns time from a real-time clock, protected against rolling early/easily
Definition machine.F:141
Interface to the message passing library MPI.
subroutine, public mp_para_env_release(para_env)
releases the para object (to be called when you don't want anymore the shared copy of this object)
Space Group Symmetry Type Module (version 1.0, Ferbruary 12, 2021)
Space Group Symmetry Module (version 1.0, January 16, 2020)
subroutine, public spgr_apply_rotations_coord(spgr, coord)
routine applies the rotation matrices to the coordinates.
subroutine, public spgr_apply_rotations_force(spgr, force)
routine applies the rotation matrices to the forces.
info for the optimizer (see the description of this module)
type of a logger, at the moment it contains just a print level starting at which level it should be l...
represents a system: atoms, molecules, their pos,vel,...
wrapper to abstract the force evaluation of the various methods
calculates the potential energy of a system, and its derivatives
stores all the informations relevant to an mpi environment