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 collects routines that perform operations directly related to MOs
10 : !> \note
11 : !> first version : most routines imported
12 : !> \author Joost VandeVondele (2003-08)
13 : ! **************************************************************************************************
14 : MODULE qs_mo_methods
15 : USE admm_types, ONLY: admm_type
16 : USE admm_utils, ONLY: admm_correct_for_eigenvalues,&
17 : admm_uncorrect_for_eigenvalues
18 : USE cp_blacs_env, ONLY: cp_blacs_env_type
19 : USE cp_control_types, ONLY: hairy_probes_type
20 : USE cp_dbcsr_api, ONLY: dbcsr_copy,&
21 : dbcsr_get_info,&
22 : dbcsr_init_p,&
23 : dbcsr_multiply,&
24 : dbcsr_p_type,&
25 : dbcsr_release_p,&
26 : dbcsr_type,&
27 : dbcsr_type_no_symmetry
28 : USE cp_dbcsr_diag, ONLY: cp_dbcsr_syevd,&
29 : cp_dbcsr_syevx
30 : USE cp_dbcsr_operations, ONLY: copy_dbcsr_to_fm,&
31 : copy_fm_to_dbcsr,&
32 : cp_dbcsr_m_by_n_from_template,&
33 : cp_dbcsr_sm_fm_multiply
34 : USE cp_fm_basic_linalg, ONLY: cp_fm_syrk,&
35 : cp_fm_triangular_multiply
36 : USE cp_fm_cholesky, ONLY: cp_fm_cholesky_decompose
37 : USE cp_fm_diag, ONLY: choose_eigv_solver,&
38 : cp_fm_power,&
39 : cp_fm_syevx
40 : USE cp_fm_struct, ONLY: cp_fm_struct_create,&
41 : cp_fm_struct_release,&
42 : cp_fm_struct_type
43 : USE cp_fm_types, ONLY: cp_fm_create,&
44 : cp_fm_get_info,&
45 : cp_fm_release,&
46 : cp_fm_set_all,&
47 : cp_fm_to_fm,&
48 : cp_fm_type
49 : USE cp_log_handling, ONLY: cp_logger_get_default_io_unit
50 : USE kinds, ONLY: dp
51 : USE message_passing, ONLY: mp_para_env_type
52 : USE parallel_gemm_api, ONLY: parallel_gemm
53 : USE physcon, ONLY: evolt
54 : USE qs_mo_occupation, ONLY: set_mo_occupation
55 : USE qs_mo_types, ONLY: get_mo_set,&
56 : mo_set_type
57 : USE scf_control_types, ONLY: scf_control_type
58 : #include "./base/base_uses.f90"
59 :
60 : IMPLICIT NONE
61 : PRIVATE
62 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_mo_methods'
63 :
64 : PUBLIC :: make_basis_simple, make_basis_cholesky, make_basis_sv, make_basis_sm, &
65 : make_basis_lowdin, calculate_subspace_eigenvalues, &
66 : calculate_orthonormality, calculate_magnitude, make_mo_eig
67 :
68 : INTERFACE calculate_subspace_eigenvalues
69 : MODULE PROCEDURE subspace_eigenvalues_ks_fm
70 : MODULE PROCEDURE subspace_eigenvalues_ks_dbcsr
71 : END INTERFACE
72 :
73 : INTERFACE make_basis_sv
74 : MODULE PROCEDURE make_basis_sv_fm
75 : MODULE PROCEDURE make_basis_sv_dbcsr
76 : END INTERFACE
77 :
78 : CONTAINS
79 :
80 : ! **************************************************************************************************
81 : !> \brief returns an S-orthonormal basis v (v^T S v ==1)
82 : !> \param vmatrix ...
83 : !> \param ncol ...
84 : !> \param matrix_s ...
85 : !> \par History
86 : !> 03.2006 created [Joost VandeVondele]
87 : ! **************************************************************************************************
88 29056 : SUBROUTINE make_basis_sm(vmatrix, ncol, matrix_s)
89 : TYPE(cp_fm_type), INTENT(IN) :: vmatrix
90 : INTEGER, INTENT(IN) :: ncol
91 : TYPE(dbcsr_type), POINTER :: matrix_s
92 :
93 : CHARACTER(LEN=*), PARAMETER :: routineN = 'make_basis_sm'
94 : REAL(KIND=dp), PARAMETER :: rone = 1.0_dp, rzero = 0.0_dp
95 :
96 : INTEGER :: handle, n, ncol_global
97 : TYPE(cp_fm_struct_type), POINTER :: fm_struct_tmp
98 : TYPE(cp_fm_type) :: overlap_vv, svmatrix
99 :
100 128 : IF (ncol == 0) RETURN
101 :
102 7232 : CALL timeset(routineN, handle)
103 :
104 7232 : CALL cp_fm_get_info(matrix=vmatrix, nrow_global=n, ncol_global=ncol_global)
105 7232 : IF (ncol > ncol_global) CPABORT("Wrong ncol value")
106 :
107 7232 : CALL cp_fm_create(svmatrix, vmatrix%matrix_struct, "SV", set_zero=.TRUE.)
108 7232 : CALL cp_dbcsr_sm_fm_multiply(matrix_s, vmatrix, svmatrix, ncol)
109 :
110 7232 : NULLIFY (fm_struct_tmp)
111 : CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=ncol, ncol_global=ncol, &
112 : para_env=vmatrix%matrix_struct%para_env, &
113 7232 : context=vmatrix%matrix_struct%context)
114 7232 : CALL cp_fm_create(overlap_vv, fm_struct_tmp, "overlap_vv")
115 7232 : CALL cp_fm_struct_release(fm_struct_tmp)
116 :
117 7232 : CALL parallel_gemm('T', 'N', ncol, ncol, n, rone, vmatrix, svmatrix, rzero, overlap_vv)
118 7232 : CALL cp_fm_cholesky_decompose(overlap_vv)
119 7232 : CALL cp_fm_triangular_multiply(overlap_vv, vmatrix, n_cols=ncol, side='R', invert_tr=.TRUE.)
120 :
121 7232 : CALL cp_fm_release(overlap_vv)
122 7232 : CALL cp_fm_release(svmatrix)
123 :
124 7232 : CALL timestop(handle)
125 :
126 7360 : END SUBROUTINE make_basis_sm
127 :
128 : ! **************************************************************************************************
129 : !> \brief returns an S-orthonormal basis v and the corresponding matrix S*v as well
130 : !> \param vmatrix ...
131 : !> \param ncol ...
132 : !> \param svmatrix ...
133 : !> \par History
134 : !> 03.2006 created [Joost VandeVondele]
135 : ! **************************************************************************************************
136 0 : SUBROUTINE make_basis_sv_fm(vmatrix, ncol, svmatrix)
137 :
138 : TYPE(cp_fm_type), INTENT(IN) :: vmatrix
139 : INTEGER, INTENT(IN) :: ncol
140 : TYPE(cp_fm_type), INTENT(IN) :: svmatrix
141 :
142 : CHARACTER(LEN=*), PARAMETER :: routineN = 'make_basis_sv_fm'
143 : REAL(KIND=dp), PARAMETER :: rone = 1.0_dp, rzero = 0.0_dp
144 :
145 : INTEGER :: handle, n, ncol_global
146 : TYPE(cp_fm_struct_type), POINTER :: fm_struct_tmp
147 : TYPE(cp_fm_type) :: overlap_vv
148 :
149 0 : IF (ncol == 0) RETURN
150 :
151 0 : CALL timeset(routineN, handle)
152 0 : NULLIFY (fm_struct_tmp)
153 :
154 0 : CALL cp_fm_get_info(matrix=vmatrix, nrow_global=n, ncol_global=ncol_global)
155 0 : IF (ncol > ncol_global) CPABORT("Wrong ncol value")
156 :
157 : CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=ncol, ncol_global=ncol, &
158 : para_env=vmatrix%matrix_struct%para_env, &
159 0 : context=vmatrix%matrix_struct%context)
160 0 : CALL cp_fm_create(overlap_vv, fm_struct_tmp, "overlap_vv")
161 0 : CALL cp_fm_struct_release(fm_struct_tmp)
162 :
163 0 : CALL parallel_gemm('T', 'N', ncol, ncol, n, rone, vmatrix, svmatrix, rzero, overlap_vv)
164 0 : CALL cp_fm_cholesky_decompose(overlap_vv)
165 0 : CALL cp_fm_triangular_multiply(overlap_vv, vmatrix, n_cols=ncol, side='R', invert_tr=.TRUE.)
166 0 : CALL cp_fm_triangular_multiply(overlap_vv, svmatrix, n_cols=ncol, side='R', invert_tr=.TRUE.)
167 :
168 0 : CALL cp_fm_release(overlap_vv)
169 :
170 0 : CALL timestop(handle)
171 :
172 0 : END SUBROUTINE make_basis_sv_fm
173 :
174 : ! **************************************************************************************************
175 : !> \brief ...
176 : !> \param vmatrix ...
177 : !> \param ncol ...
178 : !> \param svmatrix ...
179 : !> \param para_env ...
180 : !> \param blacs_env ...
181 : ! **************************************************************************************************
182 2870 : SUBROUTINE make_basis_sv_dbcsr(vmatrix, ncol, svmatrix, para_env, blacs_env)
183 :
184 : TYPE(dbcsr_type) :: vmatrix
185 : INTEGER, INTENT(IN) :: ncol
186 : TYPE(dbcsr_type) :: svmatrix
187 : TYPE(mp_para_env_type), POINTER :: para_env
188 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
189 :
190 : CHARACTER(LEN=*), PARAMETER :: routineN = 'make_basis_sv_dbcsr'
191 : REAL(KIND=dp), PARAMETER :: rone = 1.0_dp, rzero = 0.0_dp
192 :
193 : INTEGER :: handle, n, ncol_global
194 : TYPE(cp_fm_struct_type), POINTER :: fm_struct_tmp
195 : TYPE(cp_fm_type) :: fm_svmatrix, fm_vmatrix, overlap_vv
196 :
197 86 : IF (ncol == 0) RETURN
198 :
199 464 : CALL timeset(routineN, handle)
200 :
201 : !CALL cp_fm_get_info(matrix=vmatrix,nrow_global=n,ncol_global=ncol_global)
202 464 : CALL dbcsr_get_info(vmatrix, nfullrows_total=n, nfullcols_total=ncol_global)
203 464 : IF (ncol > ncol_global) CPABORT("Wrong ncol value")
204 :
205 : CALL cp_fm_struct_create(fm_struct_tmp, context=blacs_env, nrow_global=ncol, &
206 464 : ncol_global=ncol, para_env=para_env)
207 464 : CALL cp_fm_create(overlap_vv, fm_struct_tmp, name="fm_overlap_vv")
208 464 : CALL cp_fm_struct_release(fm_struct_tmp)
209 :
210 : CALL cp_fm_struct_create(fm_struct_tmp, context=blacs_env, nrow_global=n, &
211 464 : ncol_global=ncol_global, para_env=para_env)
212 464 : CALL cp_fm_create(fm_vmatrix, fm_struct_tmp, name="fm_vmatrix")
213 464 : CALL cp_fm_create(fm_svmatrix, fm_struct_tmp, name="fm_svmatrix")
214 464 : CALL cp_fm_struct_release(fm_struct_tmp)
215 :
216 464 : CALL copy_dbcsr_to_fm(vmatrix, fm_vmatrix)
217 464 : CALL copy_dbcsr_to_fm(svmatrix, fm_svmatrix)
218 :
219 464 : CALL parallel_gemm('T', 'N', ncol, ncol, n, rone, fm_vmatrix, fm_svmatrix, rzero, overlap_vv)
220 464 : CALL cp_fm_cholesky_decompose(overlap_vv)
221 464 : CALL cp_fm_triangular_multiply(overlap_vv, fm_vmatrix, n_cols=ncol, side='R', invert_tr=.TRUE.)
222 464 : CALL cp_fm_triangular_multiply(overlap_vv, fm_svmatrix, n_cols=ncol, side='R', invert_tr=.TRUE.)
223 :
224 464 : CALL copy_fm_to_dbcsr(fm_vmatrix, vmatrix)
225 464 : CALL copy_fm_to_dbcsr(fm_svmatrix, svmatrix)
226 :
227 464 : CALL cp_fm_release(overlap_vv)
228 464 : CALL cp_fm_release(fm_vmatrix)
229 464 : CALL cp_fm_release(fm_svmatrix)
230 :
231 464 : CALL timestop(handle)
232 :
233 550 : END SUBROUTINE make_basis_sv_dbcsr
234 :
235 : ! **************************************************************************************************
236 : !> \brief return a set of S orthonormal vectors (C^T S C == 1) where
237 : !> the cholesky decomposed form of S is passed as an argument
238 : !> \param vmatrix ...
239 : !> \param ncol ...
240 : !> \param ortho cholesky decomposed S matrix
241 : !> \par History
242 : !> 03.2006 created [Joost VandeVondele]
243 : !> \note
244 : !> if the cholesky decomposed S matrix is not available
245 : !> use make_basis_sm since this is much faster than computing the
246 : !> cholesky decomposition of S
247 : ! **************************************************************************************************
248 25128 : SUBROUTINE make_basis_cholesky(vmatrix, ncol, ortho)
249 :
250 : TYPE(cp_fm_type), INTENT(IN) :: vmatrix
251 : INTEGER, INTENT(IN) :: ncol
252 : TYPE(cp_fm_type), INTENT(IN) :: ortho
253 :
254 : CHARACTER(LEN=*), PARAMETER :: routineN = 'make_basis_cholesky'
255 : REAL(KIND=dp), PARAMETER :: rone = 1.0_dp, rzero = 0.0_dp
256 :
257 : INTEGER :: handle, n, ncol_global
258 : TYPE(cp_fm_struct_type), POINTER :: fm_struct_tmp
259 : TYPE(cp_fm_type) :: overlap_vv
260 :
261 80 : IF (ncol == 0) RETURN
262 :
263 6262 : CALL timeset(routineN, handle)
264 6262 : NULLIFY (fm_struct_tmp)
265 :
266 6262 : CALL cp_fm_get_info(matrix=vmatrix, nrow_global=n, ncol_global=ncol_global)
267 6262 : IF (ncol > ncol_global) CPABORT("Wrong ncol value")
268 :
269 : CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=ncol, ncol_global=ncol, &
270 : para_env=vmatrix%matrix_struct%para_env, &
271 6262 : context=vmatrix%matrix_struct%context)
272 6262 : CALL cp_fm_create(overlap_vv, fm_struct_tmp, "overlap_vv")
273 6262 : CALL cp_fm_struct_release(fm_struct_tmp)
274 :
275 6262 : CALL cp_fm_triangular_multiply(ortho, vmatrix, n_cols=ncol)
276 6262 : CALL cp_fm_syrk('U', 'T', n, rone, vmatrix, 1, 1, rzero, overlap_vv)
277 6262 : CALL cp_fm_cholesky_decompose(overlap_vv)
278 6262 : CALL cp_fm_triangular_multiply(overlap_vv, vmatrix, n_cols=ncol, side='R', invert_tr=.TRUE.)
279 6262 : CALL cp_fm_triangular_multiply(ortho, vmatrix, n_cols=ncol, invert_tr=.TRUE.)
280 :
281 6262 : CALL cp_fm_release(overlap_vv)
282 :
283 6262 : CALL timestop(handle)
284 :
285 6342 : END SUBROUTINE make_basis_cholesky
286 :
287 : ! **************************************************************************************************
288 : !> \brief return a set of S orthonormal vectors (C^T S C == 1) where
289 : !> a Loedwin transformation is applied to keep the rotated vectors as close
290 : !> as possible to the original ones
291 : !> \param vmatrix ...
292 : !> \param ncol ...
293 : !> \param matrix_s ...
294 : !> \param
295 : !> \par History
296 : !> 05.2009 created [MI]
297 : !> \note
298 : ! **************************************************************************************************
299 7932 : SUBROUTINE make_basis_lowdin(vmatrix, ncol, matrix_s)
300 :
301 : TYPE(cp_fm_type), INTENT(IN) :: vmatrix
302 : INTEGER, INTENT(IN) :: ncol
303 : TYPE(dbcsr_type) :: matrix_s
304 :
305 : CHARACTER(LEN=*), PARAMETER :: routineN = 'make_basis_lowdin'
306 : REAL(KIND=dp), PARAMETER :: rone = 1.0_dp, rzero = 0.0_dp
307 :
308 : INTEGER :: handle, n, ncol_global, ndep
309 : REAL(dp) :: threshold
310 : TYPE(cp_fm_struct_type), POINTER :: fm_struct_tmp
311 : TYPE(cp_fm_type) :: csc, sc, work
312 :
313 0 : IF (ncol == 0) RETURN
314 :
315 1322 : CALL timeset(routineN, handle)
316 1322 : NULLIFY (fm_struct_tmp)
317 1322 : threshold = 1.0E-7_dp
318 1322 : CALL cp_fm_get_info(matrix=vmatrix, nrow_global=n, ncol_global=ncol_global)
319 1322 : IF (ncol > ncol_global) CPABORT("Wrong ncol value")
320 :
321 1322 : CALL cp_fm_create(sc, vmatrix%matrix_struct, "SC")
322 1322 : CALL cp_dbcsr_sm_fm_multiply(matrix_s, vmatrix, sc, ncol)
323 :
324 1322 : NULLIFY (fm_struct_tmp)
325 : CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=ncol, ncol_global=ncol, &
326 : para_env=vmatrix%matrix_struct%para_env, &
327 1322 : context=vmatrix%matrix_struct%context)
328 1322 : CALL cp_fm_create(csc, fm_struct_tmp, "csc")
329 1322 : CALL cp_fm_set_all(csc, 0.0_dp)
330 1322 : CALL cp_fm_create(work, fm_struct_tmp, "work")
331 1322 : CALL cp_fm_set_all(work, 0.0_dp)
332 1322 : CALL cp_fm_struct_release(fm_struct_tmp)
333 :
334 1322 : CALL parallel_gemm('T', 'N', ncol, ncol, n, rone, vmatrix, sc, rzero, csc)
335 1322 : CALL cp_fm_power(csc, work, -0.5_dp, threshold, ndep)
336 1322 : CALL parallel_gemm('N', 'N', n, ncol, ncol, rone, vmatrix, csc, rzero, sc)
337 1322 : CALL cp_fm_to_fm(sc, vmatrix, ncol, 1, 1)
338 :
339 1322 : CALL cp_fm_release(csc)
340 1322 : CALL cp_fm_release(sc)
341 1322 : CALL cp_fm_release(work)
342 :
343 1322 : CALL timestop(handle)
344 :
345 1322 : END SUBROUTINE make_basis_lowdin
346 :
347 : ! **************************************************************************************************
348 : !> \brief given a set of vectors, return an orthogonal (C^T C == 1) set
349 : !> spanning the same space (notice, only for cases where S==1)
350 : !> \param vmatrix ...
351 : !> \param ncol ...
352 : !> \par History
353 : !> 03.2006 created [Joost VandeVondele]
354 : ! **************************************************************************************************
355 14606 : SUBROUTINE make_basis_simple(vmatrix, ncol)
356 :
357 : TYPE(cp_fm_type), INTENT(IN) :: vmatrix
358 : INTEGER, INTENT(IN) :: ncol
359 :
360 : CHARACTER(LEN=*), PARAMETER :: routineN = 'make_basis_simple'
361 : REAL(KIND=dp), PARAMETER :: rone = 1.0_dp, rzero = 0.0_dp
362 :
363 : INTEGER :: handle, n, ncol_global
364 : TYPE(cp_fm_struct_type), POINTER :: fm_struct_tmp
365 : TYPE(cp_fm_type) :: overlap_vv
366 :
367 70 : IF (ncol == 0) RETURN
368 :
369 3634 : CALL timeset(routineN, handle)
370 :
371 3634 : NULLIFY (fm_struct_tmp)
372 :
373 3634 : CALL cp_fm_get_info(matrix=vmatrix, nrow_global=n, ncol_global=ncol_global)
374 3634 : IF (ncol > ncol_global) CPABORT("Wrong ncol value")
375 :
376 : CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=ncol, ncol_global=ncol, &
377 : para_env=vmatrix%matrix_struct%para_env, &
378 3634 : context=vmatrix%matrix_struct%context)
379 3634 : CALL cp_fm_create(overlap_vv, fm_struct_tmp, "overlap_vv")
380 3634 : CALL cp_fm_struct_release(fm_struct_tmp)
381 :
382 3634 : CALL parallel_gemm('T', 'N', ncol, ncol, n, rone, vmatrix, vmatrix, rzero, overlap_vv)
383 3634 : CALL cp_fm_cholesky_decompose(overlap_vv)
384 3634 : CALL cp_fm_triangular_multiply(overlap_vv, vmatrix, n_cols=ncol, side='R', invert_tr=.TRUE.)
385 :
386 3634 : CALL cp_fm_release(overlap_vv)
387 :
388 3634 : CALL timestop(handle)
389 :
390 3704 : END SUBROUTINE make_basis_simple
391 :
392 : ! **************************************************************************************************
393 : !> \brief computes ritz values of a set of orbitals given a ks_matrix
394 : !> rotates the orbitals into eigenstates depending on do_rotation
395 : !> writes the evals to the screen depending on ionode/scr
396 : !> \param orbitals S-orthonormal orbitals
397 : !> \param ks_matrix Kohn-Sham matrix
398 : !> \param evals_arg optional, filled with the evals
399 : !> \param ionode , scr if present write to unit scr where ionode
400 : !> \param scr ...
401 : !> \param do_rotation optional rotate orbitals (default=.TRUE.)
402 : !> note that rotating the orbitals is slower
403 : !> \param co_rotate an optional set of orbitals rotated by the same rotation matrix
404 : !> \param co_rotate_dbcsr ...
405 : !> \par History
406 : !> 08.2004 documented and added do_rotation [Joost VandeVondele]
407 : !> 09.2008 only compute eigenvalues if rotation is not needed
408 : ! **************************************************************************************************
409 8179 : SUBROUTINE subspace_eigenvalues_ks_fm(orbitals, ks_matrix, evals_arg, ionode, scr, &
410 : do_rotation, co_rotate, co_rotate_dbcsr)
411 :
412 : TYPE(cp_fm_type), INTENT(IN) :: orbitals
413 : TYPE(dbcsr_type), POINTER :: ks_matrix
414 : REAL(KIND=dp), DIMENSION(:), OPTIONAL :: evals_arg
415 : LOGICAL, INTENT(IN), OPTIONAL :: ionode
416 : INTEGER, INTENT(IN), OPTIONAL :: scr
417 : LOGICAL, INTENT(IN), OPTIONAL :: do_rotation
418 : TYPE(cp_fm_type), INTENT(IN), OPTIONAL :: co_rotate
419 : TYPE(dbcsr_type), OPTIONAL, POINTER :: co_rotate_dbcsr
420 :
421 : CHARACTER(len=*), PARAMETER :: routineN = 'subspace_eigenvalues_ks_fm'
422 :
423 : INTEGER :: handle, i, j, n, ncol_global, nrow_global
424 : LOGICAL :: compute_evecs, do_rotation_local
425 8179 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: evals
426 : TYPE(cp_fm_struct_type), POINTER :: fm_struct_tmp
427 : TYPE(cp_fm_type) :: e_vectors, h_block, weighted_vectors, &
428 : weighted_vectors2
429 :
430 8179 : CALL timeset(routineN, handle)
431 :
432 8179 : do_rotation_local = .TRUE.
433 8179 : IF (PRESENT(do_rotation)) do_rotation_local = do_rotation
434 :
435 8179 : NULLIFY (fm_struct_tmp)
436 : CALL cp_fm_get_info(matrix=orbitals, &
437 : ncol_global=ncol_global, &
438 8179 : nrow_global=nrow_global)
439 :
440 : IF (do_rotation_local) THEN
441 : compute_evecs = .TRUE.
442 : ELSE
443 : ! this would be the logical choice if syevx computing only evals were faster than syevd computing evecs and evals.
444 : compute_evecs = .FALSE.
445 : ! this is not the case, so lets compute evecs always
446 : compute_evecs = .TRUE.
447 : END IF
448 :
449 8179 : IF (ncol_global > 0) THEN
450 :
451 24279 : ALLOCATE (evals(ncol_global))
452 :
453 8093 : CALL cp_fm_create(weighted_vectors, orbitals%matrix_struct, "weighted_vectors")
454 : CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=ncol_global, ncol_global=ncol_global, &
455 : para_env=orbitals%matrix_struct%para_env, &
456 8093 : context=orbitals%matrix_struct%context)
457 8093 : CALL cp_fm_create(h_block, fm_struct_tmp, name="h block")
458 8093 : IF (compute_evecs) THEN
459 8093 : CALL cp_fm_create(e_vectors, fm_struct_tmp, name="e vectors")
460 : END IF
461 8093 : CALL cp_fm_struct_release(fm_struct_tmp)
462 :
463 : ! h subblock and diag
464 8093 : CALL cp_dbcsr_sm_fm_multiply(ks_matrix, orbitals, weighted_vectors, ncol_global)
465 :
466 : CALL parallel_gemm('T', 'N', ncol_global, ncol_global, nrow_global, 1.0_dp, &
467 8093 : orbitals, weighted_vectors, 0.0_dp, h_block)
468 :
469 : ! if eigenvectors are required, go for syevd, otherwise only compute eigenvalues
470 : IF (compute_evecs) THEN
471 8093 : CALL choose_eigv_solver(h_block, e_vectors, evals)
472 : ELSE
473 : CALL cp_fm_syevx(h_block, eigenvalues=evals)
474 : END IF
475 :
476 : ! rotate the orbitals
477 8093 : IF (do_rotation_local) THEN
478 : CALL parallel_gemm('N', 'N', nrow_global, ncol_global, ncol_global, 1.0_dp, &
479 7809 : orbitals, e_vectors, 0.0_dp, weighted_vectors)
480 7809 : CALL cp_fm_to_fm(weighted_vectors, orbitals)
481 7809 : IF (PRESENT(co_rotate)) THEN
482 : CALL parallel_gemm('N', 'N', nrow_global, ncol_global, ncol_global, 1.0_dp, &
483 0 : co_rotate, e_vectors, 0.0_dp, weighted_vectors)
484 0 : CALL cp_fm_to_fm(weighted_vectors, co_rotate)
485 : END IF
486 7809 : IF (PRESENT(co_rotate_dbcsr)) THEN
487 362 : IF (ASSOCIATED(co_rotate_dbcsr)) THEN
488 358 : CALL cp_fm_create(weighted_vectors2, orbitals%matrix_struct, "weighted_vectors")
489 358 : CALL copy_dbcsr_to_fm(co_rotate_dbcsr, weighted_vectors2)
490 : CALL parallel_gemm('N', 'N', nrow_global, ncol_global, ncol_global, 1.0_dp, &
491 358 : weighted_vectors2, e_vectors, 0.0_dp, weighted_vectors)
492 358 : CALL copy_fm_to_dbcsr(weighted_vectors, co_rotate_dbcsr)
493 358 : CALL cp_fm_release(weighted_vectors2)
494 : END IF
495 : END IF
496 : END IF
497 :
498 : ! give output
499 8093 : IF (PRESENT(evals_arg)) THEN
500 8061 : n = MIN(SIZE(evals_arg), SIZE(evals))
501 81987 : evals_arg(1:n) = evals(1:n)
502 : END IF
503 :
504 8093 : IF (PRESENT(ionode) .OR. PRESENT(scr)) THEN
505 180 : IF (.NOT. PRESENT(ionode)) CPABORT("IONODE?")
506 180 : IF (.NOT. PRESENT(scr)) CPABORT("SCR?")
507 180 : IF (ionode) THEN
508 225 : DO i = 1, ncol_global, 4
509 135 : j = MIN(3, ncol_global - i)
510 90 : SELECT CASE (j)
511 : CASE (3)
512 104 : WRITE (scr, '(1X,4F16.8)') evals(i:i + j)
513 : CASE (2)
514 2 : WRITE (scr, '(1X,3F16.8)') evals(i:i + j)
515 : CASE (1)
516 7 : WRITE (scr, '(1X,2F16.8)') evals(i:i + j)
517 : CASE (0)
518 135 : WRITE (scr, '(1X,1F16.8)') evals(i:i + j)
519 : END SELECT
520 : END DO
521 : END IF
522 : END IF
523 :
524 8093 : CALL cp_fm_release(weighted_vectors)
525 8093 : CALL cp_fm_release(h_block)
526 : IF (compute_evecs) THEN
527 8093 : CALL cp_fm_release(e_vectors)
528 : END IF
529 :
530 24279 : DEALLOCATE (evals)
531 :
532 : END IF
533 :
534 8179 : CALL timestop(handle)
535 :
536 16358 : END SUBROUTINE subspace_eigenvalues_ks_fm
537 :
538 : ! **************************************************************************************************
539 : !> \brief ...
540 : !> \param orbitals ...
541 : !> \param ks_matrix ...
542 : !> \param evals_arg ...
543 : !> \param ionode ...
544 : !> \param scr ...
545 : !> \param do_rotation ...
546 : !> \param co_rotate ...
547 : !> \param para_env ...
548 : !> \param blacs_env ...
549 : ! **************************************************************************************************
550 6290 : SUBROUTINE subspace_eigenvalues_ks_dbcsr(orbitals, ks_matrix, evals_arg, ionode, scr, &
551 : do_rotation, co_rotate, para_env, blacs_env)
552 :
553 : TYPE(dbcsr_type), POINTER :: orbitals, ks_matrix
554 : REAL(KIND=dp), DIMENSION(:), OPTIONAL :: evals_arg
555 : LOGICAL, INTENT(IN), OPTIONAL :: ionode
556 : INTEGER, INTENT(IN), OPTIONAL :: scr
557 : LOGICAL, INTENT(IN), OPTIONAL :: do_rotation
558 : TYPE(dbcsr_type), OPTIONAL, POINTER :: co_rotate
559 : TYPE(mp_para_env_type), POINTER :: para_env
560 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
561 :
562 : CHARACTER(len=*), PARAMETER :: routineN = 'subspace_eigenvalues_ks_dbcsr'
563 :
564 : INTEGER :: handle, i, j, ncol_global, nrow_global
565 : LOGICAL :: compute_evecs, do_rotation_local
566 6290 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: evals
567 : TYPE(dbcsr_type), POINTER :: e_vectors, h_block, weighted_vectors
568 :
569 6290 : CALL timeset(routineN, handle)
570 :
571 6290 : do_rotation_local = .TRUE.
572 6290 : IF (PRESENT(do_rotation)) do_rotation_local = do_rotation
573 :
574 6290 : NULLIFY (e_vectors, h_block, weighted_vectors)
575 :
576 : CALL dbcsr_get_info(matrix=orbitals, &
577 : nfullcols_total=ncol_global, &
578 6290 : nfullrows_total=nrow_global)
579 :
580 : IF (do_rotation_local) THEN
581 : compute_evecs = .TRUE.
582 : ELSE
583 : ! this would be the logical choice if syevx computing only evals were faster than syevd computing evecs and evals.
584 : compute_evecs = .FALSE.
585 : ! this is not the case, so lets compute evecs always
586 : compute_evecs = .TRUE.
587 : END IF
588 :
589 6290 : IF (ncol_global > 0) THEN
590 :
591 18234 : ALLOCATE (evals(ncol_global))
592 :
593 6078 : CALL dbcsr_init_p(weighted_vectors)
594 6078 : CALL dbcsr_copy(weighted_vectors, orbitals, name="weighted_vectors")
595 :
596 6078 : CALL dbcsr_init_p(h_block)
597 : CALL cp_dbcsr_m_by_n_from_template(h_block, template=orbitals, m=ncol_global, n=ncol_global, &
598 6078 : sym=dbcsr_type_no_symmetry)
599 :
600 : !!!!!!!!!!!!!!XXXXXXXXXXXXXXXXXXX!!!!!!!!!!!!!
601 : IF (compute_evecs) THEN
602 6078 : CALL dbcsr_init_p(e_vectors)
603 : CALL cp_dbcsr_m_by_n_from_template(e_vectors, template=orbitals, m=ncol_global, n=ncol_global, &
604 6078 : sym=dbcsr_type_no_symmetry)
605 : END IF
606 :
607 : ! h subblock and diag
608 : CALL dbcsr_multiply('N', 'N', 1.0_dp, ks_matrix, orbitals, &
609 6078 : 0.0_dp, weighted_vectors)
610 : !CALL cp_dbcsr_sm_fm_multiply(ks_matrix,orbitals,weighted_vectors, ncol_global)
611 :
612 6078 : CALL dbcsr_multiply('T', 'N', 1.0_dp, orbitals, weighted_vectors, 0.0_dp, h_block)
613 : !CALL parallel_gemm('T','N',ncol_global,ncol_global,nrow_global,1.0_dp, &
614 : ! orbitals,weighted_vectors,0.0_dp,h_block)
615 :
616 : ! if eigenvectors are required, go for syevd, otherwise only compute eigenvalues
617 : IF (compute_evecs) THEN
618 6078 : CALL cp_dbcsr_syevd(h_block, e_vectors, evals, para_env=para_env, blacs_env=blacs_env)
619 : ELSE
620 : CALL cp_dbcsr_syevx(h_block, eigenvalues=evals, para_env=para_env, blacs_env=blacs_env)
621 : END IF
622 :
623 : ! rotate the orbitals
624 6078 : IF (do_rotation_local) THEN
625 2972 : CALL dbcsr_multiply('N', 'N', 1.0_dp, orbitals, e_vectors, 0.0_dp, weighted_vectors)
626 : !CALL parallel_gemm('N','N',nrow_global,ncol_global,ncol_global,1.0_dp, &
627 : ! orbitals,e_vectors,0.0_dp,weighted_vectors)
628 2972 : CALL dbcsr_copy(orbitals, weighted_vectors)
629 : !CALL cp_fm_to_fm(weighted_vectors,orbitals)
630 2972 : IF (PRESENT(co_rotate)) THEN
631 2954 : IF (ASSOCIATED(co_rotate)) THEN
632 2954 : CALL dbcsr_multiply('N', 'N', 1.0_dp, co_rotate, e_vectors, 0.0_dp, weighted_vectors)
633 : !CALL parallel_gemm('N','N',nrow_global,ncol_global,ncol_global,1.0_dp, &
634 : ! co_rotate,e_vectors,0.0_dp,weighted_vectors)
635 2954 : CALL dbcsr_copy(co_rotate, weighted_vectors)
636 : !CALL cp_fm_to_fm(weighted_vectors,co_rotate)
637 : END IF
638 : END IF
639 : END IF
640 :
641 : ! give output
642 6078 : IF (PRESENT(evals_arg)) THEN
643 19182 : evals_arg(:) = evals(:)
644 : END IF
645 :
646 6078 : IF (PRESENT(ionode) .OR. PRESENT(scr)) THEN
647 0 : IF (.NOT. PRESENT(ionode)) CPABORT("IONODE?")
648 0 : IF (.NOT. PRESENT(scr)) CPABORT("SCR?")
649 0 : IF (ionode) THEN
650 0 : DO i = 1, ncol_global, 4
651 0 : j = MIN(3, ncol_global - i)
652 0 : SELECT CASE (j)
653 : CASE (3)
654 0 : WRITE (scr, '(1X,4F16.8)') evals(i:i + j)
655 : CASE (2)
656 0 : WRITE (scr, '(1X,3F16.8)') evals(i:i + j)
657 : CASE (1)
658 0 : WRITE (scr, '(1X,2F16.8)') evals(i:i + j)
659 : CASE (0)
660 0 : WRITE (scr, '(1X,1F16.8)') evals(i:i + j)
661 : END SELECT
662 : END DO
663 : END IF
664 : END IF
665 :
666 6078 : CALL dbcsr_release_p(weighted_vectors)
667 6078 : CALL dbcsr_release_p(h_block)
668 : IF (compute_evecs) THEN
669 6078 : CALL dbcsr_release_p(e_vectors)
670 : END IF
671 :
672 6078 : DEALLOCATE (evals)
673 :
674 : END IF
675 :
676 6290 : CALL timestop(handle)
677 :
678 6290 : END SUBROUTINE subspace_eigenvalues_ks_dbcsr
679 :
680 : ! computes the effective orthonormality of a set of mos given an s-matrix
681 : ! orthonormality is the max deviation from unity of the C^T S C
682 : ! **************************************************************************************************
683 : !> \brief ...
684 : !> \param orthonormality ...
685 : !> \param mo_array ...
686 : !> \param matrix_s ...
687 : ! **************************************************************************************************
688 1376 : SUBROUTINE calculate_orthonormality(orthonormality, mo_array, matrix_s)
689 : REAL(KIND=dp) :: orthonormality
690 : TYPE(mo_set_type), DIMENSION(:), INTENT(IN) :: mo_array
691 : TYPE(dbcsr_type), OPTIONAL, POINTER :: matrix_s
692 :
693 : CHARACTER(len=*), PARAMETER :: routineN = 'calculate_orthonormality'
694 :
695 : INTEGER :: handle, i, ispin, j, k, n, ncol_local, &
696 : nrow_local, nspin
697 1376 : INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
698 : REAL(KIND=dp) :: alpha, max_alpha
699 : TYPE(cp_fm_struct_type), POINTER :: tmp_fm_struct
700 : TYPE(cp_fm_type) :: overlap, svec
701 :
702 1376 : NULLIFY (tmp_fm_struct)
703 :
704 1376 : CALL timeset(routineN, handle)
705 :
706 1376 : nspin = SIZE(mo_array)
707 1376 : max_alpha = 0.0_dp
708 :
709 2764 : DO ispin = 1, nspin
710 1388 : IF (PRESENT(matrix_s)) THEN
711 : ! get S*C
712 1330 : CALL cp_fm_create(svec, mo_array(ispin)%mo_coeff%matrix_struct)
713 : CALL cp_fm_get_info(mo_array(ispin)%mo_coeff, &
714 1330 : nrow_global=n, ncol_global=k)
715 : CALL cp_dbcsr_sm_fm_multiply(matrix_s, mo_array(ispin)%mo_coeff, &
716 1330 : svec, k)
717 : ! get C^T (S*C)
718 : CALL cp_fm_struct_create(tmp_fm_struct, nrow_global=k, ncol_global=k, &
719 : para_env=mo_array(ispin)%mo_coeff%matrix_struct%para_env, &
720 1330 : context=mo_array(ispin)%mo_coeff%matrix_struct%context)
721 1330 : CALL cp_fm_create(overlap, tmp_fm_struct)
722 1330 : CALL cp_fm_struct_release(tmp_fm_struct)
723 : CALL parallel_gemm('T', 'N', k, k, n, 1.0_dp, mo_array(ispin)%mo_coeff, &
724 1330 : svec, 0.0_dp, overlap)
725 1330 : CALL cp_fm_release(svec)
726 : ELSE
727 : ! orthogonal basis C^T C
728 : CALL cp_fm_get_info(mo_array(ispin)%mo_coeff, &
729 58 : nrow_global=n, ncol_global=k)
730 : CALL cp_fm_struct_create(tmp_fm_struct, nrow_global=k, ncol_global=k, &
731 : para_env=mo_array(ispin)%mo_coeff%matrix_struct%para_env, &
732 58 : context=mo_array(ispin)%mo_coeff%matrix_struct%context)
733 58 : CALL cp_fm_create(overlap, tmp_fm_struct)
734 58 : CALL cp_fm_struct_release(tmp_fm_struct)
735 : CALL parallel_gemm('T', 'N', k, k, n, 1.0_dp, mo_array(ispin)%mo_coeff, &
736 58 : mo_array(ispin)%mo_coeff, 0.0_dp, overlap)
737 : END IF
738 : CALL cp_fm_get_info(overlap, nrow_local=nrow_local, ncol_local=ncol_local, &
739 1388 : row_indices=row_indices, col_indices=col_indices)
740 9835 : DO i = 1, nrow_local
741 453292 : DO j = 1, ncol_local
742 443457 : alpha = overlap%local_data(i, j)
743 443457 : IF (row_indices(i) == col_indices(j)) alpha = alpha - 1.0_dp
744 451904 : max_alpha = MAX(max_alpha, ABS(alpha))
745 : END DO
746 : END DO
747 4152 : CALL cp_fm_release(overlap)
748 : END DO
749 1376 : CALL mo_array(1)%mo_coeff%matrix_struct%para_env%max(max_alpha)
750 1376 : orthonormality = max_alpha
751 : ! write(*,*) "max deviation from orthonormalization ",orthonormality
752 :
753 1376 : CALL timestop(handle)
754 :
755 1376 : END SUBROUTINE calculate_orthonormality
756 :
757 : ! computes the minimum/maximum magnitudes of C^T C. This could be useful
758 : ! to detect problems in the case of nearly singular overlap matrices.
759 : ! in this case, we expect the ratio of min/max to be large
760 : ! this routine is only similar to mo_orthonormality if S==1
761 : ! **************************************************************************************************
762 : !> \brief ...
763 : !> \param mo_array ...
764 : !> \param mo_mag_min ...
765 : !> \param mo_mag_max ...
766 : ! **************************************************************************************************
767 1356 : SUBROUTINE calculate_magnitude(mo_array, mo_mag_min, mo_mag_max)
768 : TYPE(mo_set_type), DIMENSION(:), INTENT(IN) :: mo_array
769 : REAL(KIND=dp) :: mo_mag_min, mo_mag_max
770 :
771 : CHARACTER(len=*), PARAMETER :: routineN = 'calculate_magnitude'
772 :
773 : INTEGER :: handle, ispin, k, n, nspin
774 1356 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: evals
775 : TYPE(cp_fm_struct_type), POINTER :: tmp_fm_struct
776 : TYPE(cp_fm_type) :: evecs, overlap
777 :
778 1356 : NULLIFY (tmp_fm_struct)
779 :
780 1356 : CALL timeset(routineN, handle)
781 :
782 1356 : nspin = SIZE(mo_array)
783 1356 : mo_mag_min = HUGE(0.0_dp)
784 1356 : mo_mag_max = -HUGE(0.0_dp)
785 2712 : DO ispin = 1, nspin
786 : CALL cp_fm_get_info(mo_array(ispin)%mo_coeff, &
787 1356 : nrow_global=n, ncol_global=k)
788 4068 : ALLOCATE (evals(k))
789 : CALL cp_fm_struct_create(tmp_fm_struct, nrow_global=k, ncol_global=k, &
790 : para_env=mo_array(ispin)%mo_coeff%matrix_struct%para_env, &
791 1356 : context=mo_array(ispin)%mo_coeff%matrix_struct%context)
792 1356 : CALL cp_fm_create(overlap, tmp_fm_struct)
793 1356 : CALL cp_fm_create(evecs, tmp_fm_struct)
794 1356 : CALL cp_fm_struct_release(tmp_fm_struct)
795 : CALL parallel_gemm('T', 'N', k, k, n, 1.0_dp, mo_array(ispin)%mo_coeff, &
796 1356 : mo_array(ispin)%mo_coeff, 0.0_dp, overlap)
797 1356 : CALL choose_eigv_solver(overlap, evecs, evals)
798 19474 : mo_mag_min = MIN(MINVAL(evals), mo_mag_min)
799 19474 : mo_mag_max = MAX(MAXVAL(evals), mo_mag_max)
800 1356 : CALL cp_fm_release(overlap)
801 1356 : CALL cp_fm_release(evecs)
802 5424 : DEALLOCATE (evals)
803 : END DO
804 1356 : CALL timestop(handle)
805 :
806 2712 : END SUBROUTINE calculate_magnitude
807 :
808 : ! **************************************************************************************************
809 : !> \brief Calculate KS eigenvalues starting from OF MOS
810 : !> \param mos ...
811 : !> \param nspins ...
812 : !> \param ks_rmpv ...
813 : !> \param scf_control ...
814 : !> \param mo_derivs ...
815 : !> \param admm_env ...
816 : !> \param hairy_probes ...
817 : !> \param probe ...
818 : !> \par History
819 : !> 02.2013 moved from qs_scf_post_gpw
820 : !>
821 : ! **************************************************************************************************
822 202 : SUBROUTINE make_mo_eig(mos, nspins, ks_rmpv, scf_control, mo_derivs, admm_env, &
823 : hairy_probes, probe)
824 :
825 : TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT) :: mos
826 : INTEGER, INTENT(IN) :: nspins
827 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: ks_rmpv
828 : TYPE(scf_control_type), POINTER :: scf_control
829 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mo_derivs
830 : TYPE(admm_type), OPTIONAL, POINTER :: admm_env
831 : LOGICAL, OPTIONAL :: hairy_probes
832 : TYPE(hairy_probes_type), DIMENSION(:), OPTIONAL, &
833 : POINTER :: probe
834 :
835 : CHARACTER(len=*), PARAMETER :: routineN = 'make_mo_eig'
836 :
837 : INTEGER :: handle, homo, ispin, nmo, output_unit
838 202 : REAL(KIND=dp), DIMENSION(:), POINTER :: mo_eigenvalues
839 : TYPE(cp_fm_type), POINTER :: mo_coeff
840 : TYPE(dbcsr_type), POINTER :: mo_coeff_deriv
841 :
842 202 : CALL timeset(routineN, handle)
843 :
844 202 : NULLIFY (mo_coeff_deriv, mo_coeff, mo_eigenvalues)
845 202 : output_unit = cp_logger_get_default_io_unit()
846 :
847 444 : DO ispin = 1, nspins
848 : CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, &
849 242 : eigenvalues=mo_eigenvalues, homo=homo, nmo=nmo)
850 242 : IF (output_unit > 0) WRITE (output_unit, *) " "
851 242 : IF (output_unit > 0) WRITE (output_unit, *) " Eigenvalues of the occupied subspace spin ", ispin
852 : ! IF (homo /= nmo) THEN
853 : ! IF (output_unit>0) WRITE(output_unit,*)" and ",nmo-homo," added MO eigenvalues"
854 : ! END IF
855 242 : IF (output_unit > 0) WRITE (output_unit, *) "---------------------------------------------"
856 :
857 242 : IF (scf_control%use_ot) THEN
858 : ! Also rotate the OT derivs, since they are needed for force calculations
859 128 : IF (ASSOCIATED(mo_derivs)) THEN
860 128 : mo_coeff_deriv => mo_derivs(ispin)%matrix
861 : ELSE
862 0 : mo_coeff_deriv => NULL()
863 : END IF
864 :
865 : ! If we do ADMM, we add have to modify the Kohn-Sham matrix
866 128 : IF (PRESENT(admm_env)) THEN
867 0 : CALL admm_correct_for_eigenvalues(ispin, admm_env, ks_rmpv(ispin)%matrix)
868 : END IF
869 :
870 : CALL calculate_subspace_eigenvalues(mo_coeff, ks_rmpv(ispin)%matrix, mo_eigenvalues, &
871 : scr=output_unit, ionode=output_unit > 0, do_rotation=.TRUE., &
872 128 : co_rotate_dbcsr=mo_coeff_deriv)
873 :
874 : ! If we do ADMM, we restore the original Kohn-Sham matrix
875 128 : IF (PRESENT(admm_env)) THEN
876 0 : CALL admm_uncorrect_for_eigenvalues(ispin, admm_env, ks_rmpv(ispin)%matrix)
877 : END IF
878 : ELSE
879 114 : IF (output_unit > 0) WRITE (output_unit, '(4(1X,1F16.8))') mo_eigenvalues(1:homo)
880 : END IF
881 242 : IF (.NOT. scf_control%diagonalization%mom) THEN
882 242 : IF (PRESENT(hairy_probes) .EQV. .TRUE.) THEN
883 0 : scf_control%smear%do_smear = .FALSE.
884 : CALL set_mo_occupation(mo_set=mos(ispin), &
885 : smear=scf_control%smear, &
886 0 : probe=probe)
887 : ELSE
888 242 : CALL set_mo_occupation(mo_set=mos(ispin), smear=scf_control%smear)
889 : END IF
890 : END IF
891 242 : IF (output_unit > 0) WRITE (output_unit, '(T2,A,F12.6)') &
892 565 : "Fermi Energy [eV] :", mos(ispin)%mu*evolt
893 : END DO
894 :
895 202 : CALL timestop(handle)
896 :
897 202 : END SUBROUTINE make_mo_eig
898 :
899 : END MODULE qs_mo_methods
|