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 calculates the electron transfer coupling elements by projection-operator approach
10 : !> Kondov et al. J.Phys.Chem.C 2007, 111, 11970-11981
11 : !> \author Z. Futera (02.2017)
12 : ! **************************************************************************************************
13 : MODULE et_coupling_proj
14 :
15 : USE atomic_kind_types, ONLY: atomic_kind_type,&
16 : get_atomic_kind
17 : USE basis_set_types, ONLY: get_gto_basis_set,&
18 : gto_basis_set_type
19 : USE bibliography, ONLY: Futera2017,&
20 : cite_reference
21 : USE cell_types, ONLY: cell_type
22 : USE cp_blacs_env, ONLY: cp_blacs_env_type
23 : USE cp_control_types, ONLY: dft_control_type
24 : USE cp_dbcsr_api, ONLY: dbcsr_p_type
25 : USE cp_dbcsr_operations, ONLY: copy_dbcsr_to_fm,&
26 : cp_dbcsr_sm_fm_multiply
27 : USE cp_fm_basic_linalg, ONLY: cp_fm_column_scale
28 : USE cp_fm_diag, ONLY: choose_eigv_solver,&
29 : cp_fm_power
30 : USE cp_fm_struct, ONLY: cp_fm_struct_create,&
31 : cp_fm_struct_equivalent,&
32 : cp_fm_struct_release,&
33 : cp_fm_struct_type
34 : USE cp_fm_types, ONLY: &
35 : cp_fm_create, cp_fm_get_element, cp_fm_get_submatrix, cp_fm_release, cp_fm_set_all, &
36 : cp_fm_set_element, cp_fm_to_fm, cp_fm_to_fm_submat, cp_fm_type, cp_fm_vectorssum
37 : USE cp_log_handling, ONLY: cp_get_default_logger,&
38 : cp_logger_type,&
39 : cp_to_string
40 : USE cp_output_handling, ONLY: cp_p_file,&
41 : cp_print_key_finished_output,&
42 : cp_print_key_should_output,&
43 : cp_print_key_unit_nr
44 : USE cp_realspace_grid_cube, ONLY: cp_pw_to_cube
45 : USE input_section_types, ONLY: section_get_ivals,&
46 : section_get_lval,&
47 : section_vals_get,&
48 : section_vals_get_subs_vals,&
49 : section_vals_type,&
50 : section_vals_val_get
51 : USE kinds, ONLY: default_path_length,&
52 : default_string_length,&
53 : dp
54 : USE kpoint_types, ONLY: kpoint_type
55 : USE message_passing, ONLY: mp_para_env_type
56 : USE orbital_pointers, ONLY: nso
57 : USE parallel_gemm_api, ONLY: parallel_gemm
58 : USE particle_list_types, ONLY: particle_list_type
59 : USE particle_types, ONLY: particle_type
60 : USE physcon, ONLY: evolt
61 : USE pw_env_types, ONLY: pw_env_get,&
62 : pw_env_type
63 : USE pw_pool_types, ONLY: pw_pool_p_type,&
64 : pw_pool_type
65 : USE pw_types, ONLY: pw_c1d_gs_type,&
66 : pw_r3d_rs_type
67 : USE qs_collocate_density, ONLY: calculate_wavefunction
68 : USE qs_environment_types, ONLY: get_qs_env,&
69 : qs_environment_type
70 : USE qs_kind_types, ONLY: get_qs_kind,&
71 : get_qs_kind_set,&
72 : qs_kind_type
73 : USE qs_mo_methods, ONLY: make_mo_eig
74 : USE qs_mo_occupation, ONLY: set_mo_occupation
75 : USE qs_mo_types, ONLY: allocate_mo_set,&
76 : deallocate_mo_set,&
77 : mo_set_type
78 : USE qs_subsys_types, ONLY: qs_subsys_get,&
79 : qs_subsys_type
80 : USE scf_control_types, ONLY: scf_control_type
81 : #include "./base/base_uses.f90"
82 :
83 : IMPLICIT NONE
84 :
85 : PRIVATE
86 :
87 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'et_coupling_proj'
88 :
89 : ! Electronic-coupling calculation data structure
90 : !
91 : ! n_atoms - number of atoms in the blocks
92 : ! n_blocks - number of atomic blocks (donor,acceptor,bridge,...)
93 : ! fermi - system Fermi level (alpha/beta spin component)
94 : ! m_transf - transformation matrix for basis-set orthogonalization (S^{-1/2})
95 : ! m_transf_inv - inversion transformation matrix
96 : ! block - atomic data blocks
97 : TYPE et_cpl
98 : INTEGER :: n_atoms = 0
99 : INTEGER :: n_blocks = 0
100 : REAL(KIND=dp), DIMENSION(:), POINTER :: fermi => NULL()
101 : TYPE(cp_fm_type), POINTER :: m_transf => NULL()
102 : TYPE(cp_fm_type), POINTER :: m_transf_inv => NULL()
103 : TYPE(et_cpl_block), DIMENSION(:), POINTER :: block => NULL()
104 : END TYPE et_cpl
105 :
106 : ! Electronic-coupling data block
107 : !
108 : ! n_atoms - number of atoms
109 : ! n_electrons - number of electrons
110 : ! n_ao - number of AO basis functions
111 : ! atom - list of atoms
112 : ! mo - electronic states
113 : ! hab - electronic-coupling elements
114 : TYPE et_cpl_block
115 : INTEGER :: n_atoms = 0
116 : INTEGER :: n_electrons = 0
117 : INTEGER :: n_ao = 0
118 : TYPE(et_cpl_atom), DIMENSION(:), POINTER :: atom => NULL()
119 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mo => NULL()
120 : TYPE(cp_fm_type), DIMENSION(:, :), POINTER :: hab => NULL()
121 : END TYPE et_cpl_block
122 :
123 : ! Electronic-coupling block-atom data
124 : ! id - atom ID
125 : ! n_ao - number of AO basis functions
126 : ! ao_pos - position of atom in array of AO functions
127 : TYPE et_cpl_atom
128 : INTEGER :: id = 0
129 : INTEGER :: n_ao = 0
130 : INTEGER :: ao_pos = 0
131 : END TYPE et_cpl_atom
132 :
133 : PUBLIC :: calc_et_coupling_proj
134 :
135 : CONTAINS
136 :
137 : ! **************************************************************************************************
138 : !> \brief Release memory allocate for electronic coupling data structures
139 : !> \param ec electronic coupling data structure
140 : !> \author Z. Futera (02.2017)
141 : ! **************************************************************************************************
142 10 : SUBROUTINE release_ec_data(ec)
143 :
144 : ! Routine arguments
145 : TYPE(et_cpl), POINTER :: ec
146 :
147 : INTEGER :: i, j
148 :
149 : ! Routine name for debug purposes
150 :
151 10 : IF (ASSOCIATED(ec)) THEN
152 :
153 10 : IF (ASSOCIATED(ec%fermi)) THEN
154 10 : DEALLOCATE (ec%fermi)
155 : END IF
156 10 : IF (ASSOCIATED(ec%m_transf)) THEN
157 10 : CALL cp_fm_release(matrix=ec%m_transf)
158 10 : DEALLOCATE (ec%m_transf)
159 10 : NULLIFY (ec%m_transf)
160 : END IF
161 10 : IF (ASSOCIATED(ec%m_transf_inv)) THEN
162 10 : CALL cp_fm_release(matrix=ec%m_transf_inv)
163 10 : DEALLOCATE (ec%m_transf_inv)
164 10 : NULLIFY (ec%m_transf_inv)
165 : END IF
166 :
167 10 : IF (ASSOCIATED(ec%block)) THEN
168 :
169 30 : DO i = 1, SIZE(ec%block)
170 20 : IF (ASSOCIATED(ec%block(i)%atom)) THEN
171 20 : DEALLOCATE (ec%block(i)%atom)
172 : END IF
173 20 : IF (ASSOCIATED(ec%block(i)%mo)) THEN
174 60 : DO j = 1, SIZE(ec%block(i)%mo)
175 60 : CALL deallocate_mo_set(ec%block(i)%mo(j))
176 : END DO
177 20 : DEALLOCATE (ec%block(i)%mo)
178 : END IF
179 30 : CALL cp_fm_release(ec%block(i)%hab)
180 : END DO
181 :
182 10 : DEALLOCATE (ec%block)
183 :
184 : END IF
185 :
186 10 : DEALLOCATE (ec)
187 :
188 : END IF
189 :
190 10 : END SUBROUTINE release_ec_data
191 :
192 : ! **************************************************************************************************
193 : !> \brief check the electronic-coupling input section and set the atomic block data
194 : !> \param qs_env QuickStep environment containing all system data
195 : !> \param et_proj_sec the electronic-coupling input section
196 : !> \param ec electronic coupling data structure
197 : !> \author Z. Futera (02.2017)
198 : ! **************************************************************************************************
199 10 : SUBROUTINE set_block_data(qs_env, et_proj_sec, ec)
200 :
201 : ! Routine arguments
202 : TYPE(qs_environment_type), POINTER :: qs_env
203 : TYPE(section_vals_type), POINTER :: et_proj_sec
204 : TYPE(et_cpl), POINTER :: ec
205 :
206 : INTEGER :: i, j, k, l, n, n_ao, n_atoms, n_set
207 10 : INTEGER, DIMENSION(:), POINTER :: atom_id, atom_nf, atom_ps, n_shell, t
208 10 : INTEGER, DIMENSION(:, :), POINTER :: ang_mom_id
209 : LOGICAL :: found
210 : TYPE(gto_basis_set_type), POINTER :: ao_basis_set
211 10 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
212 10 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
213 : TYPE(section_vals_type), POINTER :: block_sec
214 :
215 : ! Routine name for debug purposes
216 :
217 10 : NULLIFY (ao_basis_set)
218 10 : NULLIFY (particle_set)
219 10 : NULLIFY (qs_kind_set)
220 10 : NULLIFY (n_shell)
221 10 : NULLIFY (ang_mom_id)
222 10 : NULLIFY (atom_nf)
223 10 : NULLIFY (atom_id)
224 10 : NULLIFY (block_sec)
225 :
226 : ! Initialization
227 10 : ec%n_atoms = 0
228 10 : ec%n_blocks = 0
229 10 : NULLIFY (ec%fermi)
230 10 : NULLIFY (ec%m_transf)
231 10 : NULLIFY (ec%m_transf_inv)
232 10 : NULLIFY (ec%block)
233 :
234 : ! Number of atoms / atom types
235 10 : CALL get_qs_env(qs_env, particle_set=particle_set, qs_kind_set=qs_kind_set, natom=n_atoms)
236 : ! Number of AO basis functions
237 10 : CALL get_qs_kind_set(qs_kind_set, nsgf=n_ao)
238 :
239 : ! Number of AO functions per atom
240 30 : ALLOCATE (atom_nf(n_atoms))
241 10 : CPASSERT(ASSOCIATED(atom_nf))
242 :
243 82 : atom_nf = 0
244 82 : DO i = 1, n_atoms
245 72 : CALL get_atomic_kind(particle_set(i)%atomic_kind, kind_number=j)
246 72 : CALL get_qs_kind(qs_kind_set(j), basis_set=ao_basis_set)
247 72 : IF (.NOT. ASSOCIATED(ao_basis_set)) THEN
248 0 : CPABORT('Unsupported basis set type. ')
249 : END IF
250 : CALL get_gto_basis_set(gto_basis_set=ao_basis_set, &
251 72 : nset=n_set, nshell=n_shell, l=ang_mom_id)
252 238 : DO j = 1, n_set
253 280 : DO k = 1, n_shell(j)
254 208 : atom_nf(i) = atom_nf(i) + nso(ang_mom_id(k, j))
255 : END DO
256 : END DO
257 : END DO
258 :
259 : ! Sanity check
260 10 : n = 0
261 82 : DO i = 1, n_atoms
262 82 : n = n + atom_nf(i)
263 : END DO
264 10 : CPASSERT(n == n_ao)
265 :
266 : ! Atom position in AO array
267 30 : ALLOCATE (atom_ps(n_atoms))
268 10 : CPASSERT(ASSOCIATED(atom_ps))
269 82 : atom_ps = 1
270 72 : DO i = 1, n_atoms - 1
271 72 : atom_ps(i + 1) = atom_ps(i) + atom_nf(i)
272 : END DO
273 :
274 : ! Number of blocks
275 10 : block_sec => section_vals_get_subs_vals(et_proj_sec, 'BLOCK')
276 10 : CALL section_vals_get(block_sec, n_repetition=ec%n_blocks)
277 50 : ALLOCATE (ec%block(ec%n_blocks))
278 10 : CPASSERT(ASSOCIATED(ec%block))
279 :
280 : ! Block data
281 30 : ALLOCATE (t(n_atoms))
282 10 : CPASSERT(ASSOCIATED(t))
283 :
284 10 : ec%n_atoms = 0
285 30 : DO i = 1, ec%n_blocks
286 :
287 : ! Initialization
288 20 : ec%block(i)%n_atoms = 0
289 20 : ec%block(i)%n_electrons = 0
290 20 : ec%block(i)%n_ao = 0
291 20 : NULLIFY (ec%block(i)%atom)
292 20 : NULLIFY (ec%block(i)%mo)
293 20 : NULLIFY (ec%block(i)%hab)
294 :
295 : ! Number of electrons
296 : CALL section_vals_val_get(block_sec, i_rep_section=i, &
297 20 : keyword_name='NELECTRON', i_val=ec%block(i)%n_electrons)
298 :
299 : ! User-defined atom array
300 : CALL section_vals_val_get(block_sec, i_rep_section=i, &
301 20 : keyword_name='ATOMS', i_vals=atom_id)
302 :
303 : ! Count unique atoms
304 92 : DO j = 1, SIZE(atom_id)
305 : ! Check atom ID validity
306 72 : IF (atom_id(j) < 1 .OR. atom_id(j) > n_atoms) THEN
307 0 : CPABORT('invalid fragment atom ID ('//TRIM(ADJUSTL(cp_to_string(atom_id(j))))//')')
308 : END IF
309 : ! Check if the atom is not in previously-defined blocks
310 : found = .FALSE.
311 108 : DO k = 1, i - 1
312 348 : DO l = 1, ec%block(k)%n_atoms
313 276 : IF (ec%block(k)%atom(l)%id == atom_id(j)) THEN
314 0 : CPWARN('multiple definition of atom'//TRIM(ADJUSTL(cp_to_string(atom_id(j)))))
315 0 : found = .TRUE.
316 0 : EXIT
317 : END IF
318 : END DO
319 : END DO
320 : ! Check if the atom is not in already defined in the present block
321 72 : IF (.NOT. found) THEN
322 276 : DO k = 1, ec%block(i)%n_atoms
323 276 : IF (t(k) == atom_id(j)) THEN
324 0 : CPWARN('multiple definition of atom'//TRIM(ADJUSTL(cp_to_string(atom_id(j)))))
325 : found = .TRUE.
326 : EXIT
327 : END IF
328 : END DO
329 : END IF
330 : ! Save the atom
331 20 : IF (.NOT. found) THEN
332 72 : ec%block(i)%n_atoms = ec%block(i)%n_atoms + 1
333 72 : t(ec%block(i)%n_atoms) = atom_id(j)
334 : END IF
335 : END DO
336 :
337 : ! Memory allocation
338 132 : ALLOCATE (ec%block(i)%atom(ec%block(i)%n_atoms))
339 20 : CPASSERT(ASSOCIATED(ec%block(i)%atom))
340 :
341 : ! Save atom IDs and number of AOs
342 92 : DO j = 1, ec%block(i)%n_atoms
343 72 : ec%block(i)%atom(j)%id = t(j)
344 72 : ec%block(i)%atom(j)%n_ao = atom_nf(ec%block(i)%atom(j)%id)
345 72 : ec%block(i)%atom(j)%ao_pos = atom_ps(ec%block(i)%atom(j)%id)
346 92 : ec%block(i)%n_ao = ec%block(i)%n_ao + ec%block(i)%atom(j)%n_ao
347 : END DO
348 :
349 30 : ec%n_atoms = ec%n_atoms + ec%block(i)%n_atoms
350 : END DO
351 :
352 : ! Clean memory
353 10 : IF (ASSOCIATED(atom_nf)) THEN
354 10 : DEALLOCATE (atom_nf)
355 : END IF
356 10 : IF (ASSOCIATED(atom_ps)) THEN
357 10 : DEALLOCATE (atom_ps)
358 : END IF
359 10 : IF (ASSOCIATED(t)) THEN
360 10 : DEALLOCATE (t)
361 : END IF
362 :
363 10 : END SUBROUTINE set_block_data
364 :
365 : ! **************************************************************************************************
366 : !> \brief check the electronic-coupling input section and set the atomic block data
367 : !> \param ec electronic coupling data structure
368 : !> \param fa system Fermi level (alpha spin)
369 : !> \param fb system Fermi level (beta spin)
370 : !> \author Z. Futera (02.2017)
371 : ! **************************************************************************************************
372 10 : SUBROUTINE set_fermi(ec, fa, fb)
373 :
374 : ! Routine arguments
375 : TYPE(et_cpl), POINTER :: ec
376 : REAL(KIND=dp) :: fa
377 : REAL(KIND=dp), OPTIONAL :: fb
378 :
379 : ! Routine name for debug purposes
380 :
381 10 : NULLIFY (ec%fermi)
382 :
383 10 : IF (PRESENT(fb)) THEN
384 :
385 10 : ALLOCATE (ec%fermi(2))
386 10 : CPASSERT(ASSOCIATED(ec%fermi))
387 10 : ec%fermi(1) = fa
388 10 : ec%fermi(2) = fb
389 :
390 : ELSE
391 :
392 0 : ALLOCATE (ec%fermi(1))
393 0 : CPASSERT(ASSOCIATED(ec%fermi))
394 0 : ec%fermi(1) = fa
395 :
396 : END IF
397 :
398 10 : END SUBROUTINE set_fermi
399 :
400 : ! **************************************************************************************************
401 : !> \brief reorder Hamiltonian matrix according to defined atomic blocks
402 : !> \param ec electronic coupling data structure
403 : !> \param mat_h the Hamiltonian matrix
404 : !> \param mat_w working matrix of the same dimension
405 : !> \author Z. Futera (02.2017)
406 : ! **************************************************************************************************
407 20 : SUBROUTINE reorder_hamiltonian_matrix(ec, mat_h, mat_w)
408 :
409 : ! Routine arguments
410 : TYPE(et_cpl), POINTER :: ec
411 : TYPE(cp_fm_type), INTENT(IN) :: mat_h, mat_w
412 :
413 : INTEGER :: ic, ir, jc, jr, kc, kr, mc, mr, nc, nr
414 : REAL(KIND=dp) :: xh
415 :
416 : ! Routine name for debug purposes
417 : ! Local variables
418 :
419 20 : IF (.NOT. cp_fm_struct_equivalent(mat_h%matrix_struct, mat_w%matrix_struct)) THEN
420 0 : CPABORT('cannot reorder Hamiltonian, working-matrix structure is not equivalent')
421 : END IF
422 :
423 : ! Matrix-element reordering
424 20 : nr = 1
425 : ! Rows
426 60 : DO ir = 1, ec%n_blocks
427 204 : DO jr = 1, ec%block(ir)%n_atoms
428 592 : DO kr = 1, ec%block(ir)%atom(jr)%n_ao
429 : ! Columns
430 408 : nc = 1
431 1224 : DO ic = 1, ec%n_blocks
432 6072 : DO jc = 1, ec%block(ic)%n_atoms
433 18384 : DO kc = 1, ec%block(ic)%atom(jc)%n_ao
434 12720 : mr = ec%block(ir)%atom(jr)%ao_pos + kr - 1
435 12720 : mc = ec%block(ic)%atom(jc)%ao_pos + kc - 1
436 12720 : CALL cp_fm_get_element(mat_h, nr, nc, xh)
437 12720 : CALL cp_fm_set_element(mat_w, nr, nc, xh)
438 30288 : nc = nc + 1
439 : END DO
440 : END DO
441 : END DO
442 552 : nr = nr + 1
443 : END DO
444 : END DO
445 : END DO
446 :
447 : ! Copy the reordered matrix to original data array
448 20 : CALL cp_fm_to_fm(mat_w, mat_h)
449 :
450 20 : END SUBROUTINE reorder_hamiltonian_matrix
451 :
452 : ! **************************************************************************************************
453 : !> \brief calculated transformation matrix for basis-set orthogonalization (S^{-1/2})
454 : !> \param qs_env QuickStep environment containing all system data
455 : !> \param mat_t storage for the transformation matrix
456 : !> \param mat_i storage for the inversion transformation matrix
457 : !> \param mat_w working matrix of the same dimension
458 : !> \author Z. Futera (02.2017)
459 : ! **************************************************************************************************
460 10 : SUBROUTINE get_s_half_inv_matrix(qs_env, mat_t, mat_i, mat_w)
461 :
462 : ! Routine arguments
463 : TYPE(qs_environment_type), POINTER :: qs_env
464 : TYPE(cp_fm_type), INTENT(INOUT) :: mat_t, mat_i
465 : TYPE(cp_fm_type), INTENT(IN) :: mat_w
466 :
467 : INTEGER :: n_deps
468 10 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mat_s
469 : TYPE(scf_control_type), POINTER :: scf_cntrl
470 :
471 : ! Routine name for debug purposes
472 :
473 10 : NULLIFY (mat_s)
474 10 : NULLIFY (scf_cntrl)
475 :
476 10 : CALL get_qs_env(qs_env, matrix_s=mat_s)
477 10 : CALL copy_dbcsr_to_fm(mat_s(1)%matrix, mat_t)
478 10 : CALL copy_dbcsr_to_fm(mat_s(1)%matrix, mat_i)
479 :
480 : ! Transformation S -> S^{-1/2}
481 10 : CALL get_qs_env(qs_env, scf_control=scf_cntrl)
482 10 : CALL cp_fm_power(mat_t, mat_w, -0.5_dp, scf_cntrl%eps_eigval, n_deps)
483 10 : CALL cp_fm_power(mat_i, mat_w, +0.5_dp, scf_cntrl%eps_eigval, n_deps)
484 : ! Sanity check
485 10 : IF (n_deps /= 0) THEN
486 : CALL cp_warn(__LOCATION__, &
487 : "Overlap matrix exhibits linear dependencies. At least some "// &
488 0 : "eigenvalues have been quenched.")
489 : END IF
490 :
491 10 : END SUBROUTINE get_s_half_inv_matrix
492 :
493 : ! **************************************************************************************************
494 : !> \brief transform KS hamiltonian to orthogonalized block-separated basis set
495 : !> \param qs_env QuickStep environment containing all system data
496 : !> \param ec electronic coupling data structure
497 : !> \param fm_s full-matrix structure used for allocation of KS matrices
498 : !> \param mat_t storage for pointers to the transformed KS matrices
499 : !> \param mat_w working matrix of the same dimension
500 : !> \param n_ao total number of AO basis functions
501 : !> \param n_spins number of spin components
502 : !> \author Z. Futera (02.2017)
503 : ! **************************************************************************************************
504 10 : SUBROUTINE get_block_hamiltonian(qs_env, ec, fm_s, mat_t, mat_w, n_ao, n_spins)
505 :
506 : ! Routine arguments
507 : TYPE(qs_environment_type), POINTER :: qs_env
508 : TYPE(et_cpl), POINTER :: ec
509 : TYPE(cp_fm_struct_type), POINTER :: fm_s
510 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:), &
511 : INTENT(OUT) :: mat_t
512 : TYPE(cp_fm_type), INTENT(IN) :: mat_w
513 : INTEGER :: n_ao, n_spins
514 :
515 : INTEGER :: i
516 10 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mat_h
517 :
518 : ! Routine name for debug purposes
519 :
520 10 : NULLIFY (mat_h)
521 :
522 : ! Memory allocation
523 50 : ALLOCATE (mat_t(n_spins))
524 :
525 : ! KS Hamiltonian
526 10 : CALL get_qs_env(qs_env, matrix_ks=mat_h)
527 : ! Transformation matrix
528 10 : ALLOCATE (ec%m_transf, ec%m_transf_inv)
529 : CALL cp_fm_create(matrix=ec%m_transf, matrix_struct=fm_s, &
530 10 : name='S^(-1/2) TRANSFORMATION MATRIX')
531 : CALL cp_fm_create(matrix=ec%m_transf_inv, matrix_struct=fm_s, &
532 10 : name='S^(+1/2) TRANSFORMATION MATRIX')
533 10 : CALL get_s_half_inv_matrix(qs_env, ec%m_transf, ec%m_transf_inv, mat_w)
534 :
535 30 : DO i = 1, n_spins
536 :
537 : ! Full-matrix format
538 : CALL cp_fm_create(matrix=mat_t(i), matrix_struct=fm_s, &
539 20 : name='KS HAMILTONIAN IN SEPARATED ORTHOGONALIZED BASIS SET')
540 20 : CALL copy_dbcsr_to_fm(mat_h(i)%matrix, mat_t(i))
541 :
542 : ! Transform KS Hamiltonian to the orthogonalized AO basis set
543 20 : CALL parallel_gemm("N", "N", n_ao, n_ao, n_ao, 1.0_dp, ec%m_transf, mat_t(i), 0.0_dp, mat_w)
544 20 : CALL parallel_gemm("N", "N", n_ao, n_ao, n_ao, 1.0_dp, mat_w, ec%m_transf, 0.0_dp, mat_t(i))
545 :
546 : ! Reorder KS Hamiltonain elements to defined block structure
547 30 : CALL reorder_hamiltonian_matrix(ec, mat_t(i), mat_w)
548 :
549 : END DO
550 :
551 10 : END SUBROUTINE get_block_hamiltonian
552 :
553 : ! **************************************************************************************************
554 : !> \brief Diagonalize diagonal blocks of the KS hamiltonian in separated orthogonalized basis set
555 : !> \param qs_env QuickStep environment containing all system data
556 : !> \param ec electronic coupling data structure
557 : !> \param mat_h Hamiltonian in separated orthogonalized basis set
558 : !> \author Z. Futera (02.2017)
559 : ! **************************************************************************************************
560 10 : SUBROUTINE hamiltonian_block_diag(qs_env, ec, mat_h)
561 :
562 : ! Routine arguments
563 : TYPE(qs_environment_type), POINTER :: qs_env
564 : TYPE(et_cpl), POINTER :: ec
565 : TYPE(cp_fm_type), DIMENSION(:), INTENT(IN) :: mat_h
566 :
567 : INTEGER :: i, j, k, l, n_spins, spin
568 10 : REAL(KIND=dp), DIMENSION(:), POINTER :: vec_e
569 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
570 : TYPE(cp_fm_struct_type), POINTER :: fm_s
571 : TYPE(cp_fm_type) :: mat_u
572 10 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: dat
573 : TYPE(mp_para_env_type), POINTER :: para_env
574 :
575 : ! Routine name for debug purposes
576 :
577 10 : NULLIFY (vec_e)
578 10 : NULLIFY (blacs_env)
579 10 : NULLIFY (para_env)
580 10 : NULLIFY (fm_s)
581 :
582 : ! Parallel environment
583 10 : CALL get_qs_env(qs_env, para_env=para_env, blacs_env=blacs_env)
584 :
585 : ! Storage for block sub-matrices
586 50 : ALLOCATE (dat(ec%n_blocks))
587 10 : CPASSERT(ALLOCATED(dat))
588 :
589 : ! Storage for electronic states and couplings
590 10 : n_spins = SIZE(mat_h)
591 30 : DO i = 1, ec%n_blocks
592 100 : ALLOCATE (ec%block(i)%mo(n_spins))
593 20 : CPASSERT(ASSOCIATED(ec%block(i)%mo))
594 200 : ALLOCATE (ec%block(i)%hab(n_spins, ec%n_blocks))
595 30 : CPASSERT(ASSOCIATED(ec%block(i)%hab))
596 : END DO
597 :
598 : ! Spin components
599 30 : DO spin = 1, n_spins
600 :
601 : ! Diagonal blocks
602 20 : j = 1
603 60 : DO i = 1, ec%n_blocks
604 :
605 : ! Memory allocation
606 : CALL cp_fm_struct_create(fmstruct=fm_s, para_env=para_env, context=blacs_env, &
607 40 : nrow_global=ec%block(i)%n_ao, ncol_global=ec%block(i)%n_ao)
608 : CALL cp_fm_create(matrix=dat(i), matrix_struct=fm_s, &
609 40 : name='H_KS DIAGONAL BLOCK')
610 :
611 120 : ALLOCATE (vec_e(ec%block(i)%n_ao))
612 40 : CPASSERT(ASSOCIATED(vec_e))
613 :
614 : ! Copy block data
615 : CALL cp_fm_to_fm_submat(mat_h(spin), &
616 : dat(i), ec%block(i)%n_ao, &
617 40 : ec%block(i)%n_ao, j, j, 1, 1)
618 :
619 : ! Diagonalization
620 40 : CALL cp_fm_create(matrix=mat_u, matrix_struct=fm_s, name='UNITARY MATRIX')
621 40 : CALL choose_eigv_solver(dat(i), mat_u, vec_e)
622 40 : CALL cp_fm_to_fm(mat_u, dat(i))
623 :
624 : ! Save state energies / vectors
625 40 : CALL create_block_mo_set(qs_env, ec, i, spin, mat_u, vec_e)
626 :
627 : ! Clean memory
628 40 : CALL cp_fm_struct_release(fmstruct=fm_s)
629 40 : CALL cp_fm_release(matrix=mat_u)
630 40 : DEALLOCATE (vec_e)
631 :
632 : ! Off-set for next block
633 100 : j = j + ec%block(i)%n_ao
634 :
635 : END DO
636 :
637 : ! Off-diagonal blocks
638 20 : k = 1
639 60 : DO i = 1, ec%n_blocks
640 40 : l = 1
641 120 : DO j = 1, ec%n_blocks
642 80 : IF (i /= j) THEN
643 :
644 : ! Memory allocation
645 : CALL cp_fm_struct_create(fmstruct=fm_s, para_env=para_env, context=blacs_env, &
646 40 : nrow_global=ec%block(i)%n_ao, ncol_global=ec%block(j)%n_ao)
647 : CALL cp_fm_create(matrix=ec%block(i)%hab(spin, j), matrix_struct=fm_s, &
648 40 : name='H_KS OFF-DIAGONAL BLOCK')
649 :
650 : ! Copy block data
651 : CALL cp_fm_to_fm_submat(mat_h(spin), &
652 : ec%block(i)%hab(spin, j), ec%block(i)%n_ao, &
653 40 : ec%block(j)%n_ao, k, l, 1, 1)
654 :
655 : ! Transformation
656 40 : CALL cp_fm_create(matrix=mat_u, matrix_struct=fm_s, name='FULL WORK MATRIX')
657 : CALL parallel_gemm("T", "N", ec%block(i)%n_ao, ec%block(j)%n_ao, ec%block(i)%n_ao, &
658 40 : 1.0_dp, dat(i), ec%block(i)%hab(spin, j), 0.0_dp, mat_u)
659 : CALL parallel_gemm("N", "N", ec%block(i)%n_ao, ec%block(j)%n_ao, ec%block(j)%n_ao, &
660 40 : 1.0_dp, mat_u, dat(j), 0.0_dp, ec%block(i)%hab(spin, j))
661 :
662 : ! Clean memory
663 40 : CALL cp_fm_struct_release(fmstruct=fm_s)
664 40 : CALL cp_fm_release(matrix=mat_u)
665 :
666 : END IF
667 : ! Off-set for next block
668 120 : l = l + ec%block(j)%n_ao
669 : END DO
670 : ! Off-set for next block
671 60 : k = k + ec%block(i)%n_ao
672 : END DO
673 :
674 : ! Clean memory
675 30 : IF (ALLOCATED(dat)) THEN
676 60 : DO i = 1, SIZE(dat)
677 60 : CALL cp_fm_release(dat(i))
678 : END DO
679 : END IF
680 : END DO
681 :
682 : ! Clean memory
683 10 : IF (ALLOCATED(dat)) THEN
684 10 : DEALLOCATE (dat)
685 : END IF
686 :
687 20 : END SUBROUTINE hamiltonian_block_diag
688 :
689 : ! **************************************************************************************************
690 : !> \brief Return sum of selected squared MO coefficients
691 : !> \param blk_at list of atoms in the block
692 : !> \param mo array of MO sets
693 : !> \param id state index
694 : !> \param atom list of atoms for MO coefficient summing
695 : !> \return ...
696 : !> \author Z. Futera (02.2017)
697 : ! **************************************************************************************************
698 0 : FUNCTION get_mo_c2_sum(blk_at, mo, id, atom) RESULT(c2)
699 :
700 : ! Routine arguments
701 : TYPE(et_cpl_atom), DIMENSION(:), POINTER :: blk_at
702 : TYPE(cp_fm_type), INTENT(IN) :: mo
703 : INTEGER, INTENT(IN) :: id
704 : INTEGER, DIMENSION(:), POINTER :: atom
705 : REAL(KIND=dp) :: c2
706 :
707 : INTEGER :: i, ir, j, k
708 : LOGICAL :: found
709 : REAL(KIND=dp) :: c
710 :
711 : ! Returning value
712 : ! Routine name for debug purposes
713 : ! Local variables
714 :
715 : ! initialization
716 0 : c2 = 0.0d0
717 :
718 : ! selected atoms
719 0 : DO i = 1, SIZE(atom)
720 :
721 : ! find atomic function offset
722 0 : found = .FALSE.
723 0 : DO j = 1, SIZE(blk_at)
724 0 : IF (blk_at(j)%id == atom(i)) THEN
725 : found = .TRUE.
726 : EXIT
727 : END IF
728 : END DO
729 :
730 0 : IF (.NOT. found) THEN
731 0 : CPABORT('MO-fraction atom ID not defined in the block')
732 : END IF
733 :
734 : ! sum MO coefficients from the atom
735 0 : DO k = 1, blk_at(j)%n_ao
736 0 : ir = blk_at(j)%ao_pos + k - 1
737 0 : CALL cp_fm_get_element(mo, ir, id, c)
738 0 : c2 = c2 + c*c
739 : END DO
740 :
741 : END DO
742 :
743 0 : END FUNCTION get_mo_c2_sum
744 :
745 : ! **************************************************************************************************
746 : !> \brief Print out specific MO coefficients
747 : !> \param output_unit unit number of the open output stream
748 : !> \param qs_env QuickStep environment containing all system data
749 : !> \param ec electronic coupling data structure
750 : !> \param blk atomic-block ID
751 : !> \param n_spins number of spin components
752 : !> \author Z. Futera (02.2017)
753 : ! **************************************************************************************************
754 20 : SUBROUTINE print_mo_coeff(output_unit, qs_env, ec, blk, n_spins)
755 :
756 : ! Routine arguments
757 : INTEGER, INTENT(IN) :: output_unit
758 : TYPE(qs_environment_type), POINTER :: qs_env
759 : TYPE(et_cpl), POINTER :: ec
760 : INTEGER, INTENT(IN) :: blk, n_spins
761 :
762 : INTEGER :: j, k, l, m, n, n_ao, n_mo
763 20 : INTEGER, DIMENSION(:), POINTER :: list_at, list_mo
764 : REAL(KIND=dp) :: c1, c2
765 20 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: mat_w
766 20 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
767 : TYPE(section_vals_type), POINTER :: block_sec, print_sec
768 :
769 : ! Routine name for debug purposes
770 :
771 20 : NULLIFY (block_sec)
772 20 : NULLIFY (print_sec)
773 20 : NULLIFY (qs_kind_set)
774 :
775 : ! Atomic block data
776 : block_sec => section_vals_get_subs_vals(qs_env%input, &
777 40 : 'PROPERTIES%ET_COUPLING%PROJECTION%BLOCK')
778 :
779 20 : print_sec => section_vals_get_subs_vals(block_sec, 'PRINT', i_rep_section=blk)
780 :
781 : ! List of atoms
782 20 : CALL section_vals_val_get(print_sec, keyword_name='MO_COEFF_ATOM', n_rep_val=n)
783 :
784 20 : IF (n > 0) THEN
785 :
786 0 : IF (output_unit > 0) THEN
787 0 : WRITE (output_unit, '(/,T3,A/)') 'Block state fractions:'
788 : END IF
789 :
790 : ! Number of AO functions
791 0 : CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set)
792 0 : CALL get_qs_kind_set(qs_kind_set, nsgf=n_ao)
793 :
794 : ! MOs in orthonormal basis set
795 0 : ALLOCATE (mat_w(n_spins))
796 0 : DO j = 1, n_spins
797 0 : n_mo = ec%block(blk)%n_ao
798 : CALL cp_fm_create(matrix=mat_w(j), &
799 : matrix_struct=ec%block(blk)%mo(j)%mo_coeff%matrix_struct, &
800 0 : name='BLOCK MOs IN ORTHONORMAL BASIS SET')
801 : CALL parallel_gemm("N", "N", n_ao, n_mo, n_ao, 1.0_dp, ec%m_transf_inv, &
802 0 : ec%block(blk)%mo(j)%mo_coeff, 0.0_dp, mat_w(j))
803 : END DO
804 :
805 0 : DO j = 1, n
806 0 : NULLIFY (list_at)
807 : CALL section_vals_val_get(print_sec, keyword_name='MO_COEFF_ATOM', &
808 0 : i_rep_val=j, i_vals=list_at)
809 0 : IF (ASSOCIATED(list_at)) THEN
810 :
811 : ! List of states
812 0 : CALL section_vals_val_get(print_sec, keyword_name='MO_COEFF_ATOM_STATE', n_rep_val=m)
813 :
814 0 : IF (m > 0) THEN
815 :
816 0 : DO k = 1, m
817 0 : NULLIFY (list_mo)
818 : CALL section_vals_val_get(print_sec, keyword_name='MO_COEFF_ATOM_STATE', &
819 0 : i_rep_val=k, i_vals=list_mo)
820 0 : IF (ASSOCIATED(list_mo)) THEN
821 :
822 0 : IF (j > 1) THEN
823 0 : IF (output_unit > 0) THEN
824 0 : WRITE (output_unit, *)
825 : END IF
826 : END IF
827 :
828 0 : DO l = 1, SIZE(list_mo)
829 :
830 0 : IF (n_spins > 1) THEN
831 : c1 = get_mo_c2_sum(ec%block(blk)%atom, mat_w(1), &
832 0 : list_mo(l), list_at)
833 : c2 = get_mo_c2_sum(ec%block(blk)%atom, mat_w(2), &
834 0 : list_mo(l), list_at)
835 0 : IF (output_unit > 0) THEN
836 0 : WRITE (output_unit, '(I5,A,I5,2F20.10)') j, ' /', list_mo(l), c1, c2
837 : END IF
838 : ELSE
839 : c1 = get_mo_c2_sum(ec%block(blk)%atom, mat_w(1), &
840 0 : list_mo(l), list_at)
841 0 : IF (output_unit > 0) THEN
842 0 : WRITE (output_unit, '(I5,A,I5,F20.10)') j, ' /', list_mo(l), c1
843 : END IF
844 : END IF
845 :
846 : END DO
847 :
848 : END IF
849 : END DO
850 :
851 : END IF
852 :
853 : END IF
854 : END DO
855 :
856 : ! Clean memory
857 0 : CALL cp_fm_release(mat_w)
858 :
859 : END IF
860 :
861 40 : END SUBROUTINE print_mo_coeff
862 :
863 : ! **************************************************************************************************
864 : !> \brief Print out electronic states (MOs)
865 : !> \param output_unit unit number of the open output stream
866 : !> \param mo array of MO sets
867 : !> \param n_spins number of spin components
868 : !> \param label output label
869 : !> \param mx_mo_a maximum number of alpha states to print out
870 : !> \param mx_mo_b maximum number of beta states to print out
871 : !> \param fermi print out Fermi level and number of electrons
872 : !> \author Z. Futera (02.2017)
873 : ! **************************************************************************************************
874 40 : SUBROUTINE print_states(output_unit, mo, n_spins, label, mx_mo_a, mx_mo_b, fermi)
875 :
876 : ! Routine arguments
877 : INTEGER, INTENT(IN) :: output_unit
878 : TYPE(mo_set_type), DIMENSION(:), INTENT(IN) :: mo
879 : INTEGER, INTENT(IN) :: n_spins
880 : CHARACTER(LEN=*), INTENT(IN) :: label
881 : INTEGER, INTENT(IN), OPTIONAL :: mx_mo_a, mx_mo_b
882 : LOGICAL, INTENT(IN), OPTIONAL :: fermi
883 :
884 : INTEGER :: i, mx_a, mx_b, n
885 : LOGICAL :: prnt_fm
886 :
887 : ! Routine name for debug purposes
888 :
889 20 : prnt_fm = .FALSE.
890 20 : IF (PRESENT(fermi)) THEN
891 20 : prnt_fm = fermi
892 : END IF
893 :
894 20 : IF (output_unit > 0) THEN
895 :
896 15 : WRITE (output_unit, '(/,T3,A/)') 'State energies ('//TRIM(ADJUSTL(label))//'):'
897 :
898 : ! Spin-polarized calculation
899 15 : IF (n_spins > 1) THEN
900 :
901 15 : mx_a = mo(1)%nmo
902 15 : IF (PRESENT(mx_mo_a)) THEN
903 10 : mx_a = MIN(mo(1)%nmo, mx_mo_a)
904 : END IF
905 15 : mx_b = mo(2)%nmo
906 15 : IF (PRESENT(mx_mo_b)) THEN
907 10 : mx_b = MIN(mo(2)%nmo, mx_mo_b)
908 : END IF
909 15 : n = MAX(mx_a, mx_b)
910 :
911 181 : DO i = 1, n
912 166 : WRITE (output_unit, '(T3,I10)', ADVANCE='no') i
913 166 : IF (i <= mx_a) THEN
914 : WRITE (output_unit, '(2F12.4)', ADVANCE='no') &
915 166 : mo(1)%occupation_numbers(i), mo(1)%eigenvalues(i)
916 : ELSE
917 0 : WRITE (output_unit, '(A)', ADVANCE='no') ' '
918 : END IF
919 166 : WRITE (output_unit, '(A)', ADVANCE='no') ' '
920 181 : IF (i <= mx_b) THEN
921 : WRITE (output_unit, '(2F12.4)') &
922 161 : mo(2)%occupation_numbers(i), mo(2)%eigenvalues(i)
923 : ELSE
924 5 : WRITE (output_unit, *)
925 : END IF
926 : END DO
927 :
928 15 : IF (prnt_fm) THEN
929 : WRITE (output_unit, '(/,T3,I10,F24.4,I10,F19.4)') &
930 15 : mo(1)%nelectron, mo(1)%mu, &
931 30 : mo(2)%nelectron, mo(2)%mu
932 : END IF
933 :
934 : ! Spin-restricted calculation
935 : ELSE
936 :
937 0 : mx_a = mo(1)%nmo
938 0 : IF (PRESENT(mx_mo_a)) THEN
939 0 : mx_a = MIN(mo(1)%nmo, mx_mo_a)
940 : END IF
941 :
942 0 : DO i = 1, mx_a
943 : WRITE (output_unit, '(T3,I10,2F12.4)') &
944 0 : i, mo(1)%occupation_numbers(i), mo(1)%eigenvalues(i)
945 : END DO
946 :
947 0 : IF (prnt_fm) THEN
948 : WRITE (output_unit, '(/,T3,I10,F24.4)') &
949 0 : mo(1)%nelectron, mo(1)%mu
950 : END IF
951 :
952 : END IF
953 :
954 : END IF
955 :
956 20 : END SUBROUTINE print_states
957 :
958 : ! **************************************************************************************************
959 : !> \brief Print out donor-acceptor state couplings
960 : !> \param ec_sec ...
961 : !> \param output_unit unit number of the open output stream
962 : !> \param logger ...
963 : !> \param ec electronic coupling data structure
964 : !> \param mo ...
965 : !> \author Z. Futera (02.2017)
966 : ! **************************************************************************************************
967 10 : SUBROUTINE print_couplings(ec_sec, output_unit, logger, ec, mo)
968 :
969 : ! Routine arguments
970 : TYPE(section_vals_type), POINTER :: ec_sec
971 : INTEGER, INTENT(IN) :: output_unit
972 : TYPE(cp_logger_type), POINTER :: logger
973 : TYPE(et_cpl), POINTER :: ec
974 : TYPE(mo_set_type), DIMENSION(:), INTENT(IN) :: mo
975 :
976 : CHARACTER(LEN=default_path_length) :: filename, my_pos, title
977 : INTEGER :: i, j, k, l, n_states(2), nc, nr, nspins, &
978 : unit_nr
979 : LOGICAL :: append
980 10 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: w1, w2
981 : TYPE(section_vals_type), POINTER :: print_key
982 :
983 : ! Routine name for debug purposes
984 : ! Local variables
985 :
986 10 : n_states = 0
987 30 : DO i = 1, SIZE(mo)
988 30 : n_states(i) = mo(i)%nmo
989 : END DO
990 10 : nspins = 1
991 10 : IF (n_states(2) > 0) nspins = 2
992 :
993 : print_key => section_vals_get_subs_vals(section_vals=ec_sec, &
994 10 : subsection_name="PRINT%COUPLINGS")
995 :
996 10 : IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), &
997 : cp_p_file)) THEN
998 :
999 10 : my_pos = "REWIND"
1000 10 : append = section_get_lval(print_key, "APPEND")
1001 10 : IF (append) THEN
1002 0 : my_pos = "APPEND"
1003 : END IF
1004 :
1005 10 : IF (output_unit > 0) THEN
1006 5 : WRITE (output_unit, '(/,T3,A/)') 'Printing coupling elements to output files'
1007 : END IF
1008 :
1009 30 : DO i = 1, ec%n_blocks
1010 40 : DO j = i + 1, ec%n_blocks
1011 :
1012 10 : nr = ec%block(i)%hab(1, j)%matrix_struct%nrow_global
1013 10 : nc = ec%block(i)%hab(1, j)%matrix_struct%ncol_global
1014 :
1015 40 : ALLOCATE (w1(nr, nc))
1016 10 : CPASSERT(ASSOCIATED(w1))
1017 10 : CALL cp_fm_get_submatrix(ec%block(i)%hab(1, j), w1)
1018 10 : IF (nspins > 1) THEN
1019 30 : ALLOCATE (w2(nr, nc))
1020 10 : CPASSERT(ASSOCIATED(w2))
1021 10 : CALL cp_fm_get_submatrix(ec%block(i)%hab(2, j), w2)
1022 : END IF
1023 :
1024 10 : IF (output_unit > 0) THEN
1025 :
1026 5 : WRITE (filename, '(a5,I1.1,a1,I1.1)') "ET_BL_", i, "-", j
1027 : unit_nr = cp_print_key_unit_nr(logger, ec_sec, "PRINT%COUPLINGS", extension=".elcoup", &
1028 5 : middle_name=TRIM(filename), file_position=my_pos, log_filename=.FALSE.)
1029 :
1030 5 : WRITE (title, *) 'Coupling elements [meV] between blocks:', i, j
1031 :
1032 5 : WRITE (unit_nr, *) TRIM(title)
1033 5 : IF (nspins > 1) THEN
1034 5 : WRITE (unit_nr, '(T3,A8,T13,A8,T28,A,A)') 'State A', 'State B', 'Coupling spin 1', ' Coupling spin 2'
1035 : ELSE
1036 0 : WRITE (unit_nr, '(T3,A8,T13,A8,T28,A)') 'State A', 'State B', 'Coupling'
1037 : END IF
1038 :
1039 55 : DO k = 1, MIN(ec%block(i)%n_ao, n_states(1))
1040 836 : DO l = 1, MIN(ec%block(j)%n_ao, n_states(1))
1041 :
1042 836 : IF (nspins > 1) THEN
1043 :
1044 : WRITE (unit_nr, '(T3,I5,T13,I5,T22,E20.6)', ADVANCE='no') &
1045 786 : k, l, w1(k, l)*evolt*1000.0_dp
1046 786 : IF ((k <= n_states(2)) .AND. (l <= n_states(2))) THEN
1047 : WRITE (unit_nr, '(E20.6)') &
1048 779 : w2(k, l)*evolt*1000.0_dp
1049 : ELSE
1050 7 : WRITE (unit_nr, *)
1051 : END IF
1052 :
1053 : ELSE
1054 :
1055 : WRITE (unit_nr, '(T3,I5,T13,I5,T22,E20.6)') &
1056 0 : k, l, w1(k, l)*evolt*1000.0_dp
1057 : END IF
1058 :
1059 : END DO
1060 55 : WRITE (unit_nr, *)
1061 : END DO
1062 5 : CALL cp_print_key_finished_output(unit_nr, logger, ec_sec, "PRINT%COUPLINGS")
1063 :
1064 : END IF
1065 :
1066 10 : IF (ASSOCIATED(w1)) DEALLOCATE (w1)
1067 30 : IF (ASSOCIATED(w2)) DEALLOCATE (w2)
1068 :
1069 : END DO
1070 : END DO
1071 :
1072 : END IF
1073 10 : END SUBROUTINE print_couplings
1074 :
1075 : ! **************************************************************************************************
1076 : !> \brief Normalize set of MO vectors
1077 : !> \param qs_env QuickStep environment containing all system data
1078 : !> \param mo storage for the MO data set
1079 : !> \param n_ao number of AO basis functions
1080 : !> \param n_mo number of block states
1081 : !> \author Z. Futera (02.2017)
1082 : ! **************************************************************************************************
1083 40 : SUBROUTINE normalize_mo_vectors(qs_env, mo, n_ao, n_mo)
1084 :
1085 : ! Routine arguments
1086 : TYPE(qs_environment_type), POINTER :: qs_env
1087 : TYPE(mo_set_type), POINTER :: mo
1088 : INTEGER, INTENT(IN) :: n_ao, n_mo
1089 :
1090 : REAL(KIND=dp), DIMENSION(:), POINTER :: vec_t
1091 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
1092 : TYPE(cp_fm_struct_type), POINTER :: fm_s
1093 : TYPE(cp_fm_type) :: mat_sc, mat_t
1094 40 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mat_s
1095 : TYPE(mp_para_env_type), POINTER :: para_env
1096 :
1097 : ! Routine name for debug purposes
1098 :
1099 : ! Initialization
1100 40 : NULLIFY (blacs_env)
1101 40 : NULLIFY (para_env)
1102 40 : NULLIFY (fm_s)
1103 40 : NULLIFY (mat_s)
1104 : NULLIFY (vec_t)
1105 :
1106 : ! Overlap matrix
1107 40 : CALL get_qs_env(qs_env, matrix_s=mat_s)
1108 :
1109 : ! Calculate S*C product
1110 : CALL cp_fm_create(matrix=mat_sc, matrix_struct=mo%mo_coeff%matrix_struct, &
1111 40 : name='S*C PRODUCT MATRIX')
1112 40 : CALL cp_dbcsr_sm_fm_multiply(mat_s(1)%matrix, mo%mo_coeff, mat_sc, n_mo)
1113 :
1114 : ! Calculate C^T*S*C
1115 40 : CALL get_qs_env(qs_env, para_env=para_env, blacs_env=blacs_env)
1116 : CALL cp_fm_struct_create(fmstruct=fm_s, para_env=para_env, context=blacs_env, &
1117 40 : nrow_global=n_mo, ncol_global=n_mo)
1118 : CALL cp_fm_create(matrix=mat_t, matrix_struct=fm_s, &
1119 40 : name='C^T*S*C OVERLAP PRODUCT MATRIX')
1120 40 : CALL parallel_gemm('T', 'N', n_mo, n_mo, n_ao, 1.0_dp, mo%mo_coeff, mat_sc, 0.0_dp, mat_t)
1121 :
1122 : ! Normalization
1123 120 : ALLOCATE (vec_t(n_mo))
1124 40 : CPASSERT(ASSOCIATED(vec_t))
1125 40 : CALL cp_fm_vectorssum(mat_t, vec_t)
1126 448 : vec_t = 1.0_dp/SQRT(vec_t)
1127 40 : CALL cp_fm_column_scale(mo%mo_coeff, vec_t)
1128 :
1129 : ! Clean memory
1130 40 : CALL cp_fm_struct_release(fmstruct=fm_s)
1131 40 : CALL cp_fm_release(matrix=mat_sc)
1132 40 : CALL cp_fm_release(matrix=mat_t)
1133 40 : IF (ASSOCIATED(vec_t)) THEN
1134 40 : DEALLOCATE (vec_t)
1135 : END IF
1136 :
1137 80 : END SUBROUTINE normalize_mo_vectors
1138 :
1139 : ! **************************************************************************************************
1140 : !> \brief Transform block MO coefficients to original non-orthogonal basis set and save them
1141 : !> \param qs_env QuickStep environment containing all system data
1142 : !> \param ec electronic coupling data structure
1143 : !> \param id block ID
1144 : !> \param mo storage for the MO data set
1145 : !> \param mat_u matrix of the block states
1146 : !> \param n_ao number of AO basis functions
1147 : !> \param n_mo number of block states
1148 : !> \author Z. Futera (02.2017)
1149 : ! **************************************************************************************************
1150 40 : SUBROUTINE set_mo_coefficients(qs_env, ec, id, mo, mat_u, n_ao, n_mo)
1151 :
1152 : ! Routine arguments
1153 : TYPE(qs_environment_type), POINTER :: qs_env
1154 : TYPE(et_cpl), POINTER :: ec
1155 : INTEGER, INTENT(IN) :: id
1156 : TYPE(mo_set_type), POINTER :: mo
1157 : TYPE(cp_fm_type), INTENT(IN) :: mat_u
1158 : INTEGER, INTENT(IN) :: n_ao, n_mo
1159 :
1160 : INTEGER :: ic, ir, jc, jr, mr, nc, nr
1161 : REAL(KIND=dp) :: xu
1162 : TYPE(cp_fm_type) :: mat_w
1163 :
1164 : ! Routine name for debug purposes
1165 : ! Local variables
1166 :
1167 : ! Working matrix
1168 : CALL cp_fm_create(matrix=mat_w, matrix_struct=mo%mo_coeff%matrix_struct, &
1169 40 : name='BLOCK MO-TRANSFORMATION WORKING MATRIX')
1170 40 : CALL cp_fm_set_all(mat_w, 0.0_dp)
1171 :
1172 : ! Matrix-element reordering
1173 40 : nr = 1
1174 : ! Rows
1175 184 : DO ir = 1, ec%block(id)%n_atoms
1176 592 : DO jr = 1, ec%block(id)%atom(ir)%n_ao
1177 : ! Columns
1178 408 : nc = 1
1179 2832 : DO ic = 1, ec%block(id)%n_atoms
1180 9192 : DO jc = 1, ec%block(id)%atom(ic)%n_ao
1181 6360 : mr = ec%block(id)%atom(ir)%ao_pos + jr - 1
1182 6360 : CALL cp_fm_get_element(mat_u, nr, nc, xu)
1183 6360 : CALL cp_fm_set_element(mat_w, mr, nc, xu)
1184 15144 : nc = nc + 1
1185 : END DO
1186 : END DO
1187 552 : nr = nr + 1
1188 : END DO
1189 : END DO
1190 :
1191 : ! Transformation to original non-orthogonal basis set
1192 40 : CALL parallel_gemm("N", "N", n_ao, n_mo, n_ao, 1.0_dp, ec%m_transf, mat_w, 0.0_dp, mo%mo_coeff)
1193 40 : CALL normalize_mo_vectors(qs_env, mo, n_ao, n_mo)
1194 :
1195 : ! Clean memory
1196 40 : CALL cp_fm_release(matrix=mat_w)
1197 :
1198 40 : END SUBROUTINE set_mo_coefficients
1199 :
1200 : ! **************************************************************************************************
1201 : !> \brief Creates MO set corresponding to one atomic data block
1202 : !> \param qs_env QuickStep environment containing all system data
1203 : !> \param ec electronic coupling data structure
1204 : !> \param id block ID
1205 : !> \param spin spin component
1206 : !> \param mat_u matrix of the block states
1207 : !> \param vec_e array of the block eigenvalues
1208 : !> \author Z. Futera (02.2017)
1209 : ! **************************************************************************************************
1210 40 : SUBROUTINE create_block_mo_set(qs_env, ec, id, spin, mat_u, vec_e)
1211 :
1212 : ! Routine arguments
1213 : TYPE(qs_environment_type), POINTER :: qs_env
1214 : TYPE(et_cpl), POINTER :: ec
1215 : INTEGER, INTENT(IN) :: id, spin
1216 : TYPE(cp_fm_type), INTENT(IN) :: mat_u
1217 : REAL(KIND=dp), DIMENSION(:), POINTER :: vec_e
1218 :
1219 : INTEGER :: n_ao, n_el, n_mo
1220 : REAL(KIND=dp) :: mx_occ
1221 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
1222 : TYPE(cp_fm_struct_type), POINTER :: fm_s
1223 : TYPE(dft_control_type), POINTER :: dft_cntrl
1224 : TYPE(mo_set_type), POINTER :: mo
1225 : TYPE(mp_para_env_type), POINTER :: para_env
1226 40 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1227 : TYPE(scf_control_type), POINTER :: scf_cntrl
1228 :
1229 : ! Routine name for debug purposes
1230 :
1231 40 : NULLIFY (blacs_env)
1232 40 : NULLIFY (dft_cntrl)
1233 40 : NULLIFY (para_env)
1234 40 : NULLIFY (qs_kind_set)
1235 40 : NULLIFY (fm_s)
1236 40 : NULLIFY (scf_cntrl)
1237 : NULLIFY (mo)
1238 :
1239 : ! Number of basis functions
1240 40 : CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set)
1241 40 : CALL get_qs_kind_set(qs_kind_set, nsgf=n_ao)
1242 :
1243 : ! Number of states
1244 40 : n_mo = mat_u%matrix_struct%nrow_global
1245 40 : IF (n_mo /= mat_u%matrix_struct%ncol_global) THEN
1246 0 : CPABORT('block state matrix is not square')
1247 : END IF
1248 40 : IF (n_mo /= SIZE(vec_e)) THEN
1249 0 : CPABORT('inconsistent number of states / energies')
1250 : END IF
1251 :
1252 : ! Maximal occupancy
1253 40 : CALL get_qs_env(qs_env, dft_control=dft_cntrl)
1254 40 : mx_occ = 2.0_dp
1255 40 : IF (dft_cntrl%nspins > 1) THEN
1256 40 : mx_occ = 1.0_dp
1257 : END IF
1258 :
1259 : ! Number of electrons
1260 40 : n_el = ec%block(id)%n_electrons
1261 40 : IF (dft_cntrl%nspins > 1) THEN
1262 40 : n_el = n_el/2
1263 40 : IF (MOD(ec%block(id)%n_electrons, 2) == 1) THEN
1264 28 : IF (spin == 1) THEN
1265 14 : n_el = n_el + 1
1266 : END IF
1267 : END IF
1268 : END IF
1269 :
1270 : ! Memory allocation (Use deallocate_mo_set to prevent accidental memory leaks)
1271 40 : CALL deallocate_mo_set(ec%block(id)%mo(spin))
1272 40 : CALL allocate_mo_set(ec%block(id)%mo(spin), n_ao, n_mo, n_el, REAL(n_el, dp), mx_occ, 0.0_dp)
1273 40 : mo => ec%block(id)%mo(spin)
1274 :
1275 : ! State energies
1276 120 : ALLOCATE (mo%eigenvalues(n_mo))
1277 40 : CPASSERT(ASSOCIATED(mo%eigenvalues))
1278 896 : mo%eigenvalues = vec_e
1279 :
1280 : ! States coefficients
1281 40 : CALL get_qs_env(qs_env, para_env=para_env, blacs_env=blacs_env)
1282 : CALL cp_fm_struct_create(fmstruct=fm_s, para_env=para_env, context=blacs_env, &
1283 40 : nrow_global=n_ao, ncol_global=n_mo)
1284 40 : ALLOCATE (mo%mo_coeff)
1285 40 : CALL cp_fm_create(matrix=mo%mo_coeff, matrix_struct=fm_s, name='BLOCK STATES')
1286 :
1287 : ! Transform MO coefficients to original non-orthogonal basis set
1288 40 : CALL set_mo_coefficients(qs_env, ec, id, mo, mat_u, n_ao, n_mo)
1289 :
1290 : ! Occupancies
1291 80 : ALLOCATE (mo%occupation_numbers(n_mo))
1292 40 : CPASSERT(ASSOCIATED(mo%occupation_numbers))
1293 448 : mo%occupation_numbers = 0.0_dp
1294 :
1295 40 : IF (n_el > 0) THEN
1296 28 : CALL get_qs_env(qs_env, scf_control=scf_cntrl)
1297 28 : CALL set_mo_occupation(mo_set=mo, smear=scf_cntrl%smear)
1298 : END IF
1299 :
1300 : ! Clean memory
1301 40 : CALL cp_fm_struct_release(fmstruct=fm_s)
1302 :
1303 40 : END SUBROUTINE create_block_mo_set
1304 :
1305 : ! **************************************************************************************************
1306 : !> \brief save given electronic state to cube files
1307 : !> \param qs_env QuickStep environment containing all system data
1308 : !> \param logger output logger
1309 : !> \param input input-file block print setting section
1310 : !> \param mo electronic states data
1311 : !> \param ib block ID
1312 : !> \param im state ID
1313 : !> \param is spin ID
1314 : !> \author Z. Futera (02.2017)
1315 : ! **************************************************************************************************
1316 0 : SUBROUTINE save_mo_cube(qs_env, logger, input, mo, ib, im, is)
1317 :
1318 : ! Routine arguments
1319 : TYPE(qs_environment_type), POINTER :: qs_env
1320 : TYPE(cp_logger_type), POINTER :: logger
1321 : TYPE(section_vals_type), POINTER :: input
1322 : TYPE(mo_set_type), POINTER :: mo
1323 : INTEGER, INTENT(IN) :: ib, im, is
1324 :
1325 : CHARACTER(LEN=default_path_length) :: filename
1326 : CHARACTER(LEN=default_string_length) :: title
1327 : INTEGER :: unit_nr
1328 0 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
1329 : TYPE(cell_type), POINTER :: cell
1330 : TYPE(dft_control_type), POINTER :: dft_control
1331 : TYPE(particle_list_type), POINTER :: particles
1332 0 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1333 : TYPE(pw_c1d_gs_type) :: wf_g
1334 : TYPE(pw_env_type), POINTER :: pw_env
1335 0 : TYPE(pw_pool_p_type), DIMENSION(:), POINTER :: pw_pools
1336 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
1337 : TYPE(pw_r3d_rs_type) :: wf_r
1338 0 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1339 : TYPE(qs_subsys_type), POINTER :: subsys
1340 :
1341 : ! Routine name for debug purposes
1342 :
1343 : ! Initialization
1344 0 : NULLIFY (particles)
1345 0 : NULLIFY (subsys)
1346 :
1347 0 : NULLIFY (pw_env)
1348 0 : NULLIFY (pw_pools)
1349 0 : NULLIFY (auxbas_pw_pool)
1350 :
1351 0 : NULLIFY (atomic_kind_set)
1352 0 : NULLIFY (cell)
1353 0 : NULLIFY (dft_control)
1354 0 : NULLIFY (particle_set)
1355 0 : NULLIFY (qs_kind_set)
1356 :
1357 : ! Name of the cube file
1358 0 : WRITE (filename, '(A4,I1.1,A1,I5.5,A1,I1.1)') 'BWF_', ib, '_', im, '_', is
1359 : ! Open the file
1360 : unit_nr = cp_print_key_unit_nr(logger, input, 'MO_CUBES', extension='.cube', &
1361 0 : middle_name=TRIM(filename), file_position='REWIND', log_filename=.FALSE.)
1362 : ! Title of the file
1363 0 : WRITE (title, *) 'WAVEFUNCTION ', im, ' block ', ib, ' spin ', is
1364 :
1365 : ! List of all atoms
1366 0 : CALL get_qs_env(qs_env, subsys=subsys)
1367 0 : CALL qs_subsys_get(subsys, particles=particles)
1368 :
1369 : ! Grids for wavefunction
1370 0 : CALL get_qs_env(qs_env, pw_env=pw_env)
1371 0 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, pw_pools=pw_pools)
1372 0 : CALL auxbas_pw_pool%create_pw(wf_r)
1373 0 : CALL auxbas_pw_pool%create_pw(wf_g)
1374 :
1375 : ! Calculate the grid values
1376 : CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set, qs_kind_set=qs_kind_set, &
1377 0 : cell=cell, dft_control=dft_control, particle_set=particle_set)
1378 : CALL calculate_wavefunction(mo%mo_coeff, im, wf_r, wf_g, atomic_kind_set, &
1379 0 : qs_kind_set, cell, dft_control, particle_set, pw_env)
1380 : CALL cp_pw_to_cube(wf_r, unit_nr, title, particles=particles, &
1381 0 : stride=section_get_ivals(input, 'MO_CUBES%STRIDE'))
1382 :
1383 : ! Close file
1384 0 : CALL cp_print_key_finished_output(unit_nr, logger, input, 'MO_CUBES')
1385 :
1386 : ! Clean memory
1387 0 : CALL auxbas_pw_pool%give_back_pw(wf_r)
1388 0 : CALL auxbas_pw_pool%give_back_pw(wf_g)
1389 :
1390 0 : END SUBROUTINE save_mo_cube
1391 :
1392 : ! **************************************************************************************************
1393 : !> \brief save specified electronic states to cube files
1394 : !> \param qs_env QuickStep environment containing all system data
1395 : !> \param ec electronic coupling data structure
1396 : !> \param n_spins number of spin states
1397 : !> \author Z. Futera (02.2017)
1398 : ! **************************************************************************************************
1399 10 : SUBROUTINE save_el_states(qs_env, ec, n_spins)
1400 :
1401 : ! Routine arguments
1402 : TYPE(qs_environment_type), POINTER :: qs_env
1403 : TYPE(et_cpl), POINTER :: ec
1404 : INTEGER, INTENT(IN) :: n_spins
1405 :
1406 : INTEGER :: i, j, k, l, n
1407 10 : INTEGER, DIMENSION(:), POINTER :: list
1408 : TYPE(cp_logger_type), POINTER :: logger
1409 : TYPE(mo_set_type), POINTER :: mo
1410 : TYPE(section_vals_type), POINTER :: block_sec, mo_sec, print_sec
1411 :
1412 : ! Routine name for debug purposes
1413 :
1414 10 : NULLIFY (logger)
1415 10 : NULLIFY (block_sec)
1416 : NULLIFY (print_sec)
1417 10 : NULLIFY (mo_sec)
1418 :
1419 : ! Output logger
1420 20 : logger => cp_get_default_logger()
1421 : block_sec => section_vals_get_subs_vals(qs_env%input, &
1422 10 : 'PROPERTIES%ET_COUPLING%PROJECTION%BLOCK')
1423 :
1424 : ! Print states of all blocks
1425 30 : DO i = 1, ec%n_blocks
1426 :
1427 20 : print_sec => section_vals_get_subs_vals(block_sec, 'PRINT', i_rep_section=i)
1428 :
1429 : ! Check if the print input section is active
1430 20 : IF (BTEST(cp_print_key_should_output(logger%iter_info, &
1431 10 : print_sec, 'MO_CUBES'), cp_p_file)) THEN
1432 :
1433 0 : mo_sec => section_vals_get_subs_vals(print_sec, 'MO_CUBES')
1434 :
1435 : ! Spin states
1436 0 : DO j = 1, n_spins
1437 :
1438 0 : mo => ec%block(i)%mo(j)
1439 :
1440 0 : CALL section_vals_val_get(mo_sec, keyword_name='MO_LIST', n_rep_val=n)
1441 :
1442 : ! List of specific MOs
1443 0 : IF (n > 0) THEN
1444 :
1445 0 : DO k = 1, n
1446 0 : NULLIFY (list)
1447 : CALL section_vals_val_get(mo_sec, keyword_name='MO_LIST', &
1448 0 : i_rep_val=k, i_vals=list)
1449 0 : IF (ASSOCIATED(list)) THEN
1450 0 : DO l = 1, SIZE(list)
1451 0 : CALL save_mo_cube(qs_env, logger, print_sec, mo, i, list(l), j)
1452 : END DO
1453 : END IF
1454 : END DO
1455 :
1456 : ! Frontier MOs
1457 : ELSE
1458 :
1459 : ! Occupied states
1460 0 : CALL section_vals_val_get(mo_sec, keyword_name='NHOMO', i_val=n)
1461 :
1462 0 : IF (n > 0) THEN
1463 0 : DO k = MAX(1, mo%homo - n + 1), mo%homo
1464 0 : CALL save_mo_cube(qs_env, logger, print_sec, mo, i, k, j)
1465 : END DO
1466 : END IF
1467 :
1468 : ! Unoccupied states
1469 0 : CALL section_vals_val_get(mo_sec, keyword_name='NLUMO', i_val=n)
1470 :
1471 0 : IF (n > 0) THEN
1472 0 : DO k = mo%lfomo, MIN(mo%lfomo + n - 1, mo%nmo)
1473 0 : CALL save_mo_cube(qs_env, logger, print_sec, mo, i, k, j)
1474 : END DO
1475 : END IF
1476 :
1477 : END IF
1478 :
1479 : END DO
1480 :
1481 : END IF
1482 :
1483 : END DO
1484 :
1485 10 : END SUBROUTINE save_el_states
1486 :
1487 : ! **************************************************************************************************
1488 : !> \brief calculates the electron transfer coupling elements by projection-operator approach
1489 : !> Kondov et al. J.Phys.Chem.C 2007, 111, 11970-11981
1490 : !> \param qs_env QuickStep environment containing all system data
1491 : !> \author Z. Futera (02.2017)
1492 : ! **************************************************************************************************
1493 10 : SUBROUTINE calc_et_coupling_proj(qs_env)
1494 :
1495 : ! Routine arguments
1496 : TYPE(qs_environment_type), POINTER :: qs_env
1497 :
1498 : INTEGER :: i, j, k, n_ao, n_atoms, output_unit
1499 : LOGICAL :: do_kp, master
1500 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
1501 : TYPE(cp_fm_struct_type), POINTER :: fm_s
1502 : TYPE(cp_fm_type) :: mat_w
1503 10 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: mat_h
1504 : TYPE(cp_logger_type), POINTER :: logger
1505 10 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: ks, mo_der
1506 : TYPE(dft_control_type), POINTER :: dft_cntrl
1507 : TYPE(et_cpl), POINTER :: ec
1508 : TYPE(kpoint_type), POINTER :: kpoints
1509 10 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mo
1510 : TYPE(mp_para_env_type), POINTER :: para_env
1511 10 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1512 : TYPE(scf_control_type), POINTER :: scf_control
1513 : TYPE(section_vals_type), POINTER :: et_proj_sec
1514 :
1515 : ! Routine name for debug purposes
1516 :
1517 : ! Pointer initialization
1518 10 : NULLIFY (logger)
1519 :
1520 10 : NULLIFY (blacs_env)
1521 10 : NULLIFY (para_env)
1522 10 : NULLIFY (dft_cntrl)
1523 10 : NULLIFY (kpoints)
1524 10 : NULLIFY (qs_kind_set)
1525 : NULLIFY (et_proj_sec)
1526 :
1527 10 : NULLIFY (fm_s)
1528 10 : NULLIFY (ks, mo_der)
1529 :
1530 : NULLIFY (ec)
1531 :
1532 : ! Reference
1533 10 : CALL cite_reference(Futera2017)
1534 :
1535 : ! Stream for output to LOG file
1536 10 : logger => cp_get_default_logger()
1537 :
1538 10 : et_proj_sec => section_vals_get_subs_vals(qs_env%input, 'PROPERTIES%ET_COUPLING%PROJECTION')
1539 :
1540 : output_unit = cp_print_key_unit_nr(logger, et_proj_sec, &
1541 10 : 'PROGRAM_RUN_INFO', extension='.log')
1542 :
1543 : ! Parallel calculation - master thread
1544 10 : master = .FALSE.
1545 10 : IF (output_unit > 0) THEN
1546 : master = .TRUE.
1547 : END IF
1548 :
1549 : ! Header
1550 : IF (master) THEN
1551 : WRITE (output_unit, '(/,T2,A)') &
1552 5 : '!-----------------------------------------------------------------------------!'
1553 : WRITE (output_unit, '(T17,A)') &
1554 5 : 'Electronic coupling - Projection-operator method'
1555 : END IF
1556 :
1557 : ! Main data structure
1558 10 : ALLOCATE (ec)
1559 10 : CPASSERT(ASSOCIATED(ec))
1560 10 : CALL set_block_data(qs_env, et_proj_sec, ec)
1561 :
1562 : ! Number of atoms and AO functions
1563 10 : CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set, natom=n_atoms)
1564 10 : CALL get_qs_kind_set(qs_kind_set, nsgf=n_ao)
1565 :
1566 : ! Print out info about system partitioning
1567 10 : IF (master) THEN
1568 :
1569 : WRITE (output_unit, '(/,T3,A,I10)') &
1570 5 : 'Number of atoms = ', n_atoms
1571 : WRITE (output_unit, '(T3,A,I10)') &
1572 5 : 'Number of fragments = ', ec%n_blocks
1573 : WRITE (output_unit, '(T3,A,I10)') &
1574 5 : 'Number of fragment atoms = ', ec%n_atoms
1575 : WRITE (output_unit, '(T3,A,I10)') &
1576 5 : 'Number of unassigned atoms = ', n_atoms - ec%n_atoms
1577 : WRITE (output_unit, '(T3,A,I10)') &
1578 5 : 'Number of AO basis functions = ', n_ao
1579 :
1580 15 : DO i = 1, ec%n_blocks
1581 :
1582 : WRITE (output_unit, '(/,T3,A,I0,A)') &
1583 10 : 'Block ', i, ':'
1584 : WRITE (output_unit, '(T3,A,I10)') &
1585 10 : 'Number of block atoms = ', ec%block(i)%n_atoms
1586 : WRITE (output_unit, '(T3,A,I10)') &
1587 10 : 'Number of block electrons = ', ec%block(i)%n_electrons
1588 : WRITE (output_unit, '(T3,A,I10)') &
1589 10 : 'Number of block AO functions = ', ec%block(i)%n_ao
1590 :
1591 15 : IF (ec%block(i)%n_atoms < 10) THEN
1592 :
1593 : WRITE (output_unit, '(T3,A,10I6)') &
1594 10 : 'Block atom IDs = ', &
1595 56 : (ec%block(i)%atom(j)%id, j=1, ec%block(i)%n_atoms)
1596 :
1597 : ELSE
1598 :
1599 0 : WRITE (output_unit, '(T3,A)') 'Block atom IDs ='
1600 0 : DO j = 1, ec%block(i)%n_atoms/10
1601 0 : WRITE (output_unit, '(T3,A,10I6)') ' ', &
1602 0 : (ec%block(i)%atom((j - 1)*10 + k)%id, k=1, 10)
1603 : END DO
1604 0 : IF (MOD(ec%block(i)%n_atoms, 10) /= 0) THEN
1605 0 : WRITE (output_unit, '(T3,A,10I6)') ' ', &
1606 0 : (ec%block(i)%atom(k + 10*(ec%block(i)%n_atoms/10))%id, &
1607 0 : k=1, MOD(ec%block(i)%n_atoms, 10))
1608 : END IF
1609 :
1610 : END IF
1611 :
1612 : END DO
1613 :
1614 : END IF
1615 :
1616 : ! Full matrix data structure
1617 10 : CALL get_qs_env(qs_env, para_env=para_env, blacs_env=blacs_env)
1618 : CALL cp_fm_struct_create(fmstruct=fm_s, para_env=para_env, context=blacs_env, &
1619 10 : nrow_global=n_ao, ncol_global=n_ao)
1620 10 : CALL cp_fm_create(matrix=mat_w, matrix_struct=fm_s, name='FULL WORK MATRIX')
1621 :
1622 : ! Spin polarization / K-point sampling
1623 10 : CALL get_qs_env(qs_env, dft_control=dft_cntrl, do_kpoints=do_kp)
1624 10 : CALL get_qs_env(qs_env, mos=mo, matrix_ks=ks, mo_derivs=mo_der, scf_control=scf_control)
1625 10 : CALL make_mo_eig(mo, dft_cntrl%nspins, ks, scf_control, mo_der)
1626 :
1627 10 : IF (do_kp) THEN
1628 0 : CPABORT('ET_COUPLING not implemented with kpoints')
1629 : ELSE
1630 : ! no K-points
1631 10 : IF (master) THEN
1632 5 : WRITE (output_unit, '(T3,A)') 'No K-point sampling (Gamma point only)'
1633 : END IF
1634 : END IF
1635 :
1636 10 : IF (dft_cntrl%nspins == 2) THEN
1637 :
1638 10 : IF (master) THEN
1639 5 : WRITE (output_unit, '(/,T3,A)') 'Spin-polarized calculation'
1640 : END IF
1641 :
1642 : !<--- Open shell / No K-points ------------------------------------------------>!
1643 :
1644 : ! State eneries of the whole system
1645 10 : IF (mo(1)%nao /= mo(2)%nao) THEN
1646 0 : CPABORT('different number of alpha/beta AO basis functions')
1647 : END IF
1648 10 : IF (master) THEN
1649 : WRITE (output_unit, '(/,T3,A,I10)') &
1650 5 : 'Number of AO basis functions = ', mo(1)%nao
1651 : WRITE (output_unit, '(T3,A,I10)') &
1652 5 : 'Number of alpha states = ', mo(1)%nmo
1653 : WRITE (output_unit, '(T3,A,I10)') &
1654 5 : 'Number of beta states = ', mo(2)%nmo
1655 : END IF
1656 10 : CALL print_states(output_unit, mo, dft_cntrl%nspins, 'the whole system', fermi=.TRUE.)
1657 10 : CALL set_fermi(ec, mo(1)%mu, mo(2)%mu)
1658 :
1659 : ! KS Hamiltonian
1660 10 : CALL get_block_hamiltonian(qs_env, ec, fm_s, mat_h, mat_w, n_ao, dft_cntrl%nspins)
1661 :
1662 : ! Block diagonization
1663 10 : CALL hamiltonian_block_diag(qs_env, ec, mat_h)
1664 :
1665 : ! Print out energies and couplings
1666 30 : DO i = 1, ec%n_blocks
1667 20 : IF (output_unit > 0) THEN
1668 : CALL print_states(output_unit, ec%block(i)%mo, dft_cntrl%nspins, &
1669 : 'block '//TRIM(ADJUSTL(cp_to_string(i)))//' states', &
1670 10 : mx_mo_a=mo(1)%nmo, mx_mo_b=mo(2)%nmo, fermi=.TRUE.)
1671 : END IF
1672 30 : CALL print_mo_coeff(output_unit, qs_env, ec, i, dft_cntrl%nspins)
1673 : END DO
1674 :
1675 10 : CALL print_couplings(et_proj_sec, output_unit, logger, ec, mo)
1676 :
1677 : ELSE
1678 :
1679 0 : IF (master) THEN
1680 0 : WRITE (output_unit, '(/,T3,A)') 'Spin-restricted calculation'
1681 : END IF
1682 :
1683 : !<--- Close shell / No K-points ----------------------------------------------->!
1684 :
1685 : ! State eneries of the whole system
1686 : IF (master) THEN
1687 : WRITE (output_unit, '(/,T3,A,I10)') &
1688 0 : 'Number of AO basis functions = ', mo(1)%nao
1689 : WRITE (output_unit, '(T3,A,I10)') &
1690 0 : 'Number of states = ', mo(1)%nmo
1691 : END IF
1692 0 : CALL print_states(output_unit, mo, dft_cntrl%nspins, 'the whole system', fermi=.TRUE.)
1693 0 : CALL set_fermi(ec, mo(1)%mu)
1694 :
1695 : ! KS Hamiltonian
1696 0 : CALL get_block_hamiltonian(qs_env, ec, fm_s, mat_h, mat_w, n_ao, dft_cntrl%nspins)
1697 :
1698 : ! Block diagonization
1699 0 : CALL hamiltonian_block_diag(qs_env, ec, mat_h)
1700 :
1701 : ! Print out energies and couplings
1702 0 : DO i = 1, ec%n_blocks
1703 0 : IF (output_unit > 0) THEN
1704 : CALL print_states(output_unit, ec%block(i)%mo, dft_cntrl%nspins, &
1705 : 'block '//TRIM(ADJUSTL(cp_to_string(i)))//' states', &
1706 0 : mx_mo_a=mo(1)%nmo, fermi=.TRUE.)
1707 : END IF
1708 0 : CALL print_mo_coeff(output_unit, qs_env, ec, i, dft_cntrl%nspins)
1709 : END DO
1710 :
1711 0 : CALL print_couplings(et_proj_sec, output_unit, logger, ec, mo)
1712 :
1713 : END IF
1714 :
1715 : ! Save electronic states
1716 10 : CALL save_el_states(qs_env, ec, dft_cntrl%nspins)
1717 :
1718 : ! Footer
1719 10 : IF (master) WRITE (output_unit, '(/,T2,A)') &
1720 5 : '!-----------------------------------------------------------------------------!'
1721 :
1722 : ! Clean memory
1723 10 : CALL cp_fm_struct_release(fmstruct=fm_s)
1724 10 : CALL cp_fm_release(matrix=mat_w)
1725 10 : IF (ALLOCATED(mat_h)) THEN
1726 30 : DO i = 1, SIZE(mat_h)
1727 30 : CALL cp_fm_release(matrix=mat_h(i))
1728 : END DO
1729 10 : DEALLOCATE (mat_h)
1730 : END IF
1731 10 : CALL release_ec_data(ec)
1732 :
1733 : ! Close output stream
1734 10 : CALL cp_print_key_finished_output(output_unit, logger, et_proj_sec, 'PROGRAM_RUN_INFO')
1735 :
1736 20 : END SUBROUTINE calc_et_coupling_proj
1737 :
1738 0 : END MODULE et_coupling_proj
|