LCOV - code coverage report
Current view: top level - src - mtlr_u_j_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:21ef868) Lines: 91.2 % 319 291
Test Date: 2026-08-14 07:04:57 Functions: 100.0 % 1 1

            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              : !> \brief   Driver for self-consistent minimum tracking linear response U and J calculations.
       9              : !> \author  Ziwei Chai
      10              : !> \date    29.07.2026
      11              : !> \version 1.0
      12              : ! **************************************************************************************************
      13              : MODULE mtlr_u_j_methods
      14              : 
      15              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      16              :                                               get_atomic_kind
      17              :    USE cp_control_types,                ONLY: dft_control_type
      18              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      19              :                                               cp_logger_get_default_io_unit,&
      20              :                                               cp_logger_type
      21              :    USE force_env_methods,               ONLY: force_env_calc_energy_force
      22              :    USE force_env_types,                 ONLY: force_env_get,&
      23              :                                               force_env_type
      24              :    USE input_constants,                 ONLY: atomic_guess,&
      25              :                                               restart_guess
      26              :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      27              :                                               section_vals_type,&
      28              :                                               section_vals_val_get
      29              :    USE kinds,                           ONLY: dp
      30              :    USE physcon,                         ONLY: evolt
      31              :    USE qs_environment_types,            ONLY: get_qs_env
      32              :    USE qs_kind_types,                   ONLY: qs_kind_type
      33              :    USE scf_control_types,               ONLY: scf_control_type
      34              : #include "./base/base_uses.f90"
      35              : 
      36              :    IMPLICIT NONE
      37              : 
      38              :    PRIVATE
      39              :    PUBLIC :: do_mtlr_u_j
      40              : 
      41              : CONTAINS
      42              : ! **************************************************************************************************
      43              : !> \brief         Driver for self-consistent MTLR U/J iteration.
      44              : !>                Each outer iteration performs:
      45              : !>                  1) one standard ENERGY SCF
      46              : !>                  2) one MTLR evaluation of U and J
      47              : !>                  3) one update of the Hubbard parameters
      48              : !>                until U and J are converged.
      49              : !>                using a method based on Lowdin charges
      50              : !>                \f[Q = S^{1/2} P S^{1/2}\f]
      51              : !>                where \b P and \b S are the density and the
      52              : !>                overlap matrix, respectively.
      53              : !> \param[in,out] force_env ...
      54              : !> \date          29.07.2026
      55              : !> \author        Ziwei Chai
      56              : !> \version       1.0
      57              : ! **************************************************************************************************
      58            4 :    SUBROUTINE do_mtlr_u_j(force_env)
      59              : 
      60              :       TYPE(force_env_type), INTENT(INOUT), POINTER       :: force_env
      61              : 
      62              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'do_mtlr_u_j'
      63              : 
      64              :       INTEGER                                            :: handle, ikind, k, max_mtlr_iter, n, &
      65              :                                                             nkind, output_unit, p_iter, u_iter
      66            4 :       INTEGER, DIMENSION(:), POINTER                     :: atom_list
      67              :       LOGICAL                                            :: any_dft_plus_u, any_mtlr_kind, &
      68              :                                                             converged, do_reference_scf, &
      69              :                                                             wfn_restart_file_explicit
      70              :       LOGICAL, ALLOCATABLE, DIMENSION(:)                 :: mtlr_kind
      71              :       REAL(KIND=dp) :: delta_j, delta_u, denominator_minus, denominator_plus, eps_u_j_loop, &
      72              :          fhxc_minus, fhxc_plus, intercept_minus, intercept_plus, l, max_delta_j, max_delta_u, &
      73              :          std_j, std_minus, std_plus, std_u, sum_trq_minus, sum_trq_minus_x_trq_minus, &
      74              :          sum_trq_minus_x_vhxc_minus, sum_trq_plus, sum_trq_plus_x_trq_plus, &
      75              :          sum_trq_plus_x_vhxc_plus, sum_vhxc_minus, sum_vhxc_plus
      76            4 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: j_new, j_old, perturbation_strength, &
      77            4 :                                                             trq_minus, trq_plus, u_new, u_old, &
      78            4 :                                                             vhxc_minus, vhxc_plus
      79            4 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
      80              :       TYPE(cp_logger_type), POINTER                      :: logger
      81              :       TYPE(dft_control_type), POINTER                    :: dft_control
      82            4 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
      83              :       TYPE(scf_control_type), POINTER                    :: scf_control
      84              :       TYPE(section_vals_type), POINTER                   :: dft_section, force_env_section
      85              : 
      86            4 :       CALL timeset(routineN, handle)
      87              : 
      88            4 :       NULLIFY (atom_list, qs_kind_set, dft_control, logger, dft_section, force_env_section)
      89              : 
      90            4 :       logger => cp_get_default_logger()
      91            4 :       output_unit = cp_logger_get_default_io_unit(logger)
      92              : 
      93            4 :       CPASSERT(ASSOCIATED(force_env))
      94            4 :       CPASSERT(ASSOCIATED(force_env%qs_env))
      95              : 
      96              :       CALL get_qs_env(force_env%qs_env, &
      97              :                       qs_kind_set=qs_kind_set, &
      98              :                       dft_control=dft_control, &
      99              :                       scf_control=scf_control, &
     100            4 :                       atomic_kind_set=atomic_kind_set)
     101              : 
     102            4 :       CPASSERT(ASSOCIATED(atomic_kind_set))
     103            4 :       CPASSERT(ASSOCIATED(dft_control))
     104            4 :       CPASSERT(ASSOCIATED(qs_kind_set))
     105            4 :       CPASSERT(ASSOCIATED(scf_control))
     106              : 
     107            4 :       nkind = SIZE(atomic_kind_set)
     108            4 :       IF (SIZE(qs_kind_set) /= nkind) THEN
     109            0 :          CPABORT("The atomic-kind and Quickstep-kind arrays have inconsistent sizes.")
     110              :       END IF
     111           12 :       ALLOCATE (mtlr_kind(nkind))
     112            4 :       mtlr_kind(:) = .FALSE.
     113            4 :       any_dft_plus_u = .FALSE.
     114            4 :       any_mtlr_kind = .FALSE.
     115            8 :       DO ikind = 1, nkind
     116            4 :          IF (.NOT. ASSOCIATED(qs_kind_set(ikind)%dft_plus_u)) CYCLE
     117            4 :          any_dft_plus_u = .TRUE.
     118            8 :          IF (qs_kind_set(ikind)%dft_plus_u%do_mtlr) THEN
     119            4 :             mtlr_kind(ikind) = .TRUE.
     120            4 :             any_mtlr_kind = .TRUE.
     121              :          END IF
     122              :       END DO
     123            4 :       IF (.NOT. any_dft_plus_u) THEN
     124              :          CALL cp_abort(__LOCATION__, "RUN_TYPE MTLR requires at least one active "// &
     125            0 :                        "DFT_PLUS_U section.")
     126              :       END IF
     127            4 :       IF (.NOT. any_mtlr_kind) THEN
     128              :          CALL cp_abort(__LOCATION__, "RUN_TYPE MTLR requires an active "// &
     129            0 :                        "MINIMUM_TRACKING_LINEAR_RESPONSE subsection.")
     130              :       END IF
     131              : 
     132            4 :       CALL force_env_get(force_env, force_env_section=force_env_section)
     133            4 :       dft_section => section_vals_get_subs_vals(force_env_section, "DFT")
     134              :       CALL section_vals_val_get(dft_section, "WFN_RESTART_FILE_NAME", &
     135            4 :                                 explicit=wfn_restart_file_explicit)
     136            4 :       IF (wfn_restart_file_explicit) THEN
     137              :          CALL cp_abort(__LOCATION__, "MTLR does not allow an explicit WFN_RESTART_FILE_NAME. "// &
     138            0 :                        "Remove this keyword; the reference WFN is managed internally.")
     139              :       END IF
     140              : 
     141            4 :       SELECT CASE (scf_control%density_guess)
     142              :       CASE (restart_guess)
     143            0 :          do_reference_scf = .TRUE.
     144              :       CASE (atomic_guess)
     145            0 :          do_reference_scf = .FALSE.
     146              :       CASE DEFAULT
     147            4 :          CPABORT("MTLR requires SCF_GUESS RESTART or SCF_GUESS ATOMIC.")
     148              :       END SELECT
     149              : 
     150            4 :       IF (output_unit > 0) THEN
     151            2 :          WRITE (UNIT=output_unit, FMT="(/,T2,78('='))")
     152              :          WRITE (UNIT=output_unit, FMT="(T2,A)") &
     153            2 :             "MTLR| SCF initialization settings"
     154            2 :          WRITE (UNIT=output_unit, FMT="(T2,78('-'))")
     155            2 :          IF (scf_control%density_guess == restart_guess) THEN
     156              :             WRITE (UNIT=output_unit, FMT="(T2,A,T68,A12)") &
     157            2 :                "MTLR| SCF initial guess:", "RESTART"
     158              :             WRITE (UNIT=output_unit, FMT="(T2,A,T68,A12)") &
     159            2 :                "MTLR| QS extrapolation:", "USE_GUESS"
     160              :             WRITE (UNIT=output_unit, FMT="(T2,A)") &
     161            2 :                "MTLR| A reference SCF will precede each U/J iteration."
     162              :             WRITE (UNIT=output_unit, FMT="(T2,A)") &
     163            2 :                "MTLR| Every perturbation SCF will restart from the reference WFN."
     164              :          ELSE
     165              :             WRITE (UNIT=output_unit, FMT="(T2,A,T68,A12)") &
     166            0 :                "MTLR| SCF initial guess:", "ATOMIC"
     167              :             WRITE (UNIT=output_unit, FMT="(T2,A,T68,A12)") &
     168            0 :                "MTLR| QS extrapolation:", "USE_GUESS"
     169              :             WRITE (UNIT=output_unit, FMT="(T2,A)") &
     170            0 :                "MTLR| No separate reference SCF will be performed."
     171              :             WRITE (UNIT=output_unit, FMT="(T2,A)") &
     172            0 :                "MTLR| Every perturbation SCF will start from an atomic guess."
     173              :          END IF
     174            2 :          WRITE (UNIT=output_unit, FMT="(T2,78('='))")
     175              :       END IF
     176              : 
     177           12 :       ALLOCATE (u_new(nkind))
     178            8 :       ALLOCATE (j_new(nkind))
     179            8 :       ALLOCATE (u_old(nkind))
     180            8 :       ALLOCATE (j_old(nkind))
     181            4 :       u_new(:) = 0.0_dp
     182            4 :       j_new(:) = 0.0_dp
     183            4 :       u_old(:) = 0.0_dp
     184            4 :       j_old(:) = 0.0_dp
     185            4 :       converged = .FALSE.
     186            4 :       eps_u_j_loop = dft_control%eps_u_j_loop
     187            4 :       max_mtlr_iter = dft_control%max_mtlr_iter
     188            4 :       IF (dft_control%nspins /= 2) THEN
     189            0 :          CPABORT("Unrestricted KS has to be used (the number of spin channels should be 2).")
     190              :       END IF
     191            4 :       IF (max_mtlr_iter < 1) THEN
     192            0 :          CPABORT("MAX_MTLR_LOOP must be at least one.")
     193              :       END IF
     194            4 :       IF (eps_u_j_loop <= 0.0_dp) THEN
     195            0 :          CPABORT("EPS_U_J_LOOP must be positive.")
     196              :       END IF
     197              : 
     198              :       ! Ensure that the DFT+U+J machinery remains active during the
     199              :       ! initial MTLR calculation, even when a parameter starts from zero.
     200            8 :       DO ikind = 1, nkind
     201            4 :          IF (.NOT. mtlr_kind(ikind)) CYCLE
     202            4 :          IF (qs_kind_set(ikind)%dft_plus_u%u_minus_j == 0.0_dp) THEN
     203            0 :             qs_kind_set(ikind)%dft_plus_u%u_minus_j = EPSILON(1.0_dp)
     204              :          END IF
     205            4 :          IF (qs_kind_set(ikind)%dft_plus_u%hund_j == 0.0_dp) THEN
     206            0 :             qs_kind_set(ikind)%dft_plus_u%hund_j = EPSILON(1.0_dp)
     207              :          END IF
     208            4 :          j_old(ikind) = qs_kind_set(ikind)%dft_plus_u%hund_j
     209              :          u_old(ikind) = qs_kind_set(ikind)%dft_plus_u%u_minus_j + &
     210            8 :                         qs_kind_set(ikind)%dft_plus_u%hund_j
     211              :       END DO
     212              : 
     213           10 :       DO u_iter = 1, max_mtlr_iter
     214              : 
     215           10 :          dft_control%mtlr_dft_with_perturbation = .FALSE.
     216              : 
     217           10 :          IF (do_reference_scf) THEN
     218           10 :             IF (output_unit > 0) THEN
     219            5 :                WRITE (UNIT=output_unit, FMT="(/,T2,78('='))")
     220              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
     221            5 :                   "MTLR| Starting the unperturbed reference SCF."
     222              :                WRITE (UNIT=output_unit, FMT="(T2,A,T72,I8)") &
     223            5 :                   "MTLR| U/J iteration:", u_iter
     224            5 :                WRITE (UNIT=output_unit, FMT="(T2,78('='))")
     225              :             END IF
     226           10 :             CALL force_env_calc_energy_force(force_env, calc_force=.FALSE.)
     227              :          END IF
     228              : 
     229           20 :          DO ikind = 1, nkind
     230              : 
     231           10 :             IF (.NOT. mtlr_kind(ikind)) CYCLE
     232           10 :             CALL get_atomic_kind(atomic_kind_set(ikind), atom_list=atom_list)
     233           10 :             IF (.NOT. ANY(atom_list == qs_kind_set(ikind)%dft_plus_u%lr_atom)) THEN
     234            0 :                CPABORT("INDEX_PERTURBED_ATOM does not belong to the KIND containing the MTLR section.")
     235              :             END IF
     236           10 :             IF (.NOT. ALLOCATED( &
     237              :                 qs_kind_set(ikind)%dft_plus_u%perturbation_strength)) THEN
     238            0 :                CPABORT("MTLR target does not contain perturbation strengths.")
     239              :             END IF
     240              : 
     241           10 :             dft_control%mtlr_ikind = ikind
     242              : 
     243           10 :             n = SIZE(qs_kind_set(ikind)%dft_plus_u%perturbation_strength)
     244           10 :             IF (n < 3) THEN
     245            0 :                CPABORT("MTLR linear regression requires at least three perturbation strengths.")
     246              :             END IF
     247           10 :             l = REAL(n, dp)
     248           30 :             ALLOCATE (perturbation_strength(n))
     249           20 :             ALLOCATE (trq_plus(n))
     250           20 :             ALLOCATE (vhxc_plus(n))
     251           20 :             ALLOCATE (trq_minus(n))
     252           20 :             ALLOCATE (vhxc_minus(n))
     253           10 :             trq_plus = 0.0_dp
     254           10 :             trq_minus = 0.0_dp
     255           10 :             vhxc_plus = 0.0_dp
     256           10 :             vhxc_minus = 0.0_dp
     257           10 :             sum_trq_plus = 0.0_dp
     258           10 :             sum_vhxc_plus = 0.0_dp
     259           10 :             sum_trq_plus_x_trq_plus = 0.0_dp
     260           10 :             sum_trq_plus_x_vhxc_plus = 0.0_dp
     261           10 :             sum_trq_minus = 0.0_dp
     262           10 :             sum_vhxc_minus = 0.0_dp
     263           10 :             sum_trq_minus_x_trq_minus = 0.0_dp
     264           10 :             sum_trq_minus_x_vhxc_minus = 0.0_dp
     265           10 :             std_plus = 0.0_dp
     266           10 :             std_minus = 0.0_dp
     267           60 :             perturbation_strength(:) = qs_kind_set(ikind)%dft_plus_u%perturbation_strength(:)
     268              : 
     269           60 :             DO p_iter = 1, n
     270              : 
     271           50 :                IF (output_unit > 0) THEN
     272           25 :                   WRITE (UNIT=output_unit, FMT="(/,T2,78('='))")
     273              :                   WRITE (UNIT=output_unit, FMT="(T2,A,T72,I8)") &
     274           25 :                      "MTLR| U/J iteration:", u_iter
     275              :                   WRITE (UNIT=output_unit, FMT="(T2,A,T74,I1,A4,I1)") &
     276           25 :                      "MTLR| Perturbation SCF:", p_iter, " of ", n
     277              :                   WRITE (UNIT=output_unit, FMT="(T2,A,T72,I8)") &
     278           25 :                      "MTLR| Target KIND index:", ikind
     279              :                   WRITE (UNIT=output_unit, FMT="(T2,A,T72,I8)") &
     280           25 :                      "MTLR| Target atom index:", &
     281           50 :                      qs_kind_set(ikind)%dft_plus_u%lr_atom
     282              :                   WRITE (UNIT=output_unit, FMT="(T2,A,T63,F14.8,A3)") &
     283           25 :                      "MTLR| Perturbation strength:", &
     284           50 :                      perturbation_strength(p_iter)*evolt, " eV"
     285           25 :                   WRITE (UNIT=output_unit, FMT="(T2,78('='))")
     286              :                END IF
     287              : 
     288           50 :                dft_control%perturbation_strength = perturbation_strength(p_iter)
     289           50 :                dft_control%mtlr_dft_with_perturbation = .TRUE.
     290              : 
     291           50 :                CALL force_env_calc_energy_force(force_env, calc_force=.FALSE.)
     292              : 
     293           50 :                trq_plus(p_iter) = dft_control%trq(1) + dft_control%trq(2)
     294           50 :                trq_minus(p_iter) = dft_control%trq(1) - dft_control%trq(2)
     295           50 :                vhxc_plus(p_iter) = dft_control%vhxc(1) + dft_control%vhxc(2)
     296           60 :                vhxc_minus(p_iter) = dft_control%vhxc(1) - dft_control%vhxc(2)
     297              : 
     298              :             END DO
     299              : 
     300              :             !Calculate all the number about vhxc and trq.
     301           60 :             DO k = 1, n
     302           50 :                sum_trq_plus_x_vhxc_plus = sum_trq_plus_x_vhxc_plus + trq_plus(k)*vhxc_plus(k)
     303           50 :                sum_trq_plus = sum_trq_plus + trq_plus(k)
     304           50 :                sum_vhxc_plus = sum_vhxc_plus + vhxc_plus(k)
     305           60 :                sum_trq_plus_x_trq_plus = sum_trq_plus_x_trq_plus + trq_plus(k)*trq_plus(k)
     306              :             END DO
     307              : 
     308           60 :             DO k = 1, n
     309           50 :                sum_trq_minus_x_vhxc_minus = sum_trq_minus_x_vhxc_minus + trq_minus(k)*vhxc_minus(k)
     310           50 :                sum_trq_minus = sum_trq_minus + trq_minus(k)
     311           50 :                sum_vhxc_minus = sum_vhxc_minus + vhxc_minus(k)
     312           60 :                sum_trq_minus_x_trq_minus = sum_trq_minus_x_trq_minus + trq_minus(k)*trq_minus(k)
     313              :             END DO
     314              : 
     315           10 :             denominator_plus = l*sum_trq_plus_x_trq_plus - sum_trq_plus**2.0_dp
     316           10 :             denominator_minus = l*sum_trq_minus_x_trq_minus - sum_trq_minus**2.0_dp
     317           10 :             IF (ABS(denominator_plus) < 100.0_dp*EPSILON(1.0_dp)) THEN
     318            0 :                CPABORT("MTLR regression is singular.")
     319              :             END IF
     320           10 :             IF (ABS(denominator_minus) < 100.0_dp*EPSILON(1.0_dp)) THEN
     321            0 :                CPABORT("MTLR regression is singular.")
     322              :             END IF
     323              :             fhxc_minus = (l*sum_trq_minus_x_vhxc_minus - sum_trq_minus*sum_vhxc_minus) &
     324           10 :                          /denominator_minus
     325              :             fhxc_plus = (l*sum_trq_plus_x_vhxc_plus - sum_trq_plus*sum_vhxc_plus) &
     326           10 :                         /denominator_plus
     327           10 :             intercept_minus = (sum_vhxc_minus - fhxc_minus*sum_trq_minus)/l
     328           10 :             intercept_plus = (sum_vhxc_plus - fhxc_plus*sum_trq_plus)/l
     329           60 :             DO k = 1, n
     330           60 :                std_minus = std_minus + (vhxc_minus(k) - (trq_minus(k)*fhxc_minus + intercept_minus))**2/(l - 2)
     331              :             END DO
     332           60 :             DO k = 1, n
     333           60 :                std_plus = std_plus + (vhxc_plus(k) - (trq_plus(k)*fhxc_plus + intercept_plus))**2/(l - 2)
     334              :             END DO
     335           10 :             std_minus = SQRT(std_minus)
     336           10 :             std_plus = SQRT(std_plus)
     337              : 
     338           10 :             u_new(ikind) = 0.5_dp*fhxc_plus
     339           10 :             j_new(ikind) = -0.5_dp*fhxc_minus
     340           10 :             delta_u = u_new(ikind) - u_old(ikind)
     341           10 :             delta_j = j_new(ikind) - j_old(ikind)
     342           10 :             std_u = 0.5_dp*std_plus
     343           10 :             std_j = 0.5_dp*std_minus
     344              : 
     345           10 :             IF (output_unit > 0) THEN
     346            5 :                WRITE (UNIT=output_unit, FMT="(/,T2,78('='))")
     347              :                WRITE (UNIT=output_unit, FMT="(T2,A,I0,A,I0,A)") &
     348            5 :                   "MTLR| U/J iteration ", u_iter, &
     349           10 :                   " results for KIND ", ikind, "."
     350            5 :                WRITE (UNIT=output_unit, FMT="(T2,78('-'))")
     351              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
     352            5 :                   "MTLR| Linear-regression data for Hubbard U"
     353              :                WRITE (UNIT=output_unit, &
     354              :                       FMT="(T2,A3,T8,A10,T22,A12,T37,A13,T52,A13,T67,A13)") &
     355            5 :                   "Pt", &
     356            5 :                   "Pert.[eV]", &
     357            5 :                   "trq(+)", &
     358            5 :                   "vhxc(+)[eV]", &
     359            5 :                   "vhxc(+)-fit", &
     360           10 :                   "vhxc(+)-resid"
     361           30 :                DO k = 1, n
     362              :                   WRITE (UNIT=output_unit, &
     363              :                          FMT="(T2,I3,T8,F10.4,T22,ES12.4,T37,ES13.5,"// &
     364              :                          " T52,ES13.5,T67,ES13.4)") &
     365           25 :                      k, &
     366           25 :                      perturbation_strength(k)*evolt, &
     367           25 :                      trq_plus(k), &
     368           25 :                      vhxc_plus(k)*evolt, &
     369           25 :                      (fhxc_plus*trq_plus(k) + intercept_plus)*evolt, &
     370              :                      (vhxc_plus(k) - &
     371           55 :                       (fhxc_plus*trq_plus(k) + intercept_plus))*evolt
     372              :                END DO
     373            5 :                WRITE (UNIT=output_unit, FMT="(T2,78('-'))")
     374              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
     375            5 :                   "MTLR| Linear-regression data for Hund J"
     376              :                WRITE (UNIT=output_unit, &
     377              :                       FMT="(T2,A3,T8,A10,T22,A12,T37,A13,T52,A13,T67,A13)") &
     378            5 :                   "Pt", &
     379            5 :                   "Pert.[eV]", &
     380            5 :                   "trq(-)", &
     381            5 :                   "vhxc(-)[eV]", &
     382            5 :                   "vhxc(-)-fit", &
     383           10 :                   "vhxc(-)-resid"
     384           30 :                DO k = 1, n
     385              :                   WRITE (UNIT=output_unit, &
     386              :                          FMT="(T2,I3,T8,F10.4,T22,ES12.4,T37,ES13.5,"// &
     387              :                          " T52,ES13.5,T67,ES13.4)") &
     388           25 :                      k, &
     389           25 :                      perturbation_strength(k)*evolt, &
     390           25 :                      trq_minus(k), &
     391           25 :                      vhxc_minus(k)*evolt, &
     392           25 :                      (fhxc_minus*trq_minus(k) + intercept_minus)*evolt, &
     393              :                      (vhxc_minus(k) - &
     394           55 :                       (fhxc_minus*trq_minus(k) + intercept_minus))*evolt
     395              :                END DO
     396            5 :                WRITE (UNIT=output_unit, FMT="(T2,78('-'))")
     397              :                WRITE (UNIT=output_unit, &
     398              :                       FMT="(T2,A,T22,A16,T43,A16,T64,A16)") &
     399            5 :                   "MTLR| Parameter", &
     400            5 :                   "Old [eV]", &
     401            5 :                   "New [eV]", &
     402           10 :                   "Change [eV]"
     403            5 :                WRITE (UNIT=output_unit, FMT="(T2,78('-'))")
     404              :                WRITE (UNIT=output_unit, &
     405              :                       FMT="(T2,A,T22,ES16.8,T43,ES16.8,T64,ES16.8)") &
     406            5 :                   "MTLR| Hubbard U", &
     407            5 :                   u_old(ikind)*evolt, &
     408            5 :                   u_new(ikind)*evolt, &
     409           10 :                   (u_new(ikind) - u_old(ikind))*evolt
     410              :                WRITE (UNIT=output_unit, &
     411              :                       FMT="(T2,A,T22,ES16.8,T43,ES16.8,T64,ES16.8)") &
     412            5 :                   "MTLR| Hund J", &
     413            5 :                   j_old(ikind)*evolt, &
     414            5 :                   j_new(ikind)*evolt, &
     415           10 :                   (j_new(ikind) - j_old(ikind))*evolt
     416            5 :                WRITE (UNIT=output_unit, FMT="(T2,78('-'))")
     417              :                WRITE (UNIT=output_unit, FMT="(T2,A,T61,ES16.8,A3)") &
     418            5 :                   "MTLR| Absolute change in U:", &
     419           10 :                   ABS(u_new(ikind) - u_old(ikind))*evolt, " eV"
     420              :                WRITE (UNIT=output_unit, FMT="(T2,A,T61,ES16.8,A3)") &
     421            5 :                   "MTLR| Absolute change in J:", &
     422           10 :                   ABS(j_new(ikind) - j_old(ikind))*evolt, " eV"
     423              :                WRITE (UNIT=output_unit, FMT="(T2,A,T61,ES16.8,A3)") &
     424            5 :                   "MTLR| U fit residual:", &
     425           10 :                   std_u*evolt, " eV"
     426              :                WRITE (UNIT=output_unit, FMT="(T2,A,T61,ES16.8,A3)") &
     427            5 :                   "MTLR| J fit residual:", &
     428           10 :                   std_j*evolt, " eV"
     429            5 :                WRITE (UNIT=output_unit, FMT="(T2,78('='))")
     430              :             END IF
     431              : 
     432           10 :             DEALLOCATE (perturbation_strength)
     433           10 :             DEALLOCATE (trq_plus)
     434           10 :             DEALLOCATE (vhxc_plus)
     435           10 :             DEALLOCATE (trq_minus)
     436           20 :             DEALLOCATE (vhxc_minus)
     437              : 
     438              :          END DO
     439              : 
     440           20 :          DO ikind = 1, nkind
     441           10 :             IF (.NOT. mtlr_kind(ikind)) CYCLE
     442           10 :             qs_kind_set(ikind)%dft_plus_u%u_minus_j = u_new(ikind) - j_new(ikind)
     443           20 :             qs_kind_set(ikind)%dft_plus_u%hund_j = j_new(ikind)
     444              :          END DO
     445              : 
     446           30 :          max_delta_u = MAXVAL(ABS(PACK(u_new(:) - u_old(:), mtlr_kind)))
     447           30 :          max_delta_j = MAXVAL(ABS(PACK(j_new(:) - j_old(:), mtlr_kind)))
     448           10 :          IF (max_delta_u < eps_u_j_loop .AND. max_delta_j < eps_u_j_loop) THEN
     449            4 :             converged = .TRUE.
     450              :          END IF
     451              : 
     452           10 :          IF (output_unit > 0) THEN
     453            5 :             WRITE (UNIT=output_unit, FMT="(/,T2,78('='))")
     454              : 
     455              :             WRITE (UNIT=output_unit, FMT="(T2,A,I0,A)") &
     456            5 :                "MTLR| Iteration ", u_iter, &
     457           10 :                " completed for all atomic kinds."
     458              : 
     459            5 :             WRITE (UNIT=output_unit, FMT="(T2,78('-'))")
     460              : 
     461              :             WRITE (UNIT=output_unit, FMT="(T2,A,ES16.8,A)") &
     462            5 :                "MTLR| Maximum change in U:          ", &
     463           10 :                max_delta_u*evolt, " eV"
     464              : 
     465              :             WRITE (UNIT=output_unit, FMT="(T2,A,ES16.8,A)") &
     466            5 :                "MTLR| Maximum change in J:          ", &
     467           10 :                max_delta_j*evolt, " eV"
     468              : 
     469              :             WRITE (UNIT=output_unit, FMT="(T2,A,ES16.8,A)") &
     470            5 :                "MTLR| Convergence threshold:        ", &
     471           10 :                eps_u_j_loop*evolt, " eV"
     472              : 
     473            5 :             WRITE (UNIT=output_unit, FMT="(T2,78('-'))")
     474              : 
     475            5 :             IF (converged) THEN
     476              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
     477            2 :                   "MTLR| U and J have converged."
     478              : 
     479              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
     480            2 :                   "MTLR| Both maximum changes are below the convergence threshold."
     481              : 
     482            3 :             ELSE IF (u_iter < max_mtlr_iter) THEN
     483              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
     484            3 :                   "MTLR| U and J have not yet converged."
     485              : 
     486              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
     487            3 :                   "MTLR| Proceeding to the next linear-response U/J iteration."
     488              : 
     489              :             ELSE
     490              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
     491            0 :                   "MTLR| U and J have not converged."
     492              : 
     493              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
     494            0 :                   "MTLR| The maximum number of MTLR iterations has been reached."
     495              :             END IF
     496              : 
     497            5 :             WRITE (UNIT=output_unit, FMT="(T2,78('='))")
     498              :          END IF
     499              : 
     500           10 :          IF (converged) THEN
     501            4 :             IF (output_unit > 0) THEN
     502            2 :                WRITE (UNIT=output_unit, FMT="(/,T2,78('*'))")
     503              :                WRITE (UNIT=output_unit, FMT="(T2,A,I0,A)") &
     504            2 :                   "MTLR| U and J converged after ", &
     505            4 :                   u_iter, " iterations."
     506            2 :                WRITE (UNIT=output_unit, FMT="(T2,78('*'),/)")
     507              :             END IF
     508            6 :          ELSE IF (u_iter == max_mtlr_iter) THEN
     509            0 :             IF (output_unit > 0) THEN
     510            0 :                WRITE (UNIT=output_unit, FMT="(/,T2,78('*'))")
     511              :                WRITE (UNIT=output_unit, FMT="(T2,A,I0,A)") &
     512            0 :                   "MTLR| U and J did not converge within the maximum of ", &
     513            0 :                   max_mtlr_iter, " iterations."
     514              :                WRITE (UNIT=output_unit, FMT="(T2,A)") &
     515            0 :                   "MTLR| Results from the final iteration will be reported."
     516            0 :                WRITE (UNIT=output_unit, FMT="(T2,78('*'),/)")
     517              :             END IF
     518              :          END IF
     519              : 
     520           10 :          IF (converged .OR. u_iter == max_mtlr_iter) THEN
     521            4 :             IF (output_unit > 0) THEN
     522            2 :                WRITE (UNIT=output_unit, FMT="(/,T2,78('*'))")
     523              :                WRITE (UNIT=output_unit, FMT="(T2,A,ES16.8,A)") &
     524            2 :                   "MTLR| Maximum change in U:          ", &
     525            4 :                   max_delta_u*evolt, " eV"
     526              :                WRITE (UNIT=output_unit, FMT="(T2,A,ES16.8,A)") &
     527            2 :                   "MTLR| Maximum change in J:          ", &
     528            4 :                   max_delta_j*evolt, " eV"
     529              :                WRITE (UNIT=output_unit, FMT="(T2,A,ES16.8,A)") &
     530            2 :                   "MTLR| Maximum change over U and J: ", &
     531            4 :                   MAX(max_delta_u, max_delta_j)*evolt, " eV"
     532            2 :                WRITE (UNIT=output_unit, FMT="(T2,78('*'))")
     533            4 :                DO ikind = 1, nkind
     534            2 :                   IF (.NOT. mtlr_kind(ikind)) CYCLE
     535              :                   WRITE (UNIT=output_unit, FMT="(/,T2,A,I0,A)") &
     536            2 :                      "MTLR| Final parameters for KIND ", ikind, ":"
     537              :                   WRITE (UNIT=output_unit, FMT="(T2,A,F16.8,A)") &
     538            2 :                      "MTLR| Calculated Hubbard U:      ", &
     539            4 :                      u_new(ikind)*evolt, " eV"
     540              :                   WRITE (UNIT=output_unit, FMT="(T2,A,F16.8,A)") &
     541            2 :                      "MTLR| Calculated Hund J:         ", &
     542            4 :                      j_new(ikind)*evolt, " eV"
     543              :                   WRITE (UNIT=output_unit, FMT="(T2,A)") &
     544            2 :                      "MTLR| Recommended CP2K input parameters:"
     545              :                   WRITE (UNIT=output_unit, FMT="(T2,A,F16.8)") &
     546            2 :                      "MTLR|   U_MINUS_J [eV]           ", &
     547            4 :                      (u_new(ikind) - j_new(ikind))*evolt
     548              :                   WRITE (UNIT=output_unit, FMT="(T2,A,F16.8)") &
     549            2 :                      "MTLR|   J         [eV]           ", &
     550            6 :                      j_new(ikind)*evolt
     551              :                END DO
     552            2 :                WRITE (UNIT=output_unit, FMT="(/,T2,78('*'),/)")
     553              :             END IF
     554              :          END IF
     555              : 
     556           10 :          IF (converged) THEN
     557              :             EXIT
     558              :          END IF
     559              : 
     560           12 :          u_old(:) = u_new
     561           16 :          j_old(:) = j_new
     562              : 
     563              :       END DO
     564              : 
     565            8 :       DO ikind = 1, nkind
     566            4 :          IF (.NOT. mtlr_kind(ikind)) CYCLE
     567            4 :          qs_kind_set(ikind)%dft_plus_u%u_minus_j = u_new(ikind) - j_new(ikind)
     568            8 :          qs_kind_set(ikind)%dft_plus_u%hund_j = j_new(ikind)
     569              :       END DO
     570            4 :       dft_control%mtlr_dft_with_perturbation = .FALSE.
     571            4 :       dft_control%perturbation_strength = 0.0_dp
     572              : 
     573            4 :       CALL force_env_calc_energy_force(force_env, calc_force=.FALSE.)
     574              : 
     575            4 :       DEALLOCATE (u_new)
     576            4 :       DEALLOCATE (j_new)
     577            4 :       DEALLOCATE (u_old)
     578            4 :       DEALLOCATE (j_old)
     579            4 :       DEALLOCATE (mtlr_kind)
     580              : 
     581            4 :       CALL timestop(handle)
     582              : 
     583           12 :    END SUBROUTINE do_mtlr_u_j
     584              : 
     585              : END MODULE mtlr_u_j_methods
        

Generated by: LCOV version 2.0-1