LCOV - code coverage report
Current view: top level - src/motion - cp_lbfgs_optimizer_gopt.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:9ccafda) Lines: 81.2 % 250 203
Test Date: 2026-10-15 00:55:44 Functions: 75.0 % 8 6

            Line data    Source code
       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              : ! **************************************************************************************************
      22              : MODULE cp_lbfgs_optimizer_gopt
      23              :    USE cp_lbfgs,                        ONLY: setulb
      24              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      25              :                                               cp_logger_type,&
      26              :                                               cp_to_string
      27              :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      28              :                                               cp_print_key_unit_nr
      29              :    USE cp_subsys_types,                 ONLY: cp_subsys_type
      30              :    USE force_env_types,                 ONLY: force_env_get,&
      31              :                                               force_env_type
      32              :    USE gopt_f_methods,                  ONLY: cp_eval_at,&
      33              :                                               gopt_f_io
      34              :    USE gopt_f_types,                    ONLY: gopt_f_release,&
      35              :                                               gopt_f_retain,&
      36              :                                               gopt_f_type
      37              :    USE gopt_param_types,                ONLY: gopt_param_type
      38              :    USE input_section_types,             ONLY: section_vals_type
      39              :    USE kinds,                           ONLY: dp
      40              :    USE machine,                         ONLY: m_walltime
      41              :    USE message_passing,                 ONLY: mp_para_env_release,&
      42              :                                               mp_para_env_type
      43              :    USE space_groups,                    ONLY: spgr_apply_rotations_coord,&
      44              :                                               spgr_apply_rotations_force
      45              :    USE space_groups_types,              ONLY: spgr_type
      46              : #include "../base/base_uses.f90"
      47              : 
      48              :    IMPLICIT NONE
      49              :    PRIVATE
      50              : 
      51              :    LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .TRUE.
      52              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cp_lbfgs_optimizer_gopt'
      53              : 
      54              :    ! types
      55              :    PUBLIC :: cp_lbfgs_opt_gopt_type
      56              : 
      57              :    ! core methods
      58              : 
      59              :    ! special methos
      60              : 
      61              :    ! underlying functions
      62              :    PUBLIC :: cp_opt_gopt_create, cp_opt_gopt_release, &
      63              :              cp_opt_gopt_next, &
      64              :              cp_opt_gopt_stop
      65              : 
      66              : ! **************************************************************************************************
      67              : !> \brief info for the optimizer (see the description of this module)
      68              : !> \param task the actual task of the optimizer (in the master it is up to
      69              : !>        date, in case of error also the minions one get updated.
      70              : !> \param csave internal character string used by the lbfgs optimizer,
      71              : !>        meaningful only in the master
      72              : !> \param lsave logical array used by the lbfgs optimizer, updated only
      73              : !>        in the master
      74              : !>        On exit with task = 'NEW_X', the following information is
      75              : !>        available:
      76              : !>           lsave(1) = .true.  the initial x did not satisfy the bounds;
      77              : !>           lsave(2) = .true.  the problem contains bounds;
      78              : !>           lsave(3) = .true.  each variable has upper and lower bounds.
      79              : !> \param ref_count reference count (see doc/ReferenceCounting.html)
      80              : !> \param m the dimension of the subspace used to approximate the second
      81              : !>        derivative
      82              : !> \param print_every every how many iterations output should be written.
      83              : !>        if 0 only at end, if print_every<0 never
      84              : !> \param master the pid of the master processor
      85              : !> \param max_f_per_iter the maximum number of function evaluations per
      86              : !>        iteration
      87              : !> \param status 0: just initialized, 1: f g calculation,
      88              : !>        2: begin new iteration, 3: ended iteration,
      89              : !>        4: normal (converged) exit, 5: abnormal (error) exit,
      90              : !>        6: daellocated
      91              : !> \param n_iter the actual iteration number
      92              : !> \param kind_of_bound an array with 0 (no bound), 1 (lower bound),
      93              : !>        2 (both bounds), 3 (upper bound), to describe the bounds
      94              : !>        of every variable
      95              : !> \param i_work_array an integer workarray of dimension 3*n, present only
      96              : !>        in the master
      97              : !> \param isave is an INTEGER working array of dimension 44.
      98              : !>        On exit with task = 'NEW_X', it contains information that
      99              : !>        the user may want to access:
     100              : !> \param isave (30) = the current iteration number;
     101              : !> \param isave (34) = the total number of function and gradient
     102              : !>           evaluations;
     103              : !> \param isave (36) = the number of function value or gradient
     104              : !>           evaluations in the current iteration;
     105              : !> \param isave (38) = the number of free variables in the current
     106              : !>           iteration;
     107              : !> \param isave (39) = the number of active constraints at the current
     108              : !>           iteration;
     109              : !> \param f the actual best value of the object function
     110              : !> \param wanted_relative_f_delta the wanted relative error on f
     111              : !>        (to be multiplied by epsilon), 0.0 -> no check
     112              : !> \param wanted_projected_gradient the wanted error on the projected
     113              : !>        gradient (hessian times the gradient), 0.0 -> no check
     114              : !> \param last_f the value of f in the last iteration
     115              : !> \param projected_gradient the value of the sup norm of the projected
     116              : !>        gradient
     117              : !> \param x the actual evaluation point (best one if converged or stopped)
     118              : !> \param lower_bound the lower bounds
     119              : !> \param upper_bound the upper bounds
     120              : !> \param gradient the actual gradient
     121              : !> \param dsave info date for lbfgs (master only)
     122              : !> \param work_array a work array for lbfgs (master only)
     123              : !> \param para_env the parallel environment for this optimizer
     124              : !> \param obj_funct the objective function to be optimized
     125              : !> \par History
     126              : !>      none
     127              : !> \author Fawzi Mohamed
     128              : !>      @version 2.2002
     129              : ! **************************************************************************************************
     130              :    TYPE cp_lbfgs_opt_gopt_type
     131              :       CHARACTER(len=60) :: task = ""
     132              :       CHARACTER(len=60) :: csave = ""
     133              :       LOGICAL :: lsave(4) = .FALSE.
     134              :       INTEGER :: m = 0, print_every = 0, master = 0, max_f_per_iter = 0, status = 0, n_iter = 0
     135              :       INTEGER, DIMENSION(:), POINTER :: kind_of_bound => NULL(), i_work_array => NULL(), isave => NULL()
     136              :       REAL(kind=dp) :: f = 0.0_dp, wanted_relative_f_delta = 0.0_dp, wanted_projected_gradient = 0.0_dp, &
     137              :                        last_f = 0.0_dp, projected_gradient = 0.0_dp, eold = 0.0_dp, emin = 0.0_dp, trust_radius = 0.0_dp
     138              :       REAL(kind=dp), DIMENSION(:), POINTER :: x => NULL(), lower_bound => NULL(), upper_bound => NULL(), &
     139              :                                               gradient => NULL(), dsave => NULL(), work_array => NULL()
     140              :       TYPE(mp_para_env_type), POINTER :: para_env => NULL()
     141              :       TYPE(gopt_f_type), POINTER :: obj_funct => NULL()
     142              :    END TYPE cp_lbfgs_opt_gopt_type
     143              : 
     144              : CONTAINS
     145              : 
     146              : ! **************************************************************************************************
     147              : !> \brief calls the L-BFGS optimizer
     148              : !> \param optimizer the optimizer state
     149              : !> \param spgr optional space group information
     150              : !> \param iwunit optional output unit
     151              : ! **************************************************************************************************
     152         3333 :    SUBROUTINE cp_opt_gopt_setulb(optimizer, spgr, iwunit)
     153              :       TYPE(cp_lbfgs_opt_gopt_type), INTENT(INOUT)        :: optimizer
     154              :       TYPE(spgr_type), OPTIONAL, POINTER                 :: spgr
     155              :       INTEGER, OPTIONAL                                  :: iwunit
     156              : 
     157              :       CALL setulb(SIZE(optimizer%x), optimizer%m, optimizer%x, &
     158              :                   optimizer%lower_bound, optimizer%upper_bound, &
     159              :                   optimizer%kind_of_bound, optimizer%f, optimizer%gradient, &
     160              :                   optimizer%wanted_relative_f_delta, &
     161              :                   optimizer%wanted_projected_gradient, optimizer%work_array, &
     162              :                   optimizer%i_work_array, optimizer%task, optimizer%print_every, &
     163              :                   optimizer%csave, optimizer%lsave, optimizer%isave, &
     164         3333 :                   optimizer%dsave, optimizer%trust_radius, spgr=spgr, iwunit=iwunit)
     165              : 
     166         3333 :    END SUBROUTINE cp_opt_gopt_setulb
     167              : 
     168              : ! **************************************************************************************************
     169              : !> \brief initializes the optimizer
     170              : !> \param optimizer ...
     171              : !> \param para_env ...
     172              : !> \param obj_funct ...
     173              : !> \param x0 ...
     174              : !> \param m ...
     175              : !> \param print_every ...
     176              : !> \param wanted_relative_f_delta ...
     177              : !> \param wanted_projected_gradient ...
     178              : !> \param lower_bound ...
     179              : !> \param upper_bound ...
     180              : !> \param kind_of_bound ...
     181              : !> \param master ...
     182              : !> \param max_f_per_iter ...
     183              : !> \param trust_radius ...
     184              : !> \par History
     185              : !>      02.2002 created [fawzi]
     186              : !>      09.2003 refactored (retain/release,para_env) [fawzi]
     187              : !> \author Fawzi Mohamed
     188              : !> \note
     189              : !>      redirects the lbfgs output the the default unit
     190              : ! **************************************************************************************************
     191          624 :    SUBROUTINE cp_opt_gopt_create(optimizer, para_env, obj_funct, x0, m, print_every, &
     192            0 :                                  wanted_relative_f_delta, wanted_projected_gradient, lower_bound, upper_bound, &
     193            0 :                                  kind_of_bound, master, max_f_per_iter, trust_radius)
     194              :       TYPE(cp_lbfgs_opt_gopt_type), INTENT(OUT)          :: optimizer
     195              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     196              :       TYPE(gopt_f_type), POINTER                         :: obj_funct
     197              :       REAL(kind=dp), DIMENSION(:), INTENT(in)            :: x0
     198              :       INTEGER, INTENT(in), OPTIONAL                      :: m, print_every
     199              :       REAL(kind=dp), INTENT(in), OPTIONAL                :: wanted_relative_f_delta, &
     200              :                                                             wanted_projected_gradient
     201              :       REAL(kind=dp), DIMENSION(SIZE(x0)), INTENT(in), &
     202              :          OPTIONAL                                        :: lower_bound, upper_bound
     203              :       INTEGER, DIMENSION(SIZE(x0)), INTENT(in), OPTIONAL :: kind_of_bound
     204              :       INTEGER, INTENT(in), OPTIONAL                      :: master, max_f_per_iter
     205              :       REAL(kind=dp), INTENT(in), OPTIONAL                :: trust_radius
     206              : 
     207              :       CHARACTER(len=*), PARAMETER :: routineN = 'cp_opt_gopt_create'
     208              : 
     209              :       INTEGER                                            :: handle, lenwa, n
     210              : 
     211          104 :       CALL timeset(routineN, handle)
     212              : 
     213              :       NULLIFY (optimizer%kind_of_bound, &
     214          104 :                optimizer%i_work_array, &
     215          104 :                optimizer%isave, &
     216          104 :                optimizer%x, &
     217          104 :                optimizer%lower_bound, &
     218          104 :                optimizer%upper_bound, &
     219          104 :                optimizer%gradient, &
     220          104 :                optimizer%dsave, &
     221          104 :                optimizer%work_array, &
     222              :                optimizer%para_env, &
     223          104 :                optimizer%obj_funct)
     224          104 :       n = SIZE(x0)
     225          104 :       optimizer%m = 4
     226          104 :       IF (PRESENT(m)) optimizer%m = m
     227          104 :       optimizer%master = para_env%source
     228          104 :       optimizer%para_env => para_env
     229          104 :       CALL para_env%retain()
     230          104 :       optimizer%obj_funct => obj_funct
     231          104 :       CALL gopt_f_retain(obj_funct)
     232          104 :       optimizer%max_f_per_iter = 20
     233          104 :       IF (PRESENT(max_f_per_iter)) optimizer%max_f_per_iter = max_f_per_iter
     234          104 :       optimizer%print_every = -1
     235          104 :       optimizer%n_iter = 0
     236          104 :       optimizer%f = -1.0_dp
     237          104 :       optimizer%last_f = -1.0_dp
     238          104 :       optimizer%projected_gradient = -1.0_dp
     239          104 :       IF (PRESENT(print_every)) optimizer%print_every = print_every
     240          104 :       IF (PRESENT(master)) optimizer%master = master
     241          104 :       IF (optimizer%master == optimizer%para_env%mepos) THEN
     242              :          !MK This has to be adapted for a new L-BFGS version possibly
     243           52 :          lenwa = 2*optimizer%m*n + 5*n + 11*optimizer%m*optimizer%m + 8*optimizer%m
     244              :          ALLOCATE (optimizer%kind_of_bound(n), optimizer%i_work_array(3*n), &
     245          260 :                    optimizer%isave(44))
     246              :          ALLOCATE (optimizer%x(n), optimizer%lower_bound(n), &
     247              :                    optimizer%upper_bound(n), optimizer%gradient(n), &
     248          416 :                    optimizer%dsave(29), optimizer%work_array(lenwa))
     249        39013 :          optimizer%x = x0
     250           52 :          optimizer%task = 'START'
     251       116935 :          optimizer%i_work_array = 0
     252         2340 :          optimizer%isave = 0
     253        39013 :          optimizer%lower_bound = 0.0_dp
     254        39013 :          optimizer%upper_bound = 0.0_dp
     255        39013 :          optimizer%gradient = 0.0_dp
     256         1560 :          optimizer%dsave = 0.0_dp
     257       702772 :          optimizer%work_array = 0.0_dp
     258           52 :          IF (PRESENT(wanted_relative_f_delta)) THEN
     259           52 :             optimizer%wanted_relative_f_delta = wanted_relative_f_delta
     260              :          END IF
     261           52 :          IF (PRESENT(wanted_projected_gradient)) THEN
     262           52 :             optimizer%wanted_projected_gradient = wanted_projected_gradient
     263              :          END IF
     264        39013 :          optimizer%kind_of_bound = 0
     265           52 :          IF (PRESENT(kind_of_bound)) optimizer%kind_of_bound = kind_of_bound
     266           52 :          IF (PRESENT(lower_bound)) optimizer%lower_bound = lower_bound
     267           52 :          IF (PRESENT(upper_bound)) optimizer%upper_bound = upper_bound
     268           52 :          IF (PRESENT(trust_radius)) optimizer%trust_radius = trust_radius
     269              : 
     270           52 :          CALL cp_opt_gopt_setulb(optimizer)
     271              :       ELSE
     272              :          NULLIFY ( &
     273           52 :             optimizer%kind_of_bound, optimizer%i_work_array, optimizer%isave, &
     274           52 :             optimizer%lower_bound, optimizer%upper_bound, optimizer%gradient, &
     275           52 :             optimizer%dsave, optimizer%work_array)
     276          156 :          ALLOCATE (optimizer%x(n))
     277        39013 :          optimizer%x(:) = 0.0_dp
     278          104 :          ALLOCATE (optimizer%gradient(n))
     279        39013 :          optimizer%gradient(:) = 0.0_dp
     280              :       END IF
     281       155948 :       CALL optimizer%para_env%bcast(optimizer%x, optimizer%master)
     282          104 :       optimizer%status = 0
     283              : 
     284          104 :       CALL timestop(handle)
     285              : 
     286          104 :    END SUBROUTINE cp_opt_gopt_create
     287              : 
     288              : ! **************************************************************************************************
     289              : !> \brief releases the optimizer (see doc/ReferenceCounting.html)
     290              : !> \param optimizer the object that should be released
     291              : !> \par History
     292              : !>      02.2002 created [fawzi]
     293              : !>      09.2003 dealloc_ref->release [fawzi]
     294              : !> \author Fawzi Mohamed
     295              : ! **************************************************************************************************
     296          104 :    SUBROUTINE cp_opt_gopt_release(optimizer)
     297              :       TYPE(cp_lbfgs_opt_gopt_type), INTENT(INOUT)        :: optimizer
     298              : 
     299              :       CHARACTER(len=*), PARAMETER :: routineN = 'cp_opt_gopt_release'
     300              : 
     301              :       INTEGER                                            :: handle
     302              : 
     303          104 :       CALL timeset(routineN, handle)
     304              : 
     305          104 :       IF (ASSOCIATED(optimizer%kind_of_bound)) THEN
     306           52 :          DEALLOCATE (optimizer%kind_of_bound)
     307              :       END IF
     308          104 :       IF (ASSOCIATED(optimizer%i_work_array)) THEN
     309           52 :          DEALLOCATE (optimizer%i_work_array)
     310              :       END IF
     311          104 :       IF (ASSOCIATED(optimizer%isave)) THEN
     312           52 :          DEALLOCATE (optimizer%isave)
     313              :       END IF
     314          104 :       IF (ASSOCIATED(optimizer%x)) THEN
     315          104 :          DEALLOCATE (optimizer%x)
     316              :       END IF
     317          104 :       IF (ASSOCIATED(optimizer%lower_bound)) THEN
     318           52 :          DEALLOCATE (optimizer%lower_bound)
     319              :       END IF
     320          104 :       IF (ASSOCIATED(optimizer%upper_bound)) THEN
     321           52 :          DEALLOCATE (optimizer%upper_bound)
     322              :       END IF
     323          104 :       IF (ASSOCIATED(optimizer%gradient)) THEN
     324          104 :          DEALLOCATE (optimizer%gradient)
     325              :       END IF
     326          104 :       IF (ASSOCIATED(optimizer%dsave)) THEN
     327           52 :          DEALLOCATE (optimizer%dsave)
     328              :       END IF
     329          104 :       IF (ASSOCIATED(optimizer%work_array)) THEN
     330           52 :          DEALLOCATE (optimizer%work_array)
     331              :       END IF
     332          104 :       CALL mp_para_env_release(optimizer%para_env)
     333          104 :       CALL gopt_f_release(optimizer%obj_funct)
     334              : 
     335          104 :       CALL timestop(handle)
     336          104 :    END SUBROUTINE cp_opt_gopt_release
     337              : 
     338              : ! **************************************************************************************************
     339              : !> \brief does one optimization step
     340              : !> \param optimizer ...
     341              : !> \param n_iter ...
     342              : !> \param f ...
     343              : !> \param last_f ...
     344              : !> \param projected_gradient ...
     345              : !> \param converged ...
     346              : !> \param geo_section ...
     347              : !> \param force_env ...
     348              : !> \param gopt_param ...
     349              : !> \param spgr ...
     350              : !> \par History
     351              : !>      01.2020 modified [pcazade]
     352              : !> \author Fawzi Mohamed
     353              : !>      @version 2.2002
     354              : !> \note
     355              : !>      use directly mainlb in place of setulb ??
     356              : ! **************************************************************************************************
     357         3044 :    SUBROUTINE cp_opt_gopt_step(optimizer, n_iter, f, last_f, &
     358              :                                projected_gradient, converged, geo_section, force_env, &
     359              :                                gopt_param, spgr)
     360              :       TYPE(cp_lbfgs_opt_gopt_type), INTENT(INOUT)        :: optimizer
     361              :       INTEGER, INTENT(out), OPTIONAL                     :: n_iter
     362              :       REAL(kind=dp), INTENT(out), OPTIONAL               :: f, last_f, projected_gradient
     363              :       LOGICAL, INTENT(out), OPTIONAL                     :: converged
     364              :       TYPE(section_vals_type), POINTER                   :: geo_section
     365              :       TYPE(force_env_type), POINTER                      :: force_env
     366              :       TYPE(gopt_param_type), POINTER                     :: gopt_param
     367              :       TYPE(spgr_type), OPTIONAL, POINTER                 :: spgr
     368              : 
     369              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'cp_opt_gopt_step'
     370              : 
     371              :       CHARACTER(LEN=5)                                   :: wildcard
     372              :       INTEGER                                            :: dataunit, handle, its
     373              :       LOGICAL                                            :: conv, is_master, just_entered, &
     374              :                                                             keep_space_group
     375              :       REAL(KIND=dp)                                      :: t_diff, t_now, t_old
     376         3044 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: xold
     377              :       TYPE(cp_logger_type), POINTER                      :: logger
     378              :       TYPE(cp_subsys_type), POINTER                      :: subsys
     379              : 
     380         3044 :       NULLIFY (logger, xold)
     381         6088 :       logger => cp_get_default_logger()
     382         3044 :       CALL timeset(routineN, handle)
     383         3044 :       just_entered = .TRUE.
     384         3044 :       is_master = optimizer%master == optimizer%para_env%mepos
     385         3044 :       IF (PRESENT(converged)) converged = optimizer%status == 4
     386         9132 :       ALLOCATE (xold(SIZE(optimizer%x)))
     387              : 
     388              :       ! collecting subsys
     389         3044 :       CALL force_env_get(force_env, subsys=subsys)
     390              : 
     391         3044 :       keep_space_group = .FALSE.
     392         3044 :       IF (PRESENT(spgr)) THEN
     393         3044 :          IF (ASSOCIATED(spgr)) keep_space_group = spgr%keep_space_group
     394              :       END IF
     395              : 
     396              :       ! applies rotation matrices to coordinates
     397         3044 :       IF (keep_space_group) THEN
     398            2 :          CALL spgr_apply_rotations_coord(spgr, optimizer%x)
     399              :       END IF
     400              : 
     401      1835300 :       xold = optimizer%x
     402         3044 :       t_old = m_walltime()
     403              : 
     404         3044 :       IF (optimizer%status >= 4) THEN
     405            0 :          CPWARN("status>=4, trying to restart")
     406            0 :          optimizer%status = 0
     407              :          dataunit = cp_print_key_unit_nr(logger, geo_section, &
     408            0 :                                          "PRINT%PROGRAM_RUN_INFO", extension=".geoLog")
     409            0 :          IF (is_master) THEN
     410            0 :             optimizer%task = 'START'
     411            0 :             CALL cp_opt_gopt_setulb(optimizer, spgr=spgr, iwunit=dataunit)
     412              :          END IF
     413              :          CALL cp_print_key_finished_output(dataunit, logger, geo_section, &
     414            0 :                                            "PRINT%PROGRAM_RUN_INFO")
     415              :       END IF
     416              : 
     417              :       DO
     418              :          dataunit = cp_print_key_unit_nr(logger, geo_section, &
     419         9606 :                                          "PRINT%PROGRAM_RUN_INFO", extension=".geoLog")
     420         9606 :          ifMaster: IF (is_master) THEN
     421         4803 :             IF (optimizer%task(1:7) == 'RESTART') THEN
     422              :                ! restart the optimizer
     423            0 :                optimizer%status = 0
     424            0 :                optimizer%task = 'START'
     425              :                ! applies rotation matrices to coordinates and forces
     426            0 :                IF (keep_space_group) THEN
     427            0 :                   CALL spgr_apply_rotations_coord(spgr, optimizer%x)
     428            0 :                   CALL spgr_apply_rotations_force(spgr, optimizer%gradient)
     429              :                END IF
     430            0 :                CALL cp_opt_gopt_setulb(optimizer, spgr=spgr, iwunit=dataunit)
     431            0 :                IF (keep_space_group) THEN
     432            0 :                   CALL spgr_apply_rotations_coord(spgr, optimizer%x)
     433            0 :                   CALL spgr_apply_rotations_force(spgr, optimizer%gradient)
     434              :                END IF
     435              :             END IF
     436         4803 :             IF (optimizer%task(1:2) == 'FG') THEN
     437         1810 :                IF (optimizer%isave(36) > optimizer%max_f_per_iter) THEN
     438            0 :                   optimizer%task = 'STOP: CPU, hit max f eval in iter'
     439            0 :                   optimizer%status = 5 ! anormal exit
     440            0 :                   CALL cp_opt_gopt_setulb(optimizer, spgr=spgr, iwunit=dataunit)
     441              :                ELSE
     442         1810 :                   optimizer%status = 1
     443              :                END IF
     444         2993 :             ELSE IF (optimizer%task(1:5) == 'NEW_X') THEN
     445         2992 :                IF (just_entered) THEN
     446         1471 :                   optimizer%status = 2
     447              :                   ! applies rotation matrices to coordinates and forces
     448         1471 :                   IF (keep_space_group) THEN
     449            0 :                      CALL spgr_apply_rotations_coord(spgr, optimizer%x)
     450            0 :                      CALL spgr_apply_rotations_force(spgr, optimizer%gradient)
     451              :                   END IF
     452         1471 :                   CALL cp_opt_gopt_setulb(optimizer, spgr=spgr, iwunit=dataunit)
     453         1471 :                   IF (keep_space_group) THEN
     454            0 :                      CALL spgr_apply_rotations_coord(spgr, optimizer%x)
     455            0 :                      CALL spgr_apply_rotations_force(spgr, optimizer%gradient)
     456              :                   END IF
     457              :                ELSE
     458              :                   ! applies rotation matrices to coordinates and forces
     459         1521 :                   IF (keep_space_group) THEN
     460            1 :                      CALL spgr_apply_rotations_coord(spgr, optimizer%x)
     461            1 :                      CALL spgr_apply_rotations_force(spgr, optimizer%gradient)
     462              :                   END IF
     463         1521 :                   optimizer%status = 3
     464              :                END IF
     465            1 :             ELSE IF (optimizer%task(1:4) == 'CONV') THEN
     466            1 :                optimizer%status = 4
     467            0 :             ELSE IF (optimizer%task(1:4) == 'STOP') THEN
     468            0 :                optimizer%status = 5
     469            0 :                CPWARN("task became stop in an unknown way")
     470            0 :             ELSE IF (optimizer%task(1:5) == 'ERROR') THEN
     471            0 :                optimizer%status = 5
     472              :             ELSE
     473            0 :                CPWARN("unknown task '"//optimizer%task//"'")
     474              :             END IF
     475              :          END IF ifMaster
     476              :          CALL cp_print_key_finished_output(dataunit, logger, geo_section, &
     477         9606 :                                            "PRINT%PROGRAM_RUN_INFO")
     478         9606 :          CALL optimizer%para_env%bcast(optimizer%status, optimizer%master)
     479              :          ! Dump info
     480         9606 :          IF (optimizer%status == 3) THEN
     481         3042 :             its = 0
     482         3042 :             IF (is_master) THEN
     483              :                ! Iteration level is taken into account in the optimizer external loop
     484         1521 :                its = optimizer%isave(30)
     485              :             END IF
     486              :          END IF
     487              :          !
     488         3620 :          SELECT CASE (optimizer%status)
     489              :          CASE (1)
     490              :             !op=1 evaluate f and g
     491              :             CALL cp_eval_at(optimizer%obj_funct, x=optimizer%x, &
     492              :                             f=optimizer%f, &
     493              :                             gradient=optimizer%gradient, &
     494         3620 :                             master=optimizer%master, para_env=optimizer%para_env)
     495              :             ! do not use keywords?
     496              :             dataunit = cp_print_key_unit_nr(logger, geo_section, &
     497         3620 :                                             "PRINT%PROGRAM_RUN_INFO", extension=".geoLog")
     498         3620 :             IF (is_master) THEN
     499              :                ! applies rotation matrices to coordinates and forces
     500         1810 :                IF (keep_space_group) THEN
     501            2 :                   CALL spgr_apply_rotations_coord(spgr, optimizer%x)
     502            2 :                   CALL spgr_apply_rotations_force(spgr, optimizer%gradient)
     503              :                END IF
     504         1810 :                CALL cp_opt_gopt_setulb(optimizer, spgr=spgr, iwunit=dataunit)
     505         1810 :                IF (keep_space_group) THEN
     506            2 :                   CALL spgr_apply_rotations_coord(spgr, optimizer%x)
     507            2 :                   CALL spgr_apply_rotations_force(spgr, optimizer%gradient)
     508              :                END IF
     509              :             END IF
     510              :             CALL cp_print_key_finished_output(dataunit, logger, geo_section, &
     511         3620 :                                               "PRINT%PROGRAM_RUN_INFO")
     512      4650332 :             CALL optimizer%para_env%bcast(optimizer%x, optimizer%master)
     513              :          CASE (2)
     514              :             !op=2 begin new iter
     515      3511658 :             CALL optimizer%para_env%bcast(optimizer%x, optimizer%master)
     516         2942 :             t_old = m_walltime()
     517              :          CASE (3)
     518              :             !op=3 ended iter
     519         3042 :             wildcard = "LBFGS"
     520              :             dataunit = cp_print_key_unit_nr(logger, geo_section, &
     521         3042 :                                             "PRINT%PROGRAM_RUN_INFO", extension=".geoLog")
     522         3042 :             IF (is_master) its = optimizer%isave(30)
     523         3042 :             CALL optimizer%para_env%bcast(its, optimizer%master)
     524              : 
     525              :             ! Some IO and Convergence check
     526         3042 :             t_now = m_walltime()
     527         3042 :             t_diff = t_now - t_old
     528         3042 :             t_old = t_now
     529              :             CALL gopt_f_io(optimizer%obj_funct, force_env, force_env%root_section, &
     530              :                            its, optimizer%f, dataunit, optimizer%eold, optimizer%emin, wildcard, gopt_param, &
     531      1835262 :                            SIZE(optimizer%x), optimizer%x - xold, optimizer%gradient, conv, used_time=t_diff)
     532         3042 :             CALL optimizer%para_env%bcast(conv, optimizer%master)
     533              :             CALL cp_print_key_finished_output(dataunit, logger, geo_section, &
     534         3042 :                                               "PRINT%PROGRAM_RUN_INFO")
     535         3042 :             optimizer%eold = optimizer%f
     536         3042 :             optimizer%emin = MIN(optimizer%emin, optimizer%eold)
     537      1835262 :             xold = optimizer%x
     538         3042 :             IF (PRESENT(converged)) converged = conv
     539            2 :             EXIT
     540              :          CASE (4)
     541              :             !op=4 (convergence - normal exit)
     542              :             ! Specific L-BFGS convergence criteria.. overrides the convergence criteria on
     543              :             ! stepsize and gradients
     544              :             dataunit = cp_print_key_unit_nr(logger, geo_section, &
     545            2 :                                             "PRINT%PROGRAM_RUN_INFO", extension=".geoLog")
     546            2 :             IF (dataunit > 0) THEN
     547            1 :                WRITE (dataunit, '(T2,A)') ""
     548            1 :                WRITE (dataunit, '(T2,A)') "************************************************"
     549            1 :                WRITE (dataunit, '(T2,A)') "* Specific L-BFGS convergence criteria         *"
     550            1 :                WRITE (dataunit, '(T2,A)') "* WANTED_PROJ_GRADIENT and WANTED_REL_F_ERROR  *"
     551            1 :                WRITE (dataunit, '(T2,A)') "* satisfied .... run CONVERGED!                *"
     552            1 :                WRITE (dataunit, '(T2,A)') "*                    * * *                     *"
     553            1 :                WRITE (dataunit, '(T2,A)') "* General convergence criteria on stepsize and *"
     554            1 :                WRITE (dataunit, '(T2,A)') "* gradients may or may not have been satisfied *"
     555            1 :                WRITE (dataunit, '(T2,A)') "* yet; if unsatisfactory, try tightening the   *"
     556            1 :                WRITE (dataunit, '(T2,A)') "* L-BFGS convergence criteria and restart run. *"
     557            1 :                WRITE (dataunit, '(T2,A)') "************************************************"
     558            1 :                WRITE (dataunit, '(T2,A)') ""
     559              :             END IF
     560              :             CALL cp_print_key_finished_output(dataunit, logger, geo_section, &
     561            2 :                                               "PRINT%PROGRAM_RUN_INFO")
     562            2 :             IF (PRESENT(converged)) converged = .TRUE.
     563            0 :             EXIT
     564              :          CASE (5)
     565              :             ! Restore the last accepted point; a failed FG request may leave x at a trial point.
     566            0 :             CALL optimizer%para_env%bcast(optimizer%task, optimizer%master)
     567            0 :             optimizer%x = xold
     568              :             CALL cp_eval_at(optimizer%obj_funct, x=optimizer%x, &
     569              :                             f=optimizer%f, gradient=optimizer%gradient, &
     570            0 :                             master=optimizer%master, para_env=optimizer%para_env)
     571            0 :             IF (PRESENT(converged)) converged = .FALSE.
     572            0 :             EXIT
     573              :          CASE (6)
     574              :             ! deallocated
     575            0 :             CPABORT("step on a deallocated opt structure ")
     576              :          CASE default
     577              :             CALL cp_abort(__LOCATION__, &
     578            0 :                           "unknown status "//cp_to_string(optimizer%status))
     579            0 :             optimizer%status = 5
     580         9606 :             EXIT
     581              :          END SELECT
     582         6562 :          IF (optimizer%status == 1 .AND. just_entered) THEN
     583          102 :             optimizer%eold = optimizer%f
     584          102 :             optimizer%emin = optimizer%eold
     585              :          END IF
     586              :          just_entered = .FALSE.
     587              :       END DO
     588              : 
     589      3667556 :       CALL optimizer%para_env%bcast(optimizer%x, optimizer%master)
     590              :       CALL cp_opt_gopt_bcast_res(optimizer, &
     591              :                                  n_iter=optimizer%n_iter, &
     592              :                                  f=optimizer%f, last_f=optimizer%last_f, &
     593         3044 :                                  projected_gradient=optimizer%projected_gradient)
     594              : 
     595         3044 :       DEALLOCATE (xold)
     596         3044 :       IF (PRESENT(f)) f = optimizer%f
     597         3044 :       IF (PRESENT(last_f)) last_f = optimizer%last_f
     598         3044 :       IF (PRESENT(projected_gradient)) projected_gradient = optimizer%projected_gradient
     599         3044 :       IF (PRESENT(n_iter)) n_iter = optimizer%n_iter
     600         3044 :       CALL timestop(handle)
     601              : 
     602         3044 :    END SUBROUTINE cp_opt_gopt_step
     603              : 
     604              : ! **************************************************************************************************
     605              : !> \brief returns the results (and broadcasts them)
     606              : !> \param optimizer the optimizer object the info is taken from
     607              : !> \param n_iter the number of iterations
     608              : !> \param f the actual value of the objective function (f)
     609              : !> \param last_f the last value of f
     610              : !> \param projected_gradient the infinity norm of the projected gradient
     611              : !> \par History
     612              : !>      none
     613              : !> \author Fawzi Mohamed
     614              : !>      @version 2.2002
     615              : !> \note
     616              : !>      private routine
     617              : ! **************************************************************************************************
     618         3044 :    SUBROUTINE cp_opt_gopt_bcast_res(optimizer, n_iter, f, last_f, &
     619              :                                     projected_gradient)
     620              :       TYPE(cp_lbfgs_opt_gopt_type), INTENT(IN)           :: optimizer
     621              :       INTEGER, INTENT(out), OPTIONAL                     :: n_iter
     622              :       REAL(kind=dp), INTENT(inout), OPTIONAL             :: f, last_f, projected_gradient
     623              : 
     624              :       REAL(kind=dp), DIMENSION(4)                        :: results
     625              : 
     626         3044 :       IF (optimizer%master == optimizer%para_env%mepos) THEN
     627              :          results = [REAL(optimizer%isave(30), kind=dp), &
     628         7610 :                     optimizer%f, optimizer%dsave(2), optimizer%dsave(13)]
     629              :       END IF
     630         3044 :       CALL optimizer%para_env%bcast(results, optimizer%master)
     631         3044 :       IF (PRESENT(n_iter)) n_iter = NINT(results(1))
     632         3044 :       IF (PRESENT(f)) f = results(2)
     633         3044 :       IF (PRESENT(last_f)) last_f = results(3)
     634         3044 :       IF (PRESENT(projected_gradient)) projected_gradient = results(4)
     635              : 
     636         3044 :    END SUBROUTINE cp_opt_gopt_bcast_res
     637              : 
     638              : ! **************************************************************************************************
     639              : !> \brief goes to the next optimal point (after an optimizer iteration)
     640              : !>      returns true if converged
     641              : !> \param optimizer the optimizer that goes to the next point
     642              : !> \param n_iter ...
     643              : !> \param f ...
     644              : !> \param last_f ...
     645              : !> \param projected_gradient ...
     646              : !> \param converged ...
     647              : !> \param geo_section ...
     648              : !> \param force_env ...
     649              : !> \param gopt_param ...
     650              : !> \param spgr ...
     651              : !> \return ...
     652              : !> \par History
     653              : !>      01.2020 modified [pcazade]
     654              : !> \author Fawzi Mohamed
     655              : !>      @version 2.2002
     656              : !> \note
     657              : !>      if you deactivate convergence control it returns never false
     658              : ! **************************************************************************************************
     659         3044 :    FUNCTION cp_opt_gopt_next(optimizer, n_iter, f, last_f, &
     660              :                              projected_gradient, converged, geo_section, force_env, &
     661              :                              gopt_param, spgr) RESULT(res)
     662              :       TYPE(cp_lbfgs_opt_gopt_type), INTENT(INOUT)        :: optimizer
     663              :       INTEGER, INTENT(out), OPTIONAL                     :: n_iter
     664              :       REAL(kind=dp), INTENT(out), OPTIONAL               :: f, last_f, projected_gradient
     665              :       LOGICAL, INTENT(out)                               :: converged
     666              :       TYPE(section_vals_type), POINTER                   :: geo_section
     667              :       TYPE(force_env_type), POINTER                      :: force_env
     668              :       TYPE(gopt_param_type), POINTER                     :: gopt_param
     669              :       TYPE(spgr_type), OPTIONAL, POINTER                 :: spgr
     670              :       LOGICAL                                            :: res
     671              : 
     672              :       ! passes spgr structure if present
     673              :       CALL cp_opt_gopt_step(optimizer, n_iter=n_iter, f=f, &
     674              :                             last_f=last_f, projected_gradient=projected_gradient, &
     675              :                             converged=converged, geo_section=geo_section, &
     676         3044 :                             force_env=force_env, gopt_param=gopt_param, spgr=spgr)
     677         3044 :       res = (optimizer%status < 4) .AND. .NOT. converged
     678              : 
     679         3044 :    END FUNCTION cp_opt_gopt_next
     680              : 
     681              : ! **************************************************************************************************
     682              : !> \brief stops the optimization
     683              : !> \param optimizer ...
     684              : !> \par History
     685              : !>      none
     686              : !> \author Fawzi Mohamed
     687              : !>      @version 2.2002
     688              : ! **************************************************************************************************
     689            0 :    SUBROUTINE cp_opt_gopt_stop(optimizer)
     690              :       TYPE(cp_lbfgs_opt_gopt_type), INTENT(INOUT)        :: optimizer
     691              : 
     692            0 :       optimizer%task = 'STOPPED on user request'
     693            0 :       optimizer%status = 4 ! normal exit
     694            0 :       IF (optimizer%master == optimizer%para_env%mepos) THEN
     695            0 :          CALL cp_opt_gopt_setulb(optimizer)
     696              :       END IF
     697              : 
     698            0 :    END SUBROUTINE cp_opt_gopt_stop
     699              : 
     700            0 : END MODULE cp_lbfgs_optimizer_gopt
        

Generated by: LCOV version 2.0-1