(git:da6e80d)
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-2025 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,&
68 USE kinds, ONLY: default_path_length,&
69 dp,&
70 int_8
71 USE mathconstants, ONLY: twopi,&
72 z_one,&
73 z_zero
74 USE message_passing, ONLY: mp_comm_type,&
82 USE physcon, ONLY: evolt
83 USE pw_env_types, ONLY: pw_env_get,&
86 USE pw_pool_types, ONLY: pw_pool_p_type,&
88 USE pw_types, ONLY: pw_c1d_gs_type,&
95 USE qs_mo_types, ONLY: allocate_mo_set,&
103 USE qs_operators_ao, ONLY: rrc_xyz_ao
105 USE qs_subsys_types, ONLY: qs_subsys_get,&
109 USE util, ONLY: sort
110#include "./base/base_uses.f90"
111
112 IMPLICIT NONE
113
114 PRIVATE
115
116 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_tddfpt2_properties'
117
118 ! number of first derivative components (3: d/dx, d/dy, d/dz)
119 INTEGER, PARAMETER, PRIVATE :: nderivs = 3
120 INTEGER, PARAMETER, PRIVATE :: maxspins = 2
121
124
125! **************************************************************************************************
126
127CONTAINS
128
129! **************************************************************************************************
130!> \brief Compute the action of the dipole operator on the ground state wave function.
131!> \param dipole_op_mos_occ 2-D array [x,y,z ; spin] of matrices where to put the computed quantity
132!> (allocated and initialised on exit)
133!> \param tddfpt_control TDDFPT control parameters
134!> \param gs_mos molecular orbitals optimised for the ground state
135!> \param qs_env Quickstep environment
136!> \par History
137!> * 05.2016 created as 'tddfpt_print_summary' [Sergey Chulkov]
138!> * 06.2018 dipole operator based on the Berry-phase formula [Sergey Chulkov]
139!> * 08.2018 splited of from 'tddfpt_print_summary' and merged with code from 'tddfpt'
140!> [Sergey Chulkov]
141!> \note \parblock
142!> Adapted version of the subroutine find_contributions() which was originally created
143!> by Thomas Chassaing on 02.2005.
144!>
145!> The relation between dipole integrals in velocity and length forms are the following:
146!> \f[<\psi_i|\nabla|\psi_a> = <\psi_i|\vec{r}|\hat{H}\psi_a> - <\hat{H}\psi_i|\vec{r}|\psi_a>
147!> = (\epsilon_a - \epsilon_i) <\psi_i|\vec{r}|\psi_a> .\f],
148!> due to the commutation identity:
149!> \f[\vec{r}\hat{H} - \hat{H}\vec{r} = [\vec{r},\hat{H}] = [\vec{r},-1/2 \nabla^2] = \nabla\f] .
150!> \endparblock
151! **************************************************************************************************
152 SUBROUTINE tddfpt_dipole_operator(dipole_op_mos_occ, tddfpt_control, gs_mos, qs_env)
153 TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :), &
154 INTENT(inout) :: dipole_op_mos_occ
155 TYPE(tddfpt2_control_type), POINTER :: tddfpt_control
156 TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
157 INTENT(in) :: gs_mos
158 TYPE(qs_environment_type), POINTER :: qs_env
159
160 CHARACTER(LEN=*), PARAMETER :: routinen = 'tddfpt_dipole_operator'
161
162 INTEGER :: handle, i_cos_sin, icol, ideriv, irow, &
163 ispin, jderiv, nao, ncols_local, &
164 ndim_periodic, nrows_local, nspins
165 INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
166 INTEGER, DIMENSION(maxspins) :: nmo_occ, nmo_virt
167 REAL(kind=dp) :: eval_occ
168 REAL(kind=dp), CONTIGUOUS, DIMENSION(:, :), &
169 POINTER :: local_data_ediff, local_data_wfm
170 REAL(kind=dp), DIMENSION(3) :: kvec, reference_point
171 TYPE(cell_type), POINTER :: cell
172 TYPE(cp_blacs_env_type), POINTER :: blacs_env
173 TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:) :: gamma_00, gamma_inv_00
174 TYPE(cp_fm_struct_type), POINTER :: fm_struct
175 TYPE(cp_fm_type) :: ediff_inv, rrc_mos_occ, wfm_ao_ao, &
176 wfm_mo_virt_mo_occ
177 TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: s_mos_virt
178 TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: dberry_mos_occ, gamma_real_imag, opvec
179 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: berry_cossin_xyz, matrix_s, rrc_xyz, scrm
180 TYPE(dft_control_type), POINTER :: dft_control
181 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
182 POINTER :: sab_orb
183 TYPE(pw_env_type), POINTER :: pw_env
184 TYPE(pw_poisson_type), POINTER :: poisson_env
185 TYPE(qs_ks_env_type), POINTER :: ks_env
186
187 CALL timeset(routinen, handle)
188
189 NULLIFY (blacs_env, cell, matrix_s, pw_env)
190 CALL get_qs_env(qs_env, blacs_env=blacs_env, cell=cell, matrix_s=matrix_s, pw_env=pw_env)
191
192 nspins = SIZE(gs_mos)
193 CALL dbcsr_get_info(matrix_s(1)%matrix, nfullrows_total=nao)
194 DO ispin = 1, nspins
195 nmo_occ(ispin) = SIZE(gs_mos(ispin)%evals_occ)
196 nmo_virt(ispin) = SIZE(gs_mos(ispin)%evals_virt)
197 END DO
198
199 ! +++ allocate dipole operator matrices (must be deallocated elsewhere)
200 ALLOCATE (dipole_op_mos_occ(nderivs, nspins))
201 DO ispin = 1, nspins
202 CALL cp_fm_get_info(gs_mos(ispin)%mos_occ, matrix_struct=fm_struct)
203
204 DO ideriv = 1, nderivs
205 CALL cp_fm_create(dipole_op_mos_occ(ideriv, ispin), fm_struct)
206 END DO
207 END DO
208
209 ! +++ allocate work matrices
210 ALLOCATE (s_mos_virt(nspins))
211 DO ispin = 1, nspins
212 CALL cp_fm_get_info(gs_mos(ispin)%mos_virt, matrix_struct=fm_struct)
213 CALL cp_fm_create(s_mos_virt(ispin), fm_struct)
214 CALL cp_dbcsr_sm_fm_multiply(matrix_s(1)%matrix, &
215 gs_mos(ispin)%mos_virt, &
216 s_mos_virt(ispin), &
217 ncol=nmo_virt(ispin), alpha=1.0_dp, beta=0.0_dp)
218 END DO
219
220 ! check that the chosen dipole operator is consistent with the periodic boundary conditions used
221 CALL pw_env_get(pw_env, poisson_env=poisson_env)
222 ndim_periodic = count(poisson_env%parameters%periodic == 1)
223
224 ! select default for dipole form
225 IF (tddfpt_control%dipole_form == 0) THEN
226 CALL get_qs_env(qs_env, dft_control=dft_control)
227 IF (dft_control%qs_control%xtb) THEN
228 IF (ndim_periodic == 0) THEN
229 tddfpt_control%dipole_form = tddfpt_dipole_length
230 ELSE
231 tddfpt_control%dipole_form = tddfpt_dipole_berry
232 END IF
233 ELSE
234 tddfpt_control%dipole_form = tddfpt_dipole_velocity
235 END IF
236 END IF
237
238 SELECT CASE (tddfpt_control%dipole_form)
240 IF (ndim_periodic /= 3) THEN
241 CALL cp_warn(__location__, &
242 "Fully periodic Poisson solver (PERIODIC xyz) is needed "// &
243 "for oscillator strengths based on the Berry phase formula")
244 END IF
245
246 NULLIFY (berry_cossin_xyz)
247 ! index: 1 = Re[exp(-i * G_t * t)],
248 ! 2 = Im[exp(-i * G_t * t)];
249 ! t = x,y,z
250 CALL dbcsr_allocate_matrix_set(berry_cossin_xyz, 2)
251
252 DO i_cos_sin = 1, 2
253 CALL dbcsr_init_p(berry_cossin_xyz(i_cos_sin)%matrix)
254 CALL dbcsr_copy(berry_cossin_xyz(i_cos_sin)%matrix, matrix_s(1)%matrix)
255 END DO
256
257 ! +++ allocate berry-phase-related work matrices
258 ALLOCATE (gamma_00(nspins), gamma_inv_00(nspins), gamma_real_imag(2, nspins), opvec(2, nspins))
259 ALLOCATE (dberry_mos_occ(nderivs, nspins))
260 DO ispin = 1, nspins
261 NULLIFY (fm_struct)
262 CALL cp_fm_struct_create(fm_struct, nrow_global=nmo_occ(ispin), &
263 ncol_global=nmo_occ(ispin), context=blacs_env)
264
265 CALL cp_cfm_create(gamma_00(ispin), fm_struct)
266 CALL cp_cfm_create(gamma_inv_00(ispin), fm_struct)
267
268 DO i_cos_sin = 1, 2
269 CALL cp_fm_create(gamma_real_imag(i_cos_sin, ispin), fm_struct)
270 END DO
271 CALL cp_fm_struct_release(fm_struct)
272
273 ! G_real C_0, G_imag C_0
274 CALL cp_fm_get_info(gs_mos(ispin)%mos_occ, matrix_struct=fm_struct)
275 DO i_cos_sin = 1, 2
276 CALL cp_fm_create(opvec(i_cos_sin, ispin), fm_struct)
277 END DO
278
279 ! dBerry * C_0
280 DO ideriv = 1, nderivs
281 CALL cp_fm_create(dberry_mos_occ(ideriv, ispin), fm_struct)
282 CALL cp_fm_set_all(dberry_mos_occ(ideriv, ispin), 0.0_dp)
283 END DO
284 END DO
285
286 DO ideriv = 1, nderivs
287 kvec(:) = twopi*cell%h_inv(ideriv, :)
288 DO i_cos_sin = 1, 2
289 CALL dbcsr_set(berry_cossin_xyz(i_cos_sin)%matrix, 0.0_dp)
290 END DO
291 CALL build_berry_moment_matrix(qs_env, berry_cossin_xyz(1)%matrix, &
292 berry_cossin_xyz(2)%matrix, kvec)
293
294 DO ispin = 1, nspins
295 ! i_cos_sin = 1: cos (real) component; opvec(1) = gamma_real C_0
296 ! i_cos_sin = 2: sin (imaginary) component; opvec(2) = gamma_imag C_0
297 DO i_cos_sin = 1, 2
298 CALL cp_dbcsr_sm_fm_multiply(berry_cossin_xyz(i_cos_sin)%matrix, &
299 gs_mos(ispin)%mos_occ, &
300 opvec(i_cos_sin, ispin), &
301 ncol=nmo_occ(ispin), alpha=1.0_dp, beta=0.0_dp)
302 END DO
303
304 CALL parallel_gemm('T', 'N', nmo_occ(ispin), nmo_occ(ispin), nao, &
305 1.0_dp, gs_mos(ispin)%mos_occ, opvec(1, ispin), &
306 0.0_dp, gamma_real_imag(1, ispin))
307
308 CALL parallel_gemm('T', 'N', nmo_occ(ispin), nmo_occ(ispin), nao, &
309 -1.0_dp, gs_mos(ispin)%mos_occ, opvec(2, ispin), &
310 0.0_dp, gamma_real_imag(2, ispin))
311
312 CALL cp_fm_to_cfm(msourcer=gamma_real_imag(1, ispin), &
313 msourcei=gamma_real_imag(2, ispin), &
314 mtarget=gamma_00(ispin))
315
316 ! gamma_inv_00 = Q = [C_0^T (gamma_real - i gamma_imag) C_0] ^ {-1}
317 CALL cp_cfm_set_all(gamma_inv_00(ispin), z_zero, z_one)
318 CALL cp_cfm_solve(gamma_00(ispin), gamma_inv_00(ispin))
319
320 CALL cp_cfm_to_fm(msource=gamma_inv_00(ispin), &
321 mtargetr=gamma_real_imag(1, ispin), &
322 mtargeti=gamma_real_imag(2, ispin))
323
324 ! dBerry_mos_occ is identical to dBerry_psi0 from qs_linres_op % polar_operators()
325 CALL parallel_gemm("N", "N", nao, nmo_occ(ispin), nmo_occ(ispin), &
326 1.0_dp, opvec(1, ispin), gamma_real_imag(2, ispin), &
327 0.0_dp, dipole_op_mos_occ(1, ispin))
328 CALL parallel_gemm("N", "N", nao, nmo_occ(ispin), nmo_occ(ispin), &
329 -1.0_dp, opvec(2, ispin), gamma_real_imag(1, ispin), &
330 1.0_dp, dipole_op_mos_occ(1, ispin))
331
332 DO jderiv = 1, nderivs
333 CALL cp_fm_scale_and_add(1.0_dp, dberry_mos_occ(jderiv, ispin), &
334 cell%hmat(jderiv, ideriv), dipole_op_mos_occ(1, ispin))
335 END DO
336 END DO
337 END DO
338
339 ! --- release berry-phase-related work matrices
340 CALL cp_fm_release(opvec)
341 CALL cp_fm_release(gamma_real_imag)
342 DO ispin = nspins, 1, -1
343 CALL cp_cfm_release(gamma_inv_00(ispin))
344 CALL cp_cfm_release(gamma_00(ispin))
345 END DO
346 DEALLOCATE (gamma_00, gamma_inv_00)
347 CALL dbcsr_deallocate_matrix_set(berry_cossin_xyz)
348
349 NULLIFY (fm_struct)
350 CALL cp_fm_struct_create(fm_struct, nrow_global=nao, ncol_global=nao, context=blacs_env)
351 CALL cp_fm_create(wfm_ao_ao, fm_struct)
352 CALL cp_fm_struct_release(fm_struct)
353
354 ! trans_dipole = 2|e|/|G_mu| * Tr Imag(evects^T * (gamma_real - i gamma_imag) * C_0 * gamma_inv_00) +
355 ! 2|e|/|G_mu| * Tr Imag(C_0^T * (gamma_real - i gamma_imag) * evects * gamma_inv_00) ,
356 !
357 ! Taking into account the symmetry of the matrices 'gamma_real' and 'gamma_imag' and the fact
358 ! that the response wave-function is a real-valued function, the above expression can be simplified as
359 ! trans_dipole = 4|e|/|G_mu| * Tr Imag(evects^T * (gamma_real - i gamma_imag) * C_0 * gamma_inv_00)
360 !
361 ! 1/|G_mu| = |lattice_vector_mu| / (2*pi) .
362 DO ispin = 1, nspins
363 ! wfm_ao_ao = S * mos_virt * mos_virt^T
364 CALL parallel_gemm('N', 'T', nao, nao, nmo_virt(ispin), &
365 1.0_dp/twopi, s_mos_virt(ispin), gs_mos(ispin)%mos_virt, &
366 0.0_dp, wfm_ao_ao)
367
368 DO ideriv = 1, nderivs
369 CALL parallel_gemm('N', 'N', nao, nmo_occ(ispin), nao, &
370 1.0_dp, wfm_ao_ao, dberry_mos_occ(ideriv, ispin), &
371 0.0_dp, dipole_op_mos_occ(ideriv, ispin))
372 END DO
373 END DO
374
375 CALL cp_fm_release(wfm_ao_ao)
376 CALL cp_fm_release(dberry_mos_occ)
377
379 IF (ndim_periodic /= 0) THEN
380 CALL cp_warn(__location__, &
381 "Non-periodic Poisson solver (PERIODIC none) is needed "// &
382 "for oscillator strengths based on the length operator")
383 END IF
384
385 ! compute components of the dipole operator in the length form
386 NULLIFY (rrc_xyz)
387 CALL dbcsr_allocate_matrix_set(rrc_xyz, nderivs)
388
389 DO ideriv = 1, nderivs
390 CALL dbcsr_init_p(rrc_xyz(ideriv)%matrix)
391 CALL dbcsr_copy(rrc_xyz(ideriv)%matrix, matrix_s(1)%matrix)
392 END DO
393
394 CALL get_reference_point(reference_point, qs_env=qs_env, &
395 reference=tddfpt_control%dipole_reference, &
396 ref_point=tddfpt_control%dipole_ref_point)
397
398 CALL rrc_xyz_ao(op=rrc_xyz, qs_env=qs_env, rc=reference_point, order=1, &
399 minimum_image=.false., soft=.false.)
400
401 NULLIFY (fm_struct)
402 CALL cp_fm_struct_create(fm_struct, nrow_global=nao, ncol_global=nao, context=blacs_env)
403 CALL cp_fm_create(wfm_ao_ao, fm_struct)
404 CALL cp_fm_struct_release(fm_struct)
405
406 DO ispin = 1, nspins
407 CALL cp_fm_get_info(gs_mos(ispin)%mos_occ, matrix_struct=fm_struct)
408 CALL cp_fm_create(rrc_mos_occ, fm_struct)
409
410 ! wfm_ao_ao = S * mos_virt * mos_virt^T
411 CALL parallel_gemm('N', 'T', nao, nao, nmo_virt(ispin), &
412 1.0_dp, s_mos_virt(ispin), gs_mos(ispin)%mos_virt, &
413 0.0_dp, wfm_ao_ao)
414
415 DO ideriv = 1, nderivs
416 CALL cp_dbcsr_sm_fm_multiply(rrc_xyz(ideriv)%matrix, &
417 gs_mos(ispin)%mos_occ, &
418 rrc_mos_occ, &
419 ncol=nmo_occ(ispin), alpha=1.0_dp, beta=0.0_dp)
420
421 CALL parallel_gemm('N', 'N', nao, nmo_occ(ispin), nao, &
422 1.0_dp, wfm_ao_ao, rrc_mos_occ, &
423 0.0_dp, dipole_op_mos_occ(ideriv, ispin))
424 END DO
425
426 CALL cp_fm_release(rrc_mos_occ)
427 END DO
428
429 CALL cp_fm_release(wfm_ao_ao)
430 CALL dbcsr_deallocate_matrix_set(rrc_xyz)
431
433 ! generate overlap derivatives
434 CALL get_qs_env(qs_env, ks_env=ks_env, sab_orb=sab_orb)
435 NULLIFY (scrm)
436 CALL build_overlap_matrix(ks_env, matrix_s=scrm, nderivative=1, &
437 basis_type_a="ORB", basis_type_b="ORB", &
438 sab_nl=sab_orb)
439
440 DO ispin = 1, nspins
441 NULLIFY (fm_struct)
442 CALL cp_fm_struct_create(fm_struct, nrow_global=nmo_virt(ispin), &
443 ncol_global=nmo_occ(ispin), context=blacs_env)
444 CALL cp_fm_create(ediff_inv, fm_struct)
445 CALL cp_fm_create(wfm_mo_virt_mo_occ, fm_struct)
446 CALL cp_fm_struct_release(fm_struct)
447
448 CALL cp_fm_get_info(ediff_inv, nrow_local=nrows_local, ncol_local=ncols_local, &
449 row_indices=row_indices, col_indices=col_indices, local_data=local_data_ediff)
450 CALL cp_fm_get_info(wfm_mo_virt_mo_occ, local_data=local_data_wfm)
451
452!$OMP PARALLEL DO DEFAULT(NONE), &
453!$OMP PRIVATE(eval_occ, icol, irow), &
454!$OMP SHARED(col_indices, gs_mos, ispin, local_data_ediff, ncols_local, nrows_local, row_indices)
455 DO icol = 1, ncols_local
456 ! E_occ_i ; imo_occ = col_indices(icol)
457 eval_occ = gs_mos(ispin)%evals_occ(col_indices(icol))
458
459 DO irow = 1, nrows_local
460 ! ediff_inv_weights(a, i) = 1.0 / (E_virt_a - E_occ_i)
461 ! imo_virt = row_indices(irow)
462 local_data_ediff(irow, icol) = 1.0_dp/(gs_mos(ispin)%evals_virt(row_indices(irow)) - eval_occ)
463 END DO
464 END DO
465!$OMP END PARALLEL DO
466
467 DO ideriv = 1, nderivs
468 CALL cp_dbcsr_sm_fm_multiply(scrm(ideriv + 1)%matrix, &
469 gs_mos(ispin)%mos_occ, &
470 dipole_op_mos_occ(ideriv, ispin), &
471 ncol=nmo_occ(ispin), alpha=1.0_dp, beta=0.0_dp)
472
473 CALL parallel_gemm('T', 'N', nmo_virt(ispin), nmo_occ(ispin), nao, &
474 1.0_dp, gs_mos(ispin)%mos_virt, dipole_op_mos_occ(ideriv, ispin), &
475 0.0_dp, wfm_mo_virt_mo_occ)
476
477 ! in-place element-wise (Schur) product;
478 ! avoid allocation of a temporary [nmo_virt x nmo_occ] matrix which is needed
479 ! for cp_fm_schur_product() subroutine call
480
481!$OMP PARALLEL DO DEFAULT(NONE), &
482!$OMP PRIVATE(icol, irow), &
483!$OMP SHARED(ispin, local_data_ediff, local_data_wfm, ncols_local, nrows_local)
484 DO icol = 1, ncols_local
485 DO irow = 1, nrows_local
486 local_data_wfm(irow, icol) = local_data_wfm(irow, icol)*local_data_ediff(irow, icol)
487 END DO
488 END DO
489!$OMP END PARALLEL DO
490
491 CALL parallel_gemm('N', 'N', nao, nmo_occ(ispin), nmo_virt(ispin), &
492 1.0_dp, s_mos_virt(ispin), wfm_mo_virt_mo_occ, &
493 0.0_dp, dipole_op_mos_occ(ideriv, ispin))
494 END DO
495
496 CALL cp_fm_release(wfm_mo_virt_mo_occ)
497 CALL cp_fm_release(ediff_inv)
498 END DO
500
501 CASE DEFAULT
502 cpabort("Unimplemented form of the dipole operator")
503 END SELECT
504
505 ! --- release work matrices
506 CALL cp_fm_release(s_mos_virt)
507
508 CALL timestop(handle)
509 END SUBROUTINE tddfpt_dipole_operator
510
511! **************************************************************************************************
512!> \brief Print final TDDFPT excitation energies and oscillator strengths.
513!> \param log_unit output unit
514!> \param evects TDDFPT trial vectors (SIZE(evects,1) -- number of spins;
515!> SIZE(evects,2) -- number of excited states to print)
516!> \param evals TDDFPT eigenvalues
517!> \param ostrength TDDFPT oscillator strength
518!> \param mult multiplicity
519!> \param dipole_op_mos_occ action of the dipole operator on the ground state wave function
520!> [x,y,z ; spin]
521!> \param dipole_form ...
522!> \par History
523!> * 05.2016 created [Sergey Chulkov]
524!> * 06.2016 transition dipole moments and oscillator strengths [Sergey Chulkov]
525!> * 07.2016 spin-unpolarised electron density [Sergey Chulkov]
526!> * 08.2018 compute 'dipole_op_mos_occ' in a separate subroutine [Sergey Chulkov]
527!> \note \parblock
528!> Adapted version of the subroutine find_contributions() which was originally created
529!> by Thomas Chassaing on 02.2005.
530!>
531!> Transition dipole moment along direction 'd' is computed as following:
532!> \f[ t_d(spin) = Tr[evects^T dipole\_op\_mos\_occ(d, spin)] .\f]
533!> \endparblock
534! **************************************************************************************************
535 SUBROUTINE tddfpt_print_summary(log_unit, evects, evals, ostrength, mult, &
536 dipole_op_mos_occ, dipole_form)
537 INTEGER, INTENT(in) :: log_unit
538 TYPE(cp_fm_type), DIMENSION(:, :), INTENT(in) :: evects
539 REAL(kind=dp), DIMENSION(:), INTENT(in) :: evals
540 REAL(kind=dp), DIMENSION(:), INTENT(inout) :: ostrength
541 INTEGER, INTENT(in) :: mult
542 TYPE(cp_fm_type), DIMENSION(:, :), INTENT(in) :: dipole_op_mos_occ
543 INTEGER, INTENT(in) :: dipole_form
544
545 CHARACTER(LEN=*), PARAMETER :: routinen = 'tddfpt_print_summary'
546
547 CHARACTER(len=1) :: lsd_str
548 CHARACTER(len=20) :: mult_str
549 INTEGER :: handle, ideriv, ispin, istate, nspins, &
550 nstates
551 REAL(kind=dp) :: osc_strength
552 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: trans_dipoles
553
554 CALL timeset(routinen, handle)
555
556 nspins = SIZE(evects, 1)
557 nstates = SIZE(evects, 2)
558
559 IF (nspins > 1) THEN
560 lsd_str = 'U'
561 ELSE
562 lsd_str = 'R'
563 END IF
564
565 ! *** summary header ***
566 IF (log_unit > 0) THEN
567 CALL integer_to_string(mult, mult_str)
568 WRITE (log_unit, '(/,1X,A1,A,1X,A)') lsd_str, "-TDDFPT states of multiplicity", trim(mult_str)
569 SELECT CASE (dipole_form)
571 WRITE (log_unit, '(1X,A,/)') "Transition dipoles calculated using Berry operator formulation"
573 WRITE (log_unit, '(1X,A,/)') "Transition dipoles calculated using length formulation"
575 WRITE (log_unit, '(1X,A,/)') "Transition dipoles calculated using velocity 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 DO ideriv = 1, nderivs
595 CALL cp_fm_trace(evects(ispin, :), dipole_op_mos_occ(ideriv, ispin), &
596 trans_dipoles(:, ideriv, ispin))
597 END DO
598 END DO
599
600 IF (nspins == 1) THEN
601 trans_dipoles(:, :, 1) = sqrt(2.0_dp)*trans_dipoles(:, :, 1)
602 ELSE
603 trans_dipoles(:, :, 1) = sqrt(trans_dipoles(:, :, 1)**2 + trans_dipoles(:, :, 2)**2)
604 END IF
605 END IF
606
607 ! *** summary information ***
608 DO istate = 1, nstates
609 osc_strength = 2.0_dp/3.0_dp*evals(istate)* &
610 accurate_dot_product(trans_dipoles(istate, :, 1), trans_dipoles(istate, :, 1))
611 ostrength(istate) = osc_strength
612 IF (log_unit > 0) THEN
613 WRITE (log_unit, '(1X,A,T9,I7,T19,F11.5,T31,3(1X,ES11.4E2),T69,ES12.5E2)') &
614 "TDDFPT|", istate, evals(istate)*evolt, trans_dipoles(istate, 1:nderivs, 1), osc_strength
615 END IF
616 END DO
617
618 ! punch a checksum for the regs
619 IF (log_unit > 0) THEN
620 WRITE (log_unit, '(/,T2,A,E14.6)') 'TDDFPT : CheckSum =', sqrt(sum(evals**2))
621 END IF
622
623 DEALLOCATE (trans_dipoles)
624
625 CALL timestop(handle)
626 END SUBROUTINE tddfpt_print_summary
627
628! **************************************************************************************************
629!> \brief Print excitation analysis.
630!> \param log_unit output unit
631!> \param evects TDDFPT trial vectors (SIZE(evects,1) -- number of spins;
632!> SIZE(evects,2) -- number of excited states to print)
633!> \param evals TDDFPT eigenvalues
634!> \param gs_mos molecular orbitals optimised for the ground state
635!> \param matrix_s overlap matrix
636!> \param spinflip ...
637!> \param min_amplitude the smallest excitation amplitude to print
638!> \par History
639!> * 05.2016 created as 'tddfpt_print_summary' [Sergey Chulkov]
640!> * 08.2018 splited of from 'tddfpt_print_summary' [Sergey Chulkov]
641! **************************************************************************************************
642 SUBROUTINE tddfpt_print_excitation_analysis(log_unit, evects, evals, gs_mos, matrix_s, spinflip, min_amplitude)
643 INTEGER, INTENT(in) :: log_unit
644 TYPE(cp_fm_type), DIMENSION(:, :), INTENT(in) :: evects
645 REAL(kind=dp), DIMENSION(:), INTENT(in) :: evals
646 TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
647 INTENT(in) :: gs_mos
648 TYPE(dbcsr_type), POINTER :: matrix_s
649 INTEGER :: spinflip
650 REAL(kind=dp), INTENT(in) :: min_amplitude
651
652 CHARACTER(LEN=*), PARAMETER :: routinen = 'tddfpt_print_excitation_analysis'
653
654 CHARACTER(len=5) :: spin_label, spin_label2
655 INTEGER :: handle, icol, iproc, irow, ispin, &
656 istate, nao, ncols_local, nrows_local, &
657 nspins, nstates, spin2, state_spin, &
658 state_spin2
659 INTEGER(kind=int_8) :: iexc, imo_occ, imo_virt, ind, nexcs, &
660 nexcs_local, nexcs_max_local, &
661 nmo_virt_occ, nmo_virt_occ_alpha
662 INTEGER(kind=int_8), ALLOCATABLE, DIMENSION(:) :: inds_local, inds_recv, nexcs_recv
663 INTEGER(kind=int_8), DIMENSION(1) :: nexcs_send
664 INTEGER(kind=int_8), DIMENSION(maxspins) :: nmo_occ8, nmo_virt8
665 INTEGER, ALLOCATABLE, DIMENSION(:) :: inds
666 INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
667 INTEGER, DIMENSION(maxspins) :: nmo_occ, nmo_virt
668 LOGICAL :: do_exc_analysis
669 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: weights_local, weights_neg_abs_recv, &
670 weights_recv
671 REAL(kind=dp), CONTIGUOUS, DIMENSION(:, :), &
672 POINTER :: local_data
673 TYPE(cp_blacs_env_type), POINTER :: blacs_env
674 TYPE(cp_fm_struct_type), POINTER :: fm_struct
675 TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: s_mos_virt, weights_fm
676 TYPE(mp_para_env_type), POINTER :: para_env
677 TYPE(mp_request_type) :: send_handler, send_handler2
678 TYPE(mp_request_type), ALLOCATABLE, DIMENSION(:) :: recv_handlers, recv_handlers2
679
680 CALL timeset(routinen, handle)
681
682 nspins = SIZE(gs_mos, 1)
683 nstates = SIZE(evects, 2)
684 do_exc_analysis = min_amplitude < 1.0_dp
685
686 CALL cp_fm_get_info(gs_mos(1)%mos_occ, context=blacs_env, para_env=para_env)
687 CALL dbcsr_get_info(matrix_s, nfullrows_total=nao)
688
689 DO ispin = 1, nspins
690 nmo_occ(ispin) = SIZE(gs_mos(ispin)%evals_occ)
691 nmo_virt(ispin) = SIZE(gs_mos(ispin)%evals_virt)
692 nmo_occ8(ispin) = SIZE(gs_mos(ispin)%evals_occ, kind=int_8)
693 nmo_virt8(ispin) = SIZE(gs_mos(ispin)%evals_virt, kind=int_8)
694 END DO
695
696 ! *** excitation analysis ***
697 IF (do_exc_analysis) THEN
698 cpassert(log_unit <= 0 .OR. para_env%is_source())
699 nmo_virt_occ_alpha = int(nmo_virt(1), int_8)*int(nmo_occ(1), int_8)
700
701 IF (log_unit > 0) THEN
702 WRITE (log_unit, "(1X,A)") "", &
703 "-------------------------------------------------------------------------------", &
704 "- Excitation analysis -", &
705 "-------------------------------------------------------------------------------"
706 WRITE (log_unit, '(8X,A,T27,A,T49,A,T69,A)') "State", "Occupied", "Virtual", "Excitation"
707 WRITE (log_unit, '(8X,A,T28,A,T49,A,T69,A)') "number", "orbital", "orbital", "amplitude"
708 WRITE (log_unit, '(1X,79("-"))')
709
710 IF (nspins == 1) THEN
711 state_spin = 1
712 state_spin2 = 2
713 spin_label = ' '
714 spin_label2 = ' '
715 ELSE IF (spinflip .NE. no_sf_tddfpt) THEN
716 state_spin = 1
717 state_spin2 = 2
718 spin_label = '(alp)'
719 spin_label2 = '(bet)'
720 END IF
721 END IF
722
723 ALLOCATE (s_mos_virt(SIZE(evects, 1)), weights_fm(SIZE(evects, 1)))
724 DO ispin = 1, SIZE(evects, 1)
725 IF (spinflip == no_sf_tddfpt) THEN
726 spin2 = ispin
727 ELSE
728 spin2 = 2
729 END IF
730 CALL cp_fm_get_info(gs_mos(spin2)%mos_virt, matrix_struct=fm_struct)
731 CALL cp_fm_create(s_mos_virt(ispin), fm_struct)
732 CALL cp_dbcsr_sm_fm_multiply(matrix_s, &
733 gs_mos(spin2)%mos_virt, &
734 s_mos_virt(ispin), &
735 ncol=nmo_virt(spin2), alpha=1.0_dp, beta=0.0_dp)
736
737 NULLIFY (fm_struct)
738 CALL cp_fm_struct_create(fm_struct, nrow_global=nmo_virt(spin2), ncol_global=nmo_occ(ispin), &
739 context=blacs_env)
740 CALL cp_fm_create(weights_fm(ispin), fm_struct)
741 CALL cp_fm_struct_release(fm_struct)
742 END DO
743
744 nexcs_max_local = 0
745 DO ispin = 1, SIZE(evects, 1)
746 CALL cp_fm_get_info(weights_fm(ispin), nrow_local=nrows_local, ncol_local=ncols_local)
747 nexcs_max_local = nexcs_max_local + int(nrows_local, int_8)*int(ncols_local, int_8)
748 END DO
749
750 ALLOCATE (weights_local(nexcs_max_local), inds_local(nexcs_max_local))
751
752 DO istate = 1, nstates
753 nexcs_local = 0
754 nmo_virt_occ = 0
755
756 ! analyse matrix elements locally and transfer only significant
757 ! excitations to the master node for subsequent ordering
758 DO ispin = 1, SIZE(evects, 1)
759 IF (spinflip == no_sf_tddfpt) THEN
760 spin2 = ispin
761 ELSE
762 spin2 = 2
763 END IF
764 ! compute excitation amplitudes
765 CALL parallel_gemm('T', 'N', nmo_virt(spin2), nmo_occ(ispin), nao, 1.0_dp, s_mos_virt(ispin), &
766 evects(ispin, istate), 0.0_dp, weights_fm(ispin))
767
768 CALL cp_fm_get_info(weights_fm(ispin), nrow_local=nrows_local, ncol_local=ncols_local, &
769 row_indices=row_indices, col_indices=col_indices, local_data=local_data)
770
771 ! locate single excitations with significant amplitudes (>= min_amplitude)
772 DO icol = 1, ncols_local
773 DO irow = 1, nrows_local
774 IF (abs(local_data(irow, icol)) >= min_amplitude) THEN
775 ! number of non-negligible excitations
776 nexcs_local = nexcs_local + 1
777 ! excitation amplitude
778 weights_local(nexcs_local) = local_data(irow, icol)
779 ! index of single excitation (ivirt, iocc, ispin) in compressed form
780 inds_local(nexcs_local) = nmo_virt_occ + int(row_indices(irow), int_8) + &
781 int(col_indices(icol) - 1, int_8)*nmo_virt8(spin2)
782 END IF
783 END DO
784 END DO
785
786 nmo_virt_occ = nmo_virt_occ + nmo_virt8(spin2)*nmo_occ8(ispin)
787 END DO
788
789 IF (para_env%is_source()) THEN
790 ! master node
791 ALLOCATE (nexcs_recv(para_env%num_pe), recv_handlers(para_env%num_pe), recv_handlers2(para_env%num_pe))
792
793 ! collect number of non-negligible excitations from other nodes
794 DO iproc = 1, para_env%num_pe
795 IF (iproc - 1 /= para_env%mepos) THEN
796 CALL para_env%irecv(nexcs_recv(iproc:iproc), iproc - 1, recv_handlers(iproc), 0)
797 ELSE
798 nexcs_recv(iproc) = nexcs_local
799 END IF
800 END DO
801
802 DO iproc = 1, para_env%num_pe
803 IF (iproc - 1 /= para_env%mepos) &
804 CALL recv_handlers(iproc)%wait()
805 END DO
806
807 ! compute total number of non-negligible excitations
808 nexcs = 0
809 DO iproc = 1, para_env%num_pe
810 nexcs = nexcs + nexcs_recv(iproc)
811 END DO
812
813 ! receive indices and amplitudes of selected excitations
814 ALLOCATE (weights_recv(nexcs), weights_neg_abs_recv(nexcs))
815 ALLOCATE (inds_recv(nexcs), inds(nexcs))
816
817 nmo_virt_occ = 0
818 DO iproc = 1, para_env%num_pe
819 IF (nexcs_recv(iproc) > 0) THEN
820 IF (iproc - 1 /= para_env%mepos) THEN
821 ! excitation amplitudes
822 CALL para_env%irecv(weights_recv(nmo_virt_occ + 1:nmo_virt_occ + nexcs_recv(iproc)), &
823 iproc - 1, recv_handlers(iproc), 1)
824 ! compressed indices
825 CALL para_env%irecv(inds_recv(nmo_virt_occ + 1:nmo_virt_occ + nexcs_recv(iproc)), &
826 iproc - 1, recv_handlers2(iproc), 2)
827 ELSE
828 ! data on master node
829 weights_recv(nmo_virt_occ + 1:nmo_virt_occ + nexcs_recv(iproc)) = weights_local(1:nexcs_recv(iproc))
830 inds_recv(nmo_virt_occ + 1:nmo_virt_occ + nexcs_recv(iproc)) = inds_local(1:nexcs_recv(iproc))
831 END IF
832
833 nmo_virt_occ = nmo_virt_occ + nexcs_recv(iproc)
834 END IF
835 END DO
836
837 DO iproc = 1, para_env%num_pe
838 IF (iproc - 1 /= para_env%mepos .AND. nexcs_recv(iproc) > 0) THEN
839 CALL recv_handlers(iproc)%wait()
840 CALL recv_handlers2(iproc)%wait()
841 END IF
842 END DO
843
844 DEALLOCATE (nexcs_recv, recv_handlers, recv_handlers2)
845 ELSE
846 ! working node: send the number of selected excited states to the master node
847 nexcs_send(1) = nexcs_local
848 CALL para_env%isend(nexcs_send, para_env%source, send_handler, 0)
849 CALL send_handler%wait()
850
851 IF (nexcs_local > 0) THEN
852 ! send excitation amplitudes
853 CALL para_env%isend(weights_local(1:nexcs_local), para_env%source, send_handler, 1)
854 ! send compressed indices
855 CALL para_env%isend(inds_local(1:nexcs_local), para_env%source, send_handler2, 2)
856
857 CALL send_handler%wait()
858 CALL send_handler2%wait()
859 END IF
860 END IF
861
862 ! sort non-negligible excitations on the master node according to their amplitudes,
863 ! uncompress indices and print summary information
864 IF (para_env%is_source() .AND. log_unit > 0) THEN
865 weights_neg_abs_recv(:) = -abs(weights_recv)
866 CALL sort(weights_neg_abs_recv, int(nexcs), inds)
867
868 WRITE (log_unit, '(T7,I8,F10.5,A)') istate, evals(istate)*evolt, " eV"
869
870 ! This reinitialization is needed to prevent the intel fortran compiler from introduce
871 ! a bug when using optimization level 3 flag
872 state_spin = 1
873 state_spin2 = 1
874 IF (spinflip .NE. no_sf_tddfpt) THEN
875 state_spin = 1
876 state_spin2 = 2
877 END IF
878 DO iexc = 1, nexcs
879 ind = inds_recv(inds(iexc)) - 1
880 IF ((nspins > 1) .AND. (spinflip == no_sf_tddfpt)) THEN
881 IF (ind < nmo_virt_occ_alpha) THEN
882 spin_label = '(alp)'
883 spin_label2 = '(alp)'
884 ELSE
885 state_spin = 2
886 state_spin2 = 2
887 ind = ind - nmo_virt_occ_alpha
888 spin_label = '(bet)'
889 spin_label2 = '(bet)'
890 END IF
891 END IF
892 imo_occ = ind/nmo_virt8(state_spin2) + 1
893 imo_virt = mod(ind, nmo_virt8(state_spin2)) + 1
894
895 WRITE (log_unit, '(T27,I8,1X,A5,T48,I8,1X,A5,T70,F9.6)') imo_occ, spin_label, &
896 nmo_occ8(state_spin2) + imo_virt, spin_label2, weights_recv(inds(iexc))
897 END DO
898 END IF
899
900 ! deallocate temporary arrays
901 IF (para_env%is_source()) &
902 DEALLOCATE (weights_recv, weights_neg_abs_recv, inds_recv, inds)
903 END DO
904
905 DEALLOCATE (weights_local, inds_local)
906 IF (log_unit > 0) THEN
907 WRITE (log_unit, "(1X,A)") &
908 "-------------------------------------------------------------------------------"
909 END IF
910 END IF
911
912 CALL cp_fm_release(weights_fm)
913 CALL cp_fm_release(s_mos_virt)
914
915 CALL timestop(handle)
916
918
919! **************************************************************************************************
920!> \brief Print natural transition orbital analysis.
921!> \param qs_env Information on Kinds and Particles
922!> \param evects TDDFPT trial vectors (SIZE(evects,1) -- number of spins;
923!> SIZE(evects,2) -- number of excited states to print)
924!> \param evals TDDFPT eigenvalues
925!> \param ostrength ...
926!> \param gs_mos molecular orbitals optimised for the ground state
927!> \param matrix_s overlap matrix
928!> \param print_section ...
929!> \par History
930!> * 06.2019 created [JGH]
931! **************************************************************************************************
932 SUBROUTINE tddfpt_print_nto_analysis(qs_env, evects, evals, ostrength, gs_mos, matrix_s, print_section)
933 TYPE(qs_environment_type), POINTER :: qs_env
934 TYPE(cp_fm_type), DIMENSION(:, :), INTENT(in) :: evects
935 REAL(kind=dp), DIMENSION(:), INTENT(in) :: evals, ostrength
936 TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
937 INTENT(in) :: gs_mos
938 TYPE(dbcsr_type), POINTER :: matrix_s
939 TYPE(section_vals_type), POINTER :: print_section
940
941 CHARACTER(LEN=*), PARAMETER :: routinen = 'tddfpt_print_nto_analysis'
942 INTEGER, PARAMETER :: ntomax = 10
943
944 CHARACTER(LEN=20), DIMENSION(2) :: nto_name
945 INTEGER :: handle, i, ia, icg, iounit, ispin, &
946 istate, j, nao, nlist, nmax, nmo, &
947 nnto, nspins, nstates
948 INTEGER, DIMENSION(2) :: iv
949 INTEGER, DIMENSION(2, ntomax) :: ia_index
950 INTEGER, DIMENSION(:), POINTER :: slist, stride
951 LOGICAL :: append_cube, cube_file, explicit
952 REAL(kind=dp) :: os_threshold, sume, threshold
953 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: eigvals
954 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: eigenvalues
955 REAL(kind=dp), DIMENSION(ntomax) :: ia_eval
956 TYPE(cp_fm_struct_type), POINTER :: fm_mo_struct, fm_struct
957 TYPE(cp_fm_type) :: sev, smat, tmat, wmat, work, wvec
958 TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: teig
959 TYPE(cp_logger_type), POINTER :: logger
960 TYPE(mo_set_type), ALLOCATABLE, DIMENSION(:) :: nto_set
961 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
962 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
963 TYPE(section_vals_type), POINTER :: molden_section, nto_section
964
965 CALL timeset(routinen, handle)
966
967 logger => cp_get_default_logger()
968 iounit = cp_logger_get_default_io_unit(logger)
969
970 IF (btest(cp_print_key_should_output(logger%iter_info, print_section, &
971 "NTO_ANALYSIS"), cp_p_file)) THEN
972
973 CALL cite_reference(martin2003)
974
975 CALL section_vals_val_get(print_section, "NTO_ANALYSIS%THRESHOLD", r_val=threshold)
976 CALL section_vals_val_get(print_section, "NTO_ANALYSIS%INTENSITY_THRESHOLD", r_val=os_threshold)
977 CALL section_vals_val_get(print_section, "NTO_ANALYSIS%STATE_LIST", explicit=explicit)
978
979 IF (explicit) THEN
980 CALL section_vals_val_get(print_section, "NTO_ANALYSIS%STATE_LIST", i_vals=slist)
981 nlist = SIZE(slist)
982 ELSE
983 nlist = 0
984 END IF
985
986 IF (iounit > 0) THEN
987 WRITE (iounit, "(1X,A)") "", &
988 "-------------------------------------------------------------------------------", &
989 "- Natural Orbital analysis -", &
990 "-------------------------------------------------------------------------------"
991 END IF
992
993 nspins = SIZE(evects, 1)
994 nstates = SIZE(evects, 2)
995 CALL dbcsr_get_info(matrix_s, nfullrows_total=nao)
996
997 DO istate = 1, nstates
998 IF (os_threshold > ostrength(istate)) THEN
999 IF (iounit > 0) THEN
1000 WRITE (iounit, "(1X,A,I6)") " Skipping state ", istate
1001 END IF
1002 cycle
1003 END IF
1004 IF (nlist > 0) THEN
1005 IF (.NOT. any(slist == istate)) THEN
1006 IF (iounit > 0) THEN
1007 WRITE (iounit, "(1X,A,I6)") " Skipping state ", istate
1008 END IF
1009 cycle
1010 END IF
1011 END IF
1012 IF (iounit > 0) THEN
1013 WRITE (iounit, "(1X,A,I6,T30,F10.5,A)") " STATE NR. ", istate, evals(istate)*evolt, " eV"
1014 END IF
1015 nmax = 0
1016 DO ispin = 1, nspins
1017 CALL cp_fm_get_info(evects(ispin, istate), matrix_struct=fm_struct, ncol_global=nmo)
1018 nmax = max(nmax, nmo)
1019 END DO
1020 ALLOCATE (eigenvalues(nmax, nspins))
1021 eigenvalues = 0.0_dp
1022 ! SET 1: Hole states
1023 ! SET 2: Particle states
1024 nto_name(1) = 'Hole_states'
1025 nto_name(2) = 'Particle_states'
1026 ALLOCATE (nto_set(2))
1027 DO i = 1, 2
1028 CALL allocate_mo_set(nto_set(i), nao, ntomax, 0, 0.0_dp, 1.0_dp, 0.0_dp)
1029 CALL cp_fm_get_info(evects(1, istate), matrix_struct=fm_struct)
1030 CALL cp_fm_struct_create(fmstruct=fm_mo_struct, template_fmstruct=fm_struct, &
1031 ncol_global=ntomax)
1032 CALL cp_fm_create(tmat, fm_mo_struct)
1033 CALL init_mo_set(nto_set(i), fm_ref=tmat, name=nto_name(i))
1034 CALL cp_fm_release(tmat)
1035 CALL cp_fm_struct_release(fm_mo_struct)
1036 END DO
1037 !
1038 ALLOCATE (teig(nspins))
1039 ! hole states
1040 ! Diagonalize X(T)*S*X
1041 DO ispin = 1, nspins
1042 associate(ev => evects(ispin, istate))
1043 CALL cp_fm_get_info(ev, matrix_struct=fm_struct, ncol_global=nmo)
1044 CALL cp_fm_create(sev, fm_struct)
1045 CALL cp_fm_struct_create(fmstruct=fm_mo_struct, template_fmstruct=fm_struct, &
1046 nrow_global=nmo, ncol_global=nmo)
1047 CALL cp_fm_create(tmat, fm_mo_struct)
1048 CALL cp_fm_create(teig(ispin), fm_mo_struct)
1049 CALL cp_dbcsr_sm_fm_multiply(matrix_s, ev, sev, ncol=nmo, alpha=1.0_dp, beta=0.0_dp)
1050 CALL parallel_gemm('T', 'N', nmo, nmo, nao, 1.0_dp, ev, sev, 0.0_dp, tmat)
1051 END associate
1052
1053 CALL choose_eigv_solver(tmat, teig(ispin), eigenvalues(1:nmo, ispin))
1054
1055 CALL cp_fm_struct_release(fm_mo_struct)
1056 CALL cp_fm_release(tmat)
1057 CALL cp_fm_release(sev)
1058 END DO
1059 ! find major determinants i->a
1060 ia_index = 0
1061 sume = 0.0_dp
1062 nnto = 0
1063 DO i = 1, ntomax
1064 iv = maxloc(eigenvalues)
1065 ia_eval(i) = eigenvalues(iv(1), iv(2))
1066 ia_index(1:2, i) = iv(1:2)
1067 sume = sume + ia_eval(i)
1068 eigenvalues(iv(1), iv(2)) = 0.0_dp
1069 nnto = nnto + 1
1070 IF (sume > threshold) EXIT
1071 END DO
1072 ! store hole states
1073 CALL set_mo_set(nto_set(1), nmo=nnto)
1074 DO i = 1, nnto
1075 ia = ia_index(1, i)
1076 ispin = ia_index(2, i)
1077 CALL cp_fm_get_info(gs_mos(ispin)%mos_occ, ncol_global=nmo)
1078 CALL cp_fm_get_info(teig(ispin), matrix_struct=fm_struct)
1079 CALL cp_fm_struct_create(fmstruct=fm_mo_struct, template_fmstruct=fm_struct, &
1080 nrow_global=nmo, ncol_global=1)
1081 CALL cp_fm_create(tmat, fm_mo_struct)
1082 CALL cp_fm_struct_release(fm_mo_struct)
1083 CALL cp_fm_get_info(gs_mos(1)%mos_occ, matrix_struct=fm_struct)
1084 CALL cp_fm_struct_create(fmstruct=fm_mo_struct, template_fmstruct=fm_struct, &
1085 ncol_global=1)
1086 CALL cp_fm_create(wvec, fm_mo_struct)
1087 CALL cp_fm_struct_release(fm_mo_struct)
1088 CALL cp_fm_to_fm(teig(ispin), tmat, 1, ia, 1)
1089 CALL parallel_gemm('N', 'N', nao, 1, nmo, 1.0_dp, gs_mos(ispin)%mos_occ, &
1090 tmat, 0.0_dp, wvec)
1091 CALL cp_fm_to_fm(wvec, nto_set(1)%mo_coeff, 1, 1, i)
1092 CALL cp_fm_release(wvec)
1093 CALL cp_fm_release(tmat)
1094 END DO
1095 ! particle states
1096 ! Solve generalized eigenvalue equation: (S*X)*(S*X)(T)*v = lambda*S*v
1097 CALL set_mo_set(nto_set(2), nmo=nnto)
1098 DO ispin = 1, nspins
1099 associate(ev => evects(ispin, istate))
1100 CALL cp_fm_get_info(ev, matrix_struct=fm_struct, nrow_global=nao, ncol_global=nmo)
1101 ALLOCATE (eigvals(nao))
1102 eigvals = 0.0_dp
1103 CALL cp_fm_create(sev, fm_struct)
1104 CALL cp_dbcsr_sm_fm_multiply(matrix_s, ev, sev, ncol=nmo, alpha=1.0_dp, beta=0.0_dp)
1105 END associate
1106 CALL cp_fm_struct_create(fmstruct=fm_mo_struct, template_fmstruct=fm_struct, &
1107 nrow_global=nao, ncol_global=nao)
1108 CALL cp_fm_create(tmat, fm_mo_struct)
1109 CALL cp_fm_create(smat, fm_mo_struct)
1110 CALL cp_fm_create(wmat, fm_mo_struct)
1111 CALL cp_fm_create(work, fm_mo_struct)
1112 CALL cp_fm_struct_release(fm_mo_struct)
1113 CALL copy_dbcsr_to_fm(matrix_s, smat)
1114 CALL parallel_gemm('N', 'T', nao, nao, nmo, 1.0_dp, sev, sev, 0.0_dp, tmat)
1115 CALL cp_fm_geeig(tmat, smat, wmat, eigvals, work)
1116 DO i = 1, nnto
1117 IF (ispin == ia_index(2, i)) THEN
1118 icg = 0
1119 DO j = 1, nao
1120 IF (abs(eigvals(j) - ia_eval(i)) < 1.e-6_dp) THEN
1121 icg = j
1122 EXIT
1123 END IF
1124 END DO
1125 IF (icg == 0) THEN
1126 CALL cp_warn(__location__, &
1127 "Could not locate particle state associated with hole state.")
1128 ELSE
1129 CALL cp_fm_to_fm(wmat, nto_set(2)%mo_coeff, 1, icg, i)
1130 END IF
1131 END IF
1132 END DO
1133 DEALLOCATE (eigvals)
1134 CALL cp_fm_release(sev)
1135 CALL cp_fm_release(tmat)
1136 CALL cp_fm_release(smat)
1137 CALL cp_fm_release(wmat)
1138 CALL cp_fm_release(work)
1139 END DO
1140 ! print
1141 IF (iounit > 0) THEN
1142 sume = 0.0_dp
1143 DO i = 1, nnto
1144 sume = sume + ia_eval(i)
1145 WRITE (iounit, "(T6,A,i2,T30,A,i1,T42,A,F8.5,T63,A,F8.5)") &
1146 "Particle-Hole state:", i, " Spin:", ia_index(2, i), &
1147 "Eigenvalue:", ia_eval(i), " Sum Eigv:", sume
1148 END DO
1149 END IF
1150 ! Cube and Molden files
1151 nto_section => section_vals_get_subs_vals(print_section, "NTO_ANALYSIS")
1152 CALL section_vals_val_get(nto_section, "CUBE_FILES", l_val=cube_file)
1153 CALL section_vals_val_get(nto_section, "STRIDE", i_vals=stride)
1154 CALL section_vals_val_get(nto_section, "APPEND", l_val=append_cube)
1155 IF (cube_file) THEN
1156 CALL print_nto_cubes(qs_env, nto_set, istate, stride, append_cube, nto_section)
1157 END IF
1158 CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set, particle_set=particle_set)
1159 molden_section => section_vals_get_subs_vals(print_section, "MOS_MOLDEN")
1160 CALL write_mos_molden(nto_set, qs_kind_set, particle_set, molden_section)
1161 !
1162 DEALLOCATE (eigenvalues)
1163 CALL cp_fm_release(teig)
1164 !
1165 DO i = 1, 2
1166 CALL deallocate_mo_set(nto_set(i))
1167 END DO
1168 DEALLOCATE (nto_set)
1169 END DO
1170
1171 IF (iounit > 0) THEN
1172 WRITE (iounit, "(1X,A)") &
1173 "-------------------------------------------------------------------------------"
1174 END IF
1175
1176 END IF
1177
1178 CALL timestop(handle)
1179
1180 END SUBROUTINE tddfpt_print_nto_analysis
1181
1182! **************************************************************************************************
1183!> \brief Print exciton descriptors, cf. Mewes et al., JCTC 14, 710-725 (2018)
1184!> \param log_unit output unit
1185!> \param evects TDDFPT trial vectors (SIZE(evects,1) -- number of spins;
1186!> SIZE(evects,2) -- number of excited states to print)
1187!> \param gs_mos molecular orbitals optimised for the ground state
1188!> \param matrix_s overlap matrix
1189!> \param do_directional_exciton_descriptors flag for computing descriptors for each (cartesian) direction
1190!> \param qs_env Information on particles/geometry
1191!> \par History
1192!> * 12.2024 created as 'tddfpt_print_exciton_descriptors' [Maximilian Graml]
1193! **************************************************************************************************
1194 SUBROUTINE tddfpt_print_exciton_descriptors(log_unit, evects, gs_mos, matrix_s, &
1195 do_directional_exciton_descriptors, qs_env)
1196 INTEGER, INTENT(in) :: log_unit
1197 TYPE(cp_fm_type), DIMENSION(:, :), INTENT(in) :: evects
1198 TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
1199 INTENT(in) :: gs_mos
1200 TYPE(dbcsr_type), POINTER :: matrix_s
1201 LOGICAL, INTENT(IN) :: do_directional_exciton_descriptors
1202 TYPE(qs_environment_type), INTENT(IN), POINTER :: qs_env
1203
1204 CHARACTER(LEN=*), PARAMETER :: routinen = 'tddfpt_print_exciton_descriptors'
1205
1206 CHARACTER(LEN=4) :: prefix_output
1207 INTEGER :: handle, ispin, istate, n_moments_quad, &
1208 nao, nspins, nstates
1209 INTEGER, DIMENSION(maxspins) :: nmo_occ, nmo_virt
1210 LOGICAL :: print_checkvalue
1211 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: ref_point_multipole
1212 TYPE(cp_blacs_env_type), POINTER :: blacs_env
1213 TYPE(cp_fm_struct_type), POINTER :: fm_struct_mo_coeff, &
1214 fm_struct_s_mos_virt, fm_struct_x_ia_n
1215 TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: eigvec_x_ia_n, fm_multipole_ab, &
1216 fm_multipole_ai, fm_multipole_ij, &
1217 s_mos_virt
1218 TYPE(cp_fm_type), DIMENSION(:), POINTER :: mo_coeff
1219 TYPE(exciton_descr_type), ALLOCATABLE, &
1220 DIMENSION(:) :: exc_descr
1221
1222 CALL timeset(routinen, handle)
1223
1224 nspins = SIZE(evects, 1)
1225 nstates = SIZE(evects, 2)
1226
1227 cpassert(nspins == 1) ! Other spins are not yet implemented for exciton descriptors
1228
1229 CALL cp_fm_get_info(gs_mos(1)%mos_occ, context=blacs_env)
1230 CALL dbcsr_get_info(matrix_s, nfullrows_total=nao)
1231
1232 DO ispin = 1, nspins
1233 nmo_occ(ispin) = SIZE(gs_mos(ispin)%evals_occ)
1234 nmo_virt(ispin) = SIZE(gs_mos(ispin)%evals_virt)
1235 END DO
1236
1237 ! Prepare fm with all MO coefficents, i.e. nao x nao
1238 ALLOCATE (mo_coeff(nspins))
1239 CALL cp_fm_struct_create(fm_struct_mo_coeff, nrow_global=nao, ncol_global=nao, &
1240 context=blacs_env)
1241 DO ispin = 1, nspins
1242 CALL cp_fm_create(mo_coeff(ispin), fm_struct_mo_coeff)
1243 CALL cp_fm_to_fm_submat_general(gs_mos(ispin)%mos_occ, &
1244 mo_coeff(ispin), &
1245 nao, &
1246 nmo_occ(ispin), &
1247 1, &
1248 1, &
1249 1, &
1250 1, &
1251 blacs_env)
1252 CALL cp_fm_to_fm_submat_general(gs_mos(ispin)%mos_virt, &
1253 mo_coeff(ispin), &
1254 nao, &
1255 nmo_virt(ispin), &
1256 1, &
1257 1, &
1258 1, &
1259 nmo_occ(ispin) + 1, &
1260 blacs_env)
1261 END DO
1262 CALL cp_fm_struct_release(fm_struct_mo_coeff)
1263
1264 ! Compute multipole moments
1265 ! fm_multipole_XY have structure inherited by libint, i.e. x, y, z, xx, xy, xz, yy, yz, zz
1266 n_moments_quad = 9
1267 ALLOCATE (ref_point_multipole(3))
1268 ALLOCATE (fm_multipole_ij(n_moments_quad))
1269 ALLOCATE (fm_multipole_ab(n_moments_quad))
1270 ALLOCATE (fm_multipole_ai(n_moments_quad))
1271
1272 CALL get_multipoles_mo(fm_multipole_ai, fm_multipole_ij, fm_multipole_ab, &
1273 qs_env, mo_coeff, ref_point_multipole, 2, &
1274 nmo_occ(1), nmo_virt(1), blacs_env)
1275
1276 CALL cp_fm_release(mo_coeff)
1277
1278 ! Compute eigenvector X of the Casida equation from trial vectors
1279 ALLOCATE (s_mos_virt(nspins), eigvec_x_ia_n(nspins))
1280 DO ispin = 1, nspins
1281 CALL cp_fm_get_info(gs_mos(ispin)%mos_virt, matrix_struct=fm_struct_s_mos_virt)
1282 CALL cp_fm_create(s_mos_virt(ispin), fm_struct_s_mos_virt)
1283 NULLIFY (fm_struct_s_mos_virt)
1284 CALL cp_dbcsr_sm_fm_multiply(matrix_s, &
1285 gs_mos(ispin)%mos_virt, &
1286 s_mos_virt(ispin), &
1287 ncol=nmo_virt(ispin), alpha=1.0_dp, beta=0.0_dp)
1288
1289 CALL cp_fm_struct_create(fm_struct_x_ia_n, nrow_global=nmo_occ(ispin), ncol_global=nmo_virt(ispin), &
1290 context=blacs_env)
1291 CALL cp_fm_create(eigvec_x_ia_n(ispin), fm_struct_x_ia_n)
1292 CALL cp_fm_struct_release(fm_struct_x_ia_n)
1293 END DO
1294 ALLOCATE (exc_descr(nstates))
1295 DO istate = 1, nstates
1296 DO ispin = 1, nspins
1297 CALL cp_fm_set_all(eigvec_x_ia_n(ispin), 0.0_dp)
1298 ! compute eigenvectors X of the TDA equation
1299 ! Reshuffle multiplication from
1300 ! X_ai = S_µa ^T * C_µi
1301 ! to
1302 ! X_ia = C_µi ^T * S_µa
1303 ! for compatibility with the structure needed for get_exciton_descriptors of bse_properties.F
1304 CALL parallel_gemm('T', 'N', nmo_occ(ispin), nmo_virt(ispin), nao, 1.0_dp, &
1305 evects(ispin, istate), s_mos_virt(ispin), 0.0_dp, eigvec_x_ia_n(ispin))
1306
1307 CALL get_exciton_descriptors(exc_descr, eigvec_x_ia_n(ispin), &
1308 fm_multipole_ij, fm_multipole_ab, &
1309 fm_multipole_ai, &
1310 istate, nmo_occ(ispin), nmo_virt(ispin))
1311
1312 END DO
1313 END DO
1314 CALL cp_fm_release(eigvec_x_ia_n)
1315 CALL cp_fm_release(s_mos_virt)
1316 CALL cp_fm_release(fm_multipole_ai)
1317 CALL cp_fm_release(fm_multipole_ij)
1318 CALL cp_fm_release(fm_multipole_ab)
1319
1320 ! Actual printing
1321 print_checkvalue = .true.
1322 prefix_output = ' '
1323 CALL print_exciton_descriptors(exc_descr, ref_point_multipole, log_unit, &
1324 nstates, print_checkvalue, do_directional_exciton_descriptors, &
1325 prefix_output, qs_env)
1326
1327 DEALLOCATE (ref_point_multipole)
1328 DEALLOCATE (exc_descr)
1329
1330 CALL timestop(handle)
1331
1333
1334! **************************************************************************************************
1335!> \brief ...
1336!> \param vin ...
1337!> \param vout ...
1338!> \param mos_occ ...
1339!> \param matrix_s ...
1340! **************************************************************************************************
1341 SUBROUTINE project_vector(vin, vout, mos_occ, matrix_s)
1342 TYPE(dbcsr_type) :: vin, vout
1343 TYPE(cp_fm_type), INTENT(IN) :: mos_occ
1344 TYPE(dbcsr_type), POINTER :: matrix_s
1345
1346 CHARACTER(LEN=*), PARAMETER :: routinen = 'project_vector'
1347
1348 INTEGER :: handle, nao, nmo
1349 REAL(kind=dp) :: norm(1)
1350 TYPE(cp_fm_struct_type), POINTER :: fm_struct, fm_vec_struct
1351 TYPE(cp_fm_type) :: csvec, svec, vec
1352
1353 CALL timeset(routinen, handle)
1354
1355 CALL cp_fm_get_info(mos_occ, matrix_struct=fm_struct, nrow_global=nao, ncol_global=nmo)
1356 CALL cp_fm_struct_create(fmstruct=fm_vec_struct, template_fmstruct=fm_struct, &
1357 nrow_global=nao, ncol_global=1)
1358 CALL cp_fm_create(vec, fm_vec_struct)
1359 CALL cp_fm_create(svec, fm_vec_struct)
1360 CALL cp_fm_struct_release(fm_vec_struct)
1361 CALL cp_fm_struct_create(fmstruct=fm_vec_struct, template_fmstruct=fm_struct, &
1362 nrow_global=nmo, ncol_global=1)
1363 CALL cp_fm_create(csvec, fm_vec_struct)
1364 CALL cp_fm_struct_release(fm_vec_struct)
1365
1366 CALL copy_dbcsr_to_fm(vin, vec)
1367 CALL cp_dbcsr_sm_fm_multiply(matrix_s, vec, svec, ncol=1, alpha=1.0_dp, beta=0.0_dp)
1368 CALL parallel_gemm('T', 'N', nmo, 1, nao, 1.0_dp, mos_occ, svec, 0.0_dp, csvec)
1369 CALL parallel_gemm('N', 'N', nao, 1, nmo, -1.0_dp, mos_occ, csvec, 1.0_dp, vec)
1370 CALL cp_fm_vectorsnorm(vec, norm)
1371 cpassert(norm(1) > 1.e-14_dp)
1372 norm(1) = sqrt(1._dp/norm(1))
1373 CALL cp_fm_scale(norm(1), vec)
1374 CALL copy_fm_to_dbcsr(vec, vout, keep_sparsity=.false.)
1375
1376 CALL cp_fm_release(csvec)
1377 CALL cp_fm_release(svec)
1378 CALL cp_fm_release(vec)
1379
1380 CALL timestop(handle)
1381
1382 END SUBROUTINE project_vector
1383
1384! **************************************************************************************************
1385!> \brief ...
1386!> \param va ...
1387!> \param vb ...
1388!> \param res ...
1389! **************************************************************************************************
1390 SUBROUTINE vec_product(va, vb, res)
1391 TYPE(dbcsr_type) :: va, vb
1392 REAL(kind=dp), INTENT(OUT) :: res
1393
1394 CHARACTER(LEN=*), PARAMETER :: routinen = 'vec_product'
1395
1396 INTEGER :: handle, icol, irow
1397 LOGICAL :: found
1398 REAL(kind=dp), DIMENSION(:, :), POINTER :: vba, vbb
1399 TYPE(dbcsr_iterator_type) :: iter
1400 TYPE(mp_comm_type) :: group
1401
1402 CALL timeset(routinen, handle)
1403
1404 res = 0.0_dp
1405
1406 CALL dbcsr_get_info(va, group=group)
1407 CALL dbcsr_iterator_start(iter, va)
1408 DO WHILE (dbcsr_iterator_blocks_left(iter))
1409 CALL dbcsr_iterator_next_block(iter, irow, icol, vba)
1410 CALL dbcsr_get_block_p(vb, row=irow, col=icol, block=vbb, found=found)
1411 res = res + sum(vba*vbb)
1412 cpassert(found)
1413 END DO
1414 CALL dbcsr_iterator_stop(iter)
1415 CALL group%sum(res)
1416
1417 CALL timestop(handle)
1418
1419 END SUBROUTINE vec_product
1420
1421! **************************************************************************************************
1422!> \brief ...
1423!> \param qs_env ...
1424!> \param mos ...
1425!> \param istate ...
1426!> \param stride ...
1427!> \param append_cube ...
1428!> \param print_section ...
1429! **************************************************************************************************
1430 SUBROUTINE print_nto_cubes(qs_env, mos, istate, stride, append_cube, print_section)
1431
1432 TYPE(qs_environment_type), POINTER :: qs_env
1433 TYPE(mo_set_type), DIMENSION(:), INTENT(IN) :: mos
1434 INTEGER, INTENT(IN) :: istate
1435 INTEGER, DIMENSION(:), POINTER :: stride
1436 LOGICAL, INTENT(IN) :: append_cube
1437 TYPE(section_vals_type), POINTER :: print_section
1438
1439 CHARACTER(LEN=default_path_length) :: filename, my_pos_cube, title
1440 INTEGER :: i, iset, nmo, unit_nr
1441 LOGICAL :: mpi_io
1442 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
1443 TYPE(cell_type), POINTER :: cell
1444 TYPE(cp_fm_type), POINTER :: mo_coeff
1445 TYPE(cp_logger_type), POINTER :: logger
1446 TYPE(dft_control_type), POINTER :: dft_control
1447 TYPE(particle_list_type), POINTER :: particles
1448 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1449 TYPE(pw_c1d_gs_type) :: wf_g
1450 TYPE(pw_env_type), POINTER :: pw_env
1451 TYPE(pw_pool_p_type), DIMENSION(:), POINTER :: pw_pools
1452 TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
1453 TYPE(pw_r3d_rs_type) :: wf_r
1454 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1455 TYPE(qs_subsys_type), POINTER :: subsys
1456
1457 logger => cp_get_default_logger()
1458
1459 CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, pw_env=pw_env)
1460 CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, pw_pools=pw_pools)
1461 CALL auxbas_pw_pool%create_pw(wf_r)
1462 CALL auxbas_pw_pool%create_pw(wf_g)
1463
1464 CALL get_qs_env(qs_env, subsys=subsys)
1465 CALL qs_subsys_get(subsys, particles=particles)
1466
1467 my_pos_cube = "REWIND"
1468 IF (append_cube) THEN
1469 my_pos_cube = "APPEND"
1470 END IF
1471
1472 CALL get_qs_env(qs_env=qs_env, &
1473 atomic_kind_set=atomic_kind_set, &
1474 qs_kind_set=qs_kind_set, &
1475 cell=cell, &
1476 particle_set=particle_set)
1477
1478 DO iset = 1, 2
1479 CALL get_mo_set(mo_set=mos(iset), mo_coeff=mo_coeff, nmo=nmo)
1480 DO i = 1, nmo
1481 CALL calculate_wavefunction(mo_coeff, i, wf_r, wf_g, atomic_kind_set, qs_kind_set, &
1482 cell, dft_control, particle_set, pw_env)
1483 IF (iset == 1) THEN
1484 WRITE (filename, '(a4,I3.3,I2.2,a11)') "NTO_STATE", istate, i, "_Hole_State"
1485 ELSEIF (iset == 2) THEN
1486 WRITE (filename, '(a4,I3.3,I2.2,a15)') "NTO_STATE", istate, i, "_Particle_State"
1487 END IF
1488 mpi_io = .true.
1489 unit_nr = cp_print_key_unit_nr(logger, print_section, '', extension=".cube", &
1490 middle_name=trim(filename), file_position=my_pos_cube, &
1491 log_filename=.false., ignore_should_output=.true., mpi_io=mpi_io)
1492 IF (iset == 1) THEN
1493 WRITE (title, *) "Natural Transition Orbital Hole State", i
1494 ELSEIF (iset == 2) THEN
1495 WRITE (title, *) "Natural Transition Orbital Particle State", i
1496 END IF
1497 CALL cp_pw_to_cube(wf_r, unit_nr, title, particles=particles, stride=stride, mpi_io=mpi_io)
1498 CALL cp_print_key_finished_output(unit_nr, logger, print_section, '', &
1499 ignore_should_output=.true., mpi_io=mpi_io)
1500 END DO
1501 END DO
1502
1503 CALL auxbas_pw_pool%give_back_pw(wf_g)
1504 CALL auxbas_pw_pool%give_back_pw(wf_r)
1505
1506 END SUBROUTINE print_nto_cubes
1507
1508END 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, prefix_output, qs_env)
Prints exciton descriptors, cf. Mewes et al., JCTC 14, 710-725 (2018)
Definition bse_print.F:507
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, qs_env, mo_coeff, rpoint, n_moments, homo_red, virtual_red, context_bse)
...
Definition bse_util.F:1715
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_create(matrix, matrix_struct, name)
Creates a new full matrix with the given structure.
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_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...
subroutine, public dbcsr_iterator_next_block(iterator, row, column, block, block_number_argument_has_been_removed, row_size, col_size, row_offset, col_offset)
...
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_start(iterator, matrix, shared, dynamic, dynamic_byrows)
...
subroutine, public dbcsr_set(matrix, alpha)
...
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)
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 Single option version: Cholesky decomposition of B.
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:234
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, use_sp)
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, stride, 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_velocity
integer, parameter, public tddfpt_dipole_length
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
sums arrays of real/complex numbers with much reduced round-off as compared to a naive implementation...
Definition kahan_sum.F:29
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)
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, 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, 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, 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 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)
Get the components of a MO set data structure.
subroutine, public init_mo_set(mo_set, fm_pool, fm_ref, fm_struct, name)
initializes an allocated mo_set. eigenvalues, mo_coeff, occupation_numbers are valid only after this ...
Calculates the moment integrals <a|r^m|b> and <a|r x d/dr|b>
Definition qs_moments.F:14
subroutine, public build_berry_moment_matrix(qs_env, cosmat, sinmat, kvec, sab_orb_external, basis_type)
...
Define the neighbor list data types and the corresponding functionality.
subroutine, public rrc_xyz_ao(op, qs_env, rc, order, minimum_image, soft)
Calculation of the components of the dipole operator in the length form by taking the relative positi...
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)
Calculation of the overlap matrix over Cartesian Gaussian functions.
Definition qs_overlap.F:120
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_summary(log_unit, evects, evals, ostrength, mult, dipole_op_mos_occ, dipole_form)
Print final TDDFPT excitation energies and oscillator strengths.
subroutine, public tddfpt_print_excitation_analysis(log_unit, evects, evals, gs_mos, matrix_s, spinflip, min_amplitude)
Print excitation analysis.
subroutine, public tddfpt_print_exciton_descriptors(log_unit, evects, gs_mos, matrix_s, do_directional_exciton_descriptors, qs_env)
Print exciton descriptors, cf. Mewes et al., JCTC 14, 710-725 (2018)
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:55
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.