(git:f2099e5)
Loading...
Searching...
No Matches
qs_tddfpt2_properties.F
Go to the documentation of this file.
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
10 USE bibliography, ONLY: martin2003,&
11 cite_reference
16 USE cell_types, ONLY: cell_type
19 USE cp_cfm_types, ONLY: cp_cfm_create,&
27 USE cp_dbcsr_api, ONLY: &
44 USE cp_fm_types, ONLY: cp_fm_create,&
55 USE cp_output_handling, ONLY: cp_p_file,&
60 USE input_constants, ONLY: no_sf_tddfpt,&
69 USE kinds, ONLY: default_path_length,&
70 dp,&
71 int_8
72 USE mathconstants, ONLY: twopi,&
73 z_one,&
74 z_zero
75 USE message_passing, ONLY: mp_comm_type,&
83 USE physcon, ONLY: evolt
84 USE pw_env_types, ONLY: pw_env_get,&
87 USE pw_pool_types, ONLY: pw_pool_p_type,&
89 USE pw_types, ONLY: pw_c1d_gs_type,&
96 USE qs_mo_types, ONLY: allocate_mo_set,&
107 USE qs_subsys_types, ONLY: qs_subsys_get,&
111 USE util, ONLY: sort
112#include "./base/base_uses.f90"
113
114 IMPLICIT NONE
115
116 PRIVATE
117
118 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_tddfpt2_properties'
119
120 ! number of first derivative components (3: d/dx, d/dy, d/dz)
121 INTEGER, PARAMETER, PRIVATE :: nderivs = 3
122 INTEGER, PARAMETER, PRIVATE :: maxspins = 2
123
126
127! **************************************************************************************************
128
129CONTAINS
130
131! **************************************************************************************************
132!> \brief Compute the action of the dipole operator on the ground state wave function.
133!> \param dipole_op_mos_occ 2-D array [x,y,z ; spin] of matrices where to put the computed quantity
134!> (allocated and initialised on exit)
135!> \param tddfpt_control TDDFPT control parameters
136!> \param gs_mos molecular orbitals optimised for the ground state
137!> \param qs_env Quickstep environment
138!> \par History
139!> * 05.2016 created as 'tddfpt_print_summary' [Sergey Chulkov]
140!> * 06.2018 dipole operator based on the Berry-phase formula [Sergey Chulkov]
141!> * 08.2018 splited of from 'tddfpt_print_summary' and merged with code from 'tddfpt'
142!> [Sergey Chulkov]
143!> \note \parblock
144!> Adapted version of the subroutine find_contributions() which was originally created
145!> by Thomas Chassaing on 02.2005.
146!>
147!> The relation between dipole integrals in velocity and length forms are the following:
148!> \f[<\psi_i|\nabla|\psi_a> = <\psi_i|\vec{r}|\hat{H}\psi_a> - <\hat{H}\psi_i|\vec{r}|\psi_a>
149!> = (\epsilon_a - \epsilon_i) <\psi_i|\vec{r}|\psi_a> .\f],
150!> due to the commutation identity:
151!> \f[\vec{r}\hat{H} - \hat{H}\vec{r} = [\vec{r},\hat{H}] = [\vec{r},-1/2 \nabla^2] = \nabla\f] .
152!> \endparblock
153! **************************************************************************************************
154 SUBROUTINE tddfpt_dipole_operator(dipole_op_mos_occ, tddfpt_control, gs_mos, qs_env)
155 TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :), &
156 INTENT(inout) :: dipole_op_mos_occ
157 TYPE(tddfpt2_control_type), POINTER :: tddfpt_control
158 TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
159 INTENT(in) :: gs_mos
160 TYPE(qs_environment_type), POINTER :: qs_env
161
162 CHARACTER(LEN=*), PARAMETER :: routinen = 'tddfpt_dipole_operator'
163
164 INTEGER :: handle, i_cos_sin, icol, ideriv, irow, &
165 ispin, jderiv, nao, ncols_local, &
166 ndim_periodic, nrows_local, nspins
167 INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
168 INTEGER, DIMENSION(maxspins) :: nmo_occ, nmo_virt
169 REAL(kind=dp) :: eval_occ
170 REAL(kind=dp), CONTIGUOUS, DIMENSION(:, :), &
171 POINTER :: local_data_ediff, local_data_wfm
172 REAL(kind=dp), DIMENSION(3) :: kvec, reference_point
173 TYPE(cell_type), POINTER :: cell
174 TYPE(cp_blacs_env_type), POINTER :: blacs_env
175 TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:) :: gamma_00, gamma_inv_00
176 TYPE(cp_fm_struct_type), POINTER :: fm_struct
177 TYPE(cp_fm_type) :: ediff_inv, wfm_ao_ao, wfm_mo_virt_mo_occ
178 TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: s_mos_virt
179 TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: dberry_mos_occ, gamma_real_imag, opvec
180 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: berry_cossin_xyz, matrix_s, rrc_xyz, scrm
181 TYPE(dft_control_type), POINTER :: dft_control
182 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
183 POINTER :: sab_orb
184 TYPE(pw_env_type), POINTER :: pw_env
185 TYPE(pw_poisson_type), POINTER :: poisson_env
186 TYPE(qs_ks_env_type), POINTER :: ks_env
187
188 CALL timeset(routinen, handle)
189
190 NULLIFY (blacs_env, cell, matrix_s, pw_env)
191 CALL get_qs_env(qs_env, blacs_env=blacs_env, cell=cell, matrix_s=matrix_s, pw_env=pw_env)
192
193 nspins = SIZE(gs_mos)
194 CALL dbcsr_get_info(matrix_s(1)%matrix, nfullrows_total=nao)
195 DO ispin = 1, nspins
196 nmo_occ(ispin) = SIZE(gs_mos(ispin)%evals_occ)
197 nmo_virt(ispin) = SIZE(gs_mos(ispin)%evals_virt)
198 END DO
199
200 ! +++ allocate dipole operator matrices (must be deallocated elsewhere)
201 ALLOCATE (dipole_op_mos_occ(nderivs, nspins))
202 DO ispin = 1, nspins
203 CALL cp_fm_get_info(gs_mos(ispin)%mos_occ, matrix_struct=fm_struct)
204
205 DO ideriv = 1, nderivs
206 CALL cp_fm_create(dipole_op_mos_occ(ideriv, ispin), fm_struct)
207 END DO
208 END DO
209
210 ! +++ allocate work matrices
211 ALLOCATE (s_mos_virt(nspins))
212 DO ispin = 1, nspins
213 CALL cp_fm_get_info(gs_mos(ispin)%mos_virt, matrix_struct=fm_struct)
214 CALL cp_fm_create(s_mos_virt(ispin), fm_struct)
215 CALL cp_dbcsr_sm_fm_multiply(matrix_s(1)%matrix, &
216 gs_mos(ispin)%mos_virt, &
217 s_mos_virt(ispin), &
218 ncol=nmo_virt(ispin), alpha=1.0_dp, beta=0.0_dp)
219 END DO
220
221 ! check that the chosen dipole operator is consistent with the periodic boundary conditions used
222 CALL pw_env_get(pw_env, poisson_env=poisson_env)
223 ndim_periodic = count(poisson_env%parameters%periodic == 1)
224
225 ! select default for dipole form
226 IF (tddfpt_control%dipole_form == 0) THEN
227 CALL get_qs_env(qs_env, dft_control=dft_control)
228 IF (dft_control%qs_control%xtb) THEN
229 IF (ndim_periodic == 0) THEN
230 tddfpt_control%dipole_form = tddfpt_dipole_length
231 ELSE
232 tddfpt_control%dipole_form = tddfpt_dipole_velocity
233 END IF
234 ELSE
235 tddfpt_control%dipole_form = tddfpt_dipole_velocity
236 END IF
237 END IF
238
239 SELECT CASE (tddfpt_control%dipole_form)
241 IF (ndim_periodic /= 3) THEN
242 CALL cp_warn(__location__, &
243 "Fully periodic Poisson solver (PERIODIC xyz) "// &
244 "or a large supercell in non-periodic directions is needed "// &
245 "for oscillator strengths based on the Berry phase formula")
246 END IF
247
248 NULLIFY (berry_cossin_xyz)
249 ! index: 1 = Re[exp(-i * G_t * t)],
250 ! 2 = Im[exp(-i * G_t * t)];
251 ! t = x,y,z
252 CALL dbcsr_allocate_matrix_set(berry_cossin_xyz, 2)
253
254 DO i_cos_sin = 1, 2
255 CALL dbcsr_init_p(berry_cossin_xyz(i_cos_sin)%matrix)
256 CALL dbcsr_copy(berry_cossin_xyz(i_cos_sin)%matrix, matrix_s(1)%matrix)
257 END DO
258
259 ! +++ allocate berry-phase-related work matrices
260 ALLOCATE (gamma_00(nspins), gamma_inv_00(nspins), gamma_real_imag(2, nspins), opvec(2, nspins))
261 ALLOCATE (dberry_mos_occ(nderivs, nspins))
262 DO ispin = 1, nspins
263 NULLIFY (fm_struct)
264 CALL cp_fm_struct_create(fm_struct, nrow_global=nmo_occ(ispin), &
265 ncol_global=nmo_occ(ispin), context=blacs_env)
266
267 CALL cp_cfm_create(gamma_00(ispin), fm_struct)
268 CALL cp_cfm_create(gamma_inv_00(ispin), fm_struct)
269
270 DO i_cos_sin = 1, 2
271 CALL cp_fm_create(gamma_real_imag(i_cos_sin, ispin), fm_struct)
272 END DO
273 CALL cp_fm_struct_release(fm_struct)
274
275 ! G_real C_0, G_imag C_0
276 CALL cp_fm_get_info(gs_mos(ispin)%mos_occ, matrix_struct=fm_struct)
277 DO i_cos_sin = 1, 2
278 CALL cp_fm_create(opvec(i_cos_sin, ispin), fm_struct)
279 END DO
280
281 ! dBerry * C_0
282 DO ideriv = 1, nderivs
283 CALL cp_fm_create(dberry_mos_occ(ideriv, ispin), fm_struct)
284 CALL cp_fm_set_all(dberry_mos_occ(ideriv, ispin), 0.0_dp)
285 END DO
286 END DO
287
288 DO ideriv = 1, nderivs
289 kvec(:) = twopi*cell%h_inv(ideriv, :)
290 CALL build_berry_moment_matrix(qs_env, berry_cossin_xyz(1)%matrix, &
291 berry_cossin_xyz(2)%matrix, kvec)
292
293 DO ispin = 1, nspins
294 ! i_cos_sin = 1: cos (real) component; opvec(1) = gamma_real C_0
295 ! i_cos_sin = 2: sin (imaginary) component; opvec(2) = gamma_imag C_0
296 DO i_cos_sin = 1, 2
297 CALL cp_dbcsr_sm_fm_multiply(berry_cossin_xyz(i_cos_sin)%matrix, &
298 gs_mos(ispin)%mos_occ, &
299 opvec(i_cos_sin, ispin), &
300 ncol=nmo_occ(ispin), alpha=1.0_dp, beta=0.0_dp)
301 END DO
302
303 CALL parallel_gemm('T', 'N', nmo_occ(ispin), nmo_occ(ispin), nao, &
304 1.0_dp, gs_mos(ispin)%mos_occ, opvec(1, ispin), &
305 0.0_dp, gamma_real_imag(1, ispin))
306
307 CALL parallel_gemm('T', 'N', nmo_occ(ispin), nmo_occ(ispin), nao, &
308 -1.0_dp, gs_mos(ispin)%mos_occ, opvec(2, ispin), &
309 0.0_dp, gamma_real_imag(2, ispin))
310
311 CALL cp_fm_to_cfm(msourcer=gamma_real_imag(1, ispin), &
312 msourcei=gamma_real_imag(2, ispin), &
313 mtarget=gamma_00(ispin))
314
315 ! gamma_inv_00 = Q = [C_0^T (gamma_real - i gamma_imag) C_0] ^ {-1}
316 CALL cp_cfm_set_all(gamma_inv_00(ispin), z_zero, z_one)
317 CALL cp_cfm_solve(gamma_00(ispin), gamma_inv_00(ispin))
318
319 CALL cp_cfm_to_fm(msource=gamma_inv_00(ispin), &
320 mtargetr=gamma_real_imag(1, ispin), &
321 mtargeti=gamma_real_imag(2, ispin))
322
323 ! dBerry_mos_occ is identical to dBerry_psi0 from qs_linres_op % polar_operators()
324 CALL parallel_gemm("N", "N", nao, nmo_occ(ispin), nmo_occ(ispin), &
325 1.0_dp, opvec(1, ispin), gamma_real_imag(2, ispin), &
326 0.0_dp, dipole_op_mos_occ(1, ispin))
327 CALL parallel_gemm("N", "N", nao, nmo_occ(ispin), nmo_occ(ispin), &
328 -1.0_dp, opvec(2, ispin), gamma_real_imag(1, ispin), &
329 1.0_dp, dipole_op_mos_occ(1, ispin))
330
331 DO jderiv = 1, nderivs
332 CALL cp_fm_scale_and_add(1.0_dp, dberry_mos_occ(jderiv, ispin), &
333 cell%hmat(jderiv, ideriv), dipole_op_mos_occ(1, ispin))
334 END DO
335 END DO
336 END DO
337
338 ! --- release berry-phase-related work matrices
339 CALL cp_fm_release(opvec)
340 CALL cp_fm_release(gamma_real_imag)
341 DO ispin = nspins, 1, -1
342 CALL cp_cfm_release(gamma_inv_00(ispin))
343 CALL cp_cfm_release(gamma_00(ispin))
344 END DO
345 DEALLOCATE (gamma_00, gamma_inv_00)
346 CALL dbcsr_deallocate_matrix_set(berry_cossin_xyz)
347
348 ! trans_dipole = 2|e|/|G_mu| * Tr Imag(evects^T * (gamma_real - i gamma_imag) * C_0 * gamma_inv_00) +
349 ! 2|e|/|G_mu| * Tr Imag(C_0^T * (gamma_real - i gamma_imag) * evects * gamma_inv_00) ,
350 !
351 ! Taking into account the symmetry of the matrices 'gamma_real' and 'gamma_imag' and the fact
352 ! that the response wave-function is a real-valued function, the above expression can be simplified as
353 ! trans_dipole = 4|e|/|G_mu| * Tr Imag(evects^T * (gamma_real - i gamma_imag) * C_0 * gamma_inv_00)
354 !
355 ! 1/|G_mu| = |lattice_vector_mu| / (2*pi) .
356 DO ispin = 1, nspins
357
358 DO ideriv = 1, nderivs
359 CALL cp_fm_to_fm(dberry_mos_occ(ideriv, ispin), dipole_op_mos_occ(ideriv, ispin))
360 END DO
361 END DO
362
363 CALL cp_fm_release(wfm_ao_ao)
364 CALL cp_fm_release(dberry_mos_occ)
365
367 IF (ndim_periodic /= 0) THEN
368 CALL cp_warn(__location__, &
369 "Non-periodic Poisson solver (PERIODIC none) "// &
370 "or a large supercell approach is needed "// &
371 "for oscillator strengths based on the length operator")
372 END IF
373
374 ! compute components of the dipole operator in the length form
375 NULLIFY (rrc_xyz)
376 CALL dbcsr_allocate_matrix_set(rrc_xyz, nderivs)
377
378 DO ideriv = 1, nderivs
379 CALL dbcsr_init_p(rrc_xyz(ideriv)%matrix)
380 CALL dbcsr_copy(rrc_xyz(ideriv)%matrix, matrix_s(1)%matrix)
381 END DO
382
383 CALL get_reference_point(reference_point, qs_env=qs_env, &
384 reference=tddfpt_control%dipole_reference, &
385 ref_point=tddfpt_control%dipole_ref_point)
386
387 CALL build_local_moment_matrix(qs_env, rrc_xyz, 1, ref_point=reference_point, &
388 all_images=.true.)
389
390 DO ispin = 1, nspins
391
392 DO ideriv = 1, nderivs
393 CALL cp_dbcsr_sm_fm_multiply(rrc_xyz(ideriv)%matrix, &
394 gs_mos(ispin)%mos_occ, &
395 dipole_op_mos_occ(ideriv, ispin), &
396 ncol=nmo_occ(ispin), alpha=1.0_dp, beta=0.0_dp)
397 END DO
398
399 END DO
400
401 CALL dbcsr_deallocate_matrix_set(rrc_xyz)
402
404 ! generate overlap derivatives
405 CALL get_qs_env(qs_env, ks_env=ks_env, sab_orb=sab_orb)
406 NULLIFY (scrm)
407 CALL build_overlap_matrix(ks_env, matrix_s=scrm, nderivative=1, &
408 basis_type_a="ORB", basis_type_b="ORB", &
409 sab_nl=sab_orb)
410
411 DO ispin = 1, nspins
412 DO ideriv = 1, nderivs
413 CALL cp_dbcsr_sm_fm_multiply(scrm(ideriv + 1)%matrix, &
414 gs_mos(ispin)%mos_occ, &
415 dipole_op_mos_occ(ideriv, ispin), &
416 ncol=nmo_occ(ispin), alpha=1.0_dp, beta=0.0_dp)
417 END DO
418
419 CALL cp_fm_release(wfm_mo_virt_mo_occ)
420 END DO
422
424 ! generate overlap derivatives
425 CALL get_qs_env(qs_env, ks_env=ks_env, sab_orb=sab_orb)
426 NULLIFY (scrm)
427 CALL build_overlap_matrix(ks_env, matrix_s=scrm, nderivative=1, &
428 basis_type_a="ORB", basis_type_b="ORB", &
429 sab_nl=sab_orb)
430
431 DO ispin = 1, nspins
432 NULLIFY (fm_struct)
433 CALL cp_fm_struct_create(fm_struct, nrow_global=nmo_virt(ispin), &
434 ncol_global=nmo_occ(ispin), context=blacs_env)
435 CALL cp_fm_create(ediff_inv, fm_struct)
436 CALL cp_fm_create(wfm_mo_virt_mo_occ, fm_struct)
437 CALL cp_fm_struct_release(fm_struct)
438
439 CALL cp_fm_get_info(ediff_inv, nrow_local=nrows_local, ncol_local=ncols_local, &
440 row_indices=row_indices, col_indices=col_indices, local_data=local_data_ediff)
441 CALL cp_fm_get_info(wfm_mo_virt_mo_occ, local_data=local_data_wfm)
442
443!$OMP PARALLEL DO DEFAULT(NONE), &
444!$OMP PRIVATE(eval_occ, icol, irow), &
445!$OMP SHARED(col_indices, gs_mos, ispin, local_data_ediff, ncols_local, nrows_local, row_indices)
446 DO icol = 1, ncols_local
447 ! E_occ_i ; imo_occ = col_indices(icol)
448 eval_occ = gs_mos(ispin)%evals_occ(col_indices(icol))
449
450 DO irow = 1, nrows_local
451 ! ediff_inv_weights(a, i) = 1.0 / (E_virt_a - E_occ_i)
452 ! imo_virt = row_indices(irow)
453 local_data_ediff(irow, icol) = 1.0_dp/(gs_mos(ispin)%evals_virt(row_indices(irow)) - eval_occ)
454 END DO
455 END DO
456!$OMP END PARALLEL DO
457
458 DO ideriv = 1, nderivs
459 CALL cp_dbcsr_sm_fm_multiply(scrm(ideriv + 1)%matrix, &
460 gs_mos(ispin)%mos_occ, &
461 dipole_op_mos_occ(ideriv, ispin), &
462 ncol=nmo_occ(ispin), alpha=1.0_dp, beta=0.0_dp)
463
464 CALL parallel_gemm('T', 'N', nmo_virt(ispin), nmo_occ(ispin), nao, &
465 1.0_dp, gs_mos(ispin)%mos_virt, dipole_op_mos_occ(ideriv, ispin), &
466 0.0_dp, wfm_mo_virt_mo_occ)
467
468 ! in-place element-wise (Schur) product;
469 ! avoid allocation of a temporary [nmo_virt x nmo_occ] matrix which is needed
470 ! for cp_fm_schur_product() subroutine call
471
472!$OMP PARALLEL DO DEFAULT(NONE), &
473!$OMP PRIVATE(icol, irow), &
474!$OMP SHARED(ispin, local_data_ediff, local_data_wfm, ncols_local, nrows_local)
475 DO icol = 1, ncols_local
476 DO irow = 1, nrows_local
477 local_data_wfm(irow, icol) = local_data_wfm(irow, icol)*local_data_ediff(irow, icol)
478 END DO
479 END DO
480!$OMP END PARALLEL DO
481
482 CALL parallel_gemm('N', 'N', nao, nmo_occ(ispin), nmo_virt(ispin), &
483 1.0_dp, s_mos_virt(ispin), wfm_mo_virt_mo_occ, &
484 0.0_dp, dipole_op_mos_occ(ideriv, ispin))
485 END DO
486
487 CALL cp_fm_release(wfm_mo_virt_mo_occ)
488 CALL cp_fm_release(ediff_inv)
489 END DO
491
492 CASE DEFAULT
493 cpabort("Unimplemented form of the dipole operator")
494 END SELECT
495
496 ! --- release work matrices
497 CALL cp_fm_release(s_mos_virt)
498
499 CALL timestop(handle)
500 END SUBROUTINE tddfpt_dipole_operator
501
502! **************************************************************************************************
503!> \brief Print final TDDFPT excitation energies and oscillator strengths.
504!> \param log_unit output unit
505!> \param evects TDDFPT trial vectors (SIZE(evects,1) -- number of spins;
506!> SIZE(evects,2) -- number of excited states to print)
507!> \param evals TDDFPT eigenvalues
508!> \param gs_mos ...
509!> \param ostrength TDDFPT oscillator strength
510!> \param mult multiplicity
511!> \param dipole_op_mos_occ action of the dipole operator on the ground state wave function
512!> [x,y,z ; spin]
513!> \param dipole_form ...
514!> \par History
515!> * 05.2016 created [Sergey Chulkov]
516!> * 06.2016 transition dipole moments and oscillator strengths [Sergey Chulkov]
517!> * 07.2016 spin-unpolarised electron density [Sergey Chulkov]
518!> * 08.2018 compute 'dipole_op_mos_occ' in a separate subroutine [Sergey Chulkov]
519!> \note \parblock
520!> Adapted version of the subroutine find_contributions() which was originally created
521!> by Thomas Chassaing on 02.2005.
522!>
523!> Transition dipole moment along direction 'd' is computed as following:
524!> \f[ t_d(spin) = Tr[evects^T dipole\_op\_mos\_occ(d, spin)] .\f]
525!> \endparblock
526! **************************************************************************************************
527 SUBROUTINE tddfpt_print_summary(log_unit, evects, evals, gs_mos, ostrength, mult, &
528 dipole_op_mos_occ, dipole_form)
529 INTEGER, INTENT(in) :: log_unit
530 TYPE(cp_fm_type), DIMENSION(:, :), INTENT(in) :: evects
531 REAL(kind=dp), DIMENSION(:), INTENT(in) :: evals
532 TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
533 POINTER :: gs_mos
534 REAL(kind=dp), DIMENSION(:), INTENT(inout) :: ostrength
535 INTEGER, INTENT(in) :: mult
536 TYPE(cp_fm_type), DIMENSION(:, :), INTENT(in) :: dipole_op_mos_occ
537 INTEGER, INTENT(in) :: dipole_form
538
539 CHARACTER(LEN=*), PARAMETER :: routinen = 'tddfpt_print_summary'
540
541 CHARACTER(len=1) :: lsd_str
542 CHARACTER(len=20) :: mult_str
543 INTEGER :: handle, i, ideriv, ispin, istate, j, &
544 nactive, nao, nocc, nspins, nstates
545 REAL(kind=dp) :: osc_strength
546 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: trans_dipoles
547 TYPE(cp_fm_struct_type), POINTER :: matrix_struct
548 TYPE(cp_fm_type) :: dipact
549
550 CALL timeset(routinen, handle)
551
552 nspins = SIZE(evects, 1)
553 nstates = SIZE(evects, 2)
554
555 IF (nspins > 1) THEN
556 lsd_str = 'U'
557 ELSE
558 lsd_str = 'R'
559 END IF
560
561 ! *** summary header ***
562 IF (log_unit > 0) THEN
563 CALL integer_to_string(mult, mult_str)
564 WRITE (log_unit, '(/,1X,A1,A,1X,A)') lsd_str, "-TDDFPT states of multiplicity", trim(mult_str)
565 SELECT CASE (dipole_form)
567 WRITE (log_unit, '(1X,A,/)') "Transition dipoles calculated using Berry operator formulation"
569 WRITE (log_unit, '(1X,A,/)') "Transition dipoles calculated using length formulation"
571 WRITE (log_unit, '(1X,A,/)') "Transition dipoles calculated using velocity formulation"
573 WRITE (log_unit, '(1X,A,/)') "Transition dipoles calculated using old velocity formulation"
575 WRITE (log_unit, '(1X,A,/)') "Transition dipoles calculated using SCF-MO moment formulation"
576 CASE DEFAULT
577 cpabort("Unimplemented form of the dipole operator")
578 END SELECT
579
580 WRITE (log_unit, '(T10,A,T19,A,T37,A,T69,A)') "State", "Excitation", &
581 "Transition dipole (a.u.)", "Oscillator"
582 WRITE (log_unit, '(T10,A,T19,A,T37,A,T49,A,T61,A,T67,A)') "number", "energy (eV)", &
583 "x", "y", "z", "strength (a.u.)"
584 WRITE (log_unit, '(T10,72("-"))')
585 END IF
586
587 ! transition dipole moment
588 ALLOCATE (trans_dipoles(nstates, nderivs, nspins))
589 trans_dipoles(:, :, :) = 0.0_dp
590
591 ! nspins == 1 .AND. mult == 3 : spin-flip transitions are forbidden due to symmetry reasons
592 IF (nspins > 1 .OR. mult == 1) THEN
593 DO ispin = 1, nspins
594 CALL cp_fm_get_info(dipole_op_mos_occ(1, ispin), nrow_global=nao, ncol_global=nocc)
595 CALL cp_fm_get_info(evects(ispin, 1), ncol_global=nactive)
596 IF (nocc == nactive) THEN
597 DO ideriv = 1, nderivs
598 CALL cp_fm_trace(evects(ispin, :), dipole_op_mos_occ(ideriv, ispin), &
599 trans_dipoles(:, ideriv, ispin))
600 END DO
601 ELSE ! res
602 CALL cp_fm_get_info(evects(ispin, 1), matrix_struct=matrix_struct)
603 CALL cp_fm_create(dipact, matrix_struct)
604 DO ideriv = 1, nderivs
605 DO i = 1, nactive
606 j = gs_mos(ispin)%index_active(i)
607 CALL cp_fm_to_fm(dipole_op_mos_occ(ideriv, ispin), dipact, &
608 ncol=1, source_start=j, target_start=i)
609 END DO
610 CALL cp_fm_trace(evects(ispin, :), dipact, trans_dipoles(:, ideriv, ispin))
611 END DO
612 CALL cp_fm_release(dipact)
613 END IF
614 END DO
615
616 IF (nspins == 1) THEN
617 trans_dipoles(:, :, 1) = sqrt(2.0_dp)*trans_dipoles(:, :, 1)
618 ELSE
619 trans_dipoles(:, :, 1) = trans_dipoles(:, :, 1) + trans_dipoles(:, :, 2)
620 END IF
621 END IF
622
623 ! *** summary information ***
624 DO istate = 1, nstates
625
626 SELECT CASE (dipole_form)
628 osc_strength = 2.0_dp/3.0_dp*evals(istate)*sum(trans_dipoles(istate, :, 1)**2)
630 osc_strength = 2.0_dp/3.0_dp*evals(istate)*sum(trans_dipoles(istate, :, 1)**2)
632 osc_strength = 2.0_dp/3.0_dp/evals(istate)*sum(trans_dipoles(istate, :, 1)**2)
634 osc_strength = 2.0_dp/3.0_dp*evals(istate)*sum(trans_dipoles(istate, :, 1)**2)
635 CASE DEFAULT
636 cpabort("Unimplemented form of the dipole operator")
637 END SELECT
638
639 ostrength(istate) = osc_strength
640 IF (log_unit > 0) THEN
641 WRITE (log_unit, '(1X,A,T9,I7,T19,F11.5,T31,3(1X,ES11.4E2),T69,ES12.5E2)') &
642 "TDDFPT|", istate, evals(istate)*evolt, trans_dipoles(istate, 1:nderivs, 1), osc_strength
643 END IF
644 END DO
645
646 ! punch a checksum for the regs
647 IF (log_unit > 0) THEN
648 WRITE (log_unit, '(/,T2,A,E16.8)') 'TDDFPT : CheckSum E = ', sqrt(sum(evals**2))
649 WRITE (log_unit, '(/,T2,A,E16.8)') 'TDDFPT : CheckSum F = ', sqrt(sum(ostrength**2))
650 END IF
651
652 DEALLOCATE (trans_dipoles)
653
654 CALL timestop(handle)
655 END SUBROUTINE tddfpt_print_summary
656
657! **************************************************************************************************
658!> \brief Print excitation analysis.
659!> \param log_unit output unit
660!> \param evects TDDFPT trial vectors (SIZE(evects,1) -- number of spins;
661!> SIZE(evects,2) -- number of excited states to print)
662!> \param evals TDDFPT eigenvalues
663!> \param gs_mos molecular orbitals optimised for the ground state
664!> \param matrix_s overlap matrix
665!> \param spinflip ...
666!> \param min_amplitude the smallest excitation amplitude to print
667!> \par History
668!> * 05.2016 created as 'tddfpt_print_summary' [Sergey Chulkov]
669!> * 08.2018 splited of from 'tddfpt_print_summary' [Sergey Chulkov]
670! **************************************************************************************************
671 SUBROUTINE tddfpt_print_excitation_analysis(log_unit, evects, evals, gs_mos, matrix_s, spinflip, &
672 min_amplitude)
673 INTEGER, INTENT(in) :: log_unit
674 TYPE(cp_fm_type), DIMENSION(:, :), INTENT(in) :: evects
675 REAL(kind=dp), DIMENSION(:), INTENT(in) :: evals
676 TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
677 INTENT(in) :: gs_mos
678 TYPE(dbcsr_type), POINTER :: matrix_s
679 INTEGER :: spinflip
680 REAL(kind=dp), INTENT(in) :: min_amplitude
681
682 CHARACTER(LEN=*), PARAMETER :: routinen = 'tddfpt_print_excitation_analysis'
683
684 CHARACTER(len=5) :: spin_label, spin_label2
685 INTEGER :: handle, icol, iproc, irow, ispin, &
686 istate, nao, ncols_local, nrows_local, &
687 nspins, nstates, spin2, state_spin, &
688 state_spin2
689 INTEGER(kind=int_8) :: iexc, imo_act, imo_occ, imo_virt, ind, &
690 nexcs, nexcs_local, nexcs_max_local, &
691 nmo_virt_occ, nmo_virt_occ_alpha
692 INTEGER(kind=int_8), ALLOCATABLE, DIMENSION(:) :: inds_local, inds_recv, nexcs_recv
693 INTEGER(kind=int_8), DIMENSION(1) :: nexcs_send
694 INTEGER(kind=int_8), DIMENSION(maxspins) :: nactive8, nmo_occ8, nmo_virt8
695 INTEGER, ALLOCATABLE, DIMENSION(:) :: inds
696 INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
697 INTEGER, DIMENSION(maxspins) :: nactive, nmo_occ, nmo_virt
698 LOGICAL :: do_exc_analysis
699 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: weights_local, weights_neg_abs_recv, &
700 weights_recv
701 REAL(kind=dp), CONTIGUOUS, DIMENSION(:, :), &
702 POINTER :: local_data
703 TYPE(cp_blacs_env_type), POINTER :: blacs_env
704 TYPE(cp_fm_struct_type), POINTER :: fm_struct
705 TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: s_mos_virt, weights_fm
706 TYPE(mp_para_env_type), POINTER :: para_env
707 TYPE(mp_request_type) :: send_handler, send_handler2
708 TYPE(mp_request_type), ALLOCATABLE, DIMENSION(:) :: recv_handlers, recv_handlers2
709
710 CALL timeset(routinen, handle)
711
712 nspins = SIZE(gs_mos, 1)
713 nstates = SIZE(evects, 2)
714 do_exc_analysis = min_amplitude < 1.0_dp
715
716 CALL cp_fm_get_info(gs_mos(1)%mos_occ, context=blacs_env, para_env=para_env)
717 CALL dbcsr_get_info(matrix_s, nfullrows_total=nao)
718
719 DO ispin = 1, nspins
720 nactive(ispin) = gs_mos(ispin)%nmo_active
721 nactive8(ispin) = int(nactive(ispin), kind=int_8)
722 nmo_occ(ispin) = SIZE(gs_mos(ispin)%evals_occ)
723 nmo_virt(ispin) = SIZE(gs_mos(ispin)%evals_virt)
724 nmo_occ8(ispin) = SIZE(gs_mos(ispin)%evals_occ, kind=int_8)
725 nmo_virt8(ispin) = SIZE(gs_mos(ispin)%evals_virt, kind=int_8)
726 END DO
727
728 ! *** excitation analysis ***
729 IF (do_exc_analysis) THEN
730 cpassert(log_unit <= 0 .OR. para_env%is_source())
731 nmo_virt_occ_alpha = int(nmo_virt(1), int_8)*int(nmo_occ(1), int_8)
732
733 IF (log_unit > 0) THEN
734 WRITE (log_unit, "(1X,A)") "", &
735 "-------------------------------------------------------------------------------", &
736 "- Excitation analysis -", &
737 "-------------------------------------------------------------------------------"
738 WRITE (log_unit, '(8X,A,T27,A,T49,A,T69,A)') "State", "Occupied", "Virtual", "Excitation"
739 WRITE (log_unit, '(8X,A,T28,A,T49,A,T69,A)') "number", "orbital", "orbital", "amplitude"
740 WRITE (log_unit, '(1X,79("-"))')
741
742 IF (nspins == 1) THEN
743 state_spin = 1
744 state_spin2 = 2
745 spin_label = ' '
746 spin_label2 = ' '
747 ELSE IF (spinflip /= no_sf_tddfpt) THEN
748 state_spin = 1
749 state_spin2 = 2
750 spin_label = '(alp)'
751 spin_label2 = '(bet)'
752 END IF
753 END IF
754
755 ALLOCATE (s_mos_virt(SIZE(evects, 1)), weights_fm(SIZE(evects, 1)))
756 DO ispin = 1, SIZE(evects, 1)
757 IF (spinflip == no_sf_tddfpt) THEN
758 spin2 = ispin
759 ELSE
760 spin2 = 2
761 END IF
762 CALL cp_fm_get_info(gs_mos(spin2)%mos_virt, matrix_struct=fm_struct)
763 CALL cp_fm_create(s_mos_virt(ispin), fm_struct)
764 CALL cp_dbcsr_sm_fm_multiply(matrix_s, &
765 gs_mos(spin2)%mos_virt, &
766 s_mos_virt(ispin), &
767 ncol=nmo_virt(spin2), alpha=1.0_dp, beta=0.0_dp)
768
769 NULLIFY (fm_struct)
770 CALL cp_fm_struct_create(fm_struct, nrow_global=nmo_virt(spin2), ncol_global=nactive(ispin), &
771 context=blacs_env)
772 CALL cp_fm_create(weights_fm(ispin), fm_struct)
773 CALL cp_fm_set_all(weights_fm(ispin), 0.0_dp)
774 CALL cp_fm_struct_release(fm_struct)
775 END DO
776
777 nexcs_max_local = 0
778 DO ispin = 1, SIZE(evects, 1)
779 CALL cp_fm_get_info(weights_fm(ispin), nrow_local=nrows_local, ncol_local=ncols_local)
780 nexcs_max_local = nexcs_max_local + int(nrows_local, int_8)*int(ncols_local, int_8)
781 END DO
782
783 ALLOCATE (weights_local(nexcs_max_local), inds_local(nexcs_max_local))
784
785 DO istate = 1, nstates
786 nexcs_local = 0
787 nmo_virt_occ = 0
788
789 ! analyse matrix elements locally and transfer only significant
790 ! excitations to the master node for subsequent ordering
791 DO ispin = 1, SIZE(evects, 1)
792 IF (spinflip == no_sf_tddfpt) THEN
793 spin2 = ispin
794 ELSE
795 spin2 = 2
796 END IF
797 ! compute excitation amplitudes
798 CALL parallel_gemm('T', 'N', nmo_virt(spin2), nactive(ispin), nao, 1.0_dp, s_mos_virt(ispin), &
799 evects(ispin, istate), 0.0_dp, weights_fm(ispin))
800
801 CALL cp_fm_get_info(weights_fm(ispin), nrow_local=nrows_local, ncol_local=ncols_local, &
802 row_indices=row_indices, col_indices=col_indices, local_data=local_data)
803
804 ! locate single excitations with significant amplitudes (>= min_amplitude)
805 DO icol = 1, ncols_local
806 DO irow = 1, nrows_local
807 IF (abs(local_data(irow, icol)) >= min_amplitude) THEN
808 ! number of non-negligible excitations
809 nexcs_local = nexcs_local + 1
810 ! excitation amplitude
811 weights_local(nexcs_local) = local_data(irow, icol)
812 ! index of single excitation (ivirt, iocc, ispin) in compressed form
813 inds_local(nexcs_local) = nmo_virt_occ + int(row_indices(irow), int_8) + &
814 int(col_indices(icol) - 1, int_8)*nmo_virt8(spin2)
815 END IF
816 END DO
817 END DO
818
819 nmo_virt_occ = nmo_virt_occ + nmo_virt8(spin2)*nmo_occ8(ispin)
820 END DO
821
822 IF (para_env%is_source()) THEN
823 ! master node
824 ALLOCATE (nexcs_recv(para_env%num_pe), recv_handlers(para_env%num_pe), recv_handlers2(para_env%num_pe))
825
826 ! collect number of non-negligible excitations from other nodes
827 DO iproc = 1, para_env%num_pe
828 IF (iproc - 1 /= para_env%mepos) THEN
829 CALL para_env%irecv(nexcs_recv(iproc:iproc), iproc - 1, recv_handlers(iproc), 0)
830 ELSE
831 nexcs_recv(iproc) = nexcs_local
832 END IF
833 END DO
834
835 DO iproc = 1, para_env%num_pe
836 IF (iproc - 1 /= para_env%mepos) THEN
837 CALL recv_handlers(iproc)%wait()
838 END IF
839 END DO
840
841 ! compute total number of non-negligible excitations
842 nexcs = 0
843 DO iproc = 1, para_env%num_pe
844 nexcs = nexcs + nexcs_recv(iproc)
845 END DO
846
847 ! receive indices and amplitudes of selected excitations
848 ALLOCATE (weights_recv(nexcs), weights_neg_abs_recv(nexcs))
849 ALLOCATE (inds_recv(nexcs), inds(nexcs))
850
851 nmo_virt_occ = 0
852 DO iproc = 1, para_env%num_pe
853 IF (nexcs_recv(iproc) > 0) THEN
854 IF (iproc - 1 /= para_env%mepos) THEN
855 ! excitation amplitudes
856 CALL para_env%irecv(weights_recv(nmo_virt_occ + 1:nmo_virt_occ + nexcs_recv(iproc)), &
857 iproc - 1, recv_handlers(iproc), 1)
858 ! compressed indices
859 CALL para_env%irecv(inds_recv(nmo_virt_occ + 1:nmo_virt_occ + nexcs_recv(iproc)), &
860 iproc - 1, recv_handlers2(iproc), 2)
861 ELSE
862 ! data on master node
863 weights_recv(nmo_virt_occ + 1:nmo_virt_occ + nexcs_recv(iproc)) = weights_local(1:nexcs_recv(iproc))
864 inds_recv(nmo_virt_occ + 1:nmo_virt_occ + nexcs_recv(iproc)) = inds_local(1:nexcs_recv(iproc))
865 END IF
866
867 nmo_virt_occ = nmo_virt_occ + nexcs_recv(iproc)
868 END IF
869 END DO
870
871 DO iproc = 1, para_env%num_pe
872 IF (iproc - 1 /= para_env%mepos .AND. nexcs_recv(iproc) > 0) THEN
873 CALL recv_handlers(iproc)%wait()
874 CALL recv_handlers2(iproc)%wait()
875 END IF
876 END DO
877
878 DEALLOCATE (nexcs_recv, recv_handlers, recv_handlers2)
879 ELSE
880 ! working node: send the number of selected excited states to the master node
881 nexcs_send(1) = nexcs_local
882 CALL para_env%isend(nexcs_send, para_env%source, send_handler, 0)
883 CALL send_handler%wait()
884
885 IF (nexcs_local > 0) THEN
886 ! send excitation amplitudes
887 CALL para_env%isend(weights_local(1:nexcs_local), para_env%source, send_handler, 1)
888 ! send compressed indices
889 CALL para_env%isend(inds_local(1:nexcs_local), para_env%source, send_handler2, 2)
890
891 CALL send_handler%wait()
892 CALL send_handler2%wait()
893 END IF
894 END IF
895
896 ! sort non-negligible excitations on the master node according to their amplitudes,
897 ! uncompress indices and print summary information
898 IF (para_env%is_source() .AND. log_unit > 0) THEN
899 weights_neg_abs_recv(:) = -abs(weights_recv)
900 CALL sort(weights_neg_abs_recv, int(nexcs), inds)
901
902 WRITE (log_unit, '(T7,I8,F10.5,A)') istate, evals(istate)*evolt, " eV"
903
904 ! This reinitialization is needed to prevent the intel fortran compiler from introduce
905 ! a bug when using optimization level 3 flag
906 state_spin = 1
907 state_spin2 = 1
908 IF (spinflip /= no_sf_tddfpt) THEN
909 state_spin = 1
910 state_spin2 = 2
911 END IF
912 DO iexc = 1, nexcs
913 ind = inds_recv(inds(iexc)) - 1
914 IF ((nspins > 1) .AND. (spinflip == no_sf_tddfpt)) THEN
915 IF (ind < nmo_virt_occ_alpha) THEN
916 state_spin = 1
917 state_spin2 = 1
918 spin_label = '(alp)'
919 spin_label2 = '(alp)'
920 ELSE
921 state_spin = 2
922 state_spin2 = 2
923 ind = ind - nmo_virt_occ_alpha
924 spin_label = '(bet)'
925 spin_label2 = '(bet)'
926 END IF
927 END IF
928 imo_act = ind/nmo_virt8(state_spin2) + 1
929 imo_occ = gs_mos(state_spin)%index_active(imo_act)
930 imo_virt = mod(ind, nmo_virt8(state_spin2)) + 1
931
932 WRITE (log_unit, '(T27,I8,1X,A5,T48,I8,1X,A5,T70,F9.6)') imo_occ, spin_label, &
933 nmo_occ8(state_spin2) + imo_virt, spin_label2, weights_recv(inds(iexc))
934 END DO
935 END IF
936
937 ! deallocate temporary arrays
938 IF (para_env%is_source()) THEN
939 DEALLOCATE (weights_recv, weights_neg_abs_recv, inds_recv, inds)
940 END IF
941 END DO
942
943 DEALLOCATE (weights_local, inds_local)
944 IF (log_unit > 0) THEN
945 WRITE (log_unit, "(1X,A)") &
946 "-------------------------------------------------------------------------------"
947 END IF
948 END IF
949
950 CALL cp_fm_release(weights_fm)
951 CALL cp_fm_release(s_mos_virt)
952
953 CALL timestop(handle)
954
956
957! **************************************************************************************************
958!> \brief Print natural transition orbital analysis.
959!> \param qs_env Information on Kinds and Particles
960!> \param evects TDDFPT trial vectors (SIZE(evects,1) -- number of spins;
961!> SIZE(evects,2) -- number of excited states to print)
962!> \param evals TDDFPT eigenvalues
963!> \param ostrength ...
964!> \param gs_mos molecular orbitals optimised for the ground state
965!> \param matrix_s overlap matrix
966!> \param print_section ...
967!> \par History
968!> * 06.2019 created [JGH]
969! **************************************************************************************************
970 SUBROUTINE tddfpt_print_nto_analysis(qs_env, evects, evals, ostrength, gs_mos, matrix_s, print_section)
971 TYPE(qs_environment_type), POINTER :: qs_env
972 TYPE(cp_fm_type), DIMENSION(:, :), INTENT(in) :: evects
973 REAL(kind=dp), DIMENSION(:), INTENT(in) :: evals, ostrength
974 TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
975 INTENT(in) :: gs_mos
976 TYPE(dbcsr_type), POINTER :: matrix_s
977 TYPE(section_vals_type), POINTER :: print_section
978
979 CHARACTER(LEN=*), PARAMETER :: routinen = 'tddfpt_print_nto_analysis'
980 INTEGER, PARAMETER :: ntomax = 10
981
982 CHARACTER(LEN=20), DIMENSION(2) :: nto_name
983 INTEGER :: handle, i, ia, icg, iounit, ispin, &
984 istate, j, nao, nlist, nmax, nmo, &
985 nnto, nspins, nstates
986 INTEGER, DIMENSION(2) :: iv
987 INTEGER, DIMENSION(2, ntomax) :: ia_index
988 INTEGER, DIMENSION(:), POINTER :: slist, stride
989 LOGICAL :: append_cube, cube_file, explicit
990 REAL(kind=dp) :: os_threshold, sume, threshold
991 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: eigvals
992 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: eigenvalues
993 REAL(kind=dp), DIMENSION(ntomax) :: ia_eval
994 TYPE(cell_type), POINTER :: cell
995 TYPE(cp_fm_struct_type), POINTER :: fm_mo_struct, fm_struct
996 TYPE(cp_fm_type) :: sev, smat, tmat, wmat, work, wvec
997 TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: teig
998 TYPE(cp_logger_type), POINTER :: logger
999 TYPE(mo_set_type), ALLOCATABLE, DIMENSION(:) :: nto_set
1000 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1001 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1002 TYPE(section_vals_type), POINTER :: molden_section, nto_section
1003
1004 CALL timeset(routinen, handle)
1005
1006 logger => cp_get_default_logger()
1007 iounit = cp_logger_get_default_io_unit(logger)
1008
1009 IF (btest(cp_print_key_should_output(logger%iter_info, print_section, &
1010 "NTO_ANALYSIS"), cp_p_file)) THEN
1011
1012 CALL cite_reference(martin2003)
1013
1014 CALL section_vals_val_get(print_section, "NTO_ANALYSIS%THRESHOLD", r_val=threshold)
1015 CALL section_vals_val_get(print_section, "NTO_ANALYSIS%INTENSITY_THRESHOLD", r_val=os_threshold)
1016 CALL section_vals_val_get(print_section, "NTO_ANALYSIS%STATE_LIST", explicit=explicit)
1017
1018 IF (explicit) THEN
1019 CALL section_vals_val_get(print_section, "NTO_ANALYSIS%STATE_LIST", i_vals=slist)
1020 nlist = SIZE(slist)
1021 ELSE
1022 nlist = 0
1023 END IF
1024
1025 IF (iounit > 0) THEN
1026 WRITE (iounit, "(1X,A)") "", &
1027 "-------------------------------------------------------------------------------", &
1028 "- Natural Orbital analysis -", &
1029 "-------------------------------------------------------------------------------"
1030 END IF
1031
1032 nspins = SIZE(evects, 1)
1033 nstates = SIZE(evects, 2)
1034 CALL dbcsr_get_info(matrix_s, nfullrows_total=nao)
1035
1036 DO istate = 1, nstates
1037 IF (os_threshold > ostrength(istate)) THEN
1038 IF (iounit > 0) THEN
1039 WRITE (iounit, "(1X,A,I6)") " Skipping state ", istate
1040 END IF
1041 cycle
1042 END IF
1043 IF (nlist > 0) THEN
1044 IF (.NOT. any(slist == istate)) THEN
1045 IF (iounit > 0) THEN
1046 WRITE (iounit, "(1X,A,I6)") " Skipping state ", istate
1047 END IF
1048 cycle
1049 END IF
1050 END IF
1051 IF (iounit > 0) THEN
1052 WRITE (iounit, "(1X,A,I6,T30,F10.5,A)") " STATE NR. ", istate, evals(istate)*evolt, " eV"
1053 END IF
1054 nmax = 0
1055 DO ispin = 1, nspins
1056 CALL cp_fm_get_info(evects(ispin, istate), matrix_struct=fm_struct, ncol_global=nmo)
1057 nmax = max(nmax, nmo)
1058 END DO
1059 ALLOCATE (eigenvalues(nmax, nspins))
1060 eigenvalues = 0.0_dp
1061 ! SET 1: Hole states
1062 ! SET 2: Particle states
1063 nto_name(1) = 'Hole_states'
1064 nto_name(2) = 'Particle_states'
1065 ALLOCATE (nto_set(2))
1066 DO i = 1, 2
1067 CALL allocate_mo_set(nto_set(i), nao, ntomax, 0, 0.0_dp, 1.0_dp, 0.0_dp)
1068 CALL cp_fm_get_info(evects(1, istate), matrix_struct=fm_struct)
1069 CALL cp_fm_struct_create(fmstruct=fm_mo_struct, template_fmstruct=fm_struct, &
1070 ncol_global=ntomax)
1071 CALL cp_fm_create(tmat, fm_mo_struct)
1072 CALL init_mo_set(nto_set(i), fm_ref=tmat, name=nto_name(i))
1073 CALL cp_fm_release(tmat)
1074 CALL cp_fm_struct_release(fm_mo_struct)
1075 END DO
1076 !
1077 ALLOCATE (teig(nspins))
1078 ! hole states
1079 ! Diagonalize X(T)*S*X
1080 DO ispin = 1, nspins
1081 associate(ev => evects(ispin, istate))
1082 CALL cp_fm_get_info(ev, matrix_struct=fm_struct, ncol_global=nmo)
1083 CALL cp_fm_create(sev, fm_struct)
1084 CALL cp_fm_struct_create(fmstruct=fm_mo_struct, template_fmstruct=fm_struct, &
1085 nrow_global=nmo, ncol_global=nmo)
1086 CALL cp_fm_create(tmat, fm_mo_struct)
1087 CALL cp_fm_create(teig(ispin), fm_mo_struct)
1088 CALL cp_dbcsr_sm_fm_multiply(matrix_s, ev, sev, ncol=nmo, alpha=1.0_dp, beta=0.0_dp)
1089 CALL parallel_gemm('T', 'N', nmo, nmo, nao, 1.0_dp, ev, sev, 0.0_dp, tmat)
1090 END associate
1091
1092 CALL choose_eigv_solver(tmat, teig(ispin), eigenvalues(1:nmo, ispin))
1093
1094 CALL cp_fm_struct_release(fm_mo_struct)
1095 CALL cp_fm_release(tmat)
1096 CALL cp_fm_release(sev)
1097 END DO
1098 ! find major determinants i->a
1099 ia_index = 0
1100 sume = 0.0_dp
1101 nnto = 0
1102 DO i = 1, ntomax
1103 iv = maxloc(eigenvalues)
1104 ia_eval(i) = eigenvalues(iv(1), iv(2))
1105 ia_index(1:2, i) = iv(1:2)
1106 sume = sume + ia_eval(i)
1107 eigenvalues(iv(1), iv(2)) = 0.0_dp
1108 nnto = nnto + 1
1109 IF (sume > threshold) EXIT
1110 END DO
1111 ! store hole states
1112 CALL set_mo_set(nto_set(1), nmo=nnto)
1113 DO i = 1, nnto
1114 ia = ia_index(1, i)
1115 ispin = ia_index(2, i)
1116 CALL cp_fm_get_info(gs_mos(ispin)%mos_occ, ncol_global=nmo)
1117 CALL cp_fm_get_info(teig(ispin), matrix_struct=fm_struct)
1118 CALL cp_fm_struct_create(fmstruct=fm_mo_struct, template_fmstruct=fm_struct, &
1119 nrow_global=nmo, ncol_global=1)
1120 CALL cp_fm_create(tmat, fm_mo_struct)
1121 CALL cp_fm_struct_release(fm_mo_struct)
1122 CALL cp_fm_get_info(gs_mos(1)%mos_occ, matrix_struct=fm_struct)
1123 CALL cp_fm_struct_create(fmstruct=fm_mo_struct, template_fmstruct=fm_struct, &
1124 ncol_global=1)
1125 CALL cp_fm_create(wvec, fm_mo_struct)
1126 CALL cp_fm_struct_release(fm_mo_struct)
1127 CALL cp_fm_to_fm(teig(ispin), tmat, 1, ia, 1)
1128 CALL parallel_gemm('N', 'N', nao, 1, nmo, 1.0_dp, gs_mos(ispin)%mos_occ, &
1129 tmat, 0.0_dp, wvec)
1130 CALL cp_fm_to_fm(wvec, nto_set(1)%mo_coeff, 1, 1, i)
1131 CALL cp_fm_release(wvec)
1132 CALL cp_fm_release(tmat)
1133 END DO
1134 ! particle states
1135 ! Solve generalized eigenvalue equation: (S*X)*(S*X)(T)*v = lambda*S*v
1136 CALL set_mo_set(nto_set(2), nmo=nnto)
1137 DO ispin = 1, nspins
1138 associate(ev => evects(ispin, istate))
1139 CALL cp_fm_get_info(ev, matrix_struct=fm_struct, nrow_global=nao, ncol_global=nmo)
1140 ALLOCATE (eigvals(nao))
1141 eigvals = 0.0_dp
1142 CALL cp_fm_create(sev, fm_struct)
1143 CALL cp_dbcsr_sm_fm_multiply(matrix_s, ev, sev, ncol=nmo, alpha=1.0_dp, beta=0.0_dp)
1144 END associate
1145 CALL cp_fm_struct_create(fmstruct=fm_mo_struct, template_fmstruct=fm_struct, &
1146 nrow_global=nao, ncol_global=nao)
1147 CALL cp_fm_create(tmat, fm_mo_struct)
1148 CALL cp_fm_create(smat, fm_mo_struct)
1149 CALL cp_fm_create(wmat, fm_mo_struct)
1150 CALL cp_fm_create(work, fm_mo_struct)
1151 CALL cp_fm_struct_release(fm_mo_struct)
1152 CALL copy_dbcsr_to_fm(matrix_s, smat)
1153 CALL parallel_gemm('N', 'T', nao, nao, nmo, 1.0_dp, sev, sev, 0.0_dp, tmat)
1154 CALL cp_fm_geeig(tmat, smat, wmat, eigvals, work)
1155 DO i = 1, nnto
1156 IF (ispin == ia_index(2, i)) THEN
1157 icg = 0
1158 DO j = 1, nao
1159 IF (abs(eigvals(j) - ia_eval(i)) < 1.e-6_dp) THEN
1160 icg = j
1161 EXIT
1162 END IF
1163 END DO
1164 IF (icg == 0) THEN
1165 CALL cp_warn(__location__, &
1166 "Could not locate particle state associated with hole state.")
1167 ELSE
1168 CALL cp_fm_to_fm(wmat, nto_set(2)%mo_coeff, 1, icg, i)
1169 END IF
1170 END IF
1171 END DO
1172 DEALLOCATE (eigvals)
1173 CALL cp_fm_release(sev)
1174 CALL cp_fm_release(tmat)
1175 CALL cp_fm_release(smat)
1176 CALL cp_fm_release(wmat)
1177 CALL cp_fm_release(work)
1178 END DO
1179 ! print
1180 IF (iounit > 0) THEN
1181 sume = 0.0_dp
1182 DO i = 1, nnto
1183 sume = sume + ia_eval(i)
1184 WRITE (iounit, "(T6,A,i2,T30,A,i1,T42,A,F8.5,T63,A,F8.5)") &
1185 "Particle-Hole state:", i, " Spin:", ia_index(2, i), &
1186 "Eigenvalue:", ia_eval(i), " Sum Eigv:", sume
1187 END DO
1188 END IF
1189 ! Cube and Molden files
1190 nto_section => section_vals_get_subs_vals(print_section, "NTO_ANALYSIS")
1191 CALL section_vals_val_get(nto_section, "CUBE_FILES", l_val=cube_file)
1192 CALL section_vals_val_get(nto_section, "STRIDE", i_vals=stride)
1193 CALL section_vals_val_get(nto_section, "APPEND", l_val=append_cube)
1194 IF (cube_file) THEN
1195 CALL print_nto_cubes(qs_env, nto_set, istate, stride, append_cube, nto_section)
1196 END IF
1197 CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set, particle_set=particle_set, cell=cell)
1198 molden_section => section_vals_get_subs_vals(print_section, "MOS_MOLDEN")
1199 CALL write_mos_molden(nto_set, qs_kind_set, particle_set, molden_section, cell=cell, qs_env=qs_env)
1200 !
1201 DEALLOCATE (eigenvalues)
1202 CALL cp_fm_release(teig)
1203 !
1204 DO i = 1, 2
1205 CALL deallocate_mo_set(nto_set(i))
1206 END DO
1207 DEALLOCATE (nto_set)
1208 END DO
1209
1210 IF (iounit > 0) THEN
1211 WRITE (iounit, "(1X,A)") &
1212 "-------------------------------------------------------------------------------"
1213 END IF
1214
1215 END IF
1216
1217 CALL timestop(handle)
1218
1219 END SUBROUTINE tddfpt_print_nto_analysis
1220
1221! **************************************************************************************************
1222!> \brief Print exciton descriptors, cf. Mewes et al., JCTC 14, 710-725 (2018)
1223!> \param log_unit output unit
1224!> \param evects TDDFPT trial vectors (SIZE(evects,1) -- number of spins;
1225!> SIZE(evects,2) -- number of excited states to print)
1226!> \param gs_mos molecular orbitals optimised for the ground state
1227!> \param matrix_s overlap matrix
1228!> \param do_directional_exciton_descriptors flag for computing descriptors for each (cartesian) direction
1229!> \param do_directional_exciton_crosscorrelation flag for adding the crosscorrelation matrix to the directional descriptors
1230!> \param qs_env Information on particles/geometry
1231!> \par History
1232!> * 12.2024 created as 'tddfpt_print_exciton_descriptors' [Maximilian Graml]
1233! **************************************************************************************************
1234 SUBROUTINE tddfpt_print_exciton_descriptors(log_unit, evects, gs_mos, matrix_s, &
1235 do_directional_exciton_descriptors, &
1236 do_directional_exciton_crosscorrelation, qs_env)
1237 INTEGER, INTENT(in) :: log_unit
1238 TYPE(cp_fm_type), DIMENSION(:, :), INTENT(in) :: evects
1239 TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
1240 INTENT(in) :: gs_mos
1241 TYPE(dbcsr_type), POINTER :: matrix_s
1242 LOGICAL, INTENT(IN) :: do_directional_exciton_descriptors, &
1243 do_directional_exciton_crosscorrelation
1244 TYPE(qs_environment_type), INTENT(IN), POINTER :: qs_env
1245
1246 CHARACTER(LEN=*), PARAMETER :: routinen = 'tddfpt_print_exciton_descriptors'
1247
1248 CHARACTER(LEN=4) :: prefix_output
1249 INTEGER :: handle, ispin, istate, n_moments_quad, &
1250 nactive, nao, nspins, nstates
1251 INTEGER, DIMENSION(maxspins) :: nmo_occ, nmo_virt
1252 LOGICAL :: print_checkvalue
1253 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: ref_point_multipole
1254 TYPE(cp_blacs_env_type), POINTER :: blacs_env
1255 TYPE(cp_fm_struct_type), POINTER :: fm_struct_mo_coeff, &
1256 fm_struct_s_mos_virt, fm_struct_x_ia_n
1257 TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: eigvec_x_ia_n, fm_multipole_ab, &
1258 fm_multipole_ai, fm_multipole_ij, &
1259 s_mos_virt
1260 TYPE(cp_fm_type), DIMENSION(:), POINTER :: mo_coeff
1261 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_multipole
1262 TYPE(exciton_descr_type), ALLOCATABLE, &
1263 DIMENSION(:) :: exc_descr
1264 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
1265 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1266
1267 CALL timeset(routinen, handle)
1268
1269 nspins = SIZE(evects, 1)
1270 nstates = SIZE(evects, 2)
1271
1272 cpassert(nspins == 1) ! Other spins are not yet implemented for exciton descriptors
1273
1274 CALL cp_fm_get_info(gs_mos(1)%mos_occ, context=blacs_env)
1275 CALL dbcsr_get_info(matrix_s, nfullrows_total=nao)
1276
1277 DO ispin = 1, nspins
1278 nmo_occ(ispin) = SIZE(gs_mos(ispin)%evals_occ)
1279 nmo_virt(ispin) = SIZE(gs_mos(ispin)%evals_virt)
1280 END DO
1281
1282 ! Prepare fm with all MO coefficents, i.e. nao x nao
1283 ALLOCATE (mo_coeff(nspins))
1284 CALL cp_fm_struct_create(fm_struct_mo_coeff, nrow_global=nao, ncol_global=nao, &
1285 context=blacs_env)
1286 DO ispin = 1, nspins
1287 CALL cp_fm_create(mo_coeff(ispin), fm_struct_mo_coeff)
1288 CALL cp_fm_to_fm_submat_general(gs_mos(ispin)%mos_occ, &
1289 mo_coeff(ispin), &
1290 nao, &
1291 nmo_occ(ispin), &
1292 1, &
1293 1, &
1294 1, &
1295 1, &
1296 blacs_env)
1297 CALL cp_fm_to_fm_submat_general(gs_mos(ispin)%mos_virt, &
1298 mo_coeff(ispin), &
1299 nao, &
1300 nmo_virt(ispin), &
1301 1, &
1302 1, &
1303 1, &
1304 nmo_occ(ispin) + 1, &
1305 blacs_env)
1306 END DO
1307 CALL cp_fm_struct_release(fm_struct_mo_coeff)
1308
1309 ! Compute multipole moments
1310 ! fm_multipole_XY have structure inherited by libint, i.e. x, y, z, xx, xy, xz, yy, yz, zz
1311 n_moments_quad = 9
1312 ALLOCATE (ref_point_multipole(3))
1313 ALLOCATE (fm_multipole_ij(n_moments_quad))
1314 ALLOCATE (fm_multipole_ab(n_moments_quad))
1315 ALLOCATE (fm_multipole_ai(n_moments_quad))
1316
1317 CALL get_multipoles_ao(qs_env, 2, matrix_multipole, ref_point_multipole)
1318 CALL get_qs_env(qs_env, mos=mos)
1319 CALL get_multipoles_mo(fm_multipole_ai, fm_multipole_ij, fm_multipole_ab, &
1320 matrix_multipole, mos, mo_coeff, &
1321 nmo_occ(1), nmo_virt(1), blacs_env)
1322 CALL dbcsr_deallocate_matrix_set(matrix_multipole)
1323
1324 CALL cp_fm_release(mo_coeff)
1325
1326 ! Compute eigenvector X of the Casida equation from trial vectors
1327 ALLOCATE (s_mos_virt(nspins), eigvec_x_ia_n(nspins))
1328 DO ispin = 1, nspins
1329 CALL cp_fm_get_info(gs_mos(ispin)%mos_virt, matrix_struct=fm_struct_s_mos_virt)
1330 CALL cp_fm_create(s_mos_virt(ispin), fm_struct_s_mos_virt)
1331 NULLIFY (fm_struct_s_mos_virt)
1332 CALL cp_dbcsr_sm_fm_multiply(matrix_s, &
1333 gs_mos(ispin)%mos_virt, &
1334 s_mos_virt(ispin), &
1335 ncol=nmo_virt(ispin), alpha=1.0_dp, beta=0.0_dp)
1336
1337 CALL cp_fm_struct_create(fm_struct_x_ia_n, nrow_global=nmo_occ(ispin), ncol_global=nmo_virt(ispin), &
1338 context=blacs_env)
1339 CALL cp_fm_create(eigvec_x_ia_n(ispin), fm_struct_x_ia_n)
1340 CALL cp_fm_struct_release(fm_struct_x_ia_n)
1341 END DO
1342 ALLOCATE (exc_descr(nstates))
1343 DO istate = 1, nstates
1344 DO ispin = 1, nspins
1345 CALL cp_fm_set_all(eigvec_x_ia_n(ispin), 0.0_dp)
1346 ! compute eigenvectors X of the TDA equation
1347 ! Reshuffle multiplication from
1348 ! X_ai = S_ma ^T * C_mi
1349 ! to
1350 ! X_ia = C_mi ^T * S_ma
1351 ! for compatibility with the structure needed for get_exciton_descriptors of bse_properties.F
1352 CALL cp_fm_get_info(evects(ispin, istate), ncol_global=nactive)
1353 IF (nactive /= nmo_occ(ispin)) THEN
1354 CALL cp_abort(__location__, &
1355 "Reduced active space excitations not implemented")
1356 END IF
1357 CALL parallel_gemm('T', 'N', nmo_occ(ispin), nmo_virt(ispin), nao, 1.0_dp, &
1358 evects(ispin, istate), s_mos_virt(ispin), 0.0_dp, eigvec_x_ia_n(ispin))
1359
1360 CALL get_exciton_descriptors(exc_descr, eigvec_x_ia_n(ispin), &
1361 fm_multipole_ij, fm_multipole_ab, &
1362 fm_multipole_ai, &
1363 istate, nmo_occ(ispin), nmo_virt(ispin))
1364 END DO
1365 END DO
1366 CALL cp_fm_release(eigvec_x_ia_n)
1367 CALL cp_fm_release(s_mos_virt)
1368 CALL cp_fm_release(fm_multipole_ai)
1369 CALL cp_fm_release(fm_multipole_ij)
1370 CALL cp_fm_release(fm_multipole_ab)
1371
1372 ! Actual printing
1373 print_checkvalue = .true.
1374 prefix_output = ' '
1375 CALL get_qs_env(qs_env, particle_set=particle_set)
1376 CALL print_exciton_descriptors(exc_descr, ref_point_multipole, log_unit, &
1377 nstates, print_checkvalue, do_directional_exciton_descriptors, &
1378 do_directional_exciton_crosscorrelation, prefix_output, particle_set)
1379
1380 DEALLOCATE (ref_point_multipole)
1381 DEALLOCATE (exc_descr)
1382
1383 CALL timestop(handle)
1384
1386
1387! **************************************************************************************************
1388!> \brief ...
1389!> \param vin ...
1390!> \param vout ...
1391!> \param mos_occ ...
1392!> \param matrix_s ...
1393! **************************************************************************************************
1394 SUBROUTINE project_vector(vin, vout, mos_occ, matrix_s)
1395 TYPE(dbcsr_type) :: vin, vout
1396 TYPE(cp_fm_type), INTENT(IN) :: mos_occ
1397 TYPE(dbcsr_type), POINTER :: matrix_s
1398
1399 CHARACTER(LEN=*), PARAMETER :: routinen = 'project_vector'
1400
1401 INTEGER :: handle, nao, nmo
1402 REAL(kind=dp) :: norm(1)
1403 TYPE(cp_fm_struct_type), POINTER :: fm_struct, fm_vec_struct
1404 TYPE(cp_fm_type) :: csvec, svec, vec
1405
1406 CALL timeset(routinen, handle)
1407
1408 CALL cp_fm_get_info(mos_occ, matrix_struct=fm_struct, nrow_global=nao, ncol_global=nmo)
1409 CALL cp_fm_struct_create(fmstruct=fm_vec_struct, template_fmstruct=fm_struct, &
1410 nrow_global=nao, ncol_global=1)
1411 CALL cp_fm_create(vec, fm_vec_struct)
1412 CALL cp_fm_create(svec, fm_vec_struct)
1413 CALL cp_fm_struct_release(fm_vec_struct)
1414 CALL cp_fm_struct_create(fmstruct=fm_vec_struct, template_fmstruct=fm_struct, &
1415 nrow_global=nmo, ncol_global=1)
1416 CALL cp_fm_create(csvec, fm_vec_struct)
1417 CALL cp_fm_struct_release(fm_vec_struct)
1418
1419 CALL copy_dbcsr_to_fm(vin, vec)
1420 CALL cp_dbcsr_sm_fm_multiply(matrix_s, vec, svec, ncol=1, alpha=1.0_dp, beta=0.0_dp)
1421 CALL parallel_gemm('T', 'N', nmo, 1, nao, 1.0_dp, mos_occ, svec, 0.0_dp, csvec)
1422 CALL parallel_gemm('N', 'N', nao, 1, nmo, -1.0_dp, mos_occ, csvec, 1.0_dp, vec)
1423 CALL cp_fm_vectorsnorm(vec, norm)
1424 cpassert(norm(1) > 1.e-14_dp)
1425 norm(1) = sqrt(1._dp/norm(1))
1426 CALL cp_fm_scale(norm(1), vec)
1427 CALL copy_fm_to_dbcsr(vec, vout, keep_sparsity=.false.)
1428
1429 CALL cp_fm_release(csvec)
1430 CALL cp_fm_release(svec)
1431 CALL cp_fm_release(vec)
1432
1433 CALL timestop(handle)
1434
1435 END SUBROUTINE project_vector
1436
1437! **************************************************************************************************
1438!> \brief ...
1439!> \param va ...
1440!> \param vb ...
1441!> \param res ...
1442! **************************************************************************************************
1443 SUBROUTINE vec_product(va, vb, res)
1444 TYPE(dbcsr_type) :: va, vb
1445 REAL(kind=dp), INTENT(OUT) :: res
1446
1447 CHARACTER(LEN=*), PARAMETER :: routinen = 'vec_product'
1448
1449 INTEGER :: handle, icol, irow
1450 LOGICAL :: found
1451 REAL(kind=dp), DIMENSION(:, :), POINTER :: vba, vbb
1452 TYPE(dbcsr_iterator_type) :: iter
1453 TYPE(mp_comm_type) :: group
1454
1455 CALL timeset(routinen, handle)
1456
1457 res = 0.0_dp
1458
1459 CALL dbcsr_get_info(va, group=group)
1460 CALL dbcsr_iterator_start(iter, va)
1461 DO WHILE (dbcsr_iterator_blocks_left(iter))
1462 CALL dbcsr_iterator_next_block(iter, irow, icol, vba)
1463 CALL dbcsr_get_block_p(vb, row=irow, col=icol, block=vbb, found=found)
1464 res = res + sum(vba*vbb)
1465 cpassert(found)
1466 END DO
1467 CALL dbcsr_iterator_stop(iter)
1468 CALL group%sum(res)
1469
1470 CALL timestop(handle)
1471
1472 END SUBROUTINE vec_product
1473
1474! **************************************************************************************************
1475!> \brief ...
1476!> \param qs_env ...
1477!> \param mos ...
1478!> \param istate ...
1479!> \param stride ...
1480!> \param append_cube ...
1481!> \param print_section ...
1482! **************************************************************************************************
1483 SUBROUTINE print_nto_cubes(qs_env, mos, istate, stride, append_cube, print_section)
1484
1485 TYPE(qs_environment_type), POINTER :: qs_env
1486 TYPE(mo_set_type), DIMENSION(:), INTENT(IN) :: mos
1487 INTEGER, INTENT(IN) :: istate
1488 INTEGER, DIMENSION(:), POINTER :: stride
1489 LOGICAL, INTENT(IN) :: append_cube
1490 TYPE(section_vals_type), POINTER :: print_section
1491
1492 CHARACTER(LEN=default_path_length) :: filename, my_pos_cube, title
1493 INTEGER :: i, iset, nmo, unit_nr
1494 LOGICAL :: mpi_io
1495 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
1496 TYPE(cell_type), POINTER :: cell
1497 TYPE(cp_fm_type), POINTER :: mo_coeff
1498 TYPE(cp_logger_type), POINTER :: logger
1499 TYPE(dft_control_type), POINTER :: dft_control
1500 TYPE(particle_list_type), POINTER :: particles
1501 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1502 TYPE(pw_c1d_gs_type) :: wf_g
1503 TYPE(pw_env_type), POINTER :: pw_env
1504 TYPE(pw_pool_p_type), DIMENSION(:), POINTER :: pw_pools
1505 TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
1506 TYPE(pw_r3d_rs_type) :: wf_r
1507 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1508 TYPE(qs_subsys_type), POINTER :: subsys
1509
1510 logger => cp_get_default_logger()
1511
1512 CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, pw_env=pw_env)
1513 CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, pw_pools=pw_pools)
1514 CALL auxbas_pw_pool%create_pw(wf_r)
1515 CALL auxbas_pw_pool%create_pw(wf_g)
1516
1517 CALL get_qs_env(qs_env, subsys=subsys)
1518 CALL qs_subsys_get(subsys, particles=particles)
1519
1520 my_pos_cube = "REWIND"
1521 IF (append_cube) THEN
1522 my_pos_cube = "APPEND"
1523 END IF
1524
1525 CALL get_qs_env(qs_env=qs_env, &
1526 atomic_kind_set=atomic_kind_set, &
1527 qs_kind_set=qs_kind_set, &
1528 cell=cell, &
1529 particle_set=particle_set)
1530
1531 DO iset = 1, 2
1532 CALL get_mo_set(mo_set=mos(iset), mo_coeff=mo_coeff, nmo=nmo)
1533 DO i = 1, nmo
1534 CALL calculate_wavefunction(mo_coeff, i, wf_r, wf_g, atomic_kind_set, qs_kind_set, &
1535 cell, dft_control, particle_set, pw_env)
1536 IF (iset == 1) THEN
1537 WRITE (filename, '(a4,I3.3,I2.2,a11)') "NTO_STATE", istate, i, "_Hole_State"
1538 ELSE IF (iset == 2) THEN
1539 WRITE (filename, '(a4,I3.3,I2.2,a15)') "NTO_STATE", istate, i, "_Particle_State"
1540 END IF
1541 mpi_io = .true.
1542 unit_nr = cp_print_key_unit_nr(logger, print_section, '', extension=".cube", &
1543 middle_name=trim(filename), file_position=my_pos_cube, &
1544 log_filename=.false., ignore_should_output=.true., mpi_io=mpi_io)
1545 IF (iset == 1) THEN
1546 WRITE (title, *) "Natural Transition Orbital Hole State", i
1547 ELSE IF (iset == 2) THEN
1548 WRITE (title, *) "Natural Transition Orbital Particle State", i
1549 END IF
1550 CALL cp_pw_to_cube(wf_r, unit_nr, title, particles=particles, stride=stride, mpi_io=mpi_io)
1551 CALL cp_print_key_finished_output(unit_nr, logger, print_section, '', &
1552 ignore_should_output=.true., mpi_io=mpi_io)
1553 END DO
1554 END DO
1555
1556 CALL auxbas_pw_pool%give_back_pw(wf_g)
1557 CALL auxbas_pw_pool%give_back_pw(wf_r)
1558
1559 END SUBROUTINE print_nto_cubes
1560
1561END MODULE qs_tddfpt2_properties
Define the atomic kind types and their sub types.
collects all references to literature in CP2K as new algorithms / method are included from literature...
integer, save, public martin2003
Routines for printing information in context of the BSE calculation.
Definition bse_print.F:13
subroutine, public print_exciton_descriptors(exc_descr, ref_point_multipole, unit_nr, num_print_exc_descr, print_checkvalue, print_directional_exc_descr, print_directional_crosscorrelation, prefix_output, particle_set)
Prints exciton descriptors, cf. Mewes et al., JCTC 14, 710-725 (2018).
Definition bse_print.F:669
Routines for computing excitonic properties, e.g. exciton diameter, from the BSE.
subroutine, public get_exciton_descriptors(exc_descr, fm_x_ia, fm_multipole_ij_trunc, fm_multipole_ab_trunc, fm_multipole_ai_trunc, i_exc, homo, virtual, fm_y_ia)
...
Auxiliary routines for GW + Bethe-Salpeter for computing electronic excitations.
Definition bse_util.F:13
subroutine, public get_multipoles_mo(fm_multipole_ai_trunc, fm_multipole_ij_trunc, fm_multipole_ab_trunc, matrix_multipole, mos, mo_coeff, homo_red, virtual_red, context_bse, ispin)
The multipoles in the MO window, D^k_pq = sum_µν C_µp M^k_µν C_νq, cut to the ai, ij and ab blocks of...
Definition bse_util.F:1744
Handles all functions related to the CELL.
Definition cell_types.F:15
methods related to the blacs parallel environment
Basic linear algebra operations for complex full matrices.
subroutine, public cp_cfm_solve(matrix_a, general_a, determinant)
Solve the system of linear equations A*b=A_general using LU decomposition. Pay attention that both ma...
Represents a complex full matrix distributed on many processors.
subroutine, public cp_cfm_release(matrix)
Releases a full matrix.
subroutine, public cp_fm_to_cfm(msourcer, msourcei, mtarget)
Construct a complex full matrix by taking its real and imaginary parts from two separate real-value f...
subroutine, public cp_cfm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
Creates a new full matrix with the given structure.
subroutine, public cp_cfm_set_all(matrix, alpha, beta)
Set all elements of the full matrix to alpha. Besides, set all diagonal matrix elements to beta (if g...
subroutine, public cp_cfm_to_fm(msource, mtargetr, mtargeti)
Copy real and imaginary parts of a complex full matrix into separate real-value full matrices.
Defines control structures, which contain the parameters and the settings for the DFT-based calculati...
logical function, public dbcsr_iterator_blocks_left(iterator)
...
subroutine, public dbcsr_iterator_stop(iterator)
...
subroutine, public dbcsr_copy(matrix_b, matrix_a, name, keep_sparsity, keep_imaginary)
...
subroutine, public dbcsr_get_block_p(matrix, row, col, block, found, row_size, col_size)
...
subroutine, public dbcsr_get_info(matrix, nblkrows_total, nblkcols_total, nfullrows_total, nfullcols_total, nblkrows_local, nblkcols_local, nfullrows_local, nfullcols_local, my_prow, my_pcol, local_rows, local_cols, proc_row_dist, proc_col_dist, row_blk_size, col_blk_size, row_blk_offset, col_blk_offset, distribution, name, matrix_type, group)
...
subroutine, public dbcsr_init_p(matrix)
...
subroutine, public dbcsr_iterator_next_block(iterator, row, column, block, block_number_argument_has_been_removed, row_size, col_size, row_offset, col_offset, transposed)
...
subroutine, public dbcsr_iterator_start(iterator, matrix, shared, dynamic, dynamic_byrows)
...
DBCSR operations in CP2K.
subroutine, public cp_dbcsr_sm_fm_multiply(matrix, fm_in, fm_out, ncol, alpha, beta)
multiply a dbcsr with a fm matrix
subroutine, public copy_dbcsr_to_fm(matrix, fm, plan)
Copy a DBCSR matrix to a BLACS matrix.
subroutine, public copy_fm_to_dbcsr(fm, matrix, keep_sparsity)
Copy a BLACS matrix to a dbcsr matrix.
Basic linear algebra operations for full matrices.
subroutine, public cp_fm_scale_and_add(alpha, matrix_a, beta, matrix_b)
calc A <- alpha*A + beta*B optimized for alpha == 1.0 (just add beta*B) and beta == 0....
subroutine, public cp_fm_scale(alpha, matrix_a)
scales a matrix matrix_a = alpha * matrix_b
used for collecting some of the diagonalization schemes available for cp_fm_type. cp_fm_power also mo...
Definition cp_fm_diag.F:17
subroutine, public cp_fm_geeig(amatrix, bmatrix, eigenvectors, eigenvalues, work)
General Eigenvalue Problem AX = BXE. Use cuSOLVERMp directly when requested and large enough; otherwi...
subroutine, public choose_eigv_solver(matrix, eigenvectors, eigenvalues, info)
Choose the Eigensolver depending on which library is available ELPA seems to be unstable for small sy...
Definition cp_fm_diag.F:262
represent the structure of a full matrix
subroutine, public cp_fm_struct_create(fmstruct, para_env, context, nrow_global, ncol_global, nrow_block, ncol_block, descriptor, first_p_pos, local_leading_dimension, template_fmstruct, square_blocks, force_block)
allocates and initializes a full matrix structure
subroutine, public cp_fm_struct_release(fmstruct)
releases a full matrix structure
represent a full matrix distributed on many processors
Definition cp_fm_types.F:15
subroutine, public cp_fm_get_info(matrix, name, nrow_global, ncol_global, nrow_block, ncol_block, nrow_local, ncol_local, row_indices, col_indices, local_data, context, nrow_locals, ncol_locals, matrix_struct, para_env)
returns all kind of information about the full matrix
subroutine, public cp_fm_vectorsnorm(matrix, norm_array)
find the inorm of each column norm_{j}= sqrt( \sum_{i} A_{ij}*A_{ij} )
subroutine, public cp_fm_to_fm_submat_general(source, destination, nrows, ncols, s_firstrow, s_firstcol, d_firstrow, d_firstcol, global_context)
General copy of a submatrix of fm matrix to a submatrix of another fm matrix. The two matrices can ha...
subroutine, public cp_fm_set_all(matrix, alpha, beta)
set all elements of a matrix to the same value, and optionally the diagonal to a different one
subroutine, public cp_fm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
creates a new full matrix with the given structure
various routines to log and control the output. The idea is that decisions about where to log should ...
integer function, public cp_logger_get_default_io_unit(logger)
returns the unit nr for the ionode (-1 on all other processors) skips as well checks if the procs cal...
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
routines to handle the output, The idea is to remove the decision of wheter to output and what to out...
integer function, public cp_print_key_unit_nr(logger, basis_section, print_key_path, extension, middle_name, local, log_filename, ignore_should_output, file_form, file_position, file_action, file_status, do_backup, on_file, is_new_file, mpi_io, fout)
...
subroutine, public cp_print_key_finished_output(unit_nr, logger, basis_section, print_key_path, local, ignore_should_output, on_file, mpi_io)
should be called after you finish working with a unit obtained with cp_print_key_unit_nr,...
integer, parameter, public cp_p_file
integer function, public cp_print_key_should_output(iteration_info, basis_section, print_key_path, used_print_key, first_time)
returns what should be done with the given property if btest(res,cp_p_store) then the property should...
A wrapper around pw_to_cube() which accepts particle_list_type.
subroutine, public cp_pw_to_cube(pw, unit_nr, title, particles, zeff, stride, max_file_size_mb, zero_tails, silent, mpi_io)
...
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public tddfpt_dipole_berry
integer, parameter, public tddfpt_dipole_scf_moment
integer, parameter, public tddfpt_dipole_velocity
integer, parameter, public tddfpt_dipole_length
integer, parameter, public tddfpt_dipole_velocity_old
integer, parameter, public no_sf_tddfpt
objects that represent the structure of input sections and the data contained in an input section
recursive type(section_vals_type) function, pointer, public section_vals_get_subs_vals(section_vals, subsection_name, i_rep_section, can_return_null)
returns the values of the requested subsection
subroutine, public section_vals_val_get(section_vals, keyword_name, i_rep_section, i_rep_val, n_rep_val, val, l_val, i_val, r_val, c_val, l_vals, i_vals, r_vals, c_vals, explicit)
returns the requested value
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public int_8
Definition kinds.F:54
integer, parameter, public dp
Definition kinds.F:34
integer, parameter, public default_path_length
Definition kinds.F:58
Definition of mathematical constants and functions.
complex(kind=dp), parameter, public z_one
real(kind=dp), parameter, public twopi
complex(kind=dp), parameter, public z_zero
Interface to the message passing library MPI.
Functions handling the MOLDEN format. Split from mode_selective.
subroutine, public write_mos_molden(mos, qs_kind_set, particle_set, print_section, cell, unoccupied_orbs, unoccupied_evals, qs_env, calc_energies)
Write out the MOs in molden format for visualisation.
Calculates the moment integrals <a|r^m|b>.
subroutine, public get_reference_point(rpoint, drpoint, qs_env, fist_env, reference, ref_point, ifirst, ilast)
...
basic linear algebra operations for full matrixes
represent a simple array based list of the given type
Define the data structure for the particle information.
Definition of physical constants:
Definition physcon.F:68
real(kind=dp), parameter, public evolt
Definition physcon.F:183
container for various plainwaves related things
subroutine, public pw_env_get(pw_env, pw_pools, cube_info, gridlevel_info, auxbas_pw_pool, auxbas_grid, auxbas_rs_desc, auxbas_rs_grid, rs_descs, rs_grids, xc_pw_pool, vdw_pw_pool, poisson_env, interp_section)
returns the various attributes of the pw env
functions related to the poisson solver on regular grids
Manages a pool of grids (to be used for example as tmp objects), but can also be used to instantiate ...
Calculate the plane wave density by collocating the primitive Gaussian functions (pgf).
subroutine, public calculate_wavefunction(mo_vectors, ivector, rho, rho_gspace, atomic_kind_set, qs_kind_set, cell, dft_control, particle_set, pw_env, basis_type)
maps a given wavefunction on the grid
subroutine, public get_qs_env(qs_env, atomic_kind_set, qs_kind_set, cell, super_cell, cell_ref, use_ref_cell, kpoints, dft_control, mos, sab_orb, sab_all, qmmm, qmmm_periodic, mimic, sac_ae, sac_ppl, sac_lri, sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_almo, sab_kp, sab_kp_nosym, sab_cneo, particle_set, energy, force, matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, run_rtp, rtp, matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_ks_im_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, matrix_s_ri_aux_kp, matrix_s, matrix_s_ri_aux, matrix_w, matrix_p_mp2, matrix_p_mp2_admm, matrix_vhxc, rho, rho_xc, pw_env, ewald_env, ewald_pw, active_space, mpools, input, para_env, blacs_env, scf_control, rel_control, kinetic, qs_charges, vppl, xcint_weights, rho_core, rho_nlcc, rho_nlcc_g, ks_env, ks_qmmm_env, wf_history, scf_env, local_particles, local_molecules, distribution_2d, dbcsr_dist, molecule_kind_set, molecule_set, subsys, cp_subsys, oce, local_rho_set, rho_atom_set, task_list, task_list_soft, rho0_atom_set, rho0_mpole, rhoz_set, rhoz_cneo_set, ecoul_1c, rho0_s_rs, rho0_s_gs, rhoz_cneo_s_rs, rhoz_cneo_s_gs, do_kpoints, has_unit_metric, requires_mo_derivs, mo_derivs, mo_loc_history, nkind, natom, nelectron_total, nelectron_spin, efield, neighbor_list_id, linres_control, xas_env, virial, cp_ddapc_env, cp_ddapc_ewald, outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, results, se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, lri_env, lri_density, exstate_env, ec_env, harris_env, dispersion_env, gcp_env, vee, rho_external, external_vxc, mask, mp2_env, bs_env, kg_env, wanniercentres, atprop, ls_scf_env, do_transport, transport_env, v_hartree_rspace, s_mstruct_changed, rho_changed, potential_changed, forces_up_to_date, mscfg_env, almo_scf_env, gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, eeq, rhs, do_rixs, tb_tblite)
Get the QUICKSTEP environment.
Define the quickstep kind type and their sub types.
Definition and initialisation of the mo data type.
Definition qs_mo_types.F:22
subroutine, public set_mo_set(mo_set, maxocc, homo, lfomo, nao, nelectron, n_el_f, nmo, eigenvalues, occupation_numbers, uniform_occupation, kts, mu, flexible_electron_count)
Set the components of a MO set data structure.
subroutine, public init_mo_set(mo_set, fm_pool, fm_ref, fm_struct, name, counter, complex_coeff)
initializes an allocated mo_set. eigenvalues, mo_coeff, occupation_numbers are valid only after this ...
subroutine, public allocate_mo_set(mo_set, nao, nmo, nelectron, n_el_f, maxocc, flexible_electron_count)
Allocates a mo set and partially initializes it (nao,nmo,nelectron, and flexible_electron_count are v...
subroutine, public deallocate_mo_set(mo_set)
Deallocate a wavefunction data structure.
subroutine, public get_mo_set(mo_set, maxocc, homo, lfomo, nao, nelectron, n_el_f, nmo, eigenvalues, occupation_numbers, mo_coeff, mo_coeff_b, uniform_occupation, kts, mu, flexible_electron_count, cmo_coeff)
Get the components of a MO set data structure.
Calculates the moment integrals <a|r^m|b> and <a|r x d/dr|b>.
Definition qs_moments.F:14
subroutine, public build_local_moment_matrix(qs_env, moments, nmoments, ref_point, ref_points, basis_type, all_images, minimum_image, neighbor_image, first_component)
...
Definition qs_moments.F:166
subroutine, public build_berry_moment_matrix(qs_env, cosmat, sinmat, kvec, sab_orb_external, basis_type)
...
subroutine, public get_multipoles_ao(qs_env, n_moments, matrix_multipole, rpoint)
The AO multipoles M^k_µν = <φ_µ|(r - r_0)^k|φ_ν> of every order up to n_moments, on the block pattern...
Definition qs_moments.F:427
Define the neighbor list data types and the corresponding functionality.
Calculation of overlap matrix, its derivatives and forces.
Definition qs_overlap.F:19
subroutine, public build_overlap_matrix(ks_env, matrix_s, matrixkp_s, matrix_name, nderivative, basis_type_a, basis_type_b, sab_nl, calculate_forces, matrix_p, matrixkp_p, ext_kpoints)
Calculation of the overlap matrix over Cartesian Gaussian functions.
Definition qs_overlap.F:121
types that represent a quickstep subsys
subroutine, public qs_subsys_get(subsys, atomic_kinds, atomic_kind_set, particles, particle_set, local_particles, molecules, molecule_set, molecule_kinds, molecule_kind_set, local_molecules, para_env, colvar_p, shell_particles, core_particles, gci, multipoles, natom, nparticle, ncore, nshell, nkind, atprop, virial, results, cell, cell_ref, use_ref_cell, energy, force, qs_kind_set, cp_subsys, nelectron_total, nelectron_spin)
...
subroutine, public tddfpt_dipole_operator(dipole_op_mos_occ, tddfpt_control, gs_mos, qs_env)
Compute the action of the dipole operator on the ground state wave function.
subroutine, public tddfpt_print_nto_analysis(qs_env, evects, evals, ostrength, gs_mos, matrix_s, print_section)
Print natural transition orbital analysis.
subroutine, public tddfpt_print_exciton_descriptors(log_unit, evects, gs_mos, matrix_s, do_directional_exciton_descriptors, do_directional_exciton_crosscorrelation, qs_env)
Print exciton descriptors, cf. Mewes et al., JCTC 14, 710-725 (2018).
subroutine, public tddfpt_print_excitation_analysis(log_unit, evects, evals, gs_mos, matrix_s, spinflip, min_amplitude)
Print excitation analysis.
subroutine, public tddfpt_print_summary(log_unit, evects, evals, gs_mos, ostrength, mult, dipole_op_mos_occ, dipole_form)
Print final TDDFPT excitation energies and oscillator strengths.
Utilities for string manipulations.
subroutine, public integer_to_string(inumber, string)
Converts an integer number to a string. The WRITE statement will return an error message,...
All kind of helpful little routines.
Definition util.F:14
Provides all information about an atomic kind.
Type defining parameters related to the simulation cell.
Definition cell_types.F:60
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
Represent a complex full matrix.
keeps the information about the structure of a full matrix
represent a full matrix
type of a logger, at the moment it contains just a print level starting at which level it should be l...
stores all the informations relevant to an mpi environment
contained for different pw related things
environment for the poisson solver
to create arrays of pools
Manages a pool of grids (to be used for example as tmp objects), but can also be used to instantiate ...
Provides all information about a quickstep kind.
calculation environment to calculate the ks matrix, holds all the needed vars. assumes that the core ...
Ground state molecular orbitals.