Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief Construction of the Exchange part of the Fock Matrix
10 : !> \author Teodoro Laino [tlaino] (05.2009) - Split and module reorganization
11 : !> \par History
12 : !> Teodoro Laino (04.2008) [tlaino] - University of Zurich : d-orbitals
13 : !> Teodoro Laino (09.2008) [tlaino] - University of Zurich : Speed-up
14 : !> Teodoro Laino (09.2008) [tlaino] - University of Zurich : Periodic SE
15 : ! **************************************************************************************************
16 : MODULE se_fock_matrix_exchange
17 : USE atomic_kind_types, ONLY: atomic_kind_type,&
18 : get_atomic_kind_set
19 : USE cell_types, ONLY: cell_type
20 : USE cp_control_types, ONLY: dft_control_type,&
21 : semi_empirical_control_type
22 : USE cp_dbcsr_api, ONLY: dbcsr_get_block_p,&
23 : dbcsr_p_type
24 : USE input_constants, ONLY: do_se_IS_kdso,&
25 : do_se_IS_kdso_d
26 : USE kinds, ONLY: dp
27 : USE message_passing, ONLY: mp_para_env_type
28 : USE multipole_types, ONLY: do_multipole_none
29 : USE particle_types, ONLY: particle_type
30 : USE qs_environment_types, ONLY: get_qs_env,&
31 : qs_environment_type
32 : USE qs_force_types, ONLY: qs_force_type
33 : USE qs_kind_types, ONLY: get_qs_kind,&
34 : qs_kind_type
35 : USE qs_neighbor_list_types, ONLY: get_iterator_info,&
36 : neighbor_list_iterate,&
37 : neighbor_list_iterator_create,&
38 : neighbor_list_iterator_p_type,&
39 : neighbor_list_iterator_release,&
40 : neighbor_list_set_p_type
41 : USE se_fock_matrix_integrals, ONLY: dfock2E,&
42 : fock1_2el,&
43 : fock2E
44 : USE semi_empirical_int_arrays, ONLY: rij_threshold
45 : USE semi_empirical_store_int_types, ONLY: semi_empirical_si_type
46 : USE semi_empirical_types, ONLY: get_se_param,&
47 : se_int_control_type,&
48 : se_taper_type,&
49 : semi_empirical_p_type,&
50 : semi_empirical_type,&
51 : setup_se_int_control_type
52 : USE semi_empirical_utils, ONLY: finalize_se_taper,&
53 : initialize_se_taper
54 : USE virial_methods, ONLY: virial_pair_force
55 : USE virial_types, ONLY: virial_type
56 : #include "./base/base_uses.f90"
57 :
58 : IMPLICIT NONE
59 : PRIVATE
60 :
61 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'se_fock_matrix_exchange'
62 : LOGICAL, PARAMETER, PRIVATE :: debug_this_module = .FALSE.
63 :
64 : PUBLIC :: build_fock_matrix_exchange
65 :
66 : CONTAINS
67 :
68 : ! **************************************************************************************************
69 : !> \brief Construction of the Exchange part of the Fock matrix
70 : !> \param qs_env ...
71 : !> \param ks_matrix ...
72 : !> \param matrix_p ...
73 : !> \param calculate_forces ...
74 : !> \param store_int_env ...
75 : !> \author JGH
76 : ! **************************************************************************************************
77 39152 : SUBROUTINE build_fock_matrix_exchange(qs_env, ks_matrix, matrix_p, calculate_forces, &
78 : store_int_env)
79 :
80 : TYPE(qs_environment_type), POINTER :: qs_env
81 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: ks_matrix, matrix_p
82 : LOGICAL, INTENT(in) :: calculate_forces
83 : TYPE(semi_empirical_si_type), POINTER :: store_int_env
84 :
85 : CHARACTER(len=*), PARAMETER :: routineN = 'build_fock_matrix_exchange'
86 :
87 : INTEGER :: atom_a, atom_b, handle, iatom, icol, &
88 : ikind, integral_screening, irow, &
89 : jatom, jkind, natorb_a, nkind, nspins
90 39152 : INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_of_kind
91 : INTEGER, DIMENSION(2) :: size_p_block_a
92 : LOGICAL :: anag, check, defined, found, switch, &
93 : use_virial
94 39152 : LOGICAL, ALLOCATABLE, DIMENSION(:) :: se_defined
95 : REAL(KIND=dp) :: delta, dr
96 : REAL(KIND=dp), DIMENSION(3) :: force_ab, rij
97 : REAL(KIND=dp), DIMENSION(45, 45) :: p_block_tot
98 39152 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: ks_block_a, ks_block_b, p_block_a, &
99 39152 : p_block_b
100 39152 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
101 : TYPE(cell_type), POINTER :: cell
102 : TYPE(dft_control_type), POINTER :: dft_control
103 : TYPE(mp_para_env_type), POINTER :: para_env
104 : TYPE(neighbor_list_iterator_p_type), &
105 39152 : DIMENSION(:), POINTER :: nl_iterator
106 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
107 39152 : POINTER :: sab_orb
108 39152 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
109 39152 : TYPE(qs_force_type), DIMENSION(:), POINTER :: force
110 39152 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
111 : TYPE(se_int_control_type) :: se_int_control
112 : TYPE(se_taper_type), POINTER :: se_taper
113 : TYPE(semi_empirical_control_type), POINTER :: se_control
114 39152 : TYPE(semi_empirical_p_type), DIMENSION(:), POINTER :: se_kind_list
115 : TYPE(semi_empirical_type), POINTER :: se_kind_a, se_kind_b
116 : TYPE(virial_type), POINTER :: virial
117 :
118 39152 : CALL timeset(routineN, handle)
119 :
120 39152 : NULLIFY (dft_control, cell, force, particle_set, se_control, se_taper)
121 : CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, cell=cell, se_taper=se_taper, &
122 39152 : para_env=para_env, virial=virial)
123 :
124 39152 : CALL initialize_se_taper(se_taper, exchange=.TRUE.)
125 39152 : se_control => dft_control%qs_control%se_control
126 39152 : anag = se_control%analytical_gradients
127 39152 : use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
128 39152 : nspins = dft_control%nspins
129 :
130 39152 : CPASSERT(ASSOCIATED(matrix_p))
131 39152 : CPASSERT(SIZE(ks_matrix) > 0)
132 :
133 : ! Identify proper integral screening (according user requests)
134 39152 : integral_screening = se_control%integral_screening
135 39152 : IF ((integral_screening == do_se_IS_kdso_d) .AND. (.NOT. se_control%force_kdsod_EX)) THEN
136 1360 : integral_screening = do_se_IS_kdso
137 : END IF
138 : CALL setup_se_int_control_type(se_int_control, shortrange=.FALSE., &
139 : do_ewald_r3=.FALSE., do_ewald_gks=.FALSE., integral_screening=integral_screening, &
140 39152 : max_multipole=do_multipole_none, pc_coulomb_int=.FALSE.)
141 :
142 : CALL get_qs_env(qs_env=qs_env, sab_orb=sab_orb, &
143 39152 : atomic_kind_set=atomic_kind_set, qs_kind_set=qs_kind_set)
144 :
145 39152 : nkind = SIZE(atomic_kind_set)
146 39152 : IF (calculate_forces) THEN
147 3002 : CALL get_qs_env(qs_env=qs_env, particle_set=particle_set, force=force)
148 3002 : delta = se_control%delta
149 3002 : CALL get_atomic_kind_set(atomic_kind_set=atomic_kind_set, atom_of_kind=atom_of_kind)
150 : END IF
151 :
152 331394 : ALLOCATE (se_defined(nkind), se_kind_list(nkind))
153 135634 : DO ikind = 1, nkind
154 96482 : CALL get_qs_kind(qs_kind_set(ikind), se_parameter=se_kind_a)
155 96482 : se_kind_list(ikind)%se_param => se_kind_a
156 96482 : CALL get_se_param(se_kind_a, defined=defined, natorb=natorb_a)
157 135634 : se_defined(ikind) = (defined .AND. natorb_a >= 1)
158 : END DO
159 :
160 39152 : CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
161 3789851 : DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
162 3750699 : CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, iatom=iatom, jatom=jatom, r=rij)
163 3750699 : IF (.NOT. se_defined(ikind)) CYCLE
164 3750699 : IF (.NOT. se_defined(jkind)) CYCLE
165 3750699 : se_kind_a => se_kind_list(ikind)%se_param
166 3750699 : se_kind_b => se_kind_list(jkind)%se_param
167 :
168 3750699 : IF (iatom <= jatom) THEN
169 1925181 : irow = iatom
170 1925181 : icol = jatom
171 1925181 : switch = .FALSE.
172 : ELSE
173 1825518 : irow = jatom
174 1825518 : icol = iatom
175 1825518 : switch = .TRUE.
176 : END IF
177 : ! Retrieve blocks for KS and P
178 : CALL dbcsr_get_block_p(matrix=ks_matrix(1)%matrix, &
179 3750699 : row=irow, col=icol, BLOCK=ks_block_a, found=found)
180 3750699 : CPASSERT(ASSOCIATED(ks_block_a))
181 : CALL dbcsr_get_block_p(matrix=matrix_p(1)%matrix, &
182 3750699 : row=irow, col=icol, BLOCK=p_block_a, found=found)
183 3750699 : CPASSERT(ASSOCIATED(p_block_a))
184 3750699 : size_p_block_a(1) = SIZE(p_block_a, 1)
185 3750699 : size_p_block_a(2) = SIZE(p_block_a, 2)
186 42976662 : p_block_tot(1:size_p_block_a(1), 1:size_p_block_a(2)) = 2.0_dp*p_block_a
187 :
188 : ! Handle more configurations
189 3750699 : IF (nspins == 2) THEN
190 : CALL dbcsr_get_block_p(matrix=ks_matrix(2)%matrix, &
191 20303 : row=irow, col=icol, BLOCK=ks_block_b, found=found)
192 20303 : CPASSERT(ASSOCIATED(ks_block_b))
193 : CALL dbcsr_get_block_p(matrix=matrix_p(2)%matrix, &
194 20303 : row=irow, col=icol, BLOCK=p_block_b, found=found)
195 20303 : CPASSERT(ASSOCIATED(p_block_b))
196 20303 : check = (size_p_block_a(1) == SIZE(p_block_b, 1)) .AND. (size_p_block_a(2) == SIZE(p_block_b, 2))
197 0 : CPASSERT(check)
198 217376 : p_block_tot(1:SIZE(p_block_a, 1), 1:SIZE(p_block_a, 2)) = p_block_a + p_block_b
199 : END IF
200 :
201 15002796 : dr = DOT_PRODUCT(rij, rij)
202 3789851 : IF (iatom == jatom .AND. dr < rij_threshold) THEN
203 : ! Once center - Two electron Terms
204 188985 : IF (nspins == 1) THEN
205 184724 : CALL fock1_2el(se_kind_a, p_block_tot, p_block_a, ks_block_a, factor=0.5_dp)
206 4261 : ELSE IF (nspins == 2) THEN
207 4261 : CALL fock1_2el(se_kind_a, p_block_tot, p_block_a, ks_block_a, factor=1.0_dp)
208 4261 : CALL fock1_2el(se_kind_a, p_block_tot, p_block_b, ks_block_b, factor=1.0_dp)
209 : END IF
210 : ELSE
211 : ! Exchange Terms
212 3561714 : IF (nspins == 1) THEN
213 : CALL fock2E(se_kind_a, se_kind_b, rij, switch, size_p_block_a, p_block_a, ks_block_a, &
214 : factor=0.5_dp, anag=anag, se_int_control=se_int_control, se_taper=se_taper, &
215 3545672 : store_int_env=store_int_env)
216 16042 : ELSE IF (nspins == 2) THEN
217 : CALL fock2E(se_kind_a, se_kind_b, rij, switch, size_p_block_a, p_block_a, ks_block_a, &
218 : factor=1.0_dp, anag=anag, se_int_control=se_int_control, se_taper=se_taper, &
219 16042 : store_int_env=store_int_env)
220 :
221 : CALL fock2E(se_kind_a, se_kind_b, rij, switch, size_p_block_a, p_block_b, ks_block_b, &
222 : factor=1.0_dp, anag=anag, se_int_control=se_int_control, se_taper=se_taper, &
223 16042 : store_int_env=store_int_env)
224 : END IF
225 3561714 : IF (calculate_forces) THEN
226 172272 : atom_a = atom_of_kind(iatom)
227 172272 : atom_b = atom_of_kind(jatom)
228 172272 : force_ab = 0.0_dp
229 172272 : IF (nspins == 1) THEN
230 : CALL dfock2E(se_kind_a, se_kind_b, rij, switch, size_p_block_a, p_block_a, &
231 : factor=0.5_dp, anag=anag, se_int_control=se_int_control, se_taper=se_taper, force=force_ab, &
232 172111 : delta=delta)
233 161 : ELSE IF (nspins == 2) THEN
234 : CALL dfock2E(se_kind_a, se_kind_b, rij, switch, size_p_block_a, p_block_a, &
235 : factor=1.0_dp, anag=anag, se_int_control=se_int_control, se_taper=se_taper, force=force_ab, &
236 161 : delta=delta)
237 :
238 : CALL dfock2E(se_kind_a, se_kind_b, rij, switch, size_p_block_a, p_block_b, &
239 : factor=1.0_dp, anag=anag, se_int_control=se_int_control, se_taper=se_taper, force=force_ab, &
240 161 : delta=delta)
241 : END IF
242 172272 : IF (switch) THEN
243 88778 : force_ab(1) = -force_ab(1)
244 88778 : force_ab(2) = -force_ab(2)
245 88778 : force_ab(3) = -force_ab(3)
246 : END IF
247 172272 : IF (use_virial) THEN
248 0 : CALL virial_pair_force(virial%pv_virial, -1.0_dp, force_ab, rij)
249 : END IF
250 :
251 172272 : force(ikind)%rho_elec(1, atom_a) = force(ikind)%rho_elec(1, atom_a) - force_ab(1)
252 172272 : force(jkind)%rho_elec(1, atom_b) = force(jkind)%rho_elec(1, atom_b) + force_ab(1)
253 :
254 172272 : force(ikind)%rho_elec(2, atom_a) = force(ikind)%rho_elec(2, atom_a) - force_ab(2)
255 172272 : force(jkind)%rho_elec(2, atom_b) = force(jkind)%rho_elec(2, atom_b) + force_ab(2)
256 :
257 172272 : force(ikind)%rho_elec(3, atom_a) = force(ikind)%rho_elec(3, atom_a) - force_ab(3)
258 172272 : force(jkind)%rho_elec(3, atom_b) = force(jkind)%rho_elec(3, atom_b) + force_ab(3)
259 : END IF
260 : END IF
261 : END DO
262 39152 : CALL neighbor_list_iterator_release(nl_iterator)
263 :
264 39152 : DEALLOCATE (se_kind_list, se_defined)
265 :
266 39152 : CALL finalize_se_taper(se_taper)
267 :
268 39152 : CALL timestop(handle)
269 :
270 78304 : END SUBROUTINE build_fock_matrix_exchange
271 :
272 : END MODULE se_fock_matrix_exchange
273 :
|