(git:ed6f26b)
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-2025 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%wanted_relative_f_delta = wanted_relative_f_delta
263 optimizer%wanted_projected_gradient = wanted_projected_gradient
264 optimizer%kind_of_bound = 0
265 IF (PRESENT(kind_of_bound)) optimizer%kind_of_bound = kind_of_bound
266 IF (PRESENT(lower_bound)) optimizer%lower_bound = lower_bound
267 IF (PRESENT(upper_bound)) optimizer%upper_bound = upper_bound
268 IF (PRESENT(trust_radius)) optimizer%trust_radius = trust_radius
269
270 CALL setulb(SIZE(optimizer%x), optimizer%m, optimizer%x, &
271 optimizer%lower_bound, optimizer%upper_bound, &
272 optimizer%kind_of_bound, optimizer%f, optimizer%gradient, &
273 optimizer%wanted_relative_f_delta, &
274 optimizer%wanted_projected_gradient, optimizer%work_array, &
275 optimizer%i_work_array, optimizer%task, optimizer%print_every, &
276 optimizer%csave, optimizer%lsave, optimizer%isave, &
277 optimizer%dsave, optimizer%trust_radius)
278 ELSE
279 NULLIFY ( &
280 optimizer%kind_of_bound, optimizer%i_work_array, optimizer%isave, &
281 optimizer%lower_bound, optimizer%upper_bound, optimizer%gradient, &
282 optimizer%dsave, optimizer%work_array)
283 ALLOCATE (optimizer%x(n))
284 optimizer%x(:) = 0.0_dp
285 ALLOCATE (optimizer%gradient(n))
286 optimizer%gradient(:) = 0.0_dp
287 END IF
288 CALL optimizer%para_env%bcast(optimizer%x, optimizer%master)
289 optimizer%status = 0
290
291 CALL timestop(handle)
292
293 END SUBROUTINE cp_opt_gopt_create
294
295! **************************************************************************************************
296!> \brief releases the optimizer (see doc/ReferenceCounting.html)
297!> \param optimizer the object that should be released
298!> \par History
299!> 02.2002 created [fawzi]
300!> 09.2003 dealloc_ref->release [fawzi]
301!> \author Fawzi Mohamed
302! **************************************************************************************************
303 SUBROUTINE cp_opt_gopt_release(optimizer)
304 TYPE(cp_lbfgs_opt_gopt_type), INTENT(INOUT) :: optimizer
305
306 CHARACTER(len=*), PARAMETER :: routinen = 'cp_opt_gopt_release'
307
308 INTEGER :: handle
309
310 CALL timeset(routinen, handle)
311
312 IF (ASSOCIATED(optimizer%kind_of_bound)) THEN
313 DEALLOCATE (optimizer%kind_of_bound)
314 END IF
315 IF (ASSOCIATED(optimizer%i_work_array)) THEN
316 DEALLOCATE (optimizer%i_work_array)
317 END IF
318 IF (ASSOCIATED(optimizer%isave)) THEN
319 DEALLOCATE (optimizer%isave)
320 END IF
321 IF (ASSOCIATED(optimizer%x)) THEN
322 DEALLOCATE (optimizer%x)
323 END IF
324 IF (ASSOCIATED(optimizer%lower_bound)) THEN
325 DEALLOCATE (optimizer%lower_bound)
326 END IF
327 IF (ASSOCIATED(optimizer%upper_bound)) THEN
328 DEALLOCATE (optimizer%upper_bound)
329 END IF
330 IF (ASSOCIATED(optimizer%gradient)) THEN
331 DEALLOCATE (optimizer%gradient)
332 END IF
333 IF (ASSOCIATED(optimizer%dsave)) THEN
334 DEALLOCATE (optimizer%dsave)
335 END IF
336 IF (ASSOCIATED(optimizer%work_array)) THEN
337 DEALLOCATE (optimizer%work_array)
338 END IF
339 CALL mp_para_env_release(optimizer%para_env)
340 CALL gopt_f_release(optimizer%obj_funct)
341
342 CALL timestop(handle)
343 END SUBROUTINE cp_opt_gopt_release
344
345! **************************************************************************************************
346!> \brief takes different valuse from the optimizer
347!> \param optimizer ...
348!> \param para_env ...
349!> \param obj_funct ...
350!> \param m ...
351!> \param print_every ...
352!> \param wanted_relative_f_delta ...
353!> \param wanted_projected_gradient ...
354!> \param x ...
355!> \param lower_bound ...
356!> \param upper_bound ...
357!> \param kind_of_bound ...
358!> \param master ...
359!> \param actual_projected_gradient ...
360!> \param n_var ...
361!> \param n_iter ...
362!> \param status ...
363!> \param max_f_per_iter ...
364!> \param at_end ...
365!> \param is_master ...
366!> \param last_f ...
367!> \param f ...
368!> \par History
369!> none
370!> \author Fawzi Mohamed
371!> @version 2.2002
372! **************************************************************************************************
373 SUBROUTINE cp_opt_gopt_get(optimizer, para_env, &
374 obj_funct, m, print_every, &
375 wanted_relative_f_delta, wanted_projected_gradient, &
376 x, lower_bound, upper_bound, kind_of_bound, master, &
377 actual_projected_gradient, &
378 n_var, n_iter, status, max_f_per_iter, at_end, &
379 is_master, last_f, f)
380 TYPE(cp_lbfgs_opt_gopt_type), INTENT(IN) :: optimizer
381 TYPE(mp_para_env_type), OPTIONAL, POINTER :: para_env
382 TYPE(gopt_f_type), OPTIONAL, POINTER :: obj_funct
383 INTEGER, INTENT(out), OPTIONAL :: m, print_every
384 REAL(kind=dp), INTENT(out), OPTIONAL :: wanted_relative_f_delta, &
385 wanted_projected_gradient
386 REAL(kind=dp), DIMENSION(:), OPTIONAL, POINTER :: x, lower_bound, upper_bound
387 INTEGER, DIMENSION(:), OPTIONAL, POINTER :: kind_of_bound
388 INTEGER, INTENT(out), OPTIONAL :: master
389 REAL(kind=dp), INTENT(out), OPTIONAL :: actual_projected_gradient
390 INTEGER, INTENT(out), OPTIONAL :: n_var, n_iter, status, max_f_per_iter
391 LOGICAL, INTENT(out), OPTIONAL :: at_end, is_master
392 REAL(kind=dp), INTENT(out), OPTIONAL :: last_f, f
393
394 IF (PRESENT(is_master)) is_master = optimizer%master == optimizer%para_env%mepos
395 IF (PRESENT(master)) master = optimizer%master
396 IF (PRESENT(status)) status = optimizer%status
397 IF (PRESENT(para_env)) para_env => optimizer%para_env
398 IF (PRESENT(obj_funct)) obj_funct = optimizer%obj_funct
399 IF (PRESENT(m)) m = optimizer%m
400 IF (PRESENT(max_f_per_iter)) max_f_per_iter = optimizer%max_f_per_iter
401 IF (PRESENT(wanted_projected_gradient)) &
402 wanted_projected_gradient = optimizer%wanted_projected_gradient
403 IF (PRESENT(wanted_relative_f_delta)) &
404 wanted_relative_f_delta = optimizer%wanted_relative_f_delta
405 IF (PRESENT(print_every)) print_every = optimizer%print_every
406 IF (PRESENT(x)) x => optimizer%x
407 IF (PRESENT(n_var)) n_var = SIZE(x)
408 IF (PRESENT(lower_bound)) lower_bound => optimizer%lower_bound
409 IF (PRESENT(upper_bound)) upper_bound => optimizer%upper_bound
410 IF (PRESENT(kind_of_bound)) kind_of_bound => optimizer%kind_of_bound
411 IF (PRESENT(n_iter)) n_iter = optimizer%n_iter
412 IF (PRESENT(last_f)) last_f = optimizer%last_f
413 IF (PRESENT(f)) f = optimizer%f
414 IF (PRESENT(at_end)) at_end = optimizer%status > 3
415 IF (PRESENT(actual_projected_gradient)) &
416 actual_projected_gradient = optimizer%projected_gradient
417 IF (optimizer%master == optimizer%para_env%mepos) THEN
418 IF (optimizer%isave(30) > 1 .AND. (optimizer%task(1:5) == "NEW_X" .OR. &
419 optimizer%task(1:4) == "STOP" .AND. optimizer%task(7:9) == "CPU")) THEN
420 ! nr iterations >1 .and. dsave contains the wanted data
421 IF (PRESENT(last_f)) last_f = optimizer%dsave(2)
422 IF (PRESENT(actual_projected_gradient)) &
423 actual_projected_gradient = optimizer%dsave(13)
424 ELSE
425 cpassert(.NOT. PRESENT(last_f))
426 cpassert(.NOT. PRESENT(actual_projected_gradient))
427 END IF
428 ELSE IF (PRESENT(lower_bound) .OR. PRESENT(upper_bound) .OR. PRESENT(kind_of_bound)) THEN
429 cpwarn("asked undefined types")
430 END IF
431
432 END SUBROUTINE cp_opt_gopt_get
433
434! **************************************************************************************************
435!> \brief does one optimization step
436!> \param optimizer ...
437!> \param n_iter ...
438!> \param f ...
439!> \param last_f ...
440!> \param projected_gradient ...
441!> \param converged ...
442!> \param geo_section ...
443!> \param force_env ...
444!> \param gopt_param ...
445!> \param spgr ...
446!> \par History
447!> 01.2020 modified [pcazade]
448!> \author Fawzi Mohamed
449!> @version 2.2002
450!> \note
451!> use directly mainlb in place of setulb ??
452! **************************************************************************************************
453 SUBROUTINE cp_opt_gopt_step(optimizer, n_iter, f, last_f, &
454 projected_gradient, converged, geo_section, force_env, &
455 gopt_param, spgr)
456 TYPE(cp_lbfgs_opt_gopt_type), INTENT(INOUT) :: optimizer
457 INTEGER, INTENT(out), OPTIONAL :: n_iter
458 REAL(kind=dp), INTENT(out), OPTIONAL :: f, last_f, projected_gradient
459 LOGICAL, INTENT(out), OPTIONAL :: converged
460 TYPE(section_vals_type), POINTER :: geo_section
461 TYPE(force_env_type), POINTER :: force_env
462 TYPE(gopt_param_type), POINTER :: gopt_param
463 TYPE(spgr_type), OPTIONAL, POINTER :: spgr
464
465 CHARACTER(len=*), PARAMETER :: routinen = 'cp_opt_gopt_step'
466
467 CHARACTER(LEN=5) :: wildcard
468 INTEGER :: dataunit, handle, its
469 LOGICAL :: conv, is_master, justentred, &
470 keep_space_group
471 REAL(kind=dp) :: t_diff, t_now, t_old
472 REAL(kind=dp), DIMENSION(:), POINTER :: xold
473 TYPE(cp_logger_type), POINTER :: logger
474 TYPE(cp_subsys_type), POINTER :: subsys
475
476 NULLIFY (logger, xold)
477 logger => cp_get_default_logger()
478 CALL timeset(routinen, handle)
479 justentred = .true.
480 is_master = optimizer%master == optimizer%para_env%mepos
481 IF (PRESENT(converged)) converged = optimizer%status == 4
482 ALLOCATE (xold(SIZE(optimizer%x)))
483
484 ! collecting subsys
485 CALL force_env_get(force_env, subsys=subsys)
486
487 keep_space_group = .false.
488 IF (PRESENT(spgr)) THEN
489 IF (ASSOCIATED(spgr)) keep_space_group = spgr%keep_space_group
490 END IF
491
492 ! applies rotation matrices to coordinates
493 IF (keep_space_group) THEN
494 CALL spgr_apply_rotations_coord(spgr, optimizer%x)
495 END IF
496
497 xold = optimizer%x
498 t_old = m_walltime()
499
500 IF (optimizer%status >= 4) THEN
501 cpwarn("status>=4, trying to restart")
502 optimizer%status = 0
503 IF (is_master) THEN
504 optimizer%task = 'START'
505 CALL setulb(SIZE(optimizer%x), optimizer%m, optimizer%x, &
506 optimizer%lower_bound, optimizer%upper_bound, &
507 optimizer%kind_of_bound, optimizer%f, optimizer%gradient, &
508 optimizer%wanted_relative_f_delta, &
509 optimizer%wanted_projected_gradient, optimizer%work_array, &
510 optimizer%i_work_array, optimizer%task, optimizer%print_every, &
511 optimizer%csave, optimizer%lsave, optimizer%isave, &
512 optimizer%dsave, optimizer%trust_radius, spgr=spgr)
513 END IF
514 END IF
515
516 DO
517 ifmaster: IF (is_master) THEN
518 IF (optimizer%task(1:7) == 'RESTART') THEN
519 ! restart the optimizer
520 optimizer%status = 0
521 optimizer%task = 'START'
522 ! applies rotation matrices to coordinates and forces
523 IF (keep_space_group) THEN
524 CALL spgr_apply_rotations_coord(spgr, optimizer%x)
525 CALL spgr_apply_rotations_force(spgr, optimizer%gradient)
526 END IF
527 CALL setulb(SIZE(optimizer%x), optimizer%m, optimizer%x, &
528 optimizer%lower_bound, optimizer%upper_bound, &
529 optimizer%kind_of_bound, optimizer%f, optimizer%gradient, &
530 optimizer%wanted_relative_f_delta, &
531 optimizer%wanted_projected_gradient, optimizer%work_array, &
532 optimizer%i_work_array, optimizer%task, optimizer%print_every, &
533 optimizer%csave, optimizer%lsave, optimizer%isave, &
534 optimizer%dsave, optimizer%trust_radius, spgr=spgr)
535 IF (keep_space_group) THEN
536 CALL spgr_apply_rotations_coord(spgr, optimizer%x)
537 CALL spgr_apply_rotations_force(spgr, optimizer%gradient)
538 END IF
539 END IF
540 IF (optimizer%task(1:2) == 'FG') THEN
541 IF (optimizer%isave(36) > optimizer%max_f_per_iter) THEN
542 optimizer%task = 'STOP: CPU, hit max f eval in iter'
543 optimizer%status = 5 ! anormal exit
544 CALL setulb(SIZE(optimizer%x), optimizer%m, optimizer%x, &
545 optimizer%lower_bound, optimizer%upper_bound, &
546 optimizer%kind_of_bound, optimizer%f, optimizer%gradient, &
547 optimizer%wanted_relative_f_delta, &
548 optimizer%wanted_projected_gradient, optimizer%work_array, &
549 optimizer%i_work_array, optimizer%task, optimizer%print_every, &
550 optimizer%csave, optimizer%lsave, optimizer%isave, &
551 optimizer%dsave, optimizer%trust_radius, spgr=spgr)
552 ELSE
553 optimizer%status = 1
554 END IF
555 ELSE IF (optimizer%task(1:5) == 'NEW_X') THEN
556 IF (justentred) THEN
557 optimizer%status = 2
558 ! applies rotation matrices to coordinates and forces
559 IF (keep_space_group) THEN
560 CALL spgr_apply_rotations_coord(spgr, optimizer%x)
561 CALL spgr_apply_rotations_force(spgr, optimizer%gradient)
562 END IF
563 CALL setulb(SIZE(optimizer%x), optimizer%m, optimizer%x, &
564 optimizer%lower_bound, optimizer%upper_bound, &
565 optimizer%kind_of_bound, optimizer%f, optimizer%gradient, &
566 optimizer%wanted_relative_f_delta, &
567 optimizer%wanted_projected_gradient, optimizer%work_array, &
568 optimizer%i_work_array, optimizer%task, optimizer%print_every, &
569 optimizer%csave, optimizer%lsave, optimizer%isave, &
570 optimizer%dsave, optimizer%trust_radius, spgr=spgr)
571 IF (keep_space_group) THEN
572 CALL spgr_apply_rotations_coord(spgr, optimizer%x)
573 CALL spgr_apply_rotations_force(spgr, optimizer%gradient)
574 END IF
575 ELSE
576 ! applies rotation matrices to coordinates and forces
577 IF (keep_space_group) THEN
578 CALL spgr_apply_rotations_coord(spgr, optimizer%x)
579 CALL spgr_apply_rotations_force(spgr, optimizer%gradient)
580 END IF
581 optimizer%status = 3
582 END IF
583 ELSE IF (optimizer%task(1:4) == 'CONV') THEN
584 optimizer%status = 4
585 ELSE IF (optimizer%task(1:4) == 'STOP') THEN
586 optimizer%status = 5
587 cpwarn("task became stop in an unknown way")
588 ELSE IF (optimizer%task(1:5) == 'ERROR') THEN
589 optimizer%status = 5
590 ELSE
591 cpwarn("unknown task '"//optimizer%task//"'")
592 END IF
593 END IF ifmaster
594 CALL optimizer%para_env%bcast(optimizer%status, optimizer%master)
595 ! Dump info
596 IF (optimizer%status == 3) THEN
597 its = 0
598 IF (is_master) THEN
599 ! Iteration level is taken into account in the optimizer external loop
600 its = optimizer%isave(30)
601 END IF
602 END IF
603 !
604 SELECT CASE (optimizer%status)
605 CASE (1)
606 !op=1 evaluate f and g
607 CALL cp_eval_at(optimizer%obj_funct, x=optimizer%x, &
608 f=optimizer%f, &
609 gradient=optimizer%gradient, &
610 final_evaluation=.false., &
611 master=optimizer%master, para_env=optimizer%para_env)
612 ! do not use keywords?
613 IF (is_master) THEN
614 ! applies rotation matrices to coordinates and forces
615 IF (keep_space_group) THEN
616 CALL spgr_apply_rotations_coord(spgr, optimizer%x)
617 CALL spgr_apply_rotations_force(spgr, optimizer%gradient)
618 END IF
619 CALL setulb(SIZE(optimizer%x), optimizer%m, optimizer%x, &
620 optimizer%lower_bound, optimizer%upper_bound, &
621 optimizer%kind_of_bound, optimizer%f, optimizer%gradient, &
622 optimizer%wanted_relative_f_delta, &
623 optimizer%wanted_projected_gradient, optimizer%work_array, &
624 optimizer%i_work_array, optimizer%task, optimizer%print_every, &
625 optimizer%csave, optimizer%lsave, optimizer%isave, &
626 optimizer%dsave, optimizer%trust_radius, spgr=spgr)
627 IF (keep_space_group) THEN
628 CALL spgr_apply_rotations_coord(spgr, optimizer%x)
629 CALL spgr_apply_rotations_force(spgr, optimizer%gradient)
630 END IF
631 END IF
632 CALL optimizer%para_env%bcast(optimizer%x, optimizer%master)
633 CASE (2)
634 !op=2 begin new iter
635 CALL optimizer%para_env%bcast(optimizer%x, optimizer%master)
636 t_old = m_walltime()
637 CASE (3)
638 !op=3 ended iter
639 wildcard = "LBFGS"
640 dataunit = cp_print_key_unit_nr(logger, geo_section, &
641 "PRINT%PROGRAM_RUN_INFO", extension=".geoLog")
642 IF (is_master) its = optimizer%isave(30)
643 CALL optimizer%para_env%bcast(its, optimizer%master)
644
645 ! Some IO and Convergence check
646 t_now = m_walltime()
647 t_diff = t_now - t_old
648 t_old = t_now
649 CALL gopt_f_io(optimizer%obj_funct, force_env, force_env%root_section, &
650 its, optimizer%f, dataunit, optimizer%eold, optimizer%emin, wildcard, gopt_param, &
651 SIZE(optimizer%x), optimizer%x - xold, optimizer%gradient, conv, used_time=t_diff)
652 CALL optimizer%para_env%bcast(conv, optimizer%master)
653 CALL cp_print_key_finished_output(dataunit, logger, geo_section, &
654 "PRINT%PROGRAM_RUN_INFO")
655 optimizer%eold = optimizer%f
656 optimizer%emin = min(optimizer%emin, optimizer%eold)
657 xold = optimizer%x
658 IF (PRESENT(converged)) converged = conv
659 EXIT
660 CASE (4)
661 !op=4 (convergence - normal exit)
662 ! Specific L-BFGS convergence criteria.. overrides the convergence criteria on
663 ! stepsize and gradients
664 dataunit = cp_print_key_unit_nr(logger, geo_section, &
665 "PRINT%PROGRAM_RUN_INFO", extension=".geoLog")
666 IF (dataunit > 0) THEN
667 WRITE (dataunit, '(T2,A)') ""
668 WRITE (dataunit, '(T2,A)') "***********************************************"
669 WRITE (dataunit, '(T2,A)') "* Specific L-BFGS convergence criteria "
670 WRITE (dataunit, '(T2,A)') "* WANTED_PROJ_GRADIENT and WANTED_REL_F_ERROR "
671 WRITE (dataunit, '(T2,A)') "* satisfied .... run CONVERGED! "
672 WRITE (dataunit, '(T2,A)') "***********************************************"
673 WRITE (dataunit, '(T2,A)') ""
674 END IF
675 CALL cp_print_key_finished_output(dataunit, logger, geo_section, &
676 "PRINT%PROGRAM_RUN_INFO")
677 IF (PRESENT(converged)) converged = .true.
678 EXIT
679 CASE (5)
680 ! op=5 abnormal exit ()
681 CALL optimizer%para_env%bcast(optimizer%task, optimizer%master)
682 CASE (6)
683 ! deallocated
684 cpabort("step on a deallocated opt structure ")
685 CASE default
686 CALL cp_abort(__location__, &
687 "unknown status "//cp_to_string(optimizer%status))
688 optimizer%status = 5
689 EXIT
690 END SELECT
691 IF (optimizer%status == 1 .AND. justentred) THEN
692 optimizer%eold = optimizer%f
693 optimizer%emin = optimizer%eold
694 END IF
695 justentred = .false.
696 END DO
697
698 CALL optimizer%para_env%bcast(optimizer%x, optimizer%master)
699 CALL cp_opt_gopt_bcast_res(optimizer, &
700 n_iter=optimizer%n_iter, &
701 f=optimizer%f, last_f=optimizer%last_f, &
702 projected_gradient=optimizer%projected_gradient)
703
704 DEALLOCATE (xold)
705 IF (PRESENT(f)) f = optimizer%f
706 IF (PRESENT(last_f)) last_f = optimizer%last_f
707 IF (PRESENT(projected_gradient)) &
708 projected_gradient = optimizer%projected_gradient
709 IF (PRESENT(n_iter)) n_iter = optimizer%n_iter
710 CALL timestop(handle)
711
712 END SUBROUTINE cp_opt_gopt_step
713
714! **************************************************************************************************
715!> \brief returns the results (and broadcasts them)
716!> \param optimizer the optimizer object the info is taken from
717!> \param n_iter the number of iterations
718!> \param f the actual value of the objective function (f)
719!> \param last_f the last value of f
720!> \param projected_gradient the infinity norm of the projected gradient
721!> \par History
722!> none
723!> \author Fawzi Mohamed
724!> @version 2.2002
725!> \note
726!> private routine
727! **************************************************************************************************
728 SUBROUTINE cp_opt_gopt_bcast_res(optimizer, n_iter, f, last_f, &
729 projected_gradient)
730 TYPE(cp_lbfgs_opt_gopt_type), INTENT(IN) :: optimizer
731 INTEGER, INTENT(out), OPTIONAL :: n_iter
732 REAL(kind=dp), INTENT(inout), OPTIONAL :: f, last_f, projected_gradient
733
734 REAL(kind=dp), DIMENSION(4) :: results
735
736 IF (optimizer%master == optimizer%para_env%mepos) THEN
737 results = (/real(optimizer%isave(30), kind=dp), &
738 optimizer%f, optimizer%dsave(2), optimizer%dsave(13)/)
739 END IF
740 CALL optimizer%para_env%bcast(results, optimizer%master)
741 IF (PRESENT(n_iter)) n_iter = nint(results(1))
742 IF (PRESENT(f)) f = results(2)
743 IF (PRESENT(last_f)) last_f = results(3)
744 IF (PRESENT(projected_gradient)) &
745 projected_gradient = results(4)
746
747 END SUBROUTINE cp_opt_gopt_bcast_res
748
749! **************************************************************************************************
750!> \brief goes to the next optimal point (after an optimizer iteration)
751!> returns true if converged
752!> \param optimizer the optimizer that goes to the next point
753!> \param n_iter ...
754!> \param f ...
755!> \param last_f ...
756!> \param projected_gradient ...
757!> \param converged ...
758!> \param geo_section ...
759!> \param force_env ...
760!> \param gopt_param ...
761!> \param spgr ...
762!> \return ...
763!> \par History
764!> 01.2020 modified [pcazade]
765!> \author Fawzi Mohamed
766!> @version 2.2002
767!> \note
768!> if you deactivate convergence control it returns never false
769! **************************************************************************************************
770 FUNCTION cp_opt_gopt_next(optimizer, n_iter, f, last_f, &
771 projected_gradient, converged, geo_section, force_env, &
772 gopt_param, spgr) RESULT(res)
773 TYPE(cp_lbfgs_opt_gopt_type), INTENT(INOUT) :: optimizer
774 INTEGER, INTENT(out), OPTIONAL :: n_iter
775 REAL(kind=dp), INTENT(out), OPTIONAL :: f, last_f, projected_gradient
776 LOGICAL, INTENT(out) :: converged
777 TYPE(section_vals_type), POINTER :: geo_section
778 TYPE(force_env_type), POINTER :: force_env
779 TYPE(gopt_param_type), POINTER :: gopt_param
780 TYPE(spgr_type), OPTIONAL, POINTER :: spgr
781 LOGICAL :: res
782
783 ! passes spgr structure if present
784 CALL cp_opt_gopt_step(optimizer, n_iter=n_iter, f=f, &
785 last_f=last_f, projected_gradient=projected_gradient, &
786 converged=converged, geo_section=geo_section, &
787 force_env=force_env, gopt_param=gopt_param, spgr=spgr)
788 res = (optimizer%status < 40) .AND. .NOT. converged
789
790 END FUNCTION cp_opt_gopt_next
791
792! **************************************************************************************************
793!> \brief stops the optimization
794!> \param optimizer ...
795!> \par History
796!> none
797!> \author Fawzi Mohamed
798!> @version 2.2002
799! **************************************************************************************************
800 SUBROUTINE cp_opt_gopt_stop(optimizer)
801 TYPE(cp_lbfgs_opt_gopt_type), INTENT(INOUT) :: optimizer
802
803 optimizer%task = 'STOPPED on user request'
804 optimizer%status = 4 ! normal exit
805 IF (optimizer%master == optimizer%para_env%mepos) THEN
806 CALL setulb(SIZE(optimizer%x), optimizer%m, optimizer%x, &
807 optimizer%lower_bound, optimizer%upper_bound, &
808 optimizer%kind_of_bound, optimizer%f, optimizer%gradient, &
809 optimizer%wanted_relative_f_delta, &
810 optimizer%wanted_projected_gradient, optimizer%work_array, &
811 optimizer%i_work_array, optimizer%task, optimizer%print_every, &
812 optimizer%csave, optimizer%lsave, optimizer%isave, &
813 optimizer%dsave, optimizer%trust_radius)
814 END IF
815
816 END SUBROUTINE cp_opt_gopt_stop
817
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)
This subroutine partitions the working arrays wa and iwa, and then uses the limited memory BFGS metho...
Definition cp_lbfgs.F:185
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:147
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