LCOV - code coverage report
Current view: top level - src - qs_cdft_opt_types.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:71c3ab0) Lines: 89.6 % 106 95
Test Date: 2026-07-25 06:35:44 Functions: 71.4 % 7 5

            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 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        17790 :    SUBROUTINE cdft_opt_type_release(cdft_opt_control)
     134              : 
     135              :       TYPE(cdft_opt_type), POINTER                       :: cdft_opt_control
     136              : 
     137        17790 :       IF (ASSOCIATED(cdft_opt_control)) THEN
     138          484 :          IF (ASSOCIATED(cdft_opt_control%jacobian_vector)) THEN
     139            4 :             DEALLOCATE (cdft_opt_control%jacobian_vector)
     140              :          END IF
     141          484 :          IF (ALLOCATED(cdft_opt_control%jacobian_step)) THEN
     142          484 :             DEALLOCATE (cdft_opt_control%jacobian_step)
     143              :          END IF
     144              : 
     145          484 :          DEALLOCATE (cdft_opt_control)
     146              :       END IF
     147              : 
     148        17790 :       NULLIFY (cdft_opt_control)
     149              : 
     150        17790 :    END SUBROUTINE cdft_opt_type_release
     151              : 
     152              : ! **************************************************************************************************
     153              : !> \brief reads the parameters of the CDFT optimizer type
     154              : !> \param cdft_opt_control the object that will contain the values read
     155              : !> \param inp_section the input section that contains the values that are read
     156              : !> \par History
     157              : !>      03.2018 created [Nico Holmberg]
     158              : !> \author Nico Holmberg
     159              : ! **************************************************************************************************
     160           70 :    SUBROUTINE cdft_opt_type_read(cdft_opt_control, inp_section)
     161              : 
     162              :       TYPE(cdft_opt_type), POINTER                       :: cdft_opt_control
     163              :       TYPE(section_vals_type), POINTER                   :: inp_section
     164              : 
     165              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'cdft_opt_type_read'
     166              : 
     167              :       INTEGER                                            :: handle
     168           70 :       INTEGER, DIMENSION(:), POINTER                     :: tmplist
     169              :       LOGICAL                                            :: exists
     170           70 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: rtmplist
     171              :       TYPE(section_vals_type), POINTER                   :: cdft_opt_section
     172              : 
     173           70 :       CALL timeset(routineN, handle)
     174              : 
     175           70 :       CPASSERT(ASSOCIATED(cdft_opt_control))
     176           70 :       cdft_opt_section => section_vals_get_subs_vals(inp_section, "CDFT_OPT")
     177              : 
     178              :       CALL section_vals_val_get(cdft_opt_section, "MAX_LS", &
     179           70 :                                 i_val=cdft_opt_control%max_ls)
     180              :       CALL section_vals_val_get(cdft_opt_section, "JACOBIAN_TYPE", &
     181           70 :                                 i_val=cdft_opt_control%jacobian_type)
     182              :       CALL section_vals_val_get(cdft_opt_section, "JACOBIAN_STEP", &
     183           70 :                                 r_vals=rtmplist)
     184          210 :       ALLOCATE (cdft_opt_control%jacobian_step(SIZE(rtmplist)))
     185          284 :       cdft_opt_control%jacobian_step(:) = rtmplist
     186              :       CALL section_vals_val_get(cdft_opt_section, "BROYDEN_TYPE", &
     187           70 :                                 i_val=cdft_opt_control%broyden_type)
     188              :       CALL section_vals_val_get(cdft_opt_section, "CONTINUE_LS", &
     189           70 :                                 l_val=cdft_opt_control%continue_ls)
     190              :       CALL section_vals_val_get(cdft_opt_section, "FACTOR_LS", &
     191           70 :                                 r_val=cdft_opt_control%factor_ls)
     192           70 :       IF (cdft_opt_control%factor_ls <= 0.0_dp .OR. &
     193              :           cdft_opt_control%factor_ls >= 1.0_dp) THEN
     194              :          CALL cp_abort(__LOCATION__, &
     195            0 :                        "Keyword FACTOR_LS must be between 0.0 and 1.0.")
     196              :       END IF
     197           70 :       CALL section_vals_val_get(cdft_opt_section, "JACOBIAN_FREQ", explicit=exists)
     198           70 :       IF (exists) THEN
     199              :          CALL section_vals_val_get(cdft_opt_section, "JACOBIAN_FREQ", &
     200           64 :                                    i_vals=tmplist)
     201           64 :          IF (SIZE(tmplist) /= 2) THEN
     202              :             CALL cp_abort(__LOCATION__, &
     203            0 :                           "Keyword JACOBIAN_FREQ takes exactly two input values.")
     204              :          END IF
     205          192 :          IF (ANY(tmplist < 0)) THEN
     206              :             CALL cp_abort(__LOCATION__, &
     207            0 :                           "Keyword JACOBIAN_FREQ takes only positive values.")
     208              :          END IF
     209           64 :          IF (ALL(tmplist == 0)) THEN
     210              :             CALL cp_abort(__LOCATION__, &
     211            0 :                           "Both values to keyword JACOBIAN_FREQ cannot be zero.")
     212              :          END IF
     213          384 :          cdft_opt_control%jacobian_freq(:) = tmplist(1:2)
     214              :       END IF
     215              :       CALL section_vals_val_get(cdft_opt_section, "JACOBIAN_RESTART", &
     216           70 :                                 l_val=cdft_opt_control%jacobian_restart)
     217           70 :       IF (cdft_opt_control%jacobian_restart) THEN
     218              :          CALL section_vals_val_get(cdft_opt_section, "JACOBIAN_VECTOR", &
     219           10 :                                    r_vals=rtmplist)
     220           30 :          ALLOCATE (cdft_opt_control%jacobian_vector(SIZE(rtmplist)))
     221           88 :          cdft_opt_control%jacobian_vector = rtmplist
     222              :       END IF
     223              : 
     224           70 :       CALL timestop(handle)
     225              : 
     226          140 :    END SUBROUTINE cdft_opt_type_read
     227              : 
     228              : ! **************************************************************************************************
     229              : !> \brief writes information about the CDFT optimizer object
     230              : !> \param cdft_opt_control the CDFT optimizer object
     231              : !> \param optimizer the type of optimizer to use
     232              : !> \param output_unit the output unit handle
     233              : !> \par History
     234              : !>      03.2018 created [Nico Holmberg]
     235              : !> \author Nico Holmberg
     236              : ! **************************************************************************************************
     237           60 :    SUBROUTINE cdft_opt_type_write(cdft_opt_control, optimizer, output_unit)
     238              :       TYPE(cdft_opt_type), POINTER                       :: cdft_opt_control
     239              :       INTEGER                                            :: optimizer, output_unit
     240              : 
     241           60 :       CPASSERT(ASSOCIATED(cdft_opt_control))
     242              : 
     243           73 :       SELECT CASE (optimizer)
     244              :       CASE DEFAULT
     245              :          ! Do nothing
     246              :       CASE (outer_scf_optimizer_broyden)
     247           13 :          WRITE (output_unit, '(T3,A)') "Optimization with Broyden's method"
     248           68 :          SELECT CASE (cdft_opt_control%broyden_type)
     249              :          CASE (broyden_type_1)
     250           11 :             WRITE (output_unit, '(A)') "                  variant : 1st method"
     251              :          CASE (broyden_type_1_explicit)
     252            1 :             WRITE (output_unit, '(A)') "                  variant : 1st method with explicit initial Jacobian"
     253              :          CASE (broyden_type_1_ls)
     254            0 :             WRITE (output_unit, '(A)') "                  variant : 1st method with backtracking line search"
     255              :          CASE (broyden_type_1_explicit_ls)
     256              :             WRITE (output_unit, '(A)') &
     257            0 :                "                  variant : 1st method with explicit initial Jacobian"
     258              :             WRITE (output_unit, '(A)') &
     259            0 :                "                            and backtracking line search"
     260              :          CASE (broyden_type_2)
     261            1 :             WRITE (output_unit, '(A)') "                  variant : 2nd method"
     262              :          CASE (broyden_type_2_explicit)
     263            0 :             WRITE (output_unit, '(A)') "                  variant : 2nd method with explicit initial Jacobian"
     264              :          CASE (broyden_type_2_ls)
     265            0 :             WRITE (output_unit, '(A)') "                  variant : 2nd method with backtracking line search"
     266              :          CASE (broyden_type_2_explicit_ls)
     267              :             WRITE (output_unit, '(A)') &
     268            0 :                "                  variant : 2nd method with explicit initial Jacobian"
     269              :             WRITE (output_unit, '(A)') &
     270           13 :                "                            and backtracking line search"
     271              :          END SELECT
     272              :       CASE (outer_scf_optimizer_newton)
     273           44 :          WRITE (output_unit, '(T3,A)') "Optimization with Newton's method"
     274              :       CASE (outer_scf_optimizer_newton_ls)
     275           60 :          WRITE (output_unit, '(T3,A)') "Optimization with Newton's method using backtracking line search"
     276              :       END SELECT
     277          120 :       SELECT CASE (optimizer)
     278              :       CASE DEFAULT
     279              :          ! Do nothing
     280              :       CASE (outer_scf_optimizer_broyden, outer_scf_optimizer_newton, outer_scf_optimizer_newton_ls)
     281           60 :          IF (cdft_opt_control%jacobian_freq(2) > 0) THEN
     282              :             WRITE (output_unit, '(T6,A,I4,A)') &
     283           56 :                "The Jacobian is restarted every ", cdft_opt_control%jacobian_freq(2), " energy evaluation"
     284           56 :             IF (cdft_opt_control%jacobian_freq(1) > 0) THEN
     285              :                WRITE (output_unit, '(T29,A,I4,A)') &
     286           56 :                   "or every ", cdft_opt_control%jacobian_freq(1), " CDFT SCF iteration"
     287              :             END IF
     288              :          ELSE
     289              :             WRITE (output_unit, '(T6,A,I4,A)') &
     290            4 :                "The Jacobian is restarted every ", cdft_opt_control%jacobian_freq(1), " CDFT SCF iteration"
     291              :          END IF
     292              :          WRITE (output_unit, '(T3,A,F8.4)') &
     293          120 :             "Optimizer step size: ", cdft_opt_control%newton_step_save
     294              :       END SELECT
     295              : 
     296           60 :    END SUBROUTINE cdft_opt_type_write
     297              : 
     298              : ! **************************************************************************************************
     299              : !> \brief copies settings between two CDFT optimizer control objects retaining both
     300              : !> \param new the object where to copy the settings
     301              : !> \param old the object from where to copy the settings
     302              : !> \par History
     303              : !>      03.2018 created [Nico Holmberg]
     304              : !> \author Nico Holmberg
     305              : ! **************************************************************************************************
     306         1590 :    SUBROUTINE cdft_opt_type_copy(new, old)
     307              : 
     308              :       TYPE(cdft_opt_type), POINTER                       :: new, old
     309              : 
     310              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'cdft_opt_type_copy'
     311              : 
     312              :       INTEGER                                            :: handle
     313              : 
     314              :       ! Do nothing if cdft_opt_type is not allocated
     315              :       ! this happens if CDFT is performed with an optimizer other than Broyden/Newton
     316         1590 :       IF (.NOT. ASSOCIATED(old)) RETURN
     317              : 
     318          758 :       CALL timeset(routineN, handle)
     319              : 
     320          758 :       IF (.NOT. ASSOCIATED(new)) CALL cdft_opt_type_create(new)
     321          758 :       new%max_ls = old%max_ls
     322          758 :       new%continue_ls = old%continue_ls
     323          758 :       new%factor_ls = old%factor_ls
     324          758 :       new%jacobian_type = old%jacobian_type
     325         3790 :       new%jacobian_freq(:) = old%jacobian_freq(:)
     326          758 :       new%newton_step = old%newton_step
     327          758 :       new%newton_step_save = old%newton_step_save
     328         3790 :       new%ijacobian(:) = old%ijacobian(:)
     329          758 :       new%build_jacobian = old%build_jacobian
     330          758 :       new%broyden_type = old%broyden_type
     331          758 :       new%broyden_update = old%broyden_update
     332          758 :       IF (ALLOCATED(new%jacobian_step)) DEALLOCATE (new%jacobian_step)
     333         2274 :       ALLOCATE (new%jacobian_step(SIZE(old%jacobian_step)))
     334         2334 :       new%jacobian_step(:) = old%jacobian_step
     335          758 :       IF (old%jacobian_restart) THEN
     336              :          ! Transfer restart vector for inverse Jacobian matrix
     337              :          ! (qs_calculate_inverse_jacobian handles deallocation of transferred vector)
     338           30 :          new%jacobian_restart = .TRUE.
     339           90 :          ALLOCATE (new%jacobian_vector(SIZE(old%jacobian_vector)))
     340          234 :          new%jacobian_vector = old%jacobian_vector
     341           30 :          DEALLOCATE (old%jacobian_vector)
     342           30 :          old%jacobian_restart = .FALSE.
     343              :       END IF
     344              : 
     345          758 :       CALL timestop(handle)
     346              : 
     347          758 :    END SUBROUTINE cdft_opt_type_copy
     348              : 
     349            0 : END MODULE qs_cdft_opt_types
        

Generated by: LCOV version 2.0-1