SF-TDDFT implementation (#4446)

The linear-response TDDFT module was extended to spin-flip excitations. This extension is
capable to make collinear and noncollinear SF-TDDFT calculations. Some key details of the
implementation are:

  - The noncollinear kernel used is the Wang & Ziegler kernel with a screening in the
    denominator to stabilize it
  - The noncollinear kernel derivative is calculated by finite differences
This commit is contained in:
Luis I Hernández Segura 2025-09-21 10:31:49 +02:00 committed by GitHub
parent 916bf6ee98
commit b69419fcbe
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
39 changed files with 3072 additions and 663 deletions

View file

@ -499,6 +499,8 @@ MODULE cp_control_types
INTEGER :: nprocs = 0
!> type of kernel function/approximation to use
INTEGER :: kernel = 0
!> type of spin excitations to compute
INTEGER :: spinflip = 0
!> for full kernel, do we have HFX/ADMM
LOGICAL :: do_hfx = .FALSE.
LOGICAL :: do_admm = .FALSE.

View file

@ -1674,6 +1674,7 @@ CONTAINS
CALL section_vals_val_get(t_section, "NLUMO", i_val=t_control%nlumo)
CALL section_vals_val_get(t_section, "NPROC_STATE", i_val=t_control%nprocs)
CALL section_vals_val_get(t_section, "KERNEL", i_val=t_control%kernel)
CALL section_vals_val_get(t_section, "SPINFLIP", i_val=t_control%spinflip)
CALL section_vals_val_get(t_section, "OE_CORR", i_val=t_control%oe_corr)
CALL section_vals_val_get(t_section, "EV_SHIFT", r_val=t_control%ev_shift)
CALL section_vals_val_get(t_section, "EOS_SHIFT", r_val=t_control%eos_shift)

View file

@ -106,6 +106,7 @@ CONTAINS
CALL set_qs_env(qs_env, force=lr_force)
!
tdlr_section => section_vals_get_subs_vals(qs_env%input, "PROPERTIES%TDDFPT%LINRES")
! Solve the Z-vector linear equation system
CALL response_equation(qs_env, p_env, ex_env%cpmos, unit_nr, tdlr_section)
!
CALL get_qs_env(qs_env, dft_control=dft_control)
@ -120,7 +121,7 @@ CONTAINS
CALL response_force(qs_env=qs_env, vh_rspace=ex_env%vh_rspace, &
vxc_rspace=ex_env%vxc_rspace, vtau_rspace=ex_env%vtau_rspace, &
vadmm_rspace=ex_env%vadmm_rspace, matrix_hz=ex_env%matrix_hz, &
matrix_pz=ex_env%matrix_px1, matrix_pz_admm=p_env%p1_admm, &
matrix_pz=p_env%p1, matrix_pz_admm=p_env%p1_admm, &
matrix_wz=p_env%w1, &
p_env=p_env, ex_env=ex_env, &
debug=ex_env%debug_forces)

View file

@ -113,7 +113,7 @@ CONTAINS
! **************************************************************************************************
SUBROUTINE derivatives_four_center(qs_env, rho_ao, rho_ao_resp, hfx_section, para_env, &
irep, use_virial, adiabatic_rescale_factor, resp_only, &
external_x_data)
external_x_data, nspins)
TYPE(qs_environment_type), POINTER :: qs_env
TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: rho_ao
@ -125,6 +125,7 @@ CONTAINS
REAL(dp), INTENT(IN), OPTIONAL :: adiabatic_rescale_factor
LOGICAL, INTENT(IN), OPTIONAL :: resp_only
TYPE(hfx_type), DIMENSION(:, :), POINTER, OPTIONAL :: external_x_data
INTEGER, INTENT(IN), OPTIONAL :: nspins
CHARACTER(LEN=*), PARAMETER :: routineN = 'derivatives_four_center'
@ -138,7 +139,7 @@ CONTAINS
INTEGER :: kind_kind_idx, kkind, kset, l_atom, l_max, latom, latom_block, latom_end, &
latom_start, lkind, lset, max_am, max_pgf, max_set, my_bin_id, my_bin_size, my_thread_id, &
n_threads, natom, nbits, ncob, ncos_max, nints, nkimages, nkind, nneighbors, nseta, &
nsetb, nsgf_max, nspins, sgfb, shm_task_counter, shm_total_bins, sphi_a_u1, sphi_a_u2, &
nsetb, nsgf_max, my_nspins, sgfb, shm_task_counter, shm_total_bins, sphi_a_u1, sphi_a_u2, &
sphi_a_u3, sphi_b_u1, sphi_b_u2, sphi_b_u3, sphi_c_u1, sphi_c_u2, sphi_c_u3, sphi_d_u1, &
sphi_d_u2, sphi_d_u3, swap_id, tmp_i4, unit_id
INTEGER(int_8) :: atom_block, counter, estimate_to_store_int, max_val_memory, &
@ -239,7 +240,11 @@ CONTAINS
cell=cell, &
dft_control=dft_control)
nspins = dft_control%nspins
IF (PRESENT(nspins)) THEN
my_nspins = nspins
ELSE
my_nspins = dft_control%nspins
END IF
nkimages = dft_control%nimages
CPASSERT(nkimages == 1)
@ -337,7 +342,7 @@ CONTAINS
!$OMP shm_pmax_atom,&
!$OMP use_virial,&
!$OMP do_print_load_balance_info,&
!$OMP nkimages,nspins,my_x_data)&
!$OMP nkimages,my_nspins,my_x_data)&
!$OMP PRIVATE(actual_x_data,atomic_kind_set,atomic_offset_ac,atomic_offset_ad,atomic_offset_bc,&
!$OMP atomic_offset_bd,atom_of_kind,basis_info,&
!$OMP basis_parameter,bin,bins_left,bintime_start,bintime_stop,bits_max_val,buffer_left,buffer_overflow,buffer_size,&
@ -514,7 +519,7 @@ CONTAINS
antisymmetric=is_anti_symmetric)
END IF
IF (nspins == 2) THEN
IF (my_nspins == 2) THEN
ALLOCATE (full_density_beta(shm_block_offset(ncpu + 1), 1))
CALL get_full_density(para_env, full_density_beta(:, 1), rho_ao(2, 1)%matrix, shm_number_of_p_entries, &
shm_block_offset, &
@ -555,7 +560,7 @@ CONTAINS
! maybe in the future
IF (with_resp_density .AND. .NOT. my_resp_only) THEN
full_density_alpha(:, 1) = full_density_alpha(:, 1) - full_density_resp
IF (nspins == 2) THEN
IF (my_nspins == 2) THEN
full_density_beta(:, 1) = &
full_density_beta(:, 1) - full_density_resp_beta
END IF
@ -638,7 +643,7 @@ CONTAINS
ALLOCATE (pad_buf_resp(nsgf_max**2))
ALLOCATE (pac_buf_resp(nsgf_max**2))
END IF
IF (nspins == 2) THEN
IF (my_nspins == 2) THEN
ALLOCATE (pbd_buf_beta(nsgf_max**2))
ALLOCATE (pbc_buf_beta(nsgf_max**2))
ALLOCATE (pad_buf_beta(nsgf_max**2))
@ -1035,7 +1040,7 @@ CONTAINS
forces_map(4, 1) = lkind
forces_map(4, 2) = l_atom
IF (nspins == 1) THEN
IF (my_nspins == 1) THEN
fac = 0.25_dp*hf_fraction
ELSE
fac = 0.5_dp*hf_fraction
@ -1339,8 +1344,8 @@ CONTAINS
spherical_estimate = MAX(spherical_estimate, ABS(primitive_forces(i)))
END DO
spherical_estimate_virial = 0.0_dp
IF (use_virial) THEN
spherical_estimate_virial = 0.0_dp
DO i = 1, 3*nints
spherical_estimate_virial = MAX(spherical_estimate_virial, ABS(primitive_forces_virial(i)))
END DO
@ -1414,7 +1419,7 @@ CONTAINS
offset_ad_set, offset_ac_set, atomic_offset_bd, atomic_offset_bc, &
atomic_offset_ad, atomic_offset_ac, is_anti_symmetric)
END IF
IF (nspins == 2) THEN
IF (my_nspins == 2) THEN
IF (with_resp_density) THEN
CALL prefetch_density_matrix(nsgfa(iset), nsgfb(jset), nsgfc(kset), nsgfd(lset), &
full_density_beta(:, 1), pbd_buf_beta, pbc_buf_beta, &
@ -1453,7 +1458,7 @@ CONTAINS
pbd_buf, pbc_buf, pad_buf, pac_buf, fac, &
T2, force, forces_map, coord)
END IF
IF (nspins == 2) THEN
IF (my_nspins == 2) THEN
IF (with_resp_density) THEN
CALL update_forces(nsgfa(iset), nsgfb(jset), nsgfc(kset), nsgfd(lset), &
pbd_buf_beta, pbc_buf_beta, pad_buf_beta, pac_buf_beta, &
@ -1486,7 +1491,7 @@ CONTAINS
pbd_buf, pbc_buf, pad_buf, pac_buf, fac, &
T2, tmp_virial, coord, i)
END IF
IF (nspins == 2) THEN
IF (my_nspins == 2) THEN
IF (with_resp_density) THEN
CALL update_virial(nsgfa(iset), nsgfb(jset), nsgfc(kset), nsgfd(lset), &
pbd_buf_beta, pbc_buf_beta, pad_buf_beta, pac_buf_beta, &
@ -1684,7 +1689,7 @@ CONTAINS
IF (with_resp_density) THEN
DEALLOCATE (full_density_resp)
END IF
IF (nspins == 2) THEN
IF (my_nspins == 2) THEN
DEALLOCATE (full_density_beta)
IF (with_resp_density) THEN
DEALLOCATE (full_density_resp_beta)
@ -1728,7 +1733,7 @@ CONTAINS
DEALLOCATE (nimages)
IF (nspins == 2) THEN
IF (my_nspins == 2) THEN
DEALLOCATE (pbd_buf_beta, pbc_buf_beta, pad_buf_beta, pac_buf_beta)
IF (with_resp_density) THEN
DEALLOCATE (pbd_buf_resp_beta)

View file

@ -133,7 +133,7 @@ CONTAINS
! **************************************************************************************************
SUBROUTINE integrate_four_center(qs_env, x_data, ks_matrix, ehfx, rho_ao, hfx_section, para_env, &
geometry_did_change, irep, distribute_fock_matrix, &
ispin)
ispin, nspins)
TYPE(qs_environment_type), POINTER :: qs_env
TYPE(hfx_type), DIMENSION(:, :), POINTER :: x_data
@ -146,6 +146,7 @@ CONTAINS
INTEGER :: irep
LOGICAL, INTENT(IN) :: distribute_fock_matrix
INTEGER, INTENT(IN) :: ispin
INTEGER, INTENT(IN), OPTIONAL :: nspins
CHARACTER(LEN=*), PARAMETER :: routineN = 'integrate_four_center'
@ -161,7 +162,7 @@ CONTAINS
INTEGER :: katom_start, kind_kind_idx, kkind, kset, l_max, latom, latom_block, latom_end, &
latom_start, lkind, lset, ma, max_am, max_pgf, max_set, mb, my_bin_id, my_bin_size, &
my_thread_id, n_threads, natom, nbits, ncob, ncos_max, nints, nkimages, nkind, &
nneighbors, nseta, nsetb, nsgf_max, nspins, pa, sgfb, shm_task_counter, shm_total_bins, &
nneighbors, nseta, nsetb, nsgf_max, my_nspins, pa, sgfb, shm_task_counter, shm_total_bins, &
sphi_a_u1, sphi_a_u2, sphi_a_u3, sphi_b_u1, sphi_b_u2, sphi_b_u3, sphi_c_u1, sphi_c_u2, &
sphi_c_u3, sphi_d_u1, sphi_d_u2, sphi_d_u3, swap_id, tmp_i4, unit_id
INTEGER(int_8) :: atom_block, counter, estimate_to_store_int, max_val_memory, &
@ -313,6 +314,10 @@ CONTAINS
n_threads = 1
!$ n_threads = omp_get_max_threads()
! This initialization is needed to prevent a segmentation fault. The correct assigment is done below
my_nspins = 0
IF (PRESENT(nspins)) my_nspins = nspins
shm_neris_total = 0
shm_nprim_ints = 0
shm_neris_onthefly = 0
@ -374,7 +379,8 @@ CONTAINS
!$OMP shm_pmax_block,&
!$OMP shm_atomic_pair_list,&
!$OMP shm_mem_compression_counter,&
!$OMP do_print_load_balance_info) &
!$OMP do_print_load_balance_info,&
!$OMP my_nspins) &
!$OMP PRIVATE(ln_10,i_thread,actual_x_data,do_periodic,screening_parameter,potential_parameter,&
!$OMP general_parameter,load_balance_parameter,memory_parameter,cache_size,bits_max_val,&
!$OMP basis_parameter,basis_info,treat_lsd_in_core,ncpu,n_processes,neris_total,neris_incore,&
@ -382,7 +388,7 @@ CONTAINS
!$OMP compression_factor_disk,nprim_ints,neris_tmp,max_val_memory,max_am,do_p_screening,&
!$OMP max_set,particle_set,atomic_kind_set,natom,kind_of,ncos_max,nsgf_max,ikind,&
!$OMP nseta,npgfa,la_max,nsgfa,primitive_integrals,pbd_buf,pbc_buf,pad_buf,pac_buf,kbd_buf,kbc_buf,&
!$OMP kad_buf,kac_buf,ee_work,ee_work2,ee_buffer1,ee_buffer2,ee_primitives_tmp,nspins,max_contraction,&
!$OMP kad_buf,kac_buf,ee_work,ee_work2,ee_buffer1,ee_buffer2,ee_primitives_tmp,max_contraction,&
!$OMP max_pgf,jkind,lb_max,nsetb,npgfb,first_sgfb,sphi_b,nsgfb,ncob,sgfb,nneighbors,pgf_list_ij,pgf_list_kl,&
!$OMP pgf_product_list,nimages,ks_fully_occ,subtr_size_mb,use_disk_storage,counter,do_disk_storage,&
!$OMP maxval_container_disk,maxval_cache_disk,integral_containers_disk,integral_caches_disk,eps_schwarz,&
@ -517,7 +523,7 @@ CONTAINS
ALLOCATE (ee_buffer2(ncos_max**4))
ALLOCATE (ee_primitives_tmp(nsgf_max**4))
nspins = dft_control%nspins
IF (my_nspins .EQ. 0) my_nspins = dft_control%nspins
ALLOCATE (max_contraction(max_set, natom))
@ -607,7 +613,7 @@ CONTAINS
subtr_size_mb = 2_int_8*shm_block_offset(ncpu + 1)
! ** if non restricted ==> alpha/beta spin
IF (.NOT. treat_lsd_in_core) THEN
IF (nspins == 2) subtr_size_mb = subtr_size_mb*2_int_8
IF (my_nspins == 2) subtr_size_mb = subtr_size_mb*2_int_8
END IF
! ** Initial P only MAX(alpha,beta) (shared)
IF (do_p_screening .OR. screening_parameter%do_p_screening_forces) THEN
@ -719,7 +725,7 @@ CONTAINS
!! Get the full density from all the processors
NULLIFY (full_density_alpha, full_density_beta)
ALLOCATE (full_density_alpha(shm_block_offset(ncpu + 1), nkimages))
IF (.NOT. treat_lsd_in_core .OR. nspins == 1) THEN
IF (.NOT. treat_lsd_in_core .OR. my_nspins == 1) THEN
CALL timeset(routineN//"_getP", handle_getP)
DO img = 1, nkimages
CALL get_full_density(para_env, full_density_alpha(:, img), rho_ao(ispin, img)%matrix, shm_number_of_p_entries, &
@ -727,7 +733,7 @@ CONTAINS
kind_of, basis_parameter, get_max_vals_spin=.FALSE., antisymmetric=is_anti_symmetric)
END DO
IF (nspins == 2) THEN
IF (my_nspins == 2) THEN
ALLOCATE (full_density_beta(shm_block_offset(ncpu + 1), nkimages))
DO img = 1, nkimages
CALL get_full_density(para_env, full_density_beta(:, img), rho_ao(2, img)%matrix, shm_number_of_p_entries, &
@ -798,7 +804,7 @@ CONTAINS
full_ks_alpha = 0.0_dp
IF (.NOT. treat_lsd_in_core) THEN
IF (nspins == 2) THEN
IF (my_nspins == 2) THEN
ALLOCATE (shm_master_x_data%full_ks_beta(shm_block_offset(ncpu + 1), nkimages))
full_ks_beta => shm_master_x_data%full_ks_beta
full_ks_beta = 0.0_dp
@ -840,7 +846,7 @@ CONTAINS
!$OMP BARRIER
!! Initialize a prefactor depending on the fraction and the number of spins
IF (nspins == 1) THEN
IF (my_nspins == 1) THEN
fac = 0.5_dp*hf_fraction
ELSE
fac = 1.0_dp*hf_fraction
@ -1679,7 +1685,7 @@ CONTAINS
iset, jset, kset, lset, offset_bd_set, offset_bc_set, offset_ad_set, offset_ac_set, &
atomic_offset_bd, atomic_offset_bc, atomic_offset_ad, atomic_offset_ac)
IF (.NOT. treat_lsd_in_core) THEN
IF (nspins == 2) THEN
IF (my_nspins == 2) THEN
CALL update_fock_matrix( &
nsgfa(iset), nsgfb(jset), nsgfc(kset), nsgfd(lset), &
fac, symm_fac, full_density_beta(:, 1), full_ks_beta(:, 1), &
@ -1699,7 +1705,7 @@ CONTAINS
iset, jset, kset, lset, offset_bd_set, offset_bc_set, offset_ad_set, offset_ac_set, &
atomic_offset_bd, atomic_offset_bc, atomic_offset_ad, atomic_offset_ac)
IF (.NOT. treat_lsd_in_core) THEN
IF (nspins == 2) THEN
IF (my_nspins == 2) THEN
CALL update_fock_matrix_as( &
nsgfa(iset), nsgfb(jset), nsgfc(kset), nsgfd(lset), &
fac, symm_fac, full_density_beta(:, 1), full_ks_beta(:, 1), &
@ -1807,7 +1813,7 @@ CONTAINS
mb_size_p = shm_block_offset(ncpu + 1)/1024/128
mb_size_f = shm_block_offset(ncpu + 1)/1024/128
IF (.NOT. treat_lsd_in_core) THEN
IF (nspins == 2) THEN
IF (my_nspins == 2) THEN
mb_size_f = mb_size_f*2
mb_size_p = mb_size_p*2
END IF
@ -1872,7 +1878,7 @@ CONTAINS
IF (i > j) THEN
full_ks_alpha(i, img) = (full_ks_alpha(i, img) + full_ks_alpha(j, img)*afac)
full_ks_alpha(j, img) = full_ks_alpha(i, img)*afac
IF (.NOT. treat_lsd_in_core .AND. nspins == 2) THEN
IF (.NOT. treat_lsd_in_core .AND. my_nspins == 2) THEN
full_ks_beta(i, img) = (full_ks_beta(i, img) + full_ks_beta(j, img)*afac)
full_ks_beta(j, img) = full_ks_beta(i, img)*afac
END IF
@ -1880,7 +1886,7 @@ CONTAINS
! ** For adiabatically rescaled functionals we need the energy coming from the diagonal elements
IF (i == j) THEN
ene_x_aa_diag = ene_x_aa_diag + full_ks_alpha(i, img)*full_density_alpha(i, img)
IF (.NOT. treat_lsd_in_core .AND. nspins == 2) THEN
IF (.NOT. treat_lsd_in_core .AND. my_nspins == 2) THEN
ene_x_bb_diag = ene_x_bb_diag + full_ks_beta(i, img)*full_density_beta(i, img)
END IF
END IF
@ -1908,7 +1914,7 @@ CONTAINS
NULLIFY (full_ks_alpha)
DEALLOCATE (shm_master_x_data%full_ks_alpha)
IF (.NOT. treat_lsd_in_core) THEN
IF (nspins == 2) THEN
IF (my_nspins == 2) THEN
DO img = 1, nkimages
CALL distribute_ks_matrix(para_env, full_ks_beta(:, img), ks_matrix(2, img)%matrix, shm_number_of_p_entries, &
shm_block_offset, kind_of, basis_parameter, &
@ -1936,7 +1942,7 @@ CONTAINS
END IF
ene_x_bb = 0.0_dp
IF (nspins == 2 .AND. .NOT. treat_lsd_in_core) THEN
IF (my_nspins == 2 .AND. .NOT. treat_lsd_in_core) THEN
DO img = 1, nkimages
CALL dbcsr_dot_threadsafe(ks_matrix(2, img)%matrix, rho_ao(2, img)%matrix, etmp)
ene_x_bb = ene_x_bb + etmp
@ -1961,7 +1967,7 @@ CONTAINS
END DO
! ** Now correct
ene_x_aa = (ene_x_aa + ene_x_aa_diag)*0.5_dp
IF (nspins == 2) THEN
IF (my_nspins == 2) THEN
DO img = 1, nkimages
DO pa = 1, SIZE(full_ks_beta, 1)
ene_x_bb = ene_x_bb + full_ks_beta(pa, img)*full_density_beta(pa, img)
@ -1971,7 +1977,7 @@ CONTAINS
ene_x_bb = (ene_x_bb + ene_x_bb_diag)*0.5_dp
END IF
CALL para_env%sum(ene_x_aa)
IF (nspins == 2) CALL para_env%sum(ene_x_bb)
IF (my_nspins == 2) CALL para_env%sum(ene_x_bb)
ehfx = 0.5_dp*(ene_x_aa + ene_x_bb)
END IF
@ -2126,7 +2132,7 @@ CONTAINS
!$OMP MASTER
DEALLOCATE (full_density_alpha)
IF (.NOT. treat_lsd_in_core) THEN
IF (nspins == 2) THEN
IF (my_nspins == 2) THEN
DEALLOCATE (full_density_beta)
END IF
END IF

View file

@ -583,6 +583,9 @@ MODULE input_constants
INTEGER, PARAMETER, PUBLIC :: tddfpt_kernel_none = 2, &
tddfpt_kernel_full = 1, &
tddfpt_kernel_stda = 0
INTEGER, PARAMETER, PUBLIC :: no_sf_tddfpt = 0, &
tddfpt_sf_col = 1, &
tddfpt_sf_noncol = 2
INTEGER, PARAMETER, PUBLIC :: oe_none = 0, &
oe_lb = 1, &
oe_gllb = 2, &

View file

@ -38,8 +38,8 @@ MODULE input_cp2k_properties_dft
ot_precond_full_single, ot_precond_full_single_inverse, ot_precond_none, &
ot_precond_s_inverse, scan_x, scan_xy, scan_xyz, scan_xz, scan_y, scan_yz, scan_z, &
tddfpt_dipole_berry, tddfpt_dipole_length, tddfpt_dipole_velocity, tddfpt_kernel_full, &
tddfpt_kernel_none, tddfpt_kernel_stda, use_mom_ref_coac, use_mom_ref_com, &
use_mom_ref_user, use_mom_ref_zero
tddfpt_kernel_none, tddfpt_kernel_stda, no_sf_tddfpt, tddfpt_sf_col, tddfpt_sf_noncol, &
use_mom_ref_coac, use_mom_ref_com, use_mom_ref_user, use_mom_ref_zero
USE input_cp2k_atprop, ONLY: create_atprop_section
USE input_cp2k_dft, ONLY: create_interp_section, &
create_mgrid_section
@ -1508,7 +1508,7 @@ CONTAINS
"Density Functional Perturbation Theory. "// &
"Current implementation works for hybrid functionals. "// &
"Can be used with Gaussian and Plane Waves (GPW) method only.", &
n_keywords=12, n_subsections=4, repeats=.FALSE., &
n_keywords=14, n_subsections=4, repeats=.FALSE., &
citations=(/Iannuzzi2005/))
NULLIFY (keyword, print_key, subsection)
@ -1570,6 +1570,16 @@ CONTAINS
CALL section_add_keyword(section, keyword)
CALL keyword_release(keyword)
! spin-flip TDDFPT options
CALL keyword_create(keyword, __LOCATION__, name="SPINFLIP", &
description="Selects the type of spin-flip TDDFPT kernel", &
usage="SPINFLIP NONCOLLINEAR", &
enum_c_vals=s2a("NONE", "COLLINEAR", "NONCOLLINEAR"), &
enum_i_vals=(/no_sf_tddfpt, tddfpt_sf_col, tddfpt_sf_noncol/), &
default_i_val=no_sf_tddfpt)
CALL section_add_keyword(section, keyword)
CALL keyword_release(keyword)
CALL keyword_create(keyword, __LOCATION__, name="OE_CORR", &
description="Orbital energy correction potential.", &
enum_c_vals=s2a("NONE", "LB94", "GLLB", "SAOP", "SHIFT"), &

View file

@ -159,8 +159,10 @@ CONTAINS
END IF
IF (.NOT. loverlap_deltat) THEN
! Calculate energy, response vector and some contributions to the force
CALL qs_energies_properties(qs_env, calc_forces)
! Update total energy of the selected excited state
CALL excited_state_energy(qs_env, calculate_forces=.FALSE.)
END IF

View file

@ -84,7 +84,8 @@ CONTAINS
! **************************************************************************************************
!> \brief Refactoring of qs_energies_scf. Moves computation of properties
!> into separate subroutine
!> into separate subroutine. Calculates energy and if calc_forces then the response vector
!> and some contributions to the force
!> \param qs_env ...
!> \param calc_forces ...
!> \par History
@ -191,10 +192,12 @@ CONTAINS
END IF
! Compute Linear Response properties as post-scf
! Initialization of TDDFPT calculation
IF (.NOT. qs_env%linres_run) THEN
CALL linres_calculation_low(qs_env)
END IF
! Calculates the energy, response vector and some contributions to the force
IF (dft_control%tddfpt2_control%enabled) THEN
CALL tddfpt(qs_env, calc_forces)
END IF

View file

@ -197,7 +197,7 @@ CONTAINS
dft_control%qs_control%cdft_control%save_pot = .TRUE.
END IF
! recalculate energy with forces
! recalculate energy and the response vector for the Z-vector linear equation system if calc_force = .true.
CALL qs_energies(qs_env, calc_forces=.TRUE.)
NULLIFY (para_env)
@ -374,6 +374,8 @@ CONTAINS
END IF
! Excited state forces
! Solve the response linear equation system for the Z-vector method
! and calculate remaining terms of the force
CALL excited_state_energy(qs_env, calculate_forces=.TRUE.)
! replicate forces (get current pointer)

View file

@ -27,7 +27,9 @@
MODULE qs_fxc
USE cp_control_types, ONLY: dft_control_type
USE input_section_types, ONLY: section_vals_get_subs_vals,&
USE input_section_types, ONLY: section_get_ival,&
section_get_rval,&
section_vals_get_subs_vals,&
section_vals_type
USE kinds, ONLY: dp
USE pw_env_types, ONLY: pw_env_get,&
@ -41,20 +43,26 @@ MODULE qs_fxc
USE qs_ks_types, ONLY: get_ks_env,&
qs_ks_env_type
USE qs_rho_methods, ONLY: qs_rho_copy,&
qs_rho_scale_and_add
qs_rho_scale_and_add,&
qs_rho_scale_and_add_b
USE qs_rho_types, ONLY: qs_rho_create,&
qs_rho_get,&
qs_rho_release,&
qs_rho_type
USE qs_vxc, ONLY: qs_vxc_create
USE xc, ONLY: xc_calc_2nd_deriv,&
xc_prep_2nd_deriv
xc_calc_2nd_deriv_analytical,&
xc_calc_3rd_deriv_analytical,&
xc_prep_2nd_deriv,&
xc_prep_3rd_deriv
USE xc_derivative_set_types, ONLY: xc_derivative_set_type,&
xc_dset_release
USE xc_derivatives, ONLY: xc_functionals_get_needs
USE xc_rho_cflags_types, ONLY: xc_rho_cflags_type
USE xc_rho_set_types, ONLY: xc_rho_set_release,&
xc_rho_set_type
USE xc_rho_set_types, ONLY: xc_rho_set_create,&
xc_rho_set_release,&
xc_rho_set_type,&
xc_rho_set_update
#include "./base/base_uses.f90"
IMPLICIT NONE
@ -62,7 +70,7 @@ MODULE qs_fxc
PRIVATE
! *** Public subroutines ***
PUBLIC :: qs_fxc_fdiff, qs_fxc_analytic, qs_fgxc_gdiff, qs_fgxc_create, qs_fgxc_release
PUBLIC :: qs_fxc_fdiff, qs_fxc_analytic, qs_fgxc_gdiff, qs_fgxc_analytic, qs_fgxc_create, qs_fgxc_release
CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_fxc'
@ -80,8 +88,9 @@ CONTAINS
!> \param is_triplet ...
!> \param v_xc ...
!> \param v_xc_tau ...
!> \param spinflip ...
! **************************************************************************************************
SUBROUTINE qs_fxc_analytic(rho0, rho1_r, tau1_r, xc_section, auxbas_pw_pool, is_triplet, v_xc, v_xc_tau)
SUBROUTINE qs_fxc_analytic(rho0, rho1_r, tau1_r, xc_section, auxbas_pw_pool, is_triplet, v_xc, v_xc_tau, spinflip)
TYPE(qs_rho_type), POINTER :: rho0
TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho1_r, tau1_r
@ -89,12 +98,13 @@ CONTAINS
TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
LOGICAL, INTENT(IN) :: is_triplet
TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: v_xc, v_xc_tau
LOGICAL, OPTIONAL :: spinflip
CHARACTER(len=*), PARAMETER :: routineN = 'qs_fxc_analytic'
INTEGER :: handle, nspins
INTEGER, DIMENSION(2, 3) :: bo
LOGICAL :: lsd
LOGICAL :: do_sf, lsd
REAL(KIND=dp) :: fac
TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho0_g, rho1_g
TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho0_r, tau0_r
@ -108,6 +118,9 @@ CONTAINS
CPASSERT(.NOT. ASSOCIATED(v_xc))
CPASSERT(.NOT. ASSOCIATED(v_xc_tau))
do_sf = .FALSE.
IF (PRESENT(spinflip)) do_sf = spinflip
CALL qs_rho_get(rho0, rho_r=rho0_r, rho_g=rho0_g, tau_r=tau0_r)
nspins = SIZE(rho0_r)
@ -119,10 +132,12 @@ CONTAINS
bo = rho1_r(1)%pw_grid%bounds_local
xc_fun_section => section_vals_get_subs_vals(xc_section, "XC_FUNCTIONAL")
needs = xc_functionals_get_needs(xc_fun_section, lsd, .TRUE.)
! calculate the arguments needed by the functionals
! calculate the arguments needed by the functionals and the values of the functional on the grid
CALL xc_prep_2nd_deriv(deriv_set, rho0_set, rho0_r, auxbas_pw_pool, xc_section=xc_section, tau_r=tau0_r)
! Folds the density rho1 with the functional
CALL xc_calc_2nd_deriv(v_xc, v_xc_tau, deriv_set, rho0_set, rho1_r, rho1_g, tau1_r, &
auxbas_pw_pool, xc_section=xc_section, gapw=.FALSE., do_triplet=is_triplet)
auxbas_pw_pool, xc_section=xc_section, gapw=.FALSE., do_triplet=is_triplet, &
do_sf=do_sf)
CALL xc_dset_release(deriv_set)
CALL xc_rho_set_release(rho0_set)
@ -265,6 +280,161 @@ CONTAINS
END SUBROUTINE qs_fxc_fdiff
! **************************************************************************************************
!> \brief Calculates the values at the grid points in real space (r_i), of the second and third
!> functional derivatives of the exchange-correlation energy functional.
!> fxc_rho(r_i) = fxc[n](r_i)*n^(1)(r_i) ! Second functional derivative
!> gxc_rho(r_i) = n^(1)(r_i)*gxc[n](r_i)*n^(1)(r_i) ! Third functional derivative
!> \param rho0_struct Ground state density, n(r).
!> \param rho1_struct Density used to fold the functional derivatives, n^(1)(r).
!> \param xc_section ...
!> \param pw_pool ...
!> \param fxc_rho Second functional derivative with respect to the density, n(r).
!> \param fxc_tau mGGA contribution to the second functional derivative with respect to the density.
!> \param gxc_rho Third functional derivative with respect to the density, n(r).
!> \param gxc_tau mGGA contribution to the third functional derivative with respect to the density.
!> \param spinflip Flag used to activate the spin-flip noncollinear kernel and kernel derivatives.
!> \par History
!> * 07.2024 Created [LHS]
! **************************************************************************************************
SUBROUTINE qs_fgxc_analytic(rho0_struct, rho1_struct, xc_section, pw_pool, &
fxc_rho, fxc_tau, gxc_rho, gxc_tau, spinflip)
TYPE(qs_rho_type), POINTER :: rho0_struct, rho1_struct
TYPE(section_vals_type), POINTER :: xc_section
TYPE(pw_pool_type), POINTER :: pw_pool
TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: fxc_rho, fxc_tau, gxc_rho, gxc_tau
LOGICAL, INTENT(IN), OPTIONAL :: spinflip
CHARACTER(len=*), PARAMETER :: routineN = 'qs_fgxc_analytic'
INTEGER :: handle, ispin, nspins, spindim
INTEGER, DIMENSION(2, 3) :: bo
LOGICAL :: do_sf, lsd
REAL(KIND=dp) :: fac
TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho0_g, rho1_g
TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho0_r, rho1_r, tau0_r, tau1_r
TYPE(section_vals_type), POINTER :: xc_fun_section
TYPE(xc_derivative_set_type) :: deriv_set
TYPE(xc_rho_cflags_type) :: needs
TYPE(xc_rho_set_type) :: rho0_set, rho1_set
CALL timeset(routineN, handle)
! Only rho0 and rho1 should be associated
CPASSERT(.NOT. ASSOCIATED(fxc_rho))
CPASSERT(.NOT. ASSOCIATED(fxc_tau))
CPASSERT(.NOT. ASSOCIATED(gxc_rho))
CPASSERT(.NOT. ASSOCIATED(gxc_tau))
CPASSERT(ASSOCIATED(rho0_struct))
CPASSERT(ASSOCIATED(rho1_struct))
! Initialize parameters
do_sf = .FALSE.
IF (PRESENT(spinflip)) do_sf = spinflip
!
! Get the values on the gridpoints of the rho0 density
CALL qs_rho_get(rho0_struct, rho_r=rho0_r, rho_g=rho0_g, tau_r=tau0_r)
nspins = SIZE(rho0_r)
lsd = (nspins == 2)
!
IF (do_sf) THEN
spindim = 1
ELSE
spindim = nspins
END IF
!
fac = 0._dp
IF (nspins == 1) THEN
fac = 1.0_dp
END IF
! Read xc functional section and find out what the functional actually needs
xc_fun_section => section_vals_get_subs_vals(xc_section, "XC_FUNCTIONAL")
needs = xc_functionals_get_needs(xc_fun_section, lsd, .TRUE.)
! Create fields for the kernel and kernel derivative
ALLOCATE (fxc_rho(spindim), gxc_rho(nspins))
DO ispin = 1, spindim
CALL pw_pool%create_pw(fxc_rho(ispin))
CALL pw_zero(fxc_rho(ispin))
END DO
DO ispin = 1, nspins
CALL pw_pool%create_pw(gxc_rho(ispin))
CALL pw_zero(gxc_rho(ispin))
END DO
! Create fields for mGGA functionals. This implementation is not ready yet!
IF (needs%tau .OR. needs%tau_spin) THEN
IF (.NOT. ASSOCIATED(tau1_r)) &
CPABORT("Tau-dependent functionals requires allocated kinetic energy density grid")
ALLOCATE (fxc_tau(spindim), gxc_tau(nspins))
DO ispin = 1, spindim
CALL pw_pool%create_pw(fxc_tau(ispin))
CALL pw_zero(fxc_tau(ispin))
END DO
DO ispin = 1, nspins
CALL pw_pool%create_pw(gxc_tau(ispin))
CALL pw_zero(gxc_tau(ispin))
END DO
END IF
! Build rho0_set
! calculate the arguments needed by the functionals
! Needs
! deriv_set xc_derivative_set_type just declared
! rho0_set xc_rho_set_type just declared
! rho0_r pw_type calculated by qs_rho_get
! pw_pool given by the calling subroutine
! xc_section given by the calling subroutine
! tau0_r pw_type calculated by qs_rho_get
CALL xc_prep_3rd_deriv(deriv_set, rho0_set, rho0_r, pw_pool, xc_section, tau_r=tau0_r, &
do_sf=do_sf)
! Build rho1_set
! Get the values on the gridpoints of the rho1 density
CALL qs_rho_get(rho1_struct, rho_r=rho1_r, rho_g=rho1_g, tau_r=tau1_r)
bo = rho1_r(1)%pw_grid%bounds_local
! create the place where to store the argument for the functionals
! Needs
! rho1_set xc_rho_set_type just declared
! bo 2x3 integer matrix should have bounds_local or rho1_r
CALL xc_rho_set_create(rho1_set, bo, &
rho_cutoff=section_get_rval(xc_section, "DENSITY_CUTOFF"), &
drho_cutoff=section_get_rval(xc_section, "GRADIENT_CUTOFF"), &
tau_cutoff=section_get_rval(xc_section, "TAU_CUTOFF"))
! calculate the arguments needed by the functionals
! Needs
! rho1_set object created by xc_rho_set_create
! rho1_r,rho1_g,tau1_r pw_type values of rho1 in real space grid
! needs xc_rho_cflags_type defined through xc_functionals_get_needs
! pw_pool Given by the calling subroutine
CALL xc_rho_set_update(rho1_set, rho1_r, rho1_g, tau1_r, needs, &
section_get_ival(xc_section, "XC_GRID%XC_DERIV"), &
section_get_ival(xc_section, "XC_GRID%XC_SMOOTH_RHO"), &
pw_pool, spinflip=do_sf)
! Calculate exchange correlation kernel
! Needs
! fxc_rho, fxc_tau pw_type not associated
! deriv_set created and defined by xc_prep_3rd_deriv
! rho0_set xc_rho_set_type build by xc_prep_3rd_deriv
! rho1_set xc_rho_set_type build by xc_rho_set_create/update
! pw_pool needs to be given by the calling subroutine
! xc_section needs to be given by the calling subroutine
CALL xc_calc_2nd_deriv_analytical(fxc_rho, fxc_tau, deriv_set, rho0_set, rho1_set, pw_pool, &
xc_section, .FALSE., spinflip=do_sf, tddfpt_fac=fac)
! Calculate exchange correlation kernel derivative
CALL xc_calc_3rd_deriv_analytical(gxc_rho, gxc_tau, deriv_set, rho0_set, rho1_set, pw_pool, &
xc_section, spinflip=do_sf)
CALL xc_dset_release(deriv_set)
CALL xc_rho_set_release(rho0_set)
CALL xc_rho_set_release(rho1_set)
CALL timestop(handle)
END SUBROUTINE qs_fgxc_analytic
! **************************************************************************************************
!> \brief ...
!> \param ks_env ...
@ -278,9 +448,10 @@ CONTAINS
!> \param fxc_tau ...
!> \param gxc_rho ...
!> \param gxc_tau ...
!> \param spinflip ...
! **************************************************************************************************
SUBROUTINE qs_fgxc_gdiff(ks_env, rho0_struct, rho1_struct, xc_section, accuracy, epsrho, &
is_triplet, fxc_rho, fxc_tau, gxc_rho, gxc_tau)
is_triplet, fxc_rho, fxc_tau, gxc_rho, gxc_tau, spinflip)
TYPE(qs_ks_env_type), POINTER :: ks_env
TYPE(qs_rho_type), POINTER :: rho0_struct, rho1_struct
@ -289,16 +460,19 @@ CONTAINS
REAL(KIND=dp), INTENT(IN) :: epsrho
LOGICAL, INTENT(IN) :: is_triplet
TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: fxc_rho, fxc_tau, gxc_rho, gxc_tau
LOGICAL, OPTIONAL :: spinflip
CHARACTER(len=*), PARAMETER :: routineN = 'qs_fgxc_gdiff'
INTEGER :: handle, ispin, istep, nspins, nstep
LOGICAL :: do_sf
REAL(KIND=dp) :: alpha, beta, exc, oeps1
REAL(KIND=dp), DIMENSION(-4:4) :: ak
TYPE(dft_control_type), POINTER :: dft_control
TYPE(pw_env_type), POINTER :: pw_env
TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: v_tau_rspace, vxc00
TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho1_r, tau1_r, v_tau_rspace, vxc00, &
vxc00b
TYPE(qs_rho_type), POINTER :: rhoin
CALL timeset(routineN, handle)
@ -310,6 +484,9 @@ CONTAINS
CPASSERT(ASSOCIATED(rho0_struct))
CPASSERT(ASSOCIATED(rho1_struct))
do_sf = .FALSE.
IF (PRESENT(spinflip)) do_sf = spinflip
ak = 0.0_dp
SELECT CASE (accuracy)
CASE (:4)
@ -330,8 +507,14 @@ CONTAINS
nspins = dft_control%nspins
exc = 0.0_dp
CALL qs_fxc_fdiff(ks_env, rho0_struct, rho1_struct, xc_section, accuracy, is_triplet, &
fxc_rho, fxc_tau)
IF (do_sf) THEN
CALL qs_rho_get(rho1_struct, rho_r=rho1_r, tau_r=tau1_r)
CALL qs_fxc_analytic(rho0_struct, rho1_r, tau1_r, xc_section, &
auxbas_pw_pool, is_triplet, fxc_rho, fxc_tau, spinflip=do_sf)
ELSE
CALL qs_fxc_fdiff(ks_env, rho0_struct, rho1_struct, xc_section, accuracy, is_triplet, &
fxc_rho, fxc_tau)
END IF
DO istep = -nstep, nstep
@ -341,12 +524,25 @@ CONTAINS
NULLIFY (rhoin)
ALLOCATE (rhoin)
CALL qs_rho_create(rhoin)
NULLIFY (vxc00, v_tau_rspace)
NULLIFY (vxc00, vxc00b, v_tau_rspace)
CALL qs_rho_copy(rho0_struct, rhoin, auxbas_pw_pool, nspins)
CALL qs_rho_scale_and_add(rhoin, rho1_struct, alpha, beta)
CALL qs_fxc_fdiff(ks_env=ks_env, rho0_struct=rhoin, rho1_struct=rho1_struct, &
xc_section=xc_section, accuracy=accuracy, is_triplet=is_triplet, &
fxc_rho=vxc00, fxc_tau=v_tau_rspace)
IF (do_sf) THEN
! variation in alpha density
CALL qs_fxc_analytic(rhoin, rho1_r, tau1_r, &
xc_section, auxbas_pw_pool, is_triplet, &
vxc00, v_tau_rspace, spinflip=do_sf)
! variation in beta density
CALL qs_rho_copy(rho0_struct, rhoin, auxbas_pw_pool, nspins)
CALL qs_rho_scale_and_add_b(rhoin, rho1_struct, alpha, beta)
CALL qs_fxc_analytic(rhoin, rho1_r, tau1_r, &
xc_section, auxbas_pw_pool, is_triplet, &
vxc00b, v_tau_rspace, spinflip=do_sf)
ELSE
CALL qs_fxc_fdiff(ks_env=ks_env, rho0_struct=rhoin, rho1_struct=rho1_struct, &
xc_section=xc_section, accuracy=accuracy, is_triplet=is_triplet, &
fxc_rho=vxc00, fxc_tau=v_tau_rspace)
END IF
CALL qs_rho_release(rhoin)
DEALLOCATE (rhoin)
IF (.NOT. ASSOCIATED(gxc_rho)) THEN
@ -356,13 +552,22 @@ CONTAINS
CALL pw_zero(gxc_rho(ispin))
END DO
END IF
DO ispin = 1, nspins
CALL pw_axpy(vxc00(ispin), gxc_rho(ispin), ak(istep))
END DO
IF (do_sf) THEN
CALL pw_axpy(vxc00(1), gxc_rho(1), ak(istep))
CALL pw_axpy(vxc00b(1), gxc_rho(2), ak(istep))
ELSE
DO ispin = 1, nspins
CALL pw_axpy(vxc00(ispin), gxc_rho(ispin), ak(istep))
END DO
END IF
DO ispin = 1, SIZE(vxc00)
CALL auxbas_pw_pool%give_back_pw(vxc00(ispin))
END DO
DEALLOCATE (vxc00)
IF (ASSOCIATED(vxc00b)) THEN
CALL auxbas_pw_pool%give_back_pw(vxc00b(1))
DEALLOCATE (vxc00b)
END IF
IF (ASSOCIATED(v_tau_rspace)) THEN
IF (.NOT. ASSOCIATED(gxc_tau)) THEN
ALLOCATE (gxc_tau(nspins))

View file

@ -541,10 +541,14 @@ CONTAINS
! **************************************************************************************************
!> \brief computes matrix elements corresponding to a given potential
!> \param v_rspace ...
!> \param hmat ...
!> If compute_tau
!> hmat(\mu,\nu) = \int v_rspace(r)\nabla\mu(r)\cdot\nabla\nu(r) dr
!> else
!> hmat(\mu,\nu) = \int v_rspace(r)\mu(r)\nu(r) dr
!> \param v_rspace Potential in real space
!> \param hmat Matrix to write the result
!> \param hmat_kp ...
!> \param pmat ...
!> \param pmat Input density matrix, not used in the calculation but the screening. See note below.
!> \param pmat_kp ...
!> \param qs_env ...
!> \param calculate_forces ...

View file

@ -70,7 +70,8 @@ MODULE qs_rho_methods
CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_rho_methods'
PUBLIC :: qs_rho_update_rho, qs_rho_update_tddfpt, &
qs_rho_rebuild, qs_rho_copy, qs_rho_scale_and_add
qs_rho_rebuild, qs_rho_copy, qs_rho_scale_and_add, &
qs_rho_scale_and_add_b
PUBLIC :: duplicate_rho_type, allocate_rho_ao_imag_from_real
CONTAINS
@ -1057,6 +1058,123 @@ CONTAINS
END SUBROUTINE qs_rho_copy
! **************************************************************************************************
!> \brief rhoa(2) = alpha*rhoa(2)+beta*rhob(1)
!> \param rhoa ...
!> \param rhob ...
!> \param alpha ...
!> \param beta ...
! **************************************************************************************************
SUBROUTINE qs_rho_scale_and_add_b(rhoa, rhob, alpha, beta)
TYPE(qs_rho_type), INTENT(IN) :: rhoa, rhob
REAL(KIND=dp), INTENT(IN) :: alpha, beta
CHARACTER(len=*), PARAMETER :: routineN = 'qs_rho_scale_and_add_b'
INTEGER :: handle
REAL(KIND=dp), DIMENSION(:), POINTER :: tot_rho_g_a, tot_rho_g_b, tot_rho_r_a, &
tot_rho_r_b
TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: rho_ao_a, rho_ao_b, rho_ao_im_a, &
rho_ao_im_b
TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho_g_a, rho_g_b, tau_g_a, tau_g_b
TYPE(pw_c1d_gs_type), DIMENSION(:, :), POINTER :: drho_g_a, drho_g_b
TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho_r_a, rho_r_b, tau_r_a, tau_r_b
TYPE(pw_r3d_rs_type), DIMENSION(:, :), POINTER :: drho_r_a, drho_r_b
TYPE(pw_r3d_rs_type), POINTER :: rho_r_sccs_a, rho_r_sccs_b
CALL timeset(routineN, handle)
NULLIFY (rho_ao_a, rho_ao_im_a, rho_r_a, rho_g_a, drho_r_a, &
drho_g_a, tau_r_a, tau_g_a, tot_rho_r_a, tot_rho_g_a, rho_r_sccs_a)
CALL qs_rho_get(rhoa, &
rho_ao=rho_ao_a, &
rho_ao_im=rho_ao_im_a, &
rho_r=rho_r_a, &
rho_g=rho_g_a, &
drho_r=drho_r_a, &
drho_g=drho_g_a, &
tau_r=tau_r_a, &
tau_g=tau_g_a, &
tot_rho_r=tot_rho_r_a, &
tot_rho_g=tot_rho_g_a, &
rho_r_sccs=rho_r_sccs_a)
NULLIFY (rho_ao_b, rho_ao_im_b, rho_r_b, rho_g_b, drho_r_b, &
drho_g_b, tau_r_b, tau_g_b, tot_rho_r_b, tot_rho_g_b, rho_r_sccs_b)
CALL qs_rho_get(rhob, &
rho_ao=rho_ao_b, &
rho_ao_im=rho_ao_im_b, &
rho_r=rho_r_b, &
rho_g=rho_g_b, &
drho_r=drho_r_b, &
drho_g=drho_g_b, &
tau_r=tau_r_b, &
tau_g=tau_g_b, &
tot_rho_r=tot_rho_r_b, &
tot_rho_g=tot_rho_g_b, &
rho_r_sccs=rho_r_sccs_b)
! rho_ao
IF (ASSOCIATED(rho_ao_a) .AND. ASSOCIATED(rho_ao_b)) THEN
CALL dbcsr_add(rho_ao_a(2)%matrix, rho_ao_b(1)%matrix, alpha, beta)
END IF
! rho_ao_im
IF (ASSOCIATED(rho_ao_im_a) .AND. ASSOCIATED(rho_ao_im_b)) THEN
CALL dbcsr_add(rho_ao_im_a(2)%matrix, rho_ao_im_b(1)%matrix, alpha, beta)
END IF
! rho_r
IF (ASSOCIATED(rho_r_a) .AND. ASSOCIATED(rho_r_b)) THEN
CALL pw_axpy(rho_r_b(1), rho_r_a(2), beta, alpha)
END IF
! rho_g
IF (ASSOCIATED(rho_g_a) .AND. ASSOCIATED(rho_g_b)) THEN
CALL pw_axpy(rho_g_b(1), rho_g_a(2), beta, alpha)
END IF
! SCCS
IF (ASSOCIATED(rho_r_sccs_a) .AND. ASSOCIATED(rho_r_sccs_b)) THEN
CALL pw_axpy(rho_r_sccs_b, rho_r_sccs_a, beta, alpha)
END IF
! drho_r
IF (ASSOCIATED(drho_r_a) .AND. ASSOCIATED(drho_r_b)) THEN
CPASSERT(ASSOCIATED(drho_r_a) .AND. ASSOCIATED(drho_r_b)) ! not implemented
END IF
! drho_g
IF (ASSOCIATED(drho_g_a) .AND. ASSOCIATED(drho_g_b)) THEN
CPASSERT(ASSOCIATED(drho_g_a) .AND. ASSOCIATED(drho_g_b)) ! not implemented
END IF
! tau_r
IF (ASSOCIATED(tau_r_a) .AND. ASSOCIATED(tau_r_b)) THEN
CALL pw_axpy(tau_r_b(1), tau_r_a(2), beta, alpha)
END IF
! tau_g
IF (ASSOCIATED(tau_g_a) .AND. ASSOCIATED(tau_g_b)) THEN
CALL pw_axpy(tau_g_b(1), tau_g_a(2), beta, alpha)
END IF
! tot_rho_r
IF (ASSOCIATED(tot_rho_r_a) .AND. ASSOCIATED(tot_rho_r_b)) THEN
tot_rho_r_a(2) = alpha*tot_rho_r_a(2) + beta*tot_rho_r_b(1)
END IF
! tot_rho_g
IF (ASSOCIATED(tot_rho_g_a) .AND. ASSOCIATED(tot_rho_g_b)) THEN
tot_rho_g_a(2) = alpha*tot_rho_g_a(2) + beta*tot_rho_g_b(1)
END IF
CALL timestop(handle)
END SUBROUTINE qs_rho_scale_and_add_b
! **************************************************************************************************
!> \brief rhoa = alpha*rhoa+beta*rhob
!> \param rhoa ...

View file

@ -27,7 +27,8 @@ MODULE qs_tddfpt2_eigensolver
cp_fm_release, cp_fm_set_all, cp_fm_set_submatrix, cp_fm_to_fm, cp_fm_type
USE cp_log_handling, ONLY: cp_logger_type
USE cp_output_handling, ONLY: cp_iterate
USE input_constants, ONLY: tddfpt_kernel_full,&
USE input_constants, ONLY: no_sf_tddfpt,&
tddfpt_kernel_full,&
tddfpt_kernel_none,&
tddfpt_kernel_stda
USE input_section_types, ONLY: section_vals_type
@ -113,7 +114,7 @@ CONTAINS
CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_orthogonalize_psi1_psi0'
INTEGER :: handle, ispin, ivect, nactive, nao, &
nspins, nvects
nspins, nvects, spin
TYPE(cp_fm_struct_type), POINTER :: matrix_struct
TYPE(cp_fm_type) :: evortho
TYPE(cp_fm_type), DIMENSION(:), POINTER :: mos
@ -127,12 +128,17 @@ CONTAINS
IF (nvects > 0) THEN
IF (.NOT. tddfpt_control%do_smearing) THEN
DO ispin = 1, nspins
IF (tddfpt_control%spinflip == no_sf_tddfpt) THEN
spin = ispin
ELSE
spin = 2
END IF
CALL cp_fm_get_info(matrix=evects(ispin, 1), matrix_struct=matrix_struct, &
nrow_global=nao, ncol_global=nactive)
CALL cp_fm_create(evortho, matrix_struct)
DO ivect = 1, nvects
! evortho: C0 * C0^T * S * C1 == (S * C0 * C0^T)^T * C1
CALL parallel_gemm('T', 'N', nao, nactive, nao, 1.0_dp, S_C0_C0T(ispin), &
CALL parallel_gemm('T', 'N', nao, nactive, nao, 1.0_dp, S_C0_C0T(spin), &
evects(ispin, ivect), 0.0_dp, evortho)
CALL cp_fm_scale_and_add(1.0_dp, evects(ispin, ivect), -1.0_dp, evortho)
END DO
@ -172,22 +178,24 @@ CONTAINS
!> for each spin in atomic basis set, and S is the corresponding overlap matrix
!> \param max_norm the largest possible overlap between the ground state and
!> excited state wave functions
!> \param spinflip ...
!> \return true if trial vectors are non-orthogonal to occupied molecular orbitals
!> \par History
!> * 07.2016 created [Sergey Chulkov]
!> * 05.2019 use temporary work matrices [JHU]
! **************************************************************************************************
FUNCTION tddfpt_is_nonorthogonal_psi1_psi0(evects, S_C0, max_norm) &
FUNCTION tddfpt_is_nonorthogonal_psi1_psi0(evects, S_C0, max_norm, spinflip) &
RESULT(is_nonortho)
TYPE(cp_fm_type), DIMENSION(:, :), INTENT(in) :: evects
TYPE(cp_fm_type), DIMENSION(:), INTENT(in) :: S_C0
REAL(kind=dp), INTENT(in) :: max_norm
INTEGER, INTENT(in) :: spinflip
LOGICAL :: is_nonortho
CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_is_nonorthogonal_psi1_psi0'
INTEGER :: handle, ispin, ivect, nactive, nao, &
nocc, nspins, nvects
nocc, nspins, nvects, spin
REAL(kind=dp) :: maxabs_val
TYPE(cp_fm_struct_type), POINTER :: matrix_struct, matrix_struct_tmp
TYPE(cp_fm_type) :: aortho
@ -200,7 +208,14 @@ CONTAINS
is_nonortho = .FALSE.
loop: DO ispin = 1, nspins
CALL cp_fm_get_info(matrix=S_C0(ispin), ncol_global=nocc)
IF (spinflip == no_sf_tddfpt) THEN
spin = ispin
ELSE
spin = 2
END IF
CALL cp_fm_get_info(matrix=S_C0(spin), ncol_global=nocc)
CALL cp_fm_get_info(matrix=evects(ispin, 1), matrix_struct=matrix_struct, &
nrow_global=nao, ncol_global=nactive)
CALL cp_fm_struct_create(matrix_struct_tmp, nrow_global=nocc, &
@ -208,8 +223,8 @@ CONTAINS
CALL cp_fm_create(aortho, matrix_struct_tmp)
CALL cp_fm_struct_release(matrix_struct_tmp)
DO ivect = 1, nvects
! aortho = S_0^T * S * C_1
CALL parallel_gemm('T', 'N', nocc, nactive, nao, 1.0_dp, S_C0(ispin), &
! aortho = S_C0^T * S * C_1
CALL parallel_gemm('T', 'N', nocc, nactive, nao, 1.0_dp, S_C0(spin), &
evects(ispin, ivect), 0.0_dp, aortho)
CALL cp_fm_maxabsval(aortho, maxabs_val)
is_nonortho = maxabs_val > max_norm
@ -290,7 +305,7 @@ CONTAINS
END DO
DO jvect = nvects_old + 1, nvects_total
! <psi1_i | psi1_j>
! Orthogonalization <psi1_i | psi1_j>
DO ivect = 1, jvect - 1
CALL cp_fm_trace(evects(:, jvect), S_evects(:, ivect), weights(1:nspins), accurate=.FALSE.)
norm = SUM(weights(1:nspins))
@ -300,7 +315,7 @@ CONTAINS
END DO
END DO
! <psi1_j | psi1_j>
! Normalization <psi1_j | psi1_j> = 1
DO ispin = 1, nspins
CALL cp_dbcsr_sm_fm_multiply(matrix_s, evects(ispin, jvect), S_evects(ispin, jvect), &
ncol=nactive(ispin), alpha=1.0_dp, beta=0.0_dp)
@ -367,7 +382,7 @@ CONTAINS
CALL timeset(routineN, handle)
nspins = SIZE(evects, 1)
nspins = SIZE(gs_mos, 1)
nvects = SIZE(evects, 2)
do_hfx = tddfpt_control%do_hfx
do_admm = tddfpt_control%do_admm
@ -381,9 +396,9 @@ CONTAINS
IF (debug_this_module) THEN
CPASSERT(nspins > 0)
CPASSERT(SIZE(Aop_evects, 1) == nspins)
CPASSERT(SIZE(Aop_evects, 1) == SIZE(evects, 1))
CPASSERT(SIZE(S_evects, 1) == SIZE(evects, 1))
CPASSERT(SIZE(Aop_evects, 2) == nvects)
CPASSERT(SIZE(S_evects, 1) == nspins)
CPASSERT(SIZE(S_evects, 2) == nvects)
CPASSERT(SIZE(gs_mos) == nspins)
END IF
@ -396,19 +411,19 @@ CONTAINS
CALL cp_fm_get_info(evects(1, 1), para_env=para_env)
IF (ALLOCATED(work_matrices%evects_sub)) THEN
DO ivect = 1, nvects
DO ispin = 1, nspins
DO ispin = 1, SIZE(evects, 1)
ASSOCIATE (evect => evects(ispin, ivect), work_matrix => work_matrices%evects_sub(ispin, ivect))
IF (ASSOCIATED(evect%matrix_struct)) THEN
IF (ASSOCIATED(work_matrix%matrix_struct)) THEN
CALL cp_fm_copy_general(evect, work_matrix, para_env)
ELSE
CALL cp_fm_copy_general(evect, fm_dummy, para_env)
END IF
ELSE IF (ASSOCIATED(work_matrix%matrix_struct)) THEN
CALL cp_fm_copy_general(fm_dummy, work_matrix, para_env)
ELSE
CALL cp_fm_copy_general(fm_dummy, fm_dummy, para_env)
END IF
IF (ASSOCIATED(evect%matrix_struct)) THEN
IF (ASSOCIATED(work_matrix%matrix_struct)) THEN
CALL cp_fm_copy_general(evect, work_matrix, para_env)
ELSE
CALL cp_fm_copy_general(evect, fm_dummy, para_env)
END IF
ELSE IF (ASSOCIATED(work_matrix%matrix_struct)) THEN
CALL cp_fm_copy_general(fm_dummy, work_matrix, para_env)
ELSE
CALL cp_fm_copy_general(fm_dummy, fm_dummy, para_env)
END IF
END ASSOCIATE
END DO
END DO
@ -427,7 +442,7 @@ CONTAINS
ELSE IF (tddfpt_control%kernel == tddfpt_kernel_none) THEN
! No kernel
DO ivect = 1, nvects
DO ispin = 1, nspins
DO ispin = 1, SIZE(evects, 1)
CALL cp_fm_set_all(Aop_evects(ispin, ivect), 0.0_dp)
END DO
END DO
@ -437,20 +452,20 @@ CONTAINS
IF (ALLOCATED(work_matrices%evects_sub)) THEN
DO ivect = 1, nvects
DO ispin = 1, nspins
DO ispin = 1, SIZE(evects, 1)
ASSOCIATE (Aop_evect => Aop_evects(ispin, ivect), &
work_matrix => work_matrices%Aop_evects_sub(ispin, ivect))
IF (ASSOCIATED(Aop_evect%matrix_struct)) THEN
IF (ASSOCIATED(work_matrix%matrix_struct)) THEN
CALL cp_fm_copy_general(work_matrix, Aop_evect, para_env)
ELSE
CALL cp_fm_copy_general(fm_dummy, Aop_evect, para_env)
END IF
ELSE IF (ASSOCIATED(work_matrix%matrix_struct)) THEN
CALL cp_fm_copy_general(work_matrix, fm_dummy, para_env)
ELSE
CALL cp_fm_copy_general(fm_dummy, fm_dummy, para_env)
END IF
IF (ASSOCIATED(Aop_evect%matrix_struct)) THEN
IF (ASSOCIATED(work_matrix%matrix_struct)) THEN
CALL cp_fm_copy_general(work_matrix, Aop_evect, para_env)
ELSE
CALL cp_fm_copy_general(fm_dummy, Aop_evect, para_env)
END IF
ELSE IF (ASSOCIATED(work_matrix%matrix_struct)) THEN
CALL cp_fm_copy_general(work_matrix, fm_dummy, para_env)
ELSE
CALL cp_fm_copy_general(fm_dummy, fm_dummy, para_env)
END IF
END ASSOCIATE
END DO
END DO
@ -458,7 +473,7 @@ CONTAINS
! orbital energy difference term
CALL tddfpt_apply_energy_diff(Aop_evects=Aop_evects, evects=evects, S_evects=S_evects, &
gs_mos=gs_mos, matrix_ks=matrix_ks)
gs_mos=gs_mos, matrix_ks=matrix_ks, tddfpt_control=tddfpt_control)
! if smeared occupation, then add aCCSX here
IF (tddfpt_control%do_smearing) THEN
@ -547,7 +562,7 @@ CONTAINS
!> \param evals Ritz eigenvalues (initialised on exit)
!> \param krylov_vects Krylov's vectors
!> \param Aop_krylov action of TDDFPT operator on Krylov's vectors
!> \param Atilde ...
!> \param Atilde TDDFPT matrix projected into the Krylov's vectors subspace
!> \param nkvo ...
!> \param nkvn ...
!> \par History
@ -653,25 +668,27 @@ CONTAINS
!> \param Aop_ritz approximate action of TDDFPT operator on Ritz vectors
!> \param gs_mos molecular orbitals optimised for the ground state
!> \param matrix_s overlap matrix
!> \param tddfpt_control ...
!> \par History
!> * 06.2016 created [Sergey Chulkov]
!> * 03.2017 refactored to achieve significant performance gain [Sergey Chulkov]
! **************************************************************************************************
SUBROUTINE tddfpt_compute_residual_vects(residual_vects, evals, ritz_vects, Aop_ritz, gs_mos, &
matrix_s)
matrix_s, tddfpt_control)
TYPE(cp_fm_type), DIMENSION(:, :), INTENT(in) :: residual_vects
REAL(kind=dp), DIMENSION(:), INTENT(in) :: evals
TYPE(cp_fm_type), DIMENSION(:, :), INTENT(in) :: ritz_vects, Aop_ritz
TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
INTENT(in) :: gs_mos
TYPE(dbcsr_type), POINTER :: matrix_s
TYPE(tddfpt2_control_type), POINTER :: tddfpt_control
CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_compute_residual_vects'
REAL(kind=dp), PARAMETER :: eref_scale = 0.99_dp, threshold = 16.0_dp*EPSILON(1.0_dp)
INTEGER :: handle, icol_local, irow_local, irv, &
ispin, nao, ncols_local, nrows_local, &
nrvs, nspins
nrvs, nspins, spin2, spinflip
INTEGER, DIMENSION(:), POINTER :: col_indices_local, row_indices_local
INTEGER, DIMENSION(maxspins) :: nactive, nmo_virt
REAL(kind=dp) :: e_occ_plus_lambda, eref, lambda
@ -684,18 +701,24 @@ CONTAINS
nspins = SIZE(residual_vects, 1)
nrvs = SIZE(residual_vects, 2)
spinflip = tddfpt_control%spinflip
IF (nrvs > 0) THEN
CALL dbcsr_get_info(matrix_s, nfullrows_total=nao)
ALLOCATE (awork(nspins), vomat(nspins))
DO ispin = 1, nspins
nmo_virt(ispin) = SIZE(gs_mos(ispin)%evals_virt)
IF (spinflip == no_sf_tddfpt) THEN
spin2 = ispin
ELSE
spin2 = 2
END IF
nmo_virt(spin2) = SIZE(gs_mos(spin2)%evals_virt)
!
CALL cp_fm_get_info(matrix=ritz_vects(ispin, 1), matrix_struct=ao_mo_struct, &
ncol_global=nactive(ispin))
CALL cp_fm_create(awork(ispin), ao_mo_struct)
!
CALL cp_fm_struct_create(virt_mo_struct, nrow_global=nmo_virt(ispin), &
CALL cp_fm_struct_create(virt_mo_struct, nrow_global=nmo_virt(spin2), &
ncol_global=nactive(ispin), template_fmstruct=ao_mo_struct)
CALL cp_fm_create(vomat(ispin), virt_mo_struct)
CALL cp_fm_struct_release(virt_mo_struct)
@ -706,6 +729,11 @@ CONTAINS
lambda = evals(irv)
DO ispin = 1, nspins
IF (spinflip == no_sf_tddfpt) THEN
spin2 = ispin
ELSE
spin2 = 2
END IF
CALL cp_fm_get_info(vomat(ispin), nrow_local=nrows_local, &
ncol_local=ncols_local, row_indices=row_indices_local, &
col_indices=col_indices_local, local_data=weights_ldata)
@ -715,14 +743,15 @@ CONTAINS
ncol=nactive(ispin), alpha=-lambda, beta=0.0_dp)
CALL cp_fm_scale_and_add(1.0_dp, awork(ispin), 1.0_dp, Aop_ritz(ispin, irv))
!
CALL parallel_gemm('T', 'N', nmo_virt(ispin), nactive(ispin), nao, 1.0_dp, gs_mos(ispin)%mos_virt, &
CALL parallel_gemm('T', 'N', nmo_virt(spin2), nactive(ispin), nao, 1.0_dp, gs_mos(spin2)%mos_virt, &
awork(ispin), 0.0_dp, vomat(ispin))
! Apply Davidson preconditioner to the residue vectors vomat to obtain new directions
DO icol_local = 1, ncols_local
e_occ_plus_lambda = gs_mos(ispin)%evals_occ(col_indices_local(icol_local)) + lambda
DO irow_local = 1, nrows_local
eref = gs_mos(ispin)%evals_virt(row_indices_local(irow_local)) - e_occ_plus_lambda
eref = gs_mos(spin2)%evals_virt(row_indices_local(irow_local)) - e_occ_plus_lambda
! eref = e_virt - e_occ - lambda = e_virt - e_occ - (eref_scale*lambda + (1-eref_scale)*lambda);
! eref_new = e_virt - e_occ - eref_scale*lambda = eref + (1 - eref_scale)*lambda
@ -733,7 +762,7 @@ CONTAINS
END DO
END DO
CALL parallel_gemm('N', 'N', nao, nactive(ispin), nmo_virt(ispin), 1.0_dp, gs_mos(ispin)%mos_virt, &
CALL parallel_gemm('N', 'N', nao, nactive(ispin), nmo_virt(spin2), 1.0_dp, gs_mos(spin2)%mos_virt, &
vomat(ispin), 0.0_dp, residual_vects(ispin, irv))
END DO
END DO
@ -805,9 +834,9 @@ CONTAINS
CALL timeset(routineN, handle)
nspins = SIZE(gs_mos)
nspins = SIZE(evects, 1)
nstates = tddfpt_control%nstates
nstates_total = tddfpt_total_number_of_states(gs_mos)
nstates_total = tddfpt_total_number_of_states(tddfpt_control, gs_mos)
IF (debug_this_module) THEN
CPASSERT(SIZE(evects, 1) == nspins)
@ -818,9 +847,7 @@ CONTAINS
CALL get_qs_env(qs_env, matrix_s=matrix_s)
! adjust the number of Krylov vectors
max_krylov_vects = tddfpt_control%nkvs
IF (max_krylov_vects < nstates) max_krylov_vects = nstates
IF (INT(max_krylov_vects, kind=int_8) > nstates_total) max_krylov_vects = INT(nstates_total)
max_krylov_vects = MIN(MAX(tddfpt_control%nkvs, nstates), INT(nstates_total))
ALLOCATE (Aop_ritz(nspins, nstates))
DO istate = 1, nstates
@ -856,6 +883,7 @@ CONTAINS
! davidson iteration
CALL cp_iterate(logger%iter_info, iter_nr_out=iter)
! Matrix-vector operations
CALL tddfpt_compute_Aop_evects(Aop_evects=Aop_krylov(:, nvects_exist + 1:nvects_exist + nvects_new), &
evects=krylov_vects(:, nvects_exist + 1:nvects_exist + nvects_new), &
S_evects=S_krylov(:, nvects_exist + 1:nvects_exist + nvects_new), &
@ -898,7 +926,7 @@ CONTAINS
CALL tddfpt_compute_residual_vects(residual_vects=krylov_vects(:, nvects_exist + 1:nvects_exist + nvects_new), &
evals=evals_last(1:nvects_new), &
ritz_vects=evects(:, 1:nvects_new), Aop_ritz=Aop_ritz(:, 1:nvects_new), &
gs_mos=gs_mos, matrix_s=matrix_s(1)%matrix)
gs_mos=gs_mos, matrix_s=matrix_s(1)%matrix, tddfpt_control=tddfpt_control)
CALL tddfpt_orthogonalize_psi1_psi0(krylov_vects(:, nvects_exist + 1:nvects_exist + nvects_new), &
work_matrices%S_C0_C0T, qs_env, &
@ -908,7 +936,8 @@ CONTAINS
S_krylov(:, 1:nvects_exist + nvects_new), matrix_s(1)%matrix)
is_nonortho = tddfpt_is_nonorthogonal_psi1_psi0(krylov_vects(:, nvects_exist + 1:nvects_exist + nvects_new), &
work_matrices%S_C0, tddfpt_control%orthogonal_eps)
work_matrices%S_C0, tddfpt_control%orthogonal_eps, &
tddfpt_control%spinflip)
ELSE
! convergence or the maximum number of Krylov vectors have been achieved
nvects_new = 0

View file

@ -20,7 +20,10 @@ MODULE qs_tddfpt2_fhxc
cp_fm_get_info,&
cp_fm_release,&
cp_fm_type
USE input_constants, ONLY: do_admm_aux_exch_func_none
USE input_constants, ONLY: do_admm_aux_exch_func_none,&
no_sf_tddfpt,&
tddfpt_sf_col,&
tddfpt_sf_noncol
USE kinds, ONLY: default_string_length,&
dp
USE lri_environment_types, ONLY: lri_kind_type
@ -111,10 +114,11 @@ CONTAINS
CHARACTER(LEN=default_string_length) :: basis_type
INTEGER :: handle, ikind, ispin, ivect, nao, &
nao_aux, nkind, nspins, nvects
nao_aux, nkind, nspins, nvects, &
spinflip
INTEGER, DIMENSION(:), POINTER :: blk_sizes
INTEGER, DIMENSION(maxspins) :: nactive
LOGICAL :: gapw, gapw_xc
LOGICAL :: do_noncol, gapw, gapw_xc
TYPE(admm_type), POINTER :: admm_env
TYPE(cp_fm_type) :: work_aux_orb, work_orb_orb
TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: A_xc_munu_sub, rho_ia_ao, &
@ -142,6 +146,9 @@ CONTAINS
gapw = dft_control%qs_control%gapw
gapw_xc = dft_control%qs_control%gapw_xc
spinflip = dft_control%tddfpt2_control%spinflip
do_noncol = spinflip .EQ. tddfpt_sf_noncol
CALL cp_fm_get_info(evects(1, 1), nrow_global=nao)
DO ispin = 1, nspins
@ -158,6 +165,8 @@ CONTAINS
END IF
DO ivect = 1, nvects
! Transform TDDFT vectors to AO space and store them into rho_ia_ao
IF (ALLOCATED(work_matrices%evects_sub)) THEN
IF (ASSOCIATED(work_matrices%evects_sub(1, ivect)%matrix_struct)) THEN
DO ispin = 1, nspins
@ -230,46 +239,54 @@ CONTAINS
CALL pw_zero(work_matrices%A_ia_rspace_sub(ispin))
END DO
! C_x d^{2}E_{x}^{DFT}[\rho] / d\rho^2
! + C_{HF} d^{2}E_{x, ADMM}^{DFT}[\rho] / d\rho^2 in case of ADMM calculation
IF (gapw_xc) THEN
IF (kernel_env%do_exck) THEN
CPABORT("NYA")
! Skip kernel if collinear xc-kernel for spin-flip is requested
IF (spinflip /= tddfpt_sf_col) THEN
! C_x d^{2}E_{x}^{DFT}[\rho] / d\rho^2
! + C_{HF} d^{2}E_{x, ADMM}^{DFT}[\rho] / d\rho^2 in case of ADMM calculation
IF (gapw_xc) THEN
IF (kernel_env%do_exck) THEN
CPABORT("NYA")
ELSE
CALL tddfpt_apply_xc(A_ia_rspace=work_matrices%A_ia_rspace_sub, kernel_env=kernel_env, &
rho_ia_struct=work_matrices%rho_xc_struct_sub, &
is_rks_triplets=is_rks_triplets, pw_env=sub_env%pw_env, &
work_v_xc=work_matrices%wpw_rspace_sub, &
work_v_xc_tau=work_matrices%wpw_tau_rspace_sub, &
spinflip=spinflip)
END IF
DO ispin = 1, nspins
CALL pw_scale(work_matrices%A_ia_rspace_sub(ispin), &
work_matrices%A_ia_rspace_sub(ispin)%pw_grid%dvol)
CALL integrate_v_rspace(v_rspace=work_matrices%A_ia_rspace_sub(ispin), &
hmat=work_matrices%A_ia_munu_sub(ispin), &
qs_env=qs_env, calculate_forces=.FALSE., gapw=gapw_xc, &
pw_env_external=sub_env%pw_env, &
task_list_external=sub_env%task_list_orb_soft)
CALL pw_zero(work_matrices%A_ia_rspace_sub(ispin))
END DO
ELSE
CALL tddfpt_apply_xc(A_ia_rspace=work_matrices%A_ia_rspace_sub, kernel_env=kernel_env, &
rho_ia_struct=work_matrices%rho_xc_struct_sub, &
is_rks_triplets=is_rks_triplets, pw_env=sub_env%pw_env, &
work_v_xc=work_matrices%wpw_rspace_sub, &
work_v_xc_tau=work_matrices%wpw_tau_rspace_sub)
IF (kernel_env%do_exck) THEN
CALL tddfpt_apply_xc_potential(work_matrices%A_ia_rspace_sub, work_matrices%fxc_rspace_sub, &
work_matrices%rho_orb_struct_sub, is_rks_triplets)
ELSE
CALL tddfpt_apply_xc(A_ia_rspace=work_matrices%A_ia_rspace_sub, kernel_env=kernel_env, &
rho_ia_struct=work_matrices%rho_orb_struct_sub, &
is_rks_triplets=is_rks_triplets, pw_env=sub_env%pw_env, &
work_v_xc=work_matrices%wpw_rspace_sub, &
work_v_xc_tau=work_matrices%wpw_tau_rspace_sub, &
spinflip=spinflip)
END IF
END IF
DO ispin = 1, nspins
CALL pw_scale(work_matrices%A_ia_rspace_sub(ispin), &
work_matrices%A_ia_rspace_sub(ispin)%pw_grid%dvol)
CALL integrate_v_rspace(v_rspace=work_matrices%A_ia_rspace_sub(ispin), &
hmat=work_matrices%A_ia_munu_sub(ispin), &
qs_env=qs_env, calculate_forces=.FALSE., gapw=gapw_xc, &
pw_env_external=sub_env%pw_env, &
task_list_external=sub_env%task_list_orb_soft)
CALL pw_zero(work_matrices%A_ia_rspace_sub(ispin))
END DO
ELSE
IF (kernel_env%do_exck) THEN
CALL tddfpt_apply_xc_potential(work_matrices%A_ia_rspace_sub, work_matrices%fxc_rspace_sub, &
work_matrices%rho_orb_struct_sub, is_rks_triplets)
ELSE
CALL tddfpt_apply_xc(A_ia_rspace=work_matrices%A_ia_rspace_sub, kernel_env=kernel_env, &
rho_ia_struct=work_matrices%rho_orb_struct_sub, &
is_rks_triplets=is_rks_triplets, pw_env=sub_env%pw_env, &
work_v_xc=work_matrices%wpw_rspace_sub, &
work_v_xc_tau=work_matrices%wpw_tau_rspace_sub)
IF (gapw .OR. gapw_xc) THEN
rho_atom_set => sub_env%local_rho_set%rho_atom_set
rho1_atom_set => work_matrices%local_rho_set%rho_atom_set
CALL calculate_xc_2nd_deriv_atom(rho_atom_set, rho1_atom_set, qs_env, kernel_env%xc_section, &
sub_env%para_env, do_tddfpt2=.TRUE., do_triplet=is_rks_triplets, &
do_sf=do_noncol)
END IF
END IF
IF (gapw .OR. gapw_xc) THEN
rho_atom_set => sub_env%local_rho_set%rho_atom_set
rho1_atom_set => work_matrices%local_rho_set%rho_atom_set
CALL calculate_xc_2nd_deriv_atom(rho_atom_set, rho1_atom_set, qs_env, kernel_env%xc_section, &
sub_env%para_env, do_tddfpt2=.TRUE., do_triplet=is_rks_triplets)
END IF
END IF ! spin-flip
! ADMM correction
IF (do_admm .AND. admm_xc_correction) THEN
@ -314,7 +331,8 @@ CONTAINS
rho_ia_struct=work_matrices%rho_aux_fit_struct_sub, &
is_rks_triplets=is_rks_triplets, pw_env=sub_env%pw_env, &
work_v_xc=work_matrices%wpw_rspace_sub, &
work_v_xc_tau=work_matrices%wpw_tau_rspace_sub)
work_v_xc_tau=work_matrices%wpw_tau_rspace_sub, &
spinflip=spinflip)
DO ispin = 1, nspins
CALL pw_scale(V_rspace_sub(ispin), V_rspace_sub(ispin)%pw_grid%dvol)
CALL integrate_v_rspace(v_rspace=V_rspace_sub(ispin), &
@ -330,7 +348,7 @@ CONTAINS
CALL calculate_xc_2nd_deriv_atom(rho_atom_set, rho1_atom_set, qs_env, &
kernel_env_admm_aux%xc_section, &
sub_env%para_env, do_tddfpt2=.TRUE., &
do_triplet=is_rks_triplets, &
do_triplet=is_rks_triplets, do_sf=do_noncol, &
kind_set_external=admm_env%admm_gapw_env%admm_kind_set)
CALL update_ks_atom(qs_env, A_xc_munu_sub, rho_ia_ao_aux_fit, forces=.FALSE., tddft=.TRUE., &
rho_atom_external=rho1_atom_set, &
@ -373,7 +391,8 @@ CONTAINS
rho_ia_struct=work_matrices%rho_aux_fit_struct_sub, &
is_rks_triplets=is_rks_triplets, pw_env=sub_env%pw_env, &
work_v_xc=work_matrices%wpw_rspace_sub, &
work_v_xc_tau=work_matrices%wpw_tau_rspace_sub)
work_v_xc_tau=work_matrices%wpw_tau_rspace_sub, &
spinflip=spinflip)
IF (admm_env%do_gapw) THEN
CPWARN("GAPW/ADMM needs symmetric ADMM kernel")
CPABORT("GAPW/ADMM@TDDFT")
@ -383,7 +402,7 @@ CONTAINS
END IF
! electron-hole Coulomb interaction
IF (.NOT. is_rks_triplets) THEN
IF ((.NOT. is_rks_triplets) .AND. (spinflip .EQ. no_sf_tddfpt)) THEN
! a sum J_i{alpha}a{alpha}_munu + J_i{beta}a{beta}_munu can be computed by solving
! the Poisson equation for combined density (rho_{ia,alpha} + rho_{ia,beta}) .
! The following action will destroy reciprocal-space grid in spin-unrestricted case.

View file

@ -62,7 +62,9 @@ MODULE qs_tddfpt2_fhxc_forces
hfx_ri_update_ks
USE hfx_types, ONLY: hfx_type
USE input_constants, ONLY: do_admm_aux_exch_func_none,&
no_sf_tddfpt,&
tddfpt_kernel_full,&
tddfpt_sf_col,&
xc_kernel_method_analytic,&
xc_kernel_method_best,&
xc_kernel_method_numeric,&
@ -94,7 +96,8 @@ MODULE qs_tddfpt2_fhxc_forces
qs_environment_type,&
set_qs_env
USE qs_force_types, ONLY: qs_force_type
USE qs_fxc, ONLY: qs_fgxc_create,&
USE qs_fxc, ONLY: qs_fgxc_analytic,&
qs_fgxc_create,&
qs_fgxc_gdiff,&
qs_fgxc_release
USE qs_gapw_densities, ONLY: prepare_gapw_den
@ -148,10 +151,12 @@ MODULE qs_tddfpt2_fhxc_forces
CONTAINS
! **************************************************************************************************
!> \brief Calculate direct tddft forces
!> \param qs_env ...
!> \param ex_env ...
!> \param gs_mos ...
!> \brief Calculate direct tddft forces. Calculate the three last terms of the response vector
!> in equation 49 and the first term of \Lambda_munu in equation 51 in
!> J. Chem. Theory Comput. 2022, 18, 7, 41864202 (https://doi.org/10.1021/acs.jctc.2c00144)
!> \param qs_env Holds all system information relevant for the calculation.
!> \param ex_env Holds the response vector ex_env%cpmos and Lambda ex_env%matrix_wx1.
!> \param gs_mos MO coefficients of the ground state.
!> \param full_kernel ...
!> \param debug_forces ...
!> \par History
@ -171,10 +176,10 @@ CONTAINS
CHARACTER(LEN=default_string_length) :: basis_type
INTEGER :: handle, iounit, ispin, mspin, myfun, &
n_rep_hf, nao, nao_aux, natom, nkind, &
norb, nspins, order
norb(2), nspins, order, spin
LOGICAL :: distribute_fock_matrix, do_admm, do_analytic, do_hfx, do_hfxlr, do_hfxsr, &
do_numeric, gapw, gapw_xc, hfx_treat_lsd_in_core, is_rks_triplets, s_mstruct_changed, &
use_virial
do_numeric, do_sf, gapw, gapw_xc, hfx_treat_lsd_in_core, is_rks_triplets, &
s_mstruct_changed, use_virial
REAL(KIND=dp) :: eh1, eh1c, eps_delta, eps_fit, focc, &
fscal, fval, kval, xehartree
REAL(KIND=dp), DIMENSION(3) :: fodeb
@ -183,7 +188,7 @@ CONTAINS
TYPE(cp_fm_struct_type), POINTER :: fm_struct, fm_struct_mat
TYPE(cp_fm_type) :: cvcmat, vcvec
TYPE(cp_fm_type), DIMENSION(:), POINTER :: cpmos, evect
TYPE(cp_fm_type), POINTER :: mos
TYPE(cp_fm_type), POINTER :: mos, mos2
TYPE(cp_logger_type), POINTER :: logger
TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_fx, matrix_gx, matrix_hfx, &
matrix_hfx_admm, matrix_hfx_admm_asymm, matrix_hfx_asymm, matrix_hx, matrix_p, &
@ -232,6 +237,11 @@ CONTAINS
tddfpt_control => dft_control%tddfpt2_control
nspins = dft_control%nspins
is_rks_triplets = tddfpt_control%rks_triplets .AND. (nspins == 1)
IF (tddfpt_control%spinflip == no_sf_tddfpt) THEN
do_sf = .FALSE.
ELSE
do_sf = .TRUE.
END IF
CPASSERT(tddfpt_control%kernel == tddfpt_kernel_full)
do_hfx = tddfpt_control%do_hfx
do_hfxsr = tddfpt_control%do_hfxsr
@ -248,20 +258,22 @@ CONTAINS
focc = 1.0_dp
IF (nspins == 2) focc = 0.5_dp
DO ispin = 1, nspins
DO ispin = 1, SIZE(evect, 1)
! Calculate (C*X^T + X*C^T)/2
CALL dbcsr_set(matrix_px1(ispin)%matrix, 0.0_dp)
CALL cp_fm_get_info(evect(ispin), ncol_global=norb)
CALL cp_fm_get_info(evect(ispin), ncol_global=norb(ispin))
CALL cp_dbcsr_plus_fm_fm_t(matrix_px1(ispin)%matrix, &
matrix_v=evect(ispin), &
matrix_g=gs_mos(ispin)%mos_occ, &
ncol=norb, alpha=2.0_dp*focc, symmetry_mode=1)
ncol=norb(ispin), alpha=2.0_dp*focc, symmetry_mode=1)
! Calculate (C*X^T - X*C^T)/2
CALL dbcsr_set(matrix_px1_asymm(ispin)%matrix, 0.0_dp)
CALL cp_fm_get_info(evect(ispin), ncol_global=norb)
CALL cp_fm_get_info(evect(ispin), ncol_global=norb(ispin))
CALL cp_dbcsr_plus_fm_fm_t(matrix_px1_asymm(ispin)%matrix, &
matrix_v=gs_mos(ispin)%mos_occ, &
matrix_g=evect(ispin), &
ncol=norb, alpha=2.0_dp*focc, &
ncol=norb(ispin), alpha=2.0_dp*focc, &
symmetry_mode=-1)
END DO
!
@ -270,7 +282,7 @@ CONTAINS
NULLIFY (hartree_local, local_rho_set, local_rho_set_admm)
IF (gapw .OR. gapw_xc) THEN
IF (nspins == 2) THEN
DO ispin = 1, nspins
DO ispin = 1, SIZE(evect, 1)
CALL dbcsr_scale(matrix_px1(ispin)%matrix, 2.0_dp)
END DO
END IF
@ -298,7 +310,7 @@ CONTAINS
sap_oce, eps_fit)
CALL set_qs_env(qs_env, oce=oce)
mpga(1:nspins, 1:1) => matrix_px1(1:nspins)
mpga(1:SIZE(evect, 1), 1:1) => matrix_px1(1:SIZE(evect, 1))
CALL calculate_rho_atom_coeff(qs_env, mpga, local_rho_set%rho_atom_set, &
qs_kind_set, oce, sab, para_env)
CALL prepare_gapw_den(qs_env, local_rho_set, do_rho0=gapw)
@ -317,7 +329,7 @@ CONTAINS
qs_kind_set, oce, sab, para_env)
CALL prepare_gapw_den(qs_env, local_rho_set_g, do_rho0=.FALSE.)
IF (nspins == 2) THEN
DO ispin = 1, nspins
DO ispin = 1, SIZE(evect, 1)
CALL dbcsr_scale(matrix_px1(ispin)%matrix, 0.5_dp)
END DO
END IF
@ -327,8 +339,9 @@ CONTAINS
CALL get_qs_env(qs_env, admm_env=admm_env)
nao_aux = admm_env%nao_aux_fit
nao = admm_env%nao_orb
!
DO ispin = 1, nspins
! Fit the symmetrized and antisymmetrized matrices
DO ispin = 1, SIZE(evect, 1)
CALL copy_dbcsr_to_fm(matrix_px1(ispin)%matrix, admm_env%work_orb_orb)
CALL parallel_gemm('N', 'N', nao_aux, nao, nao, &
1.0_dp, admm_env%A, admm_env%work_orb_orb, 0.0_dp, &
@ -359,7 +372,7 @@ CONTAINS
CALL local_rho_set_create(local_rho_set_admm)
CALL allocate_rho_atom_internals(local_rho_set_admm%rho_atom_set, atomic_kind_set, &
admm_env%admm_gapw_env%admm_kind_set, dft_control, para_env)
mpga(1:nspins, 1:1) => matrix_px1_admm(1:nspins)
mpga(1:SIZE(evect, 1), 1:1) => matrix_px1_admm(1:SIZE(evect, 1))
CALL get_admm_env(admm_env, sab_aux_fit=sab_aux_fit)
CALL calculate_rho_atom_coeff(qs_env, mpga, local_rho_set_admm%rho_atom_set, &
admm_env%admm_gapw_env%admm_kind_set, &
@ -392,30 +405,33 @@ CONTAINS
CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
poisson_env=poisson_env)
ALLOCATE (rhox_r(nspins), rhox_g(nspins))
DO ispin = 1, nspins
ALLOCATE (rhox_r(SIZE(evect, 1)), rhox_g(SIZE(evect, 1)))
DO ispin = 1, SIZE(evect, 1)
CALL auxbas_pw_pool%create_pw(rhox_r(ispin))
CALL auxbas_pw_pool%create_pw(rhox_g(ispin))
END DO
CALL auxbas_pw_pool%create_pw(rhox_tot_gspace)
CALL pw_zero(rhox_tot_gspace)
DO ispin = 1, nspins
DO ispin = 1, SIZE(evect, 1)
! Calculate gridpoint values of the density associated to 2*matrix_px1 = C*X^T + X*C^T
IF (nspins == 2) CALL dbcsr_scale(matrix_px1(ispin)%matrix, 2.0_dp)
CALL calculate_rho_elec(ks_env=ks_env, matrix_p=matrix_px1(ispin)%matrix, &
rho=rhox_r(ispin), rho_gspace=rhox_g(ispin), &
soft_valid=gapw)
! rhox_tot_gspace contains the values on the grid points of rhox = sum_munu 4D^X_munu*mu(r)*nu(r)
CALL pw_axpy(rhox_g(ispin), rhox_tot_gspace)
! Recover matrix_px1 = (C*X^T + X*C^T)/2
IF (nspins == 2) CALL dbcsr_scale(matrix_px1(ispin)%matrix, 0.5_dp)
END DO
IF (gapw_xc) THEN
ALLOCATE (rhoxx_r(nspins), rhoxx_g(nspins))
DO ispin = 1, nspins
ALLOCATE (rhoxx_r(SIZE(evect, 1)), rhoxx_g(SIZE(evect, 1)))
DO ispin = 1, SIZE(evect, 1)
CALL auxbas_pw_pool%create_pw(rhoxx_r(ispin))
CALL auxbas_pw_pool%create_pw(rhoxx_g(ispin))
END DO
DO ispin = 1, nspins
DO ispin = 1, SIZE(evect, 1)
IF (nspins == 2) CALL dbcsr_scale(matrix_px1(ispin)%matrix, 2.0_dp)
CALL calculate_rho_elec(ks_env=ks_env, matrix_p=matrix_px1(ispin)%matrix, &
rho=rhoxx_r(ispin), rho_gspace=rhoxx_g(ispin), &
@ -426,7 +442,7 @@ CONTAINS
CALL get_qs_env(qs_env, matrix_s=matrix_s, force=force)
IF (.NOT. is_rks_triplets) THEN
IF (.NOT. (is_rks_triplets .OR. do_sf)) THEN
CALL auxbas_pw_pool%create_pw(xv_hartree_rspace)
CALL auxbas_pw_pool%create_pw(xv_hartree_gspace)
! calculate associated hartree potential
@ -456,7 +472,7 @@ CONTAINS
IF (debug_forces) THEN
fodeb(1:3) = force(1)%rho_elec(1:3, 1) - fodeb(1:3)
CALL para_env%sum(fodeb)
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Px*dKh[X] ", fodeb
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Dx*dKh[Dx] ", fodeb
END IF
IF (gapw) THEN
IF (debug_forces) fodeb(1:3) = force(1)%g0s_Vh_elec(1:3, 1)
@ -472,7 +488,7 @@ CONTAINS
IF (debug_forces) THEN
fodeb(1:3) = force(1)%g0s_Vh_elec(1:3, 1) - fodeb(1:3)
CALL para_env%sum(fodeb)
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Px*dKh[X]PAWg0", fodeb
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Dx*dKh[Dx]PAWg0", fodeb
END IF
IF (debug_forces) fodeb(1:3) = force(1)%Vhxc_atom(1:3, 1)
CALL update_ks_atom(qs_env, matrix_hx, matrix_px1, forces=.TRUE., &
@ -480,7 +496,7 @@ CONTAINS
IF (debug_forces) THEN
fodeb(1:3) = force(1)%Vhxc_atom(1:3, 1) - fodeb(1:3)
CALL para_env%sum(fodeb)
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Px*dKh[X]PAW ", fodeb
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Dx*dKh[Dx]PAW", fodeb
END IF
END IF
END IF
@ -493,7 +509,7 @@ CONTAINS
xc_section => full_kernel%xc_section
CALL section_vals_val_get(xc_section, "XC_FUNCTIONAL%_SECTION_PARAMETERS_", &
i_val=myfun)
IF (myfun /= xc_none) THEN
IF (.NOT. ((myfun == xc_none) .OR. (tddfpt_control%spinflip == tddfpt_sf_col))) THEN
SELECT CASE (ex_env%xc_kernel_method)
CASE (xc_kernel_method_best)
do_analytic = .TRUE.
@ -518,6 +534,8 @@ CONTAINS
CALL qs_rho_get(rho, rho_ao=matrix_p)
NULLIFY (rhox)
ALLOCATE (rhox)
! Create rhox object to collect all information on matrix_px1, including its values on the
! grid points
CALL qs_rho_create(rhox)
IF (gapw_xc) THEN
CALL qs_rho_set(rho_struct=rhox, rho_ao=matrix_px1, rho_r=rhoxx_r, rho_g=rhoxx_g, &
@ -526,12 +544,19 @@ CONTAINS
CALL qs_rho_set(rho_struct=rhox, rho_ao=matrix_px1, rho_r=rhox_r, rho_g=rhox_g, &
rho_r_valid=.TRUE., rho_g_valid=.TRUE.)
END IF
! Calculate the exchange-correlation kernel derivative contribution, notice that for open-shell
! rhox_r contains a factor of 2!
IF (do_analytic .AND. .NOT. do_numeric) THEN
CPABORT("Analytic 3rd EXC derivatives not available")
IF (.NOT. do_sf) THEN
CPABORT("Analytic 3rd EXC derivatives not available")
ELSE !TODO
CALL qs_fgxc_analytic(rho, rhox, xc_section, auxbas_pw_pool, &
fxc_rho, fxc_tau, gxc_rho, gxc_tau, spinflip=do_sf)
END IF
ELSEIF (do_numeric) THEN
IF (do_analytic) THEN
CALL qs_fgxc_gdiff(ks_env, rho, rhox, xc_section, order, eps_delta, is_rks_triplets, &
fxc_rho, fxc_tau, gxc_rho, gxc_tau)
fxc_rho, fxc_tau, gxc_rho, gxc_tau, spinflip=do_sf)
ELSE
CALL qs_fgxc_create(ks_env, rho, rhox, xc_section, order, is_rks_triplets, &
fxc_rho, fxc_tau, gxc_rho, gxc_tau)
@ -572,13 +597,15 @@ CONTAINS
IF (debug_forces) fodeb(1:3) = force(1)%rho_elec(1:3, 1)
NULLIFY (matrix_fx)
CALL dbcsr_allocate_matrix_set(matrix_fx, nspins)
DO ispin = 1, nspins
CALL dbcsr_allocate_matrix_set(matrix_fx, SIZE(fxc_rho))
DO ispin = 1, SIZE(fxc_rho, 1)
ALLOCATE (matrix_fx(ispin)%matrix)
CALL dbcsr_create(matrix_fx(ispin)%matrix, template=matrix_s(1)%matrix)
CALL dbcsr_copy(matrix_fx(ispin)%matrix, matrix_s(1)%matrix)
CALL dbcsr_set(matrix_fx(ispin)%matrix, 0.0_dp)
CALL pw_scale(fxc_rho(ispin), fxc_rho(ispin)%pw_grid%dvol)
! Calculate 2sum_sigmatau<munu|fxc|sigmatau>D^X_sigmatau
! fxc_rho here containes a factor of 2
CALL integrate_v_rspace(qs_env=qs_env, v_rspace=fxc_rho(ispin), &
pmat=matrix_px1(ispin), hmat=matrix_fx(ispin), &
gapw=(gapw .OR. gapw_xc), calculate_forces=.TRUE.)
@ -586,12 +613,14 @@ CONTAINS
IF (debug_forces) THEN
fodeb(1:3) = force(1)%rho_elec(1:3, 1) - fodeb(1:3)
CALL para_env%sum(fodeb)
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Px*dKf[X] ", fodeb
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Dx*dfxc[Dx] ", fodeb
END IF
IF (debug_forces) fodeb(1:3) = force(1)%rho_elec(1:3, 1)
NULLIFY (matrix_gx)
CALL dbcsr_allocate_matrix_set(matrix_gx, nspins)
! Calculate exchange-correlation kernel derivative 2<D^X D^X|gxc|mu nu>
! gxc comes with a factor of 4, so a factor of 1/2 is introduced
DO ispin = 1, nspins
ALLOCATE (matrix_gx(ispin)%matrix)
CALL dbcsr_create(matrix_gx(ispin)%matrix, template=matrix_s(1)%matrix)
@ -607,7 +636,7 @@ CONTAINS
IF (debug_forces) THEN
fodeb(1:3) = force(1)%rho_elec(1:3, 1) - fodeb(1:3)
CALL para_env%sum(fodeb)
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: P*dKg[X] ", fodeb
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Dx*dgxc[Dx]", fodeb
END IF
CALL qs_fgxc_release(ks_env, fxc_rho, fxc_tau, gxc_rho, gxc_tau)
@ -619,7 +648,7 @@ CONTAINS
IF (debug_forces) THEN
fodeb(1:3) = force(1)%Vhxc_atom(1:3, 1) - fodeb(1:3)
CALL para_env%sum(fodeb)
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Px*dKf[X]PAW ", fodeb
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Dx*dfxc[Dx]PAW ", fodeb
END IF
IF (debug_forces) fodeb(1:3) = force(1)%Vhxc_atom(1:3, 1)
IF (nspins == 1) THEN
@ -634,13 +663,13 @@ CONTAINS
IF (debug_forces) THEN
fodeb(1:3) = force(1)%Vhxc_atom(1:3, 1) - fodeb(1:3)
CALL para_env%sum(fodeb)
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Px*dKg[X]PAW ", fodeb
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Dx*dgxc[Dx]PAW ", fodeb
END IF
END IF
END IF
! ADMM XC correction Exc[rho_admm]
IF (do_admm .AND. tddfpt_control%admm_xc_correction) THEN
IF (do_admm .AND. tddfpt_control%admm_xc_correction .AND. (tddfpt_control%spinflip .NE. tddfpt_sf_col)) THEN
IF (admm_env%aux_exch_func == do_admm_aux_exch_func_none) THEN
! nothing to do
ELSE
@ -658,13 +687,16 @@ CONTAINS
END IF
!
NULLIFY (mfx, mgx)
CALL dbcsr_allocate_matrix_set(mfx, nspins)
CALL dbcsr_allocate_matrix_set(mfx, SIZE(evect, 1))
CALL dbcsr_allocate_matrix_set(mgx, nspins)
DO ispin = 1, nspins
ALLOCATE (mfx(ispin)%matrix, mgx(ispin)%matrix)
DO ispin = 1, SIZE(evect, 1)
ALLOCATE (mfx(ispin)%matrix)
CALL dbcsr_create(mfx(ispin)%matrix, template=matrix_s_aux_fit(1)%matrix)
CALL dbcsr_copy(mfx(ispin)%matrix, matrix_s_aux_fit(1)%matrix)
CALL dbcsr_set(mfx(ispin)%matrix, 0.0_dp)
END DO
DO ispin = 1, nspins
ALLOCATE (mgx(ispin)%matrix)
CALL dbcsr_create(mgx(ispin)%matrix, template=matrix_s_aux_fit(1)%matrix)
CALL dbcsr_copy(mgx(ispin)%matrix, matrix_s_aux_fit(1)%matrix)
CALL dbcsr_set(mgx(ispin)%matrix, 0.0_dp)
@ -675,12 +707,12 @@ CONTAINS
CALL qs_rho_get(rho_aux_fit, rho_r=rho_r_aux, rho_g=rho_g_aux)
CALL qs_rho_get(rho_aux_fit, rho_ao=matrix_p_admm)
! rhox_aux
ALLOCATE (rhox_r_aux(nspins), rhox_g_aux(nspins))
DO ispin = 1, nspins
ALLOCATE (rhox_r_aux(SIZE(evect, 1)), rhox_g_aux(SIZE(evect, 1)))
DO ispin = 1, SIZE(evect, 1)
CALL auxbas_pw_pool%create_pw(rhox_r_aux(ispin))
CALL auxbas_pw_pool%create_pw(rhox_g_aux(ispin))
END DO
DO ispin = 1, nspins
DO ispin = 1, SIZE(evect, 1)
CALL calculate_rho_elec(ks_env=ks_env, matrix_p=matrix_px1_admm(ispin)%matrix, &
rho=rhox_r_aux(ispin), rho_gspace=rhox_g_aux(ispin), &
basis_type=basis_type, &
@ -713,7 +745,7 @@ CONTAINS
! because this would release the arrays. Instead we're simply going to deallocate rhox_aux.
DEALLOCATE (rhox_aux)
DO ispin = 1, nspins
DO ispin = 1, SIZE(evect, 1)
CALL auxbas_pw_pool%give_back_pw(rhox_r_aux(ispin))
CALL auxbas_pw_pool%give_back_pw(rhox_g_aux(ispin))
END DO
@ -722,7 +754,7 @@ CONTAINS
IF (nspins == 2) fscal = 2.0_dp
!
IF (debug_forces) fodeb(1:3) = force(1)%rho_elec(1:3, 1)
DO ispin = 1, nspins
DO ispin = 1, SIZE(evect, 1)
CALL pw_scale(fxc_rho(ispin), fxc_rho(ispin)%pw_grid%dvol)
CALL integrate_v_rspace(qs_env=qs_env, v_rspace=fxc_rho(ispin), &
hmat=mfx(ispin), &
@ -735,11 +767,11 @@ CONTAINS
IF (debug_forces) THEN
fodeb(1:3) = force(1)%rho_elec(1:3, 1) - fodeb(1:3)
CALL para_env%sum(fodeb)
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Px*dKf[X]ADMM", fodeb
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Dx*dfxc[Dx]ADMM", fodeb
END IF
IF (debug_forces) fodeb(1:3) = force(1)%rho_elec(1:3, 1)
DO ispin = 1, nspins
DO ispin = 1, SIZE(evect, 1)
CALL pw_scale(gxc_rho(ispin), gxc_rho(ispin)%pw_grid%dvol)
CALL pw_scale(gxc_rho(ispin), 0.5_dp)
CALL integrate_v_rspace(qs_env=qs_env, v_rspace=gxc_rho(ispin), &
@ -754,7 +786,7 @@ CONTAINS
IF (debug_forces) THEN
fodeb(1:3) = force(1)%rho_elec(1:3, 1) - fodeb(1:3)
CALL para_env%sum(fodeb)
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: P*dKg[X]ADMM", fodeb
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Dx*dgxc[Dx]ADMM", fodeb
END IF
CALL qs_fgxc_release(ks_env, fxc_rho, fxc_tau, gxc_rho, gxc_tau)
!
@ -799,7 +831,7 @@ CONTAINS
IF (debug_forces) THEN
fodeb(1:3) = force(1)%Vhxc_atom(1:3, 1) - fodeb(1:3)
CALL para_env%sum(fodeb)
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Px*dKf[X]ADMM-PAW ", fodeb
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Dx*dfxc[Dx]ADMM-PAW ", fodeb
END IF
IF (debug_forces) fodeb(1:3) = force(1)%Vhxc_atom(1:3, 1)
IF (nspins == 1) THEN
@ -818,7 +850,7 @@ CONTAINS
IF (debug_forces) THEN
fodeb(1:3) = force(1)%Vhxc_atom(1:3, 1) - fodeb(1:3)
CALL para_env%sum(fodeb)
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: P*dKg[X]ADMM-PAW ", fodeb
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Dx*dgxc[Dx]ADMM-PAW ", fodeb
END IF
END IF
!
@ -848,7 +880,7 @@ CONTAINS
nao_aux = admm_env%nao_aux_fit
ALLOCATE (dbwork)
CALL dbcsr_create(dbwork, template=matrix_fx(1)%matrix)
DO ispin = 1, nspins
DO ispin = 1, SIZE(evect, 1)
! fx
CALL cp_dbcsr_sm_fm_multiply(mfx(ispin)%matrix, admm_env%A, &
admm_env%work_aux_orb, nao)
@ -877,20 +909,20 @@ CONTAINS
END IF
END IF
DO ispin = 1, nspins
DO ispin = 1, SIZE(evect, 1)
CALL auxbas_pw_pool%give_back_pw(rhox_r(ispin))
CALL auxbas_pw_pool%give_back_pw(rhox_g(ispin))
END DO
DEALLOCATE (rhox_r, rhox_g)
CALL auxbas_pw_pool%give_back_pw(rhox_tot_gspace)
IF (gapw_xc) THEN
DO ispin = 1, nspins
DO ispin = 1, SIZE(evect, 1)
CALL auxbas_pw_pool%give_back_pw(rhoxx_r(ispin))
CALL auxbas_pw_pool%give_back_pw(rhoxx_g(ispin))
END DO
DEALLOCATE (rhoxx_r, rhoxx_g)
END IF
IF (.NOT. is_rks_triplets) THEN
IF (.NOT. (is_rks_triplets .OR. do_sf)) THEN
CALL auxbas_pw_pool%give_back_pw(xv_hartree_rspace)
CALL auxbas_pw_pool%give_back_pw(xv_hartree_gspace)
END IF
@ -898,9 +930,9 @@ CONTAINS
! HFX
IF (do_hfx) THEN
NULLIFY (matrix_hfx, matrix_hfx_asymm)
CALL dbcsr_allocate_matrix_set(matrix_hfx, nspins)
CALL dbcsr_allocate_matrix_set(matrix_hfx_asymm, nspins)
DO ispin = 1, nspins
CALL dbcsr_allocate_matrix_set(matrix_hfx, SIZE(evect, 1))
CALL dbcsr_allocate_matrix_set(matrix_hfx_asymm, SIZE(evect, 1))
DO ispin = 1, SIZE(evect, 1)
ALLOCATE (matrix_hfx(ispin)%matrix)
CALL dbcsr_create(matrix_hfx(ispin)%matrix, template=matrix_s(1)%matrix)
CALL dbcsr_copy(matrix_hfx(ispin)%matrix, matrix_s(1)%matrix)
@ -919,7 +951,7 @@ CONTAINS
CALL section_vals_val_get(hfx_section, "TREAT_LSD_IN_CORE", l_val=hfx_treat_lsd_in_core, &
i_rep_section=1)
mspin = 1
IF (hfx_treat_lsd_in_core) mspin = nspins
IF (hfx_treat_lsd_in_core) mspin = SIZE(evect, 1)
!
CALL get_qs_env(qs_env=qs_env, x_data=x_data, s_mstruct_changed=s_mstruct_changed)
distribute_fock_matrix = .TRUE.
@ -927,9 +959,9 @@ CONTAINS
IF (do_admm) THEN
CALL get_admm_env(qs_env%admm_env, matrix_s_aux_fit=matrix_s_aux_fit)
NULLIFY (matrix_hfx_admm, matrix_hfx_admm_asymm)
CALL dbcsr_allocate_matrix_set(matrix_hfx_admm, nspins)
CALL dbcsr_allocate_matrix_set(matrix_hfx_admm_asymm, nspins)
DO ispin = 1, nspins
CALL dbcsr_allocate_matrix_set(matrix_hfx_admm, SIZE(evect, 1))
CALL dbcsr_allocate_matrix_set(matrix_hfx_admm_asymm, SIZE(evect, 1))
DO ispin = 1, SIZE(evect, 1)
ALLOCATE (matrix_hfx_admm(ispin)%matrix)
CALL dbcsr_create(matrix_hfx_admm(ispin)%matrix, template=matrix_s_aux_fit(1)%matrix)
CALL dbcsr_copy(matrix_hfx_admm(ispin)%matrix, matrix_s_aux_fit(1)%matrix)
@ -942,8 +974,8 @@ CONTAINS
END DO
!
NULLIFY (mpe, mhe)
ALLOCATE (mpe(nspins, 1), mhe(nspins, 1))
DO ispin = 1, nspins
ALLOCATE (mpe(SIZE(evect, 1), 1), mhe(SIZE(evect, 1), 1))
DO ispin = 1, SIZE(evect)
mhe(ispin, 1)%matrix => matrix_hfx_admm(ispin)%matrix
mpe(ispin, 1)%matrix => matrix_px1_admm(ispin)%matrix
END DO
@ -957,11 +989,11 @@ CONTAINS
eh1 = 0.0
CALL integrate_four_center(qs_env, x_data, mhe, eh1, mpe, hfx_section, &
para_env, s_mstruct_changed, 1, distribute_fock_matrix, &
ispin=ispin)
ispin=ispin, nspins=SIZE(evect, 1))
END DO
END IF
!anti-symmetric density
DO ispin = 1, nspins
DO ispin = 1, SIZE(evect, 1)
mhe(ispin, 1)%matrix => matrix_hfx_admm_asymm(ispin)%matrix
mpe(ispin, 1)%matrix => matrix_px1_admm_asymm(ispin)%matrix
END DO
@ -975,7 +1007,7 @@ CONTAINS
eh1 = 0.0
CALL integrate_four_center(qs_env, x_data, mhe, eh1, mpe, hfx_section, &
para_env, s_mstruct_changed, 1, distribute_fock_matrix, &
ispin=ispin)
ispin=ispin, nspins=SIZE(evect, 1))
END DO
END IF
!
@ -984,7 +1016,7 @@ CONTAINS
ALLOCATE (dbwork, dbwork_asymm)
CALL dbcsr_create(dbwork, template=matrix_hfx(1)%matrix)
CALL dbcsr_create(dbwork_asymm, template=matrix_hfx(1)%matrix, matrix_type=dbcsr_type_antisymmetric)
DO ispin = 1, nspins
DO ispin = 1, SIZE(evect, 1)
CALL cp_dbcsr_sm_fm_multiply(matrix_hfx_admm(ispin)%matrix, admm_env%A, &
admm_env%work_aux_orb, nao)
CALL parallel_gemm('T', 'N', nao, nao, nao_aux, &
@ -1023,8 +1055,10 @@ CONTAINS
use_virial = .FALSE.
NULLIFY (mdum)
fval = 2.0_dp*REAL(nspins, KIND=dp)*0.5_dp !0.5 factor because of symemtry/anti-symmetry
! For SF TDDFT integrate_four_center and derivatives_four_center routines introduce a factor of 1/2
IF (do_sf) fval = fval*2.0_dp
IF (debug_forces) fodeb(1:3) = force(1)%fock_4c(1:3, 1)
DO ispin = 1, nspins
DO ispin = 1, SIZE(evect, 1)
mpe(ispin, 1)%matrix => matrix_px1_admm(ispin)%matrix
END DO
IF (x_data(1, 1)%do_hfx_ri) THEN
@ -1034,9 +1068,9 @@ CONTAINS
use_virial=use_virial, rescale_factor=fval)
ELSE
CALL derivatives_four_center(qs_env, mpe, mdum, hfx_section, para_env, 1, use_virial, &
adiabatic_rescale_factor=fval)
adiabatic_rescale_factor=fval, nspins=SIZE(mpe, 1))
END IF
DO ispin = 1, nspins
DO ispin = 1, SIZE(evect, 1)
mpe(ispin, 1)%matrix => matrix_px1_admm_asymm(ispin)%matrix
END DO
IF (x_data(1, 1)%do_hfx_ri) THEN
@ -1046,12 +1080,12 @@ CONTAINS
use_virial=use_virial, rescale_factor=fval)
ELSE
CALL derivatives_four_center(qs_env, mpe, mdum, hfx_section, para_env, 1, use_virial, &
adiabatic_rescale_factor=fval)
adiabatic_rescale_factor=fval, nspins=SIZE(mpe, 1))
END IF
IF (debug_forces) THEN
fodeb(1:3) = force(1)%fock_4c(1:3, 1) - fodeb(1:3)
CALL para_env%sum(fodeb)
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Px*hfx'*Px ", fodeb
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Dx*dhfx'*Dx ", fodeb
END IF
!
DEALLOCATE (mpe, mhe)
@ -1060,8 +1094,8 @@ CONTAINS
CALL dbcsr_deallocate_matrix_set(matrix_hfx_admm_asymm)
ELSE
NULLIFY (mpe, mhe)
ALLOCATE (mpe(nspins, 1), mhe(nspins, 1))
DO ispin = 1, nspins
ALLOCATE (mpe(SIZE(evect, 1), 1), mhe(SIZE(evect, 1), 1))
DO ispin = 1, SIZE(evect, 1)
mhe(ispin, 1)%matrix => matrix_hfx(ispin)%matrix
mpe(ispin, 1)%matrix => matrix_px1(ispin)%matrix
END DO
@ -1075,12 +1109,12 @@ CONTAINS
eh1 = 0.0
CALL integrate_four_center(qs_env, x_data, mhe, eh1, mpe, hfx_section, &
para_env, s_mstruct_changed, 1, distribute_fock_matrix, &
ispin=ispin)
ispin=ispin, nspins=SIZE(mpe, 1))
END DO
END IF
!anti-symmetric density matrix
DO ispin = 1, nspins
DO ispin = 1, SIZE(evect, 1)
mhe(ispin, 1)%matrix => matrix_hfx_asymm(ispin)%matrix
mpe(ispin, 1)%matrix => matrix_px1_asymm(ispin)%matrix
END DO
@ -1094,15 +1128,17 @@ CONTAINS
eh1 = 0.0
CALL integrate_four_center(qs_env, x_data, mhe, eh1, mpe, hfx_section, &
para_env, s_mstruct_changed, 1, distribute_fock_matrix, &
ispin=ispin)
ispin=ispin, nspins=SIZE(mpe, 1))
END DO
END IF
! forces
use_virial = .FALSE.
NULLIFY (mdum)
fval = 2.0_dp*REAL(nspins, KIND=dp)*0.5_dp !extra 0.5 factor because of symmetry/antisymemtry
! For SF TDDFT integrate_four_center and derivatives_four_center routines introduce a factor of 1/2
IF (do_sf) fval = fval*2.0_dp
IF (debug_forces) fodeb(1:3) = force(1)%fock_4c(1:3, 1)
DO ispin = 1, nspins
DO ispin = 1, SIZE(evect, 1)
mpe(ispin, 1)%matrix => matrix_px1(ispin)%matrix
END DO
IF (x_data(1, 1)%do_hfx_ri) THEN
@ -1112,9 +1148,9 @@ CONTAINS
use_virial=use_virial, rescale_factor=fval)
ELSE
CALL derivatives_four_center(qs_env, mpe, mdum, hfx_section, para_env, 1, use_virial, &
adiabatic_rescale_factor=fval)
adiabatic_rescale_factor=fval, nspins=SIZE(mpe, 1))
END IF
DO ispin = 1, nspins
DO ispin = 1, SIZE(evect, 1)
mpe(ispin, 1)%matrix => matrix_px1_asymm(ispin)%matrix
END DO
IF (x_data(1, 1)%do_hfx_ri) THEN
@ -1124,18 +1160,20 @@ CONTAINS
use_virial=use_virial, rescale_factor=fval)
ELSE
CALL derivatives_four_center(qs_env, mpe, mdum, hfx_section, para_env, 1, use_virial, &
adiabatic_rescale_factor=fval)
adiabatic_rescale_factor=fval, nspins=SIZE(mpe, 1))
END IF
IF (debug_forces) THEN
fodeb(1:3) = force(1)%fock_4c(1:3, 1) - fodeb(1:3)
CALL para_env%sum(fodeb)
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Px*hfx'*Px ", fodeb
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Dx*dhfx*Dx ", fodeb
END IF
!
DEALLOCATE (mpe, mhe)
END IF
fval = 2.0_dp*REAL(nspins, KIND=dp)*0.5_dp !extra 0.5 because of symm/antisymm
DO ispin = 1, nspins
! For SF TDDFT integrate_four_center and derivatives_four_center routines introduce a factor of 1/2
IF (do_sf) fval = fval*2.0_dp
DO ispin = 1, SIZE(evect, 1)
CALL dbcsr_scale(matrix_hfx(ispin)%matrix, fval)
CALL dbcsr_scale(matrix_hfx_asymm(ispin)%matrix, fval)
END DO
@ -1176,83 +1214,140 @@ CONTAINS
cpmos => ex_env%cpmos
focc = 2.0_dp
IF (nspins == 2) focc = 1.0_dp
! Initialize mos and dimensions of occupied space
! In the following comments mos is referred to as Ca and mos2 as Cb
spin = 1
mos => gs_mos(1)%mos_occ
CALL cp_fm_get_info(mos, ncol_global=norb(1))
IF (nspins == 2) THEN
mos2 => gs_mos(2)%mos_occ
CALL cp_fm_get_info(mos2, ncol_global=norb(2))
END IF
! Build response vector, Eq. 49, and the third term of \Lamda_munu, Eq. 51
DO ispin = 1, nspins
mos => gs_mos(ispin)%mos_occ
CALL cp_fm_get_info(evect(ispin), ncol_global=norb)
CALL cp_fm_create(vcvec, mos%matrix_struct, "vcvec")
! Initialize mos and dimensions of occupied space
IF (.NOT. do_sf) THEN
spin = ispin
mos => gs_mos(ispin)%mos_occ
mos2 => gs_mos(ispin)%mos_occ
END IF
! Create working fields for the response vector
CALL cp_fm_create(vcvec, gs_mos(ispin)%mos_occ%matrix_struct, "vcvec")
CALL cp_fm_get_info(vcvec, matrix_struct=fm_struct, nrow_global=nao)
CALL cp_fm_struct_create(fm_struct_mat, context=fm_struct%context, nrow_global=norb, &
ncol_global=norb, para_env=fm_struct%para_env)
CALL cp_fm_struct_create(fm_struct_mat, context=fm_struct%context, nrow_global=norb(spin), &
ncol_global=norb(ispin), para_env=fm_struct%para_env)
CALL cp_fm_create(cvcmat, fm_struct_mat)
CALL cp_fm_struct_release(fm_struct_mat)
!
! Allocate and initialize the Lambda matrix
ALLOCATE (matrix_wx1(ispin)%matrix)
CALL dbcsr_create(matrix=matrix_wx1(ispin)%matrix, template=matrix_s(1)%matrix)
CALL cp_dbcsr_alloc_block_from_nbl(matrix_wx1(ispin)%matrix, sab_orb)
CALL dbcsr_set(matrix_wx1(ispin)%matrix, 0.0_dp)
!
IF (.NOT. is_rks_triplets) THEN
! Add Hartree contributions to the perturbation vector
IF (.NOT. (is_rks_triplets .OR. do_sf)) THEN
CALL cp_dbcsr_sm_fm_multiply(matrix_hx(ispin)%matrix, evect(ispin), &
cpmos(ispin), norb, alpha=focc, beta=1.0_dp)
CALL cp_dbcsr_sm_fm_multiply(matrix_hx(ispin)%matrix, mos, vcvec, norb, alpha=1.0_dp, beta=0.0_dp)
CALL parallel_gemm("T", "N", norb, norb, nao, 1.0_dp, mos, vcvec, 0.0_dp, cvcmat)
CALL parallel_gemm("N", "N", nao, norb, norb, 1.0_dp, evect(ispin), cvcmat, 0.0_dp, vcvec)
cpmos(ispin), norb(ispin), alpha=focc, beta=1.0_dp)
CALL cp_dbcsr_sm_fm_multiply(matrix_hx(ispin)%matrix, mos, vcvec, norb(ispin), alpha=1.0_dp, beta=0.0_dp)
CALL parallel_gemm("T", "N", norb(ispin), norb(ispin), nao, 1.0_dp, mos, vcvec, 0.0_dp, cvcmat)
CALL parallel_gemm("N", "N", nao, norb(ispin), norb(ispin), 1.0_dp, evect(ispin), cvcmat, 0.0_dp, vcvec)
CALL cp_dbcsr_sm_fm_multiply(matrix_s(1)%matrix, vcvec, cpmos(ispin), &
norb, alpha=-focc, beta=1.0_dp)
norb(ispin), alpha=-focc, beta=1.0_dp)
!
CALL cp_dbcsr_plus_fm_fm_t(matrix_wx1(ispin)%matrix, matrix_v=mos, matrix_g=vcvec, &
ncol=norb, alpha=2.0_dp, symmetry_mode=1)
ncol=norb(ispin), alpha=2.0_dp, symmetry_mode=1)
END IF
!
IF (myfun /= xc_none) THEN
CALL cp_dbcsr_sm_fm_multiply(matrix_fx(ispin)%matrix, evect(ispin), &
cpmos(ispin), norb, alpha=focc, beta=1.0_dp)
CALL cp_dbcsr_sm_fm_multiply(matrix_fx(ispin)%matrix, mos, vcvec, norb, alpha=1.0_dp, beta=0.0_dp)
CALL parallel_gemm("T", "N", norb, norb, nao, 1.0_dp, mos, vcvec, 0.0_dp, cvcmat)
CALL parallel_gemm("N", "N", nao, norb, norb, 1.0_dp, evect(ispin), cvcmat, 0.0_dp, vcvec)
CALL cp_dbcsr_sm_fm_multiply(matrix_s(1)%matrix, vcvec, cpmos(ispin), &
norb, alpha=-focc, beta=1.0_dp)
! Add exchange-correlation kernel and exchange-correlation kernel derivative contributions to the response vector
IF ((myfun /= xc_none) .AND. (tddfpt_control%spinflip /= tddfpt_sf_col)) THEN
! XC Kernel contributions
! For spin-flip excitations this is the only contribution to the alpha response vector
IF (.NOT. (do_sf .AND. (ispin .EQ. 2))) THEN
! F*X
CALL cp_dbcsr_sm_fm_multiply(matrix_fx(spin)%matrix, evect(spin), &
cpmos(ispin), norb(ispin), alpha=focc, beta=1.0_dp)
END IF
! For spin-flip excitations this is the only contribution to the beta response vector
IF (.NOT. (do_sf .AND. (ispin .EQ. 1))) THEN
! F*Cb
CALL cp_dbcsr_sm_fm_multiply(matrix_fx(spin)%matrix, mos2, vcvec, norb(ispin), alpha=1.0_dp, beta=0.0_dp)
! Ca^T*F*Cb
CALL parallel_gemm("T", "N", norb(spin), norb(ispin), nao, 1.0_dp, mos, vcvec, 0.0_dp, cvcmat)
! X*Ca^T*F*Cb
CALL parallel_gemm("N", "N", nao, norb(ispin), norb(spin), 1.0_dp, evect(spin), cvcmat, 0.0_dp, vcvec)
! -S*X*Ca^T*F*Cb
CALL cp_dbcsr_sm_fm_multiply(matrix_s(1)%matrix, vcvec, cpmos(ispin), &
norb(ispin), alpha=-focc, beta=1.0_dp)
! Add contributions to the \Lambda_munu for the perturbed overlap matrix term, third term of Eq. 51
! 2X*Ca^T*F*Cb*Cb^T
CALL cp_dbcsr_plus_fm_fm_t(matrix_wx1(ispin)%matrix, matrix_v=vcvec, matrix_g=gs_mos(ispin)%mos_occ, &
ncol=norb(ispin), alpha=2.0_dp, symmetry_mode=1)
END IF
!
CALL cp_dbcsr_plus_fm_fm_t(matrix_wx1(ispin)%matrix, matrix_v=mos, matrix_g=vcvec, &
ncol=norb, alpha=2.0_dp, symmetry_mode=1)
! XC g (third functional derivative) contributions
! g*Ca*focc
CALL cp_dbcsr_sm_fm_multiply(matrix_gx(ispin)%matrix, gs_mos(ispin)%mos_occ, &
cpmos(ispin), norb(ispin), alpha=focc, beta=1.0_dp)
! Add contributions to the \Lambda_munu for the perturbed overlap matrix term, third term of Eq. 51
! g*Ca
CALL cp_dbcsr_sm_fm_multiply(matrix_gx(ispin)%matrix, gs_mos(ispin)%mos_occ, vcvec, norb(ispin), &
alpha=1.0_dp, beta=0.0_dp)
! Ca^T*g*Ca
CALL parallel_gemm("T", "N", norb(ispin), norb(ispin), nao, 1.0_dp, gs_mos(ispin)%mos_occ, vcvec, 0.0_dp, cvcmat)
! Ca*Ca^T*g*Ca
CALL parallel_gemm("N", "N", nao, norb(ispin), norb(ispin), 1.0_dp, gs_mos(ispin)%mos_occ, cvcmat, 0.0_dp, vcvec)
! Ca*Ca^T*g*Ca*Ca^T
CALL cp_dbcsr_plus_fm_fm_t(matrix_wx1(ispin)%matrix, matrix_v=vcvec, matrix_g=gs_mos(ispin)%mos_occ, &
ncol=norb(ispin), alpha=1.0_dp, symmetry_mode=1)
!
CALL cp_dbcsr_sm_fm_multiply(matrix_gx(ispin)%matrix, mos, &
cpmos(ispin), norb, alpha=focc, beta=1.0_dp)
!
CALL cp_dbcsr_sm_fm_multiply(matrix_gx(ispin)%matrix, mos, vcvec, norb, alpha=1.0_dp, beta=0.0_dp)
CALL parallel_gemm("T", "N", norb, norb, nao, 1.0_dp, mos, vcvec, 0.0_dp, cvcmat)
CALL parallel_gemm("N", "N", nao, norb, norb, 1.0_dp, mos, cvcmat, 0.0_dp, vcvec)
CALL cp_dbcsr_plus_fm_fm_t(matrix_wx1(ispin)%matrix, matrix_v=mos, matrix_g=vcvec, &
ncol=norb, alpha=1.0_dp, symmetry_mode=1)
END IF
!
! Add Fock contributions to the response vector
IF (do_hfx) THEN
CALL cp_dbcsr_sm_fm_multiply(matrix_hfx(ispin)%matrix, evect(ispin), &
cpmos(ispin), norb, alpha=focc, beta=1.0_dp)
CALL cp_dbcsr_sm_fm_multiply(matrix_hfx(ispin)%matrix, mos, vcvec, norb, alpha=1.0_dp, beta=0.0_dp)
CALL cp_dbcsr_sm_fm_multiply(matrix_hfx_asymm(ispin)%matrix, evect(ispin), &
cpmos(ispin), norb, alpha=focc, beta=1.0_dp)
CALL cp_dbcsr_sm_fm_multiply(matrix_hfx_asymm(ispin)%matrix, mos, vcvec, norb, alpha=1.0_dp, beta=1.0_dp)
!
CALL parallel_gemm("T", "N", norb, norb, nao, 1.0_dp, mos, vcvec, 0.0_dp, cvcmat)
CALL parallel_gemm("N", "N", nao, norb, norb, 1.0_dp, evect(ispin), cvcmat, 0.0_dp, vcvec)
CALL cp_dbcsr_sm_fm_multiply(matrix_s(1)%matrix, vcvec, cpmos(ispin), &
norb, alpha=-focc, beta=1.0_dp)
!
CALL cp_dbcsr_plus_fm_fm_t(matrix_wx1(ispin)%matrix, matrix_v=mos, matrix_g=vcvec, &
ncol=norb, alpha=2.0_dp, symmetry_mode=1)
! For spin-flip excitations this is the only contribution to the alpha response vector
IF (.NOT. (do_sf .AND. (ispin .EQ. 2))) THEN
! F^sym*X
CALL cp_dbcsr_sm_fm_multiply(matrix_hfx(spin)%matrix, evect(spin), &
cpmos(ispin), norb(ispin), alpha=focc, beta=1.0_dp)
! F^asym*X
CALL cp_dbcsr_sm_fm_multiply(matrix_hfx_asymm(spin)%matrix, evect(spin), &
cpmos(ispin), norb(ispin), alpha=focc, beta=1.0_dp)
END IF
! For spin-flip excitations this is the only contribution to the beta response vector
IF (.NOT. (do_sf .AND. (ispin .EQ. 1))) THEN
! F^sym*Cb
CALL cp_dbcsr_sm_fm_multiply(matrix_hfx(spin)%matrix, mos2, vcvec, norb(ispin), alpha=1.0_dp, beta=0.0_dp)
! -F^asym*Cb
CALL cp_dbcsr_sm_fm_multiply(matrix_hfx_asymm(spin)%matrix, mos2, vcvec, norb(ispin), &
alpha=1.0_dp, beta=1.0_dp)
! Ca^T*F*Cb
CALL parallel_gemm("T", "N", norb(spin), norb(ispin), nao, 1.0_dp, mos, vcvec, 0.0_dp, cvcmat)
! X*Ca^T*F*Cb
CALL parallel_gemm("N", "N", nao, norb(ispin), norb(spin), 1.0_dp, evect(spin), cvcmat, 0.0_dp, vcvec)
! -S*X*Ca^T*F*Cb
CALL cp_dbcsr_sm_fm_multiply(matrix_s(1)%matrix, vcvec, cpmos(ispin), &
norb(ispin), alpha=-focc, beta=1.0_dp)
! Add contributions to the \Lambda_munu for the perturbed overlap matrix term, third term of Eq. 51
! 2X*Ca^T*F*Cb*Cb^T
CALL cp_dbcsr_plus_fm_fm_t(matrix_wx1(ispin)%matrix, matrix_v=vcvec, matrix_g=mos2, &
ncol=norb(ispin), alpha=2.0_dp, symmetry_mode=1)
END IF
END IF
!
CALL cp_fm_release(vcvec)
CALL cp_fm_release(cvcmat)
END DO
IF (.NOT. is_rks_triplets) THEN
IF (.NOT. (is_rks_triplets .OR. do_sf)) THEN
CALL dbcsr_deallocate_matrix_set(matrix_hx)
END IF
IF (ASSOCIATED(ex_env%matrix_wx1)) CALL dbcsr_deallocate_matrix_set(ex_env%matrix_wx1)
ex_env%matrix_wx1 => matrix_wx1
IF (myfun /= xc_none) THEN
IF (.NOT. ((myfun == xc_none) .OR. (tddfpt_control%spinflip == tddfpt_sf_col))) THEN
CALL dbcsr_deallocate_matrix_set(matrix_fx)
CALL dbcsr_deallocate_matrix_set(matrix_gx)
END IF

View file

@ -49,6 +49,7 @@ MODULE qs_tddfpt2_forces
USE hfx_ri, ONLY: hfx_ri_update_ks
USE hfx_types, ONLY: hfx_type
USE input_constants, ONLY: do_admm_aux_exch_func_none,&
no_sf_tddfpt,&
oe_shift,&
tddfpt_kernel_full,&
tddfpt_kernel_none,&
@ -143,10 +144,14 @@ MODULE qs_tddfpt2_forces
CONTAINS
! **************************************************************************************************
!> \brief Perform TDDFPT gradient calculation.
!> \brief Perform TDDFPT gradient calculation. This routine calculates the response vector R of Eq. 49
!> in J. Chem. Theory Comput. 2022, 18, 41864202 (https://doi.org/10.1021/acs.jctc.2c00144)
!> in ex_env%cpmos and a few contributions to the gradient.
!> \param qs_env Quickstep environment
!> \param gs_mos ...
!> \param ex_env ...
!> \param ex_env Holds: Response vector ex_env%cpmos = R
!> Difference density ex_env%matrix_pe = T
!> Matrix ex_env%matrix_hz = H_munu[T]
!> \param kernel_env ...
!> \param sub_env ...
!> \param work_matrices ...
@ -164,7 +169,8 @@ CONTAINS
CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_forces_main'
INTEGER :: handle, ispin, nspins
INTEGER :: handle, ispin, nspins, spin
LOGICAL :: do_sf
TYPE(admm_type), POINTER :: admm_env
TYPE(cp_fm_struct_type), POINTER :: matrix_struct
TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_pe_asymm, matrix_pe_symm, &
@ -180,6 +186,11 @@ CONTAINS
nspins = dft_control%nspins
tddfpt_control => dft_control%tddfpt2_control
IF (tddfpt_control%spinflip .EQ. no_sf_tddfpt) THEN
do_sf = .FALSE.
ELSE
do_sf = .TRUE.
END IF
! rhs of linres equation
IF (ASSOCIATED(ex_env%cpmos)) THEN
DO ispin = 1, SIZE(ex_env%cpmos)
@ -188,17 +199,24 @@ CONTAINS
DEALLOCATE (ex_env%cpmos)
END IF
ALLOCATE (ex_env%cpmos(nspins))
! Create and initialize rectangular matrices of nao*occ dimension for alpha and beta R vectors
! for the Z-vector equation system: AZ=-R
DO ispin = 1, nspins
CALL cp_fm_get_info(matrix=ex_env%evect(ispin), matrix_struct=matrix_struct)
CALL cp_fm_get_info(gs_mos(ispin)%mos_occ, matrix_struct=matrix_struct)
CALL cp_fm_create(ex_env%cpmos(ispin), matrix_struct)
CALL cp_fm_set_all(ex_env%cpmos(ispin), 0.0_dp)
END DO
CALL get_qs_env(qs_env=qs_env, matrix_s=matrix_s)
NULLIFY (matrix_pe_asymm, matrix_pe_symm)
! Build difference density matrix_pe = X*X^T - (C*X^T*S*X*C^T + (C*X^T*S*X*C^T)^T)/2
!
CALL dbcsr_allocate_matrix_set(ex_env%matrix_pe, nspins)
CALL dbcsr_allocate_matrix_set(matrix_pe_symm, nspins)
CALL dbcsr_allocate_matrix_set(matrix_pe_asymm, nspins)
DO ispin = 1, nspins
! Initialize matrix_pe as a sparse matrix with zeros
ALLOCATE (ex_env%matrix_pe(ispin)%matrix)
CALL dbcsr_create(ex_env%matrix_pe(ispin)%matrix, template=matrix_s(1)%matrix)
CALL dbcsr_copy(ex_env%matrix_pe(ispin)%matrix, matrix_s(1)%matrix)
@ -213,11 +231,17 @@ CONTAINS
matrix_type=dbcsr_type_antisymmetric)
CALL dbcsr_complete_redistribute(ex_env%matrix_pe(ispin)%matrix, matrix_pe_asymm(ispin)%matrix)
CALL tddfpt_resvec1(ex_env%evect(ispin), gs_mos(ispin)%mos_occ, &
matrix_s(1)%matrix, ex_env%matrix_pe(ispin)%matrix)
IF (do_sf) THEN
spin = 1
ELSE
spin = ispin
END IF
! Add difference density to matrix_pe
CALL tddfpt_resvec1(ex_env%evect(spin), gs_mos(spin)%mos_occ, &
matrix_s(1)%matrix, ex_env%matrix_pe(ispin)%matrix, ispin, do_sf)
END DO
!
! ground state ADMM!
! Project the difference density into auxiliary basis for ADMM
IF (dft_control%do_admm) THEN
CALL get_qs_env(qs_env, admm_env=admm_env)
CALL get_admm_env(admm_env, matrix_s_aux_fit=matrix_s_aux_fit)
@ -232,6 +256,7 @@ CONTAINS
END DO
END IF
!
CALL dbcsr_allocate_matrix_set(ex_env%matrix_hz, nspins)
DO ispin = 1, nspins
ALLOCATE (ex_env%matrix_hz(ispin)%matrix)
@ -239,6 +264,7 @@ CONTAINS
CALL dbcsr_copy(ex_env%matrix_hz(ispin)%matrix, matrix_s(1)%matrix)
CALL dbcsr_set(ex_env%matrix_hz(ispin)%matrix, 0.0_dp)
END DO
! Calculate first term of R vector: H_{\mu i\sigma}[T]
IF (dft_control%qs_control%xtb) THEN
CALL tddfpt_resvec2_xtb(qs_env, ex_env%matrix_pe, gs_mos, ex_env%matrix_hz, ex_env%cpmos)
ELSE
@ -246,9 +272,9 @@ CONTAINS
gs_mos, ex_env%matrix_hz, ex_env%cpmos)
END IF
!
CALL dbcsr_allocate_matrix_set(ex_env%matrix_px1, nspins)
CALL dbcsr_allocate_matrix_set(ex_env%matrix_px1_asymm, nspins)
DO ispin = 1, nspins
CALL dbcsr_allocate_matrix_set(ex_env%matrix_px1, SIZE(ex_env%evect, 1))
CALL dbcsr_allocate_matrix_set(ex_env%matrix_px1_asymm, SIZE(ex_env%evect, 1))
DO ispin = 1, SIZE(ex_env%evect, 1)
ALLOCATE (ex_env%matrix_px1(ispin)%matrix)
CALL dbcsr_create(ex_env%matrix_px1(ispin)%matrix, template=matrix_s(1)%matrix)
CALL dbcsr_copy(ex_env%matrix_px1(ispin)%matrix, matrix_s(1)%matrix)
@ -263,9 +289,9 @@ CONTAINS
IF (tddfpt_control%do_admm) THEN
CALL get_qs_env(qs_env, admm_env=admm_env)
CALL get_admm_env(admm_env, matrix_s_aux_fit=matrix_s_aux_fit)
CALL dbcsr_allocate_matrix_set(ex_env%matrix_px1_admm, nspins)
CALL dbcsr_allocate_matrix_set(ex_env%matrix_px1_admm_asymm, nspins)
DO ispin = 1, nspins
CALL dbcsr_allocate_matrix_set(ex_env%matrix_px1_admm, SIZE(ex_env%evect, 1))
CALL dbcsr_allocate_matrix_set(ex_env%matrix_px1_admm_asymm, SIZE(ex_env%evect, 1))
DO ispin = 1, SIZE(ex_env%evect, 1)
ALLOCATE (ex_env%matrix_px1_admm(ispin)%matrix)
CALL dbcsr_create(ex_env%matrix_px1_admm(ispin)%matrix, template=matrix_s_aux_fit(1)%matrix)
CALL dbcsr_copy(ex_env%matrix_px1_admm(ispin)%matrix, matrix_s_aux_fit(1)%matrix)
@ -278,9 +304,9 @@ CONTAINS
ex_env%matrix_px1_admm_asymm(ispin)%matrix)
END DO
END IF
! TDA forces
! TDA forces. Calculates and adds all missing terms for the response vector, Eq. 49.
CALL tddfpt_forces(qs_env, ex_env, gs_mos, kernel_env, sub_env, work_matrices)
! Rotate res vector cpmos into original frame of occupied orbitals
! Rotate res vector cpmos into original frame of occupied orbitals. Why do we need this?
CALL tddfpt_resvec3(qs_env, ex_env%cpmos, work_matrices)
CALL dbcsr_deallocate_matrix_set(matrix_pe_symm)
@ -341,6 +367,7 @@ CONTAINS
ELSE
!
CALL exstate_potential_release(ex_env)
! Build the values of hartree, fock and exchange-correlation potential on the grid
CALL ks_ref_potential(qs_env, ex_env%vh_rspace, ex_env%vxc_rspace, &
ex_env%vtau_rspace, ex_env%vadmm_rspace, ehartree, exc)
CALL ks_ref_potential_atom(qs_env, ex_env%local_rho_set, ex_env%local_rho_set_admm, &
@ -360,9 +387,14 @@ CONTAINS
END SUBROUTINE tddfpt_forces
! **************************************************************************************************
!> \brief Calculate direct tddft forces
!> \brief Calculate direct tddft forces.
!> J. Chem. Theory Comput. 2022, 18, 7, 41864202 (https://doi.org/10.1021/acs.jctc.2c00144)
!> \param qs_env ...
!> \param ex_env ...
!> \param ex_env Holds on exit
!> cpmos = R, Response vector, Eq. 49.
!> matrix_pe = T, Difference density, Eq. 44.
!> matrix_wx1 = CK[D^X]X^T, Third term of Eq. 51.
!> matrix_wz = CX^T(\omegaS - K)XC^T, Last term of Eq. 51.
!> \param gs_mos ...
!> \param kernel_env ...
!> \param sub_env ...
@ -386,7 +418,8 @@ CONTAINS
CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_force_direct'
INTEGER :: handle, iounit, ispin, natom, norb, &
nspins
nspins, spin
LOGICAL :: do_sf
REAL(KIND=dp) :: evalue
REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: ftot1, ftot2
REAL(KIND=dp), DIMENSION(3) :: fodeb
@ -418,6 +451,11 @@ CONTAINS
sab_orb=sab_orb, dft_control=dft_control, force=force)
NULLIFY (tddfpt_control)
tddfpt_control => dft_control%tddfpt2_control
IF (tddfpt_control%spinflip .EQ. no_sf_tddfpt) THEN
do_sf = .FALSE.
ELSE
do_sf = .TRUE.
END IF
nspins = dft_control%nspins
IF (debug_forces) THEN
@ -426,27 +464,43 @@ CONTAINS
CALL total_qs_force(ftot1, force, atomic_kind_set)
END IF
! Build last terms of the response vector, Eq. 49, and third term of Lambda_munu, Eq. 51.
! the response vector is in ex_env%cpmos and Lambda is in ex_env%matrix_wx1
CALL tddfpt_kernel_force(qs_env, ex_env, gs_mos, kernel_env, sub_env, work_matrices, debug_forces)
! Overlap matrix
! Overlap matrix, build the Lambda matrix, Eq. 51.
NULLIFY (matrix_wx1, matrix_wz)
CALL dbcsr_allocate_matrix_set(matrix_wz, nspins)
matrix_wx1 => ex_env%matrix_wx1
CALL get_qs_env(qs_env=qs_env, matrix_s=matrix_s, matrix_ks=matrix_ks)
NULLIFY (matrix_wz)
CALL dbcsr_allocate_matrix_set(matrix_wz, nspins)
DO ispin = 1, nspins
IF (do_sf) THEN
spin = 1
ELSE
spin = ispin
END IF
! Create and initialize the Lambda matrix as a sparse matrix
ALLOCATE (matrix_wz(ispin)%matrix)
CALL dbcsr_create(matrix=matrix_wz(ispin)%matrix, template=matrix_s(1)%matrix)
CALL cp_dbcsr_alloc_block_from_nbl(matrix_wz(ispin)%matrix, sab_orb)
CALL dbcsr_set(matrix_wz(ispin)%matrix, 0.0_dp)
CALL cp_fm_get_info(gs_mos(ispin)%mos_occ, ncol_global=norb)
CALL cp_dbcsr_plus_fm_fm_t(matrix_wz(ispin)%matrix, matrix_v=evect(ispin), ncol=norb)
evalue = ex_env%evalue
IF (tddfpt_control%oe_corr == oe_shift) THEN
evalue = ex_env%evalue - tddfpt_control%ev_shift
! For spin-flip excitations only the beta component of the Lambda matrix
! contains the excitation energy term
IF (.NOT. (do_sf .AND. (ispin == 1))) THEN
CALL cp_fm_get_info(gs_mos(spin)%mos_occ, ncol_global=norb)
CALL cp_dbcsr_plus_fm_fm_t(matrix_wz(ispin)%matrix, matrix_v=evect(spin), ncol=norb)
evalue = ex_env%evalue
IF (tddfpt_control%oe_corr == oe_shift) THEN
evalue = ex_env%evalue - tddfpt_control%ev_shift
END IF
CALL dbcsr_scale(matrix_wz(ispin)%matrix, evalue)
END IF
! For spin-flip excitations only the alpha component of the Lambda matrix
! contains the occupied MO energy term
IF (.NOT. (do_sf .AND. (ispin == 2))) THEN
CALL calculate_wx_matrix(gs_mos(ispin)%mos_occ, evect(spin), matrix_ks(ispin)%matrix, &
matrix_wz(ispin)%matrix)
END IF
CALL dbcsr_scale(matrix_wz(ispin)%matrix, evalue)
CALL calculate_wx_matrix(gs_mos(ispin)%mos_occ, evect(ispin), matrix_ks(ispin)%matrix, &
matrix_wz(ispin)%matrix)
END DO
IF (nspins == 2) THEN
CALL dbcsr_add(matrix_wz(1)%matrix, matrix_wz(2)%matrix, &
@ -454,6 +508,8 @@ CONTAINS
END IF
NULLIFY (scrm)
IF (debug_forces) fodeb(1:3) = force(1)%overlap(1:3, 1)
! Calculate the force contribution of matrix_xz into the force in ks_env.
! force%overlap = Tr(dS*matrix_wz), last term of Eq. 51.
CALL build_overlap_matrix(ks_env, matrix_s=scrm, &
matrix_name="OVERLAP MATRIX", &
basis_type_a="ORB", basis_type_b="ORB", &
@ -467,7 +523,8 @@ CONTAINS
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Wx*dS ", fodeb
END IF
! Overlap matrix
! Overlap matrix. Build a part of the first term of Lamda, Eq. 51, corresponding to
! the second term of Eq. 41. matrix_wz = C*X^T*(omega*S - K)*X*C^T
CALL get_qs_env(qs_env=qs_env, matrix_s=matrix_s, matrix_ks=matrix_ks)
NULLIFY (matrix_wz)
CALL dbcsr_allocate_matrix_set(matrix_wz, nspins)
@ -476,13 +533,22 @@ CONTAINS
CALL dbcsr_create(matrix=matrix_wz(ispin)%matrix, template=matrix_s(1)%matrix)
CALL cp_dbcsr_alloc_block_from_nbl(matrix_wz(ispin)%matrix, sab_orb)
CALL dbcsr_set(matrix_wz(ispin)%matrix, 0.0_dp)
CALL cp_fm_get_info(gs_mos(ispin)%mos_occ, ncol_global=norb)
evalue = ex_env%evalue
IF (tddfpt_control%oe_corr == oe_shift) THEN
evalue = ex_env%evalue - tddfpt_control%ev_shift
! For spin-flip excitations only the alpha component of Lambda has contributions
! of this term, so skip beta
IF (.NOT. (do_sf .AND. (ispin == 2))) THEN
CALL cp_fm_get_info(gs_mos(ispin)%mos_occ, ncol_global=norb)
evalue = ex_env%evalue
IF (tddfpt_control%oe_corr == oe_shift) THEN
evalue = ex_env%evalue - tddfpt_control%ev_shift
END IF
IF (do_sf) THEN
spin = 2
ELSE
spin = ispin
END IF
CALL calculate_xwx_matrix(gs_mos(ispin)%mos_occ, evect(ispin), matrix_s(1)%matrix, &
matrix_ks(spin)%matrix, matrix_wz(ispin)%matrix, evalue)
END IF
CALL calculate_xwx_matrix(gs_mos(ispin)%mos_occ, evect(ispin), matrix_s(1)%matrix, &
matrix_ks(ispin)%matrix, matrix_wz(ispin)%matrix, evalue)
END DO
IF (nspins == 2) THEN
CALL dbcsr_add(matrix_wz(1)%matrix, matrix_wz(2)%matrix, &
@ -503,11 +569,16 @@ CONTAINS
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: xWx*dS ", fodeb
END IF
! Overlap matrix
! Compute force contribution of the first term of Eq. 41 in the first term of Eq. 51
! that was calculated in tddfpt_kernel_force,
! force%overlap = 0.5C*H[T]*C^T
IF (ASSOCIATED(matrix_wx1)) THEN
IF (nspins == 2) THEN
IF (nspins == 2 .AND. .NOT. do_sf) THEN
CALL dbcsr_add(matrix_wx1(1)%matrix, matrix_wx1(2)%matrix, &
alpha_scalar=0.5_dp, beta_scalar=0.5_dp)
ELSE IF (nspins == 2 .AND. do_sf) THEN
CALL dbcsr_add(matrix_wx1(1)%matrix, matrix_wx1(2)%matrix, &
alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
END IF
NULLIFY (scrm)
IF (debug_forces) fodeb(1:3) = force(1)%overlap(1:3, 1)
@ -520,7 +591,7 @@ CONTAINS
IF (debug_forces) THEN
fodeb(1:3) = force(1)%overlap(1:3, 1) - fodeb(1:3)
CALL para_env%sum(fodeb)
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: WK*dS ", fodeb
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: D^XKP*dS ", fodeb
END IF
END IF
@ -538,16 +609,21 @@ CONTAINS
END SUBROUTINE tddfpt_force_direct
! **************************************************************************************************
!> \brief ...
!> \brief Build the spin difference density,
!> matrix_pe = matrix_pe + X*X^T - (C*X^T*S*X*C^T + (C*X^T*S*X*C^T)^T)/2
!> \param evect ...
!> \param mos_occ ...
!> \param matrix_s ...
!> \param matrix_pe ...
!> \param spin ...
!> \param do_sf ...
! **************************************************************************************************
SUBROUTINE tddfpt_resvec1(evect, mos_occ, matrix_s, matrix_pe)
SUBROUTINE tddfpt_resvec1(evect, mos_occ, matrix_s, matrix_pe, spin, do_sf)
TYPE(cp_fm_type), INTENT(IN) :: evect, mos_occ
TYPE(dbcsr_type), POINTER :: matrix_s, matrix_pe
INTEGER, INTENT(IN) :: spin
LOGICAL, INTENT(IN) :: do_sf
CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_resvec1'
@ -558,39 +634,78 @@ CONTAINS
TYPE(cp_logger_type), POINTER :: logger
CALL timeset(routineN, handle)
! X*X^T
CALL cp_fm_get_info(mos_occ, nrow_global=nao, ncol_global=norb)
CALL cp_dbcsr_plus_fm_fm_t(matrix_pe, matrix_v=evect, ncol=norb)
! X^T*S*X
CALL cp_fm_get_info(evect, matrix_struct=fmstruct)
NULLIFY (fmstruct2)
CALL cp_fm_struct_create(fmstruct=fmstruct2, template_fmstruct=fmstruct, &
nrow_global=norb, ncol_global=norb)
CALL cp_fm_create(xxmat, matrix_struct=fmstruct2)
CALL cp_fm_struct_release(fmstruct2)
CALL cp_fm_create(cxmat, matrix_struct=fmstruct)
CALL cp_dbcsr_sm_fm_multiply(matrix_s, evect, cxmat, norb, alpha=1.0_dp, beta=0.0_dp)
CALL parallel_gemm('T', 'N', norb, norb, nao, 1.0_dp, cxmat, evect, 0.0_dp, xxmat)
CALL parallel_gemm('N', 'N', nao, norb, norb, 1.0_dp, mos_occ, xxmat, 0.0_dp, cxmat)
CALL cp_fm_release(xxmat)
! C*C^T*XX
CALL cp_dbcsr_plus_fm_fm_t(matrix_pe, matrix_v=mos_occ, matrix_g=cxmat, &
ncol=norb, alpha=-1.0_dp, symmetry_mode=1)
CALL cp_fm_release(cxmat)
! matrix_pe = X*X^T
IF (.NOT. do_sf .OR. (do_sf .AND. (spin .EQ. 2))) THEN
CALL cp_dbcsr_plus_fm_fm_t(matrix_pe, matrix_v=evect, ncol=norb)
END IF
! matrix_pe = matrix_pe - (C*X^T*S*X*C^T + (C*X^T*S*X*C^T)^T)/2
IF (.NOT. do_sf .OR. (do_sf .AND. (spin .EQ. 1))) THEN
CALL cp_fm_get_info(evect, matrix_struct=fmstruct)
NULLIFY (fmstruct2)
CALL cp_fm_struct_create(fmstruct=fmstruct2, template_fmstruct=fmstruct, &
nrow_global=norb, ncol_global=norb)
CALL cp_fm_create(xxmat, matrix_struct=fmstruct2)
CALL cp_fm_struct_release(fmstruct2)
CALL cp_fm_create(cxmat, matrix_struct=fmstruct)
! S*X
CALL cp_dbcsr_sm_fm_multiply(matrix_s, evect, cxmat, norb, alpha=1.0_dp, beta=0.0_dp)
! (S*X)^T*X
CALL parallel_gemm('T', 'N', norb, norb, nao, 1.0_dp, cxmat, evect, 0.0_dp, xxmat)
! C*X^T*S*X
CALL parallel_gemm('N', 'N', nao, norb, norb, 1.0_dp, mos_occ, xxmat, 0.0_dp, cxmat)
CALL cp_fm_release(xxmat)
! matrix_pe = matrix_pe - (C*(C^T*X^T*S*X)^T + C^T*(C^T*X^T*S*X))/2
CALL cp_dbcsr_plus_fm_fm_t(matrix_pe, matrix_v=mos_occ, matrix_g=cxmat, &
ncol=norb, alpha=-1.0_dp, symmetry_mode=1)
CALL cp_fm_release(cxmat)
END IF
!
! Test for Tr(Pe*S)=0
CALL dbcsr_dot(matrix_pe, matrix_s, tmp)
IF (ABS(tmp) > 1.e-08_dp) THEN
logger => cp_get_default_logger()
IF (logger%para_env%is_source()) THEN
iounit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
ELSE
iounit = -1
IF (.NOT. do_sf) THEN
IF (ABS(tmp) > 1.e-08_dp) THEN
logger => cp_get_default_logger()
IF (logger%para_env%is_source()) THEN
iounit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
ELSE
iounit = -1
END IF
CPWARN("Electron count of excitation density matrix is non-zero.")
IF (iounit > 0) THEN
WRITE (iounit, "(T2,A,T61,G20.10)") "Measured electron count is ", tmp
WRITE (iounit, "(T2,A,/)") REPEAT("*", 79)
END IF
END IF
CPWARN("Electron count of excitation density matrix is non-zero.")
IF (iounit > 0) THEN
WRITE (iounit, "(T2,A,T61,G20.10)") "Measured electron count is ", tmp
WRITE (iounit, "(T2,A,/)") REPEAT("*", 79)
ELSE IF (spin .EQ. 1) THEN
IF (ABS(tmp + 1) > 1.e-08_dp) THEN
logger => cp_get_default_logger()
IF (logger%para_env%is_source()) THEN
iounit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
ELSE
iounit = -1
END IF
CPWARN("Count of occupied occupation number change is not -1.")
IF (iounit > 0) THEN
WRITE (iounit, "(T2,A,T61,G20.10)") "Measured electron count is ", tmp
WRITE (iounit, "(T2,A,/)") REPEAT("*", 79)
END IF
END IF
ELSE IF (spin .EQ. 2) THEN
IF (ABS(tmp - 1) > 1.e-08_dp) THEN
logger => cp_get_default_logger()
IF (logger%para_env%is_source()) THEN
iounit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
ELSE
iounit = -1
END IF
CPWARN("Count of unoccupied occupation number change is not 1.")
IF (iounit > 0) THEN
WRITE (iounit, "(T2,A,T61,G20.10)") "Measured electron count is ", tmp
WRITE (iounit, "(T2,A,/)") REPEAT("*", 79)
END IF
END IF
END IF
!
@ -634,12 +749,14 @@ CONTAINS
END SUBROUTINE tddfpt_resvec1_admm
! **************************************************************************************************
!> \brief ...
!> \brief Calculates the action of the H operator as in the first term of equation 49 in
!> https://doi.org/10.1021/acs.jctc.2c00144 (J. Chem. Theory Comput. 2022, 18, 41864202)
!> cpmos = H_{\mu i\sigma}[matrix_pe]
!> \param qs_env ...
!> \param matrix_pe ...
!> \param matrix_pe Input square matrix with the size of the number of atomic orbitals squared nao^2
!> \param matrix_pe_admm ...
!> \param gs_mos ...
!> \param matrix_hz ...
!> \param matrix_hz Holds H_{\mu\nu\sigma}[matrix_pe] on exit
!> \param cpmos ...
! **************************************************************************************************
SUBROUTINE tddfpt_resvec2(qs_env, matrix_pe, matrix_pe_admm, gs_mos, matrix_hz, cpmos)
@ -907,9 +1024,7 @@ CONTAINS
DEALLOCATE (v_xc_tau)
END IF
IF (dft_control%do_admm) THEN
IF (qs_env%admm_env%aux_exch_func == do_admm_aux_exch_func_none) THEN
! nothing to do
ELSE
IF (qs_env%admm_env%aux_exch_func /= do_admm_aux_exch_func_none) THEN
! add ADMM xc_section_aux terms: f_x[rhoz_ADMM]
CALL get_qs_env(qs_env, admm_env=admm_env)
CALL get_admm_env(admm_env, rho_aux_fit=rho_aux_fit, matrix_s_aux_fit=msaux, &

View file

@ -205,7 +205,7 @@ CONTAINS
ex_env%evalue = evals(istate)
CALL cp_fm_release(ex_env%evect)
ALLOCATE (ex_env%evect(nspins))
DO ispin = 1, nspins
DO ispin = 1, SIZE(evects, 1)
CALL cp_fm_get_info(matrix=evects(ispin, 1), matrix_struct=matrix_struct)
CALL cp_fm_create(ex_env%evect(ispin), matrix_struct)
CALL cp_fm_to_fm(evects(ispin, istate), ex_env%evect(ispin))
@ -233,12 +233,14 @@ CONTAINS
CALL response_force(qs_env=qs_env, vh_rspace=ex_env%vh_rspace, &
vxc_rspace=ex_env%vxc_rspace, vtau_rspace=ex_env%vtau_rspace, &
vadmm_rspace=ex_env%vadmm_rspace, matrix_hz=ex_env%matrix_hz, &
matrix_pz=ex_env%matrix_px1, matrix_pz_admm=p_env%p1_admm, &
matrix_pz=p_env%p1, matrix_pz_admm=p_env%p1_admm, &
matrix_wz=p_env%w1, p_env=p_env, ex_env=ex_env, debug=debug_forces)
END IF
CALL p_env_release(p_env)
!
CALL replicate_qs_force(td_force, para_env)
CALL pforce(iwunit, gs_force, atomic_kind_set, natom)
CALL pforce(iwunit, td_force, atomic_kind_set, natom)
CALL sum_qs_force(td_force, gs_force)
CALL pforce(iwunit, td_force, atomic_kind_set, natom)
!

View file

@ -44,8 +44,8 @@ MODULE qs_tddfpt2_methods
hfx_create
USE input_constants, ONLY: &
do_admm_aux_exch_func_none, do_admm_basis_projection, do_admm_exch_scaling_none, &
do_admm_purify_none, do_potential_truncated, tddfpt_dipole_velocity, tddfpt_kernel_full, &
tddfpt_kernel_none, tddfpt_kernel_stda
do_admm_purify_none, do_potential_truncated, no_sf_tddfpt, tddfpt_dipole_velocity, &
tddfpt_kernel_full, tddfpt_kernel_none, tddfpt_kernel_stda, tddfpt_sf_col, tddfpt_sf_noncol
USE input_section_types, ONLY: section_vals_get,&
section_vals_get_subs_vals,&
section_vals_type,&
@ -133,7 +133,8 @@ MODULE qs_tddfpt2_methods
CONTAINS
! **************************************************************************************************
!> \brief Perform TDDFPT calculation.
!> \brief Perform TDDFPT calculation. If calc_forces then it also builds the response vector for the
!> Z-vector method and calculates some contributions to the force
!> \param qs_env Quickstep environment
!> \param calc_forces ...
!> \param rixs_env ...
@ -155,8 +156,8 @@ CONTAINS
nstate_max, nstates, nvirt, old_state
INTEGER, DIMENSION(maxspins) :: nactive
LOGICAL :: do_admm, do_exck, do_hfx, do_hfxlr, &
do_hfxsr, do_rixs, do_soc, lmult_tmp, &
state_change
do_hfxsr, do_rixs, do_sf, do_soc, &
lmult_tmp, state_change
REAL(kind=dp) :: gsmin, gsval, xsval
REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: evals, ostrength
TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
@ -234,6 +235,7 @@ CONTAINS
tddfpt_control%hfxsr_re_int = .TRUE.
tddfpt_control%do_hfxlr = do_hfxlr
tddfpt_control%do_exck = do_exck
do_sf = tddfpt_control%spinflip /= no_sf_tddfpt
IF (tddfpt_control%do_hfxlr) THEN
kernel_section => section_vals_get_subs_vals(tddfpt_section, "XC%HFX_KERNEL%HFXLR")
CALL section_vals_val_get(kernel_section, "RCUT", r_val=tddfpt_control%hfxlr_rcut)
@ -348,9 +350,13 @@ CONTAINS
nstates = tddfpt_control%nstates
!! Too many states can lead to Problems
!! You should be warned if there are more states
!! then occ-virt Combinations!!
!! than occ-virt Combinations!!
CALL cp_fm_get_info(gs_mos(1)%mos_occ, ncol_global=nocc)
CALL cp_fm_get_info(gs_mos(1)%mos_virt, ncol_global=nvirt)
IF (tddfpt_control%spinflip == no_sf_tddfpt) THEN
CALL cp_fm_get_info(gs_mos(1)%mos_virt, ncol_global=nvirt)
ELSE
CALL cp_fm_get_info(gs_mos(2)%mos_virt, ncol_global=nvirt)
END IF
nstate_max = nocc*nvirt
IF (nstates > nstate_max) THEN
CPWARN("NUMBER OF EXCITED STATES COULD LEAD TO PROBLEMS!")
@ -359,7 +365,7 @@ CONTAINS
tddfpt_control%nstates = nstate_max
END IF
CALL tddfpt_create_work_matrices(work_matrices, gs_mos, nstates, do_hfx, do_admm, &
do_hfxlr, do_exck, qs_env, sub_env)
do_hfxlr, do_exck, do_sf, qs_env, sub_env)
! create full_kernel and admm_kernel within tddfpt_energies
kernel_env%full_kernel => full_kernel_env
@ -405,12 +411,17 @@ CONTAINS
NULLIFY (kernel_env%stda_kernel)
END IF
ALLOCATE (evects(nspins, nstates))
IF (do_sf) THEN
! only alpha -> beta excitations are considered in spin-flip TDDFT
ALLOCATE (evects(1, nstates))
ELSE
ALLOCATE (evects(nspins, nstates))
END IF
ALLOCATE (evals(nstates))
ALLOCATE (S_evects(SIZE(evects, 1), nstates))
ALLOCATE (S_evects(nspins, nstates))
DO istate = 1, nstates
DO ispin = 1, nspins
DO ispin = 1, SIZE(evects, 1)
CALL fm_pool_create_fm( &
work_matrices%fm_pool_ao_mo_occ(ispin)%pool, &
S_evects(ispin, istate))
@ -419,7 +430,7 @@ CONTAINS
IF (.NOT. do_soc) THEN
! compute tddfpt excitation energies of multiplicity mult
CALL tddfpt_energies(qs_env, nstates, work_matrices, &
CALL tddfpt_energies(qs_env, nstates, nspins, work_matrices, &
tddfpt_control, logger, tddfpt_print_section, evects, evals, &
gs_mos, tddfpt_section, S_evects, matrix_s, kernel_env, matrix_ks, &
sub_env, ostrength, dipole_op_mos_occ, mult, xc_section, full_kernel_env, &
@ -483,8 +494,8 @@ CONTAINS
ex_env%evalue = evals(my_state)
! excitation vector
CALL cp_fm_release(ex_env%evect)
ALLOCATE (ex_env%evect(nspins))
DO ispin = 1, nspins
ALLOCATE (ex_env%evect(SIZE(evects, 1)))
DO ispin = 1, SIZE(evects, 1)
CALL cp_fm_get_info(matrix=evects(ispin, 1), &
matrix_struct=matrix_struct)
CALL cp_fm_create(ex_env%evect(ispin), matrix_struct)
@ -507,6 +518,7 @@ CONTAINS
my_state, " with excitation energy ", ex_env%evalue*evolt, " eV"
END IF
! Calculate response vector
IF (calc_forces) THEN
CALL tddfpt_forces_main(qs_env, gs_mos, ex_env, kernel_env, &
sub_env, work_matrices)
@ -867,7 +879,16 @@ CONTAINS
IF (tddfpt_control%rks_triplets) THEN
WRITE (log_unit, "(T2,A,T74,A7)") "KERNEL| Spin symmetry of excitations", "Triplet"
ELSE IF (lsd) THEN
WRITE (log_unit, "(T2,A,T69,A12)") "KERNEL| Spin symmetry of excitations", "Unrestricted"
! Spin-conserving excitations where requested
IF (tddfpt_control%spinflip == no_sf_tddfpt) THEN
WRITE (log_unit, "(T2,A,T69,A12)") "KERNEL| Spin symmetry of excitations", "Unrestricted"
! Spin-flip excitations with collinear exchange-correlation kernel requested
ELSE IF (tddfpt_control%spinflip == tddfpt_sf_col) THEN
WRITE (log_unit, "(T2,A,T72,A9)") "KERNEL| Spin flip", "Collinear"
! Spin-flip excitations with noncollinear exchange-correlation kernel requested
ELSE IF (tddfpt_control%spinflip == tddfpt_sf_noncol) THEN
WRITE (log_unit, "(T2,A,T69,A12)") "KERNEL| Spin flip", "Noncollinear"
END IF
ELSE
WRITE (log_unit, "(T2,A,T74,A7)") "KERNEL| Spin symmetry of excitations", "Singlet"
END IF
@ -883,6 +904,7 @@ CONTAINS
!> \brief The energy calculation has been moved to its own subroutine
!> \param qs_env ...
!> \param nstates ...
!> \param nspins ...
!> \param work_matrices ...
!> \param tddfpt_control ...
!> \param logger ...
@ -903,14 +925,14 @@ CONTAINS
!> \param full_kernel_env ...
!> \param kernel_env_admm_aux ...
! **************************************************************************************************
SUBROUTINE tddfpt_energies(qs_env, nstates, work_matrices, &
SUBROUTINE tddfpt_energies(qs_env, nstates, nspins, work_matrices, &
tddfpt_control, logger, tddfpt_print_section, evects, evals, &
gs_mos, tddfpt_section, S_evects, matrix_s, kernel_env, matrix_ks, &
sub_env, ostrength, dipole_op_mos_occ, mult, xc_section, full_kernel_env, &
kernel_env_admm_aux)
TYPE(qs_environment_type), POINTER :: qs_env
INTEGER :: nstates
INTEGER :: nstates, nspins
TYPE(tddfpt_work_matrices) :: work_matrices
TYPE(tddfpt2_control_type), POINTER :: tddfpt_control
TYPE(cp_logger_type), POINTER :: logger
@ -1020,12 +1042,21 @@ CONTAINS
tddfpt_print_section)
END IF
!! Too many states can lead to problems
!! Too many states can lead to Problems
!! You should be warned if there are more states
!! then occ-virt combinations!!
!! than occ-virt Combinations!!
CALL cp_fm_get_info(gs_mos(1)%mos_occ, ncol_global=nocc)
CALL cp_fm_get_info(gs_mos(1)%mos_virt, ncol_global=nvirt)
IF (tddfpt_control%spinflip == no_sf_tddfpt) THEN
CALL cp_fm_get_info(gs_mos(1)%mos_virt, ncol_global=nvirt)
ELSE
CALL cp_fm_get_info(gs_mos(2)%mos_virt, ncol_global=nvirt)
END IF
nstate_max = nocc*nvirt
IF ((SIZE(gs_mos, 1) == 2) .AND. (tddfpt_control%spinflip == no_sf_tddfpt)) THEN
CALL cp_fm_get_info(gs_mos(2)%mos_occ, ncol_global=nocc)
CALL cp_fm_get_info(gs_mos(2)%mos_virt, ncol_global=nvirt)
nstate_max = nocc*nvirt + nstate_max
END IF
IF (nstates > nstate_max) THEN
CPWARN("NUMBER OF EXCITED STATES COULD LEAD TO PROBLEMS!")
CPWARN("Experimental: CHANGED NSTATES TO ITS MAXIMUM VALUE!")
@ -1056,7 +1087,7 @@ CONTAINS
! according to their excitation energies
log_unit = cp_print_key_unit_nr(logger, tddfpt_print_section, &
"GUESS_VECTORS", extension=".tddfptLog")
CALL tddfpt_guess_vectors(evects=evects, evals=evals, &
CALL tddfpt_guess_vectors(tddfpt_control, nspins, evects=evects, evals=evals, &
gs_mos=gs_mos, log_unit=log_unit)
CALL cp_print_key_finished_output(log_unit, logger, &
tddfpt_print_section, "GUESS_VECTORS")
@ -1200,6 +1231,7 @@ CONTAINS
evals, &
gs_mos, &
matrix_s(1)%matrix, &
tddfpt_control%spinflip, &
min_amplitude=tddfpt_control%min_excitation_amplitude)
CALL tddfpt_print_nto_analysis(qs_env, &
evects, evals, &
@ -1287,6 +1319,7 @@ CONTAINS
INTEGER :: handle, ispin, istate, log_unit, mult, &
nspins
LOGICAL :: do_sf
REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: evals_mult, ostrength_mult
TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: evects_mult
@ -1300,6 +1333,7 @@ CONTAINS
nspins = SIZE(gs_mos)
ALLOCATE (evects_mult(nspins, nstates))
ALLOCATE (evals_mult(nstates))
do_sf = tddfpt_control%spinflip /= no_sf_tddfpt
! First multiplicity
IF (lmult_tmp) THEN
@ -1320,7 +1354,7 @@ CONTAINS
mult = 3
END IF
CALL tddfpt_energies(qs_env, nstates, work_matrices, tddfpt_control, logger, &
CALL tddfpt_energies(qs_env, nstates, nspins, work_matrices, tddfpt_control, logger, &
tddfpt_print_section, evects_mult, evals_mult, &
gs_mos, tddfpt_section, S_evects, matrix_s, &
kernel_env, matrix_ks, sub_env, ostrength_mult, &
@ -1334,7 +1368,7 @@ CONTAINS
CALL tddfpt_release_work_matrices(work_matrices, sub_env)
CALL tddfpt_create_work_matrices(work_matrices, gs_mos, nstates, tddfpt_control%do_hfx, &
tddfpt_control%do_admm, tddfpt_control%do_hfxlr, &
tddfpt_control%do_exck, qs_env, sub_env)
tddfpt_control%do_exck, do_sf, qs_env, sub_env)
END IF
DO istate = 1, nstates
@ -1376,7 +1410,7 @@ CONTAINS
mult = 1
END IF
CALL tddfpt_energies(qs_env, nstates, work_matrices, tddfpt_control, logger, &
CALL tddfpt_energies(qs_env, nstates, nspins, work_matrices, tddfpt_control, logger, &
tddfpt_print_section, evects, evals, &
gs_mos, tddfpt_section, S_evects, matrix_s, &
kernel_env, matrix_ks, sub_env, ostrength, &

View file

@ -9,6 +9,7 @@ MODULE qs_tddfpt2_operators
USE admm_types, ONLY: admm_type
USE cell_types, ONLY: cell_type,&
pbc
USE cp_control_types, ONLY: tddfpt2_control_type
USE cp_dbcsr_api, ONLY: &
dbcsr_create, dbcsr_filter, dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, &
dbcsr_iterator_start, dbcsr_iterator_stop, dbcsr_iterator_type, dbcsr_p_type, &
@ -28,6 +29,8 @@ MODULE qs_tddfpt2_operators
USE hartree_local_types, ONLY: hartree_local_type
USE hfx_admm_utils, ONLY: tddft_hfx_matrix
USE hfx_types, ONLY: hfx_type
USE input_constants, ONLY: no_sf_tddfpt,&
tddfpt_sf_noncol
USE input_section_types, ONLY: section_vals_get,&
section_vals_get_subs_vals,&
section_vals_type
@ -95,23 +98,25 @@ CONTAINS
!> \param gs_mos molecular orbitals optimised for the ground state (only occupied orbital
!> energies [component %evals_occ] are needed)
!> \param matrix_ks Kohn-Sham matrix
!> \param tddfpt_control ...
!> \par History
!> * 05.2016 initialise all matrix elements in one go [Sergey Chulkov]
!> * 03.2017 renamed from tddfpt_init_energy_diff(), altered prototype [Sergey Chulkov]
!> \note Based on the subroutine p_op_l1() which was originally created by
!> Thomas Chassaing on 08.2002.
! **************************************************************************************************
SUBROUTINE tddfpt_apply_energy_diff(Aop_evects, evects, S_evects, gs_mos, matrix_ks)
SUBROUTINE tddfpt_apply_energy_diff(Aop_evects, evects, S_evects, gs_mos, matrix_ks, tddfpt_control)
TYPE(cp_fm_type), DIMENSION(:, :), INTENT(INOUT) :: Aop_evects
TYPE(cp_fm_type), DIMENSION(:, :), INTENT(IN) :: evects, S_evects
TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
INTENT(in) :: gs_mos
TYPE(dbcsr_p_type), DIMENSION(:), INTENT(in) :: matrix_ks
TYPE(tddfpt2_control_type), INTENT(in), POINTER :: tddfpt_control
CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_apply_energy_diff'
INTEGER :: handle, ispin, ivect, nactive, nao, &
nspins, nvects
nspins, nvects, spin2
TYPE(cp_fm_struct_type), POINTER :: matrix_struct
TYPE(cp_fm_type) :: hevec
@ -120,13 +125,19 @@ CONTAINS
nspins = SIZE(evects, 1)
nvects = SIZE(evects, 2)
DO ispin = 1, nspins
DO ispin = 1, SIZE(evects, 1)
CALL cp_fm_get_info(matrix=evects(ispin, 1), matrix_struct=matrix_struct, &
nrow_global=nao, ncol_global=nactive)
CALL cp_fm_create(hevec, matrix_struct)
IF (tddfpt_control%spinflip == no_sf_tddfpt) THEN
spin2 = ispin
ELSE
spin2 = 2
END IF
DO ivect = 1, nvects
CALL cp_dbcsr_sm_fm_multiply(matrix_ks(ispin)%matrix, evects(ispin, ivect), &
CALL cp_dbcsr_sm_fm_multiply(matrix_ks(spin2)%matrix, evects(ispin, ivect), &
Aop_evects(ispin, ivect), ncol=nactive, &
alpha=1.0_dp, beta=1.0_dp)
@ -267,9 +278,10 @@ CONTAINS
!> \param work_v_xc work real-space grid to store the gradient of the exchange-correlation
!> potential with respect to the response density (modified on exit)
!> \param work_v_xc_tau ...
!> \param spinflip ...
! **************************************************************************************************
SUBROUTINE tddfpt_apply_xc(A_ia_rspace, kernel_env, rho_ia_struct, is_rks_triplets, &
pw_env, work_v_xc, work_v_xc_tau)
pw_env, work_v_xc, work_v_xc_tau, spinflip)
TYPE(pw_r3d_rs_type), DIMENSION(:), INTENT(INOUT) :: A_ia_rspace
TYPE(full_kernel_env_type), INTENT(IN) :: kernel_env
@ -277,14 +289,17 @@ CONTAINS
LOGICAL, INTENT(in) :: is_rks_triplets
TYPE(pw_env_type), POINTER :: pw_env
TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: work_v_xc, work_v_xc_tau
INTEGER, INTENT(in), OPTIONAL :: spinflip
INTEGER :: ispin, nspins
INTEGER :: ispin, my_spinflip, nspins
nspins = SIZE(A_ia_rspace)
my_spinflip = 0
IF (PRESENT(spinflip)) my_spinflip = spinflip
IF (kernel_env%deriv2_analytic) THEN
CALL tddfpt_apply_xc_analytic(kernel_env, rho_ia_struct, is_rks_triplets, nspins, &
pw_env, work_v_xc, work_v_xc_tau)
CALL tddfpt_apply_xc_analytic(kernel_env, rho_ia_struct, is_rks_triplets, my_spinflip, &
nspins, pw_env, work_v_xc, work_v_xc_tau)
ELSE
CALL tddfpt_apply_xc_fd(kernel_env, rho_ia_struct, is_rks_triplets, nspins, &
pw_env, work_v_xc, work_v_xc_tau)
@ -343,6 +358,7 @@ CONTAINS
!> \param rho_ia_struct response density for the given trial vector
!> \param is_rks_triplets indicates that the triplet excited states calculation using
!> spin-unpolarised molecular orbitals has been requested
!> \param spinflip ...
!> \param nspins ...
!> \param pw_env plain wave environment
!> \param work_v_xc work real-space grid to store the gradient of the exchange-correlation
@ -357,18 +373,19 @@ CONTAINS
!> \note Based on the subroutine kpp1_calc_k_p_p1() which was originally created by
!> Mohamed Fawzi on 10.2002.
! **************************************************************************************************
SUBROUTINE tddfpt_apply_xc_analytic(kernel_env, rho_ia_struct, is_rks_triplets, nspins, &
pw_env, work_v_xc, work_v_xc_tau)
SUBROUTINE tddfpt_apply_xc_analytic(kernel_env, rho_ia_struct, is_rks_triplets, spinflip, &
nspins, pw_env, work_v_xc, work_v_xc_tau)
TYPE(full_kernel_env_type), INTENT(in) :: kernel_env
TYPE(qs_rho_type), POINTER :: rho_ia_struct
LOGICAL, INTENT(in) :: is_rks_triplets
INTEGER, INTENT(in) :: nspins
INTEGER, INTENT(in) :: spinflip, nspins
TYPE(pw_env_type), POINTER :: pw_env
TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: work_v_xc, work_v_xc_tau
CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_apply_xc_analytic'
INTEGER :: handle, ispin
LOGICAL :: do_spinflip
TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho_ia_g, rho_ia_g2
TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho_ia_r, rho_ia_r2, tau_ia_r, tau_ia_r2
@ -383,6 +400,13 @@ CONTAINS
CPASSERT(SIZE(rho_ia_r) == nspins)
CPASSERT((.NOT. ASSOCIATED(tau_ia_r)) .OR. SIZE(tau_ia_r) == nspins)
CPASSERT((.NOT. is_rks_triplets) .OR. nspins == 1)
CPASSERT((spinflip .NE. no_sf_tddfpt) .EQV. (nspins == 2))
END IF
IF (spinflip == tddfpt_sf_noncol) THEN
do_spinflip = .TRUE.
ELSE
do_spinflip = .FALSE.
END IF
NULLIFY (tau_ia_r2)
@ -418,7 +442,8 @@ CONTAINS
CALL xc_calc_2nd_deriv_analytical(v_xc=work_v_xc, v_xc_tau=work_v_xc_tau, deriv_set=kernel_env%xc_deriv_set, &
rho_set=kernel_env%xc_rho_set, &
rho1_set=kernel_env%xc_rho1_set, pw_pool=auxbas_pw_pool, &
xc_section=kernel_env%xc_section, gapw=.FALSE., tddfpt_fac=kernel_env%beta)
xc_section=kernel_env%xc_section, gapw=.FALSE., tddfpt_fac=kernel_env%beta, &
spinflip=do_spinflip)
IF (is_rks_triplets) THEN
DEALLOCATE (rho_ia_r2)
@ -554,7 +579,7 @@ CONTAINS
nspins = SIZE(evects, 1)
nvects = SIZE(evects, 2)
IF (nspins > 1) THEN
IF (SIZE(gs_mos) > 1) THEN
alpha = 1.0_dp
ELSE
alpha = 2.0_dp

View file

@ -57,7 +57,8 @@ MODULE qs_tddfpt2_properties
cp_print_key_should_output,&
cp_print_key_unit_nr
USE cp_realspace_grid_cube, ONLY: cp_pw_to_cube
USE input_constants, ONLY: tddfpt_dipole_berry,&
USE input_constants, ONLY: no_sf_tddfpt,&
tddfpt_dipole_berry,&
tddfpt_dipole_length,&
tddfpt_dipole_velocity
USE input_section_types, ONLY: section_vals_get_subs_vals,&
@ -632,26 +633,29 @@ CONTAINS
!> \param evals TDDFPT eigenvalues
!> \param gs_mos molecular orbitals optimised for the ground state
!> \param matrix_s overlap matrix
!> \param spinflip ...
!> \param min_amplitude the smallest excitation amplitude to print
!> \par History
!> * 05.2016 created as 'tddfpt_print_summary' [Sergey Chulkov]
!> * 08.2018 splited of from 'tddfpt_print_summary' [Sergey Chulkov]
! **************************************************************************************************
SUBROUTINE tddfpt_print_excitation_analysis(log_unit, evects, evals, gs_mos, matrix_s, min_amplitude)
SUBROUTINE tddfpt_print_excitation_analysis(log_unit, evects, evals, gs_mos, matrix_s, spinflip, min_amplitude)
INTEGER, INTENT(in) :: log_unit
TYPE(cp_fm_type), DIMENSION(:, :), INTENT(in) :: evects
REAL(kind=dp), DIMENSION(:), INTENT(in) :: evals
TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
INTENT(in) :: gs_mos
TYPE(dbcsr_type), POINTER :: matrix_s
INTEGER :: spinflip
REAL(kind=dp), INTENT(in) :: min_amplitude
CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_print_excitation_analysis'
CHARACTER(len=5) :: spin_label
CHARACTER(len=5) :: spin_label, spin_label2
INTEGER :: handle, icol, iproc, irow, ispin, &
istate, nao, ncols_local, nrows_local, &
nspins, nstates, state_spin
nspins, nstates, spin2, state_spin, &
state_spin2
INTEGER(kind=int_8) :: iexc, imo_occ, imo_virt, ind, nexcs, &
nexcs_local, nexcs_max_local, &
nmo_virt_occ, nmo_virt_occ_alpha
@ -675,7 +679,7 @@ CONTAINS
CALL timeset(routineN, handle)
nspins = SIZE(evects, 1)
nspins = SIZE(gs_mos, 1)
nstates = SIZE(evects, 2)
do_exc_analysis = min_amplitude < 1.0_dp
@ -705,28 +709,40 @@ CONTAINS
IF (nspins == 1) THEN
state_spin = 1
state_spin2 = 2
spin_label = ' '
spin_label2 = ' '
ELSE IF (spinflip .NE. no_sf_tddfpt) THEN
state_spin = 1
state_spin2 = 2
spin_label = '(alp)'
spin_label2 = '(bet)'
END IF
END IF
ALLOCATE (S_mos_virt(nspins), weights_fm(nspins))
DO ispin = 1, nspins
CALL cp_fm_get_info(gs_mos(ispin)%mos_virt, matrix_struct=fm_struct)
ALLOCATE (S_mos_virt(SIZE(evects, 1)), weights_fm(SIZE(evects, 1)))
DO ispin = 1, SIZE(evects, 1)
IF (spinflip == no_sf_tddfpt) THEN
spin2 = ispin
ELSE
spin2 = 2
END IF
CALL cp_fm_get_info(gs_mos(spin2)%mos_virt, matrix_struct=fm_struct)
CALL cp_fm_create(S_mos_virt(ispin), fm_struct)
CALL cp_dbcsr_sm_fm_multiply(matrix_s, &
gs_mos(ispin)%mos_virt, &
gs_mos(spin2)%mos_virt, &
S_mos_virt(ispin), &
ncol=nmo_virt(ispin), alpha=1.0_dp, beta=0.0_dp)
ncol=nmo_virt(spin2), alpha=1.0_dp, beta=0.0_dp)
NULLIFY (fm_struct)
CALL cp_fm_struct_create(fm_struct, nrow_global=nmo_virt(ispin), ncol_global=nmo_occ(ispin), &
CALL cp_fm_struct_create(fm_struct, nrow_global=nmo_virt(spin2), ncol_global=nmo_occ(ispin), &
context=blacs_env)
CALL cp_fm_create(weights_fm(ispin), fm_struct)
CALL cp_fm_struct_release(fm_struct)
END DO
nexcs_max_local = 0
DO ispin = 1, nspins
DO ispin = 1, SIZE(evects, 1)
CALL cp_fm_get_info(weights_fm(ispin), nrow_local=nrows_local, ncol_local=ncols_local)
nexcs_max_local = nexcs_max_local + INT(nrows_local, int_8)*INT(ncols_local, int_8)
END DO
@ -739,9 +755,14 @@ CONTAINS
! analyse matrix elements locally and transfer only significant
! excitations to the master node for subsequent ordering
DO ispin = 1, nspins
DO ispin = 1, SIZE(evects, 1)
IF (spinflip == no_sf_tddfpt) THEN
spin2 = ispin
ELSE
spin2 = 2
END IF
! compute excitation amplitudes
CALL parallel_gemm('T', 'N', nmo_virt(ispin), nmo_occ(ispin), nao, 1.0_dp, S_mos_virt(ispin), &
CALL parallel_gemm('T', 'N', nmo_virt(spin2), nmo_occ(ispin), nao, 1.0_dp, S_mos_virt(ispin), &
evects(ispin, istate), 0.0_dp, weights_fm(ispin))
CALL cp_fm_get_info(weights_fm(ispin), nrow_local=nrows_local, ncol_local=ncols_local, &
@ -757,12 +778,12 @@ CONTAINS
weights_local(nexcs_local) = local_data(irow, icol)
! index of single excitation (ivirt, iocc, ispin) in compressed form
inds_local(nexcs_local) = nmo_virt_occ + INT(row_indices(irow), int_8) + &
INT(col_indices(icol) - 1, int_8)*nmo_virt8(ispin)
INT(col_indices(icol) - 1, int_8)*nmo_virt8(spin2)
END IF
END DO
END DO
nmo_virt_occ = nmo_virt_occ + nmo_virt8(ispin)*nmo_occ8(ispin)
nmo_virt_occ = nmo_virt_occ + nmo_virt8(spin2)*nmo_occ8(ispin)
END DO
IF (para_env%is_source()) THEN
@ -846,24 +867,33 @@ CONTAINS
WRITE (log_unit, '(T7,I8,F10.5,A)') istate, evals(istate)*evolt, " eV"
! This reinitialization is needed to prevent the intel fortran compiler from introduce
! a bug when using optimization level 3 flag
state_spin = 1
state_spin2 = 1
IF (spinflip .NE. no_sf_tddfpt) THEN
state_spin = 1
state_spin2 = 2
END IF
DO iexc = 1, nexcs
ind = inds_recv(inds(iexc)) - 1
IF (nspins > 1) THEN
IF ((nspins > 1) .AND. (spinflip == no_sf_tddfpt)) THEN
IF (ind < nmo_virt_occ_alpha) THEN
state_spin = 1
spin_label = '(alp)'
spin_label2 = '(alp)'
ELSE
state_spin = 2
state_spin2 = 2
ind = ind - nmo_virt_occ_alpha
spin_label = '(bet)'
spin_label2 = '(bet)'
END IF
END IF
imo_occ = ind/nmo_virt8(state_spin) + 1
imo_virt = MOD(ind, nmo_virt8(state_spin)) + 1
imo_occ = ind/nmo_virt8(state_spin2) + 1
imo_virt = MOD(ind, nmo_virt8(state_spin2)) + 1
WRITE (log_unit, '(T27,I8,1X,A5,T48,I8,1X,A5,T70,F9.6)') imo_occ, spin_label, &
nmo_occ8(state_spin) + imo_virt, spin_label, weights_recv(inds(iexc))
nmo_occ8(state_spin2) + imo_virt, spin_label2, weights_recv(inds(iexc))
END DO
END IF

View file

@ -214,25 +214,27 @@ CONTAINS
!> \param do_admm ...
!> \param do_hfxlr ...
!> \param do_exck ...
!> \param do_sf ...
!> \param qs_env Quickstep environment
!> \param sub_env parallel group environment
!> \par History
!> * 02.2017 created [Sergey Chulkov]
! **************************************************************************************************
SUBROUTINE tddfpt_create_work_matrices(work_matrices, gs_mos, nstates, do_hfx, do_admm, &
do_hfxlr, do_exck, qs_env, sub_env)
do_hfxlr, do_exck, do_sf, qs_env, sub_env)
TYPE(tddfpt_work_matrices), INTENT(out) :: work_matrices
TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
INTENT(in) :: gs_mos
INTEGER, INTENT(in) :: nstates
LOGICAL, INTENT(in) :: do_hfx, do_admm, do_hfxlr, do_exck
LOGICAL, INTENT(in) :: do_hfx, do_admm, do_hfxlr, do_exck, do_sf
TYPE(qs_environment_type), POINTER :: qs_env
TYPE(tddfpt_subgroup_env_type), INTENT(in) :: sub_env
CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_create_work_matrices'
INTEGER :: handle, igroup, ispin, istate, nao, &
nao_aux, natom, ngroups, nspins
INTEGER :: evecs_dim, handle, igroup, ispin, &
istate, nao, nao_aux, natom, ngroups, &
nspins
INTEGER, DIMENSION(maxspins) :: nmo_occ, nmo_virt
TYPE(admm_type), POINTER :: admm_env
TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
@ -271,6 +273,11 @@ CONTAINS
NULLIFY (work_matrices%rho_xc_struct_sub)
nspins = SIZE(gs_mos)
IF (do_sf) THEN
evecs_dim = 1
ELSE
evecs_dim = nspins
END IF
CALL get_qs_env(qs_env, blacs_env=blacs_env, matrix_s=matrix_s)
CALL dbcsr_get_info(matrix_s(1)%matrix, nfullrows_total=nao)
@ -313,25 +320,25 @@ CONTAINS
END DO
IF (sub_env%is_split) THEN
DO ispin = 1, nspins
DO ispin = 1, evecs_dim
CALL cp_fm_struct_create(fm_struct_evects(ispin)%struct, nrow_global=nao, &
ncol_global=nmo_occ(ispin), context=sub_env%blacs_env)
END DO
ALLOCATE (work_matrices%evects_sub(nspins, nstates), work_matrices%Aop_evects_sub(nspins, nstates))
ALLOCATE (work_matrices%evects_sub(evecs_dim, nstates), work_matrices%Aop_evects_sub(evecs_dim, nstates))
CALL blacs_env%get(para_env=para_env)
igroup = sub_env%group_distribution(para_env%mepos)
ngroups = sub_env%ngroups
DO istate = ngroups - igroup, nstates, ngroups
DO ispin = 1, nspins
DO ispin = 1, evecs_dim
CALL cp_fm_create(work_matrices%evects_sub(ispin, istate), fm_struct_evects(ispin)%struct)
CALL cp_fm_create(work_matrices%Aop_evects_sub(ispin, istate), fm_struct_evects(ispin)%struct)
END DO
END DO
DO ispin = nspins, 1, -1
DO ispin = evecs_dim, 1, -1
CALL cp_fm_struct_release(fm_struct_evects(ispin)%struct)
END DO
END IF
@ -356,8 +363,8 @@ CONTAINS
! group-specific dbcsr matrices
NULLIFY (work_matrices%A_ia_munu_sub)
CALL dbcsr_allocate_matrix_set(work_matrices%A_ia_munu_sub, nspins)
DO ispin = 1, nspins
CALL dbcsr_allocate_matrix_set(work_matrices%A_ia_munu_sub, evecs_dim)
DO ispin = 1, evecs_dim
CALL dbcsr_init_p(work_matrices%A_ia_munu_sub(ispin)%matrix)
CALL tddfpt_dbcsr_create_by_dist(work_matrices%A_ia_munu_sub(ispin)%matrix, template=matrix_s(1)%matrix, &
dbcsr_dist=sub_env%dbcsr_dist, sab=sub_env%sab_orb)

View file

@ -38,8 +38,8 @@ MODULE qs_tddfpt2_utils
cp_logger_get_default_io_unit,&
cp_logger_type
USE input_constants, ONLY: &
cholesky_dbcsr, cholesky_inverse, cholesky_off, cholesky_restore, oe_gllb, oe_lb, oe_none, &
oe_saop, oe_shift
cholesky_dbcsr, cholesky_inverse, cholesky_off, cholesky_restore, no_sf_tddfpt, oe_gllb, &
oe_lb, oe_none, oe_saop, oe_shift
USE input_section_types, ONLY: section_vals_create,&
section_vals_get,&
section_vals_get_subs_vals,&
@ -726,12 +726,14 @@ CONTAINS
! **************************************************************************************************
!> \brief Compute the number of possible singly excited states (occ -> virt)
!> \param tddfpt_control ...
!> \param gs_mos occupied and virtual molecular orbitals optimised for the ground state
!> \return the number of possible single excitations
!> \par History
!> * 01.2017 created [Sergey Chulkov]
! **************************************************************************************************
PURE FUNCTION tddfpt_total_number_of_states(gs_mos) RESULT(nstates_total)
PURE FUNCTION tddfpt_total_number_of_states(tddfpt_control, gs_mos) RESULT(nstates_total)
TYPE(tddfpt2_control_type), POINTER :: tddfpt_control
TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
INTENT(in) :: gs_mos
INTEGER(kind=int_8) :: nstates_total
@ -741,11 +743,18 @@ CONTAINS
nstates_total = 0
nspins = SIZE(gs_mos)
DO ispin = 1, nspins
nstates_total = nstates_total + &
SIZE(gs_mos(ispin)%evals_occ, kind=int_8)* &
SIZE(gs_mos(ispin)%evals_virt, kind=int_8)
END DO
! Total number of possible excitations for spin-conserving TDDFT
IF (tddfpt_control%spinflip == no_sf_tddfpt) THEN
DO ispin = 1, nspins
nstates_total = nstates_total + &
SIZE(gs_mos(ispin)%evals_occ, kind=int_8)* &
SIZE(gs_mos(ispin)%evals_virt, kind=int_8)
END DO
! Total number of possible excitations for spin-flip TDDFT
ELSE
nstates_total = SIZE(gs_mos(1)%evals_occ, kind=int_8)* &
SIZE(gs_mos(2)%evals_virt, kind=int_8)
END IF
END FUNCTION tddfpt_total_number_of_states
! **************************************************************************************************
@ -909,6 +918,8 @@ CONTAINS
! **************************************************************************************************
!> \brief Generate missed guess vectors.
!> \param tddfpt_control ...
!> \param nspins ...
!> \param evects guess vectors distributed across all processors (initialised on exit)
!> \param evals guessed transition energies (initialised on exit)
!> \param gs_mos occupied and virtual molecular orbitals optimised for the ground state
@ -927,20 +938,22 @@ CONTAINS
!> a restart file).
!> \endparblock
! **************************************************************************************************
SUBROUTINE tddfpt_guess_vectors(evects, evals, gs_mos, log_unit)
SUBROUTINE tddfpt_guess_vectors(tddfpt_control, nspins, evects, evals, gs_mos, log_unit)
TYPE(tddfpt2_control_type), POINTER :: tddfpt_control
INTEGER :: nspins
TYPE(cp_fm_type), DIMENSION(:, :), INTENT(inout) :: evects
REAL(kind=dp), DIMENSION(:), INTENT(inout) :: evals
TYPE(tddfpt_ground_state_mos), &
DIMENSION(SIZE(evects, 1)), INTENT(in) :: gs_mos
TYPE(tddfpt_ground_state_mos), DIMENSION(nspins), &
INTENT(in) :: gs_mos
INTEGER, INTENT(in) :: log_unit
CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_guess_vectors'
CHARACTER(len=5) :: spin_label
CHARACTER(len=5) :: spin_label1, spin_label2
INTEGER :: handle, imo_occ, imo_virt, ind, ispin, &
istate, jspin, nspins, nstates, &
istate, jspin, nstates, &
nstates_occ_virt_alpha, &
nstates_selected
nstates_selected, spin1, spin2
INTEGER, ALLOCATABLE, DIMENSION(:) :: inds
INTEGER, DIMENSION(maxspins) :: nmo_occ_avail, nmo_occ_selected, &
nmo_virt_selected
@ -950,7 +963,6 @@ CONTAINS
CALL timeset(routineN, handle)
nspins = SIZE(evects, 1)
nstates = SIZE(evects, 2)
IF (debug_this_module) THEN
@ -971,23 +983,41 @@ CONTAINS
! TO DO: the variable 'nstates_selected' should probably be declared as INTEGER(kind=int_8),
! however we need a special version of the subroutine sort() in order to do so
nstates_selected = DOT_PRODUCT(nmo_occ_selected(1:nspins), nmo_virt_selected(1:nspins))
IF (tddfpt_control%spinflip == no_sf_tddfpt) THEN
nstates_selected = DOT_PRODUCT(nmo_occ_selected(1:nspins), nmo_virt_selected(1:nspins))
ELSE
nstates_selected = nmo_occ_selected(1)*nmo_virt_selected(2)
END IF
ALLOCATE (inds(nstates_selected))
ALLOCATE (e_virt_minus_occ(nstates_selected))
istate = 0
DO ispin = 1, nspins
DO imo_occ = 1, nmo_occ_selected(ispin)
! Here imo_occ enumerate Occupied orbitals in inverse order (from the last to the first element)
e_occ = gs_mos(ispin)%evals_occ(nmo_occ_avail(ispin) - imo_occ + 1)
IF (tddfpt_control%spinflip == no_sf_tddfpt) THEN
! Guess for spin-conserving TDDFT
DO ispin = 1, nspins
DO imo_occ = 1, nmo_occ_selected(ispin)
! Here imo_occ enumerate Occupied orbitals in inverse order (from the last to the first element)
e_occ = gs_mos(ispin)%evals_occ(nmo_occ_avail(ispin) - imo_occ + 1)
DO imo_virt = 1, nmo_virt_selected(ispin)
istate = istate + 1
e_virt_minus_occ(istate) = gs_mos(ispin)%evals_virt(imo_virt) - e_occ
DO imo_virt = 1, nmo_virt_selected(ispin)
istate = istate + 1
e_virt_minus_occ(istate) = gs_mos(ispin)%evals_virt(imo_virt) - e_occ
END DO
END DO
END DO
END DO
ELSE
! Guess for spin-flip TDDFT
DO imo_occ = 1, nmo_occ_selected(1)
! Here imo_occ enumerate alpha Occupied orbitals in inverse order (from the last to the first element)
e_occ = gs_mos(1)%evals_occ(nmo_occ_avail(1) - imo_occ + 1)
DO imo_virt = 1, nmo_virt_selected(2)
istate = istate + 1
e_virt_minus_occ(istate) = gs_mos(2)%evals_virt(imo_virt) - e_occ
END DO
END DO
END IF
IF (debug_this_module) THEN
CPASSERT(istate == nstates_selected)
@ -995,12 +1025,27 @@ CONTAINS
CALL sort(e_virt_minus_occ, nstates_selected, inds)
! Labels and spin component for closed-shell
IF (nspins == 1) THEN
ispin = 1
spin_label = ' '
spin1 = 1
spin2 = spin1
spin_label1 = ' '
spin_label2 = spin_label1
! Labels and spin component for spin-flip excitations
ELSE IF (tddfpt_control%spinflip .NE. no_sf_tddfpt) THEN
spin1 = 1
spin2 = 2
spin_label1 = '(alp)'
spin_label2 = '(bet)'
END IF
nstates_occ_virt_alpha = nmo_occ_selected(1)*nmo_virt_selected(1)
IF (tddfpt_control%spinflip == no_sf_tddfpt) THEN
! Calculate maximum number of alpha excitations
nstates_occ_virt_alpha = nmo_occ_selected(1)*nmo_virt_selected(1)
ELSE
! Calculate maximum number of spin-flip excitations
nstates_occ_virt_alpha = nmo_occ_selected(1)*nmo_virt_selected(2)
END IF
IF (log_unit > 0) THEN
WRITE (log_unit, "(1X,A)") "", &
"-------------------------------------------------------------------------------", &
@ -1012,45 +1057,59 @@ CONTAINS
END IF
DO istate = 1, nstates
! Initial guess vector read from restart file
IF (ASSOCIATED(evects(1, istate)%matrix_struct)) THEN
IF (log_unit > 0) &
WRITE (log_unit, '(T7,I8,T28,A19,T60,F14.5)') &
istate, "*** restarted ***", evals(istate)*evolt
! New initial guess vector
ELSE
! Index of excited state - 1
ind = inds(istate) - 1
IF (nspins > 1) THEN
! Labels and spin component for open-shell spin-conserving excitations
IF ((nspins > 1) .AND. (tddfpt_control%spinflip == no_sf_tddfpt)) THEN
IF (ind < nstates_occ_virt_alpha) THEN
ispin = 1
spin_label = '(alp)'
spin1 = 1
spin2 = 1
spin_label1 = '(alp)'
spin_label2 = '(alp)'
ELSE
ispin = 2
ind = ind - nstates_occ_virt_alpha
spin_label = '(bet)'
spin1 = 2
spin2 = 2
spin_label1 = '(bet)'
spin_label2 = '(bet)'
END IF
END IF
imo_occ = nmo_occ_avail(ispin) - ind/nmo_virt_selected(ispin)
imo_virt = MOD(ind, nmo_virt_selected(ispin)) + 1
! Recover index of occupied MO (imo_occ) and unoccupied MO (imo_virt)
! associated to the excited state index (ind+1)
imo_occ = nmo_occ_avail(spin1) - ind/nmo_virt_selected(spin2)
imo_virt = MOD(ind, nmo_virt_selected(spin2)) + 1
! Assign initial guess for excitation energy
evals(istate) = e_virt_minus_occ(istate)
IF (log_unit > 0) &
WRITE (log_unit, '(T7,I8,T24,I8,T37,A5,T45,I8,T54,A5,T60,F14.5)') &
istate, imo_occ, spin_label, nmo_occ_avail(ispin) + imo_virt, spin_label, e_virt_minus_occ(istate)*evolt
istate, imo_occ, spin_label1, nmo_occ_avail(spin2) + imo_virt, spin_label2, e_virt_minus_occ(istate)*evolt
DO jspin = 1, nspins
DO jspin = 1, SIZE(evects, 1)
! .NOT. ASSOCIATED(evects(jspin, istate)%matrix_struct))
CALL cp_fm_create(evects(jspin, istate), fm_struct_evects(jspin)%struct)
CALL cp_fm_set_all(evects(jspin, istate), 0.0_dp)
IF (jspin == ispin) &
CALL cp_fm_to_fm(gs_mos(ispin)%mos_virt, evects(ispin, istate), &
IF (jspin == spin1) &
! Half transform excitation vector to ao space:
! evects_mi = c_ma*X_ai
CALL cp_fm_to_fm(gs_mos(spin2)%mos_virt, evects(spin1, istate), &
ncol=1, source_start=imo_virt, target_start=imo_occ)
END DO
END IF
END DO
IF (log_unit > 0) THEN
WRITE (log_unit, '(/,T7,A,T50,I24)') 'Number of active states:', tddfpt_total_number_of_states(gs_mos)
WRITE (log_unit, '(/,T7,A,T50,I24)') 'Number of active states:', tddfpt_total_number_of_states(tddfpt_control, gs_mos)
WRITE (log_unit, "(1X,A)") &
"-------------------------------------------------------------------------------"
END IF

View file

@ -435,16 +435,17 @@ CONTAINS
!> \param para_env ...
!> \param do_tddfpt2 New implementation of TDDFT.
!> \param do_triplet ...
!> \param do_sf ...
!> \param kind_set_external ...
! **************************************************************************************************
SUBROUTINE calculate_xc_2nd_deriv_atom(rho_atom_set, rho1_atom_set, qs_env, xc_section, para_env, &
do_tddfpt2, do_triplet, kind_set_external)
do_tddfpt2, do_triplet, do_sf, kind_set_external)
TYPE(rho_atom_type), DIMENSION(:), POINTER :: rho_atom_set, rho1_atom_set
TYPE(qs_environment_type), POINTER :: qs_env
TYPE(section_vals_type), POINTER :: xc_section
TYPE(mp_para_env_type), INTENT(IN) :: para_env
LOGICAL, INTENT(IN), OPTIONAL :: do_tddfpt2, do_triplet
LOGICAL, INTENT(IN), OPTIONAL :: do_tddfpt2, do_triplet, do_sf
TYPE(qs_kind_type), DIMENSION(:), OPTIONAL, &
POINTER :: kind_set_external
@ -455,8 +456,8 @@ CONTAINS
INTEGER, DIMENSION(2) :: local_loop_limit
INTEGER, DIMENSION(2, 3) :: bounds
INTEGER, DIMENSION(:), POINTER :: atom_list
LOGICAL :: gradient_functional, lsd, paw_atom, &
scale_rho, tau_f
LOGICAL :: gradient_functional, lsd, my_do_sf, &
paw_atom, scale_rho, tau_f
REAL(KIND=dp) :: density_cut, gradient_cut, rtot, tau_cut
REAL(KIND=dp), CONTIGUOUS, DIMENSION(:, :, :), &
POINTER :: vxc_h, vxc_s
@ -511,6 +512,9 @@ CONTAINS
CALL section_vals_val_get(xc_section, "TAU_CUTOFF", &
r_val=tau_cut)
my_do_sf = .FALSE.
IF (PRESENT(do_sf)) my_do_sf = do_sf
xc_fun_section => section_vals_get_subs_vals(xc_section, &
"XC_FUNCTIONAL")
IF (lsd) THEN
@ -682,11 +686,13 @@ CONTAINS
CALL xc_2nd_deriv_of_r(xc_section=xc_section, &
rho_set=rho_set_h, rho1_set=rho1_set_h, &
deriv_set=deriv_set, &
w=weight, vxc=vxc_h, vxg=vxg_h, do_triplet=do_triplet)
w=weight, vxc=vxc_h, vxg=vxg_h, do_triplet=do_triplet, &
do_sf=my_do_sf)
CALL xc_2nd_deriv_of_r(xc_section=xc_section, &
rho_set=rho_set_s, rho1_set=rho1_set_s, &
deriv_set=deriv_set, &
w=weight, vxc=vxc_s, vxg=vxg_s, do_triplet=do_triplet)
w=weight, vxc=vxc_s, vxg=vxg_s, do_triplet=do_triplet, &
do_sf=my_do_sf)
CALL get_rho_atom(rho_atom=rho1_atom, ga_Vlocal_gb_h=int_hh, ga_Vlocal_gb_s=int_ss)
IF (gradient_functional) THEN

View file

@ -645,9 +645,11 @@ CONTAINS
! **************************************************************************************************
!> \brief Initializes vectors for MO-coefficient based linear response solver
!> and calculates response density, and energy-weighted response density matrix
!> J. Chem. Theory Comput. 2022, 18, 41864202 (https://doi.org/10.1021/acs.jctc.2c00144)
!>
!> \param qs_env ...
!> \param p_env ...
!> \param p_env Holds the two results of this routine, p_env%p1 = CZ^T + ZC^T,
!> p_env%w1 = 0.5\sum_i(C_i*\epsilon_i*Z_i^T + Z_i*\epsilon_i*C_i^T)
!> \param cpmos RHS of equation as Ax + b = 0 (sign of b)
!> \param iounit ...
!> \param lr_section ...
@ -780,7 +782,7 @@ CONTAINS
END DO
END IF
! Calculate Wz = 0.5*(psi1*eps*psi0^T + psi0*eps*psi1^T)
! Calculate the second term of Eq. 51 Wz = 0.5*(psi1*eps*psi0^T + psi0*eps*psi1^T)
CALL get_qs_env(qs_env, matrix_ks=matrix_ks)
DO ispin = 1, nspins
CALL calculate_wz_matrix(mos(ispin), psi1(ispin), matrix_ks(ispin)%matrix, &
@ -965,7 +967,7 @@ CONTAINS
mpa => matrix_pz
END IF
!
! START OF Tr(P+Z)Hcore
! START OF Tr[(P+Z)Hcore]
!
! Kinetic energy matrix
@ -1060,7 +1062,7 @@ CONTAINS
CALL total_qs_force(ftot2, force, atomic_kind_set)
fodeb(1:3) = ftot2(1:3, 1) - ftot1(1:3, 1)
CALL para_env%sum(fodeb)
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Pz*dHcore", fodeb
IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: (T+Dz)*dHcore", fodeb
END IF
IF (debug_stress .AND. use_virial) THEN
stdeb = fconv*(virial%pv_virial - sttot)

File diff suppressed because it is too large Load diff

View file

@ -339,9 +339,10 @@ CONTAINS
!> \param vxc ...
!> \param vxg ...
!> \param do_triplet ...
!> \param do_sf ...
! **************************************************************************************************
SUBROUTINE xc_2nd_deriv_of_r(rho_set, rho1_set, xc_section, &
deriv_set, w, vxc, vxg, do_triplet)
deriv_set, w, vxc, vxg, do_triplet, do_sf)
! As input of this routine one gets rho and drho on a one dimensional grid.
! The grid is the angular grid corresponding to a given point ir on the radial grid.
@ -356,12 +357,12 @@ CONTAINS
REAL(dp), DIMENSION(:, :), POINTER :: w
REAL(dp), CONTIGUOUS, DIMENSION(:, :, :), POINTER :: vxc
REAL(dp), DIMENSION(:, :, :, :), POINTER :: vxg
LOGICAL, INTENT(IN), OPTIONAL :: do_triplet
LOGICAL, INTENT(IN), OPTIONAL :: do_triplet, do_sf
CHARACTER(LEN=*), PARAMETER :: routineN = 'xc_2nd_deriv_of_r'
INTEGER :: handle, ispin, nspins
LOGICAL :: lsd
LOGICAL :: lsd, my_do_sf
REAL(dp) :: drho_cutoff, my_fac_triplet
TYPE(cp_sll_xc_deriv_type), POINTER :: pos
TYPE(pw_pool_type), POINTER :: pw_pool
@ -381,6 +382,9 @@ CONTAINS
IF (do_triplet) my_fac_triplet = -1.0_dp
END IF
my_do_sf = .FALSE.
IF (PRESENT(do_sf)) my_do_sf = do_sf
CALL xc_rho_set_get(rho_set, drho_cutoff=drho_cutoff)
xc_fun_section => section_vals_get_subs_vals(xc_section, &
"XC_FUNCTIONAL")
@ -409,7 +413,7 @@ CONTAINS
NULLIFY (vxc_tau_pw)
CALL xc_calc_2nd_deriv_analytical(vxc_pw, vxc_tau_pw, deriv_set, rho_set, rho1_set, pw_pool, &
xc_section, gapw=.TRUE., vxg=vxg, tddfpt_fac=my_fac_triplet)
xc_section, gapw=.TRUE., vxg=vxg, tddfpt_fac=my_fac_triplet, spinflip=do_sf)
DEALLOCATE (vxc_pw)

View file

@ -593,10 +593,10 @@ CONTAINS
!> \param needs the components of rho that are needed
!> \param xc_deriv_method_id ...
!> \param xc_rho_smooth_id ...
!> \param pw_pool pool for the allocation of pw and cr3d
!> \param pw_pool pool for the allocation of pw and array
! **************************************************************************************************
SUBROUTINE xc_rho_set_update(rho_set, rho_r, rho_g, tau, needs, &
xc_deriv_method_id, xc_rho_smooth_id, pw_pool)
xc_deriv_method_id, xc_rho_smooth_id, pw_pool, spinflip)
TYPE(xc_rho_set_type), INTENT(INOUT) :: rho_set
TYPE(pw_r3d_rs_type), DIMENSION(:), INTENT(IN) :: rho_r
TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho_g
@ -604,18 +604,22 @@ CONTAINS
TYPE(xc_rho_cflags_type), INTENT(in) :: needs
INTEGER, INTENT(IN) :: xc_deriv_method_id, xc_rho_smooth_id
TYPE(pw_pool_type), POINTER :: pw_pool
LOGICAL, OPTIONAL :: spinflip
REAL(KIND=dp), PARAMETER :: f13 = (1.0_dp/3.0_dp)
INTEGER :: i, idir, ispin, j, k, nspins
LOGICAL :: gradient_f, my_rho_g_local, &
needs_laplace, needs_rho_g
needs_laplace, needs_rho_g, do_sf
REAL(kind=dp) :: rho_cutoff
TYPE(pw_r3d_rs_type), DIMENSION(2) :: laplace_rho_r
TYPE(pw_r3d_rs_type), DIMENSION(3, 2) :: drho_r
TYPE(pw_c1d_gs_type) :: my_rho_g, tmp_g
TYPE(pw_r3d_rs_type), DIMENSION(2) :: my_rho_r
do_sf = .FALSE.
IF (PRESENT(spinflip)) do_sf = spinflip
IF (ANY(rho_set%local_bounds /= pw_pool%pw_grid%bounds_local)) &
CPABORT("pw_pool cr3d have different size than expected")
nspins = SIZE(rho_r)
@ -626,12 +630,20 @@ CONTAINS
! some checks
SELECT CASE (nspins)
CASE (1)
CPASSERT(.NOT. needs%rho_spin)
CPASSERT(.NOT. needs%drho_spin)
CPASSERT(.NOT. needs%norm_drho_spin)
CPASSERT(.NOT. needs%rho_spin_1_3)
CPASSERT(.NOT. needs%tau_spin)
CPASSERT(.NOT. needs%laplace_rho_spin)
IF (.NOT. do_sf) THEN
CPASSERT(.NOT. needs%rho_spin)
CPASSERT(.NOT. needs%drho_spin)
CPASSERT(.NOT. needs%norm_drho_spin)
CPASSERT(.NOT. needs%rho_spin_1_3)
CPASSERT(.NOT. needs%tau_spin)
CPASSERT(.NOT. needs%laplace_rho_spin)
ELSE
CPASSERT(.NOT. needs%rho)
CPASSERT(.NOT. needs%drho)
CPASSERT(.NOT. needs%rho_1_3)
CPASSERT(.NOT. needs%tau)
CPASSERT(.NOT. needs%laplace_rho)
END IF
CASE (2)
CPASSERT(.NOT. needs%rho)
CPASSERT(.NOT. needs%drho)
@ -724,55 +736,113 @@ CONTAINS
SELECT CASE (nspins)
CASE (1)
IF (needs%rho_1_3) THEN
CALL pw_pool%create_cr3d(rho_set%rho_1_3)
!$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i,j,k) SHARED(rho_set,my_rho_r)
DO k = rho_set%local_bounds(1, 3), rho_set%local_bounds(2, 3)
DO j = rho_set%local_bounds(1, 2), rho_set%local_bounds(2, 2)
DO i = rho_set%local_bounds(1, 1), rho_set%local_bounds(2, 1)
rho_set%rho_1_3(i, j, k) = MAX(my_rho_r(1)%array(i, j, k), 0.0_dp)**f13
IF (.NOT. do_sf) THEN
IF (needs%rho_1_3) THEN
CALL pw_pool%create_cr3d(rho_set%rho_1_3)
!$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i,j,k) SHARED(rho_set,my_rho_r)
DO k = rho_set%local_bounds(1, 3), rho_set%local_bounds(2, 3)
DO j = rho_set%local_bounds(1, 2), rho_set%local_bounds(2, 2)
DO i = rho_set%local_bounds(1, 1), rho_set%local_bounds(2, 1)
rho_set%rho_1_3(i, j, k) = MAX(my_rho_r(1)%array(i, j, k), 0.0_dp)**f13
END DO
END DO
END DO
END DO
rho_set%owns%rho_1_3 = .TRUE.
rho_set%has%rho_1_3 = .TRUE.
END IF
IF (needs%rho) THEN
rho_set%rho => my_rho_r(1)%array
NULLIFY (my_rho_r(1)%array)
rho_set%owns%rho = .TRUE.
rho_set%has%rho = .TRUE.
END IF
IF (needs%norm_drho) THEN
CALL pw_pool%create_cr3d(rho_set%norm_drho)
!$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i,j,k) SHARED(rho_set,drho_r)
DO k = rho_set%local_bounds(1, 3), rho_set%local_bounds(2, 3)
DO j = rho_set%local_bounds(1, 2), rho_set%local_bounds(2, 2)
DO i = rho_set%local_bounds(1, 1), rho_set%local_bounds(2, 1)
rho_set%norm_drho(i, j, k) = SQRT( &
drho_r(1, 1)%array(i, j, k)**2 + &
drho_r(2, 1)%array(i, j, k)**2 + &
drho_r(3, 1)%array(i, j, k)**2)
rho_set%owns%rho_1_3 = .TRUE.
rho_set%has%rho_1_3 = .TRUE.
END IF
IF (needs%rho) THEN
rho_set%rho => my_rho_r(1)%array
NULLIFY (my_rho_r(1)%array)
rho_set%owns%rho = .TRUE.
rho_set%has%rho = .TRUE.
END IF
IF (needs%norm_drho) THEN
CALL pw_pool%create_cr3d(rho_set%norm_drho)
!$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i,j,k) SHARED(rho_set,drho_r)
DO k = rho_set%local_bounds(1, 3), rho_set%local_bounds(2, 3)
DO j = rho_set%local_bounds(1, 2), rho_set%local_bounds(2, 2)
DO i = rho_set%local_bounds(1, 1), rho_set%local_bounds(2, 1)
rho_set%norm_drho(i, j, k) = SQRT( &
drho_r(1, 1)%array(i, j, k)**2 + &
drho_r(2, 1)%array(i, j, k)**2 + &
drho_r(3, 1)%array(i, j, k)**2)
END DO
END DO
END DO
END DO
rho_set%owns%norm_drho = .TRUE.
rho_set%has%norm_drho = .TRUE.
END IF
IF (needs%laplace_rho) THEN
rho_set%laplace_rho => laplace_rho_r(1)%array
NULLIFY (laplace_rho_r(1)%array)
rho_set%owns%laplace_rho = .TRUE.
rho_set%has%laplace_rho = .TRUE.
END IF
rho_set%owns%norm_drho = .TRUE.
rho_set%has%norm_drho = .TRUE.
END IF
IF (needs%laplace_rho) THEN
rho_set%laplace_rho => laplace_rho_r(1)%array
NULLIFY (laplace_rho_r(1)%array)
rho_set%owns%laplace_rho = .TRUE.
rho_set%has%laplace_rho = .TRUE.
END IF
IF (needs%drho) THEN
DO idir = 1, 3
rho_set%drho(idir)%array => drho_r(idir, 1)%array
NULLIFY (drho_r(idir, 1)%array)
END DO
rho_set%owns%drho = .TRUE.
rho_set%has%drho = .TRUE.
IF (needs%drho) THEN
DO idir = 1, 3
rho_set%drho(idir)%array => drho_r(idir, 1)%array
NULLIFY (drho_r(idir, 1)%array)
END DO
rho_set%owns%drho = .TRUE.
rho_set%has%drho = .TRUE.
END IF
ELSE
IF (needs%norm_drho) THEN
CALL pw_pool%create_cr3d(rho_set%norm_drho)
!$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i,j,k) SHARED(rho_set,drho_r)
DO k = rho_set%local_bounds(1, 3), rho_set%local_bounds(2, 3)
DO j = rho_set%local_bounds(1, 2), rho_set%local_bounds(2, 2)
DO i = rho_set%local_bounds(1, 1), rho_set%local_bounds(2, 1)
rho_set%norm_drho(i, j, k) = SQRT( &
drho_r(1, 1)%array(i, j, k)**2 + &
drho_r(2, 1)%array(i, j, k)**2 + &
drho_r(3, 1)%array(i, j, k)**2)
END DO
END DO
END DO
rho_set%owns%norm_drho = .TRUE.
rho_set%has%norm_drho = .TRUE.
END IF
IF (needs%rho_spin) THEN
rho_set%rhoa => my_rho_r(1)%array
NULLIFY (my_rho_r(1)%array)
rho_set%owns%rho_spin = .TRUE.
rho_set%has%rho_spin = .TRUE.
END IF
IF (needs%norm_drho_spin) THEN
CALL pw_pool%create_cr3d(rho_set%norm_drhoa)
!$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i,j,k) SHARED(rho_set,drho_r)
DO k = rho_set%local_bounds(1, 3), rho_set%local_bounds(2, 3)
DO j = rho_set%local_bounds(1, 2), rho_set%local_bounds(2, 2)
DO i = rho_set%local_bounds(1, 1), rho_set%local_bounds(2, 1)
rho_set%norm_drhoa(i, j, k) = SQRT( &
drho_r(1, 1)%array(i, j, k)**2 + &
drho_r(2, 1)%array(i, j, k)**2 + &
drho_r(3, 1)%array(i, j, k)**2)
END DO
END DO
END DO
rho_set%owns%norm_drho_spin = .TRUE.
rho_set%has%norm_drho_spin = .TRUE.
END IF
IF (needs%laplace_rho_spin) THEN
rho_set%laplace_rhoa => laplace_rho_r(1)%array
NULLIFY (laplace_rho_r(1)%array)
rho_set%owns%laplace_rho_spin = .TRUE.
rho_set%has%laplace_rho_spin = .TRUE.
END IF
IF (needs%drho_spin) THEN
DO idir = 1, 3
rho_set%drhoa(idir)%array => drho_r(idir, 1)%array
NULLIFY (drho_r(idir, 1)%array)
END DO
rho_set%owns%drho_spin = .TRUE.
rho_set%has%drho_spin = .TRUE.
END IF
END IF
CASE (2)
IF (needs%rho_spin_1_3) THEN

View file

@ -0,0 +1,11 @@
# runs are executed in the same order as in this file
# the second field tells which test should be run in order to compare with the last available output
# e.g. 0 means do not compare anything, running is enough
# 1 compares the last total energy in the file
# for details see cp2k/tools/do_regtest
# Check noncollinear kernel for optimizations using LDA, GGA and global Hybrid functional
"h2o_pade_opt.inp" = [{matcher="E_total", tol=1.0E-11, ref=-16.83108497678968}]
"h2o_pbe_opt.inp" = [{matcher="E_total", tol=1.0E-06, ref=-16.93971229185894}]
"h2o_pbe0_opt.inp" = [{matcher="E_total", tol=1.0E-11, ref=-16.92940602177875}]
#
#EOF

View file

@ -0,0 +1,92 @@
&GLOBAL
PRINT_LEVEL LOW
PROJECT ftest
RUN_TYPE GEO_OPT
&END GLOBAL
&MOTION
&GEO_OPT
MAX_ITER 1
&END GEO_OPT
&END MOTION
&FORCE_EVAL
METHOD Quickstep
&DFT
MULTIPLICITY 3
UKS
&EXCITED_STATES T
STATE 1
&END EXCITED_STATES
&MGRID
CUTOFF 280
REL_CUTOFF 60
&END MGRID
&POISSON
PERIODIC NONE
POISSON_SOLVER MT
&END POISSON
&QS
METHOD GPW
&END QS
&SCF
EPS_SCF 1.0E-8
MAX_SCF 50
SCF_GUESS ATOMIC
&OT
MINIMIZER DIIS
PRECONDITIONER FULL_SINGLE_INVERSE
&END OT
&OUTER_SCF
EPS_SCF 1.0E-8
MAX_SCF 10
&END OUTER_SCF
&END SCF
&XC
&XC_FUNCTIONAL PADE
&END XC_FUNCTIONAL
&END XC
&END DFT
&PRINT
&FORCES
&END FORCES
&END PRINT
&PROPERTIES
&TDDFPT
CONVERGENCE [eV] 1.0e-7
KERNEL FULL
MAX_ITER 50
NSTATES 5
SPINFLIP NONCOLLINEAR
&LINRES
EPS 1.0E-10
EPS_FILTER 1.0E-15
MAX_ITER 20
PRECONDITIONER FULL_SINGLE_INVERSE
&END LINRES
&END TDDFPT
&END PROPERTIES
&SUBSYS
&CELL
ABC [angstrom] 4.0 4.0 4.0
PERIODIC NONE
&END CELL
&COORD
O 0.000000 0.000000 0.000000
H 0.000000 -0.757136 0.580545
H 0.000000 0.757136 0.580545
&END COORD
&KIND H
BASIS_SET DZV-GTH-PADE
POTENTIAL GTH-PADE-q1
&END KIND
&KIND O
BASIS_SET DZVP-GTH-PADE
POTENTIAL GTH-PADE-q6
&END KIND
&TOPOLOGY
&CENTER_COORDINATES
&END CENTER_COORDINATES
&END TOPOLOGY
&END SUBSYS
&END FORCE_EVAL

View file

@ -0,0 +1,107 @@
&GLOBAL
PRINT_LEVEL LOW
PROJECT ftest
RUN_TYPE GEO_OPT
&END GLOBAL
&MOTION
&GEO_OPT
MAX_ITER 1
&END GEO_OPT
&END MOTION
&FORCE_EVAL
METHOD Quickstep
&DFT
MULTIPLICITY 3
UKS
&EXCITED_STATES T
STATE 1
&END EXCITED_STATES
&MGRID
CUTOFF 280
REL_CUTOFF 60
&END MGRID
&POISSON
PERIODIC NONE
POISSON_SOLVER MT
&END POISSON
&QS
METHOD GPW
&END QS
&SCF
EPS_SCF 1.0E-8
MAX_SCF 50
SCF_GUESS ATOMIC
&OT
MINIMIZER DIIS
PRECONDITIONER FULL_SINGLE_INVERSE
&END OT
&OUTER_SCF
EPS_SCF 1.0E-8
MAX_SCF 10
&END OUTER_SCF
&END SCF
&XC
&HF
FRACTION 0.25
&INTERACTION_POTENTIAL
CUTOFF_RADIUS 10.0
POTENTIAL_TYPE TRUNCATED
T_C_G_DATA ./t_c_g.dat
&END INTERACTION_POTENTIAL
&SCREENING
EPS_SCHWARZ 1.0E-12
&END SCREENING
&END HF
&XC_FUNCTIONAL
&PBE
SCALE_C 1.0
SCALE_X 0.75
&END PBE
&END XC_FUNCTIONAL
&END XC
&END DFT
&PRINT
&FORCES
&END FORCES
&END PRINT
&PROPERTIES
&TDDFPT
CONVERGENCE [eV] 1.0e-7
KERNEL FULL
MAX_ITER 50
NSTATES 5
SPINFLIP COLLINEAR
&LINRES
EPS 1.0E-10
EPS_FILTER 1.0E-15
MAX_ITER 20
PRECONDITIONER FULL_SINGLE_INVERSE
&END LINRES
&END TDDFPT
&END PROPERTIES
&SUBSYS
&CELL
ABC [angstrom] 4.0 4.0 4.0
PERIODIC NONE
&END CELL
&COORD
O 0.000000 0.000000 0.000000
H 0.000000 -0.757136 0.580545
H 0.000000 0.757136 0.580545
&END COORD
&KIND H
BASIS_SET DZV-GTH-PADE
POTENTIAL GTH-PADE-q1
&END KIND
&KIND O
BASIS_SET DZVP-GTH-PADE
POTENTIAL GTH-PADE-q6
&END KIND
&TOPOLOGY
&CENTER_COORDINATES
&END CENTER_COORDINATES
&END TOPOLOGY
&END SUBSYS
&END FORCE_EVAL

View file

@ -0,0 +1,92 @@
&GLOBAL
PRINT_LEVEL LOW
PROJECT ftest
RUN_TYPE GEO_OPT
&END GLOBAL
&MOTION
&GEO_OPT
MAX_ITER 1
&END GEO_OPT
&END MOTION
&FORCE_EVAL
METHOD Quickstep
&DFT
MULTIPLICITY 3
UKS
&EXCITED_STATES T
STATE 1
&END EXCITED_STATES
&MGRID
CUTOFF 280
REL_CUTOFF 60
&END MGRID
&POISSON
PERIODIC NONE
POISSON_SOLVER MT
&END POISSON
&QS
METHOD GPW
&END QS
&SCF
EPS_SCF 1.0E-8
MAX_SCF 50
SCF_GUESS ATOMIC
&OT
MINIMIZER DIIS
PRECONDITIONER FULL_SINGLE_INVERSE
&END OT
&OUTER_SCF
EPS_SCF 1.0E-8
MAX_SCF 10
&END OUTER_SCF
&END SCF
&XC
&XC_FUNCTIONAL PBE
&END XC_FUNCTIONAL
&END XC
&END DFT
&PRINT
&FORCES
&END FORCES
&END PRINT
&PROPERTIES
&TDDFPT
CONVERGENCE [eV] 1.0e-7
KERNEL FULL
MAX_ITER 50
NSTATES 5
SPINFLIP NONCOLLINEAR
&LINRES
EPS 1.0E-10
EPS_FILTER 1.0E-15
MAX_ITER 20
PRECONDITIONER FULL_SINGLE_INVERSE
&END LINRES
&END TDDFPT
&END PROPERTIES
&SUBSYS
&CELL
ABC [angstrom] 4.0 4.0 4.0
PERIODIC NONE
&END CELL
&COORD
O 0.000000 0.000000 0.000000
H 0.000000 -0.757136 0.580545
H 0.000000 0.757136 0.580545
&END COORD
&KIND H
BASIS_SET DZV-GTH-PADE
POTENTIAL GTH-PADE-q1
&END KIND
&KIND O
BASIS_SET DZVP-GTH-PADE
POTENTIAL GTH-PADE-q6
&END KIND
&TOPOLOGY
&CENTER_COORDINATES
&END CENTER_COORDINATES
&END TOPOLOGY
&END SUBSYS
&END FORCE_EVAL

View file

@ -0,0 +1,18 @@
# runs are executed in the same order as in this file
# the second field tells which test should be run in order to compare with the last available output
# e.g. 0 means do not compare anything, running is enough
# 1 compares the last total energy in the file
# for details see cp2k/tools/do_regtest
"h2o_pade.inp" = [{matcher="M068", tol=1.0E-03, ref=-6.92175}]
"h2o_pbe.inp" = [{matcher="M068", tol=1.0E-03, ref=-6.95678}]
"h2o_pbe0_col.inp" = [{matcher="M068", tol=1.0E-03, ref=11.73433}]
"h2o_pbe0_admm_pbex.inp" = [{matcher="M068", tol=1.0E-03, ref=9.59331}]
"h2o_pbe0_admm_none.inp" = [{matcher="M068", tol=1.0E-03, ref=9.74160}]
#
#EOF

View file

@ -0,0 +1,63 @@
&GLOBAL
PRINT_LEVEL LOW
PROJECT h2o_pade
RUN_TYPE ENERGY
&END GLOBAL
&FORCE_EVAL
METHOD Quickstep
&DFT
BASIS_SET_FILE_NAME BASIS_SET
MULTIPLICITY 3
POTENTIAL_FILE_NAME POTENTIAL
UKS
&MGRID
CUTOFF 100
&END MGRID
&QS
&END QS
&SCF
IGNORE_CONVERGENCE_FAILURE
MAX_SCF 10
SCF_GUESS atomic
&END SCF
&XC
&XC_FUNCTIONAL PBE
&END XC_FUNCTIONAL
&END XC
&END DFT
&PROPERTIES
&TDDFPT
CONVERGENCE 1.0e-5
MAX_ITER 10
MAX_KV 10
NSTATES 3
SPINFLIP NONCOLLINEAR
&XC
&XC_FUNCTIONAL PADE
&END XC_FUNCTIONAL
&XC_GRID
XC_DERIV SPLINE2_SMOOTH
&END XC_GRID
&END XC
&END TDDFPT
&END PROPERTIES
&SUBSYS
&CELL
ABC 5.0 5.0 5.0
&END CELL
&COORD
O 0.000000 0.000000 -0.065587 H2O
H 0.000000 -0.757136 0.520545 H2O
H 0.000000 0.757136 0.520545 H2O
&END COORD
&KIND H
BASIS_SET DZVP-GTH-PADE
POTENTIAL GTH-PADE-q1
&END KIND
&KIND O
BASIS_SET DZVP-GTH-PADE
POTENTIAL GTH-PADE-q6
&END KIND
&END SUBSYS
&END FORCE_EVAL

View file

@ -0,0 +1,63 @@
&GLOBAL
PRINT_LEVEL LOW
PROJECT h2o_pbe
RUN_TYPE ENERGY
&END GLOBAL
&FORCE_EVAL
METHOD Quickstep
&DFT
BASIS_SET_FILE_NAME BASIS_SET
MULTIPLICITY 3
POTENTIAL_FILE_NAME POTENTIAL
UKS
&MGRID
CUTOFF 100
&END MGRID
&QS
&END QS
&SCF
IGNORE_CONVERGENCE_FAILURE
MAX_SCF 10
SCF_GUESS atomic
&END SCF
&XC
&XC_FUNCTIONAL PBE
&END XC_FUNCTIONAL
&END XC
&END DFT
&PROPERTIES
&TDDFPT
CONVERGENCE 1.0e-5
MAX_ITER 10
MAX_KV 10
NSTATES 3
SPINFLIP NONCOLLINEAR
&XC
&XC_FUNCTIONAL PBE
&END XC_FUNCTIONAL
&XC_GRID
XC_DERIV SPLINE2_SMOOTH
&END XC_GRID
&END XC
&END TDDFPT
&END PROPERTIES
&SUBSYS
&CELL
ABC 5.0 5.0 5.0
&END CELL
&COORD
O 0.000000 0.000000 -0.065587 H2O
H 0.000000 -0.757136 0.520545 H2O
H 0.000000 0.757136 0.520545 H2O
&END COORD
&KIND H
BASIS_SET DZVP-GTH-PADE
POTENTIAL GTH-PADE-q1
&END KIND
&KIND O
BASIS_SET DZVP-GTH-PADE
POTENTIAL GTH-PADE-q6
&END KIND
&END SUBSYS
&END FORCE_EVAL

View file

@ -0,0 +1,88 @@
&GLOBAL
PRINT_LEVEL LOW
PROJECT h2o_pbe0_admm_none
RUN_TYPE ENERGY
&END GLOBAL
&FORCE_EVAL
METHOD Quickstep
&DFT
BASIS_SET_FILE_NAME BASIS_SET
BASIS_SET_FILE_NAME BASIS_ADMM
MULTIPLICITY 3
POTENTIAL_FILE_NAME POTENTIAL
UKS
&AUXILIARY_DENSITY_MATRIX_METHOD
ADMM_PURIFICATION_METHOD NONE
ADMM_TYPE NONE
EXCH_CORRECTION_FUNC NONE
EXCH_SCALING_MODEL NONE
METHOD BASIS_PROJECTION
&END AUXILIARY_DENSITY_MATRIX_METHOD
&MGRID
CUTOFF 100
&END MGRID
&QS
&END QS
&SCF
IGNORE_CONVERGENCE_FAILURE
MAX_SCF 10
SCF_GUESS atomic
&END SCF
&XC
&HF
FRACTION 0.25
&INTERACTION_POTENTIAL
CUTOFF_RADIUS 10.0
POTENTIAL_TYPE TRUNCATED
T_C_G_DATA ./t_c_g.dat
&END INTERACTION_POTENTIAL
&SCREENING
EPS_SCHWARZ 1.0E-12
&END SCREENING
&END HF
&XC_FUNCTIONAL
&PBE
SCALE_C 1.0
SCALE_X 0.75
&END PBE
&END XC_FUNCTIONAL
&END XC
&END DFT
&PROPERTIES
&TDDFPT
CONVERGENCE 1.0e-5
MAX_ITER 10
MAX_KV 10
NSTATES 3
SPINFLIP COLLINEAR
&XC
&XC_FUNCTIONAL PBE
&END XC_FUNCTIONAL
&XC_GRID
XC_DERIV SPLINE2_SMOOTH
&END XC_GRID
&END XC
&END TDDFPT
&END PROPERTIES
&SUBSYS
&CELL
ABC 5.0 5.0 5.0
&END CELL
&COORD
O 0.000000 0.000000 -0.065587 H2O
H 0.000000 -0.757136 0.520545 H2O
H 0.000000 0.757136 0.520545 H2O
&END COORD
&KIND H
BASIS_SET DZVP-GTH-PADE
BASIS_SET AUX_FIT cFIT3
POTENTIAL GTH-PADE-q1
&END KIND
&KIND O
BASIS_SET DZVP-GTH-PADE
BASIS_SET AUX_FIT cFIT3
POTENTIAL GTH-PADE-q6
&END KIND
&END SUBSYS
&END FORCE_EVAL

View file

@ -0,0 +1,88 @@
&GLOBAL
PRINT_LEVEL LOW
PROJECT h2o_pbe0_admm_pbex
RUN_TYPE ENERGY
&END GLOBAL
&FORCE_EVAL
METHOD Quickstep
&DFT
BASIS_SET_FILE_NAME BASIS_SET
BASIS_SET_FILE_NAME BASIS_ADMM
MULTIPLICITY 3
POTENTIAL_FILE_NAME POTENTIAL
UKS
&AUXILIARY_DENSITY_MATRIX_METHOD
ADMM_PURIFICATION_METHOD NONE
ADMM_TYPE NONE
EXCH_CORRECTION_FUNC PBEx
EXCH_SCALING_MODEL NONE
METHOD BASIS_PROJECTION
&END AUXILIARY_DENSITY_MATRIX_METHOD
&MGRID
CUTOFF 100
&END MGRID
&QS
&END QS
&SCF
IGNORE_CONVERGENCE_FAILURE
MAX_SCF 10
SCF_GUESS atomic
&END SCF
&XC
&HF
FRACTION 0.25
&INTERACTION_POTENTIAL
CUTOFF_RADIUS 10.0
POTENTIAL_TYPE TRUNCATED
T_C_G_DATA ./t_c_g.dat
&END INTERACTION_POTENTIAL
&SCREENING
EPS_SCHWARZ 1.0E-12
&END SCREENING
&END HF
&XC_FUNCTIONAL
&PBE
SCALE_C 1.0
SCALE_X 0.75
&END PBE
&END XC_FUNCTIONAL
&END XC
&END DFT
&PROPERTIES
&TDDFPT
CONVERGENCE 1.0e-5
MAX_ITER 10
MAX_KV 10
NSTATES 3
SPINFLIP COLLINEAR
&XC
&XC_FUNCTIONAL PBE
&END XC_FUNCTIONAL
&XC_GRID
XC_DERIV SPLINE2_SMOOTH
&END XC_GRID
&END XC
&END TDDFPT
&END PROPERTIES
&SUBSYS
&CELL
ABC 5.0 5.0 5.0
&END CELL
&COORD
O 0.000000 0.000000 -0.065587 H2O
H 0.000000 -0.757136 0.520545 H2O
H 0.000000 0.757136 0.520545 H2O
&END COORD
&KIND H
BASIS_SET DZVP-GTH-PADE
BASIS_SET AUX_FIT cFIT3
POTENTIAL GTH-PADE-q1
&END KIND
&KIND O
BASIS_SET DZVP-GTH-PADE
BASIS_SET AUX_FIT cFIT3
POTENTIAL GTH-PADE-q6
&END KIND
&END SUBSYS
&END FORCE_EVAL

View file

@ -0,0 +1,78 @@
&GLOBAL
PRINT_LEVEL LOW
PROJECT h2o_pbe0_col
RUN_TYPE ENERGY
&END GLOBAL
&FORCE_EVAL
METHOD Quickstep
&DFT
BASIS_SET_FILE_NAME BASIS_SET
MULTIPLICITY 3
POTENTIAL_FILE_NAME POTENTIAL
UKS
&MGRID
CUTOFF 100
&END MGRID
&QS
&END QS
&SCF
IGNORE_CONVERGENCE_FAILURE
MAX_SCF 10
SCF_GUESS atomic
&END SCF
&XC
&HF
FRACTION 0.25
&INTERACTION_POTENTIAL
CUTOFF_RADIUS 10.0
POTENTIAL_TYPE TRUNCATED
T_C_G_DATA ./t_c_g.dat
&END INTERACTION_POTENTIAL
&SCREENING
EPS_SCHWARZ 1.0E-12
&END SCREENING
&END HF
&XC_FUNCTIONAL
&PBE
SCALE_C 1.0
SCALE_X 0.75
&END PBE
&END XC_FUNCTIONAL
&END XC
&END DFT
&PROPERTIES
&TDDFPT
CONVERGENCE 1.0e-5
MAX_ITER 10
MAX_KV 10
NSTATES 3
SPINFLIP COLLINEAR
&XC
&XC_FUNCTIONAL PBE
&END XC_FUNCTIONAL
&XC_GRID
XC_DERIV SPLINE2_SMOOTH
&END XC_GRID
&END XC
&END TDDFPT
&END PROPERTIES
&SUBSYS
&CELL
ABC 5.0 5.0 5.0
&END CELL
&COORD
O 0.000000 0.000000 -0.065587 H2O
H 0.000000 -0.757136 0.520545 H2O
H 0.000000 0.757136 0.520545 H2O
&END COORD
&KIND H
BASIS_SET DZVP-GTH-PADE
POTENTIAL GTH-PADE-q1
&END KIND
&KIND O
BASIS_SET DZVP-GTH-PADE
POTENTIAL GTH-PADE-q6
&END KIND
&END SUBSYS
&END FORCE_EVAL

View file

@ -3,6 +3,8 @@
# Directories have been reordered according the execution time needed for a gfortran pdbg run using 2 MPI tasks
# in case a new directory is added just add it at the top of the list..
# the order will be regularly checked and modified...
QS/regtest-tddfpt-sf-force libint
QS/regtest-tddfpt-sf libint
xTB/regtest-tblite-gfn1-grad tblite
QS/regtest-spgr-id spglib
HP-DFT