LCOV - code coverage report
Current view: top level - src - qs_loc_dipole.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:936074a) Lines: 83.3 % 78 65
Test Date: 2025-12-04 06:27:48 Functions: 100.0 % 1 1

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief
      10              : ! **************************************************************************************************
      11              : MODULE qs_loc_dipole
      12              :    USE atomic_kind_types,               ONLY: get_atomic_kind
      13              :    USE cell_types,                      ONLY: cell_type,&
      14              :                                               pbc
      15              :    USE cp_control_types,                ONLY: dft_control_type
      16              :    USE cp_log_handling,                 ONLY: cp_logger_type
      17              :    USE cp_output_handling,              ONLY: cp_iter_string,&
      18              :                                               cp_p_file,&
      19              :                                               cp_print_key_finished_output,&
      20              :                                               cp_print_key_should_output,&
      21              :                                               cp_print_key_unit_nr
      22              :    USE cp_result_methods,               ONLY: cp_results_erase,&
      23              :                                               get_results,&
      24              :                                               put_results
      25              :    USE cp_result_types,                 ONLY: cp_result_type
      26              :    USE input_section_types,             ONLY: section_get_ival,&
      27              :                                               section_vals_get_subs_vals,&
      28              :                                               section_vals_type,&
      29              :                                               section_vals_val_get
      30              :    USE kinds,                           ONLY: default_string_length,&
      31              :                                               dp
      32              :    USE mathconstants,                   ONLY: twopi,&
      33              :                                               z_one
      34              :    USE moments_utils,                   ONLY: get_reference_point
      35              :    USE particle_types,                  ONLY: particle_type
      36              :    USE physcon,                         ONLY: debye
      37              :    USE qs_environment_types,            ONLY: get_qs_env,&
      38              :                                               qs_environment_type
      39              :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      40              :                                               qs_kind_type
      41              :    USE qs_loc_types,                    ONLY: qs_loc_env_type
      42              : #include "./base/base_uses.f90"
      43              : 
      44              :    IMPLICIT NONE
      45              :    PRIVATE
      46              : 
      47              :    ! Global parameters
      48              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_loc_dipole'
      49              :    PUBLIC :: loc_dipole
      50              : 
      51              : ! **************************************************************************************************
      52              : 
      53              : CONTAINS
      54              : 
      55              : ! **************************************************************************************************
      56              : !> \brief Computes and prints the Dipole (using localized charges)
      57              : !> \param input ...
      58              : !> \param dft_control ...
      59              : !> \param qs_loc_env ...
      60              : !> \param logger ...
      61              : !> \param qs_env the qs_env in which the qs_env lives
      62              : ! **************************************************************************************************
      63           80 :    SUBROUTINE loc_dipole(input, dft_control, qs_loc_env, logger, qs_env)
      64              :       TYPE(section_vals_type), POINTER                   :: input
      65              :       TYPE(dft_control_type), POINTER                    :: dft_control
      66              :       TYPE(qs_loc_env_type), POINTER                     :: qs_loc_env
      67              :       TYPE(cp_logger_type), POINTER                      :: logger
      68              :       TYPE(qs_environment_type), POINTER                 :: qs_env
      69              : 
      70              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'loc_dipole'
      71              : 
      72              :       CHARACTER(LEN=default_string_length)               :: description, descriptionThisDip, iter
      73              :       COMPLEX(KIND=dp)                                   :: zeta
      74              :       COMPLEX(KIND=dp), DIMENSION(3)                     :: ggamma, zphase
      75              :       INTEGER                                            :: handle, i, ikind, ispins, j, n_rep, &
      76              :                                                             reference, unit_nr
      77              :       LOGICAL                                            :: do_berry, first_time, floating, ghost
      78              :       REAL(KIND=dp)                                      :: charge_tot, theta, zeff, zwfc
      79              :       REAL(KIND=dp), DIMENSION(3)                        :: ci, dipole, dipole_old, gvec, rcc, ria
      80           80 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: ref_point
      81              :       TYPE(cell_type), POINTER                           :: cell
      82              :       TYPE(cp_result_type), POINTER                      :: results
      83           80 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
      84           80 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
      85              :       TYPE(section_vals_type), POINTER                   :: print_key
      86              : 
      87           80 :       CALL timeset(routineN, handle)
      88              : 
      89           80 :       print_key => section_vals_get_subs_vals(input, "DFT%LOCALIZE%PRINT%TOTAL_DIPOLE")
      90           80 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key, first_time=first_time) &
      91              :                 , cp_p_file)) THEN
      92           16 :          NULLIFY (cell, particle_set, qs_kind_set, ref_point, results)
      93              :          CALL get_qs_env(qs_env=qs_env, &
      94              :                          cell=cell, &
      95              :                          particle_set=particle_set, &
      96              :                          qs_kind_set=qs_kind_set, &
      97           16 :                          results=results)
      98              : 
      99           16 :          reference = section_get_ival(print_key, keyword_name="REFERENCE")
     100           16 :          CALL section_vals_val_get(print_key, "REF_POINT", r_vals=ref_point)
     101           16 :          CALL section_vals_val_get(print_key, "PERIODIC", l_val=do_berry)
     102           16 :          description = '[DIPOLE]'
     103           16 :          descriptionThisDip = '[TOTAL_DIPOLE]'
     104           16 :          CALL get_reference_point(rcc, qs_env=qs_env, reference=reference, ref_point=ref_point)
     105              : 
     106           16 :          dipole = 0.0_dp
     107           16 :          IF (do_berry) THEN
     108           64 :             rcc = pbc(rcc, cell)
     109           16 :             charge_tot = REAL(dft_control%charge, KIND=dp)
     110          256 :             ria = twopi*MATMUL(cell%h_inv, rcc)
     111           64 :             zphase = CMPLX(COS(ria), SIN(ria), KIND=dp)**charge_tot
     112           64 :             ggamma = z_one
     113              : 
     114              :             ! Nuclear charges
     115          102 :             DO i = 1, SIZE(particle_set)
     116           86 :                CALL get_atomic_kind(particle_set(i)%atomic_kind, kind_number=ikind)
     117           86 :                CALL get_qs_kind(qs_kind_set(ikind), ghost=ghost, floating=floating)
     118          188 :                IF (.NOT. ghost .AND. .NOT. floating) THEN
     119           86 :                   CALL get_qs_kind(qs_kind_set(ikind), core_charge=zeff)
     120           86 :                   ria = pbc(particle_set(i)%r, cell)
     121          344 :                   DO j = 1, 3
     122         1032 :                      gvec = twopi*cell%h_inv(j, :)
     123         1032 :                      theta = SUM(ria(:)*gvec(:))
     124          258 :                      zeta = CMPLX(COS(theta), SIN(theta), KIND=dp)**(zeff)
     125          344 :                      ggamma(j) = ggamma(j)*zeta
     126              :                   END DO
     127              :                END IF
     128              :             END DO
     129              : 
     130              :             ! Charges of the wfc involved
     131              :             ! Warning, this assumes the same occupation for all states
     132           16 :             zwfc = 3.0_dp - REAL(dft_control%nspins, dp)
     133              : 
     134           32 :             DO ispins = 1, dft_control%nspins
     135          148 :                DO i = 1, SIZE(qs_loc_env%localized_wfn_control%centers_set(ispins)%array, 2)
     136          116 :                   ria = pbc(qs_loc_env%localized_wfn_control%centers_set(ispins)%array(1:3, i), cell)
     137          480 :                   DO j = 1, 3
     138         1392 :                      gvec = twopi*cell%h_inv(j, :)
     139         1392 :                      theta = SUM(ria(:)*gvec(:))
     140          348 :                      zeta = CMPLX(COS(theta), SIN(theta), KIND=dp)**(-zwfc)
     141          464 :                      ggamma(j) = ggamma(j)*zeta
     142              :                   END DO
     143              :                END DO
     144              :             END DO
     145           64 :             ggamma = ggamma*zphase
     146           64 :             ci = AIMAG(LOG(ggamma))/twopi
     147          208 :             dipole = MATMUL(cell%hmat, ci)
     148              :          ELSE
     149              :             ! Charges of the atoms involved
     150            0 :             DO i = 1, SIZE(particle_set)
     151            0 :                CALL get_atomic_kind(particle_set(i)%atomic_kind, kind_number=ikind)
     152            0 :                CALL get_qs_kind(qs_kind_set(ikind), ghost=ghost, floating=floating)
     153            0 :                IF (.NOT. ghost .AND. .NOT. floating) THEN
     154            0 :                   CALL get_qs_kind(qs_kind_set(ikind), core_charge=zeff)
     155            0 :                   ria = pbc(particle_set(i)%r, cell)
     156            0 :                   dipole = dipole + zeff*(ria - rcc)
     157              :                END IF
     158              :             END DO
     159              : 
     160              :             ! Charges of the wfc involved
     161              :             ! Warning, this assumes the same occupation for all states
     162            0 :             zwfc = 3.0_dp - REAL(dft_control%nspins, dp)
     163              : 
     164            0 :             DO ispins = 1, dft_control%nspins
     165            0 :                DO i = 1, SIZE(qs_loc_env%localized_wfn_control%centers_set(ispins)%array, 2)
     166            0 :                   ria = pbc(qs_loc_env%localized_wfn_control%centers_set(ispins)%array(1:3, i), cell)
     167            0 :                   dipole = dipole - zwfc*(ria - rcc)
     168              :                END DO
     169              :             END DO
     170              :          END IF
     171              : 
     172              :          ! Print and possibly store results
     173              :          unit_nr = cp_print_key_unit_nr(logger, print_key, extension=".Dipole", &
     174           16 :                                         middle_name="TOTAL_DIPOLE")
     175           16 :          IF (unit_nr > 0) THEN
     176            8 :             IF (first_time) THEN
     177              :                WRITE (unit=unit_nr, fmt="(A,T31,A,T88,A,T136,A)") &
     178            8 :                   "# iter_level", "dipole(x,y,z)[atomic units]", &
     179            8 :                   "dipole(x,y,z)[debye]", &
     180           16 :                   "delta_dipole(x,y,z)[atomic units]"
     181              :             END IF
     182            8 :             iter = cp_iter_string(logger%iter_info)
     183            8 :             CALL get_results(results, descriptionThisDip, n_rep=n_rep)
     184            8 :             IF (n_rep == 0) THEN
     185            3 :                dipole_old = 0._dp
     186              :             ELSE
     187            5 :                CALL get_results(results, descriptionThisDip, dipole_old, nval=n_rep)
     188              :             END IF
     189            8 :             IF (do_berry) THEN
     190              :                WRITE (unit=unit_nr, fmt="(a,9(es18.8))") &
     191           88 :                   iter(1:15), dipole, dipole*debye, pbc(dipole - dipole_old, cell)
     192              :             ELSE
     193              :                WRITE (unit=unit_nr, fmt="(a,9(es18.8))") &
     194            0 :                   iter(1:15), dipole, dipole*debye, (dipole - dipole_old)
     195              :             END IF
     196              :          END IF
     197           16 :          CALL cp_print_key_finished_output(unit_nr, logger, print_key)
     198           16 :          CALL cp_results_erase(results, description)
     199           16 :          CALL put_results(results, description, dipole)
     200           16 :          CALL cp_results_erase(results, descriptionThisDip)
     201           16 :          CALL put_results(results, descriptionThisDip, dipole)
     202              :       END IF
     203              : 
     204           80 :       CALL timestop(handle)
     205              : 
     206           80 :    END SUBROUTINE loc_dipole
     207              : 
     208              : END MODULE qs_loc_dipole
        

Generated by: LCOV version 2.0-1