Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief Routines for an energy correction on top of a Kohn-Sham calculation
10 : !> \par History
11 : !> 03.2026 created from energy_correction
12 : !> \author JGH
13 : ! **************************************************************************************************
14 : MODULE ec_diag_solver
15 : USE atomic_kind_types, ONLY: atomic_kind_type
16 : USE basis_set_types, ONLY: gto_basis_set_type
17 : USE cp_blacs_env, ONLY: cp_blacs_env_type
18 : USE cp_control_types, ONLY: dft_control_type
19 : USE cp_dbcsr_api, ONLY: &
20 : dbcsr_create, dbcsr_filter, dbcsr_get_info, dbcsr_p_type, dbcsr_release, dbcsr_scale, &
21 : dbcsr_set, dbcsr_type, dbcsr_type_no_symmetry
22 : USE cp_dbcsr_operations, ONLY: copy_dbcsr_to_fm,&
23 : copy_fm_to_dbcsr,&
24 : cp_dbcsr_sm_fm_multiply
25 : USE cp_fm_diag, ONLY: cp_fm_geeig
26 : USE cp_fm_struct, ONLY: cp_fm_struct_create,&
27 : cp_fm_struct_release,&
28 : cp_fm_struct_type
29 : USE cp_fm_types, ONLY: cp_fm_create,&
30 : cp_fm_init_random,&
31 : cp_fm_release,&
32 : cp_fm_set_all,&
33 : cp_fm_type
34 : USE cp_log_handling, ONLY: cp_logger_get_default_unit_nr
35 : USE dm_ls_scf, ONLY: calculate_w_matrix_ls,&
36 : post_scf_sparsities
37 : USE dm_ls_scf_methods, ONLY: apply_matrix_preconditioner,&
38 : density_matrix_sign,&
39 : density_matrix_tc2,&
40 : density_matrix_trs4,&
41 : ls_scf_init_matrix_s
42 : USE dm_ls_scf_qs, ONLY: matrix_ls_create,&
43 : matrix_ls_to_qs,&
44 : matrix_qs_to_ls
45 : USE dm_ls_scf_types, ONLY: ls_scf_env_type
46 : USE ec_env_types, ONLY: energy_correction_type
47 : USE ec_methods, ONLY: ec_mos_init
48 : USE input_constants, ONLY: ec_matrix_sign,&
49 : ec_matrix_tc2,&
50 : ec_matrix_trs4,&
51 : ec_ot_atomic,&
52 : ec_ot_gs,&
53 : ot_precond_full_single_inverse,&
54 : ot_precond_solver_default
55 : USE kinds, ONLY: dp
56 : USE kpoint_methods, ONLY: kpoint_density_matrices,&
57 : kpoint_density_transform,&
58 : kpoint_set_mo_occupation
59 : USE message_passing, ONLY: mp_para_env_type
60 : USE particle_types, ONLY: particle_type
61 : USE preconditioner, ONLY: make_preconditioner
62 : USE preconditioner_types, ONLY: destroy_preconditioner,&
63 : init_preconditioner,&
64 : preconditioner_type
65 : USE qs_atomic_block, ONLY: calculate_atomic_block_dm
66 : USE qs_density_matrices, ONLY: calculate_density_matrix,&
67 : calculate_w_matrix
68 : USE qs_environment_types, ONLY: get_qs_env,&
69 : qs_environment_type
70 : USE qs_kind_types, ONLY: get_qs_kind,&
71 : qs_kind_type
72 : USE qs_mo_methods, ONLY: calculate_subspace_eigenvalues,&
73 : make_basis_sm
74 : USE qs_mo_occupation, ONLY: set_mo_occupation
75 : USE qs_mo_types, ONLY: allocate_mo_set,&
76 : deallocate_mo_set,&
77 : get_mo_set,&
78 : init_mo_set,&
79 : mo_set_type
80 : USE qs_ot_eigensolver, ONLY: ot_eigensolver
81 : USE qs_rho_types, ONLY: qs_rho_get,&
82 : qs_rho_type
83 : USE qs_scf_diagonalization, ONLY: diag_kp_basic
84 : USE string_utilities, ONLY: uppercase
85 : #include "./base/base_uses.f90"
86 :
87 : IMPLICIT NONE
88 :
89 : PRIVATE
90 :
91 : ! Global parameters
92 :
93 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'ec_diag_solver'
94 :
95 : PUBLIC :: ec_diag_solver_gamma, ec_diag_solver_kp, ec_ot_diag_solver, ec_ls_init, ec_ls_solver
96 :
97 : ! **************************************************************************************************
98 :
99 : CONTAINS
100 :
101 : ! **************************************************************************************************
102 : !> \brief Solve KS equation using diagonalization
103 : !> \param qs_env ...
104 : !> \param ec_env ...
105 : !> \param matrix_ks ...
106 : !> \param matrix_s ...
107 : !> \param matrix_p ...
108 : !> \param matrix_w ...
109 : !> \par History
110 : !> 03.2014 created [JGH]
111 : !> \author JGH
112 : ! **************************************************************************************************
113 312 : SUBROUTINE ec_diag_solver_gamma(qs_env, ec_env, matrix_ks, matrix_s, matrix_p, matrix_w)
114 :
115 : TYPE(qs_environment_type), POINTER :: qs_env
116 : TYPE(energy_correction_type) :: ec_env
117 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks, matrix_s, matrix_p, matrix_w
118 :
119 : CHARACTER(LEN=*), PARAMETER :: routineN = 'ec_diag_solver_gamma'
120 :
121 : INTEGER :: handle, ispin, nmo(2), nsize, nspins
122 : REAL(KIND=dp) :: eps_filter, flexible_electron_count, &
123 : focc(2), n_el_f
124 312 : REAL(KIND=dp), DIMENSION(:), POINTER :: eigvals
125 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
126 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
127 : TYPE(cp_fm_type) :: fm_k, fm_s, fm_w
128 : TYPE(cp_fm_type), POINTER :: fm_mos
129 : TYPE(dbcsr_type), POINTER :: ref_matrix
130 : TYPE(dft_control_type), POINTER :: dft_control
131 312 : TYPE(mo_set_type), ALLOCATABLE, DIMENSION(:) :: moset
132 : TYPE(mp_para_env_type), POINTER :: para_env
133 :
134 312 : CALL timeset(routineN, handle)
135 :
136 312 : CALL get_qs_env(qs_env=qs_env, dft_control=dft_control)
137 312 : eps_filter = dft_control%qs_control%eps_filter_matrix
138 312 : nspins = dft_control%nspins
139 :
140 312 : nmo = 0
141 312 : CALL get_qs_env(qs_env=qs_env, nelectron_spin=nmo)
142 936 : focc = 1._dp
143 1248 : IF (nspins == 1) focc = 2._dp
144 :
145 312 : CALL dbcsr_get_info(matrix_ks(1, 1)%matrix, nfullrows_total=nsize)
146 :
147 312 : NULLIFY (blacs_env, para_env)
148 312 : CALL get_qs_env(qs_env=qs_env, blacs_env=blacs_env, para_env=para_env)
149 312 : NULLIFY (fm_struct)
150 : CALL cp_fm_struct_create(fm_struct, context=blacs_env, nrow_global=nsize, &
151 312 : ncol_global=nsize, para_env=para_env)
152 312 : CALL cp_fm_create(fm_k, fm_struct)
153 312 : CALL cp_fm_create(fm_s, fm_struct)
154 312 : CALL cp_fm_create(fm_w, fm_struct)
155 312 : CALL cp_fm_struct_release(fm_struct)
156 :
157 : ! MO sets
158 312 : flexible_electron_count = 0.0_dp
159 312 : IF (ec_env%smear%do_smear) flexible_electron_count = 0.0001_dp
160 :
161 1248 : ALLOCATE (moset(nspins))
162 624 : DO ispin = 1, nspins
163 312 : n_el_f = nmo(ispin)
164 : CALL allocate_mo_set(moset(ispin), nsize, nsize, nmo(ispin), n_el_f, &
165 312 : focc(ispin), flexible_electron_count)
166 624 : CALL init_mo_set(moset(ispin), fm_ref=fm_w, name="MO")
167 : END DO
168 :
169 624 : DO ispin = 1, nspins
170 312 : ref_matrix => matrix_s(1, 1)%matrix
171 312 : CALL copy_dbcsr_to_fm(ref_matrix, fm_s)
172 312 : ref_matrix => matrix_ks(ispin, 1)%matrix
173 312 : CALL copy_dbcsr_to_fm(ref_matrix, fm_k)
174 312 : CALL get_mo_set(moset(ispin), eigenvalues=eigvals, mo_coeff=fm_mos)
175 624 : CALL cp_fm_geeig(fm_k, fm_s, fm_mos, eigvals, fm_w)
176 : END DO
177 : !
178 312 : CALL set_mo_occupation(moset, ec_env%smear)
179 : !
180 624 : DO ispin = 1, nspins
181 312 : ec_env%ekTS = ec_env%ekTS + moset(ispin)%kTS
182 312 : CALL calculate_density_matrix(moset(ispin), matrix_p(ispin, 1)%matrix)
183 624 : CALL calculate_w_matrix(moset(ispin), matrix_w(ispin, 1)%matrix)
184 : END DO
185 : !
186 312 : CALL cp_fm_release(fm_k)
187 312 : CALL cp_fm_release(fm_s)
188 312 : CALL cp_fm_release(fm_w)
189 624 : DO ispin = 1, nspins
190 624 : CALL deallocate_mo_set(moset(ispin))
191 : END DO
192 312 : DEALLOCATE (moset)
193 :
194 312 : CALL timestop(handle)
195 :
196 1248 : END SUBROUTINE ec_diag_solver_gamma
197 :
198 : ! **************************************************************************************************
199 : !> \brief Solve Kpoint-KS equation using diagonalization
200 : !> \param qs_env ...
201 : !> \param ec_env ...
202 : !> \param matrix_ks ...
203 : !> \param matrix_s ...
204 : !> \param matrix_p ...
205 : !> \param matrix_w ...
206 : !> \par History
207 : !> 03.2026 created [JGH]
208 : !> \author JGH
209 : ! **************************************************************************************************
210 10 : SUBROUTINE ec_diag_solver_kp(qs_env, ec_env, matrix_ks, matrix_s, matrix_p, matrix_w)
211 :
212 : TYPE(qs_environment_type), POINTER :: qs_env
213 : TYPE(energy_correction_type) :: ec_env
214 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks, matrix_s, matrix_p, matrix_w
215 :
216 : CHARACTER(LEN=*), PARAMETER :: routineN = 'ec_diag_solver_kp'
217 :
218 : INTEGER :: handle, i, ispin, nsize
219 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
220 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
221 10 : TYPE(cp_fm_type), DIMENSION(:), POINTER :: fmwork
222 : TYPE(dbcsr_type), POINTER :: tempmat
223 10 : TYPE(mo_set_type), DIMENSION(:, :), POINTER :: mos
224 : TYPE(mp_para_env_type), POINTER :: para_env
225 :
226 10 : CALL timeset(routineN, handle)
227 :
228 10 : CALL dbcsr_get_info(matrix_ks(1, 1)%matrix, nfullrows_total=nsize)
229 :
230 10 : NULLIFY (blacs_env, para_env)
231 10 : CALL get_qs_env(qs_env=qs_env, blacs_env=blacs_env, para_env=para_env)
232 10 : NULLIFY (fm_struct)
233 : CALL cp_fm_struct_create(fm_struct, context=blacs_env, nrow_global=nsize, &
234 10 : ncol_global=nsize, para_env=para_env)
235 50 : ALLOCATE (fmwork(4))
236 50 : DO i = 1, 4
237 50 : CALL cp_fm_create(fmwork(i), fm_struct)
238 : END DO
239 10 : CALL cp_fm_struct_release(fm_struct)
240 :
241 : ! Diagonalization
242 10 : CALL diag_kp_basic(matrix_ks, matrix_s, ec_env%kpoints, fmwork)
243 : ! MO occupations
244 10 : CALL kpoint_set_mo_occupation(ec_env%kpoints, ec_env%smear)
245 : ! density matrices
246 10 : CALL kpoint_density_matrices(ec_env%kpoints)
247 10 : CALL kpoint_density_matrices(ec_env%kpoints, .TRUE.)
248 : ! density matrices in real space
249 10 : tempmat => matrix_s(1, 1)%matrix
250 : CALL kpoint_density_transform(ec_env%kpoints, matrix_p, .FALSE., tempmat, &
251 10 : ec_env%sab_orb, fmwork)
252 : CALL kpoint_density_transform(ec_env%kpoints, matrix_w, .TRUE., tempmat, &
253 10 : ec_env%sab_orb, fmwork)
254 :
255 10 : ec_env%ekTS = 0.0_dp
256 10 : mos => ec_env%kpoints%kp_env(1)%kpoint_env%mos
257 20 : DO ispin = 1, SIZE(mos, 2)
258 20 : ec_env%ekTS = ec_env%ekTS + mos(1, ispin)%kTS
259 : END DO
260 :
261 10 : CALL cp_fm_release(fmwork)
262 :
263 10 : CALL timestop(handle)
264 :
265 10 : END SUBROUTINE ec_diag_solver_kp
266 :
267 : ! **************************************************************************************************
268 : !> \brief Use OT-diagonalziation to obtain density matrix from Harris Kohn-Sham matrix
269 : !> Initial guess of density matrix is either the atomic block initial guess from SCF
270 : !> or the ground-state density matrix. The latter only works if the same basis is used
271 : !>
272 : !> \param qs_env ...
273 : !> \param ec_env ...
274 : !> \param matrix_ks Harris Kohn-Sham matrix
275 : !> \param matrix_s Overlap matrix in Harris functional basis
276 : !> \param matrix_p Harris dentiy matrix, calculated here
277 : !> \param matrix_w Harris energy weighted density matrix, calculated here
278 : !>
279 : !> \par History
280 : !> 09.2020 created
281 : !> \author F.Belleflamme
282 : ! **************************************************************************************************
283 4 : SUBROUTINE ec_ot_diag_solver(qs_env, ec_env, matrix_ks, matrix_s, matrix_p, matrix_w)
284 : TYPE(qs_environment_type), POINTER :: qs_env
285 : TYPE(energy_correction_type), POINTER :: ec_env
286 : TYPE(dbcsr_p_type), DIMENSION(:, :), INTENT(IN), &
287 : POINTER :: matrix_ks, matrix_s
288 : TYPE(dbcsr_p_type), DIMENSION(:, :), &
289 : INTENT(INOUT), POINTER :: matrix_p, matrix_w
290 :
291 : CHARACTER(len=*), PARAMETER :: routineN = 'ec_ot_diag_solver'
292 :
293 : INTEGER :: handle, homo, ikind, iounit, ispin, &
294 : max_iter, nao, nkind, nmo, nspins
295 : INTEGER, DIMENSION(2) :: nelectron_spin
296 4 : REAL(KIND=dp), DIMENSION(:), POINTER :: eigenvalues
297 4 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
298 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
299 : TYPE(cp_fm_type) :: sv
300 : TYPE(cp_fm_type), POINTER :: mo_coeff
301 4 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: p_rmpv
302 4 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: rho_ao
303 : TYPE(dft_control_type), POINTER :: dft_control
304 : TYPE(gto_basis_set_type), POINTER :: basis_set, harris_basis
305 4 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
306 : TYPE(mp_para_env_type), POINTER :: para_env
307 4 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
308 : TYPE(preconditioner_type), POINTER :: local_preconditioner
309 4 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
310 : TYPE(qs_kind_type), POINTER :: qs_kind
311 : TYPE(qs_rho_type), POINTER :: rho
312 :
313 4 : CALL timeset(routineN, handle)
314 :
315 4 : iounit = cp_logger_get_default_unit_nr(local=.FALSE.)
316 :
317 4 : CPASSERT(ASSOCIATED(qs_env))
318 4 : CPASSERT(ASSOCIATED(ec_env))
319 4 : CPASSERT(ASSOCIATED(matrix_ks))
320 4 : CPASSERT(ASSOCIATED(matrix_s))
321 4 : CPASSERT(ASSOCIATED(matrix_p))
322 4 : CPASSERT(ASSOCIATED(matrix_w))
323 :
324 : CALL get_qs_env(qs_env=qs_env, &
325 : atomic_kind_set=atomic_kind_set, &
326 : blacs_env=blacs_env, &
327 : dft_control=dft_control, &
328 : nelectron_spin=nelectron_spin, &
329 : para_env=para_env, &
330 : particle_set=particle_set, &
331 4 : qs_kind_set=qs_kind_set)
332 4 : nspins = dft_control%nspins
333 :
334 : ! Maximum number of OT iterations for diagonalization
335 4 : max_iter = 200
336 :
337 : ! If linear scaling, need to allocate and init MO set
338 : ! set it to qs_env%mos
339 4 : IF (dft_control%qs_control%do_ls_scf) THEN
340 0 : CALL ec_mos_init(qs_env, matrix_s(1, 1)%matrix)
341 : END IF
342 :
343 4 : CALL get_qs_env(qs_env, mos=mos)
344 :
345 : ! Inital guess to use
346 4 : NULLIFY (p_rmpv)
347 :
348 : ! Using ether ground-state DM or ATOMIC GUESS requires
349 : ! Harris functional to use the same basis set
350 4 : CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set, nkind=nkind)
351 4 : CALL uppercase(ec_env%basis)
352 : ! Harris basis only differs from ground-state basis if explicitly added
353 : ! thus only two cases that need to be tested
354 : ! 1) explicit Harris basis present?
355 4 : IF (ec_env%basis == "HARRIS") THEN
356 12 : DO ikind = 1, nkind
357 8 : qs_kind => qs_kind_set(ikind)
358 : ! Basis sets of ground-state
359 8 : CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set, basis_type="ORB")
360 : ! Basis sets of energy correction
361 8 : CALL get_qs_kind(qs_kind=qs_kind, basis_set=harris_basis, basis_type="HARRIS")
362 :
363 12 : IF (basis_set%name /= harris_basis%name) THEN
364 0 : CPABORT("OT-Diag initial guess: Harris and ground state need to use the same basis")
365 : END IF
366 : END DO
367 : END IF
368 : ! 2) Harris uses MAOs
369 4 : IF (ec_env%mao) THEN
370 0 : CPABORT("OT-Diag initial guess: not implemented for MAOs")
371 : END IF
372 :
373 : ! Initital guess obtained for OT Diagonalization
374 6 : SELECT CASE (ec_env%ec_initial_guess)
375 : CASE (ec_ot_atomic)
376 :
377 2 : p_rmpv => matrix_p(:, 1)
378 :
379 : CALL calculate_atomic_block_dm(p_rmpv, matrix_s(1, 1)%matrix, atomic_kind_set, qs_kind_set, &
380 2 : nspins, nelectron_spin, iounit, para_env)
381 :
382 : CASE (ec_ot_gs)
383 :
384 2 : CALL get_qs_env(qs_env, rho=rho)
385 2 : CALL qs_rho_get(rho, rho_ao_kp=rho_ao)
386 2 : p_rmpv => rho_ao(:, 1)
387 :
388 : CASE DEFAULT
389 4 : CPABORT("Unknown inital guess for OT-Diagonalization (Harris functional)")
390 : END SELECT
391 :
392 8 : DO ispin = 1, nspins
393 : CALL get_mo_set(mo_set=mos(ispin), &
394 : mo_coeff=mo_coeff, &
395 : nmo=nmo, &
396 : nao=nao, &
397 4 : homo=homo)
398 :
399 : ! Calculate first MOs
400 4 : CALL cp_fm_set_all(mo_coeff, 0.0_dp)
401 4 : CALL cp_fm_init_random(mo_coeff, nmo)
402 :
403 4 : CALL cp_fm_create(sv, mo_coeff%matrix_struct, "SV")
404 : ! multiply times PS
405 : ! PS*C(:,1:nomo)+C(:,nomo+1:nmo) (nomo=NINT(nelectron/maxocc))
406 4 : CALL cp_dbcsr_sm_fm_multiply(matrix_s(1, 1)%matrix, mo_coeff, sv, nmo)
407 4 : CALL cp_dbcsr_sm_fm_multiply(p_rmpv(ispin)%matrix, sv, mo_coeff, homo)
408 4 : CALL cp_fm_release(sv)
409 : ! and ortho the result
410 : ! If DFBT or SE, then needs has_unit_metrix option
411 16 : CALL make_basis_sm(mo_coeff, nmo, matrix_s(1, 1)%matrix)
412 : END DO
413 :
414 : ! Preconditioner
415 : NULLIFY (local_preconditioner)
416 4 : ALLOCATE (local_preconditioner)
417 : CALL init_preconditioner(local_preconditioner, para_env=para_env, &
418 4 : blacs_env=blacs_env)
419 8 : DO ispin = 1, nspins
420 : CALL make_preconditioner(local_preconditioner, &
421 : precon_type=ot_precond_full_single_inverse, &
422 : solver_type=ot_precond_solver_default, &
423 : matrix_h=matrix_ks(ispin, 1)%matrix, &
424 : matrix_s=matrix_s(ispin, 1)%matrix, &
425 : convert_precond_to_dbcsr=.TRUE., &
426 4 : mo_set=mos(ispin), energy_gap=0.2_dp)
427 :
428 : CALL get_mo_set(mos(ispin), &
429 : mo_coeff=mo_coeff, &
430 : eigenvalues=eigenvalues, &
431 : nmo=nmo, &
432 4 : homo=homo)
433 : CALL ot_eigensolver(matrix_h=matrix_ks(ispin, 1)%matrix, &
434 : matrix_s=matrix_s(1, 1)%matrix, &
435 : matrix_c_fm=mo_coeff, &
436 : preconditioner=local_preconditioner, &
437 : eps_gradient=ec_env%eps_default, &
438 : iter_max=max_iter, &
439 4 : silent=.FALSE.)
440 : CALL calculate_subspace_eigenvalues(mo_coeff, matrix_ks(ispin, 1)%matrix, &
441 4 : evals_arg=eigenvalues, do_rotation=.TRUE.)
442 :
443 : ! Deallocate preconditioner
444 4 : CALL destroy_preconditioner(local_preconditioner)
445 4 : DEALLOCATE (local_preconditioner)
446 :
447 : !fm->dbcsr
448 : CALL copy_fm_to_dbcsr(mos(ispin)%mo_coeff, &
449 12 : mos(ispin)%mo_coeff_b)
450 : END DO
451 :
452 : ! Calculate density matrix from MOs
453 8 : DO ispin = 1, nspins
454 4 : CALL calculate_density_matrix(mos(ispin), matrix_p(ispin, 1)%matrix)
455 :
456 8 : CALL calculate_w_matrix(mos(ispin), matrix_w(ispin, 1)%matrix)
457 : END DO
458 :
459 : ! Get rid of MO environment again
460 4 : IF (dft_control%qs_control%do_ls_scf) THEN
461 0 : DO ispin = 1, nspins
462 0 : CALL deallocate_mo_set(mos(ispin))
463 : END DO
464 0 : IF (ASSOCIATED(qs_env%mos)) THEN
465 0 : DO ispin = 1, SIZE(qs_env%mos)
466 0 : CALL deallocate_mo_set(qs_env%mos(ispin))
467 : END DO
468 0 : DEALLOCATE (qs_env%mos)
469 : END IF
470 : END IF
471 :
472 4 : CALL timestop(handle)
473 :
474 4 : END SUBROUTINE ec_ot_diag_solver
475 :
476 : ! **************************************************************************************************
477 : !> \brief Solve the Harris functional by linear scaling density purification scheme,
478 : !> instead of the diagonalization performed in ec_diag_solver
479 : !>
480 : !> \param qs_env ...
481 : !> \param matrix_ks Harris Kohn-Sham matrix
482 : !> \param matrix_s Overlap matrix in Harris functional basis
483 : !> \par History
484 : !> 09.2020 created
485 : !> \author F.Belleflamme
486 : ! **************************************************************************************************
487 30 : SUBROUTINE ec_ls_init(qs_env, matrix_ks, matrix_s)
488 : TYPE(qs_environment_type), POINTER :: qs_env
489 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks, matrix_s
490 :
491 : CHARACTER(len=*), PARAMETER :: routineN = 'ec_ls_init'
492 :
493 : INTEGER :: handle, ispin, nspins
494 : TYPE(dft_control_type), POINTER :: dft_control
495 : TYPE(energy_correction_type), POINTER :: ec_env
496 : TYPE(ls_scf_env_type), POINTER :: ls_env
497 :
498 30 : CALL timeset(routineN, handle)
499 :
500 : CALL get_qs_env(qs_env=qs_env, &
501 : dft_control=dft_control, &
502 30 : ec_env=ec_env)
503 30 : nspins = dft_control%nspins
504 30 : ls_env => ec_env%ls_env
505 :
506 : ! create the matrix template for use in the ls procedures
507 : CALL matrix_ls_create(matrix_ls=ls_env%matrix_s, matrix_qs=matrix_s(1, 1)%matrix, &
508 30 : ls_mstruct=ls_env%ls_mstruct)
509 :
510 30 : IF (ALLOCATED(ls_env%matrix_p)) THEN
511 16 : DO ispin = 1, SIZE(ls_env%matrix_p)
512 16 : CALL dbcsr_release(ls_env%matrix_p(ispin))
513 : END DO
514 : ELSE
515 88 : ALLOCATE (ls_env%matrix_p(nspins))
516 : END IF
517 :
518 60 : DO ispin = 1, nspins
519 : CALL dbcsr_create(ls_env%matrix_p(ispin), template=ls_env%matrix_s, &
520 60 : matrix_type=dbcsr_type_no_symmetry)
521 : END DO
522 :
523 120 : ALLOCATE (ls_env%matrix_ks(nspins))
524 60 : DO ispin = 1, nspins
525 : CALL dbcsr_create(ls_env%matrix_ks(ispin), template=ls_env%matrix_s, &
526 60 : matrix_type=dbcsr_type_no_symmetry)
527 : END DO
528 :
529 : ! Set up S matrix and needed functions of S
530 30 : CALL ls_scf_init_matrix_s(matrix_s(1, 1)%matrix, ls_env)
531 :
532 : ! Bring KS matrix from QS to LS form
533 : ! EC KS-matrix already calculated
534 60 : DO ispin = 1, nspins
535 : CALL matrix_qs_to_ls(matrix_ls=ls_env%matrix_ks(ispin), &
536 : matrix_qs=matrix_ks(ispin, 1)%matrix, &
537 : ls_mstruct=ls_env%ls_mstruct, &
538 60 : covariant=.TRUE.)
539 : END DO
540 :
541 30 : CALL timestop(handle)
542 :
543 30 : END SUBROUTINE ec_ls_init
544 :
545 : ! **************************************************************************************************
546 : !> \brief Solve the Harris functional by linear scaling density purification scheme,
547 : !> instead of the diagonalization performed in ec_diag_solver
548 : !>
549 : !> \param qs_env ...
550 : !> \param matrix_p Harris dentiy matrix, calculated here
551 : !> \param matrix_w Harris energy weighted density matrix, calculated here
552 : !> \param ec_ls_method which purification scheme should be used
553 : !> \par History
554 : !> 12.2019 created [JGH]
555 : !> 08.2020 refactoring [fbelle]
556 : !> \author Fabian Belleflamme
557 : ! **************************************************************************************************
558 :
559 30 : SUBROUTINE ec_ls_solver(qs_env, matrix_p, matrix_w, ec_ls_method)
560 : TYPE(qs_environment_type), POINTER :: qs_env
561 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_p, matrix_w
562 : INTEGER, INTENT(IN) :: ec_ls_method
563 :
564 : CHARACTER(LEN=*), PARAMETER :: routineN = 'ec_ls_solver'
565 :
566 : INTEGER :: handle, ispin, nelectron_spin_real, &
567 : nspins
568 : INTEGER, DIMENSION(2) :: nmo
569 30 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: wmat
570 30 : TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:) :: matrix_ks_deviation
571 : TYPE(dft_control_type), POINTER :: dft_control
572 : TYPE(energy_correction_type), POINTER :: ec_env
573 : TYPE(ls_scf_env_type), POINTER :: ls_env
574 : TYPE(mp_para_env_type), POINTER :: para_env
575 :
576 30 : CALL timeset(routineN, handle)
577 :
578 30 : NULLIFY (para_env)
579 : CALL get_qs_env(qs_env, &
580 : dft_control=dft_control, &
581 30 : para_env=para_env)
582 30 : nspins = dft_control%nspins
583 30 : ec_env => qs_env%ec_env
584 30 : ls_env => ec_env%ls_env
585 :
586 30 : nmo = 0
587 30 : CALL get_qs_env(qs_env=qs_env, nelectron_spin=nmo)
588 30 : IF (nspins == 1) nmo(1) = nmo(1)/2
589 90 : ls_env%homo_spin(:) = 0.0_dp
590 90 : ls_env%lumo_spin(:) = 0.0_dp
591 :
592 120 : ALLOCATE (matrix_ks_deviation(nspins))
593 60 : DO ispin = 1, nspins
594 30 : CALL dbcsr_create(matrix_ks_deviation(ispin), template=ls_env%matrix_ks(ispin))
595 60 : CALL dbcsr_set(matrix_ks_deviation(ispin), 0.0_dp)
596 : END DO
597 :
598 : ! F = S^-1/2 * F * S^-1/2
599 30 : IF (ls_env%has_s_preconditioner) THEN
600 60 : DO ispin = 1, nspins
601 : CALL apply_matrix_preconditioner(ls_env%matrix_ks(ispin), "forward", &
602 30 : ls_env%matrix_bs_sqrt, ls_env%matrix_bs_sqrt_inv)
603 :
604 60 : CALL dbcsr_filter(ls_env%matrix_ks(ispin), ls_env%eps_filter)
605 : END DO
606 : END IF
607 :
608 60 : DO ispin = 1, nspins
609 30 : nelectron_spin_real = ls_env%nelectron_spin(ispin)
610 30 : IF (ls_env%nspins == 1) nelectron_spin_real = nelectron_spin_real/2
611 :
612 30 : SELECT CASE (ec_ls_method)
613 : CASE (ec_matrix_sign)
614 : CALL density_matrix_sign(ls_env%matrix_p(ispin), &
615 : ls_env%mu_spin(ispin), &
616 : ls_env%fixed_mu, &
617 : ls_env%sign_method, &
618 : ls_env%sign_order, &
619 : ls_env%matrix_ks(ispin), &
620 : ls_env%matrix_s, &
621 : ls_env%matrix_s_inv, &
622 : nelectron_spin_real, &
623 2 : ec_env%eps_default)
624 :
625 : CASE (ec_matrix_trs4)
626 : CALL density_matrix_trs4( &
627 : ls_env%matrix_p(ispin), &
628 : ls_env%matrix_ks(ispin), &
629 : ls_env%matrix_s_sqrt_inv, &
630 : nelectron_spin_real, &
631 : ec_env%eps_default, &
632 : ls_env%homo_spin(ispin), &
633 : ls_env%lumo_spin(ispin), &
634 : ls_env%mu_spin(ispin), &
635 : matrix_ks_deviation=matrix_ks_deviation(ispin), &
636 : dynamic_threshold=ls_env%dynamic_threshold, &
637 : eps_lanczos=ls_env%eps_lanczos, &
638 26 : max_iter_lanczos=ls_env%max_iter_lanczos)
639 :
640 : CASE (ec_matrix_tc2)
641 : CALL density_matrix_tc2( &
642 : ls_env%matrix_p(ispin), &
643 : ls_env%matrix_ks(ispin), &
644 : ls_env%matrix_s_sqrt_inv, &
645 : nelectron_spin_real, &
646 : ec_env%eps_default, &
647 : ls_env%homo_spin(ispin), &
648 : ls_env%lumo_spin(ispin), &
649 : non_monotonic=ls_env%non_monotonic, &
650 : eps_lanczos=ls_env%eps_lanczos, &
651 30 : max_iter_lanczos=ls_env%max_iter_lanczos)
652 :
653 : END SELECT
654 :
655 : END DO
656 :
657 : ! de-orthonormalize
658 30 : IF (ls_env%has_s_preconditioner) THEN
659 60 : DO ispin = 1, nspins
660 : ! P = S^-1/2 * P_tilde * S^-1/2 (forward)
661 : CALL apply_matrix_preconditioner(ls_env%matrix_p(ispin), "forward", &
662 30 : ls_env%matrix_bs_sqrt, ls_env%matrix_bs_sqrt_inv)
663 :
664 60 : CALL dbcsr_filter(ls_env%matrix_p(ispin), ls_env%eps_filter)
665 : END DO
666 : END IF
667 :
668 : ! Closed-shell
669 30 : IF (nspins == 1) CALL dbcsr_scale(ls_env%matrix_p(1), 2.0_dp)
670 :
671 30 : IF (ls_env%report_all_sparsities) CALL post_scf_sparsities(ls_env)
672 :
673 : ! ls_scf_dm_to_ks
674 : ! Density matrix from LS to EC
675 60 : DO ispin = 1, nspins
676 : CALL matrix_ls_to_qs(matrix_qs=matrix_p(ispin, 1)%matrix, &
677 : matrix_ls=ls_env%matrix_p(ispin), &
678 : ls_mstruct=ls_env%ls_mstruct, &
679 60 : covariant=.FALSE.)
680 : END DO
681 :
682 30 : wmat => matrix_w(:, 1)
683 30 : CALL calculate_w_matrix_ls(wmat, ec_env%ls_env)
684 :
685 : ! clean up
686 30 : CALL dbcsr_release(ls_env%matrix_s)
687 30 : IF (ls_env%has_s_preconditioner) THEN
688 30 : CALL dbcsr_release(ls_env%matrix_bs_sqrt)
689 30 : CALL dbcsr_release(ls_env%matrix_bs_sqrt_inv)
690 : END IF
691 30 : IF (ls_env%needs_s_inv) THEN
692 2 : CALL dbcsr_release(ls_env%matrix_s_inv)
693 : END IF
694 30 : IF (ls_env%use_s_sqrt) THEN
695 30 : CALL dbcsr_release(ls_env%matrix_s_sqrt)
696 30 : CALL dbcsr_release(ls_env%matrix_s_sqrt_inv)
697 : END IF
698 :
699 60 : DO ispin = 1, SIZE(ls_env%matrix_ks)
700 60 : CALL dbcsr_release(ls_env%matrix_ks(ispin))
701 : END DO
702 30 : DEALLOCATE (ls_env%matrix_ks)
703 :
704 60 : DO ispin = 1, nspins
705 60 : CALL dbcsr_release(matrix_ks_deviation(ispin))
706 : END DO
707 30 : DEALLOCATE (matrix_ks_deviation)
708 :
709 30 : CALL timestop(handle)
710 :
711 30 : END SUBROUTINE ec_ls_solver
712 :
713 : END MODULE ec_diag_solver
714 :
|