LCOV - code coverage report
Current view: top level - src - fde_main.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:9ccafda) Lines: 98.9 % 87 86
Test Date: 2026-10-15 00:55:44 Functions: 100.0 % 2 2

            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              : MODULE fde_main
       8              :    USE bibliography,                    ONLY: Schreder2024_3,&
       9              :                                               cite_reference
      10              :    USE cp_control_types,                ONLY: dft_control_type,&
      11              :                                               fde_control_type
      12              :    USE cp_files,                        ONLY: join_paths
      13              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      14              :                                               cp_logger_get_default_io_unit,&
      15              :                                               cp_logger_type
      16              :    USE fde_methods,                     ONLY: fde_build_v_emb,&
      17              :                                               fde_read_pw,&
      18              :                                               fde_read_results,&
      19              :                                               fde_spawn,&
      20              :                                               fde_v_es,&
      21              :                                               fde_write_pw
      22              :    USE kinds,                           ONLY: default_path_length,&
      23              :                                               dp
      24              :    USE message_passing,                 ONLY: mp_para_env_type
      25              :    USE pw_env_types,                    ONLY: pw_env_get,&
      26              :                                               pw_env_type
      27              :    USE pw_methods,                      ONLY: pw_axpy,&
      28              :                                               pw_integral_ab,&
      29              :                                               pw_integrate_function,&
      30              :                                               pw_scale,&
      31              :                                               pw_zero
      32              :    USE pw_pool_types,                   ONLY: pw_pool_type
      33              :    USE pw_types,                        ONLY: pw_r3d_rs_type
      34              :    USE qs_energy_types,                 ONLY: qs_energy_type
      35              :    USE qs_environment_types,            ONLY: get_qs_env,&
      36              :                                               qs_environment_type
      37              :    USE qs_external_potential,           ONLY: interpolate_external_potential
      38              : #include "./base/base_uses.f90"
      39              : 
      40              :    IMPLICIT NONE
      41              :    PRIVATE
      42              : 
      43              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'fde_main'
      44              : 
      45              :    PUBLIC :: fde_run
      46              : 
      47              : CONTAINS
      48              : 
      49              : ! **************************************************************************************************
      50              : !> \brief Run the FDE self-consistency loop
      51              : !> \param qs_env ..
      52              : ! **************************************************************************************************
      53            2 :    SUBROUTINE fde_run(qs_env)
      54              :       TYPE(qs_environment_type), POINTER                 :: qs_env
      55              : 
      56              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'fde_run'
      57              : 
      58              :       CHARACTER(len=default_path_length)                 :: grid_path, input, res_path, rho_path, &
      59              :                                                             v_path
      60              :       INTEGER                                            :: handle, i_a, iounit, iter, max_iter, n_a
      61              :       LOGICAL                                            :: converged
      62              :       REAL(KIND=dp)                                      :: drho, e_emb, e_env, e_es_e, e_es_int, &
      63              :                                                             e_es_n, e_kin_na, e_n, e_sub, &
      64              :                                                             e_sub_bare, e_tot, e_xc_na, n_el, &
      65              :                                                             n_el_pw, phi_at_atom
      66            2 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: z
      67            2 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: r
      68              :       TYPE(cp_logger_type), POINTER                      :: logger
      69              :       TYPE(dft_control_type), POINTER                    :: dft_control
      70              :       TYPE(fde_control_type), POINTER                    :: fde_control
      71              :       TYPE(mp_para_env_type), POINTER                    :: para_env
      72              :       TYPE(pw_env_type), POINTER                         :: pw_env
      73              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
      74              :       TYPE(pw_r3d_rs_type)                               :: rho, rho_new, v_emb
      75              :       TYPE(pw_r3d_rs_type), POINTER                      :: phi_es_ptr
      76              :       TYPE(pw_r3d_rs_type), TARGET                       :: phi_es
      77              :       TYPE(qs_energy_type), POINTER                      :: qs_energy
      78              : 
      79            2 :       CALL timeset(routineN, handle)
      80              : 
      81            2 :       CALL cite_reference(Schreder2024_3)
      82              : 
      83            2 :       logger => cp_get_default_logger()
      84            2 :       iounit = cp_logger_get_default_io_unit(logger)
      85              : 
      86            2 :       NULLIFY (dft_control, fde_control, para_env, pw_env, auxbas_pw_pool, qs_energy)
      87              :       CALL get_qs_env(qs_env, dft_control=dft_control, para_env=para_env, pw_env=pw_env, &
      88            2 :                       energy=qs_energy)
      89            2 :       fde_control => dft_control%fde_control
      90            2 :       CPASSERT(ASSOCIATED(fde_control))
      91              : 
      92            2 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
      93              : 
      94              :       ! socket files
      95            2 :       v_path = join_paths(fde_control%workdir, fde_control%pot_file)
      96            2 :       grid_path = join_paths(fde_control%workdir, fde_control%grid_file)
      97            2 :       rho_path = join_paths(fde_control%workdir, fde_control%rho_file)
      98            2 :       res_path = join_paths(fde_control%workdir, fde_control%result_file)
      99            2 :       input = fde_control%molcas_input_template
     100              : 
     101              :       ! bare environment DFT energy
     102            2 :       e_env = qs_energy%total
     103              : 
     104              :       ! initial guess = zero
     105            2 :       CALL auxbas_pw_pool%create_pw(rho)
     106            2 :       CALL pw_zero(rho)
     107            2 :       CALL auxbas_pw_pool%create_pw(rho_new)
     108              : 
     109            2 :       max_iter = 1
     110            2 :       IF (fde_control%freeze_and_thaw) max_iter = fde_control%max_ft_iter
     111              : 
     112            2 :       IF (iounit > 0) THEN
     113            1 :          WRITE (iounit, '(/,T2,A)') REPEAT("=", 78)
     114            1 :          WRITE (iounit, '(T2,A)') "FDE:  Frozen-density embedding"
     115            1 :          WRITE (iounit, '(T2,A)') REPEAT("=", 78)
     116              :       END IF
     117              : 
     118            2 :       converged = .FALSE.
     119            4 :       DO iter = 1, max_iter
     120            4 :          CALL fde_build_v_emb(qs_env, rho, v_emb, e_xc_na, e_kin_na)
     121            4 :          CALL fde_write_pw(v_emb, TRIM(v_path), write_value=.TRUE.)
     122            4 :          CALL fde_write_pw(v_emb, TRIM(grid_path), write_value=.FALSE.)
     123              : 
     124            4 :          CALL fde_spawn(fde_control, TRIM(input), para_env)
     125              : 
     126            4 :          CALL fde_read_pw(rho_new, TRIM(rho_path))
     127            4 :          CALL fde_read_results(TRIM(res_path), para_env, e_sub, e_emb, e_n, n_el, n_a, z, r)
     128              : 
     129            4 :          n_el_pw = pw_integrate_function(rho_new)
     130            4 :          IF (n_el_pw > 1.0e-10_dp .AND. n_el > 0.0_dp) THEN
     131            4 :             CALL pw_scale(rho_new, n_el/n_el_pw)
     132              :          END IF
     133              : 
     134            4 :          drho = fde_drho(rho, rho_new, para_env)
     135              : 
     136            4 :          CALL fde_v_es(qs_env, phi_es)
     137            4 :          phi_es_ptr => phi_es
     138            4 :          e_es_e = pw_integral_ab(rho_new, phi_es)
     139              : 
     140            4 :          e_es_n = 0.0_dp
     141            8 :          DO i_a = 1, n_a
     142            4 :             CALL interpolate_external_potential(r(:, i_a), phi_es_ptr, func=phi_at_atom)
     143            8 :             e_es_n = e_es_n - z(i_a)*phi_at_atom
     144              :          END DO
     145            4 :          e_es_int = e_es_e + e_es_n
     146            4 :          CALL auxbas_pw_pool%give_back_pw(phi_es)
     147            4 :          DEALLOCATE (z, r)
     148              : 
     149            4 :          e_sub_bare = e_sub - e_emb
     150            4 :          e_tot = e_sub_bare + e_env + e_es_int + e_xc_na + e_kin_na
     151              : 
     152            4 :          IF (iounit > 0) THEN
     153            2 :             WRITE (iounit, '(/,T2,A,I0)') "FDE freeze-and-thaw iteration ", iter
     154            2 :             WRITE (iounit, '(T4,A,F20.10)') "E(sub, embedded)       = ", e_sub
     155            2 :             WRITE (iounit, '(T4,A,F20.10)') "E(emb)                 = ", e_emb
     156            2 :             WRITE (iounit, '(T4,A,F20.10)') "E(sub)                 = ", e_sub_bare
     157            2 :             WRITE (iounit, '(T4,A,F20.10)') "E(env)                 = ", e_env
     158            2 :             WRITE (iounit, '(T4,A,F20.10)') "E(es)                  = ", e_es_int
     159            2 :             WRITE (iounit, '(T6,A,F20.10)') "E(elec)                = ", e_es_e
     160            2 :             WRITE (iounit, '(T6,A,F20.10)') "E(nuc)                 = ", e_es_n
     161            2 :             WRITE (iounit, '(T4,A,F20.10)') "E(XC, nonadditive)     = ", e_xc_na
     162            2 :             WRITE (iounit, '(T4,A,F20.10)') "E(kin, nonadditive)    = ", e_kin_na
     163            2 :             WRITE (iounit, '(T4,A,F20.10)') "E(FDE)                 = ", e_tot
     164            2 :             WRITE (iounit, '(T4,A,F14.6,A,F14.6)') "N(sub, e): grid = ", n_el_pw, &
     165            4 :                " reported = ", n_el
     166            2 :             WRITE (iounit, '(T4,A,ES14.6)') "int|rho(sub, new) - rho(sub, old)|dr = ", drho
     167              :          END IF
     168              : 
     169            4 :          CALL auxbas_pw_pool%give_back_pw(v_emb)
     170              : 
     171            4 :          IF (fde_control%freeze_and_thaw) THEN
     172            4 :             IF (drho < fde_control%eps_ft_density) THEN
     173              :                converged = .TRUE.
     174              :             ELSE
     175            2 :                CALL pw_scale(rho, 1.0_dp - fde_control%density_mixing)
     176            2 :                CALL pw_axpy(rho_new, rho, fde_control%density_mixing)
     177              :             END IF
     178              :          ELSE
     179              :             converged = .TRUE.
     180              :          END IF
     181              : 
     182            8 :          IF (converged) EXIT
     183              : 
     184              :       END DO
     185              : 
     186            2 :       IF (iounit > 0) THEN
     187            1 :          WRITE (iounit, '(/,T2,A)') REPEAT("=", 78)
     188            1 :          IF (fde_control%freeze_and_thaw .AND. .NOT. converged) THEN
     189            0 :             WRITE (iounit, '(T2,A)') "FDE  WARNING: freeze-and-thaw did not converge"
     190              :          END IF
     191            1 :          WRITE (iounit, '(T2,A,F20.10)') "FDE final total energy = ", e_tot
     192            1 :          WRITE (iounit, '(T2,A)') REPEAT("=", 78)
     193              :       END IF
     194              : 
     195            2 :       qs_energy%total = e_tot
     196              : 
     197            2 :       CALL auxbas_pw_pool%give_back_pw(rho)
     198            2 :       CALL auxbas_pw_pool%give_back_pw(rho_new)
     199              : 
     200            2 :       CALL timestop(handle)
     201              : 
     202            4 :    END SUBROUTINE fde_run
     203              : 
     204              : ! **************************************************************************************************
     205              : !> \brief Integrated density difference: int |rho_new - rho_old| dr
     206              : !> \param rho_a ...
     207              : !> \param rho_b ...
     208              : !> \param para_env ...
     209              : !> \return ...
     210              : ! **************************************************************************************************
     211            4 :    FUNCTION fde_drho(rho_a, rho_b, para_env) RESULT(drho)
     212              :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: rho_a, rho_b
     213              :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env
     214              :       REAL(KIND=dp)                                      :: drho
     215              : 
     216        13036 :       drho = SUM(ABS(rho_b%array - rho_a%array))*rho_b%pw_grid%dvol
     217            4 :       CALL para_env%sum(drho)
     218              : 
     219            4 :    END FUNCTION fde_drho
     220              : 
     221              : END MODULE fde_main
        

Generated by: LCOV version 2.0-1