LCOV - code coverage report
Current view: top level - src - qs_outer_scf.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:71c3ab0) Lines: 89.2 % 288 257
Test Date: 2026-07-25 06:35:44 Functions: 85.7 % 7 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 for performing an outer scf loop
      10              : !> \par History
      11              : !>      Created [2006.03]
      12              : !> \author Joost VandeVondele
      13              : ! **************************************************************************************************
      14              : MODULE qs_outer_scf
      15              :    USE cp_control_types,                ONLY: ddapc_restraint_type,&
      16              :                                               dft_control_type,&
      17              :                                               s2_restraint_type
      18              :    USE cp_log_handling,                 ONLY: cp_to_string
      19              :    USE input_constants,                 ONLY: &
      20              :         broyden_type_1, broyden_type_1_explicit, broyden_type_1_explicit_ls, broyden_type_1_ls, &
      21              :         broyden_type_2, broyden_type_2_explicit, broyden_type_2_explicit_ls, broyden_type_2_ls, &
      22              :         cdft2ot, do_ddapc_constraint, do_s2_constraint, ot2cdft, outer_scf_basis_center_opt, &
      23              :         outer_scf_cdft_constraint, outer_scf_ddapc_constraint, outer_scf_none, &
      24              :         outer_scf_optimizer_bisect, outer_scf_optimizer_broyden, outer_scf_optimizer_diis, &
      25              :         outer_scf_optimizer_newton, outer_scf_optimizer_newton_ls, outer_scf_optimizer_none, &
      26              :         outer_scf_optimizer_sd, outer_scf_optimizer_secant, outer_scf_s2_constraint
      27              :    USE kinds,                           ONLY: dp
      28              :    USE mathlib,                         ONLY: diamat_all
      29              :    USE qs_basis_gradient,               ONLY: qs_basis_center_gradient,&
      30              :                                               qs_update_basis_center_pos,&
      31              :                                               return_basis_center_gradient_norm
      32              :    USE qs_cdft_opt_types,               ONLY: cdft_opt_type_copy,&
      33              :                                               cdft_opt_type_release
      34              :    USE qs_cdft_types,                   ONLY: cdft_control_type
      35              :    USE qs_energy_types,                 ONLY: qs_energy_type
      36              :    USE qs_environment_types,            ONLY: get_qs_env,&
      37              :                                               qs_environment_type,&
      38              :                                               set_qs_env
      39              :    USE qs_scf_types,                    ONLY: qs_scf_env_type
      40              :    USE scf_control_types,               ONLY: scf_control_type
      41              : #include "./base/base_uses.f90"
      42              : 
      43              :    IMPLICIT NONE
      44              : 
      45              :    PRIVATE
      46              : 
      47              : ! *** Global parameters ***
      48              : 
      49              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_outer_scf'
      50              : 
      51              : ! *** Public subroutines ***
      52              : 
      53              :    PUBLIC :: outer_loop_gradient, outer_loop_optimize, outer_loop_update_qs_env, &
      54              :              outer_loop_variables_count, outer_loop_extrapolate, &
      55              :              outer_loop_switch, outer_loop_purge_history
      56              : 
      57              : CONTAINS
      58              : 
      59              : ! **************************************************************************************************
      60              : !> \brief returns the number of variables that is employed in the outer loop. with a CDFT constraint
      61              : !>        this value is returned by the cdft_control type
      62              : !> \param scf_control the outer loop control type
      63              : !> \param cdft_control the cdft loop control type
      64              : !> \return the number of variables
      65              : !> \par History
      66              : !>      03.2006 created [Joost VandeVondele]
      67              : ! **************************************************************************************************
      68         5552 :    FUNCTION outer_loop_variables_count(scf_control, cdft_control) RESULT(res)
      69              :       TYPE(scf_control_type), POINTER                    :: scf_control
      70              :       TYPE(cdft_control_type), INTENT(IN), OPTIONAL, &
      71              :          POINTER                                         :: cdft_control
      72              :       INTEGER                                            :: res
      73              : 
      74         5552 :       SELECT CASE (scf_control%outer_scf%type)
      75              :       CASE (outer_scf_ddapc_constraint)
      76              :          res = 1
      77              :       CASE (outer_scf_s2_constraint)
      78           62 :          res = 1
      79              :       CASE (outer_scf_cdft_constraint)
      80           62 :          IF (PRESENT(cdft_control)) THEN
      81           62 :             res = SIZE(cdft_control%target)
      82              :          ELSE
      83              :             res = 1
      84              :          END IF
      85              :       CASE (outer_scf_basis_center_opt)
      86              :          res = 1
      87              :       CASE (outer_scf_none) ! just needed to communicate the gradient criterion
      88            0 :          res = 1
      89              :       CASE DEFAULT
      90         5552 :          res = 0
      91              :       END SELECT
      92              : 
      93         5552 :    END FUNCTION outer_loop_variables_count
      94              : 
      95              : ! **************************************************************************************************
      96              : !> \brief computes the gradient wrt to the outer loop variables
      97              : !> \param qs_env ...
      98              : !> \param scf_env ...
      99              : !> \par History
     100              : !>      03.2006 created [Joost VandeVondele]
     101              : ! **************************************************************************************************
     102         6241 :    SUBROUTINE outer_loop_gradient(qs_env, scf_env)
     103              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     104              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     105              : 
     106              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'outer_loop_gradient'
     107              : 
     108              :       INTEGER                                            :: handle, ihistory, ivar, n
     109              :       LOGICAL                                            :: is_constraint
     110              :       TYPE(cdft_control_type), POINTER                   :: cdft_control
     111              :       TYPE(ddapc_restraint_type), POINTER                :: ddapc_restraint_control
     112              :       TYPE(dft_control_type), POINTER                    :: dft_control
     113              :       TYPE(qs_energy_type), POINTER                      :: energy
     114              :       TYPE(s2_restraint_type), POINTER                   :: s2_restraint_control
     115              :       TYPE(scf_control_type), POINTER                    :: scf_control
     116              : 
     117         6241 :       CALL timeset(routineN, handle)
     118              : 
     119              :       CALL get_qs_env(qs_env=qs_env, scf_control=scf_control, &
     120         6241 :                       dft_control=dft_control, energy=energy)
     121         6241 :       CPASSERT(scf_control%outer_scf%have_scf)
     122              : 
     123         6241 :       ihistory = scf_env%outer_scf%iter_count
     124         6241 :       CPASSERT(ihistory <= SIZE(scf_env%outer_scf%energy, 1))
     125              : 
     126         6241 :       scf_env%outer_scf%energy(ihistory) = energy%total
     127              : 
     128        11724 :       SELECT CASE (scf_control%outer_scf%type)
     129              :       CASE (outer_scf_none)
     130              :          ! just pass the inner loop scf criterion to the outer loop one
     131         5483 :          scf_env%outer_scf%variables(1, ihistory) = scf_env%iter_delta
     132         5483 :          scf_env%outer_scf%gradient(1, ihistory) = scf_env%iter_delta
     133              :       CASE (outer_scf_ddapc_constraint)
     134           76 :          CPASSERT(dft_control%qs_control%ddapc_restraint)
     135           76 :          DO n = 1, SIZE(dft_control%qs_control%ddapc_restraint_control)
     136           76 :             NULLIFY (ddapc_restraint_control)
     137           76 :             ddapc_restraint_control => dft_control%qs_control%ddapc_restraint_control(n)
     138           76 :             is_constraint = (ddapc_restraint_control%functional_form == do_ddapc_constraint)
     139           76 :             IF (is_constraint) EXIT
     140              :          END DO
     141           76 :          CPASSERT(is_constraint)
     142              : 
     143          152 :          scf_env%outer_scf%variables(:, ihistory) = ddapc_restraint_control%strength
     144              :          scf_env%outer_scf%gradient(:, ihistory) = ddapc_restraint_control%ddapc_order_p - &
     145          152 :                                                    ddapc_restraint_control%target
     146              :       CASE (outer_scf_s2_constraint)
     147            0 :          CPASSERT(dft_control%qs_control%s2_restraint)
     148            0 :          s2_restraint_control => dft_control%qs_control%s2_restraint_control
     149            0 :          is_constraint = (s2_restraint_control%functional_form == do_s2_constraint)
     150            0 :          CPASSERT(is_constraint)
     151              : 
     152            0 :          scf_env%outer_scf%variables(:, ihistory) = s2_restraint_control%strength
     153              :          scf_env%outer_scf%gradient(:, ihistory) = s2_restraint_control%s2_order_p - &
     154            0 :                                                    s2_restraint_control%target
     155              :       CASE (outer_scf_cdft_constraint)
     156          682 :          CPASSERT(dft_control%qs_control%cdft)
     157          682 :          cdft_control => dft_control%qs_control%cdft_control
     158         1498 :          DO ivar = 1, SIZE(scf_env%outer_scf%gradient, 1)
     159          816 :             scf_env%outer_scf%variables(ivar, ihistory) = cdft_control%strength(ivar)
     160              :             scf_env%outer_scf%gradient(ivar, ihistory) = cdft_control%value(ivar) - &
     161         1498 :                                                          cdft_control%target(ivar)
     162              :          END DO
     163              :       CASE (outer_scf_basis_center_opt)
     164            0 :          CALL qs_basis_center_gradient(qs_env)
     165            0 :          scf_env%outer_scf%gradient(:, ihistory) = return_basis_center_gradient_norm(qs_env)
     166              : 
     167              :       CASE DEFAULT
     168         6241 :          CPABORT("Unknown outer SCF type")
     169              : 
     170              :       END SELECT
     171              : 
     172         6241 :       CALL timestop(handle)
     173              : 
     174         6241 :    END SUBROUTINE outer_loop_gradient
     175              : 
     176              : ! **************************************************************************************************
     177              : !> \brief optimizes the parameters of the outer_scf
     178              : !> \param scf_env the scf_env where to optimize the parameters
     179              : !> \param scf_control control parameters for the optimization
     180              : !> \par History
     181              : !>      03.2006 created [Joost VandeVondele]
     182              : !>      01.2017 added Broyden and Newton optimizers [Nico Holmberg]
     183              : !> \note
     184              : !>       ought to be general, and independent of the actual kind of variables
     185              : ! **************************************************************************************************
     186         1150 :    SUBROUTINE outer_loop_optimize(scf_env, scf_control)
     187              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     188              :       TYPE(scf_control_type), POINTER                    :: scf_control
     189              : 
     190              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'outer_loop_optimize'
     191              : 
     192              :       INTEGER                                            :: handle, i, ibuf, ihigh, ihistory, ilow, &
     193              :                                                             j, jbuf, nb, nvar, optimizer_type
     194              :       REAL(KIND=dp)                                      :: interval, scale, tmp
     195         1150 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: ev
     196         1150 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: a, b, f, x
     197         1150 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: inv_jacobian
     198              : 
     199         1150 :       CALL timeset(routineN, handle)
     200              : 
     201         1150 :       ihistory = scf_env%outer_scf%iter_count
     202         1150 :       optimizer_type = scf_control%outer_scf%optimizer
     203         1150 :       NULLIFY (inv_jacobian)
     204              : 
     205         1150 :       IF (scf_control%outer_scf%type == outer_scf_basis_center_opt) THEN
     206            0 :          scf_env%outer_scf%variables(:, ihistory + 1) = scf_env%outer_scf%variables(:, ihistory)
     207              :       ELSE
     208              :          DO WHILE (.TRUE.) ! if we need a different run type we'll restart here
     209              : 
     210           44 :             SELECT CASE (optimizer_type)
     211              :             CASE (outer_scf_optimizer_bisect) ! bisection on the gradient, needs to be 1D
     212           44 :                CPASSERT(SIZE(scf_env%outer_scf%gradient(:, 1)) == 1)
     213              :                ! find the pair of points that bracket a zero of the gradient, with the smallest interval possible
     214           44 :                ilow = -1
     215           44 :                ihigh = -1
     216           44 :                interval = HUGE(interval)
     217          100 :                DO i = 1, ihistory
     218          112 :                   DO j = i + 1, ihistory
     219              :                      ! distrust often used points
     220           12 :                      IF (scf_env%outer_scf%count(i) > scf_control%outer_scf%bisect_trust_count) CYCLE
     221           12 :                      IF (scf_env%outer_scf%count(j) > scf_control%outer_scf%bisect_trust_count) CYCLE
     222              : 
     223              :                      ! if they bracket a zero use them
     224           12 :                      IF (scf_env%outer_scf%gradient(1, i)* &
     225           56 :                          scf_env%outer_scf%gradient(1, j) < 0.0_dp) THEN
     226            4 :                         tmp = ABS(scf_env%outer_scf%variables(1, i) - scf_env%outer_scf%variables(1, j))
     227            4 :                         IF (tmp < interval) THEN
     228            4 :                            ilow = i
     229            4 :                            ihigh = j
     230            4 :                            interval = tmp
     231              :                         END IF
     232              :                      END IF
     233              :                   END DO
     234              :                END DO
     235           44 :                IF (ilow == -1) THEN ! we didn't bracket a minimum yet, try something else
     236              :                   optimizer_type = outer_scf_optimizer_diis
     237              :                   CYCLE
     238              :                END IF
     239            4 :                scf_env%outer_scf%count(ilow) = scf_env%outer_scf%count(ilow) + 1
     240            4 :                scf_env%outer_scf%count(ihigh) = scf_env%outer_scf%count(ihigh) + 1
     241              :                scf_env%outer_scf%variables(:, ihistory + 1) = 0.5_dp*(scf_env%outer_scf%variables(:, ilow) + &
     242            8 :                                                                       scf_env%outer_scf%variables(:, ihigh))
     243              :             CASE (outer_scf_optimizer_none)
     244         1752 :                scf_env%outer_scf%variables(:, ihistory + 1) = scf_env%outer_scf%variables(:, ihistory)
     245              :             CASE (outer_scf_optimizer_sd)
     246              :                ! Notice that we are just trying to find a stationary point
     247              :                ! e.g. the ddpac_constraint, one maximizes the function, so the stepsize might have
     248              :                ! to be negative
     249              :                scf_env%outer_scf%variables(:, ihistory + 1) = scf_env%outer_scf%variables(:, ihistory) - &
     250          212 :                                                              scf_control%outer_scf%step_size*scf_env%outer_scf%gradient(:, ihistory)
     251              :             CASE (outer_scf_optimizer_diis)
     252          124 :                CPASSERT(scf_control%outer_scf%diis_buffer_length > 0)
     253              :                ! set up DIIS matrix
     254          124 :                nb = MIN(ihistory, scf_control%outer_scf%diis_buffer_length)
     255          124 :                IF (nb < 2) THEN
     256              :                   optimizer_type = outer_scf_optimizer_sd
     257              :                   CYCLE
     258              :                ELSE
     259          416 :                   ALLOCATE (b(nb + 1, nb + 1), a(nb + 1, nb + 1), ev(nb + 1))
     260          168 :                   DO I = 1, nb
     261          360 :                      DO J = I, nb
     262          192 :                         ibuf = ihistory - nb + i
     263          192 :                         jbuf = ihistory - nb + j
     264              :                         b(I, J) = DOT_PRODUCT(scf_env%outer_scf%gradient(:, ibuf), &
     265          384 :                                               scf_env%outer_scf%gradient(:, jbuf))
     266          308 :                         b(J, I) = b(I, J)
     267              :                      END DO
     268              :                   END DO
     269          220 :                   b(nb + 1, :) = -1.0_dp
     270          220 :                   b(:, nb + 1) = -1.0_dp
     271           52 :                   b(nb + 1, nb + 1) = 0.0_dp
     272              : 
     273           52 :                   CALL diamat_all(b, ev)
     274          772 :                   a(:, :) = b
     275          220 :                   DO I = 1, nb + 1
     276          220 :                      IF (ABS(ev(I)) < 1.0E-12_dp) THEN
     277           60 :                         a(:, I) = 0.0_dp
     278              :                      ELSE
     279          660 :                         a(:, I) = a(:, I)/ev(I)
     280              :                      END IF
     281              :                   END DO
     282         1044 :                   ev(:) = -MATMUL(a, b(nb + 1, :))
     283              : 
     284          104 :                   scf_env%outer_scf%variables(:, ihistory + 1) = 0.0_dp
     285          168 :                   DO i = 1, nb
     286          116 :                      ibuf = ihistory - nb + i
     287              :                      scf_env%outer_scf%variables(:, ihistory + 1) = scf_env%outer_scf%variables(:, ihistory + 1) + &
     288          284 :                                                                     ev(i)*scf_env%outer_scf%variables(:, ibuf)
     289              :                   END DO
     290           52 :                   DEALLOCATE (a, b, ev)
     291              :                END IF
     292              :             CASE (outer_scf_optimizer_secant)
     293            4 :                CPASSERT(SIZE(scf_env%outer_scf%gradient, 2) >= 3)
     294            4 :                CPASSERT(SIZE(scf_env%outer_scf%gradient, 1) == 1)
     295            4 :                nvar = SIZE(scf_env%outer_scf%gradient, 1)
     296            4 :                IF (ihistory < 2) THEN
     297              :                   ! Need two history values to use secant, switch to sd
     298              :                   optimizer_type = outer_scf_optimizer_sd
     299              :                   CYCLE
     300              :                END IF
     301              :                ! secant update
     302              :                scf_env%outer_scf%variables(1, ihistory + 1) = scf_env%outer_scf%variables(1, ihistory) - &
     303              :                                                               (scf_env%outer_scf%variables(1, ihistory) - &
     304              :                                                                scf_env%outer_scf%variables(1, ihistory - 1))/ &
     305              :                                                               (scf_env%outer_scf%gradient(1, ihistory) - &
     306              :                                                                scf_env%outer_scf%gradient(1, ihistory - 1))* &
     307            2 :                                                               scf_env%outer_scf%gradient(1, ihistory)
     308              :             CASE (outer_scf_optimizer_broyden)
     309           24 :                IF (.NOT. ASSOCIATED(scf_env%outer_scf%inv_jacobian)) THEN
     310              :                   ! Inverse Jacobian not yet built, switch to sd
     311          106 :                   optimizer_type = outer_scf_optimizer_sd
     312              :                   CYCLE
     313              :                END IF
     314           16 :                inv_jacobian => scf_env%outer_scf%inv_jacobian
     315           16 :                IF (ihistory < 2) THEN
     316              :                   ! Cannot perform a Broyden update without enough SCF history on this energy evaluation
     317            2 :                   scf_control%outer_scf%cdft_opt_control%broyden_update = .FALSE.
     318              :                END IF
     319           16 :                IF (scf_control%outer_scf%cdft_opt_control%broyden_update) THEN
     320              :                   ! Perform a Broyden update of the inverse Jacobian J^(-1)
     321            6 :                   IF (SIZE(scf_env%outer_scf%gradient, 2) < 3) THEN
     322              :                      CALL cp_abort(__LOCATION__, &
     323              :                                    "Keyword EXTRAPOLATION_ORDER in section OUTER_SCF "// &
     324            0 :                                    "must be greater than or equal to 3 for Broyden optimizers.")
     325              :                   END IF
     326            6 :                   nvar = SIZE(scf_env%outer_scf%gradient, 1)
     327           24 :                   ALLOCATE (f(nvar, 1), x(nvar, 1))
     328           12 :                   DO i = 1, nvar
     329            6 :                      f(i, 1) = scf_env%outer_scf%gradient(i, ihistory) - scf_env%outer_scf%gradient(i, ihistory - 1)
     330           12 :                      x(i, 1) = scf_env%outer_scf%variables(i, ihistory) - scf_env%outer_scf%variables(i, ihistory - 1)
     331              :                   END DO
     332           10 :                   SELECT CASE (scf_control%outer_scf%cdft_opt_control%broyden_type)
     333              :                   CASE (broyden_type_1, broyden_type_1_explicit, broyden_type_1_ls, broyden_type_1_explicit_ls)
     334              :                      ! Broyden's 1st method
     335              :                      ! Denote: dx_n = \delta x_n; df_n = \delta f_n
     336              :                      ! J_(n+1)^(-1) = J_n^(-1) + (dx_n - J_n^(-1)*df_n)*(dx_n^T * J_n^(-1))/(dx_n^T * J_n^(-1) * df_n)
     337           64 :                      scale = SUM(MATMUL(TRANSPOSE(x), MATMUL(inv_jacobian, f)))
     338            4 :                      scale = 1.0_dp/scale
     339              :                      IF (scale < 1.0E-12_dp) scale = 1.0E-12_dp
     340           28 :                      inv_jacobian = inv_jacobian + scale*MATMUL((x - MATMUL(inv_jacobian, f)), &
     341           84 :                                                                 MATMUL(TRANSPOSE(x), inv_jacobian))
     342              :                   CASE (broyden_type_2, broyden_type_2_explicit, broyden_type_2_ls, broyden_type_2_explicit_ls)
     343              :                      ! Broyden's 2nd method
     344              :                      ! J_(n+1)^(-1) = J_n^(-1) + (dx_n - J_n^(-1)*df_n)*(df_n^T)/(||df_n||^2)
     345           14 :                      scale = SUM(MATMUL(TRANSPOSE(f), f))
     346            2 :                      scale = 1.0_dp/scale
     347              :                      IF (scale < 1.0E-12_dp) scale = 1.0E-12_dp
     348           36 :                      inv_jacobian = inv_jacobian + scale*MATMUL((x - MATMUL(inv_jacobian, f)), TRANSPOSE(inv_jacobian))
     349              :                   CASE DEFAULT
     350              :                      CALL cp_abort(__LOCATION__, &
     351              :                                    "Unknown Broyden type: "// &
     352            6 :                                    cp_to_string(scf_control%outer_scf%cdft_opt_control%broyden_type))
     353              :                   END SELECT
     354              :                   ! Clean up
     355            6 :                   DEALLOCATE (f, x)
     356              :                END IF
     357              :                ! Update variables x_(n+1) = x_n - J^(-1)*f(x_n)
     358              :                scf_env%outer_scf%variables(:, ihistory + 1) = scf_env%outer_scf%variables(:, ihistory) - &
     359              :                                                               scf_control%outer_scf%cdft_opt_control%newton_step* &
     360          128 :                                                               MATMUL(inv_jacobian, scf_env%outer_scf%gradient(:, ihistory))
     361           16 :                scf_control%outer_scf%cdft_opt_control%broyden_update = .TRUE.
     362              :             CASE (outer_scf_optimizer_newton, outer_scf_optimizer_newton_ls)
     363           94 :                CPASSERT(ASSOCIATED(scf_env%outer_scf%inv_jacobian))
     364           94 :                inv_jacobian => scf_env%outer_scf%inv_jacobian
     365              :                scf_env%outer_scf%variables(:, ihistory + 1) = scf_env%outer_scf%variables(:, ihistory) - &
     366              :                                                               scf_control%outer_scf%cdft_opt_control%newton_step* &
     367         1368 :                                                               MATMUL(inv_jacobian, scf_env%outer_scf%gradient(:, ihistory))
     368              :             CASE DEFAULT
     369         1190 :                CPABORT("Unknown outer SCF optimizer")
     370              :             END SELECT
     371              :             EXIT
     372              :          END DO
     373              :       END IF
     374              : 
     375         1150 :       CALL timestop(handle)
     376              : 
     377         2300 :    END SUBROUTINE outer_loop_optimize
     378              : 
     379              : ! **************************************************************************************************
     380              : !> \brief propagates the updated variables to wherever they need to be set in
     381              : !>       qs_env
     382              : !> \param qs_env ...
     383              : !> \param scf_env ...
     384              : !> \par History
     385              : !>      03.2006 created [Joost VandeVondele]
     386              : ! **************************************************************************************************
     387         1264 :    SUBROUTINE outer_loop_update_qs_env(qs_env, scf_env)
     388              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     389              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     390              : 
     391              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'outer_loop_update_qs_env'
     392              : 
     393              :       INTEGER                                            :: handle, ihistory, n
     394              :       LOGICAL                                            :: is_constraint
     395              :       TYPE(cdft_control_type), POINTER                   :: cdft_control
     396              :       TYPE(ddapc_restraint_type), POINTER                :: ddapc_restraint_control
     397              :       TYPE(dft_control_type), POINTER                    :: dft_control
     398              :       TYPE(s2_restraint_type), POINTER                   :: s2_restraint_control
     399              :       TYPE(scf_control_type), POINTER                    :: scf_control
     400              : 
     401         1264 :       CALL timeset(routineN, handle)
     402              : 
     403         1264 :       CALL get_qs_env(qs_env=qs_env, scf_control=scf_control, dft_control=dft_control)
     404         1264 :       ihistory = scf_env%outer_scf%iter_count
     405              : 
     406         1314 :       SELECT CASE (scf_control%outer_scf%type)
     407              :       CASE (outer_scf_none)
     408              :          ! do nothing
     409              :       CASE (outer_scf_ddapc_constraint)
     410           50 :          DO n = 1, SIZE(dft_control%qs_control%ddapc_restraint_control)
     411           50 :             NULLIFY (ddapc_restraint_control)
     412           50 :             ddapc_restraint_control => dft_control%qs_control%ddapc_restraint_control(n)
     413           50 :             is_constraint = (ddapc_restraint_control%functional_form == do_ddapc_constraint)
     414           50 :             IF (is_constraint) EXIT
     415              :          END DO
     416           50 :          ddapc_restraint_control%strength = scf_env%outer_scf%variables(1, ihistory + 1)
     417              :       CASE (outer_scf_s2_constraint)
     418            0 :          s2_restraint_control => dft_control%qs_control%s2_restraint_control
     419            0 :          s2_restraint_control%strength = scf_env%outer_scf%variables(1, ihistory + 1)
     420              :       CASE (outer_scf_cdft_constraint)
     421          338 :          cdft_control => dft_control%qs_control%cdft_control
     422         1560 :          cdft_control%strength(:) = scf_env%outer_scf%variables(:, ihistory + 1)
     423              :       CASE (outer_scf_basis_center_opt)
     424            0 :          CALL qs_update_basis_center_pos(qs_env)
     425              :       CASE DEFAULT
     426         1264 :          CPABORT("Unknown outer SCF type")
     427              :       END SELECT
     428              : 
     429         1264 :       CALL timestop(handle)
     430              : 
     431         1264 :    END SUBROUTINE outer_loop_update_qs_env
     432              : 
     433              : ! **************************************************************************************************
     434              : !> \brief uses the outer_scf_history to extrapolate new values for the variables
     435              : !>       and updates their value in qs_env accordingly
     436              : !> \param qs_env the qs_environment_type where to update the variables
     437              : !> \par History
     438              : !>      03.2006 created [Joost VandeVondele]
     439              : !> \note
     440              : !>       it assumes that the current value of qs_env still needs to be added to the history
     441              : !>       simple multilinear extrapolation is employed
     442              : ! **************************************************************************************************
     443         4301 :    SUBROUTINE outer_loop_extrapolate(qs_env)
     444              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     445              : 
     446              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'outer_loop_extrapolate'
     447              : 
     448              :       INTEGER                                            :: handle, ihis, ivec, n, nhistory, &
     449              :                                                             nvariables, nvec, outer_scf_ihistory
     450              :       LOGICAL                                            :: is_constraint
     451              :       REAL(kind=dp)                                      :: alpha
     452         4301 :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:)           :: extrapolation
     453         4301 :       REAL(kind=dp), DIMENSION(:, :), POINTER            :: outer_scf_history
     454              :       TYPE(ddapc_restraint_type), POINTER                :: ddapc_restraint_control
     455              :       TYPE(dft_control_type), POINTER                    :: dft_control
     456              :       TYPE(scf_control_type), POINTER                    :: scf_control
     457              : 
     458         4301 :       CALL timeset(routineN, handle)
     459              : 
     460              :       CALL get_qs_env(qs_env, outer_scf_history=outer_scf_history, &
     461              :                       outer_scf_ihistory=outer_scf_ihistory, &
     462         4301 :                       scf_control=scf_control, dft_control=dft_control)
     463              : 
     464         4301 :       nvariables = SIZE(outer_scf_history, 1)
     465         4301 :       nhistory = SIZE(outer_scf_history, 2)
     466        12903 :       ALLOCATE (extrapolation(nvariables))
     467         4301 :       CPASSERT(nhistory > 0)
     468              : 
     469              :       ! add the current version of qs_env to the history
     470         4301 :       outer_scf_ihistory = outer_scf_ihistory + 1
     471         4301 :       ivec = 1 + MODULO(outer_scf_ihistory - 1, nhistory)
     472         8232 :       SELECT CASE (scf_control%outer_scf%type)
     473              :       CASE (outer_scf_none)
     474         3931 :          outer_scf_history(1, ivec) = 0.0_dp
     475              :       CASE (outer_scf_ddapc_constraint)
     476           26 :          DO n = 1, SIZE(dft_control%qs_control%ddapc_restraint_control)
     477           26 :             NULLIFY (ddapc_restraint_control)
     478           26 :             ddapc_restraint_control => dft_control%qs_control%ddapc_restraint_control(n)
     479           26 :             is_constraint = (ddapc_restraint_control%functional_form == do_ddapc_constraint)
     480           26 :             IF (is_constraint) EXIT
     481              :          END DO
     482              :          outer_scf_history(1, ivec) = &
     483           26 :             ddapc_restraint_control%strength
     484              :       CASE (outer_scf_s2_constraint)
     485              :          outer_scf_history(1, ivec) = &
     486            0 :             dft_control%qs_control%s2_restraint_control%strength
     487              :       CASE (outer_scf_cdft_constraint)
     488              :          outer_scf_history(:, ivec) = &
     489         1436 :             dft_control%qs_control%cdft_control%strength(:)
     490              :       CASE (outer_scf_basis_center_opt)
     491            0 :          outer_scf_history(1, ivec) = 0.0_dp
     492              :       CASE DEFAULT
     493         4301 :          CPABORT("Unknown outer SCF type")
     494              :       END SELECT
     495         4301 :       CALL set_qs_env(qs_env, outer_scf_ihistory=outer_scf_ihistory)
     496              :       ! multilinear extrapolation
     497         4301 :       nvec = MIN(nhistory, outer_scf_ihistory)
     498         4301 :       alpha = nvec
     499         4301 :       ivec = 1 + MODULO(outer_scf_ihistory - 1, nhistory)
     500         8632 :       extrapolation(:) = alpha*outer_scf_history(:, ivec)
     501         9323 :       DO ihis = 2, nvec
     502         5022 :          alpha = -1.0_dp*alpha*REAL(nvec - ihis + 1, dp)/REAL(ihis, dp)
     503         5022 :          ivec = 1 + MODULO(outer_scf_ihistory - ihis, nhistory)
     504        14353 :          extrapolation(:) = extrapolation + alpha*outer_scf_history(:, ivec)
     505              :       END DO
     506              : 
     507              :       ! update qs_env to use this extrapolation
     508         4327 :       SELECT CASE (scf_control%outer_scf%type)
     509              :       CASE (outer_scf_none)
     510              :          ! nothing
     511              :       CASE (outer_scf_ddapc_constraint)
     512           26 :          ddapc_restraint_control%strength = extrapolation(1)
     513              :       CASE (outer_scf_s2_constraint)
     514            0 :          dft_control%qs_control%s2_restraint_control%strength = extrapolation(1)
     515              :       CASE (outer_scf_cdft_constraint)
     516          718 :          dft_control%qs_control%cdft_control%strength(:) = extrapolation(:)
     517              :       CASE (outer_scf_basis_center_opt)
     518              :          ! nothing to do
     519              :       CASE DEFAULT
     520         4301 :          CPABORT("Unknown outer SCF type")
     521              :       END SELECT
     522              : 
     523         4301 :       DEALLOCATE (extrapolation)
     524              : 
     525         4301 :       CALL timestop(handle)
     526              : 
     527         4301 :    END SUBROUTINE outer_loop_extrapolate
     528              : 
     529              : ! **************************************************************************************************
     530              : !> \brief switch between two outer_scf envs stored in cdft_control
     531              : !> \param scf_env the scf_env where values need to be updated using cdft_control
     532              : !> \param scf_control the scf_control where values need to be updated using cdft_control
     533              : !> \param cdft_control container for the second outer_scf env
     534              : !> \param dir determines what switching operation to perform
     535              : !> \par History
     536              : !>      12.2015 created [Nico Holmberg]
     537              : ! **************************************************************************************************
     538              : 
     539         1646 :    SUBROUTINE outer_loop_switch(scf_env, scf_control, cdft_control, dir)
     540              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     541              :       TYPE(scf_control_type), POINTER                    :: scf_control
     542              :       TYPE(cdft_control_type), POINTER                   :: cdft_control
     543              :       INTEGER, INTENT(IN)                                :: dir
     544              : 
     545              :       INTEGER                                            :: nvariables
     546              : 
     547         2328 :       SELECT CASE (dir)
     548              :       CASE (cdft2ot)
     549              :          ! Constraint -> OT
     550              :          ! Switch data in scf_control: first save values that might have changed
     551          682 :          IF (ASSOCIATED(scf_control%outer_scf%cdft_opt_control)) THEN
     552          344 :             CPASSERT(ASSOCIATED(cdft_control%constraint_control%cdft_opt_control))
     553              :             CALL cdft_opt_type_copy(cdft_control%constraint_control%cdft_opt_control, &
     554          344 :                                     scf_control%outer_scf%cdft_opt_control)
     555              :             ! OT SCF does not need cdft_opt_control
     556          344 :             CALL cdft_opt_type_release(scf_control%outer_scf%cdft_opt_control)
     557              :          END IF
     558              :          ! Now switch
     559          682 :          scf_control%outer_scf%have_scf = cdft_control%ot_control%have_scf
     560          682 :          scf_control%outer_scf%max_scf = cdft_control%ot_control%max_scf
     561          682 :          scf_control%outer_scf%eps_scf = cdft_control%ot_control%eps_scf
     562          682 :          scf_control%outer_scf%step_size = cdft_control%ot_control%step_size
     563          682 :          scf_control%outer_scf%type = cdft_control%ot_control%type
     564          682 :          scf_control%outer_scf%optimizer = cdft_control%ot_control%optimizer
     565          682 :          scf_control%outer_scf%diis_buffer_length = cdft_control%ot_control%diis_buffer_length
     566          682 :          scf_control%outer_scf%bisect_trust_count = cdft_control%ot_control%bisect_trust_count
     567              :          ! Switch data in scf_env: first save current values for constraint
     568          682 :          cdft_control%constraint%iter_count = scf_env%outer_scf%iter_count
     569        10064 :          cdft_control%constraint%energy = scf_env%outer_scf%energy
     570        19784 :          cdft_control%constraint%variables = scf_env%outer_scf%variables
     571        19784 :          cdft_control%constraint%gradient = scf_env%outer_scf%gradient
     572        10064 :          cdft_control%constraint%count = scf_env%outer_scf%count
     573          682 :          cdft_control%constraint%deallocate_jacobian = scf_env%outer_scf%deallocate_jacobian
     574          682 :          IF (ASSOCIATED(scf_env%outer_scf%inv_jacobian)) THEN
     575          152 :             nvariables = SIZE(scf_env%outer_scf%inv_jacobian, 1)
     576          152 :             IF (.NOT. ASSOCIATED(cdft_control%constraint%inv_jacobian)) THEN
     577          192 :                ALLOCATE (cdft_control%constraint%inv_jacobian(nvariables, nvariables))
     578              :             END IF
     579         1504 :             cdft_control%constraint%inv_jacobian = scf_env%outer_scf%inv_jacobian
     580              :          END IF
     581              :          ! Now switch
     582          682 :          IF (ASSOCIATED(scf_env%outer_scf%energy)) THEN
     583          682 :             DEALLOCATE (scf_env%outer_scf%energy)
     584              :          END IF
     585         2046 :          ALLOCATE (scf_env%outer_scf%energy(scf_control%outer_scf%max_scf + 1))
     586         2388 :          scf_env%outer_scf%energy = 0.0_dp
     587          682 :          IF (ASSOCIATED(scf_env%outer_scf%variables)) THEN
     588          682 :             DEALLOCATE (scf_env%outer_scf%variables)
     589              :          END IF
     590         2046 :          ALLOCATE (scf_env%outer_scf%variables(1, scf_control%outer_scf%max_scf + 1))
     591         4094 :          scf_env%outer_scf%variables = 0.0_dp
     592          682 :          IF (ASSOCIATED(scf_env%outer_scf%gradient)) THEN
     593          682 :             DEALLOCATE (scf_env%outer_scf%gradient)
     594              :          END IF
     595         2046 :          ALLOCATE (scf_env%outer_scf%gradient(1, scf_control%outer_scf%max_scf + 1))
     596         4094 :          scf_env%outer_scf%gradient = 0.0_dp
     597          682 :          IF (ASSOCIATED(scf_env%outer_scf%count)) THEN
     598          682 :             DEALLOCATE (scf_env%outer_scf%count)
     599              :          END IF
     600         2046 :          ALLOCATE (scf_env%outer_scf%count(scf_control%outer_scf%max_scf + 1))
     601         2388 :          scf_env%outer_scf%count = 0
     602              :          ! OT SCF does not need Jacobian
     603          682 :          scf_env%outer_scf%deallocate_jacobian = .TRUE.
     604          682 :          IF (ASSOCIATED(scf_env%outer_scf%inv_jacobian)) THEN
     605          152 :             DEALLOCATE (scf_env%outer_scf%inv_jacobian)
     606              :          END IF
     607              :       CASE (ot2cdft)
     608              :          ! OT -> constraint
     609          964 :          scf_control%outer_scf%have_scf = cdft_control%constraint_control%have_scf
     610          964 :          scf_control%outer_scf%max_scf = cdft_control%constraint_control%max_scf
     611          964 :          scf_control%outer_scf%eps_scf = cdft_control%constraint_control%eps_scf
     612          964 :          scf_control%outer_scf%step_size = cdft_control%constraint_control%step_size
     613          964 :          scf_control%outer_scf%type = cdft_control%constraint_control%type
     614          964 :          scf_control%outer_scf%optimizer = cdft_control%constraint_control%optimizer
     615          964 :          scf_control%outer_scf%diis_buffer_length = cdft_control%constraint_control%diis_buffer_length
     616          964 :          scf_control%outer_scf%bisect_trust_count = cdft_control%constraint_control%bisect_trust_count
     617              :          CALL cdft_opt_type_copy(scf_control%outer_scf%cdft_opt_control, &
     618          964 :                                  cdft_control%constraint_control%cdft_opt_control)
     619          964 :          nvariables = SIZE(cdft_control%constraint%variables, 1)
     620          964 :          IF (ASSOCIATED(scf_env%outer_scf%energy)) THEN
     621          964 :             DEALLOCATE (scf_env%outer_scf%energy)
     622              :          END IF
     623         2892 :          ALLOCATE (scf_env%outer_scf%energy(scf_control%outer_scf%max_scf + 1))
     624        13768 :          scf_env%outer_scf%energy = cdft_control%constraint%energy
     625          964 :          IF (ASSOCIATED(scf_env%outer_scf%variables)) THEN
     626          964 :             DEALLOCATE (scf_env%outer_scf%variables)
     627              :          END IF
     628         3856 :          ALLOCATE (scf_env%outer_scf%variables(nvariables, scf_control%outer_scf%max_scf + 1))
     629        26776 :          scf_env%outer_scf%variables = cdft_control%constraint%variables
     630          964 :          IF (ASSOCIATED(scf_env%outer_scf%gradient)) THEN
     631          964 :             DEALLOCATE (scf_env%outer_scf%gradient)
     632              :          END IF
     633         3856 :          ALLOCATE (scf_env%outer_scf%gradient(nvariables, scf_control%outer_scf%max_scf + 1))
     634        26776 :          scf_env%outer_scf%gradient = cdft_control%constraint%gradient
     635          964 :          IF (ASSOCIATED(scf_env%outer_scf%count)) THEN
     636          964 :             DEALLOCATE (scf_env%outer_scf%count)
     637              :          END IF
     638         2892 :          ALLOCATE (scf_env%outer_scf%count(scf_control%outer_scf%max_scf + 1))
     639        13768 :          scf_env%outer_scf%count = cdft_control%constraint%count
     640          964 :          scf_env%outer_scf%iter_count = cdft_control%constraint%iter_count
     641          964 :          scf_env%outer_scf%deallocate_jacobian = cdft_control%constraint%deallocate_jacobian
     642          964 :          IF (ASSOCIATED(cdft_control%constraint%inv_jacobian)) THEN
     643          188 :             IF (ASSOCIATED(scf_env%outer_scf%inv_jacobian)) THEN
     644            0 :                DEALLOCATE (scf_env%outer_scf%inv_jacobian)
     645              :             END IF
     646          752 :             ALLOCATE (scf_env%outer_scf%inv_jacobian(nvariables, nvariables))
     647         1864 :             scf_env%outer_scf%inv_jacobian = cdft_control%constraint%inv_jacobian
     648              :          END IF
     649              :       CASE DEFAULT
     650         1646 :          CPABORT("Switching direction should be either ot2cdft or cdft2ot")
     651              :       END SELECT
     652              : 
     653         1646 :    END SUBROUTINE outer_loop_switch
     654              : 
     655              : ! **************************************************************************************************
     656              : !> \brief purges outer_scf_history zeroing everything except
     657              : !>        the latest value of the outer_scf variable stored in qs_control
     658              : !> \param qs_env the qs_environment_type where to purge
     659              : !> \par History
     660              : !>      05.2016 created [Nico Holmberg]
     661              : ! **************************************************************************************************
     662            0 :    SUBROUTINE outer_loop_purge_history(qs_env)
     663              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     664              : 
     665              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'outer_loop_purge_history'
     666              : 
     667              :       INTEGER                                            :: handle, outer_scf_ihistory
     668            0 :       REAL(kind=dp), DIMENSION(:, :), POINTER            :: gradient_history, outer_scf_history, &
     669            0 :                                                             variable_history
     670              : 
     671            0 :       CALL timeset(routineN, handle)
     672              : 
     673              :       CALL get_qs_env(qs_env, outer_scf_history=outer_scf_history, &
     674              :                       outer_scf_ihistory=outer_scf_ihistory, &
     675              :                       gradient_history=gradient_history, &
     676            0 :                       variable_history=variable_history)
     677            0 :       CPASSERT(SIZE(outer_scf_history, 2) > 0)
     678            0 :       outer_scf_ihistory = 0
     679            0 :       outer_scf_history = 0.0_dp
     680            0 :       gradient_history = 0.0_dp
     681            0 :       variable_history = 0.0_dp
     682            0 :       CALL set_qs_env(qs_env, outer_scf_ihistory=outer_scf_ihistory)
     683              : 
     684            0 :       CALL timestop(handle)
     685              : 
     686            0 :    END SUBROUTINE outer_loop_purge_history
     687              : 
     688          174 : END MODULE qs_outer_scf
        

Generated by: LCOV version 2.0-1