LCOV - code coverage report
Current view: top level - src - qs_dcdr_ao.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:24d69ee) Lines: 97.3 % 224 218
Test Date: 2026-09-03 07:32:15 Functions: 100.0 % 6 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 Calculate the derivatives of the MO coefficients wrt nuclear coordinates
      10              : !> \author Sandra Luber, Edward Ditler
      11              : ! **************************************************************************************************
      12              : 
      13              : MODULE qs_dcdr_ao
      14              : 
      15              :    USE basis_set_types,                 ONLY: gto_basis_set_p_type,&
      16              :                                               gto_basis_set_type
      17              :    USE cp_control_types,                ONLY: dft_control_type
      18              :    USE cp_dbcsr_api,                    ONLY: dbcsr_copy,&
      19              :                                               dbcsr_get_block_p,&
      20              :                                               dbcsr_p_type,&
      21              :                                               dbcsr_set,&
      22              :                                               dbcsr_type
      23              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      24              :                                               copy_fm_to_dbcsr
      25              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      26              :                                               cp_fm_release,&
      27              :                                               cp_fm_type
      28              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      29              :                                               cp_logger_type
      30              :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      31              :                                               section_vals_type
      32              :    USE kinds,                           ONLY: default_string_length,&
      33              :                                               dp
      34              :    USE orbital_pointers,                ONLY: ncoset
      35              :    USE parallel_gemm_api,               ONLY: parallel_gemm
      36              :    USE pw_env_types,                    ONLY: pw_env_get,&
      37              :                                               pw_env_type
      38              :    USE pw_methods,                      ONLY: pw_axpy,&
      39              :                                               pw_copy,&
      40              :                                               pw_scale,&
      41              :                                               pw_transfer,&
      42              :                                               pw_zero
      43              :    USE pw_poisson_methods,              ONLY: pw_poisson_solve
      44              :    USE pw_poisson_types,                ONLY: pw_poisson_type
      45              :    USE pw_pool_types,                   ONLY: pw_pool_p_type,&
      46              :                                               pw_pool_type
      47              :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      48              :                                               pw_r3d_rs_type
      49              :    USE qs_collocate_density,            ONLY: calculate_drho_core,&
      50              :                                               calculate_drho_elec_dR
      51              :    USE qs_core_matrices,                ONLY: core_matrices
      52              :    USE qs_energy_types,                 ONLY: qs_energy_type
      53              :    USE qs_environment_types,            ONLY: get_qs_env,&
      54              :                                               qs_environment_type
      55              :    USE qs_fxc,                          ONLY: qs_fxc_create
      56              :    USE qs_integral_utils,               ONLY: basis_set_list_setup,&
      57              :                                               get_memory_usage
      58              :    USE qs_integrate_potential,          ONLY: integrate_v_dbasis,&
      59              :                                               integrate_v_rspace
      60              :    USE qs_kind_types,                   ONLY: qs_kind_type
      61              :    USE qs_ks_types,                     ONLY: get_ks_env,&
      62              :                                               qs_ks_env_type
      63              :    USE qs_linres_types,                 ONLY: dcdr_env_type
      64              :    USE qs_neighbor_list_types,          ONLY: get_iterator_info,&
      65              :                                               get_neighbor_list_set_p,&
      66              :                                               neighbor_list_iterate,&
      67              :                                               neighbor_list_iterator_create,&
      68              :                                               neighbor_list_iterator_p_type,&
      69              :                                               neighbor_list_iterator_release,&
      70              :                                               neighbor_list_set_p_type
      71              :    USE qs_rho_atom_types,               ONLY: rho_atom_type
      72              :    USE qs_rho_methods,                  ONLY: qs_rho_rebuild,&
      73              :                                               qs_rho_update_rho
      74              :    USE qs_rho_types,                    ONLY: qs_rho_create,&
      75              :                                               qs_rho_get,&
      76              :                                               qs_rho_release,&
      77              :                                               qs_rho_set,&
      78              :                                               qs_rho_type
      79              :    USE qs_vxc,                          ONLY: qs_vxc_create
      80              : 
      81              : !$ USE OMP_LIB, ONLY: omp_get_max_threads, omp_get_thread_num, omp_get_num_threads
      82              : !$ USE OMP_LIB, ONLY: omp_lock_kind, &
      83              : !$                    omp_init_lock, omp_set_lock, &
      84              : !$                    omp_unset_lock, omp_destroy_lock
      85              : 
      86              : #include "./base/base_uses.f90"
      87              : 
      88              :    IMPLICIT NONE
      89              : 
      90              :    PRIVATE
      91              :    PUBLIC :: core_dR, d_vhxc_dR, d_core_charge_density_dR, apply_op_constant_term
      92              :    PUBLIC :: vhxc_R_perturbed_basis_functions
      93              :    PUBLIC :: hr_mult_by_delta_1d
      94              : 
      95              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_dcdr_ao'
      96              :    CHARACTER(len=*), PARAMETER, PRIVATE :: dcdr_meta_gga_error = &
      97              :                                 "Analytical DCDR is not implemented for functionals that depend on the kinetic energy density. "// &
      98              :                                            "Use PROPERTIES%LINRES%DCDR%APT_FD T to calculate APTs by finite differences."
      99              : 
     100              : CONTAINS
     101              : 
     102              : ! **************************************************************************************************
     103              : !> \brief Build the perturbed density matrix correction depending on the overlap derivative
     104              : !> \param qs_env ...
     105              : !> \param dcdr_env ...
     106              : !> \param overlap1 Overlap derivative in AO basis
     107              : !> \author Edward Ditler
     108              : ! **************************************************************************************************
     109          252 :    SUBROUTINE apply_op_constant_term(qs_env, dcdr_env, overlap1)
     110              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     111              :       TYPE(dcdr_env_type)                                :: dcdr_env
     112              :       TYPE(dbcsr_p_type), OPTIONAL                       :: overlap1
     113              : 
     114              :       CHARACTER(len=*), PARAMETER :: routineN = 'apply_op_constant_term'
     115              : 
     116              :       INTEGER                                            :: handle, ispin
     117              :       REAL(KIND=dp)                                      :: energy_hartree
     118              :       TYPE(cp_fm_type)                                   :: rho_ao_fm, rho_ao_s1, rho_ao_s1_rho_ao, &
     119              :                                                             s1_ao
     120          252 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: rho1_ao, rho_ao
     121              :       TYPE(pw_c1d_gs_type)                               :: rho1_tot_gspace, v_hartree_gspace
     122          252 :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER        :: rho1_g
     123              :       TYPE(pw_env_type), POINTER                         :: pw_env
     124              :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
     125              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     126              :       TYPE(pw_r3d_rs_type)                               :: v_hartree_rspace
     127          252 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r, v_rspace_new, v_xc, v_xc_tau
     128              :       TYPE(qs_rho_type), POINTER                         :: perturbed_density, rho
     129          252 :       TYPE(rho_atom_type), DIMENSION(:), POINTER         :: rho0_atom_set, rho1_atom_set
     130              :       TYPE(section_vals_type), POINTER                   :: input, xc_section
     131              : 
     132              :       ! Build the perturbed density matrix correction depending on the overlap derivative
     133              :       !   P1 = C0 C1 + C1 C0
     134              :       !        - C0_(mu j) S1_(jk) C0_(k nu)
     135              :       ! This routine is adapted from apply_op_2_dft. There, build_dm_response builds
     136              :       !  C0 * dCR + dCR * C0.
     137              :       ! build_dm_response is computing $-1 * (C^0 C^1 + C^1 C^0)$ and later on in the
     138              :       !  integration the factor 2 is applied to account for the occupancy.
     139              :       ! The sign is negative because the kernel is on the RHS of the Sternheimer equation.
     140              :       !
     141              :       ! The correction factor in this routine needs to have
     142              :       !      the opposite sign mathematically as (C0 C1 + C1 C0)
     143              :       !   so the same sign in the code     because of the $-1$ in dCR
     144              :       !   so the opposite sign in the code because we are on the LHS of the Sternheimer equation.
     145              :       !
     146              :       ! This term must not go into the kernel applied by the linear response solver, because
     147              :       !  for the (P)CG algorithm, all constant terms have to be on one side of the equations
     148              :       !  and all solution dependent terms must be on the other side.
     149              : 
     150          252 :       CALL timeset(routineN, handle)
     151              : 
     152          252 :       NULLIFY (auxbas_pw_pool, pw_env, v_xc, poisson_env, input, rho, &
     153          252 :                rho1_g, v_xc_tau)
     154              : 
     155          252 :       CALL cp_fm_create(rho_ao_fm, dcdr_env%aoao_fm_struct)
     156          252 :       CALL cp_fm_create(rho_ao_s1, dcdr_env%aoao_fm_struct)
     157          252 :       CALL cp_fm_create(rho_ao_s1_rho_ao, dcdr_env%aoao_fm_struct)
     158          252 :       CALL cp_fm_create(s1_ao, dcdr_env%aoao_fm_struct)
     159              : 
     160          252 :       IF (PRESENT(overlap1)) THEN
     161            0 :          CALL copy_dbcsr_to_fm(overlap1%matrix, s1_ao)
     162              :       ELSE
     163          252 :          CALL copy_dbcsr_to_fm(dcdr_env%matrix_s1(dcdr_env%beta + 1)%matrix, s1_ao)
     164              :       END IF
     165              : 
     166          576 :       DO ispin = 1, dcdr_env%nspins
     167          324 :          CALL dbcsr_set(dcdr_env%perturbed_dm_correction(ispin)%matrix, 0._dp)
     168          324 :          CALL dbcsr_set(dcdr_env%matrix_apply_op_constant(ispin)%matrix, 0.0_dp)
     169              : 
     170              :          CALL parallel_gemm('N', 'T', dcdr_env%nao, dcdr_env%nao, dcdr_env%nmo(ispin), &
     171              :                             1.0_dp, dcdr_env%mo_coeff(ispin), dcdr_env%mo_coeff(ispin), &
     172          324 :                             0.0_dp, rho_ao_fm)
     173              : 
     174              :          CALL parallel_gemm('N', 'N', dcdr_env%nao, dcdr_env%nao, dcdr_env%nao, &
     175              :                             1.0_dp, rho_ao_fm, s1_ao, &
     176          324 :                             0.0_dp, rho_ao_s1)
     177              : 
     178              :          CALL parallel_gemm('N', 'N', dcdr_env%nao, dcdr_env%nao, dcdr_env%nao, &
     179              :                             -1._dp, rho_ao_s1, rho_ao_fm, &   ! this is the sign mentioned above.
     180          324 :                             0.0_dp, rho_ao_s1_rho_ao)
     181              : 
     182          576 :          CALL copy_fm_to_dbcsr(rho_ao_s1_rho_ao, dcdr_env%perturbed_dm_correction(ispin)%matrix)
     183              :       END DO
     184              : 
     185          252 :       CALL cp_fm_release(rho_ao_fm)
     186          252 :       CALL cp_fm_release(rho_ao_s1)
     187          252 :       CALL cp_fm_release(rho_ao_s1_rho_ao)
     188          252 :       CALL cp_fm_release(s1_ao)
     189              :       ! Done building the density matrix correction
     190              : 
     191              :       ! Build the density struct from the environment
     192              :       NULLIFY (perturbed_density)
     193          252 :       ALLOCATE (perturbed_density)
     194          252 :       CALL qs_rho_create(perturbed_density)
     195          252 :       CALL qs_rho_rebuild(perturbed_density, qs_env=qs_env)
     196              : 
     197              :       ! ... set the density matrix to be the perturbed density matrix
     198          252 :       CALL qs_rho_get(perturbed_density, rho_ao=rho1_ao)
     199          576 :       DO ispin = 1, dcdr_env%nspins
     200          576 :          CALL dbcsr_copy(rho1_ao(ispin)%matrix, dcdr_env%perturbed_dm_correction(ispin)%matrix)
     201              :       END DO
     202              : 
     203              :       ! ... updates rho_r and rho_g to the rho%rho_ao.
     204              :       CALL qs_rho_update_rho(rho_struct=perturbed_density, &
     205          252 :                              qs_env=qs_env)
     206              : 
     207              :       ! Also update the qs_env%rho
     208          252 :       CALL get_qs_env(qs_env, rho=rho)
     209          252 :       CALL qs_rho_update_rho(rho, qs_env=qs_env)
     210          252 :       CALL qs_rho_get(rho, rho_ao=rho_ao, rho_r=rho_r)
     211              : 
     212              :       energy_hartree = 0.0_dp
     213              : 
     214              :       CALL get_qs_env(qs_env=qs_env, &
     215              :                       pw_env=pw_env, &
     216          252 :                       input=input)
     217              : 
     218              :       ! Create the temporary grids
     219              :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
     220          252 :                       poisson_env=poisson_env)
     221              : 
     222          252 :       xc_section => section_vals_get_subs_vals(input, "DFT%XC")
     223              : 
     224         1080 :       ALLOCATE (v_rspace_new(dcdr_env%nspins))
     225          252 :       CALL auxbas_pw_pool%create_pw(v_hartree_gspace)
     226          252 :       CALL auxbas_pw_pool%create_pw(v_hartree_rspace)
     227              : 
     228              :       ! Calculate the Hartree potential on the total density
     229          252 :       CALL auxbas_pw_pool%create_pw(rho1_tot_gspace)
     230              : 
     231          252 :       CALL qs_rho_get(perturbed_density, rho_g=rho1_g)
     232          252 :       CALL pw_copy(rho1_g(1), rho1_tot_gspace)
     233          324 :       DO ispin = 2, dcdr_env%nspins
     234          324 :          CALL pw_axpy(rho1_g(ispin), rho1_tot_gspace)
     235              :       END DO
     236              : 
     237              :       CALL pw_poisson_solve(poisson_env, rho1_tot_gspace, &
     238              :                             energy_hartree, &
     239          252 :                             v_hartree_gspace)
     240          252 :       CALL pw_transfer(v_hartree_gspace, v_hartree_rspace)
     241              : 
     242          252 :       CALL auxbas_pw_pool%give_back_pw(rho1_tot_gspace)
     243              : 
     244              :       ! Calculate the second derivative of the exchange-correlation potential
     245              :       CALL qs_fxc_create(qs_env, rho, perturbed_density, rho0_atom_set, xc_section, &
     246          252 :                          .FALSE., v_xc, v_xc_tau, rho1_atom_set)
     247              :       !
     248              : 
     249          576 :       DO ispin = 1, dcdr_env%nspins
     250          576 :          v_rspace_new(ispin) = v_xc(ispin)
     251              :       END DO
     252          252 :       DEALLOCATE (v_xc)
     253              : 
     254              :       ! Done calculating the potentials
     255              : 
     256              :       !-------------------------------!
     257              :       ! Add both hartree and xc terms !
     258              :       !-------------------------------!
     259          252 :       CALL pw_scale(v_hartree_rspace, v_hartree_rspace%pw_grid%dvol)
     260          576 :       DO ispin = 1, dcdr_env%nspins
     261          576 :          CALL pw_scale(v_rspace_new(ispin), v_rspace_new(ispin)%pw_grid%dvol)
     262              :       END DO
     263              : 
     264          576 :       DO ispin = 1, dcdr_env%nspins
     265          324 :          CALL dbcsr_set(dcdr_env%matrix_apply_op_constant(ispin)%matrix, 0.0_dp)
     266          324 :          CALL pw_axpy(v_hartree_rspace, v_rspace_new(ispin))
     267          324 :          IF (dcdr_env%nspins == 1) THEN
     268          180 :             CALL pw_scale(v_rspace_new(1), 2.0_dp)
     269              :          END IF
     270              : 
     271              :          CALL integrate_v_rspace(v_rspace=v_rspace_new(ispin), &
     272              :                                  hmat=dcdr_env%matrix_apply_op_constant(ispin), &
     273              :                                  qs_env=qs_env, &
     274          576 :                                  calculate_forces=.FALSE.)
     275              :       END DO
     276              : 
     277          252 :       CALL auxbas_pw_pool%give_back_pw(v_hartree_gspace)
     278          252 :       CALL auxbas_pw_pool%give_back_pw(v_hartree_rspace)
     279          576 :       DO ispin = 1, dcdr_env%nspins
     280          576 :          CALL auxbas_pw_pool%give_back_pw(v_rspace_new(ispin))
     281              :       END DO
     282          252 :       DEALLOCATE (v_rspace_new)
     283              : 
     284          252 :       IF (ASSOCIATED(v_xc_tau)) THEN
     285            0 :          CALL pw_scale(v_xc_tau(1), 2._dp*v_xc_tau(1)%pw_grid%dvol)
     286              :          CALL integrate_v_rspace(v_rspace=v_xc_tau(1), &
     287              :                                  hmat=dcdr_env%matrix_apply_op_constant(1), &
     288              :                                  qs_env=qs_env, &
     289              :                                  compute_tau=.TRUE., &
     290            0 :                                  calculate_forces=.FALSE.)
     291              : 
     292            0 :          CALL auxbas_pw_pool%give_back_pw(v_xc_tau(1))
     293            0 :          DEALLOCATE (v_xc_tau)
     294              :       END IF
     295              : 
     296          252 :       CALL qs_rho_release(perturbed_density)
     297          252 :       DEALLOCATE (perturbed_density)
     298              : 
     299          252 :       CALL timestop(handle)
     300              : 
     301          756 :    END SUBROUTINE apply_op_constant_term
     302              : 
     303              : ! **************************************************************************************************
     304              : !> \brief Calculate the derivative of the Hartree term due to the core charge density
     305              : !> \param qs_env ...
     306              : !> \param dcdr_env ...
     307              : !> \author Edward Ditler
     308              : ! **************************************************************************************************
     309           72 :    SUBROUTINE d_core_charge_density_dR(qs_env, dcdr_env)
     310              :       ! drho_core contribution
     311              :       ! sum over all directions
     312              :       ! output in ao x ao
     313              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     314              :       TYPE(dcdr_env_type)                                :: dcdr_env
     315              : 
     316              :       CHARACTER(len=*), PARAMETER :: routineN = 'd_core_charge_density_dR'
     317              : 
     318              :       INTEGER                                            :: beta, handle
     319              :       TYPE(cp_logger_type), POINTER                      :: logger
     320              :       TYPE(dft_control_type), POINTER                    :: dft_control
     321              :       TYPE(pw_c1d_gs_type)                               :: drho_g, v_hartree_gspace
     322              :       TYPE(pw_env_type), POINTER                         :: pw_env
     323              :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
     324           72 :       TYPE(pw_pool_p_type), DIMENSION(:), POINTER        :: pw_pools
     325              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     326              :       TYPE(pw_r3d_rs_type)                               :: v_hartree_rspace
     327              :       TYPE(qs_rho_type), POINTER                         :: rho
     328              : 
     329           72 :       CALL timeset(routineN, handle)
     330              : 
     331           72 :       logger => cp_get_default_logger()
     332              : 
     333           72 :       NULLIFY (pw_env, auxbas_pw_pool, pw_pools, poisson_env, dft_control, &
     334           72 :                rho)
     335              : 
     336              :       CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, rho=rho, &
     337           72 :                       dft_control=dft_control)
     338              : 
     339              :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, poisson_env=poisson_env, &
     340           72 :                       pw_pools=pw_pools)
     341              : 
     342              :       ! Create the Hartree potential grids in real and reciprocal space.
     343           72 :       CALL auxbas_pw_pool%create_pw(v_hartree_gspace)
     344           72 :       CALL auxbas_pw_pool%create_pw(v_hartree_rspace)
     345              :       ! Create the grid for the derivative of the core potential
     346           72 :       CALL auxbas_pw_pool%create_pw(drho_g)
     347              : 
     348          288 :       DO beta = 1, 3
     349          216 :          CALL pw_zero(v_hartree_gspace)
     350          216 :          CALL pw_zero(v_hartree_rspace)
     351          216 :          CALL pw_zero(drho_g)
     352              : 
     353              :          ! Calculate the Hartree potential on the perturbed density and Poisson solve it
     354              :          CALL calculate_drho_core(drho_core=drho_g, qs_env=qs_env, &
     355          216 :                                   beta=beta, lambda=dcdr_env%lambda)
     356              :          CALL pw_poisson_solve(poisson_env, drho_g, &
     357          216 :                                vhartree=v_hartree_gspace)
     358          216 :          CALL pw_transfer(v_hartree_gspace, v_hartree_rspace)
     359          216 :          CALL pw_scale(v_hartree_rspace, v_hartree_rspace%pw_grid%dvol)
     360              : 
     361              :          ! Calculate the integrals
     362              :          CALL integrate_v_rspace(v_rspace=v_hartree_rspace, &
     363              :                                  hmat=dcdr_env%matrix_core_charge_1(beta), &
     364              :                                  qs_env=qs_env, &
     365          288 :                                  calculate_forces=.FALSE.)
     366              :       END DO
     367              : 
     368           72 :       CALL auxbas_pw_pool%give_back_pw(drho_g)
     369           72 :       CALL auxbas_pw_pool%give_back_pw(v_hartree_rspace)
     370           72 :       CALL auxbas_pw_pool%give_back_pw(v_hartree_gspace)
     371              : 
     372           72 :       CALL timestop(handle)
     373           72 :    END SUBROUTINE d_core_charge_density_dR
     374              : 
     375              : ! **************************************************************************************************
     376              : !> \brief Core Hamiltonian contributions to the operator (the pseudopotentials)
     377              : !> \param qs_env ...
     378              : !> \param dcdr_env ..
     379              : !> \author Edward Ditler
     380              : ! **************************************************************************************************
     381           72 :    SUBROUTINE core_dR(qs_env, dcdr_env)
     382              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     383              :       TYPE(dcdr_env_type)                                :: dcdr_env
     384              : 
     385              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'core_dR'
     386              : 
     387              :       CHARACTER(LEN=default_string_length)               :: my_basis_type
     388              :       INTEGER                                            :: handle, nder
     389              :       LOGICAL                                            :: calculate_forces
     390           72 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: rho_ao
     391           72 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_h, matrix_p_pass
     392              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     393              :       TYPE(qs_rho_type), POINTER                         :: rho
     394              : 
     395           72 :       CALL timeset(routineN, handle)
     396              : 
     397           72 :       CALL get_qs_env(qs_env=qs_env, ks_env=ks_env)
     398           72 :       CALL get_ks_env(ks_env=ks_env, rho=rho)
     399           72 :       CALL qs_rho_get(rho, rho_ao=rho_ao)
     400              : 
     401           72 :       nder = 1
     402           72 :       calculate_forces = .FALSE.
     403              : 
     404              :       my_basis_type = "ORB"
     405              : 
     406           72 :       NULLIFY (matrix_h)
     407           72 :       matrix_p_pass(1:1, 1:1) => rho_ao(1:1)
     408              :       CALL core_matrices(qs_env, matrix_h, matrix_p_pass, calculate_forces, nder, &
     409           72 :                          dcdr_env=dcdr_env)
     410              : 
     411           72 :       CALL timestop(handle)
     412              : 
     413           72 :    END SUBROUTINE core_dR
     414              : 
     415              : ! **************************************************************************************************
     416              : !> \brief The derivatives of the basis functions going into the HXC potential wrt nuclear positions
     417              : !> \param qs_env ...
     418              : !> \param dcdr_env ...
     419              : !> \author Edward Ditler
     420              : ! **************************************************************************************************
     421           72 :    SUBROUTINE d_vhxc_dR(qs_env, dcdr_env)
     422              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     423              :       TYPE(dcdr_env_type)                                :: dcdr_env
     424              : 
     425              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'd_vhxc_dR'
     426              : 
     427              :       INTEGER                                            :: handle, idir, ispin
     428           72 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: rho_ao
     429              :       TYPE(pw_c1d_gs_type)                               :: drho_g_total, v_hartree_gspace
     430           72 :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER        :: drho_g
     431              :       TYPE(pw_env_type), POINTER                         :: pw_env
     432              :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
     433           72 :       TYPE(pw_pool_p_type), DIMENSION(:), POINTER        :: pw_pools
     434              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     435              :       TYPE(pw_r3d_rs_type)                               :: drho_r_total, v_hartree_rspace
     436           72 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: drho_r, dtau_r, rho_r, v_xc, v_xc_tau
     437              :       TYPE(qs_rho_type), POINTER                         :: drho, rho
     438           72 :       TYPE(rho_atom_type), DIMENSION(:), POINTER         :: rho0_atom_set, rho1_atom_set
     439              :       TYPE(section_vals_type), POINTER                   :: input, xc_section
     440              : 
     441           72 :       CALL timeset(routineN, handle)
     442              : 
     443              :       CALL get_qs_env(qs_env=qs_env, &
     444              :                       pw_env=pw_env, &
     445              :                       input=input, &
     446           72 :                       rho=rho)
     447           72 :       CALL qs_rho_get(rho, rho_ao=rho_ao, rho_r=rho_r)
     448              : 
     449           72 :       xc_section => section_vals_get_subs_vals(input, "DFT%XC")
     450              : 
     451              :       ! get the tmp grids
     452          300 :       ALLOCATE (drho_r(dcdr_env%nspins))
     453          300 :       ALLOCATE (drho_g(dcdr_env%nspins))
     454              : 
     455              :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
     456           72 :                       pw_pools=pw_pools, poisson_env=poisson_env)
     457           72 :       CALL auxbas_pw_pool%create_pw(v_hartree_gspace)
     458           72 :       CALL auxbas_pw_pool%create_pw(v_hartree_rspace)
     459              : 
     460          156 :       DO ispin = 1, dcdr_env%nspins
     461           84 :          CALL auxbas_pw_pool%create_pw(drho_r(ispin))
     462          156 :          CALL auxbas_pw_pool%create_pw(drho_g(ispin))
     463              :       END DO
     464           72 :       CALL auxbas_pw_pool%create_pw(drho_g_total)
     465           72 :       CALL auxbas_pw_pool%create_pw(drho_r_total)
     466              : 
     467          288 :       DO idir = 1, 3
     468          216 :          CALL pw_zero(v_hartree_gspace)
     469          216 :          CALL pw_zero(v_hartree_rspace)
     470          216 :          CALL pw_zero(drho_g_total)
     471          216 :          CALL pw_zero(drho_r_total)
     472              : 
     473          468 :          DO ispin = 1, dcdr_env%nspins
     474          252 :             CALL pw_zero(drho_r(ispin))
     475          252 :             CALL pw_zero(drho_g(ispin))
     476              : 
     477              :             ! Get the density
     478              :             CALL calculate_drho_elec_dR(matrix_p=rho_ao(ispin)%matrix, &
     479              :                                         drho=drho_r(ispin), &
     480              :                                         drho_gspace=drho_g(ispin), &
     481              :                                         qs_env=qs_env, &
     482          252 :                                         beta=idir, lambda=dcdr_env%lambda)
     483              : 
     484          252 :             CALL pw_axpy(drho_g(ispin), drho_g_total)
     485          468 :             CALL pw_axpy(drho_r(ispin), drho_r_total)
     486              :          END DO
     487              :          ! Get the Hartree potential corresponding to the perturbed density
     488              :          CALL pw_poisson_solve(poisson_env, drho_g_total, &
     489          216 :                                vhartree=v_hartree_gspace)
     490          216 :          CALL pw_transfer(v_hartree_gspace, v_hartree_rspace)
     491              : 
     492          216 :          ALLOCATE (drho)
     493          216 :          CALL qs_rho_create(drho)
     494          216 :          IF (ASSOCIATED(drho_r)) THEN
     495          216 :             CALL qs_rho_set(drho, rho_r=drho_r, rho_r_valid=.TRUE.)
     496              :          END IF
     497          216 :          IF (ASSOCIATED(drho_g)) THEN
     498          216 :             CALL qs_rho_set(drho, rho_g=drho_g, rho_g_valid=.TRUE.)
     499              :          END IF
     500          216 :          IF (ASSOCIATED(dtau_r)) THEN
     501          183 :             CALL qs_rho_set(drho, tau_r=dtau_r, tau_r_valid=.TRUE.)
     502              :          END IF
     503              :          !
     504          216 :          NULLIFY (v_xc, v_xc_tau)
     505              :          CALL qs_fxc_create(qs_env, rho, drho, rho0_atom_set, xc_section, .FALSE., &
     506          216 :                             v_xc, v_xc_tau, rho1_atom_set)
     507              :          !
     508          216 :          DEALLOCATE (drho)
     509              : 
     510          216 :          IF (ASSOCIATED(v_xc_tau)) THEN
     511            0 :             CPABORT(dcdr_meta_gga_error)
     512              :          END IF
     513              : 
     514              :          !-------------------------------!
     515              :          ! Add both hartree and xc terms !
     516              :          !-------------------------------!
     517          468 :          DO ispin = 1, dcdr_env%nspins
     518              :             ! Can the dvol be different?
     519          252 :             CALL pw_scale(v_xc(ispin), v_xc(ispin)%pw_grid%dvol)
     520          252 :             CALL pw_axpy(v_hartree_rspace, v_xc(ispin), v_hartree_rspace%pw_grid%dvol)
     521              : 
     522              :             CALL integrate_v_rspace(v_rspace=v_xc(ispin), &
     523              :                                     hmat=dcdr_env%matrix_d_vhxc_dR(idir, ispin), &
     524              :                                     qs_env=qs_env, &
     525          252 :                                     calculate_forces=.FALSE.)
     526              : 
     527              :             ! v_xc gets allocated again in xc_calc_2nd_deriv
     528          468 :             CALL auxbas_pw_pool%give_back_pw(v_xc(ispin))
     529              :          END DO ! ispin
     530          504 :          DEALLOCATE (v_xc)
     531              :       END DO ! idir
     532              : 
     533           72 :       CALL auxbas_pw_pool%give_back_pw(v_hartree_gspace)
     534           72 :       CALL auxbas_pw_pool%give_back_pw(v_hartree_rspace)
     535           72 :       CALL auxbas_pw_pool%give_back_pw(drho_g_total)
     536           72 :       CALL auxbas_pw_pool%give_back_pw(drho_r_total)
     537              : 
     538          156 :       DO ispin = 1, dcdr_env%nspins
     539           84 :          CALL auxbas_pw_pool%give_back_pw(drho_g(ispin))
     540          156 :          CALL auxbas_pw_pool%give_back_pw(drho_r(ispin))
     541              :       END DO
     542              : 
     543           72 :       DEALLOCATE (drho_g)
     544           72 :       DEALLOCATE (drho_r)
     545              : 
     546           72 :       CALL timestop(handle)
     547              : 
     548           72 :    END SUBROUTINE d_vhxc_dR
     549              : 
     550              : ! **************************************************************************************************
     551              : !> \brief The derivatives of the basis functions over which the HXC potential is integrated,
     552              : !>          so < da/dR | Vhxc | b >
     553              : !> \param qs_env ...
     554              : !> \param dcdr_env ...
     555              : !> \author Edward Ditler
     556              : ! **************************************************************************************************
     557           72 :    SUBROUTINE vhxc_R_perturbed_basis_functions(qs_env, dcdr_env)
     558              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     559              :       TYPE(dcdr_env_type)                                :: dcdr_env
     560              : 
     561              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'vhxc_R_perturbed_basis_functions'
     562              : 
     563              :       INTEGER                                            :: handle, ispin
     564           72 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_vhxc_dbasis
     565           72 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_p
     566              :       TYPE(pw_env_type), POINTER                         :: pw_env
     567              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     568           72 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: v_hxc_r, v_tau_rspace
     569              :       TYPE(pw_r3d_rs_type), POINTER                      :: v_hartree_r
     570              :       TYPE(qs_energy_type), POINTER                      :: energy
     571              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     572              :       TYPE(qs_rho_type), POINTER                         :: rho_struct
     573              :       TYPE(section_vals_type), POINTER                   :: input, xc_section
     574              : 
     575           72 :       CALL timeset(routineN, handle)
     576              : 
     577           72 :       NULLIFY (rho_struct, energy, input, ks_env, pw_env, matrix_p)
     578              :       CALL get_qs_env(qs_env, &
     579              :                       rho=rho_struct, &
     580              :                       energy=energy, &
     581              :                       input=input, &
     582              :                       ks_env=ks_env, &
     583              :                       pw_env=pw_env, &
     584           72 :                       v_hartree_rspace=v_hartree_r)
     585           72 :       CALL qs_rho_get(rho_struct, rho_ao_kp=matrix_p)
     586           72 :       xc_section => section_vals_get_subs_vals(input, "DFT%XC")
     587              : 
     588           72 :       NULLIFY (auxbas_pw_pool)
     589           72 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
     590              : 
     591              :       ! *** calculate the xc potential on the pw density ***
     592              :       ! *** associates v_hxc_r if the xc potential needs to be computed.
     593              :       ! If we do wavefunction fitting, we need the vxc_potential in the auxiliary basis set
     594           72 :       NULLIFY (v_hxc_r, v_tau_rspace)
     595              :       CALL qs_vxc_create(ks_env=ks_env, rho_struct=rho_struct, xc_section=xc_section, &
     596           72 :                          vxc_rho=v_hxc_r, vxc_tau=v_tau_rspace, exc=energy%exc)
     597              : 
     598          156 :       DO ispin = 1, dcdr_env%nspins
     599           84 :          CALL pw_scale(v_hxc_r(ispin), v_hxc_r(ispin)%pw_grid%dvol)
     600              : 
     601              :          ! sum up potentials and integrate
     602           84 :          CALL pw_axpy(v_hartree_r, v_hxc_r(ispin), 1._dp)
     603              : 
     604           84 :          matrix_vhxc_dbasis => dcdr_env%matrix_vhxc_perturbed_basis(ispin, :)
     605              :          CALL integrate_v_dbasis(v_rspace=v_hxc_r(ispin), &
     606              :                                  matrix_p=matrix_p(ispin, 1)%matrix, &
     607              :                                  matrix_vhxc_dbasis=matrix_vhxc_dbasis, &
     608              :                                  qs_env=qs_env, &
     609           84 :                                  lambda=dcdr_env%lambda)
     610              : 
     611          156 :          CALL auxbas_pw_pool%give_back_pw(v_hxc_r(ispin))
     612              :       END DO
     613              : 
     614           72 :       DEALLOCATE (v_hxc_r)
     615              : 
     616           72 :       CALL timestop(handle)
     617           72 :    END SUBROUTINE vhxc_R_perturbed_basis_functions
     618              : 
     619              : ! **************************************************************************************************
     620              : !> \brief Enforce that one of the basis functions in < a | O | b > is centered on atom lambda.
     621              : !> \param matrix ...
     622              : !> \param qs_kind_set ...
     623              : !> \param basis_type ...
     624              : !> \param sab_nl ...
     625              : !> \param lambda Atom index
     626              : !> \param direction_Or True: < a | O | b==lambda >, False: < a==lambda | O | b >
     627              : ! **************************************************************************************************
     628         2610 :    SUBROUTINE hr_mult_by_delta_1d(matrix, qs_kind_set, basis_type, sab_nl, lambda, direction_Or)
     629              : 
     630              :       TYPE(dbcsr_type), POINTER                          :: matrix
     631              :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     632              :       CHARACTER(LEN=*), INTENT(IN)                       :: basis_type
     633              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     634              :          POINTER                                         :: sab_nl
     635              :       INTEGER, INTENT(IN)                                :: lambda
     636              :       LOGICAL, INTENT(IN)                                :: direction_Or
     637              : 
     638              :       CHARACTER(len=*), PARAMETER :: routineN = 'hr_mult_by_delta_1d'
     639              : 
     640              :       INTEGER                                            :: handle, iatom, icol, ikind, irow, jatom, &
     641              :                                                             jkind, ldsab, mepos, nkind, nseta, &
     642              :                                                             nsetb, nthread
     643              :       INTEGER, DIMENSION(3)                              :: cell
     644         2610 :       INTEGER, DIMENSION(:), POINTER                     :: la_max, la_min, lb_max, lb_min, npgfa, &
     645         2610 :                                                             npgfb, nsgfa, nsgfb
     646         2610 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgfa, first_sgfb
     647              :       LOGICAL                                            :: do_symmetric, found
     648              :       REAL(KIND=dp), DIMENSION(3)                        :: rab
     649         2610 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: set_radius_a, set_radius_b
     650         2610 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: k_block, rpgfa, rpgfb, scon_a, scon_b, &
     651         2610 :                                                             zeta, zetb
     652         2610 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list
     653              :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
     654              :       TYPE(neighbor_list_iterator_p_type), &
     655         2610 :          DIMENSION(:), POINTER                           :: nl_iterator
     656              : 
     657         2610 :       CALL timeset(routineN, handle)
     658              : 
     659         2610 :       nkind = SIZE(qs_kind_set)
     660              : 
     661              :       ! check for symmetry
     662         2610 :       CPASSERT(SIZE(sab_nl) > 0)
     663         2610 :       CALL get_neighbor_list_set_p(neighbor_list_sets=sab_nl, symmetric=do_symmetric)
     664              : 
     665              :       ! prepare basis set
     666        13050 :       ALLOCATE (basis_set_list(nkind))
     667         2610 :       CALL basis_set_list_setup(basis_set_list, basis_type, qs_kind_set)
     668              : 
     669              :       ! *** Allocate work storage ***
     670         2610 :       ldsab = get_memory_usage(qs_kind_set, basis_type)
     671              : 
     672              :       nthread = 1
     673         2610 : !$    nthread = omp_get_max_threads()
     674              :       ! Iterate of neighbor list
     675         2610 :       CALL neighbor_list_iterator_create(nl_iterator, sab_nl, nthread=nthread)
     676              : 
     677              : !$OMP PARALLEL DEFAULT(NONE) &
     678              : !$OMP SHARED (nthread,ldsab,nl_iterator, do_symmetric) &
     679              : !$OMP SHARED (ncoset,matrix,basis_set_list) &
     680              : !$OMP SHARED (direction_or, lambda) &
     681              : !$OMP PRIVATE (k_block,mepos,ikind,jkind,iatom,jatom,rab,cell) &
     682              : !$OMP PRIVATE (basis_set_a,basis_set_b) &
     683              : !$OMP PRIVATE (first_sgfa, la_max, la_min, npgfa, nsgfa, nseta, rpgfa, set_radius_a) &
     684              : !$OMP PRIVATE (zeta, first_sgfb, lb_max, lb_min, npgfb, nsetb, rpgfb, set_radius_b, nsgfb) &
     685         2610 : !$OMP PRIVATE (zetb, scon_a, scon_b, irow, icol, found)
     686              : 
     687              :       mepos = 0
     688              : !$    mepos = omp_get_thread_num()
     689              : 
     690              :       DO WHILE (neighbor_list_iterate(nl_iterator, mepos=mepos) == 0)
     691              :          CALL get_iterator_info(nl_iterator, mepos=mepos, ikind=ikind, jkind=jkind, &
     692              :                                 iatom=iatom, jatom=jatom, r=rab, cell=cell)
     693              :          basis_set_a => basis_set_list(ikind)%gto_basis_set
     694              :          IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
     695              :          basis_set_b => basis_set_list(jkind)%gto_basis_set
     696              :          IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
     697              :          ! basis ikind
     698              :          first_sgfa => basis_set_a%first_sgf
     699              :          la_max => basis_set_a%lmax
     700              :          la_min => basis_set_a%lmin
     701              :          npgfa => basis_set_a%npgf
     702              :          nseta = basis_set_a%nset
     703              :          nsgfa => basis_set_a%nsgf_set
     704              :          rpgfa => basis_set_a%pgf_radius
     705              :          set_radius_a => basis_set_a%set_radius
     706              :          scon_a => basis_set_a%scon
     707              :          zeta => basis_set_a%zet
     708              :          ! basis jkind
     709              :          first_sgfb => basis_set_b%first_sgf
     710              :          lb_max => basis_set_b%lmax
     711              :          lb_min => basis_set_b%lmin
     712              :          npgfb => basis_set_b%npgf
     713              :          nsetb = basis_set_b%nset
     714              :          nsgfb => basis_set_b%nsgf_set
     715              :          rpgfb => basis_set_b%pgf_radius
     716              :          set_radius_b => basis_set_b%set_radius
     717              :          scon_b => basis_set_b%scon
     718              :          zetb => basis_set_b%zet
     719              : 
     720              :          IF (do_symmetric) THEN
     721              :             IF (iatom <= jatom) THEN
     722              :                irow = iatom
     723              :                icol = jatom
     724              :             ELSE
     725              :                irow = jatom
     726              :                icol = iatom
     727              :             END IF
     728              :          ELSE
     729              :             irow = iatom
     730              :             icol = jatom
     731              :          END IF
     732              : 
     733              :          NULLIFY (k_block)
     734              :          CALL dbcsr_get_block_p(matrix, irow, icol, k_block, found)
     735              :          CPASSERT(found)
     736              : 
     737              :          IF (direction_Or) THEN
     738              :             IF (jatom /= lambda) k_block(:, :) = 0._dp
     739              :          ELSE IF (.NOT. direction_Or) THEN
     740              :             IF (iatom /= lambda) k_block(:, :) = 0._dp
     741              :          END IF
     742              :       END DO
     743              : !$OMP END PARALLEL
     744         2610 :       CALL neighbor_list_iterator_release(nl_iterator)
     745              : 
     746              :       ! Release work storage
     747         2610 :       DEALLOCATE (basis_set_list)
     748              : 
     749         2610 :       CALL timestop(handle)
     750              : 
     751         5220 :    END SUBROUTINE hr_mult_by_delta_1d
     752              : 
     753              : END MODULE qs_dcdr_ao
        

Generated by: LCOV version 2.0-1