LCOV - code coverage report
Current view: top level - src - qs_cdft_opt_types.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:42dac4a) Lines: 89.6 % 106 95
Test Date: 2025-07-25 12:55:17 Functions: 71.4 % 7 5

            Line data    Source code
       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 Control parameters for optimizers that work with CDFT constraints
      10              : !> \par   History
      11              : !>                 separated from scf_control_types [03.2018]
      12              : !> \author Nico Holmberg [03.2018]
      13              : ! **************************************************************************************************
      14              : MODULE qs_cdft_opt_types
      15              : 
      16              :    USE input_constants,                 ONLY: &
      17              :         broyden_type_1, broyden_type_1_explicit, broyden_type_1_explicit_ls, broyden_type_1_ls, &
      18              :         broyden_type_2, broyden_type_2_explicit, broyden_type_2_explicit_ls, broyden_type_2_ls, &
      19              :         outer_scf_optimizer_broyden, outer_scf_optimizer_newton, outer_scf_optimizer_newton_ls
      20              :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      21              :                                               section_vals_type,&
      22              :                                               section_vals_val_get
      23              :    USE kinds,                           ONLY: dp
      24              : #include "./base/base_uses.f90"
      25              : 
      26              :    IMPLICIT NONE
      27              : 
      28              :    PRIVATE
      29              : 
      30              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_cdft_opt_types'
      31              : 
      32              :    ! Public data types
      33              : 
      34              :    PUBLIC :: cdft_opt_type
      35              : 
      36              :    ! Public subroutines
      37              : 
      38              :    PUBLIC :: cdft_opt_type_create, &
      39              :              cdft_opt_type_release, &
      40              :              cdft_opt_type_read, &
      41              :              cdft_opt_type_write, &
      42              :              cdft_opt_type_copy
      43              : 
      44              : ! **************************************************************************************************
      45              : !> \brief contains the parameters needed by CDFT specific optimizers
      46              : !> \param build_jacobian logical which determines if the inverse Jacobian should be computed
      47              : !> \param jacobian_step the step size for calculating the finite difference Jacobian
      48              : !> \param newton_step the step size used by the Newton optimizer with values between 0 and 1
      49              : !> \param newton_step_save permanent copy of the above
      50              : !> \param jacobian_type the finite difference scheme to compute the Jacobian
      51              : !> \param broyden_type the variant of Broyden's method to use
      52              : !> \param jacobian_freq control parameters defining how often the Jacobian is built
      53              : !> \param ijacobian counter to track how many SCF iterations/energy evaluations have passed since
      54              : !>                  the last Jacobian rebuild
      55              : !> \param broyden_update logical which determines if a Broyden update is needed
      56              : !> \param max_ls the maximum number of backtracking line search steps to perform
      57              : !> \param continue_ls continue line search until max steps are reached or until the gradient
      58              : !>                    no longer decreases
      59              : !> \param factor_ls line search parameter used in generating a new step size
      60              : !> \par History
      61              : !>                 created [03.2018]
      62              : !> \author Nico Holmberg [03.2018]
      63              : ! **************************************************************************************************
      64              : 
      65              :    TYPE cdft_opt_type
      66              :       LOGICAL                              :: build_jacobian = .FALSE.
      67              :       LOGICAL                              :: broyden_update = .FALSE.
      68              :       LOGICAL                              :: continue_ls = .FALSE.
      69              :       LOGICAL                              :: jacobian_restart = .FALSE.
      70              :       REAL(KIND=dp)                        :: newton_step = 0.0_dp
      71              :       REAL(KIND=dp)                        :: newton_step_save = 0.0_dp
      72              :       REAL(KIND=dp)                        :: factor_ls = 0.0_dp
      73              :       REAL(KIND=dp), DIMENSION(:), &
      74              :          ALLOCATABLE                       :: jacobian_step
      75              :       REAL(KIND=dp), DIMENSION(:), &
      76              :          POINTER                           :: jacobian_vector => NULL()
      77              :       INTEGER                              :: jacobian_type = -1
      78              :       INTEGER                              :: broyden_type = -1
      79              :       INTEGER                              :: jacobian_freq(2) = -1
      80              :       INTEGER                              :: ijacobian(2) = -1
      81              :       INTEGER                              :: max_ls = -1
      82              :    END TYPE cdft_opt_type
      83              : 
      84              : CONTAINS
      85              : 
      86              : ! **************************************************************************************************
      87              : !> \brief allocates and initializes the CDFT optimizer control object with default values
      88              : !> \param cdft_opt_control the object to initialize
      89              : !> \par History
      90              : !>      03.2018 created [Nico Holmberg]
      91              : !> \author Nico Holmberg
      92              : ! **************************************************************************************************
      93          484 :    SUBROUTINE cdft_opt_type_create(cdft_opt_control)
      94              : 
      95              :       TYPE(cdft_opt_type), POINTER                       :: cdft_opt_control
      96              : 
      97              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'cdft_opt_type_create'
      98              : 
      99              :       INTEGER                                            :: handle
     100              : 
     101          484 :       CALL timeset(routineN, handle)
     102              : 
     103          484 :       CPASSERT(.NOT. ASSOCIATED(cdft_opt_control))
     104         3388 :       ALLOCATE (cdft_opt_control)
     105              : 
     106              :       ! Load the default values
     107              : 
     108              :       cdft_opt_control%jacobian_type = -1
     109              :       cdft_opt_control%broyden_type = -1
     110         1452 :       cdft_opt_control%jacobian_freq(:) = 1
     111          484 :       cdft_opt_control%newton_step = 1.0_dp
     112          484 :       cdft_opt_control%newton_step_save = 1.0_dp
     113          484 :       cdft_opt_control%factor_ls = 0.5_dp
     114         1452 :       cdft_opt_control%ijacobian(:) = 0
     115          484 :       cdft_opt_control%max_ls = 0
     116              :       cdft_opt_control%build_jacobian = .FALSE.
     117              :       cdft_opt_control%broyden_update = .FALSE.
     118              :       cdft_opt_control%continue_ls = .FALSE.
     119              :       cdft_opt_control%jacobian_restart = .FALSE.
     120              :       NULLIFY (cdft_opt_control%jacobian_vector)
     121              : 
     122          484 :       CALL timestop(handle)
     123              : 
     124          484 :    END SUBROUTINE cdft_opt_type_create
     125              : 
     126              : ! **************************************************************************************************
     127              : !> \brief releases the CDFT optimizer control object
     128              : !> \param cdft_opt_control the object to release
     129              : !> \par History
     130              : !>      03.2018 created [Nico Holmberg]
     131              : !> \author Nico Holmberg
     132              : ! **************************************************************************************************
     133        15266 :    SUBROUTINE cdft_opt_type_release(cdft_opt_control)
     134              : 
     135              :       TYPE(cdft_opt_type), POINTER                       :: cdft_opt_control
     136              : 
     137        15266 :       IF (ASSOCIATED(cdft_opt_control)) THEN
     138          484 :          IF (ASSOCIATED(cdft_opt_control%jacobian_vector)) &
     139            4 :             DEALLOCATE (cdft_opt_control%jacobian_vector)
     140          484 :          IF (ALLOCATED(cdft_opt_control%jacobian_step)) &
     141          484 :             DEALLOCATE (cdft_opt_control%jacobian_step)
     142              : 
     143          484 :          DEALLOCATE (cdft_opt_control)
     144              :       END IF
     145              : 
     146        15266 :       NULLIFY (cdft_opt_control)
     147              : 
     148        15266 :    END SUBROUTINE cdft_opt_type_release
     149              : 
     150              : ! **************************************************************************************************
     151              : !> \brief reads the parameters of the CDFT optimizer type
     152              : !> \param cdft_opt_control the object that will contain the values read
     153              : !> \param inp_section the input section that contains the values that are read
     154              : !> \par History
     155              : !>      03.2018 created [Nico Holmberg]
     156              : !> \author Nico Holmberg
     157              : ! **************************************************************************************************
     158           70 :    SUBROUTINE cdft_opt_type_read(cdft_opt_control, inp_section)
     159              : 
     160              :       TYPE(cdft_opt_type), POINTER                       :: cdft_opt_control
     161              :       TYPE(section_vals_type), POINTER                   :: inp_section
     162              : 
     163              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'cdft_opt_type_read'
     164              : 
     165              :       INTEGER                                            :: handle
     166           70 :       INTEGER, DIMENSION(:), POINTER                     :: tmplist
     167              :       LOGICAL                                            :: exists
     168           70 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: rtmplist
     169              :       TYPE(section_vals_type), POINTER                   :: cdft_opt_section
     170              : 
     171           70 :       CALL timeset(routineN, handle)
     172              : 
     173           70 :       CPASSERT(ASSOCIATED(cdft_opt_control))
     174           70 :       cdft_opt_section => section_vals_get_subs_vals(inp_section, "CDFT_OPT")
     175              : 
     176              :       CALL section_vals_val_get(cdft_opt_section, "MAX_LS", &
     177           70 :                                 i_val=cdft_opt_control%max_ls)
     178              :       CALL section_vals_val_get(cdft_opt_section, "JACOBIAN_TYPE", &
     179           70 :                                 i_val=cdft_opt_control%jacobian_type)
     180              :       CALL section_vals_val_get(cdft_opt_section, "JACOBIAN_STEP", &
     181           70 :                                 r_vals=rtmplist)
     182          210 :       ALLOCATE (cdft_opt_control%jacobian_step(SIZE(rtmplist)))
     183          284 :       cdft_opt_control%jacobian_step(:) = rtmplist
     184              :       CALL section_vals_val_get(cdft_opt_section, "BROYDEN_TYPE", &
     185           70 :                                 i_val=cdft_opt_control%broyden_type)
     186              :       CALL section_vals_val_get(cdft_opt_section, "CONTINUE_LS", &
     187           70 :                                 l_val=cdft_opt_control%continue_ls)
     188              :       CALL section_vals_val_get(cdft_opt_section, "FACTOR_LS", &
     189           70 :                                 r_val=cdft_opt_control%factor_ls)
     190           70 :       IF (cdft_opt_control%factor_ls .LE. 0.0_dp .OR. &
     191              :           cdft_opt_control%factor_ls .GE. 1.0_dp) &
     192              :          CALL cp_abort(__LOCATION__, &
     193            0 :                        "Keyword FACTOR_LS must be between 0.0 and 1.0.")
     194           70 :       CALL section_vals_val_get(cdft_opt_section, "JACOBIAN_FREQ", explicit=exists)
     195           70 :       IF (exists) THEN
     196              :          CALL section_vals_val_get(cdft_opt_section, "JACOBIAN_FREQ", &
     197           64 :                                    i_vals=tmplist)
     198           64 :          IF (SIZE(tmplist) /= 2) &
     199              :             CALL cp_abort(__LOCATION__, &
     200            0 :                           "Keyword JACOBIAN_FREQ takes exactly two input values.")
     201          192 :          IF (ANY(tmplist .LT. 0)) &
     202              :             CALL cp_abort(__LOCATION__, &
     203            0 :                           "Keyword JACOBIAN_FREQ takes only positive values.")
     204           64 :          IF (ALL(tmplist .EQ. 0)) &
     205              :             CALL cp_abort(__LOCATION__, &
     206            0 :                           "Both values to keyword JACOBIAN_FREQ cannot be zero.")
     207          384 :          cdft_opt_control%jacobian_freq(:) = tmplist(1:2)
     208              :       END IF
     209              :       CALL section_vals_val_get(cdft_opt_section, "JACOBIAN_RESTART", &
     210           70 :                                 l_val=cdft_opt_control%jacobian_restart)
     211           70 :       IF (cdft_opt_control%jacobian_restart) THEN
     212              :          CALL section_vals_val_get(cdft_opt_section, "JACOBIAN_VECTOR", &
     213           10 :                                    r_vals=rtmplist)
     214           30 :          ALLOCATE (cdft_opt_control%jacobian_vector(SIZE(rtmplist)))
     215           88 :          cdft_opt_control%jacobian_vector = rtmplist
     216              :       END IF
     217              : 
     218           70 :       CALL timestop(handle)
     219              : 
     220          140 :    END SUBROUTINE cdft_opt_type_read
     221              : 
     222              : ! **************************************************************************************************
     223              : !> \brief writes information about the CDFT optimizer object
     224              : !> \param cdft_opt_control the CDFT optimizer object
     225              : !> \param optimizer the type of optimizer to use
     226              : !> \param output_unit the output unit handle
     227              : !> \par History
     228              : !>      03.2018 created [Nico Holmberg]
     229              : !> \author Nico Holmberg
     230              : ! **************************************************************************************************
     231           60 :    SUBROUTINE cdft_opt_type_write(cdft_opt_control, optimizer, output_unit)
     232              :       TYPE(cdft_opt_type), POINTER                       :: cdft_opt_control
     233              :       INTEGER                                            :: optimizer, output_unit
     234              : 
     235           60 :       CPASSERT(ASSOCIATED(cdft_opt_control))
     236              : 
     237           73 :       SELECT CASE (optimizer)
     238              :       CASE DEFAULT
     239              :          ! Do nothing
     240              :       CASE (outer_scf_optimizer_broyden)
     241           13 :          WRITE (output_unit, '(T3,A)') "Optimization with Broyden's method"
     242           68 :          SELECT CASE (cdft_opt_control%broyden_type)
     243              :          CASE (broyden_type_1)
     244           11 :             WRITE (output_unit, '(A)') "                  variant : 1st method"
     245              :          CASE (broyden_type_1_explicit)
     246            1 :             WRITE (output_unit, '(A)') "                  variant : 1st method with explicit initial Jacobian"
     247              :          CASE (broyden_type_1_ls)
     248            0 :             WRITE (output_unit, '(A)') "                  variant : 1st method with backtracking line search"
     249              :          CASE (broyden_type_1_explicit_ls)
     250              :             WRITE (output_unit, '(A)') &
     251            0 :                "                  variant : 1st method with explicit initial Jacobian"
     252              :             WRITE (output_unit, '(A)') &
     253            0 :                "                            and backtracking line search"
     254              :          CASE (broyden_type_2)
     255            1 :             WRITE (output_unit, '(A)') "                  variant : 2nd method"
     256              :          CASE (broyden_type_2_explicit)
     257            0 :             WRITE (output_unit, '(A)') "                  variant : 2nd method with explicit initial Jacobian"
     258              :          CASE (broyden_type_2_ls)
     259            0 :             WRITE (output_unit, '(A)') "                  variant : 2nd method with backtracking line search"
     260              :          CASE (broyden_type_2_explicit_ls)
     261              :             WRITE (output_unit, '(A)') &
     262            0 :                "                  variant : 2nd method with explicit initial Jacobian"
     263              :             WRITE (output_unit, '(A)') &
     264           13 :                "                            and backtracking line search"
     265              :          END SELECT
     266              :       CASE (outer_scf_optimizer_newton)
     267           44 :          WRITE (output_unit, '(T3,A)') "Optimization with Newton's method"
     268              :       CASE (outer_scf_optimizer_newton_ls)
     269           60 :          WRITE (output_unit, '(T3,A)') "Optimization with Newton's method using backtracking line search"
     270              :       END SELECT
     271          120 :       SELECT CASE (optimizer)
     272              :       CASE DEFAULT
     273              :          ! Do nothing
     274              :       CASE (outer_scf_optimizer_broyden, outer_scf_optimizer_newton, outer_scf_optimizer_newton_ls)
     275           60 :          IF (cdft_opt_control%jacobian_freq(2) > 0) THEN
     276              :             WRITE (output_unit, '(T6,A,I4,A)') &
     277           56 :                "The Jacobian is restarted every ", cdft_opt_control%jacobian_freq(2), " energy evaluation"
     278           56 :             IF (cdft_opt_control%jacobian_freq(1) > 0) &
     279              :                WRITE (output_unit, '(T29,A,I4,A)') &
     280           56 :                "or every ", cdft_opt_control%jacobian_freq(1), " CDFT SCF iteration"
     281              :          ELSE
     282              :             WRITE (output_unit, '(T6,A,I4,A)') &
     283            4 :                "The Jacobian is restarted every ", cdft_opt_control%jacobian_freq(1), " CDFT SCF iteration"
     284              :          END IF
     285              :          WRITE (output_unit, '(T3,A,F8.4)') &
     286          120 :             "Optimizer step size: ", cdft_opt_control%newton_step_save
     287              :       END SELECT
     288              : 
     289           60 :    END SUBROUTINE cdft_opt_type_write
     290              : 
     291              : ! **************************************************************************************************
     292              : !> \brief copies settings between two CDFT optimizer control objects retaining both
     293              : !> \param new the object where to copy the settings
     294              : !> \param old the object from where to copy the settings
     295              : !> \par History
     296              : !>      03.2018 created [Nico Holmberg]
     297              : !> \author Nico Holmberg
     298              : ! **************************************************************************************************
     299         1498 :    SUBROUTINE cdft_opt_type_copy(new, old)
     300              : 
     301              :       TYPE(cdft_opt_type), POINTER                       :: new, old
     302              : 
     303              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'cdft_opt_type_copy'
     304              : 
     305              :       INTEGER                                            :: handle
     306              : 
     307              :       ! Do nothing if cdft_opt_type is not allocated
     308              :       ! this happens if CDFT is performed with an optimizer other than Broyden/Newton
     309         1498 :       IF (.NOT. ASSOCIATED(old)) RETURN
     310              : 
     311          758 :       CALL timeset(routineN, handle)
     312              : 
     313          758 :       IF (.NOT. ASSOCIATED(new)) CALL cdft_opt_type_create(new)
     314          758 :       new%max_ls = old%max_ls
     315          758 :       new%continue_ls = old%continue_ls
     316          758 :       new%factor_ls = old%factor_ls
     317          758 :       new%jacobian_type = old%jacobian_type
     318         3790 :       new%jacobian_freq(:) = old%jacobian_freq(:)
     319          758 :       new%newton_step = old%newton_step
     320          758 :       new%newton_step_save = old%newton_step_save
     321         3790 :       new%ijacobian(:) = old%ijacobian(:)
     322          758 :       new%build_jacobian = old%build_jacobian
     323          758 :       new%broyden_type = old%broyden_type
     324          758 :       new%broyden_update = old%broyden_update
     325          758 :       IF (ALLOCATED(new%jacobian_step)) DEALLOCATE (new%jacobian_step)
     326         2274 :       ALLOCATE (new%jacobian_step(SIZE(old%jacobian_step)))
     327         2334 :       new%jacobian_step(:) = old%jacobian_step
     328          758 :       IF (old%jacobian_restart) THEN
     329              :          ! Transfer restart vector for inverse Jacobian matrix
     330              :          ! (qs_calculate_inverse_jacobian handles deallocation of transferred vector)
     331           30 :          new%jacobian_restart = .TRUE.
     332           90 :          ALLOCATE (new%jacobian_vector(SIZE(old%jacobian_vector)))
     333          234 :          new%jacobian_vector = old%jacobian_vector
     334           30 :          DEALLOCATE (old%jacobian_vector)
     335           30 :          old%jacobian_restart = .FALSE.
     336              :       END IF
     337              : 
     338          758 :       CALL timestop(handle)
     339              : 
     340          758 :    END SUBROUTINE cdft_opt_type_copy
     341              : 
     342            0 : END MODULE qs_cdft_opt_types
        

Generated by: LCOV version 2.0-1