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 Routines for a linear scaling quickstep SCF run based on the density
10 : !> matrix
11 : !> \par History
12 : !> 2010.10 created [Joost VandeVondele]
13 : !> \author Joost VandeVondele
14 : ! **************************************************************************************************
15 : MODULE dm_ls_scf
16 : USE arnoldi_api, ONLY: arnoldi_extremal
17 : USE bibliography, ONLY: Kolafa2004,&
18 : Kuhne2007,&
19 : cite_reference
20 : USE cp_control_types, ONLY: dft_control_type
21 : USE cp_dbcsr_api, ONLY: &
22 : dbcsr_add, dbcsr_binary_read, dbcsr_binary_write, dbcsr_checksum, dbcsr_copy, &
23 : dbcsr_create, dbcsr_distribution_type, dbcsr_filter, dbcsr_get_info, dbcsr_get_occupation, &
24 : dbcsr_multiply, dbcsr_p_type, dbcsr_release, dbcsr_scale, dbcsr_set, dbcsr_type, &
25 : dbcsr_type_no_symmetry
26 : USE cp_external_control, ONLY: external_control
27 : USE cp_log_handling, ONLY: cp_get_default_logger,&
28 : cp_logger_get_default_unit_nr,&
29 : cp_logger_type
30 : USE dm_ls_chebyshev, ONLY: compute_chebyshev
31 : USE dm_ls_scf_curvy, ONLY: deallocate_curvy_data,&
32 : dm_ls_curvy_optimization
33 : USE dm_ls_scf_methods, ONLY: apply_matrix_preconditioner,&
34 : compute_homo_lumo,&
35 : density_matrix_sign,&
36 : density_matrix_sign_fixed_mu,&
37 : density_matrix_tc2,&
38 : density_matrix_trs4,&
39 : ls_scf_init_matrix_S
40 : USE dm_ls_scf_qs, ONLY: ls_scf_dm_to_ks,&
41 : ls_scf_init_qs,&
42 : ls_scf_qs_atomic_guess,&
43 : matrix_ls_create,&
44 : matrix_ls_to_qs,&
45 : matrix_qs_to_ls,&
46 : rho_mixing_ls_init
47 : USE dm_ls_scf_types, ONLY: ls_scf_env_type
48 : USE ec_env_types, ONLY: energy_correction_type
49 : USE input_constants, ONLY: ls_cluster_atomic,&
50 : ls_scf_pexsi,&
51 : ls_scf_sign,&
52 : ls_scf_tc2,&
53 : ls_scf_trs4,&
54 : transport_transmission
55 : USE input_section_types, ONLY: section_vals_type
56 : USE iterate_matrix, ONLY: purify_mcweeny
57 : USE kinds, ONLY: default_path_length,&
58 : default_string_length,&
59 : dp
60 : USE machine, ONLY: m_flush,&
61 : m_walltime
62 : USE mathlib, ONLY: binomial
63 : USE molecule_types, ONLY: molecule_type
64 : USE pao_main, ONLY: pao_optimization_end,&
65 : pao_optimization_start,&
66 : pao_post_scf,&
67 : pao_update
68 : USE pexsi_methods, ONLY: density_matrix_pexsi,&
69 : pexsi_finalize_scf,&
70 : pexsi_init_scf,&
71 : pexsi_set_convergence_tolerance,&
72 : pexsi_to_qs
73 : USE qs_diis, ONLY: qs_diis_b_clear_sparse,&
74 : qs_diis_b_create_sparse,&
75 : qs_diis_b_step_4lscf
76 : USE qs_diis_types, ONLY: qs_diis_b_release_sparse,&
77 : qs_diis_buffer_type_sparse
78 : USE qs_environment_types, ONLY: get_qs_env,&
79 : qs_environment_type
80 : USE qs_ks_types, ONLY: qs_ks_env_type
81 : USE qs_scf_post_gpw, ONLY: qs_scf_post_moments,&
82 : write_mo_free_results
83 : USE qs_scf_post_tb, ONLY: scf_post_calculation_tb
84 : USE transport, ONLY: external_scf_method,&
85 : transport_initialize
86 : USE transport_env_types, ONLY: transport_env_type
87 : #include "./base/base_uses.f90"
88 :
89 : IMPLICIT NONE
90 :
91 : PRIVATE
92 :
93 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'dm_ls_scf'
94 :
95 : PUBLIC :: calculate_w_matrix_ls, ls_scf, post_scf_sparsities
96 :
97 : CONTAINS
98 :
99 : ! **************************************************************************************************
100 : !> \brief perform an linear scaling scf procedure: entry point
101 : !>
102 : !> \param qs_env ...
103 : !> \par History
104 : !> 2010.10 created [Joost VandeVondele]
105 : !> \author Joost VandeVondele
106 : ! **************************************************************************************************
107 596 : SUBROUTINE ls_scf(qs_env)
108 : TYPE(qs_environment_type), POINTER :: qs_env
109 :
110 : CHARACTER(len=*), PARAMETER :: routineN = 'ls_scf'
111 :
112 : INTEGER :: handle
113 : LOGICAL :: pao_is_done
114 : TYPE(ls_scf_env_type), POINTER :: ls_scf_env
115 :
116 596 : CALL timeset(routineN, handle)
117 596 : CALL get_qs_env(qs_env, ls_scf_env=ls_scf_env)
118 596 : CALL pao_optimization_start(qs_env, ls_scf_env)
119 :
120 596 : pao_is_done = .FALSE.
121 1410 : DO WHILE (.NOT. pao_is_done)
122 814 : CALL ls_scf_init_scf(qs_env, ls_scf_env)
123 814 : CALL pao_update(qs_env, ls_scf_env, pao_is_done)
124 814 : CALL ls_scf_main(qs_env, ls_scf_env)
125 814 : CALL pao_post_scf(qs_env, ls_scf_env, pao_is_done)
126 814 : CALL ls_scf_post(qs_env, ls_scf_env)
127 : END DO
128 :
129 596 : CALL pao_optimization_end(ls_scf_env)
130 :
131 596 : CALL timestop(handle)
132 :
133 596 : END SUBROUTINE ls_scf
134 :
135 : ! **************************************************************************************************
136 : !> \brief initialization needed for scf
137 : !> \param qs_env ...
138 : !> \param ls_scf_env ...
139 : !> \par History
140 : !> 2010.10 created [Joost VandeVondele]
141 : !> \author Joost VandeVondele
142 : ! **************************************************************************************************
143 814 : SUBROUTINE ls_scf_init_scf(qs_env, ls_scf_env)
144 : TYPE(qs_environment_type), POINTER :: qs_env
145 : TYPE(ls_scf_env_type) :: ls_scf_env
146 :
147 : CHARACTER(len=*), PARAMETER :: routineN = 'ls_scf_init_scf'
148 :
149 : INTEGER :: handle, ispin, nspin, unit_nr
150 : TYPE(cp_logger_type), POINTER :: logger
151 814 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_s, matrix_w
152 : TYPE(dft_control_type), POINTER :: dft_control
153 814 : TYPE(molecule_type), DIMENSION(:), POINTER :: molecule_set
154 : TYPE(qs_ks_env_type), POINTER :: ks_env
155 : TYPE(section_vals_type), POINTER :: input
156 :
157 814 : CALL timeset(routineN, handle)
158 :
159 : ! get a useful output_unit
160 814 : logger => cp_get_default_logger()
161 814 : IF (logger%para_env%is_source()) THEN
162 407 : unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
163 : ELSE
164 : unit_nr = -1
165 : END IF
166 :
167 : ! get basic quantities from the qs_env
168 : CALL get_qs_env(qs_env, nelectron_total=ls_scf_env%nelectron_total, &
169 : matrix_s=matrix_s, &
170 : matrix_w=matrix_w, &
171 : ks_env=ks_env, &
172 : dft_control=dft_control, &
173 : molecule_set=molecule_set, &
174 : input=input, &
175 : has_unit_metric=ls_scf_env%has_unit_metric, &
176 : para_env=ls_scf_env%para_env, &
177 814 : nelectron_spin=ls_scf_env%nelectron_spin)
178 :
179 : ! needs forces ? There might be a better way to flag this
180 814 : ls_scf_env%calculate_forces = ASSOCIATED(matrix_w)
181 :
182 : ! some basic initialization of the QS side of things
183 814 : CALL ls_scf_init_qs(qs_env)
184 :
185 : ! create the matrix template for use in the ls procedures
186 : CALL matrix_ls_create(matrix_ls=ls_scf_env%matrix_s, matrix_qs=matrix_s(1)%matrix, &
187 814 : ls_mstruct=ls_scf_env%ls_mstruct)
188 :
189 814 : nspin = ls_scf_env%nspins
190 814 : IF (ALLOCATED(ls_scf_env%matrix_p)) THEN
191 966 : DO ispin = 1, SIZE(ls_scf_env%matrix_p)
192 966 : CALL dbcsr_release(ls_scf_env%matrix_p(ispin))
193 : END DO
194 : ELSE
195 1350 : ALLOCATE (ls_scf_env%matrix_p(nspin))
196 : END IF
197 :
198 1648 : DO ispin = 1, nspin
199 : CALL dbcsr_create(ls_scf_env%matrix_p(ispin), template=ls_scf_env%matrix_s, &
200 1648 : matrix_type=dbcsr_type_no_symmetry)
201 : END DO
202 :
203 3276 : ALLOCATE (ls_scf_env%matrix_ks(nspin))
204 1648 : DO ispin = 1, nspin
205 : CALL dbcsr_create(ls_scf_env%matrix_ks(ispin), template=ls_scf_env%matrix_s, &
206 1648 : matrix_type=dbcsr_type_no_symmetry)
207 : END DO
208 :
209 : ! set up matrix S, and needed functions of S
210 814 : CALL ls_scf_init_matrix_s(matrix_s(1)%matrix, ls_scf_env)
211 :
212 : ! get the initial guess for the SCF
213 814 : CALL ls_scf_initial_guess(qs_env, ls_scf_env)
214 :
215 814 : IF (ls_scf_env%do_rho_mixing) THEN
216 2 : CALL rho_mixing_ls_init(qs_env, ls_scf_env)
217 : END IF
218 :
219 814 : IF (ls_scf_env%do_pexsi) THEN
220 14 : CALL pexsi_init_scf(ks_env, ls_scf_env%pexsi, matrix_s(1)%matrix)
221 : END IF
222 :
223 814 : IF (qs_env%do_transport) THEN
224 0 : CALL transport_initialize(ks_env, qs_env%transport_env, matrix_s(1)%matrix)
225 : END IF
226 :
227 814 : CALL timestop(handle)
228 :
229 814 : END SUBROUTINE ls_scf_init_scf
230 :
231 : ! **************************************************************************************************
232 : !> \brief deal with the scf initial guess
233 : !> \param qs_env ...
234 : !> \param ls_scf_env ...
235 : !> \par History
236 : !> 2012.11 created [Joost VandeVondele]
237 : !> \author Joost VandeVondele
238 : ! **************************************************************************************************
239 1132 : SUBROUTINE ls_scf_initial_guess(qs_env, ls_scf_env)
240 : TYPE(qs_environment_type), POINTER :: qs_env
241 : TYPE(ls_scf_env_type) :: ls_scf_env
242 :
243 : CHARACTER(len=*), PARAMETER :: routineN = 'ls_scf_initial_guess'
244 : INTEGER, PARAMETER :: aspc_guess = 2, atomic_guess = 1, &
245 : restart_guess = 3
246 :
247 : CHARACTER(LEN=default_path_length) :: file_name, project_name
248 : INTEGER :: handle, iaspc, initial_guess_type, &
249 : ispin, istore, naspc, unit_nr
250 : REAL(KIND=dp) :: alpha, cs_pos
251 : TYPE(cp_logger_type), POINTER :: logger
252 : TYPE(dbcsr_distribution_type) :: dist
253 : TYPE(dbcsr_type) :: matrix_tmp1
254 :
255 496 : IF (ls_scf_env%do_pao) RETURN ! pao has its own initial guess
256 :
257 318 : CALL timeset(routineN, handle)
258 :
259 : ! get a useful output_unit
260 318 : logger => cp_get_default_logger()
261 318 : IF (logger%para_env%is_source()) THEN
262 159 : unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
263 : ELSE
264 : unit_nr = -1
265 : END IF
266 :
267 159 : IF (unit_nr > 0) WRITE (unit_nr, '()')
268 : ! if there is no history go for the atomic guess, otherwise extrapolate the dm history
269 318 : IF (ls_scf_env%scf_history%istore == 0) THEN
270 246 : IF (ls_scf_env%restart_read) THEN
271 : initial_guess_type = restart_guess
272 : ELSE
273 : initial_guess_type = atomic_guess
274 : END IF
275 : ELSE
276 : initial_guess_type = aspc_guess
277 : END IF
278 :
279 : ! how to get the initial guess
280 : SELECT CASE (initial_guess_type)
281 : CASE (atomic_guess)
282 242 : CALL ls_scf_qs_atomic_guess(qs_env, ls_scf_env%energy_init)
283 : CASE (restart_guess)
284 4 : project_name = logger%iter_info%project_name
285 8 : DO ispin = 1, SIZE(ls_scf_env%matrix_p)
286 4 : WRITE (file_name, '(A,I0,A)') TRIM(project_name)//"_LS_DM_SPIN_", ispin, "_RESTART.dm"
287 4 : CALL dbcsr_get_info(ls_scf_env%matrix_p(1), distribution=dist)
288 4 : CALL dbcsr_binary_read(file_name, distribution=dist, matrix_new=ls_scf_env%matrix_p(ispin))
289 4 : cs_pos = dbcsr_checksum(ls_scf_env%matrix_p(ispin), pos=.TRUE.)
290 12 : IF (unit_nr > 0) THEN
291 2 : WRITE (unit_nr, '(T2,A,E20.8)') "Read restart DM "//TRIM(file_name)//" with checksum: ", cs_pos
292 : END IF
293 : END DO
294 :
295 : ! directly go to computing the corresponding energy and ks matrix
296 4 : CALL ls_scf_dm_to_ks(qs_env, ls_scf_env, ls_scf_env%energy_init, iscf=0)
297 : CASE (aspc_guess)
298 72 : CALL cite_reference(Kolafa2004)
299 72 : CALL cite_reference(Kuhne2007)
300 72 : naspc = MIN(ls_scf_env%scf_history%istore, ls_scf_env%scf_history%nstore)
301 150 : DO ispin = 1, SIZE(ls_scf_env%matrix_p)
302 : ! actual extrapolation
303 78 : CALL dbcsr_set(ls_scf_env%matrix_p(ispin), 0.0_dp)
304 312 : DO iaspc = 1, naspc
305 : alpha = (-1.0_dp)**(iaspc + 1)*REAL(iaspc, KIND=dp)* &
306 162 : binomial(2*naspc, naspc - iaspc)/binomial(2*naspc - 2, naspc - 1)
307 162 : istore = MOD(ls_scf_env%scf_history%istore - iaspc, ls_scf_env%scf_history%nstore) + 1
308 240 : CALL dbcsr_add(ls_scf_env%matrix_p(ispin), ls_scf_env%scf_history%matrix(ispin, istore), 1.0_dp, alpha)
309 : END DO
310 : END DO
311 : END SELECT
312 :
313 : ! which cases need getting purified and non-orthogonal ?
314 72 : SELECT CASE (initial_guess_type)
315 : CASE (atomic_guess, restart_guess)
316 : ! do nothing
317 : CASE (aspc_guess)
318 : ! purification can't be done on the pexsi matrix, which is not necessarily idempotent,
319 : ! and not stored in an ortho basis form
320 72 : IF (.NOT. (ls_scf_env%do_pexsi)) THEN
321 138 : DO ispin = 1, SIZE(ls_scf_env%matrix_p)
322 : ! linear combination of P's is not idempotent. A bit of McWeeny is needed to ensure it is again
323 72 : IF (SIZE(ls_scf_env%matrix_p) == 1) CALL dbcsr_scale(ls_scf_env%matrix_p(ispin), 0.5_dp)
324 : ! to ensure that noisy blocks do not build up during MD (in particular with curvy) filter that guess a bit more
325 72 : CALL dbcsr_filter(ls_scf_env%matrix_p(ispin), ls_scf_env%eps_filter**(2.0_dp/3.0_dp))
326 72 : CALL purify_mcweeny(ls_scf_env%matrix_p(ispin:ispin), ls_scf_env%eps_filter, 3)
327 72 : IF (SIZE(ls_scf_env%matrix_p) == 1) CALL dbcsr_scale(ls_scf_env%matrix_p(ispin), 2.0_dp)
328 :
329 138 : IF (ls_scf_env%use_s_sqrt) THEN
330 : ! need to get P in the non-orthogonal basis if it was stored differently
331 : CALL dbcsr_create(matrix_tmp1, template=ls_scf_env%matrix_s, &
332 72 : matrix_type=dbcsr_type_no_symmetry)
333 : CALL dbcsr_multiply("N", "N", 1.0_dp, ls_scf_env%matrix_s_sqrt_inv, ls_scf_env%matrix_p(ispin), &
334 72 : 0.0_dp, matrix_tmp1, filter_eps=ls_scf_env%eps_filter)
335 : CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp1, ls_scf_env%matrix_s_sqrt_inv, &
336 : 0.0_dp, ls_scf_env%matrix_p(ispin), &
337 72 : filter_eps=ls_scf_env%eps_filter)
338 72 : CALL dbcsr_release(matrix_tmp1)
339 :
340 72 : IF (ls_scf_env%has_s_preconditioner) THEN
341 : CALL apply_matrix_preconditioner(ls_scf_env%matrix_p(ispin), "forward", &
342 66 : ls_scf_env%matrix_bs_sqrt, ls_scf_env%matrix_bs_sqrt_inv)
343 : END IF
344 : END IF
345 : END DO
346 : END IF
347 :
348 : ! compute corresponding energy and ks matrix
349 390 : CALL ls_scf_dm_to_ks(qs_env, ls_scf_env, ls_scf_env%energy_init, iscf=0)
350 : END SELECT
351 :
352 318 : IF (unit_nr > 0) THEN
353 159 : WRITE (unit_nr, '(T2,A,F20.9)') "Energy with the initial guess:", ls_scf_env%energy_init
354 159 : WRITE (unit_nr, '()')
355 : END IF
356 :
357 318 : CALL timestop(handle)
358 :
359 814 : END SUBROUTINE ls_scf_initial_guess
360 :
361 : ! **************************************************************************************************
362 : !> \brief store a history of matrices for later use in ls_scf_initial_guess
363 : !> \param ls_scf_env ...
364 : !> \par History
365 : !> 2012.11 created [Joost VandeVondele]
366 : !> \author Joost VandeVondele
367 : ! **************************************************************************************************
368 318 : SUBROUTINE ls_scf_store_result(ls_scf_env)
369 : TYPE(ls_scf_env_type) :: ls_scf_env
370 :
371 : CHARACTER(len=*), PARAMETER :: routineN = 'ls_scf_store_result'
372 :
373 : CHARACTER(LEN=default_path_length) :: file_name, project_name
374 : INTEGER :: handle, ispin, istore, unit_nr
375 : REAL(KIND=dp) :: cs_pos
376 : TYPE(cp_logger_type), POINTER :: logger
377 : TYPE(dbcsr_type) :: matrix_tmp1
378 :
379 318 : CALL timeset(routineN, handle)
380 :
381 : ! get a useful output_unit
382 318 : logger => cp_get_default_logger()
383 318 : IF (logger%para_env%is_source()) THEN
384 159 : unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
385 : ELSE
386 : unit_nr = -1
387 : END IF
388 :
389 318 : IF (ls_scf_env%restart_write) THEN
390 12 : DO ispin = 1, SIZE(ls_scf_env%matrix_p)
391 6 : project_name = logger%iter_info%project_name
392 6 : WRITE (file_name, '(A,I0,A)') TRIM(project_name)//"_LS_DM_SPIN_", ispin, "_RESTART.dm"
393 6 : cs_pos = dbcsr_checksum(ls_scf_env%matrix_p(ispin), pos=.TRUE.)
394 6 : IF (unit_nr > 0) THEN
395 3 : WRITE (unit_nr, '(T2,A,E20.8)') "Writing restart DM "//TRIM(file_name)//" with checksum: ", cs_pos
396 : END IF
397 6 : IF (ls_scf_env%do_transport .OR. ls_scf_env%do_pexsi) THEN
398 0 : IF (unit_nr > 0) THEN
399 0 : WRITE (unit_nr, '(T6,A)') "The restart DM "//TRIM(file_name)//" has the sparsity of S, therefore,"
400 0 : WRITE (unit_nr, '(T6,A)') "not compatible with methods that require a full DM! "
401 : END IF
402 : END IF
403 12 : CALL dbcsr_binary_write(ls_scf_env%matrix_p(ispin), file_name)
404 : END DO
405 : END IF
406 :
407 318 : IF (ls_scf_env%scf_history%nstore > 0) THEN
408 310 : ls_scf_env%scf_history%istore = ls_scf_env%scf_history%istore + 1
409 640 : DO ispin = 1, SIZE(ls_scf_env%matrix_p)
410 330 : istore = MOD(ls_scf_env%scf_history%istore - 1, ls_scf_env%scf_history%nstore) + 1
411 330 : CALL dbcsr_copy(ls_scf_env%scf_history%matrix(ispin, istore), ls_scf_env%matrix_p(ispin))
412 :
413 : ! if we have the sqrt around, we use it to go to the orthogonal basis
414 640 : IF (ls_scf_env%use_s_sqrt) THEN
415 : ! usually sqrt(S) * P * sqrt(S) should be available, or could be stored at least,
416 : ! so that the next multiplications could be saved.
417 : CALL dbcsr_create(matrix_tmp1, template=ls_scf_env%matrix_s, &
418 312 : matrix_type=dbcsr_type_no_symmetry)
419 :
420 312 : IF (ls_scf_env%has_s_preconditioner) THEN
421 : CALL apply_matrix_preconditioner(ls_scf_env%scf_history%matrix(ispin, istore), "backward", &
422 266 : ls_scf_env%matrix_bs_sqrt, ls_scf_env%matrix_bs_sqrt_inv)
423 : END IF
424 : CALL dbcsr_multiply("N", "N", 1.0_dp, ls_scf_env%matrix_s_sqrt, ls_scf_env%scf_history%matrix(ispin, istore), &
425 312 : 0.0_dp, matrix_tmp1, filter_eps=ls_scf_env%eps_filter)
426 : CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp1, ls_scf_env%matrix_s_sqrt, &
427 : 0.0_dp, ls_scf_env%scf_history%matrix(ispin, istore), &
428 312 : filter_eps=ls_scf_env%eps_filter)
429 312 : CALL dbcsr_release(matrix_tmp1)
430 : END IF
431 :
432 : END DO
433 : END IF
434 :
435 318 : CALL timestop(handle)
436 :
437 318 : END SUBROUTINE ls_scf_store_result
438 :
439 : ! **************************************************************************************************
440 : !> \brief Main SCF routine. Can we keep it clean ?
441 : !> \param qs_env ...
442 : !> \param ls_scf_env ...
443 : !> \par History
444 : !> 2010.10 created [Joost VandeVondele]
445 : !> \author Joost VandeVondele
446 : ! **************************************************************************************************
447 814 : SUBROUTINE ls_scf_main(qs_env, ls_scf_env)
448 : TYPE(qs_environment_type), POINTER :: qs_env
449 : TYPE(ls_scf_env_type) :: ls_scf_env
450 :
451 : CHARACTER(len=*), PARAMETER :: routineN = 'ls_scf_main'
452 :
453 : INTEGER :: handle, iscf, ispin, &
454 : nelectron_spin_real, nmixing, nspin, &
455 : unit_nr
456 : LOGICAL :: check_convergence, diis_step, do_transport, extra_scf, maxscf_reached, &
457 : scf_converged, should_stop, transm_maxscf_reached, transm_scf_converged
458 : REAL(KIND=dp) :: energy_diff, energy_new, energy_old, &
459 : eps_diis, t1, t2
460 : TYPE(cp_logger_type), POINTER :: logger
461 814 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks, matrix_s
462 814 : TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:) :: matrix_ks_deviation, matrix_mixing_old
463 : TYPE(energy_correction_type), POINTER :: ec_env
464 : TYPE(qs_diis_buffer_type_sparse), POINTER :: diis_buffer
465 : TYPE(transport_env_type), POINTER :: transport_env
466 :
467 814 : CALL timeset(routineN, handle)
468 :
469 : ! get a useful output_unit
470 814 : logger => cp_get_default_logger()
471 814 : IF (logger%para_env%is_source()) THEN
472 407 : unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
473 : ELSE
474 407 : unit_nr = -1
475 : END IF
476 :
477 814 : nspin = ls_scf_env%nspins
478 :
479 : ! old quantities, useful for mixing
480 4924 : ALLOCATE (matrix_mixing_old(nspin), matrix_ks_deviation(nspin))
481 1648 : DO ispin = 1, nspin
482 834 : CALL dbcsr_create(matrix_mixing_old(ispin), template=ls_scf_env%matrix_ks(ispin))
483 :
484 834 : CALL dbcsr_create(matrix_ks_deviation(ispin), template=ls_scf_env%matrix_ks(ispin))
485 1648 : CALL dbcsr_set(matrix_ks_deviation(ispin), 0.0_dp)
486 : END DO
487 2442 : ls_scf_env%homo_spin(:) = 0.0_dp
488 2442 : ls_scf_env%lumo_spin(:) = 0.0_dp
489 :
490 814 : transm_scf_converged = .FALSE.
491 814 : transm_maxscf_reached = .FALSE.
492 :
493 814 : energy_old = 0.0_dp
494 814 : IF (ls_scf_env%scf_history%istore > 0) energy_old = ls_scf_env%energy_init
495 814 : check_convergence = .TRUE.
496 814 : iscf = 0
497 814 : IF (ls_scf_env%ls_diis) THEN
498 4 : diis_step = .FALSE.
499 4 : eps_diis = ls_scf_env%eps_diis
500 4 : nmixing = ls_scf_env%nmixing
501 : NULLIFY (diis_buffer)
502 4 : ALLOCATE (diis_buffer)
503 : CALL qs_diis_b_create_sparse(diis_buffer, &
504 4 : nbuffer=ls_scf_env%max_diis)
505 4 : CALL qs_diis_b_clear_sparse(diis_buffer)
506 4 : CALL get_qs_env(qs_env, matrix_s=matrix_s)
507 : END IF
508 :
509 814 : CALL get_qs_env(qs_env, transport_env=transport_env, do_transport=do_transport)
510 :
511 : ! the real SCF loop
512 2846 : DO
513 :
514 : ! check on max SCF or timing/exit
515 2846 : CALL external_control(should_stop, "SCF", start_time=qs_env%start_time, target_time=qs_env%target_time)
516 2846 : IF (do_transport) THEN
517 0 : maxscf_reached = should_stop .OR. iscf >= ls_scf_env%max_scf
518 : ! one extra scf step for post-processing in transmission calculations
519 0 : IF (transport_env%params%method .EQ. transport_transmission) THEN
520 0 : IF (transm_maxscf_reached) THEN
521 0 : IF (unit_nr > 0) WRITE (unit_nr, '(T2,A)') "SCF not converged! "
522 : EXIT
523 : END IF
524 : transm_maxscf_reached = maxscf_reached
525 : ELSE
526 0 : IF (maxscf_reached) THEN
527 0 : IF (unit_nr > 0) WRITE (unit_nr, '(T2,A)') "SCF not converged! "
528 : EXIT
529 : END IF
530 : END IF
531 : ELSE
532 2846 : IF (should_stop .OR. iscf >= ls_scf_env%max_scf) THEN
533 48 : IF (unit_nr > 0) WRITE (unit_nr, '(T2,A)') "SCF not converged! "
534 : ! Skip Harris functional calculation if ground-state is NOT converged
535 48 : IF (qs_env%energy_correction) THEN
536 0 : CALL get_qs_env(qs_env, ec_env=ec_env)
537 0 : IF (ec_env%skip_ec) ec_env%do_skip = .TRUE.
538 : END IF
539 : EXIT
540 : END IF
541 : END IF
542 :
543 2798 : t1 = m_walltime()
544 2798 : iscf = iscf + 1
545 :
546 : ! first get a copy of the current KS matrix
547 2798 : CALL get_qs_env(qs_env, matrix_ks=matrix_ks)
548 5816 : DO ispin = 1, nspin
549 : CALL matrix_qs_to_ls(ls_scf_env%matrix_ks(ispin), matrix_ks(ispin)%matrix, &
550 3018 : ls_scf_env%ls_mstruct, covariant=.TRUE.)
551 3018 : IF (ls_scf_env%has_s_preconditioner) THEN
552 : CALL apply_matrix_preconditioner(ls_scf_env%matrix_ks(ispin), "forward", &
553 1232 : ls_scf_env%matrix_bs_sqrt, ls_scf_env%matrix_bs_sqrt_inv)
554 : END IF
555 5816 : CALL dbcsr_filter(ls_scf_env%matrix_ks(ispin), ls_scf_env%eps_filter)
556 : END DO
557 : ! run curvy steps if required. Needs an idempotent DM (either perification or restart)
558 2798 : IF ((iscf > 1 .OR. ls_scf_env%scf_history%istore > 0) .AND. ls_scf_env%curvy_steps) THEN
559 90 : CALL dm_ls_curvy_optimization(ls_scf_env, energy_old, check_convergence)
560 : ELSE
561 : ! turn the KS matrix in a density matrix
562 5624 : DO ispin = 1, nspin
563 2916 : IF (ls_scf_env%do_rho_mixing) THEN
564 36 : CALL dbcsr_copy(matrix_mixing_old(ispin), ls_scf_env%matrix_ks(ispin))
565 : ELSE
566 2880 : IF (iscf == 1) THEN
567 : ! initialize the mixing matrix with the current state if needed
568 822 : CALL dbcsr_copy(matrix_mixing_old(ispin), ls_scf_env%matrix_ks(ispin))
569 : ELSE
570 2058 : IF (ls_scf_env%ls_diis) THEN ! ------- IF-DIIS+MIX--- START
571 28 : IF (diis_step .AND. (iscf - 1) .GE. ls_scf_env%iter_ini_diis) THEN
572 22 : IF (unit_nr > 0) THEN
573 : WRITE (unit_nr, '(A61)') &
574 11 : '*************************************************************'
575 : WRITE (unit_nr, '(A50,2(I3,A1),L1,A1)') &
576 11 : " Using DIIS mixed KS: (iscf,INI_DIIS,DIIS_STEP)=(", &
577 22 : iscf, ",", ls_scf_env%iter_ini_diis, ",", diis_step, ")"
578 : WRITE (unit_nr, '(A52)') &
579 11 : " KS_nw= DIIS-Linear-Combination-Previous KS matrices"
580 : WRITE (unit_nr, '(61A)') &
581 11 : "*************************************************************"
582 : END IF
583 : CALL dbcsr_copy(matrix_mixing_old(ispin), & ! out
584 22 : ls_scf_env%matrix_ks(ispin)) ! in
585 : ELSE
586 6 : IF (unit_nr > 0) THEN
587 : WRITE (unit_nr, '(A57)') &
588 3 : "*********************************************************"
589 : WRITE (unit_nr, '(A23,F5.3,A25,I3)') &
590 3 : " Using MIXING_FRACTION=", ls_scf_env%mixing_fraction, &
591 6 : " to mix KS matrix: iscf=", iscf
592 : WRITE (unit_nr, '(A7,F5.3,A6,F5.3,A7)') &
593 3 : " KS_nw=", ls_scf_env%mixing_fraction, "*KS + ", &
594 6 : 1.0_dp - ls_scf_env%mixing_fraction, "*KS_old"
595 : WRITE (unit_nr, '(A57)') &
596 3 : "*********************************************************"
597 : END IF
598 : ! perform the mixing of ks matrices
599 : CALL dbcsr_add(matrix_mixing_old(ispin), &
600 : ls_scf_env%matrix_ks(ispin), &
601 : 1.0_dp - ls_scf_env%mixing_fraction, &
602 6 : ls_scf_env%mixing_fraction)
603 : END IF
604 : ELSE ! otherwise
605 2030 : IF (unit_nr > 0) THEN
606 : WRITE (unit_nr, '(A57)') &
607 1015 : "*********************************************************"
608 : WRITE (unit_nr, '(A23,F5.3,A25,I3)') &
609 1015 : " Using MIXING_FRACTION=", ls_scf_env%mixing_fraction, &
610 2030 : " to mix KS matrix: iscf=", iscf
611 : WRITE (unit_nr, '(A7,F5.3,A6,F5.3,A7)') &
612 1015 : " KS_nw=", ls_scf_env%mixing_fraction, "*KS + ", &
613 2030 : 1.0_dp - ls_scf_env%mixing_fraction, "*KS_old"
614 : WRITE (unit_nr, '(A57)') &
615 1015 : "*********************************************************"
616 : END IF
617 : ! perform the mixing of ks matrices
618 : CALL dbcsr_add(matrix_mixing_old(ispin), &
619 : ls_scf_env%matrix_ks(ispin), &
620 : 1.0_dp - ls_scf_env%mixing_fraction, &
621 2030 : ls_scf_env%mixing_fraction)
622 : END IF ! ------- IF-DIIS+MIX--- END
623 : END IF
624 : END IF
625 :
626 : ! compute the density matrix that matches it
627 : ! we need the proper number of states
628 2916 : nelectron_spin_real = ls_scf_env%nelectron_spin(ispin)
629 2916 : IF (ls_scf_env%nspins == 1) nelectron_spin_real = nelectron_spin_real/2
630 :
631 2916 : IF (do_transport) THEN
632 0 : IF (ls_scf_env%has_s_preconditioner) &
633 0 : CPABORT("NOT YET IMPLEMENTED with S preconditioner. ")
634 0 : IF (ls_scf_env%ls_mstruct%cluster_type .NE. ls_cluster_atomic) &
635 0 : CPABORT("NOT YET IMPLEMENTED with molecular clustering. ")
636 :
637 0 : extra_scf = maxscf_reached .OR. scf_converged
638 : ! get the current Kohn-Sham matrix (ks) and return matrix_p evaluated using an external C routine
639 : CALL external_scf_method(transport_env, ls_scf_env%matrix_s, matrix_mixing_old(ispin), &
640 : ls_scf_env%matrix_p(ispin), nelectron_spin_real, ls_scf_env%natoms, &
641 0 : energy_diff, iscf, extra_scf)
642 :
643 : ELSE
644 3824 : SELECT CASE (ls_scf_env%purification_method)
645 : CASE (ls_scf_sign)
646 : CALL density_matrix_sign(ls_scf_env%matrix_p(ispin), ls_scf_env%mu_spin(ispin), ls_scf_env%fixed_mu, &
647 : ls_scf_env%sign_method, ls_scf_env%sign_order, matrix_mixing_old(ispin), &
648 : ls_scf_env%matrix_s, ls_scf_env%matrix_s_inv, nelectron_spin_real, &
649 : ls_scf_env%eps_filter, ls_scf_env%sign_symmetric, ls_scf_env%submatrix_sign_method, &
650 908 : ls_scf_env%matrix_s_sqrt_inv)
651 : CASE (ls_scf_tc2)
652 : CALL density_matrix_tc2(ls_scf_env%matrix_p(ispin), matrix_mixing_old(ispin), ls_scf_env%matrix_s_sqrt_inv, &
653 : nelectron_spin_real, ls_scf_env%eps_filter, ls_scf_env%homo_spin(ispin), &
654 : ls_scf_env%lumo_spin(ispin), non_monotonic=ls_scf_env%non_monotonic, &
655 48 : eps_lanczos=ls_scf_env%eps_lanczos, max_iter_lanczos=ls_scf_env%max_iter_lanczos)
656 : CASE (ls_scf_trs4)
657 : CALL density_matrix_trs4(ls_scf_env%matrix_p(ispin), matrix_mixing_old(ispin), ls_scf_env%matrix_s_sqrt_inv, &
658 : nelectron_spin_real, ls_scf_env%eps_filter, ls_scf_env%homo_spin(ispin), &
659 : ls_scf_env%lumo_spin(ispin), ls_scf_env%mu_spin(ispin), &
660 : dynamic_threshold=ls_scf_env%dynamic_threshold, &
661 : matrix_ks_deviation=matrix_ks_deviation(ispin), &
662 1866 : eps_lanczos=ls_scf_env%eps_lanczos, max_iter_lanczos=ls_scf_env%max_iter_lanczos)
663 : CASE (ls_scf_pexsi)
664 94 : IF (ls_scf_env%has_s_preconditioner) &
665 0 : CPABORT("S preconditioning not implemented in combination with the PEXSI library. ")
666 94 : IF (ls_scf_env%ls_mstruct%cluster_type .NE. ls_cluster_atomic) &
667 : CALL cp_abort(__LOCATION__, &
668 0 : "Molecular clustering not implemented in combination with the PEXSI library. ")
669 : CALL density_matrix_pexsi(ls_scf_env%pexsi, ls_scf_env%matrix_p(ispin), ls_scf_env%pexsi%matrix_w(ispin), &
670 : ls_scf_env%pexsi%kTS(ispin), matrix_mixing_old(ispin), ls_scf_env%matrix_s, &
671 3010 : nelectron_spin_real, ls_scf_env%mu_spin(ispin), iscf, ispin)
672 : END SELECT
673 : END IF
674 :
675 2916 : IF (ls_scf_env%has_s_preconditioner) THEN
676 : CALL apply_matrix_preconditioner(ls_scf_env%matrix_p(ispin), "forward", &
677 1232 : ls_scf_env%matrix_bs_sqrt, ls_scf_env%matrix_bs_sqrt_inv)
678 : END IF
679 2916 : CALL dbcsr_filter(ls_scf_env%matrix_p(ispin), ls_scf_env%eps_filter)
680 :
681 5624 : IF (ls_scf_env%nspins == 1) CALL dbcsr_scale(ls_scf_env%matrix_p(ispin), 2.0_dp)
682 :
683 : END DO
684 : END IF
685 :
686 : ! compute the corresponding new energy KS matrix and new energy
687 2798 : CALL ls_scf_dm_to_ks(qs_env, ls_scf_env, energy_new, iscf)
688 :
689 2798 : IF (ls_scf_env%do_pexsi) THEN
690 94 : CALL pexsi_to_qs(ls_scf_env, qs_env, kTS=ls_scf_env%pexsi%kTS)
691 : END IF
692 :
693 : ! report current SCF loop
694 2798 : energy_diff = energy_new - energy_old
695 2798 : energy_old = energy_new
696 :
697 2798 : t2 = m_walltime()
698 2798 : IF (unit_nr > 0) THEN
699 1399 : WRITE (unit_nr, *)
700 1399 : WRITE (unit_nr, '(T2,A,I6,F20.9,F20.9,F12.6)') "SCF", iscf, energy_new, energy_diff, t2 - t1
701 1399 : WRITE (unit_nr, *)
702 1399 : CALL m_flush(unit_nr)
703 : END IF
704 :
705 2798 : IF (do_transport) THEN
706 0 : scf_converged = check_convergence .AND. ABS(energy_diff) < ls_scf_env%eps_scf*ls_scf_env%nelectron_total
707 : ! one extra scf step for post-processing in transmission calculations
708 0 : IF (transport_env%params%method .EQ. transport_transmission) THEN
709 0 : IF (transm_scf_converged) EXIT
710 : transm_scf_converged = scf_converged
711 : ELSE
712 0 : IF (scf_converged) THEN
713 0 : IF (unit_nr > 0) WRITE (unit_nr, '(/,T2,A,I5,A/)') "SCF run converged in ", iscf, " steps."
714 : EXIT
715 : END IF
716 : END IF
717 : ELSE
718 : ! exit criterion on the energy only for the time being
719 2798 : IF (check_convergence .AND. ABS(energy_diff) < ls_scf_env%eps_scf*ls_scf_env%nelectron_total) THEN
720 766 : IF (unit_nr > 0) WRITE (unit_nr, '(/,T2,A,I5,A/)') "SCF run converged in ", iscf, " steps."
721 : ! Skip Harris functional calculation if ground-state is NOT converged
722 766 : IF (qs_env%energy_correction) THEN
723 20 : CALL get_qs_env(qs_env, ec_env=ec_env)
724 20 : IF (ec_env%skip_ec) ec_env%do_skip = .FALSE.
725 : END IF
726 : EXIT
727 : END IF
728 : END IF
729 :
730 2032 : IF (ls_scf_env%ls_diis) THEN
731 : ! diis_buffer, buffer with 1) Kohn-Sham history matrix,
732 : ! 2) KS error history matrix (f=KPS-SPK),
733 : ! 3) B matrix (for finding DIIS weighting coefficients)
734 : CALL qs_diis_b_step_4lscf(diis_buffer, qs_env, ls_scf_env, unit_nr, &
735 : iscf, diis_step, eps_diis, nmixing, matrix_s(1)%matrix, &
736 18 : ls_scf_env%eps_filter)
737 : END IF
738 :
739 2032 : IF (ls_scf_env%do_pexsi) THEN
740 : CALL pexsi_set_convergence_tolerance(ls_scf_env%pexsi, energy_diff, &
741 : ls_scf_env%eps_scf*ls_scf_env%nelectron_total, &
742 : ! initialize in second scf step of first SCF cycle:
743 : (iscf .EQ. 2) .AND. (ls_scf_env%scf_history%istore .EQ. 0), &
744 156 : check_convergence)
745 : END IF
746 :
747 : END DO
748 :
749 : ! free storage
750 814 : IF (ls_scf_env%ls_diis) THEN
751 4 : CALL qs_diis_b_release_sparse(diis_buffer)
752 4 : DEALLOCATE (diis_buffer)
753 : END IF
754 1648 : DO ispin = 1, nspin
755 834 : CALL dbcsr_release(matrix_mixing_old(ispin))
756 1648 : CALL dbcsr_release(matrix_ks_deviation(ispin))
757 : END DO
758 814 : DEALLOCATE (matrix_mixing_old, matrix_ks_deviation)
759 :
760 814 : CALL timestop(handle)
761 :
762 814 : END SUBROUTINE ls_scf_main
763 :
764 : ! **************************************************************************************************
765 : !> \brief after SCF we have a density matrix, and the self consistent KS matrix
766 : !> analyze its properties.
767 : !> \param qs_env ...
768 : !> \param ls_scf_env ...
769 : !> \par History
770 : !> 2010.10 created [Joost VandeVondele]
771 : !> \author Joost VandeVondele
772 : ! **************************************************************************************************
773 814 : SUBROUTINE ls_scf_post(qs_env, ls_scf_env)
774 : TYPE(qs_environment_type), POINTER :: qs_env
775 : TYPE(ls_scf_env_type) :: ls_scf_env
776 :
777 : CHARACTER(len=*), PARAMETER :: routineN = 'ls_scf_post'
778 :
779 : INTEGER :: handle, ispin, unit_nr
780 : REAL(KIND=dp) :: occ
781 : TYPE(cp_logger_type), POINTER :: logger
782 814 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_w
783 : TYPE(dft_control_type), POINTER :: dft_control
784 :
785 814 : CALL timeset(routineN, handle)
786 :
787 814 : CALL get_qs_env(qs_env, dft_control=dft_control)
788 :
789 : ! get a useful output_unit
790 814 : logger => cp_get_default_logger()
791 814 : IF (logger%para_env%is_source()) THEN
792 407 : unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
793 : ELSE
794 407 : unit_nr = -1
795 : END IF
796 :
797 : ! store the matrix for a next scf run
798 814 : IF (.NOT. ls_scf_env%do_pao) &
799 318 : CALL ls_scf_store_result(ls_scf_env)
800 :
801 : ! write homo and lumo energy and occupation (if not already part of the output)
802 814 : IF (ls_scf_env%curvy_steps) THEN
803 18 : CALL post_scf_homo_lumo(ls_scf_env)
804 :
805 : ! always report P occ
806 18 : IF (unit_nr > 0) WRITE (unit_nr, *) ""
807 38 : DO ispin = 1, ls_scf_env%nspins
808 20 : occ = dbcsr_get_occupation(ls_scf_env%matrix_p(ispin))
809 38 : IF (unit_nr > 0) WRITE (unit_nr, '(T2,A,F20.12)') "Density matrix (P) occupation ", occ
810 : END DO
811 : END IF
812 :
813 : ! compute the matrix_w if associated
814 814 : IF (ls_scf_env%calculate_forces) THEN
815 172 : CALL get_qs_env(qs_env, matrix_w=matrix_w)
816 172 : CPASSERT(ASSOCIATED(matrix_w))
817 172 : IF (ls_scf_env%do_pexsi) THEN
818 8 : CALL pexsi_to_qs(ls_scf_env, qs_env, matrix_w=ls_scf_env%pexsi%matrix_w)
819 : ELSE
820 164 : CALL calculate_w_matrix_ls(matrix_w, ls_scf_env)
821 : END IF
822 : END IF
823 :
824 : ! compute properties
825 :
826 814 : IF (ls_scf_env%perform_mu_scan) CALL post_scf_mu_scan(ls_scf_env)
827 :
828 814 : IF (ls_scf_env%report_all_sparsities) CALL post_scf_sparsities(ls_scf_env)
829 :
830 814 : IF (dft_control%qs_control%dftb) THEN
831 44 : CALL scf_post_calculation_tb(qs_env, "DFTB", .TRUE.)
832 770 : ELSE IF (dft_control%qs_control%xtb) THEN
833 34 : CALL scf_post_calculation_tb(qs_env, "xTB", .TRUE.)
834 : ELSE
835 736 : CALL write_mo_free_results(qs_env)
836 : END IF
837 :
838 814 : IF (ls_scf_env%chebyshev%compute_chebyshev) CALL compute_chebyshev(qs_env, ls_scf_env)
839 :
840 814 : IF (.TRUE.) CALL post_scf_experiment()
841 :
842 814 : IF (dft_control%qs_control%dftb .OR. dft_control%qs_control%xtb) THEN
843 : !
844 : ELSE
845 736 : CALL qs_scf_post_moments(qs_env%input, logger, qs_env, unit_nr)
846 : END IF
847 :
848 : ! clean up used data
849 :
850 814 : CALL dbcsr_release(ls_scf_env%matrix_s)
851 814 : CALL deallocate_curvy_data(ls_scf_env%curvy_data)
852 :
853 814 : IF (ls_scf_env%has_s_preconditioner) THEN
854 260 : CALL dbcsr_release(ls_scf_env%matrix_bs_sqrt)
855 260 : CALL dbcsr_release(ls_scf_env%matrix_bs_sqrt_inv)
856 : END IF
857 :
858 814 : IF (ls_scf_env%needs_s_inv) THEN
859 798 : CALL dbcsr_release(ls_scf_env%matrix_s_inv)
860 : END IF
861 :
862 814 : IF (ls_scf_env%use_s_sqrt) THEN
863 796 : CALL dbcsr_release(ls_scf_env%matrix_s_sqrt)
864 796 : CALL dbcsr_release(ls_scf_env%matrix_s_sqrt_inv)
865 : END IF
866 :
867 1648 : DO ispin = 1, SIZE(ls_scf_env%matrix_ks)
868 1648 : CALL dbcsr_release(ls_scf_env%matrix_ks(ispin))
869 : END DO
870 814 : DEALLOCATE (ls_scf_env%matrix_ks)
871 :
872 814 : IF (ls_scf_env%do_pexsi) &
873 14 : CALL pexsi_finalize_scf(ls_scf_env%pexsi, ls_scf_env%mu_spin)
874 :
875 814 : CALL timestop(handle)
876 :
877 814 : END SUBROUTINE ls_scf_post
878 :
879 : ! **************************************************************************************************
880 : !> \brief Compute the HOMO LUMO energies post SCF
881 : !> \param ls_scf_env ...
882 : !> \par History
883 : !> 2013.06 created [Joost VandeVondele]
884 : !> \author Joost VandeVondele
885 : ! **************************************************************************************************
886 18 : SUBROUTINE post_scf_homo_lumo(ls_scf_env)
887 : TYPE(ls_scf_env_type) :: ls_scf_env
888 :
889 : CHARACTER(len=*), PARAMETER :: routineN = 'post_scf_homo_lumo'
890 :
891 : INTEGER :: handle, ispin, nspin, unit_nr
892 : LOGICAL :: converged
893 : REAL(KIND=dp) :: eps_max, eps_min, homo, lumo
894 : TYPE(cp_logger_type), POINTER :: logger
895 : TYPE(dbcsr_type) :: matrix_k, matrix_p, matrix_tmp
896 :
897 18 : CALL timeset(routineN, handle)
898 :
899 : ! get a useful output_unit
900 18 : logger => cp_get_default_logger()
901 18 : IF (logger%para_env%is_source()) THEN
902 9 : unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
903 : ELSE
904 9 : unit_nr = -1
905 : END IF
906 :
907 18 : IF (unit_nr > 0) WRITE (unit_nr, '(T2,A)') ""
908 :
909 : ! TODO: remove these limitations
910 18 : CPASSERT(.NOT. ls_scf_env%has_s_preconditioner)
911 18 : CPASSERT(ls_scf_env%use_s_sqrt)
912 :
913 18 : nspin = ls_scf_env%nspins
914 :
915 18 : CALL dbcsr_create(matrix_p, template=ls_scf_env%matrix_p(1), matrix_type=dbcsr_type_no_symmetry)
916 :
917 18 : CALL dbcsr_create(matrix_k, template=ls_scf_env%matrix_p(1), matrix_type=dbcsr_type_no_symmetry)
918 :
919 18 : CALL dbcsr_create(matrix_tmp, template=ls_scf_env%matrix_p(1), matrix_type=dbcsr_type_no_symmetry)
920 :
921 38 : DO ispin = 1, nspin
922 : ! ortho basis ks
923 : CALL dbcsr_multiply("N", "N", 1.0_dp, ls_scf_env%matrix_s_sqrt_inv, ls_scf_env%matrix_ks(ispin), &
924 20 : 0.0_dp, matrix_tmp, filter_eps=ls_scf_env%eps_filter)
925 : CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp, ls_scf_env%matrix_s_sqrt_inv, &
926 20 : 0.0_dp, matrix_k, filter_eps=ls_scf_env%eps_filter)
927 :
928 : ! extremal eigenvalues ks
929 : CALL arnoldi_extremal(matrix_k, eps_max, eps_min, max_iter=ls_scf_env%max_iter_lanczos, &
930 20 : threshold=ls_scf_env%eps_lanczos, converged=converged)
931 :
932 : ! ortho basis p
933 : CALL dbcsr_multiply("N", "N", 1.0_dp, ls_scf_env%matrix_s_sqrt, ls_scf_env%matrix_p(ispin), &
934 20 : 0.0_dp, matrix_tmp, filter_eps=ls_scf_env%eps_filter)
935 : CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp, ls_scf_env%matrix_s_sqrt, &
936 20 : 0.0_dp, matrix_p, filter_eps=ls_scf_env%eps_filter)
937 20 : IF (nspin == 1) CALL dbcsr_scale(matrix_p, 0.5_dp)
938 :
939 : ! go compute homo lumo
940 : CALL compute_homo_lumo(matrix_k, matrix_p, eps_min, eps_max, ls_scf_env%eps_filter, &
941 58 : ls_scf_env%max_iter_lanczos, ls_scf_env%eps_lanczos, homo, lumo, unit_nr)
942 :
943 : END DO
944 :
945 18 : CALL dbcsr_release(matrix_p)
946 18 : CALL dbcsr_release(matrix_k)
947 18 : CALL dbcsr_release(matrix_tmp)
948 :
949 18 : CALL timestop(handle)
950 :
951 18 : END SUBROUTINE post_scf_homo_lumo
952 :
953 : ! **************************************************************************************************
954 : !> \brief Compute the density matrix for various values of the chemical potential
955 : !> \param ls_scf_env ...
956 : !> \par History
957 : !> 2010.10 created [Joost VandeVondele]
958 : !> \author Joost VandeVondele
959 : ! **************************************************************************************************
960 2 : SUBROUTINE post_scf_mu_scan(ls_scf_env)
961 : TYPE(ls_scf_env_type) :: ls_scf_env
962 :
963 : CHARACTER(len=*), PARAMETER :: routineN = 'post_scf_mu_scan'
964 :
965 : INTEGER :: handle, imu, ispin, nelectron_spin_real, &
966 : nmu, nspin, unit_nr
967 : REAL(KIND=dp) :: mu, t1, t2, trace
968 : TYPE(cp_logger_type), POINTER :: logger
969 : TYPE(dbcsr_type) :: matrix_p
970 :
971 2 : CALL timeset(routineN, handle)
972 :
973 : ! get a useful output_unit
974 2 : logger => cp_get_default_logger()
975 2 : IF (logger%para_env%is_source()) THEN
976 1 : unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
977 : ELSE
978 : unit_nr = -1
979 : END IF
980 :
981 2 : nspin = ls_scf_env%nspins
982 :
983 2 : CALL dbcsr_create(matrix_p, template=ls_scf_env%matrix_p(1))
984 :
985 2 : nmu = 10
986 24 : DO imu = 0, nmu
987 :
988 22 : t1 = m_walltime()
989 :
990 22 : mu = -0.4_dp + imu*(0.1_dp + 0.4_dp)/nmu
991 :
992 22 : IF (unit_nr > 0) WRITE (unit_nr, *) "------- starting with mu ", mu
993 :
994 44 : DO ispin = 1, nspin
995 : ! we need the proper number of states
996 22 : nelectron_spin_real = ls_scf_env%nelectron_spin(ispin)
997 22 : IF (ls_scf_env%nspins == 1) nelectron_spin_real = nelectron_spin_real/2
998 :
999 : CALL density_matrix_sign_fixed_mu(matrix_p, trace, mu, ls_scf_env%sign_method, &
1000 : ls_scf_env%sign_order, ls_scf_env%matrix_ks(ispin), &
1001 : ls_scf_env%matrix_s, ls_scf_env%matrix_s_inv, &
1002 : ls_scf_env%eps_filter, ls_scf_env%sign_symmetric, &
1003 44 : ls_scf_env%submatrix_sign_method, ls_scf_env%matrix_s_sqrt_inv)
1004 : END DO
1005 :
1006 22 : t2 = m_walltime()
1007 :
1008 24 : IF (unit_nr > 0) WRITE (unit_nr, *) " obtained ", mu, trace, t2 - t1
1009 :
1010 : END DO
1011 :
1012 2 : CALL dbcsr_release(matrix_p)
1013 :
1014 2 : CALL timestop(handle)
1015 :
1016 2 : END SUBROUTINE post_scf_mu_scan
1017 :
1018 : ! **************************************************************************************************
1019 : !> \brief Report on the sparsities of various interesting matrices.
1020 : !>
1021 : !> \param ls_scf_env ...
1022 : !> \par History
1023 : !> 2010.10 created [Joost VandeVondele]
1024 : !> \author Joost VandeVondele
1025 : ! **************************************************************************************************
1026 180 : SUBROUTINE post_scf_sparsities(ls_scf_env)
1027 : TYPE(ls_scf_env_type) :: ls_scf_env
1028 :
1029 : CHARACTER(len=*), PARAMETER :: routineN = 'post_scf_sparsities'
1030 :
1031 : CHARACTER(LEN=default_string_length) :: title
1032 : INTEGER :: handle, ispin, nspin, unit_nr
1033 : TYPE(cp_logger_type), POINTER :: logger
1034 : TYPE(dbcsr_type) :: matrix_tmp1, matrix_tmp2
1035 :
1036 180 : CALL timeset(routineN, handle)
1037 :
1038 : ! get a useful output_unit
1039 180 : logger => cp_get_default_logger()
1040 180 : IF (logger%para_env%is_source()) THEN
1041 90 : unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
1042 : ELSE
1043 90 : unit_nr = -1
1044 : END IF
1045 :
1046 180 : nspin = ls_scf_env%nspins
1047 :
1048 180 : IF (unit_nr > 0) THEN
1049 90 : WRITE (unit_nr, '()')
1050 90 : WRITE (unit_nr, '(T2,A,E17.3)') "Sparsity reports for eps_filter: ", ls_scf_env%eps_filter
1051 90 : WRITE (unit_nr, '()')
1052 : END IF
1053 :
1054 : CALL report_matrix_sparsity(ls_scf_env%matrix_s, unit_nr, "overlap matrix (S)", &
1055 180 : ls_scf_env%eps_filter)
1056 :
1057 368 : DO ispin = 1, nspin
1058 188 : WRITE (title, '(A,I3)') "Kohn-Sham matrix (H) for spin ", ispin
1059 : CALL report_matrix_sparsity(ls_scf_env%matrix_ks(ispin), unit_nr, title, &
1060 368 : ls_scf_env%eps_filter)
1061 : END DO
1062 :
1063 180 : CALL dbcsr_create(matrix_tmp1, template=ls_scf_env%matrix_s, matrix_type=dbcsr_type_no_symmetry)
1064 180 : CALL dbcsr_create(matrix_tmp2, template=ls_scf_env%matrix_s, matrix_type=dbcsr_type_no_symmetry)
1065 :
1066 368 : DO ispin = 1, nspin
1067 188 : WRITE (title, '(A,I3)') "Density matrix (P) for spin ", ispin
1068 : CALL report_matrix_sparsity(ls_scf_env%matrix_p(ispin), unit_nr, title, &
1069 188 : ls_scf_env%eps_filter)
1070 :
1071 : CALL dbcsr_multiply("N", "N", 1.0_dp, ls_scf_env%matrix_s, ls_scf_env%matrix_p(ispin), &
1072 188 : 0.0_dp, matrix_tmp1, filter_eps=ls_scf_env%eps_filter)
1073 :
1074 188 : WRITE (title, '(A,I3,A)') "S * P(", ispin, ")"
1075 188 : CALL report_matrix_sparsity(matrix_tmp1, unit_nr, title, ls_scf_env%eps_filter)
1076 :
1077 : CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp1, ls_scf_env%matrix_s, &
1078 188 : 0.0_dp, matrix_tmp2, filter_eps=ls_scf_env%eps_filter)
1079 188 : WRITE (title, '(A,I3,A)') "S * P(", ispin, ") * S"
1080 368 : CALL report_matrix_sparsity(matrix_tmp2, unit_nr, title, ls_scf_env%eps_filter)
1081 : END DO
1082 :
1083 180 : IF (ls_scf_env%needs_s_inv) THEN
1084 : CALL report_matrix_sparsity(ls_scf_env%matrix_s_inv, unit_nr, "inv(S)", &
1085 180 : ls_scf_env%eps_filter)
1086 368 : DO ispin = 1, nspin
1087 : CALL dbcsr_multiply("N", "N", 1.0_dp, ls_scf_env%matrix_s_inv, ls_scf_env%matrix_ks(ispin), &
1088 188 : 0.0_dp, matrix_tmp1, filter_eps=ls_scf_env%eps_filter)
1089 :
1090 188 : WRITE (title, '(A,I3,A)') "inv(S) * H(", ispin, ")"
1091 368 : CALL report_matrix_sparsity(matrix_tmp1, unit_nr, title, ls_scf_env%eps_filter)
1092 : END DO
1093 : END IF
1094 :
1095 180 : IF (ls_scf_env%use_s_sqrt) THEN
1096 :
1097 : CALL report_matrix_sparsity(ls_scf_env%matrix_s_sqrt, unit_nr, "sqrt(S)", &
1098 178 : ls_scf_env%eps_filter)
1099 : CALL report_matrix_sparsity(ls_scf_env%matrix_s_sqrt_inv, unit_nr, "inv(sqrt(S))", &
1100 178 : ls_scf_env%eps_filter)
1101 :
1102 364 : DO ispin = 1, nspin
1103 : CALL dbcsr_multiply("N", "N", 1.0_dp, ls_scf_env%matrix_s_sqrt_inv, ls_scf_env%matrix_ks(ispin), &
1104 186 : 0.0_dp, matrix_tmp1, filter_eps=ls_scf_env%eps_filter)
1105 : CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp1, ls_scf_env%matrix_s_sqrt_inv, &
1106 186 : 0.0_dp, matrix_tmp2, filter_eps=ls_scf_env%eps_filter)
1107 186 : WRITE (title, '(A,I3,A)') "inv(sqrt(S)) * H(", ispin, ") * inv(sqrt(S))"
1108 364 : CALL report_matrix_sparsity(matrix_tmp2, unit_nr, title, ls_scf_env%eps_filter)
1109 : END DO
1110 :
1111 364 : DO ispin = 1, nspin
1112 : CALL dbcsr_multiply("N", "N", 1.0_dp, ls_scf_env%matrix_s_sqrt, ls_scf_env%matrix_p(ispin), &
1113 186 : 0.0_dp, matrix_tmp1, filter_eps=ls_scf_env%eps_filter)
1114 : CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp1, ls_scf_env%matrix_s_sqrt, &
1115 186 : 0.0_dp, matrix_tmp2, filter_eps=ls_scf_env%eps_filter)
1116 186 : WRITE (title, '(A,I3,A)') "sqrt(S) * P(", ispin, ") * sqrt(S)"
1117 364 : CALL report_matrix_sparsity(matrix_tmp2, unit_nr, title, ls_scf_env%eps_filter)
1118 : END DO
1119 :
1120 : END IF
1121 :
1122 180 : CALL dbcsr_release(matrix_tmp1)
1123 180 : CALL dbcsr_release(matrix_tmp2)
1124 :
1125 180 : CALL timestop(handle)
1126 :
1127 180 : END SUBROUTINE post_scf_sparsities
1128 :
1129 : ! **************************************************************************************************
1130 : !> \brief Helper routine to report on the sparsity of a single matrix,
1131 : !> for several filtering values
1132 : !> \param matrix ...
1133 : !> \param unit_nr ...
1134 : !> \param title ...
1135 : !> \param eps ...
1136 : !> \par History
1137 : !> 2010.10 created [Joost VandeVondele]
1138 : !> \author Joost VandeVondele
1139 : ! **************************************************************************************************
1140 2028 : SUBROUTINE report_matrix_sparsity(matrix, unit_nr, title, eps)
1141 : TYPE(dbcsr_type) :: matrix
1142 : INTEGER :: unit_nr
1143 : CHARACTER(LEN=*) :: title
1144 : REAL(KIND=dp) :: eps
1145 :
1146 : CHARACTER(len=*), PARAMETER :: routineN = 'report_matrix_sparsity'
1147 :
1148 : INTEGER :: handle
1149 : REAL(KIND=dp) :: eps_local, occ
1150 : TYPE(dbcsr_type) :: matrix_tmp
1151 :
1152 2028 : CALL timeset(routineN, handle)
1153 2028 : CALL dbcsr_create(matrix_tmp, template=matrix, name=TRIM(title))
1154 2028 : CALL dbcsr_copy(matrix_tmp, matrix, name=TRIM(title))
1155 :
1156 2028 : IF (unit_nr > 0) THEN
1157 1014 : WRITE (unit_nr, '(T2,A)') "Sparsity for : "//TRIM(title)
1158 : END IF
1159 :
1160 2028 : eps_local = MAX(eps, 10E-14_dp)
1161 14796 : DO
1162 16824 : IF (eps_local > 1.1_dp) EXIT
1163 14796 : CALL dbcsr_filter(matrix_tmp, eps_local)
1164 14796 : occ = dbcsr_get_occupation(matrix_tmp)
1165 14796 : IF (unit_nr > 0) WRITE (unit_nr, '(T2,F16.12,A3,F16.12)') eps_local, " : ", occ
1166 14796 : eps_local = eps_local*10
1167 : END DO
1168 :
1169 2028 : CALL dbcsr_release(matrix_tmp)
1170 :
1171 2028 : CALL timestop(handle)
1172 :
1173 2028 : END SUBROUTINE report_matrix_sparsity
1174 :
1175 : ! **************************************************************************************************
1176 : !> \brief Compute matrix_w as needed for the forces
1177 : !> \param matrix_w ...
1178 : !> \param ls_scf_env ...
1179 : !> \par History
1180 : !> 2010.11 created [Joost VandeVondele]
1181 : !> \author Joost VandeVondele
1182 : ! **************************************************************************************************
1183 194 : SUBROUTINE calculate_w_matrix_ls(matrix_w, ls_scf_env)
1184 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_w
1185 : TYPE(ls_scf_env_type) :: ls_scf_env
1186 :
1187 : CHARACTER(len=*), PARAMETER :: routineN = 'calculate_w_matrix_ls'
1188 :
1189 : INTEGER :: handle, ispin
1190 : REAL(KIND=dp) :: scaling
1191 : TYPE(dbcsr_type) :: matrix_tmp1, matrix_tmp2, matrix_tmp3
1192 :
1193 194 : CALL timeset(routineN, handle)
1194 :
1195 194 : CALL dbcsr_create(matrix_tmp1, template=ls_scf_env%matrix_s, matrix_type=dbcsr_type_no_symmetry)
1196 194 : CALL dbcsr_create(matrix_tmp2, template=ls_scf_env%matrix_s, matrix_type=dbcsr_type_no_symmetry)
1197 194 : CALL dbcsr_create(matrix_tmp3, template=ls_scf_env%matrix_s, matrix_type=dbcsr_type_no_symmetry)
1198 :
1199 194 : IF (ls_scf_env%nspins == 1) THEN
1200 186 : scaling = 0.5_dp
1201 : ELSE
1202 8 : scaling = 1.0_dp
1203 : END IF
1204 :
1205 396 : DO ispin = 1, ls_scf_env%nspins
1206 :
1207 202 : CALL dbcsr_copy(matrix_tmp3, ls_scf_env%matrix_ks(ispin))
1208 202 : IF (ls_scf_env%has_s_preconditioner) THEN
1209 : CALL apply_matrix_preconditioner(matrix_tmp3, "backward", &
1210 132 : ls_scf_env%matrix_bs_sqrt, ls_scf_env%matrix_bs_sqrt_inv)
1211 : END IF
1212 202 : CALL dbcsr_filter(matrix_tmp3, ls_scf_env%eps_filter)
1213 :
1214 : CALL dbcsr_multiply("N", "N", scaling, ls_scf_env%matrix_p(ispin), matrix_tmp3, &
1215 202 : 0.0_dp, matrix_tmp1, filter_eps=ls_scf_env%eps_filter)
1216 : CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp1, ls_scf_env%matrix_p(ispin), &
1217 202 : 0.0_dp, matrix_tmp2, filter_eps=ls_scf_env%eps_filter)
1218 396 : CALL matrix_ls_to_qs(matrix_w(ispin)%matrix, matrix_tmp2, ls_scf_env%ls_mstruct, covariant=.FALSE.)
1219 : END DO
1220 :
1221 194 : CALL dbcsr_release(matrix_tmp1)
1222 194 : CALL dbcsr_release(matrix_tmp2)
1223 194 : CALL dbcsr_release(matrix_tmp3)
1224 :
1225 194 : CALL timestop(handle)
1226 :
1227 194 : END SUBROUTINE calculate_w_matrix_ls
1228 :
1229 : ! **************************************************************************************************
1230 : !> \brief a place for quick experiments
1231 : !> \par History
1232 : !> 2010.11 created [Joost VandeVondele]
1233 : !> \author Joost VandeVondele
1234 : ! **************************************************************************************************
1235 814 : SUBROUTINE post_scf_experiment()
1236 :
1237 : CHARACTER(len=*), PARAMETER :: routineN = 'post_scf_experiment'
1238 :
1239 : INTEGER :: handle, unit_nr
1240 : TYPE(cp_logger_type), POINTER :: logger
1241 :
1242 814 : CALL timeset(routineN, handle)
1243 :
1244 : ! get a useful output_unit
1245 814 : logger => cp_get_default_logger()
1246 814 : IF (logger%para_env%is_source()) THEN
1247 407 : unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
1248 : ELSE
1249 : unit_nr = -1
1250 : END IF
1251 :
1252 814 : CALL timestop(handle)
1253 814 : END SUBROUTINE post_scf_experiment
1254 :
1255 : END MODULE dm_ls_scf
|