LCOV - code coverage report
Current view: top level - src - qs_active_space_mixing.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:06f838d) Lines: 31.2 % 256 80
Test Date: 2026-06-05 07:04:50 Functions: 55.6 % 9 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 Dense density mixing for active-space embedding.
      10              : ! **************************************************************************************************
      11              : MODULE qs_active_space_mixing
      12              :    USE cp_fm_types,                     ONLY: cp_fm_get_element,&
      13              :                                               cp_fm_set_element,&
      14              :                                               cp_fm_type
      15              :    USE input_section_types,             ONLY: section_vals_get,&
      16              :                                               section_vals_get_subs_vals,&
      17              :                                               section_vals_type,&
      18              :                                               section_vals_val_get
      19              :    USE kinds,                           ONLY: dp
      20              :    USE mathlib,                         ONLY: invert_matrix
      21              :    USE qs_active_space_types,           ONLY: active_space_type
      22              :    USE qs_density_mixing_types,         ONLY: &
      23              :         broyden_mixing_nr, direct_mixing_nr, gspace_mixing_nr, mixing_storage_create, &
      24              :         mixing_storage_type, modified_broyden_mixing_nr, multisecant_mixing_nr, no_mixing_nr, &
      25              :         pulay_mixing_nr
      26              : #include "./base/base_uses.f90"
      27              : 
      28              :    IMPLICIT NONE
      29              :    PRIVATE
      30              : 
      31              :    PUBLIC :: active_space_mixing_label
      32              :    PUBLIC :: initialize_active_space_mixing
      33              :    PUBLIC :: update_active_density
      34              : 
      35              : CONTAINS
      36              : 
      37              : ! **************************************************************************************************
      38              : !> \brief Initialize the density mixer used in the self-consistent active-space embedding loop.
      39              : !> \param active_space_env active space environment
      40              : !> \param as_input ACTIVE_SPACE input section
      41              : ! **************************************************************************************************
      42          328 :    SUBROUTINE initialize_active_space_mixing(active_space_env, as_input)
      43              :       TYPE(active_space_type), POINTER                   :: active_space_env
      44              :       TYPE(section_vals_type), POINTER                   :: as_input
      45              : 
      46              :       LOGICAL                                            :: do_mixing, legacy_alpha_explicit, &
      47              :                                                             mixing_alpha_explicit, mixing_explicit
      48              :       REAL(KIND=dp)                                      :: legacy_alpha
      49              :       TYPE(section_vals_type), POINTER                   :: mixing_section
      50              : 
      51           82 :       NULLIFY (mixing_section)
      52              : 
      53              :       CALL section_vals_val_get(as_input, "ALPHA", r_val=legacy_alpha, &
      54           82 :                                 explicit=legacy_alpha_explicit)
      55           82 :       IF (legacy_alpha < 0.0_dp .OR. legacy_alpha > 1.0_dp) THEN
      56            0 :          CPABORT("Specify an active-space damping factor between 0 and 1.")
      57              :       END IF
      58              : 
      59           82 :       mixing_section => section_vals_get_subs_vals(as_input, "MIXING")
      60           82 :       CALL section_vals_get(mixing_section, explicit=mixing_explicit)
      61           82 :       CALL section_vals_val_get(mixing_section, "_SECTION_PARAMETERS_", l_val=do_mixing)
      62              : 
      63           82 :       active_space_env%as_mixing_dim = 0
      64           82 :       active_space_env%as_mixing_iter = 0
      65              : 
      66           82 :       IF (.NOT. do_mixing) THEN
      67            0 :          active_space_env%as_mixing_method = no_mixing_nr
      68            0 :          active_space_env%alpha = 1.0_dp
      69            0 :          RETURN
      70              :       END IF
      71              : 
      72              :       CALL section_vals_val_get(mixing_section, "METHOD", &
      73           82 :                                 i_val=active_space_env%as_mixing_method)
      74              : 
      75           82 :       SELECT CASE (active_space_env%as_mixing_method)
      76              :       CASE (no_mixing_nr)
      77            0 :          active_space_env%alpha = 1.0_dp
      78            0 :          RETURN
      79              :       CASE (direct_mixing_nr, pulay_mixing_nr, broyden_mixing_nr, modified_broyden_mixing_nr)
      80            0 :          CONTINUE
      81              :       CASE (gspace_mixing_nr)
      82              :          CALL cp_abort(__LOCATION__, &
      83              :                        "ACTIVE_SPACE%MIXING%METHOD KERKER_MIXING is not supported. "// &
      84              :                        "The active-space density lives in the active MO subspace, "// &
      85            0 :                        "not in G-space.")
      86              :       CASE (multisecant_mixing_nr)
      87            0 :          CPABORT("ACTIVE_SPACE%MIXING%METHOD MULTISECANT_MIXING is not yet supported.")
      88              :       CASE DEFAULT
      89           82 :          CPABORT("Unknown ACTIVE_SPACE%MIXING%METHOD.")
      90              :       END SELECT
      91              : 
      92           82 :       IF (ASSOCIATED(active_space_env%as_mixing_store)) THEN
      93            0 :          CPABORT("Active-space mixing storage already initialized.")
      94              :       END IF
      95          246 :       ALLOCATE (active_space_env%as_mixing_store)
      96              :       CALL mixing_storage_create(active_space_env%as_mixing_store, mixing_section, &
      97           82 :                                  active_space_env%as_mixing_method, ecut=0.0_dp)
      98              : 
      99           82 :       CALL section_vals_val_get(mixing_section, "ALPHA", explicit=mixing_alpha_explicit)
     100           82 :       IF ((legacy_alpha_explicit .AND. (.NOT. mixing_alpha_explicit)) .OR. &
     101              :           ((.NOT. mixing_explicit) .AND. (.NOT. mixing_alpha_explicit))) THEN
     102           80 :          active_space_env%as_mixing_store%alpha = legacy_alpha
     103              :       END IF
     104           82 :       IF (active_space_env%as_mixing_store%alpha < 0.0_dp .OR. &
     105              :           active_space_env%as_mixing_store%alpha > 1.0_dp) THEN
     106            0 :          CPABORT("Specify an active-space mixing ALPHA between 0 and 1.")
     107              :       END IF
     108           82 :       IF (active_space_env%as_mixing_store%nbuffer < 1 .AND. &
     109              :           active_space_env%as_mixing_method /= direct_mixing_nr) THEN
     110            0 :          CPABORT("ACTIVE_SPACE%MIXING%NBUFFER has to be positive.")
     111              :       END IF
     112              : 
     113           82 :       active_space_env%alpha = active_space_env%as_mixing_store%alpha
     114              : 
     115              :    END SUBROUTINE initialize_active_space_mixing
     116              : 
     117              : ! **************************************************************************************************
     118              : !> \brief Return the current active-space mixer label for iteration output.
     119              : !> \param active_space_env active space environment
     120              : !> \return short mixer label
     121              : ! **************************************************************************************************
     122            7 :    FUNCTION active_space_mixing_label(active_space_env) RESULT(label)
     123              :       TYPE(active_space_type), POINTER                   :: active_space_env
     124              :       CHARACTER(len=15)                                  :: label
     125              : 
     126           14 :       SELECT CASE (active_space_env%as_mixing_method)
     127              :       CASE (direct_mixing_nr)
     128            7 :          label = "P_Mix"
     129              :       CASE (pulay_mixing_nr)
     130            0 :          label = "Pulay"
     131              :       CASE (broyden_mixing_nr)
     132            0 :          label = "Broy."
     133              :       CASE (modified_broyden_mixing_nr)
     134            0 :          label = "MBroy"
     135              :       CASE DEFAULT
     136            7 :          label = "NoMix"
     137              :       END SELECT
     138            7 :       IF (ASSOCIATED(active_space_env%as_mixing_store)) THEN
     139            7 :          IF (active_space_env%as_mixing_iter > 0 .AND. &
     140              :              LEN_TRIM(active_space_env%as_mixing_store%iter_method) > 0) THEN
     141            4 :             label = active_space_env%as_mixing_store%iter_method
     142              :          END IF
     143              :       END IF
     144              : 
     145            7 :    END FUNCTION active_space_mixing_label
     146              : 
     147              : ! **************************************************************************************************
     148              : !> \brief Release dense active-space mixing history buffers.
     149              : !> \param active_space_env active space environment
     150              : ! **************************************************************************************************
     151            0 :    SUBROUTINE release_active_mixing_history(active_space_env)
     152              :       TYPE(active_space_type), POINTER                   :: active_space_env
     153              : 
     154            0 :       IF (ASSOCIATED(active_space_env%as_mix_r_old)) THEN
     155            0 :          DEALLOCATE (active_space_env%as_mix_r_old)
     156              :       END IF
     157            0 :       IF (ASSOCIATED(active_space_env%as_mix_weight)) THEN
     158            0 :          DEALLOCATE (active_space_env%as_mix_weight)
     159              :       END IF
     160            0 :       IF (ASSOCIATED(active_space_env%as_mix_x_old)) THEN
     161            0 :          DEALLOCATE (active_space_env%as_mix_x_old)
     162              :       END IF
     163            0 :       IF (ASSOCIATED(active_space_env%as_mix_r_buffer)) THEN
     164            0 :          DEALLOCATE (active_space_env%as_mix_r_buffer)
     165              :       END IF
     166            0 :       IF (ASSOCIATED(active_space_env%as_mix_x_buffer)) THEN
     167            0 :          DEALLOCATE (active_space_env%as_mix_x_buffer)
     168              :       END IF
     169            0 :       active_space_env%as_mixing_dim = 0
     170              : 
     171            0 :    END SUBROUTINE release_active_mixing_history
     172              : 
     173              : ! **************************************************************************************************
     174              : !> \brief Ensure dense active-space mixing history buffers are allocated.
     175              : !> \param active_space_env active space environment
     176              : !> \param ndim length of the flattened density vector
     177              : ! **************************************************************************************************
     178            0 :    SUBROUTINE ensure_active_mixing_history(active_space_env, ndim)
     179              :       TYPE(active_space_type), POINTER                   :: active_space_env
     180              :       INTEGER, INTENT(IN)                                :: ndim
     181              : 
     182              :       INTEGER                                            :: nbuffer
     183              :       TYPE(mixing_storage_type), POINTER                 :: mixing_store
     184              : 
     185            0 :       IF (.NOT. ASSOCIATED(active_space_env%as_mixing_store)) RETURN
     186            0 :       IF (active_space_env%as_mixing_method == direct_mixing_nr) RETURN
     187              : 
     188            0 :       mixing_store => active_space_env%as_mixing_store
     189            0 :       nbuffer = mixing_store%nbuffer
     190            0 :       IF (nbuffer < 1) CPABORT("ACTIVE_SPACE%MIXING%NBUFFER has to be positive.")
     191              : 
     192            0 :       IF (active_space_env%as_mixing_dim == ndim .AND. &
     193              :           ASSOCIATED(active_space_env%as_mix_r_buffer)) RETURN
     194              : 
     195            0 :       CALL release_active_mixing_history(active_space_env)
     196              : 
     197            0 :       active_space_env%as_mixing_dim = ndim
     198            0 :       ALLOCATE (active_space_env%as_mix_r_old(ndim))
     199            0 :       ALLOCATE (active_space_env%as_mix_weight(nbuffer))
     200            0 :       ALLOCATE (active_space_env%as_mix_x_old(ndim))
     201            0 :       ALLOCATE (active_space_env%as_mix_r_buffer(nbuffer, ndim))
     202            0 :       ALLOCATE (active_space_env%as_mix_x_buffer(nbuffer, ndim))
     203              : 
     204            0 :       active_space_env%as_mix_r_old = 0.0_dp
     205            0 :       active_space_env%as_mix_weight = 1.0_dp
     206            0 :       active_space_env%as_mix_x_old = 0.0_dp
     207            0 :       active_space_env%as_mix_r_buffer = 0.0_dp
     208            0 :       active_space_env%as_mix_x_buffer = 0.0_dp
     209            0 :       mixing_store%ncall = 0
     210              : 
     211              :    END SUBROUTINE ensure_active_mixing_history
     212              : 
     213              : ! **************************************************************************************************
     214              : !> \brief Apply a direct dense active-space density mix.
     215              : !> \param p_old current active-space density vector
     216              : !> \param p_solver active-space density vector returned by the external solver
     217              : !> \param alpha mixing damping
     218              : !> \param p_mixed mixed active-space density vector
     219              : ! **************************************************************************************************
     220            8 :    SUBROUTINE active_space_direct_mix(p_old, p_solver, alpha, p_mixed)
     221              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: p_old, p_solver
     222              :       REAL(KIND=dp), INTENT(IN)                          :: alpha
     223              :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: p_mixed
     224              : 
     225           64 :       p_mixed = p_old + alpha*(p_solver - p_old)
     226              : 
     227            8 :    END SUBROUTINE active_space_direct_mix
     228              : 
     229              : ! **************************************************************************************************
     230              : !> \brief Apply Pulay mixing to the dense active-space density vector.
     231              : !> \param active_space_env active space environment
     232              : !> \param p_old current active-space density vector
     233              : !> \param p_solver active-space density vector returned by the external solver
     234              : !> \param p_mixed mixed active-space density vector
     235              : ! **************************************************************************************************
     236            0 :    SUBROUTINE active_space_pulay_mixing(active_space_env, p_old, p_solver, p_mixed)
     237              :       TYPE(active_space_type), POINTER                   :: active_space_env
     238              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: p_old, p_solver
     239              :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: p_mixed
     240              : 
     241              :       INTEGER                                            :: i, ib, ibb, j, nb, nbuffer, ndim
     242              :       REAL(KIND=dp)                                      :: inv_err, norm_c_inv, res_norm
     243            0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: alpha_c, p_diis
     244            0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: c, c_inv
     245              :       TYPE(mixing_storage_type), POINTER                 :: mixing_store
     246              : 
     247            0 :       ndim = SIZE(p_old)
     248            0 :       CALL ensure_active_mixing_history(active_space_env, ndim)
     249            0 :       mixing_store => active_space_env%as_mixing_store
     250            0 :       nbuffer = mixing_store%nbuffer
     251              : 
     252            0 :       ib = MODULO(mixing_store%ncall, nbuffer) + 1
     253            0 :       mixing_store%ncall = mixing_store%ncall + 1
     254            0 :       nb = MIN(mixing_store%ncall, nbuffer)
     255            0 :       ibb = MODULO(mixing_store%ncall, nbuffer) + 1
     256              : 
     257            0 :       active_space_env%as_mix_x_buffer(ib, :) = p_old
     258            0 :       active_space_env%as_mix_r_buffer(ib, :) = p_solver - p_old
     259              :       res_norm = SQRT(DOT_PRODUCT(active_space_env%as_mix_r_buffer(ib, :), &
     260            0 :                                   active_space_env%as_mix_r_buffer(ib, :)))
     261              : 
     262            0 :       IF (nb == 1 .OR. res_norm < 1.E-14_dp) THEN
     263            0 :          CALL active_space_direct_mix(p_old, p_solver, mixing_store%alpha, p_mixed)
     264              :       ELSE
     265            0 :          ALLOCATE (c(nb, nb))
     266            0 :          ALLOCATE (c_inv(nb, nb))
     267            0 :          ALLOCATE (alpha_c(nb))
     268            0 :          ALLOCATE (p_diis(ndim))
     269              : 
     270            0 :          c(:, :) = 0.0_dp
     271            0 :          DO i = 1, nb
     272            0 :             DO j = i, nb
     273              :                c(j, i) = DOT_PRODUCT(active_space_env%as_mix_r_buffer(i, :), &
     274            0 :                                      active_space_env%as_mix_r_buffer(j, :))
     275            0 :                c(i, j) = c(j, i)
     276              :             END DO
     277              :          END DO
     278              : 
     279            0 :          CALL invert_matrix(c, c_inv, inv_err, improve=.TRUE.)
     280            0 :          norm_c_inv = SUM(c_inv)
     281            0 :          IF (ABS(norm_c_inv) < 1.E-14_dp) THEN
     282            0 :             CALL active_space_direct_mix(p_old, p_solver, mixing_store%alpha, p_mixed)
     283              :          ELSE
     284            0 :             DO i = 1, nb
     285            0 :                alpha_c(i) = SUM(c_inv(:, i))/norm_c_inv
     286              :             END DO
     287              : 
     288            0 :             p_diis(:) = 0.0_dp
     289            0 :             DO i = 1, nb
     290              :                p_diis(:) = p_diis(:) + alpha_c(i)*(active_space_env%as_mix_x_buffer(i, :) + &
     291            0 :                                                    mixing_store%pulay_beta*active_space_env%as_mix_r_buffer(i, :))
     292              :             END DO
     293            0 :             IF (mixing_store%pulay_alpha > 0.0_dp) THEN
     294              :                p_mixed = mixing_store%pulay_alpha*p_solver + &
     295            0 :                          (1.0_dp - mixing_store%pulay_alpha)*p_diis
     296              :             ELSE
     297            0 :                p_mixed = p_diis
     298              :             END IF
     299              :          END IF
     300              : 
     301            0 :          DEALLOCATE (alpha_c)
     302            0 :          DEALLOCATE (p_diis)
     303            0 :          DEALLOCATE (c)
     304            0 :          DEALLOCATE (c_inv)
     305              :       END IF
     306              : 
     307            0 :       active_space_env%as_mix_x_buffer(ibb, :) = p_mixed
     308            0 :       mixing_store%iter_method = "Pulay"
     309              : 
     310            0 :    END SUBROUTINE active_space_pulay_mixing
     311              : 
     312              : ! **************************************************************************************************
     313              : !> \brief Apply original or modified Broyden mixing to the dense active-space density vector.
     314              : !> \param active_space_env active space environment
     315              : !> \param p_old current active-space density vector
     316              : !> \param p_solver active-space density vector returned by the external solver
     317              : !> \param p_mixed mixed active-space density vector
     318              : !> \param modified use dynamic residual weights of modified Broyden
     319              : ! **************************************************************************************************
     320            0 :    SUBROUTINE active_space_broyden_mixing(active_space_env, p_old, p_solver, p_mixed, modified)
     321              :       TYPE(active_space_type), POINTER                   :: active_space_env
     322              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: p_old, p_solver
     323              :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: p_mixed
     324              :       LOGICAL, INTENT(IN)                                :: modified
     325              : 
     326              :       INTEGER                                            :: ib, j, k, nb, nbuffer, ndim
     327              :       LOGICAL                                            :: can_update
     328              :       REAL(KIND=dp)                                      :: delta_norm, inv_err, res_norm, weight
     329            0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: c, g, p_res
     330            0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: a, b
     331              :       TYPE(mixing_storage_type), POINTER                 :: mixing_store
     332              : 
     333            0 :       ndim = SIZE(p_old)
     334            0 :       CALL ensure_active_mixing_history(active_space_env, ndim)
     335            0 :       mixing_store => active_space_env%as_mixing_store
     336            0 :       nbuffer = mixing_store%nbuffer
     337              : 
     338            0 :       ALLOCATE (p_res(ndim))
     339            0 :       p_res(:) = p_solver(:) - p_old(:)
     340            0 :       res_norm = SQRT(DOT_PRODUCT(p_res, p_res))
     341              : 
     342            0 :       mixing_store%ncall = mixing_store%ncall + 1
     343            0 :       IF (mixing_store%ncall == 1) THEN
     344            0 :          CALL active_space_direct_mix(p_old, p_solver, mixing_store%alpha, p_mixed)
     345            0 :          active_space_env%as_mix_x_old = p_old
     346            0 :          active_space_env%as_mix_r_old = p_res
     347            0 :          IF (modified) THEN
     348            0 :             mixing_store%iter_method = "MBroy"
     349              :          ELSE
     350            0 :             mixing_store%iter_method = "Broy."
     351              :          END IF
     352            0 :          DEALLOCATE (p_res)
     353            0 :          RETURN
     354              :       END IF
     355              : 
     356            0 :       nb = MIN(mixing_store%ncall - 1, nbuffer)
     357            0 :       ib = MODULO(mixing_store%ncall - 2, nbuffer) + 1
     358              : 
     359            0 :       active_space_env%as_mix_r_buffer(ib, :) = p_res - active_space_env%as_mix_r_old
     360            0 :       active_space_env%as_mix_x_buffer(ib, :) = p_old - active_space_env%as_mix_x_old
     361              :       delta_norm = SQRT(DOT_PRODUCT(active_space_env%as_mix_r_buffer(ib, :), &
     362            0 :                                     active_space_env%as_mix_r_buffer(ib, :)))
     363            0 :       can_update = res_norm > 1.E-14_dp .AND. delta_norm > 1.E-14_dp
     364              : 
     365              :       IF (can_update) THEN
     366            0 :          active_space_env%as_mix_r_buffer(ib, :) = active_space_env%as_mix_r_buffer(ib, :)/delta_norm
     367              :          active_space_env%as_mix_x_buffer(ib, :) = active_space_env%as_mix_x_buffer(ib, :)/delta_norm + &
     368            0 :                                                    mixing_store%alpha*active_space_env%as_mix_r_buffer(ib, :)
     369              : 
     370            0 :          IF (modified) THEN
     371            0 :             IF (res_norm > (mixing_store%wc/mixing_store%wmax)) THEN
     372            0 :                active_space_env%as_mix_weight(ib) = mixing_store%wc/res_norm
     373              :             ELSE
     374            0 :                active_space_env%as_mix_weight(ib) = mixing_store%wmax
     375              :             END IF
     376            0 :             active_space_env%as_mix_weight(ib) = MAX(1.0_dp, active_space_env%as_mix_weight(ib))
     377              :          END IF
     378              : 
     379            0 :          ALLOCATE (a(nb, nb))
     380            0 :          ALLOCATE (b(nb, nb))
     381            0 :          ALLOCATE (c(nb))
     382            0 :          ALLOCATE (g(nb))
     383              : 
     384            0 :          a(:, :) = 0.0_dp
     385            0 :          c(:) = 0.0_dp
     386            0 :          DO j = 1, nb
     387            0 :             DO k = j, nb
     388              :                a(k, j) = DOT_PRODUCT(active_space_env%as_mix_r_buffer(j, :), &
     389            0 :                                      active_space_env%as_mix_r_buffer(k, :))
     390            0 :                a(j, k) = a(k, j)
     391              :             END DO
     392              :          END DO
     393              : 
     394            0 :          DO j = 1, nb
     395            0 :             c(j) = DOT_PRODUCT(active_space_env%as_mix_r_buffer(j, :), p_res)
     396            0 :             IF (modified) THEN
     397            0 :                c(j) = active_space_env%as_mix_weight(j)*c(j)
     398            0 :                DO k = 1, nb
     399              :                   a(k, j) = active_space_env%as_mix_weight(k)* &
     400            0 :                             active_space_env%as_mix_weight(j)*a(k, j)
     401              :                END DO
     402            0 :                a(j, j) = mixing_store%broy_w0*mixing_store%broy_w0 + a(j, j)
     403              :             ELSE
     404            0 :                a(j, j) = mixing_store%broy_w0 + a(j, j)
     405              :             END IF
     406              :          END DO
     407              : 
     408            0 :          CALL invert_matrix(a, b, inv_err)
     409            0 :          g(:) = 0.0_dp
     410            0 :          DO j = 1, nb
     411            0 :             DO k = 1, nb
     412            0 :                g(j) = g(j) + b(k, j)*c(k)
     413              :             END DO
     414              :          END DO
     415              : 
     416            0 :          CALL active_space_direct_mix(p_old, p_solver, mixing_store%alpha, p_mixed)
     417            0 :          DO j = 1, nb
     418            0 :             weight = 1.0_dp
     419            0 :             IF (modified) weight = active_space_env%as_mix_weight(j)
     420            0 :             p_mixed = p_mixed - weight*g(j)*active_space_env%as_mix_x_buffer(j, :)
     421              :          END DO
     422              : 
     423            0 :          DEALLOCATE (a)
     424            0 :          DEALLOCATE (b)
     425            0 :          DEALLOCATE (c)
     426            0 :          DEALLOCATE (g)
     427              :       ELSE
     428            0 :          active_space_env%as_mix_r_buffer(ib, :) = 0.0_dp
     429            0 :          active_space_env%as_mix_x_buffer(ib, :) = 0.0_dp
     430            0 :          CALL active_space_direct_mix(p_old, p_solver, mixing_store%alpha, p_mixed)
     431              :       END IF
     432              : 
     433            0 :       active_space_env%as_mix_x_old = p_old
     434            0 :       active_space_env%as_mix_r_old = p_res
     435            0 :       IF (modified) THEN
     436            0 :          mixing_store%iter_method = "MBroy"
     437              :       ELSE
     438            0 :          mixing_store%iter_method = "Broy."
     439              :       END IF
     440              : 
     441            0 :       DEALLOCATE (p_res)
     442              : 
     443            0 :    END SUBROUTINE active_space_broyden_mixing
     444              : 
     445              : ! **************************************************************************************************
     446              : !> \brief Mix the dense active-space density vector.
     447              : !> \param active_space_env active space environment
     448              : !> \param p_old current active-space density vector
     449              : !> \param p_solver active-space density vector returned by the external solver
     450              : !> \param p_mixed mixed active-space density vector
     451              : ! **************************************************************************************************
     452            8 :    SUBROUTINE mix_active_density_vector(active_space_env, p_old, p_solver, p_mixed)
     453              :       TYPE(active_space_type), POINTER                   :: active_space_env
     454              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: p_old, p_solver
     455              :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: p_mixed
     456              : 
     457              :       INTEGER                                            :: active_mix_iter
     458              :       TYPE(mixing_storage_type), POINTER                 :: mixing_store
     459              : 
     460            8 :       IF (active_space_env%as_mixing_method == no_mixing_nr .OR. &
     461              :           .NOT. ASSOCIATED(active_space_env%as_mixing_store)) THEN
     462            0 :          p_mixed = p_solver
     463              :          RETURN
     464              :       END IF
     465              : 
     466            8 :       mixing_store => active_space_env%as_mixing_store
     467            8 :       active_space_env%as_mixing_iter = active_space_env%as_mixing_iter + 1
     468              : 
     469            8 :       IF (active_space_env%as_mixing_iter <= mixing_store%nskip_mixing) THEN
     470            0 :          p_mixed = p_solver
     471            0 :          mixing_store%iter_method = "NoMix"
     472            0 :          RETURN
     473              :       END IF
     474              : 
     475            8 :       active_mix_iter = active_space_env%as_mixing_iter - mixing_store%nskip_mixing
     476            8 :       IF (active_space_env%as_mixing_method == direct_mixing_nr .OR. &
     477              :           active_mix_iter <= mixing_store%n_simple_mix) THEN
     478            8 :          CALL active_space_direct_mix(p_old, p_solver, mixing_store%alpha, p_mixed)
     479            8 :          mixing_store%iter_method = "P_Mix"
     480            8 :          RETURN
     481              :       END IF
     482              : 
     483            0 :       SELECT CASE (active_space_env%as_mixing_method)
     484              :       CASE (pulay_mixing_nr)
     485            0 :          CALL active_space_pulay_mixing(active_space_env, p_old, p_solver, p_mixed)
     486              :       CASE (broyden_mixing_nr)
     487            0 :          CALL active_space_broyden_mixing(active_space_env, p_old, p_solver, p_mixed, .FALSE.)
     488              :       CASE (modified_broyden_mixing_nr)
     489            0 :          CALL active_space_broyden_mixing(active_space_env, p_old, p_solver, p_mixed, .TRUE.)
     490              :       CASE DEFAULT
     491            0 :          CPABORT("Unsupported ACTIVE_SPACE%MIXING%METHOD.")
     492              :       END SELECT
     493              : 
     494              :    END SUBROUTINE mix_active_density_vector
     495              : 
     496              : ! **************************************************************************************************
     497              : !> \brief Update active space density matrix from Fortran arrays
     498              : !> \param p_act_mo_a alpha density matrix in active space MO basis
     499              : !> \param active_space_env active space environment
     500              : !> \param p_act_mo_b beta density matrix in active space MO basis
     501              : !> \author Vladimir Rybkin
     502              : ! **************************************************************************************************
     503            8 :    SUBROUTINE update_active_density(p_act_mo_a, active_space_env, p_act_mo_b)
     504              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: p_act_mo_a
     505              :       TYPE(active_space_type), POINTER                   :: active_space_env
     506              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN), OPTIONAL  :: p_act_mo_b
     507              : 
     508              :       INTEGER                                            :: i1, i2, idx, ispin, m1, m2, nact2, &
     509              :                                                             nmo_active, nspins
     510            8 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: p_mixed, p_old, p_solver
     511              :       TYPE(cp_fm_type), POINTER                          :: p_active
     512              : 
     513            8 :       nmo_active = active_space_env%nmo_active
     514            8 :       nact2 = nmo_active*nmo_active
     515            8 :       nspins = active_space_env%nspins
     516            8 :       CPASSERT(SIZE(p_act_mo_a) == nact2)
     517            8 :       IF (nspins == 2) THEN
     518            6 :          IF (.NOT. PRESENT(p_act_mo_b)) CPABORT("Missing beta active-space density.")
     519            6 :          CPASSERT(SIZE(p_act_mo_b) == nact2)
     520              :       END IF
     521              : 
     522           24 :       ALLOCATE (p_mixed(nspins*nact2))
     523           16 :       ALLOCATE (p_old(nspins*nact2))
     524           16 :       ALLOCATE (p_solver(nspins*nact2))
     525              : 
     526           40 :       p_solver(1:nact2) = p_act_mo_a
     527            8 :       IF (nspins == 2) THEN
     528           30 :          p_solver(nact2 + 1:2*nact2) = p_act_mo_b
     529              :       END IF
     530              : 
     531              :       idx = 0
     532           22 :       DO ispin = 1, nspins
     533           14 :          p_active => active_space_env%p_active(ispin)
     534           50 :          DO i1 = 1, nmo_active
     535           28 :             m1 = active_space_env%active_orbitals(i1, ispin)
     536           98 :             DO i2 = 1, nmo_active
     537           56 :                idx = idx + 1
     538           56 :                m2 = active_space_env%active_orbitals(i2, ispin)
     539           84 :                CALL cp_fm_get_element(p_active, m1, m2, p_old(idx))
     540              :             END DO
     541              :          END DO
     542              :       END DO
     543              : 
     544            8 :       CALL mix_active_density_vector(active_space_env, p_old, p_solver, p_mixed)
     545              : 
     546            8 :       idx = 0
     547           22 :       DO ispin = 1, nspins
     548           14 :          p_active => active_space_env%p_active(ispin)
     549           50 :          DO i1 = 1, nmo_active
     550           28 :             m1 = active_space_env%active_orbitals(i1, ispin)
     551           98 :             DO i2 = 1, nmo_active
     552           56 :                idx = idx + 1
     553           56 :                m2 = active_space_env%active_orbitals(i2, ispin)
     554           84 :                CALL cp_fm_set_element(p_active, m1, m2, p_mixed(idx))
     555              :             END DO
     556              :          END DO
     557              :       END DO
     558              : 
     559            8 :       DEALLOCATE (p_mixed)
     560            8 :       DEALLOCATE (p_old)
     561            8 :       DEALLOCATE (p_solver)
     562              : 
     563            8 :    END SUBROUTINE update_active_density
     564              : 
     565              : END MODULE qs_active_space_mixing
        

Generated by: LCOV version 2.0-1