LCOV - code coverage report
Current view: top level - src - qs_cdft_grid.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:21ef868) Lines: 85.1 % 275 234
Test Date: 2026-08-14 07:04:57 Functions: 75.0 % 8 6

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Pointwise CDFT partition functions for nonuniform integration grids.
      10              : ! **************************************************************************************************
      11              : MODULE qs_cdft_grid
      12              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      13              :                                               get_atomic_kind
      14              :    USE cell_types,                      ONLY: cell_type,&
      15              :                                               pbc
      16              :    USE cp_control_types,                ONLY: dft_control_type
      17              :    USE cp_units,                        ONLY: cp_unit_from_cp2k
      18              :    USE hirshfeld_methods,               ONLY: create_shape_function
      19              :    USE hirshfeld_types,                 ONLY: hirshfeld_type
      20              :    USE input_constants,                 ONLY: becke_cutoff_element,&
      21              :                                               becke_cutoff_global,&
      22              :                                               outer_scf_becke_constraint,&
      23              :                                               outer_scf_hirshfeld_constraint
      24              :    USE kinds,                           ONLY: dp
      25              :    USE particle_types,                  ONLY: particle_type
      26              :    USE qs_cdft_types,                   ONLY: becke_constraint_type,&
      27              :                                               cdft_control_type,&
      28              :                                               hirshfeld_constraint_type
      29              :    USE qs_cdft_utils,                   ONLY: hirshfeld_constraint_init
      30              :    USE qs_environment_types,            ONLY: get_qs_env,&
      31              :                                               qs_environment_type
      32              :    USE qs_kind_types,                   ONLY: qs_kind_type
      33              : #include "./base/base_uses.f90"
      34              : 
      35              :    IMPLICIT NONE
      36              : 
      37              :    PRIVATE
      38              : 
      39              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_cdft_grid'
      40              : 
      41              :    TYPE cdft_point_context_type
      42              :       INTEGER                                            :: method = -1, natom = 0, ngroup = 0
      43              :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: numexp, cavity_numexp
      44              :       LOGICAL                                            :: calculate_derivatives = .FALSE., &
      45              :                                                             cavity_confine = .FALSE.
      46              :       LOGICAL, ALLOCATABLE, DIMENSION(:)                 :: constraint_atom
      47              :       REAL(KIND=dp)                                      :: eps = 0.0_dp, eps_cavity = 0.0_dp
      48              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: cutoffs, distances, cell_functions
      49              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: atom_coords, aij, coefficients, &
      50              :                                                             alpha, amplitude, cavity_alpha, &
      51              :                                                             cavity_amplitude, displacement, &
      52              :                                                             datom_numerator, datom_sum, dcell_point, &
      53              :                                                             density_atom_derivative
      54              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: pair_vectors, dcell_atom
      55              :       TYPE(cell_type), POINTER                           :: cell => NULL()
      56              :    END TYPE cdft_point_context_type
      57              : 
      58              :    PUBLIC :: cdft_point_context_create, &
      59              :              cdft_point_context_release, &
      60              :              cdft_point_context_type, &
      61              :              cdft_point_weights
      62              : 
      63              : CONTAINS
      64              : 
      65              : ! **************************************************************************************************
      66              : !> \brief Initialize reusable data for pointwise CDFT partition evaluation.
      67              : !> \param qs_env Quickstep environment
      68              : !> \param context pointwise partition context
      69              : !> \param calculate_derivatives allocate scratch space for coordinate derivatives
      70              : ! **************************************************************************************************
      71          424 :    SUBROUTINE cdft_point_context_create(qs_env, context, calculate_derivatives)
      72              :       TYPE(qs_environment_type), POINTER                 :: qs_env
      73              :       TYPE(cdft_point_context_type), INTENT(OUT)         :: context
      74              :       LOGICAL, INTENT(IN), OPTIONAL                      :: calculate_derivatives
      75              : 
      76              :       INTEGER                                            :: atom, iatom, igroup, ikind, jatom, natom
      77              :       REAL(KIND=dp)                                      :: chi, ircov, jrcov, uij
      78              :       REAL(KIND=dp), DIMENSION(3)                        :: pair_vector
      79          424 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: radii, radii_list
      80          424 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
      81              :       TYPE(becke_constraint_type), POINTER               :: becke_control
      82              :       TYPE(cdft_control_type), POINTER                   :: cdft_control
      83              :       TYPE(dft_control_type), POINTER                    :: dft_control
      84              :       TYPE(hirshfeld_constraint_type), POINTER           :: hirshfeld_control
      85              :       TYPE(hirshfeld_type), POINTER                      :: hirshfeld_env
      86          424 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
      87          424 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
      88              : 
      89          424 :       NULLIFY (becke_control, cdft_control, dft_control, hirshfeld_control, &
      90          424 :                hirshfeld_env, atomic_kind_set, particle_set, qs_kind_set, radii, radii_list)
      91              :       CALL get_qs_env(qs_env, cell=context%cell, dft_control=dft_control, &
      92              :                       natom=natom, particle_set=particle_set, atomic_kind_set=atomic_kind_set, &
      93          424 :                       qs_kind_set=qs_kind_set)
      94          424 :       CPASSERT(ASSOCIATED(context%cell))
      95          424 :       CPASSERT(ASSOCIATED(dft_control))
      96          424 :       CPASSERT(ASSOCIATED(particle_set))
      97          424 :       CPASSERT(ASSOCIATED(atomic_kind_set))
      98          424 :       CPASSERT(ASSOCIATED(qs_kind_set))
      99          424 :       cdft_control => dft_control%qs_control%cdft_control
     100          424 :       CPASSERT(ASSOCIATED(cdft_control))
     101              : 
     102          424 :       context%method = cdft_control%type
     103          424 :       context%natom = natom
     104          424 :       context%ngroup = SIZE(cdft_control%group)
     105          424 :       context%calculate_derivatives = .FALSE.
     106          424 :       IF (PRESENT(calculate_derivatives)) context%calculate_derivatives = calculate_derivatives
     107            0 :       ALLOCATE (context%atom_coords(3, natom), &
     108            0 :                 context%coefficients(context%ngroup, natom), &
     109            0 :                 context%constraint_atom(natom), &
     110            0 :                 context%distances(natom), context%displacement(3, natom), &
     111         5088 :                 context%cell_functions(natom))
     112         2484 :       context%coefficients = 0.0_dp
     113         1382 :       context%constraint_atom = .FALSE.
     114         1382 :       DO atom = 1, natom
     115         4256 :          context%atom_coords(:, atom) = particle_set(atom)%r
     116              :       END DO
     117          920 :       DO igroup = 1, context%ngroup
     118         1804 :          DO iatom = 1, SIZE(cdft_control%group(igroup)%atoms)
     119          884 :             atom = cdft_control%group(igroup)%atoms(iatom)
     120          884 :             context%coefficients(igroup, atom) = cdft_control%group(igroup)%coeff(iatom)
     121         1380 :             context%constraint_atom(atom) = .TRUE.
     122              :          END DO
     123              :       END DO
     124              : 
     125          424 :       SELECT CASE (context%method)
     126              :       CASE (outer_scf_becke_constraint)
     127          334 :          becke_control => cdft_control%becke_control
     128          334 :          CPASSERT(ASSOCIATED(becke_control))
     129            0 :          ALLOCATE (context%cutoffs(natom), context%aij(natom, natom), &
     130         3006 :                    context%pair_vectors(3, natom, natom))
     131          334 :          IF (context%calculate_derivatives) THEN
     132            0 :             ALLOCATE (context%dcell_point(3, natom), context%dcell_atom(3, natom, natom), &
     133           28 :                       context%datom_sum(3, natom), context%datom_numerator(3, natom))
     134              :          END IF
     135          334 :          IF (ASSOCIATED(becke_control%cutoffs)) THEN
     136          890 :             context%cutoffs(:) = becke_control%cutoffs
     137              :          ELSE
     138          148 :             SELECT CASE (becke_control%cutoff_type)
     139              :             CASE (becke_cutoff_global)
     140          222 :                context%cutoffs = becke_control%rglobal
     141              :             CASE (becke_cutoff_element)
     142            0 :                CPASSERT(ASSOCIATED(becke_control%cutoffs_tmp))
     143            0 :                CPASSERT(SIZE(becke_control%cutoffs_tmp) == SIZE(atomic_kind_set))
     144            0 :                DO atom = 1, natom
     145            0 :                   CALL get_atomic_kind(particle_set(atom)%atomic_kind, kind_number=ikind)
     146            0 :                   context%cutoffs(atom) = becke_control%cutoffs_tmp(ikind)
     147              :                END DO
     148              :             CASE DEFAULT
     149           74 :                CPABORT("Unknown Becke cutoff type.")
     150              :             END SELECT
     151              :          END IF
     152         2998 :          context%aij = 0.0_dp
     153          334 :          IF (becke_control%adjust) THEN
     154           46 :             IF (ASSOCIATED(becke_control%aij)) THEN
     155          598 :                context%aij(:, :) = becke_control%aij
     156              :             ELSE
     157            0 :                IF (ASSOCIATED(becke_control%radii)) THEN
     158            0 :                   radii => becke_control%radii
     159              :                ELSE
     160            0 :                   radii => becke_control%radii_tmp
     161              :                END IF
     162            0 :                CPASSERT(ASSOCIATED(radii))
     163            0 :                CPASSERT(SIZE(radii) == SIZE(atomic_kind_set))
     164            0 :                DO iatom = 1, natom - 1
     165            0 :                   CALL get_atomic_kind(particle_set(iatom)%atomic_kind, kind_number=ikind)
     166            0 :                   ircov = radii(ikind)
     167            0 :                   DO jatom = iatom + 1, natom
     168            0 :                      CALL get_atomic_kind(particle_set(jatom)%atomic_kind, kind_number=ikind)
     169            0 :                      jrcov = radii(ikind)
     170            0 :                      IF (ircov /= jrcov) THEN
     171            0 :                         chi = ircov/jrcov
     172            0 :                         uij = (chi - 1.0_dp)/(chi + 1.0_dp)
     173              :                         context%aij(iatom, jatom) = MAX(-0.5_dp, MIN(0.5_dp, &
     174            0 :                                                                      uij/(uij**2 - 1.0_dp)))
     175            0 :                         context%aij(jatom, iatom) = -context%aij(iatom, jatom)
     176              :                      END IF
     177              :                   END DO
     178              :                END DO
     179              :             END IF
     180              :          END IF
     181         8656 :          context%pair_vectors = 0.0_dp
     182          778 :          DO iatom = 1, natom - 1
     183         1332 :             DO jatom = iatom + 1, natom
     184              :                pair_vector = pbc(context%atom_coords(:, jatom), &
     185          554 :                                  context%atom_coords(:, iatom), context%cell)
     186         2216 :                context%pair_vectors(:, iatom, jatom) = pair_vector
     187         2660 :                context%pair_vectors(:, jatom, iatom) = -pair_vector
     188              :             END DO
     189              :          END DO
     190          334 :          context%cavity_confine = becke_control%cavity_confine
     191          334 :          context%eps_cavity = becke_control%eps_cavity
     192          334 :          IF (context%cavity_confine) THEN
     193           46 :             hirshfeld_env => becke_control%cavity_env
     194           46 :             CPASSERT(ASSOCIATED(hirshfeld_env))
     195           46 :             IF (.NOT. ASSOCIATED(hirshfeld_env%kind_shape_fn)) THEN
     196            0 :                IF (ASSOCIATED(becke_control%radii)) THEN
     197            0 :                   radii => becke_control%radii
     198            0 :                ELSE IF (ASSOCIATED(becke_control%radii_tmp)) THEN
     199            0 :                   radii => becke_control%radii_tmp
     200              :                END IF
     201            0 :                IF (ASSOCIATED(radii)) THEN
     202            0 :                   ALLOCATE (radii_list(SIZE(radii)))
     203            0 :                   DO ikind = 1, SIZE(radii)
     204            0 :                      IF (hirshfeld_env%use_bohr) THEN
     205            0 :                         radii_list(ikind) = radii(ikind)
     206              :                      ELSE
     207            0 :                         radii_list(ikind) = cp_unit_from_cp2k(radii(ikind), "angstrom")
     208              :                      END IF
     209              :                   END DO
     210              :                END IF
     211              :                CALL create_shape_function(hirshfeld_env, qs_kind_set, atomic_kind_set, &
     212            0 :                                           radius=becke_control%rcavity, radii_list=radii_list)
     213            0 :                IF (ASSOCIATED(radii_list)) DEALLOCATE (radii_list)
     214              :             END IF
     215              :             CALL store_shape_functions(hirshfeld_env, particle_set, context%cavity_numexp, &
     216              :                                        context%cavity_alpha, context%cavity_amplitude, &
     217           46 :                                        include_charge=.FALSE.)
     218              :          END IF
     219              :       CASE (outer_scf_hirshfeld_constraint)
     220           90 :          hirshfeld_control => cdft_control%hirshfeld_control
     221           90 :          CPASSERT(ASSOCIATED(hirshfeld_control))
     222           90 :          hirshfeld_env => hirshfeld_control%hirshfeld_env
     223           90 :          CPASSERT(ASSOCIATED(hirshfeld_env))
     224           90 :          IF (.NOT. ASSOCIATED(hirshfeld_env%kind_shape_fn) .OR. &
     225              :              .NOT. ASSOCIATED(hirshfeld_env%charges)) THEN
     226            0 :             CALL hirshfeld_constraint_init(qs_env)
     227              :          END IF
     228           90 :          context%eps = hirshfeld_control%eps_cutoff
     229              :          CALL store_shape_functions(hirshfeld_env, particle_set, context%numexp, &
     230           90 :                                     context%alpha, context%amplitude, include_charge=.TRUE.)
     231           90 :          IF (context%calculate_derivatives) THEN
     232           12 :             ALLOCATE (context%density_atom_derivative(3, natom))
     233              :          END IF
     234              :       CASE DEFAULT
     235          424 :          CPABORT("Unknown CDFT partition type.")
     236              :       END SELECT
     237              : 
     238              :    CONTAINS
     239              : 
     240              : ! **************************************************************************************************
     241              : !> \brief ...
     242              : !> \param environment ...
     243              : !> \param particles ...
     244              : !> \param numexp ...
     245              : !> \param alpha ...
     246              : !> \param amplitude ...
     247              : !> \param include_charge ...
     248              : ! **************************************************************************************************
     249          136 :       SUBROUTINE store_shape_functions(environment, particles, numexp, alpha, amplitude, &
     250              :                                        include_charge)
     251              :       TYPE(hirshfeld_type), POINTER                      :: environment
     252              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particles
     253              :       INTEGER, ALLOCATABLE, DIMENSION(:), INTENT(OUT)    :: numexp
     254              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :), &
     255              :          INTENT(OUT)                                     :: alpha, amplitude
     256              :       LOGICAL, INTENT(IN)                                :: include_charge
     257              : 
     258              :       INTEGER                                            :: atom, iexp, ikind, maxexp
     259              :       REAL(KIND=dp)                                      :: charge
     260              : 
     261          408 :          ALLOCATE (numexp(natom))
     262          136 :          numexp = 0
     263          136 :          maxexp = 0
     264          454 :          DO atom = 1, natom
     265          318 :             CALL get_atomic_kind(particles(atom)%atomic_kind, kind_number=ikind)
     266          318 :             numexp(atom) = environment%kind_shape_fn(ikind)%numexp
     267          454 :             maxexp = MAX(maxexp, numexp(atom))
     268              :          END DO
     269          816 :          ALLOCATE (alpha(maxexp, natom), amplitude(maxexp, natom))
     270          136 :          alpha = 0.0_dp
     271          136 :          amplitude = 0.0_dp
     272          454 :          DO atom = 1, natom
     273          318 :             CALL get_atomic_kind(particles(atom)%atomic_kind, kind_number=ikind)
     274          318 :             charge = 1.0_dp
     275          318 :             IF (include_charge) charge = environment%charges(atom)
     276         1090 :             DO iexp = 1, numexp(atom)
     277          318 :                alpha(iexp, atom) = environment%kind_shape_fn(ikind)%zet(iexp)
     278          636 :                amplitude(iexp, atom) = charge*environment%kind_shape_fn(ikind)%coef(iexp)
     279              :             END DO
     280              :          END DO
     281          136 :       END SUBROUTINE store_shape_functions
     282              : 
     283              :    END SUBROUTINE cdft_point_context_create
     284              : 
     285              : ! **************************************************************************************************
     286              : !> \brief Release a pointwise CDFT partition context.
     287              : !> \param context pointwise partition context
     288              : ! **************************************************************************************************
     289          424 :    SUBROUTINE cdft_point_context_release(context)
     290              :       TYPE(cdft_point_context_type), INTENT(INOUT)       :: context
     291              : 
     292          424 :       IF (ALLOCATED(context%numexp)) DEALLOCATE (context%numexp)
     293          424 :       IF (ALLOCATED(context%cavity_numexp)) DEALLOCATE (context%cavity_numexp)
     294          424 :       IF (ALLOCATED(context%constraint_atom)) DEALLOCATE (context%constraint_atom)
     295          424 :       IF (ALLOCATED(context%cutoffs)) DEALLOCATE (context%cutoffs)
     296          424 :       IF (ALLOCATED(context%distances)) DEALLOCATE (context%distances)
     297          424 :       IF (ALLOCATED(context%cell_functions)) DEALLOCATE (context%cell_functions)
     298          424 :       IF (ALLOCATED(context%datom_sum)) DEALLOCATE (context%datom_sum)
     299          424 :       IF (ALLOCATED(context%atom_coords)) DEALLOCATE (context%atom_coords)
     300          424 :       IF (ALLOCATED(context%aij)) DEALLOCATE (context%aij)
     301          424 :       IF (ALLOCATED(context%coefficients)) DEALLOCATE (context%coefficients)
     302          424 :       IF (ALLOCATED(context%alpha)) DEALLOCATE (context%alpha)
     303          424 :       IF (ALLOCATED(context%amplitude)) DEALLOCATE (context%amplitude)
     304          424 :       IF (ALLOCATED(context%cavity_alpha)) DEALLOCATE (context%cavity_alpha)
     305          424 :       IF (ALLOCATED(context%cavity_amplitude)) DEALLOCATE (context%cavity_amplitude)
     306          424 :       IF (ALLOCATED(context%displacement)) DEALLOCATE (context%displacement)
     307          424 :       IF (ALLOCATED(context%datom_numerator)) DEALLOCATE (context%datom_numerator)
     308          424 :       IF (ALLOCATED(context%dcell_point)) DEALLOCATE (context%dcell_point)
     309          424 :       IF (ALLOCATED(context%density_atom_derivative)) DEALLOCATE (context%density_atom_derivative)
     310          424 :       IF (ALLOCATED(context%pair_vectors)) DEALLOCATE (context%pair_vectors)
     311          424 :       IF (ALLOCATED(context%dcell_atom)) DEALLOCATE (context%dcell_atom)
     312          424 :       NULLIFY (context%cell)
     313          424 :       context%method = -1
     314          424 :       context%natom = 0
     315          424 :       context%ngroup = 0
     316          424 :       context%calculate_derivatives = .FALSE.
     317          424 :    END SUBROUTINE cdft_point_context_release
     318              : 
     319              : ! **************************************************************************************************
     320              : !> \brief Evaluate CDFT weights and coordinate derivatives at one point.
     321              : !> \param context pointwise partition context
     322              : !> \param point Cartesian point
     323              : !> \param weights group weights
     324              : !> \param point_derivative derivatives with respect to the Cartesian point
     325              : !> \param atom_derivative derivatives with respect to atom positions at fixed point
     326              : !> \param atomic_weights optional individual atomic partition weights
     327              : ! **************************************************************************************************
     328      1197500 :    SUBROUTINE cdft_point_weights(context, point, weights, point_derivative, atom_derivative, &
     329      1197500 :                                  atomic_weights)
     330              :       TYPE(cdft_point_context_type), INTENT(INOUT)       :: context
     331              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: point
     332              :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: weights
     333              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT)        :: point_derivative
     334              :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(OUT)     :: atom_derivative
     335              :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT), OPTIONAL :: atomic_weights
     336              : 
     337      1197500 :       CPASSERT(SIZE(weights) == context%ngroup)
     338      1197500 :       CPASSERT(SIZE(point_derivative, 1) == 3)
     339      1197500 :       CPASSERT(SIZE(point_derivative, 2) == context%ngroup)
     340      1197500 :       CPASSERT(SIZE(atom_derivative, 1) == 3)
     341      1197500 :       CPASSERT(SIZE(atom_derivative, 2) == context%natom)
     342      1197500 :       CPASSERT(SIZE(atom_derivative, 3) == context%ngroup)
     343      1197500 :       IF (PRESENT(atomic_weights)) THEN
     344       247500 :          CPASSERT(SIZE(atomic_weights) == context%natom)
     345              :       END IF
     346      2170000 :       SELECT CASE (context%method)
     347              :       CASE (outer_scf_becke_constraint)
     348              :          CALL becke_point_weights(context, point, weights, point_derivative, atom_derivative, &
     349      1772500 :                                   atomic_weights, context%calculate_derivatives)
     350              :       CASE (outer_scf_hirshfeld_constraint)
     351              :          CALL hirshfeld_point_weights(context, point, weights, point_derivative, atom_derivative, &
     352       375000 :                                       atomic_weights, context%calculate_derivatives)
     353              :       CASE DEFAULT
     354      1197500 :          CPABORT("Unknown CDFT partition type.")
     355              :       END SELECT
     356      1197500 :    END SUBROUTINE cdft_point_weights
     357              : 
     358              : ! **************************************************************************************************
     359              : !> \brief Evaluate Becke weights at one point.
     360              : !> \param context ...
     361              : !> \param point ...
     362              : !> \param weights ...
     363              : !> \param point_derivative ...
     364              : !> \param atom_derivative ...
     365              : !> \param atomic_weights ...
     366              : !> \param calculate_derivatives ...
     367              : ! **************************************************************************************************
     368       972500 :    SUBROUTINE becke_point_weights(context, point, weights, point_derivative, atom_derivative, &
     369       972500 :                                   atomic_weights, calculate_derivatives)
     370              :       TYPE(cdft_point_context_type), INTENT(INOUT)       :: context
     371              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: point
     372              :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: weights
     373              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT)        :: point_derivative
     374              :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(OUT)     :: atom_derivative
     375              :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT), OPTIONAL :: atomic_weights
     376              :       LOGICAL, INTENT(IN)                                :: calculate_derivatives
     377              : 
     378              :       INTEGER                                            :: atom, iatom, iexp, igroup, jatom
     379              :       REAL(KIND=dp)                                      :: adjusted_mu, cavity_density, delta, &
     380              :                                                             dmu_factor, f1, f2, f3, mu, numerator, &
     381              :                                                             old_cell, pair_distance, s, sum_cell
     382              :       REAL(KIND=dp), DIMENSION(3)                        :: dmu_i, dmu_j, dmu_point, &
     383              :                                                             dpoint_numerator, ds_i, ds_j, &
     384              :                                                             ds_point, dsum_point, unit_i, unit_j
     385              : 
     386      2125000 :       weights = 0.0_dp
     387       972500 :       IF (calculate_derivatives) THEN
     388        82500 :          point_derivative = 0.0_dp
     389       200000 :          atom_derivative = 0.0_dp
     390              :       END IF
     391      1490000 :       IF (PRESENT(atomic_weights)) atomic_weights = 0.0_dp
     392              : 
     393       972500 :       IF (context%cavity_confine) THEN
     394       172500 :          cavity_density = 0.0_dp
     395       690000 :          DO atom = 1, context%natom
     396       517500 :             IF (.NOT. context%constraint_atom(atom)) CYCLE
     397      2070000 :             context%displacement(:, atom) = pbc(context%atom_coords(:, atom), point, context%cell)
     398      1207500 :             DO iexp = 1, context%cavity_numexp(atom)
     399              :                cavity_density = cavity_density + context%cavity_amplitude(iexp, atom)* &
     400              :                                 EXP(-context%cavity_alpha(iexp, atom)* &
     401      2587500 :                                     DOT_PRODUCT(context%displacement(:, atom), context%displacement(:, atom)))
     402              :             END DO
     403              :          END DO
     404       227055 :          IF (cavity_density < context%eps_cavity) RETURN
     405              :       END IF
     406              : 
     407      3292464 :       context%cell_functions = 1.0_dp
     408       963116 :       IF (calculate_derivatives) THEN
     409       142500 :          context%dcell_point = 0.0_dp
     410       395000 :          context%dcell_atom = 0.0_dp
     411              :       END IF
     412      3292464 :       DO atom = 1, context%natom
     413      9317392 :          context%displacement(:, atom) = pbc(context%atom_coords(:, atom), point, context%cell)
     414     10280508 :          context%distances(atom) = NORM2(context%displacement(:, atom))
     415              :       END DO
     416      3292464 :       DO iatom = 1, context%natom
     417      2329348 :          IF (context%distances(iatom) > context%cutoffs(iatom)) THEN
     418       185920 :             context%cell_functions(iatom) = 0.0_dp
     419       185920 :             CYCLE
     420              :          END IF
     421      2143428 :          IF (calculate_derivatives) THEN
     422        32500 :             unit_i = 0.0_dp
     423        32500 :             IF (context%distances(iatom) > 1.0E-14_dp) THEN
     424       130000 :                unit_i = -context%displacement(:, iatom)/context%distances(iatom)
     425              :             END IF
     426              :          END IF
     427      8488944 :          DO jatom = 1, context%natom
     428      5382400 :             IF (jatom == iatom) CYCLE
     429     12955888 :             pair_distance = NORM2(context%pair_vectors(:, iatom, jatom))
     430      3238972 :             IF (pair_distance <= 1.0E-14_dp) CYCLE
     431      3238972 :             delta = context%distances(iatom) - context%distances(jatom)
     432      3238972 :             mu = delta/pair_distance
     433      3238972 :             adjusted_mu = mu + context%aij(iatom, jatom)*(1.0_dp - mu**2)
     434      3238972 :             f1 = 1.5_dp*adjusted_mu - 0.5_dp*adjusted_mu**3
     435      3238972 :             f2 = 1.5_dp*f1 - 0.5_dp*f1**3
     436      3238972 :             f3 = 1.5_dp*f2 - 0.5_dp*f2**3
     437      3238972 :             s = 0.5_dp*(1.0_dp - f3)
     438      3238972 :             old_cell = context%cell_functions(iatom)
     439      3238972 :             IF (calculate_derivatives) THEN
     440        55000 :                dmu_factor = 1.0_dp - 2.0_dp*context%aij(iatom, jatom)*mu
     441        55000 :                unit_j = 0.0_dp
     442        55000 :                IF (context%distances(jatom) > 1.0E-14_dp) THEN
     443       220000 :                   unit_j = -context%displacement(:, jatom)/context%distances(jatom)
     444              :                END IF
     445              :                dmu_i = unit_i/pair_distance - &
     446       220000 :                        delta*context%pair_vectors(:, iatom, jatom)/pair_distance**3
     447              :                dmu_j = -unit_j/pair_distance + &
     448       220000 :                        delta*context%pair_vectors(:, iatom, jatom)/pair_distance**3
     449       220000 :                dmu_point = (-unit_i + unit_j)/pair_distance
     450              :                dmu_factor = -0.5_dp*dmu_factor*1.5_dp*(1.0_dp - adjusted_mu**2)* &
     451        55000 :                             1.5_dp*(1.0_dp - f1**2)*1.5_dp*(1.0_dp - f2**2)
     452       220000 :                ds_i = dmu_factor*dmu_i
     453       220000 :                ds_j = dmu_factor*dmu_j
     454       220000 :                ds_point = dmu_factor*dmu_point
     455       675000 :                context%dcell_atom(:, :, iatom) = context%dcell_atom(:, :, iatom)*s
     456       220000 :                context%dcell_point(:, iatom) = context%dcell_point(:, iatom)*s
     457              :                context%dcell_atom(:, iatom, iatom) = &
     458       220000 :                   context%dcell_atom(:, iatom, iatom) + old_cell*ds_i
     459              :                context%dcell_atom(:, jatom, iatom) = &
     460       220000 :                   context%dcell_atom(:, jatom, iatom) + old_cell*ds_j
     461       220000 :                context%dcell_point(:, iatom) = context%dcell_point(:, iatom) + old_cell*ds_point
     462              :             END IF
     463      7525828 :             context%cell_functions(iatom) = old_cell*s
     464              :          END DO
     465              :       END DO
     466              : 
     467      3292464 :       sum_cell = SUM(context%cell_functions)
     468       963116 :       IF (sum_cell <= 1.0E-6_dp) RETURN
     469      1318076 :       IF (PRESENT(atomic_weights)) atomic_weights = context%cell_functions/sum_cell
     470       908561 :       IF (calculate_derivatives) THEN
     471       147500 :          dsum_point = SUM(context%dcell_point, DIM=2)
     472       405000 :          context%datom_sum(:, :) = SUM(context%dcell_atom, DIM=3)
     473              :       END IF
     474      1997122 :       DO igroup = 1, context%ngroup
     475      3642188 :          numerator = DOT_PRODUCT(context%coefficients(igroup, :), context%cell_functions)
     476      1088561 :          weights(igroup) = numerator/sum_cell
     477      1997122 :          IF (calculate_derivatives) THEN
     478       442500 :             dpoint_numerator = MATMUL(context%dcell_point, context%coefficients(igroup, :))
     479              :             point_derivative(:, igroup) = &
     480        70000 :                (dpoint_numerator*sum_cell - numerator*dsum_point)/sum_cell**2
     481        60000 :             DO atom = 1, context%natom
     482              :                context%datom_numerator(:, atom) = &
     483      1567500 :                   MATMUL(context%dcell_atom(:, atom, :), context%coefficients(igroup, :))
     484              :                atom_derivative(:, atom, igroup) = &
     485              :                   (context%datom_numerator(:, atom)*sum_cell - &
     486       187500 :                    numerator*context%datom_sum(:, atom))/sum_cell**2
     487              :             END DO
     488              :          END IF
     489              :       END DO
     490              :    END SUBROUTINE becke_point_weights
     491              : 
     492              : ! **************************************************************************************************
     493              : !> \brief Evaluate Hirshfeld weights at one point.
     494              : !> \param context ...
     495              : !> \param point ...
     496              : !> \param weights ...
     497              : !> \param point_derivative ...
     498              : !> \param atom_derivative ...
     499              : !> \param atomic_weights ...
     500              : !> \param calculate_derivatives ...
     501              : ! **************************************************************************************************
     502       225000 :    SUBROUTINE hirshfeld_point_weights(context, point, weights, point_derivative, atom_derivative, &
     503       225000 :                                       atomic_weights, calculate_derivatives)
     504              :       TYPE(cdft_point_context_type), INTENT(INOUT)       :: context
     505              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: point
     506              :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: weights
     507              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT)        :: point_derivative
     508              :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(OUT)     :: atom_derivative
     509              :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT), OPTIONAL :: atomic_weights
     510              :       LOGICAL, INTENT(IN)                                :: calculate_derivatives
     511              : 
     512              :       INTEGER                                            :: atom, iexp, igroup
     513              :       REAL(KIND=dp)                                      :: exponential, numerator, sum_density
     514              :       REAL(KIND=dp), DIMENSION(3)                        :: dpoint_numerator, dsum_point
     515              : 
     516       450000 :       weights = 0.0_dp
     517       225000 :       IF (calculate_derivatives) THEN
     518        50000 :          point_derivative = 0.0_dp
     519       100000 :          atom_derivative = 0.0_dp
     520              :       END IF
     521       375000 :       IF (PRESENT(atomic_weights)) atomic_weights = 0.0_dp
     522       675000 :       context%cell_functions = 0.0_dp
     523       305000 :       IF (calculate_derivatives) context%density_atom_derivative = 0.0_dp
     524       675000 :       DO atom = 1, context%natom
     525      1800000 :          context%displacement(:, atom) = pbc(context%atom_coords(:, atom), point, context%cell)
     526      1125000 :          DO iexp = 1, context%numexp(atom)
     527              :             exponential = context%amplitude(iexp, atom)* &
     528              :                           EXP(-context%alpha(iexp, atom)* &
     529      1800000 :                               DOT_PRODUCT(context%displacement(:, atom), context%displacement(:, atom)))
     530       450000 :             context%cell_functions(atom) = context%cell_functions(atom) + exponential
     531       900000 :             IF (calculate_derivatives) THEN
     532              :                context%density_atom_derivative(:, atom) = &
     533              :                   context%density_atom_derivative(:, atom) + &
     534        80000 :                   2.0_dp*context%alpha(iexp, atom)*context%displacement(:, atom)*exponential
     535              :             END IF
     536              :          END DO
     537              :       END DO
     538       675000 :       sum_density = SUM(context%cell_functions)
     539       225000 :       IF (sum_density <= context%eps) THEN
     540        68602 :          RETURN
     541              :       END IF
     542       273218 :       IF (PRESENT(atomic_weights)) atomic_weights = context%cell_functions/sum_density
     543       215204 :       IF (calculate_derivatives) dsum_point = -SUM(context%density_atom_derivative, DIM=2)
     544       312796 :       DO igroup = 1, context%ngroup
     545       469194 :          numerator = DOT_PRODUCT(context%coefficients(igroup, :), context%cell_functions)
     546       156398 :          weights(igroup) = numerator/sum_density
     547       312796 :          IF (calculate_derivatives) THEN
     548              :             dpoint_numerator(:) = &
     549       137214 :                MATMUL(context%density_atom_derivative, context%coefficients(igroup, :))
     550        26136 :             dpoint_numerator = -dpoint_numerator
     551              :             point_derivative(:, igroup) = &
     552        26136 :                (dpoint_numerator*sum_density - numerator*dsum_point)/sum_density**2
     553        19602 :             DO atom = 1, context%natom
     554              :                atom_derivative(:, atom, igroup) = &
     555              :                   (context%coefficients(igroup, atom) - weights(igroup))* &
     556        58806 :                   context%density_atom_derivative(:, atom)/sum_density
     557              :             END DO
     558              :          END IF
     559              :       END DO
     560              :    END SUBROUTINE hirshfeld_point_weights
     561              : 
     562            0 : END MODULE qs_cdft_grid
        

Generated by: LCOV version 2.0-1