Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : MODULE qs_tddfpt2_methods
9 : USE admm_methods, ONLY: admm_fit_mo_coeffs
10 : USE admm_types, ONLY: admm_type,&
11 : get_admm_env
12 : USE atomic_kind_types, ONLY: atomic_kind_type
13 : USE bibliography, ONLY: Grimme2013,&
14 : Grimme2016,&
15 : Hernandez2025,&
16 : Iannuzzi2005,&
17 : cite_reference
18 : USE cell_types, ONLY: cell_type
19 : USE cp_blacs_env, ONLY: cp_blacs_env_type
20 : USE cp_control_types, ONLY: dft_control_type,&
21 : rixs_control_type,&
22 : tddfpt2_control_type
23 : USE cp_dbcsr_api, ONLY: dbcsr_create,&
24 : dbcsr_deallocate_matrix,&
25 : dbcsr_p_type,&
26 : dbcsr_set,&
27 : dbcsr_type,&
28 : dbcsr_type_antisymmetric,&
29 : dbcsr_type_symmetric
30 : USE cp_dbcsr_cp2k_link, ONLY: cp_dbcsr_alloc_block_from_nbl
31 : USE cp_dbcsr_operations, ONLY: cp_dbcsr_sm_fm_multiply,&
32 : dbcsr_deallocate_matrix_set
33 : USE cp_fm_pool_types, ONLY: fm_pool_create_fm
34 : USE cp_fm_struct, ONLY: cp_fm_struct_create,&
35 : cp_fm_struct_release,&
36 : cp_fm_struct_type
37 : USE cp_fm_types, ONLY: cp_fm_copy_general,&
38 : cp_fm_create,&
39 : cp_fm_get_element,&
40 : cp_fm_get_info,&
41 : cp_fm_release,&
42 : cp_fm_to_fm,&
43 : cp_fm_to_fm_submat,&
44 : cp_fm_type
45 : USE cp_log_handling, ONLY: cp_get_default_logger,&
46 : cp_logger_get_default_io_unit,&
47 : cp_logger_type
48 : USE cp_output_handling, ONLY: cp_add_iter_level,&
49 : cp_iterate,&
50 : cp_print_key_finished_output,&
51 : cp_print_key_unit_nr,&
52 : cp_rm_iter_level
53 : USE exstates_types, ONLY: excited_energy_type
54 : USE header, ONLY: tddfpt_header,&
55 : tddfpt_soc_header
56 : USE hfx_admm_utils, ONLY: aux_admm_init
57 : USE hfx_types, ONLY: compare_hfx_sections,&
58 : hfx_create
59 : USE input_constants, ONLY: &
60 : do_admm_aux_exch_func_none, do_admm_basis_projection, do_admm_exch_scaling_none, &
61 : do_admm_purify_none, do_potential_truncated, no_sf_tddfpt, oe_none, &
62 : tddfpt_dipole_scf_moment, tddfpt_dipole_velocity, tddfpt_kernel_full, tddfpt_kernel_none, &
63 : tddfpt_kernel_stda, tddfpt_sf_col, tddfpt_sf_noncol
64 : USE input_section_types, ONLY: section_vals_get,&
65 : section_vals_get_subs_vals,&
66 : section_vals_type,&
67 : section_vals_val_get,&
68 : section_vals_val_set
69 : USE kinds, ONLY: dp
70 : USE kpoint_methods, ONLY: rskp_transform
71 : USE kpoint_types, ONLY: get_kpoint_info,&
72 : kpoint_env_p_type,&
73 : kpoint_env_type,&
74 : kpoint_type
75 : USE lri_environment_methods, ONLY: lri_print_stat
76 : USE lri_environment_types, ONLY: lri_density_release,&
77 : lri_env_release
78 : USE machine, ONLY: m_flush
79 : USE message_passing, ONLY: mp_para_env_type
80 : USE min_basis_set, ONLY: create_minbas_set
81 : USE parallel_gemm_api, ONLY: parallel_gemm
82 : USE particle_types, ONLY: particle_type
83 : USE physcon, ONLY: evolt
84 : USE qs_environment_types, ONLY: get_qs_env,&
85 : qs_environment_type
86 : USE qs_kernel_methods, ONLY: create_fxc_kernel,&
87 : create_kernel_env
88 : USE qs_kernel_types, ONLY: full_kernel_env_type,&
89 : kernel_env_type,&
90 : release_kernel_env
91 : USE qs_kind_types, ONLY: qs_kind_type
92 : USE qs_ks_types, ONLY: qs_ks_env_type
93 : USE qs_mo_types, ONLY: get_mo_set,&
94 : mo_set_type
95 : USE qs_moments, ONLY: qs_moment_kpoints_scf_mos
96 : USE qs_neighbor_list_types, ONLY: neighbor_list_set_p_type
97 : USE qs_overlap, ONLY: build_overlap_matrix
98 : USE qs_scf_methods, ONLY: eigensolver
99 : USE qs_scf_types, ONLY: qs_scf_env_type
100 : USE qs_tddfpt2_assign, ONLY: assign_state
101 : USE qs_tddfpt2_densities, ONLY: tddfpt_construct_aux_fit_density,&
102 : tddfpt_construct_ground_state_orb_density
103 : USE qs_tddfpt2_eigensolver, ONLY: tddfpt_davidson_solver,&
104 : tddfpt_orthogonalize_psi1_psi0,&
105 : tddfpt_orthonormalize_psi1_psi1
106 : USE qs_tddfpt2_forces, ONLY: tddfpt_forces_main
107 : USE qs_tddfpt2_fprint, ONLY: tddfpt_print_forces
108 : USE qs_tddfpt2_lri_utils, ONLY: tddfpt2_lri_init
109 : USE qs_tddfpt2_properties, ONLY: tddfpt_dipole_operator,&
110 : tddfpt_print_excitation_analysis,&
111 : tddfpt_print_exciton_descriptors,&
112 : tddfpt_print_nto_analysis,&
113 : tddfpt_print_summary
114 : USE qs_tddfpt2_restart, ONLY: tddfpt_read_restart,&
115 : tddfpt_write_newtonx_output,&
116 : tddfpt_write_restart
117 : USE qs_tddfpt2_smearing_methods, ONLY: tddfpt_smeared_occupation
118 : USE qs_tddfpt2_soc, ONLY: tddfpt_soc
119 : USE qs_tddfpt2_stda_types, ONLY: allocate_stda_env,&
120 : deallocate_stda_env,&
121 : stda_env_type,&
122 : stda_init_param
123 : USE qs_tddfpt2_stda_utils, ONLY: get_lowdin_mo_coefficients,&
124 : stda_init_matrices
125 : USE qs_tddfpt2_subgroups, ONLY: tddfpt_sub_env_init,&
126 : tddfpt_sub_env_release,&
127 : tddfpt_subgroup_env_type
128 : USE qs_tddfpt2_types, ONLY: hfxsr_create_work_matrices,&
129 : stda_create_work_matrices,&
130 : tddfpt_create_work_matrices,&
131 : tddfpt_ground_state_mos,&
132 : tddfpt_release_work_matrices,&
133 : tddfpt_work_matrices
134 : USE qs_tddfpt2_utils, ONLY: tddfpt_guess_vectors,&
135 : tddfpt_init_mos,&
136 : tddfpt_oecorr,&
137 : tddfpt_release_ground_state_mos
138 : USE rixs_types, ONLY: rixs_env_type,&
139 : tddfpt2_valence_type
140 : USE string_utilities, ONLY: integer_to_string
141 : USE util, ONLY: sort
142 : USE xc_write_output, ONLY: xc_write
143 : #include "./base/base_uses.f90"
144 :
145 : IMPLICIT NONE
146 :
147 : PRIVATE
148 :
149 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_tddfpt2_methods'
150 :
151 : LOGICAL, PARAMETER, PRIVATE :: debug_this_module = .FALSE.
152 : ! number of first derivative components (3: d/dx, d/dy, d/dz)
153 : INTEGER, PARAMETER, PRIVATE :: nderivs = 3
154 : INTEGER, PARAMETER, PRIVATE :: maxspins = 2
155 :
156 : PUBLIC :: tddfpt, tddfpt_energies, tddfpt_input
157 :
158 : ! **************************************************************************************************
159 :
160 : CONTAINS
161 :
162 : ! **************************************************************************************************
163 : !> \brief Perform TDDFPT calculation. If calc_forces then it also builds the response vector for the
164 : !> Z-vector method and calculates some contributions to the force
165 : !> \param qs_env Quickstep environment
166 : !> \param calc_forces ...
167 : !> \param rixs_env ...
168 : !> \par History
169 : !> * 05.2016 created [Sergey Chulkov]
170 : !> * 06.2016 refactored to be used with Davidson eigensolver [Sergey Chulkov]
171 : !> * 03.2017 cleaned and refactored [Sergey Chulkov]
172 : !> \note Based on the subroutines tddfpt_env_init(), and tddfpt_env_deallocate().
173 : ! **************************************************************************************************
174 1424 : SUBROUTINE tddfpt(qs_env, calc_forces, rixs_env)
175 : TYPE(qs_environment_type), POINTER :: qs_env
176 : LOGICAL, INTENT(IN) :: calc_forces
177 : TYPE(rixs_env_type), OPTIONAL, POINTER :: rixs_env
178 :
179 : CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt'
180 :
181 : INTEGER :: handle, ispin, istate, log_unit, mult, &
182 : my_state, nao, nocc, nspins, &
183 : nstate_max, nstates, nvirt, old_state
184 : INTEGER, DIMENSION(maxspins) :: nactive
185 : LOGICAL :: do_admm, do_exck, do_hfx, do_hfxlr, &
186 : do_hfxsr, do_kpoints, do_rixs, do_sf, &
187 : do_soc, lmult_tmp, state_change
188 : REAL(kind=dp) :: gsmin, gsval, xsval
189 1424 : REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: evals, ostrength
190 1424 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
191 : TYPE(cell_type), POINTER :: cell
192 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
193 : TYPE(cp_fm_struct_type), POINTER :: matrix_struct
194 1424 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: my_active, my_mos
195 1424 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: dipole_op_mos_occ, evects, S_evects
196 : TYPE(cp_logger_type), POINTER :: logger
197 1424 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks, matrix_ks_oep, matrix_s, &
198 1424 : matrix_s_aux_fit, &
199 1424 : matrix_s_aux_fit_vs_orb
200 : TYPE(dft_control_type), POINTER :: dft_control
201 : TYPE(excited_energy_type), POINTER :: ex_env
202 : TYPE(full_kernel_env_type), TARGET :: full_kernel_env, kernel_env_admm_aux
203 : TYPE(kernel_env_type) :: kernel_env
204 1424 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mos, mos_aux_fit
205 : TYPE(mp_para_env_type), POINTER :: para_env
206 1424 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
207 1424 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
208 : TYPE(qs_scf_env_type), POINTER :: scf_env
209 : TYPE(rixs_control_type), POINTER :: rixs_control
210 : TYPE(section_vals_type), POINTER :: hfxsr_section, kernel_section, &
211 : lri_section, soc_section, &
212 : tddfpt_print_section, tddfpt_section, &
213 : xc_section
214 : TYPE(stda_env_type), TARGET :: stda_kernel
215 : TYPE(tddfpt2_control_type), POINTER :: tddfpt_control
216 : TYPE(tddfpt2_valence_type), POINTER :: valence_state
217 : TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
218 1424 : POINTER :: gs_mos
219 1424 : TYPE(tddfpt_subgroup_env_type) :: sub_env
220 1424 : TYPE(tddfpt_work_matrices) :: work_matrices
221 :
222 1424 : CALL timeset(routineN, handle)
223 :
224 1424 : NULLIFY (logger)
225 1424 : logger => cp_get_default_logger()
226 :
227 1424 : NULLIFY (tddfpt_section, tddfpt_control)
228 :
229 : CALL get_qs_env(qs_env, &
230 : dft_control=dft_control, &
231 1424 : do_rixs=do_rixs)
232 1424 : do_kpoints = dft_control%nimages > 1
233 :
234 1424 : IF (do_rixs) THEN
235 16 : tddfpt_section => section_vals_get_subs_vals(qs_env%input, "PROPERTIES%RIXS%TDDFPT")
236 16 : NULLIFY (rixs_control, valence_state)
237 16 : rixs_control => dft_control%rixs_control
238 16 : tddfpt_control => rixs_control%tddfpt2_control
239 16 : valence_state => rixs_env%valence_state
240 : ELSE
241 1408 : tddfpt_section => section_vals_get_subs_vals(qs_env%input, "PROPERTIES%TDDFPT")
242 1408 : tddfpt_control => dft_control%tddfpt2_control
243 : END IF
244 :
245 : ! input section print/xc
246 : CALL tddfpt_input(qs_env, tddfpt_section, tddfpt_control, do_hfx, do_admm, do_exck, &
247 : do_hfxsr, do_hfxlr, xc_section, tddfpt_print_section, &
248 1424 : lri_section, hfxsr_section)
249 :
250 : log_unit = cp_print_key_unit_nr(logger, tddfpt_print_section, "PROGRAM_BANNER", &
251 1424 : extension=".tddfptLog")
252 :
253 1424 : tddfpt_control%do_hfx = do_hfx
254 1424 : tddfpt_control%do_admm = do_admm
255 1424 : tddfpt_control%do_hfxsr = do_hfxsr
256 1424 : tddfpt_control%hfxsr_primbas = 0
257 1424 : tddfpt_control%hfxsr_re_int = .TRUE.
258 1424 : tddfpt_control%do_hfxlr = do_hfxlr
259 1424 : tddfpt_control%do_exck = do_exck
260 1424 : do_sf = tddfpt_control%spinflip /= no_sf_tddfpt
261 1424 : IF (do_sf) CALL cite_reference(Hernandez2025)
262 1424 : IF (tddfpt_control%do_hfxlr) THEN
263 6 : kernel_section => section_vals_get_subs_vals(tddfpt_section, "XC%HFX_KERNEL%HFXLR")
264 6 : CALL section_vals_val_get(kernel_section, "RCUT", r_val=tddfpt_control%hfxlr_rcut)
265 6 : CALL section_vals_val_get(kernel_section, "SCALE", r_val=tddfpt_control%hfxlr_scale)
266 : END IF
267 :
268 1424 : soc_section => section_vals_get_subs_vals(tddfpt_section, "SOC")
269 1424 : CALL section_vals_get(soc_section, explicit=do_soc)
270 :
271 1424 : IF (do_soc) THEN
272 : ! start with multiplicity that is not specified in input
273 : ! so that excited-state gradient is for multiplicity given in input
274 10 : lmult_tmp = tddfpt_control%rks_triplets
275 10 : tddfpt_control%rks_triplets = .NOT. (tddfpt_control%rks_triplets)
276 : END IF
277 :
278 1424 : CALL cite_reference(Iannuzzi2005)
279 1424 : IF (tddfpt_control%kernel == tddfpt_kernel_stda) THEN
280 440 : CALL cite_reference(Grimme2013)
281 440 : CALL cite_reference(Grimme2016)
282 : END IF
283 :
284 1424 : CALL tddfpt_header(log_unit)
285 1424 : CALL kernel_info(log_unit, dft_control, tddfpt_control, xc_section)
286 :
287 1424 : IF (do_kpoints) THEN
288 8 : IF (calc_forces) THEN
289 0 : CPABORT("TDDFPT forces are not implemented for k-points")
290 : END IF
291 8 : IF (do_rixs) THEN
292 0 : CPABORT("RIXS/TDDFPT is not implemented for k-points")
293 : END IF
294 8 : IF (do_soc) THEN
295 0 : CPABORT("TDDFPT-SOC is not implemented for k-points")
296 : END IF
297 8 : CALL tddfpt_kpoint_independent_particle(qs_env, logger, tddfpt_control)
298 : CALL cp_print_key_finished_output(log_unit, &
299 : logger, &
300 : tddfpt_print_section, &
301 8 : "PROGRAM_BANNER")
302 8 : CALL timestop(handle)
303 8 : RETURN
304 : END IF
305 :
306 : CALL get_qs_env(qs_env, &
307 : blacs_env=blacs_env, &
308 : cell=cell, &
309 : matrix_ks=matrix_ks, &
310 : matrix_s=matrix_s, &
311 : mos=mos, &
312 1416 : scf_env=scf_env)
313 :
314 : ! obtain occupied and virtual (unoccupied) ground-state Kohn-Sham orbitals
315 1416 : NULLIFY (gs_mos)
316 1416 : CALL tddfpt_init_mos(qs_env, gs_mos, log_unit)
317 :
318 : ! obtain smeared occupation numbers
319 1416 : IF (tddfpt_control%do_smearing) THEN
320 2 : CALL tddfpt_smeared_occupation(qs_env, gs_mos, log_unit)
321 : END IF
322 :
323 : ! obtain corrected KS-matrix
324 1416 : CALL tddfpt_oecorr(qs_env, gs_mos, matrix_ks_oep)
325 :
326 1416 : IF ((tddfpt_control%do_lrigpw) .AND. &
327 : (tddfpt_control%kernel /= tddfpt_kernel_full)) THEN
328 0 : CALL cp_abort(__LOCATION__, "LRI only implemented for full kernel")
329 : END IF
330 :
331 1416 : IF (ASSOCIATED(matrix_ks_oep)) matrix_ks => matrix_ks_oep
332 :
333 : ! determine active orbitals
334 : ! default is all occupied MOs
335 1416 : CALL init_res_method(qs_env, gs_mos, tddfpt_control, tddfpt_section, log_unit)
336 :
337 : ! components of the dipole operator
338 : CALL tddfpt_dipole_operator(dipole_op_mos_occ, &
339 : tddfpt_control, &
340 : gs_mos, &
341 1416 : qs_env)
342 :
343 1416 : nspins = SIZE(gs_mos)
344 : ! multiplicity of molecular system
345 1416 : IF (nspins > 1) THEN
346 194 : mult = ABS(SIZE(gs_mos(1)%evals_occ) - SIZE(gs_mos(2)%evals_occ)) + 1
347 194 : IF (mult > 2) THEN
348 30 : CALL cp_warn(__LOCATION__, "There is a convergence issue for multiplicity >= 3")
349 : END IF
350 : ELSE
351 1222 : IF (tddfpt_control%rks_triplets) THEN
352 204 : mult = 3
353 : ELSE
354 1018 : mult = 1
355 : END IF
356 : END IF
357 :
358 : ! split mpi communicator
359 8884 : ALLOCATE (my_mos(nspins), my_active(nspins))
360 3026 : DO ispin = 1, nspins
361 1610 : my_mos(ispin) = gs_mos(ispin)%mos_occ
362 3026 : my_active(ispin) = gs_mos(ispin)%mos_active
363 : END DO
364 : CALL tddfpt_sub_env_init(sub_env, qs_env, &
365 : mos_occ=my_mos(:), mos_active=my_active(:), &
366 1416 : kernel=tddfpt_control%kernel)
367 1416 : DEALLOCATE (my_mos, my_active)
368 :
369 1416 : IF (tddfpt_control%kernel == tddfpt_kernel_full) THEN
370 : ! create environment for Full Kernel
371 852 : IF (dft_control%qs_control%xtb) THEN
372 0 : CPABORT("TDDFPT: xTB only works with sTDA Kernel")
373 : END IF
374 :
375 852 : IF (tddfpt_control%do_hfxsr) THEN
376 4 : kernel_section => section_vals_get_subs_vals(tddfpt_section, "XC%HFX_KERNEL")
377 : CALL section_vals_val_get(kernel_section, "HFXSR_PRIMBAS", &
378 4 : i_val=tddfpt_control%hfxsr_primbas)
379 : ! basis set
380 : CALL create_minbas_set(qs_env, log_unit, basis_type="TDA_HFX", &
381 4 : primitive=tddfpt_control%hfxsr_primbas)
382 : ! admm control
383 16 : ALLOCATE (full_kernel_env%admm_control)
384 4 : full_kernel_env%admm_control%purification_method = do_admm_purify_none
385 : full_kernel_env%admm_control%method = do_admm_basis_projection
386 : full_kernel_env%admm_control%scaling_model = do_admm_exch_scaling_none
387 4 : full_kernel_env%admm_control%aux_exch_func = do_admm_aux_exch_func_none
388 : ! hfx section
389 4 : full_kernel_env%hfxsr_section => hfxsr_section
390 : !
391 : CALL aux_admm_init(qs_env, mos, full_kernel_env%admm_env, &
392 4 : full_kernel_env%admm_control, "TDA_HFX")
393 : CALL get_admm_env(full_kernel_env%admm_env, mos_aux_fit=mos_aux_fit, &
394 : matrix_s_aux_fit=matrix_s_aux_fit, &
395 4 : matrix_s_aux_fit_vs_orb=matrix_s_aux_fit_vs_orb)
396 : CALL admm_fit_mo_coeffs(full_kernel_env%admm_env, matrix_s_aux_fit, &
397 4 : matrix_s_aux_fit_vs_orb, mos, mos_aux_fit, .TRUE.)
398 : ! x_data
399 : CALL get_qs_env(qs_env, cell=cell, atomic_kind_set=atomic_kind_set, &
400 : qs_kind_set=qs_kind_set, particle_set=particle_set, &
401 4 : para_env=para_env)
402 : CALL hfx_create(full_kernel_env%x_data, para_env, hfxsr_section, atomic_kind_set, &
403 4 : qs_kind_set, particle_set, dft_control, cell, orb_basis="TDA_HFX")
404 : END IF
405 :
406 : ! allocate pools and work matrices
407 852 : nstates = tddfpt_control%nstates
408 : !! Too many states can lead to Problems
409 : !! You should be warned if there are more states
410 : !! than occ-virt Combinations!!
411 852 : CALL cp_fm_get_info(gs_mos(1)%mos_occ, ncol_global=nocc)
412 852 : IF (tddfpt_control%spinflip == no_sf_tddfpt) THEN
413 830 : CALL cp_fm_get_info(gs_mos(1)%mos_virt, ncol_global=nvirt)
414 : ELSE
415 22 : CALL cp_fm_get_info(gs_mos(2)%mos_virt, ncol_global=nvirt)
416 : END IF
417 852 : nstate_max = nocc*nvirt
418 852 : IF (nstates > nstate_max) THEN
419 0 : CPWARN("NUMBER OF EXCITED STATES COULD LEAD TO PROBLEMS!")
420 0 : CPWARN("Experimental: CHANGED NSTATES TO ITS MAXIMUM VALUE!")
421 0 : nstates = nstate_max
422 0 : tddfpt_control%nstates = nstate_max
423 : END IF
424 : CALL tddfpt_create_work_matrices(work_matrices, gs_mos, nstates, &
425 852 : do_hfx, do_admm, do_hfxlr, do_exck, do_sf, qs_env, sub_env)
426 :
427 : ! create full_kernel and admm_kernel within tddfpt_energies
428 852 : kernel_env%full_kernel => full_kernel_env
429 852 : kernel_env%admm_kernel => kernel_env_admm_aux
430 852 : NULLIFY (kernel_env%stda_kernel)
431 852 : IF (do_hfxsr) THEN
432 : ! work matrices for SR HFX
433 4 : CALL hfxsr_create_work_matrices(work_matrices, qs_env, full_kernel_env%admm_env)
434 : END IF
435 852 : IF (do_hfxlr) THEN
436 : ! calculate S_half and Lowdin MO coefficients
437 6 : CALL get_lowdin_mo_coefficients(qs_env, sub_env, work_matrices)
438 : END IF
439 564 : ELSE IF (tddfpt_control%kernel == tddfpt_kernel_stda) THEN
440 : ! setup for kernel_stda outside tddfpt_energies
441 440 : CALL cp_fm_get_info(gs_mos(1)%mos_occ, nrow_global=nao)
442 1320 : nactive = tddfpt_control%nactive
443 440 : CALL allocate_stda_env(qs_env, stda_kernel, nao, nactive)
444 : ! sTDA parameters
445 440 : CALL stda_init_param(qs_env, stda_kernel, tddfpt_control%stda_control)
446 : ! allocate pools and work matrices
447 440 : nstates = tddfpt_control%nstates
448 440 : CALL stda_create_work_matrices(work_matrices, gs_mos, nstates, qs_env, sub_env)
449 : !
450 : CALL stda_init_matrices(qs_env, stda_kernel, sub_env, &
451 440 : work_matrices, tddfpt_control)
452 : !
453 440 : kernel_env%stda_kernel => stda_kernel
454 440 : NULLIFY (kernel_env%full_kernel)
455 440 : NULLIFY (kernel_env%admm_kernel)
456 124 : ELSE IF (tddfpt_control%kernel == tddfpt_kernel_none) THEN
457 : ! allocate pools and work matrices
458 124 : nstates = tddfpt_control%nstates
459 124 : CALL stda_create_work_matrices(work_matrices, gs_mos, nstates, qs_env, sub_env)
460 124 : NULLIFY (kernel_env%full_kernel)
461 124 : NULLIFY (kernel_env%admm_kernel)
462 124 : NULLIFY (kernel_env%stda_kernel)
463 : END IF
464 :
465 1416 : IF (do_sf) THEN
466 : ! only alpha -> beta excitations are considered in spin-flip TDDFT
467 246 : ALLOCATE (evects(1, nstates))
468 : ELSE
469 13252 : ALLOCATE (evects(nspins, nstates))
470 : END IF
471 4248 : ALLOCATE (evals(nstates))
472 13520 : ALLOCATE (S_evects(SIZE(evects, 1), nstates))
473 :
474 5042 : DO istate = 1, nstates
475 9272 : DO ispin = 1, SIZE(evects, 1)
476 : CALL fm_pool_create_fm( &
477 : work_matrices%fm_pool_ao_mo_active(ispin)%pool, &
478 7856 : S_evects(ispin, istate))
479 : END DO
480 : END DO
481 :
482 1416 : IF (.NOT. do_soc) THEN
483 : ! compute tddfpt excitation energies of multiplicity mult
484 : CALL tddfpt_energies(qs_env, nstates, nspins, work_matrices, &
485 : tddfpt_control, logger, tddfpt_print_section, evects, evals, &
486 : gs_mos, tddfpt_section, S_evects, matrix_s, kernel_env, matrix_ks, &
487 : sub_env, ostrength, dipole_op_mos_occ, mult, xc_section, full_kernel_env, &
488 1406 : kernel_env_admm_aux)
489 : ELSE
490 : CALL tddfpt_soc_energies(qs_env, nstates, work_matrices, &
491 : tddfpt_control, logger, tddfpt_print_section, &
492 : evects, evals, ostrength, &
493 : gs_mos, tddfpt_section, S_evects, matrix_s, kernel_env, matrix_ks, &
494 : sub_env, dipole_op_mos_occ, lmult_tmp, xc_section, full_kernel_env, &
495 10 : kernel_env_admm_aux)
496 : END IF
497 :
498 : !print forces for selected states
499 1416 : IF (calc_forces) THEN
500 : CALL tddfpt_print_forces(qs_env, evects, evals, ostrength, &
501 : tddfpt_print_section, gs_mos, &
502 654 : kernel_env, sub_env, work_matrices)
503 : END IF
504 :
505 : ! excited state potential energy surface
506 1416 : IF (qs_env%excited_state) THEN
507 1176 : IF (sub_env%is_split) THEN
508 : CALL cp_abort(__LOCATION__, &
509 : "Excited state forces not possible when states"// &
510 0 : " are distributed to different CPU pools.")
511 : END IF
512 : ! for gradients unshifted KS matrix
513 1176 : IF (ASSOCIATED(matrix_ks_oep)) CALL get_qs_env(qs_env, matrix_ks=matrix_ks)
514 1176 : CALL get_qs_env(qs_env, exstate_env=ex_env)
515 1176 : state_change = .FALSE.
516 1176 : IF (ex_env%state > 0) THEN
517 1168 : my_state = ex_env%state
518 8 : ELSE IF (ex_env%state < 0) THEN
519 : ! state following
520 32 : ALLOCATE (my_mos(nspins))
521 16 : DO ispin = 1, nspins
522 16 : my_mos(ispin) = gs_mos(ispin)%mos_occ
523 : END DO
524 8 : my_state = ABS(ex_env%state)
525 8 : CALL assign_state(qs_env, matrix_s, evects, my_mos, ex_env%wfn_history, my_state)
526 8 : DEALLOCATE (my_mos)
527 8 : IF (my_state /= ABS(ex_env%state)) THEN
528 0 : state_change = .TRUE.
529 0 : old_state = ABS(ex_env%state)
530 : END IF
531 8 : ex_env%state = -my_state
532 : ELSE
533 : CALL cp_warn(__LOCATION__, &
534 0 : "Active excited state not assigned. Use the first state.")
535 0 : my_state = 1
536 : END IF
537 1176 : CPASSERT(my_state > 0)
538 1176 : IF (my_state > nstates) THEN
539 : CALL cp_warn(__LOCATION__, &
540 0 : "There were not enough excited states calculated.")
541 0 : CPABORT("excited state potential energy surface")
542 : END IF
543 : !
544 : ! energy
545 1176 : ex_env%evalue = evals(my_state)
546 : ! excitation vector
547 1176 : CALL cp_fm_release(ex_env%evect)
548 4830 : ALLOCATE (ex_env%evect(SIZE(evects, 1)))
549 2478 : DO ispin = 1, SIZE(evects, 1)
550 : CALL cp_fm_get_info(matrix=evects(ispin, 1), &
551 1302 : matrix_struct=matrix_struct)
552 1302 : CALL cp_fm_create(ex_env%evect(ispin), matrix_struct)
553 2478 : CALL cp_fm_to_fm(evects(ispin, my_state), ex_env%evect(ispin))
554 : END DO
555 :
556 1176 : IF (log_unit > 0) THEN
557 588 : gsval = ex_env%wfn_history%gsval
558 588 : gsmin = ex_env%wfn_history%gsmin
559 588 : xsval = ex_env%wfn_history%xsval
560 588 : WRITE (log_unit, "(1X,A,T40,F10.6,A,T62,F10.6,A)") "Ground state orbital alignment:", &
561 1176 : gsmin, "[MinVal]", gsval, "[Average]"
562 588 : WRITE (log_unit, "(1X,A,T71,F10.6)") "Excitation vector alignment:", xsval
563 588 : IF (state_change) THEN
564 : WRITE (log_unit, "(1X,A,I5,T60,A14,T76,I5)") &
565 0 : "Target state has been changed from state ", &
566 0 : old_state, " to new state ", my_state
567 : END IF
568 588 : WRITE (log_unit, "(1X,A,I4,A,F12.5,A)") "Calculate properties for state:", &
569 1176 : my_state, " with excitation energy ", ex_env%evalue*evolt, " eV"
570 : END IF
571 :
572 : ! Calculate response vector
573 1176 : IF (calc_forces) THEN
574 : CALL tddfpt_forces_main(qs_env, gs_mos, ex_env, kernel_env, &
575 652 : sub_env, work_matrices)
576 : END IF
577 : END IF
578 :
579 : ! share evals, evects and mo_coefs with rixs
580 1416 : IF (do_rixs) THEN
581 : ! copy evals
582 16 : valence_state%nstates = nstates
583 48 : ALLOCATE (valence_state%evals(SIZE(evals)))
584 70 : valence_state%evals(:) = evals(:)
585 :
586 192 : ALLOCATE (valence_state%evects(nspins, nstates))
587 68 : ALLOCATE (valence_state%mos_active(nspins))
588 36 : DO ispin = 1, nspins
589 : ! copy evects
590 94 : DO istate = 1, nstates
591 : CALL cp_fm_get_info(matrix=evects(ispin, istate), &
592 74 : matrix_struct=matrix_struct)
593 74 : CALL cp_fm_create(valence_state%evects(ispin, istate), matrix_struct)
594 94 : CALL cp_fm_to_fm(evects(ispin, istate), valence_state%evects(ispin, istate))
595 : END DO
596 : ! copy mos_occ
597 : CALL cp_fm_get_info(matrix=gs_mos(ispin)%mos_active, &
598 20 : matrix_struct=matrix_struct)
599 20 : CALL cp_fm_create(valence_state%mos_active(ispin), matrix_struct)
600 36 : CALL cp_fm_to_fm(gs_mos(ispin)%mos_active, valence_state%mos_active(ispin))
601 : END DO
602 : END IF
603 :
604 : ! clean up
605 1416 : CALL cp_fm_release(evects)
606 1416 : CALL cp_fm_release(S_evects)
607 :
608 : CALL cp_print_key_finished_output(log_unit, &
609 : logger, &
610 : tddfpt_print_section, &
611 1416 : "PROGRAM_BANNER")
612 :
613 1416 : DEALLOCATE (evals, ostrength)
614 :
615 1416 : IF (tddfpt_control%kernel == tddfpt_kernel_full) THEN
616 852 : IF (do_admm) CALL release_kernel_env(kernel_env%admm_kernel)
617 852 : IF (tddfpt_control%do_lrigpw) THEN
618 10 : CALL lri_env_release(kernel_env%full_kernel%lri_env)
619 10 : DEALLOCATE (kernel_env%full_kernel%lri_env)
620 10 : CALL lri_density_release(kernel_env%full_kernel%lri_density)
621 10 : DEALLOCATE (kernel_env%full_kernel%lri_density)
622 : END IF
623 852 : CALL release_kernel_env(kernel_env%full_kernel)
624 564 : ELSE IF (tddfpt_control%kernel == tddfpt_kernel_stda) THEN
625 440 : CALL deallocate_stda_env(stda_kernel)
626 124 : ELSE IF (tddfpt_control%kernel == tddfpt_kernel_none) THEN
627 : !
628 : ELSE
629 0 : CPABORT('Unknown kernel type')
630 : END IF
631 1416 : CALL tddfpt_release_work_matrices(work_matrices, sub_env)
632 1416 : CALL tddfpt_sub_env_release(sub_env)
633 :
634 1416 : CALL cp_fm_release(dipole_op_mos_occ)
635 :
636 3026 : DO ispin = nspins, 1, -1
637 3026 : CALL tddfpt_release_ground_state_mos(gs_mos(ispin))
638 : END DO
639 1416 : DEALLOCATE (gs_mos)
640 :
641 1416 : IF (ASSOCIATED(matrix_ks_oep)) THEN
642 32 : CALL dbcsr_deallocate_matrix_set(matrix_ks_oep)
643 : END IF
644 :
645 1416 : CALL timestop(handle)
646 :
647 9968 : END SUBROUTINE tddfpt
648 :
649 : ! **************************************************************************************************
650 : !> \brief TDDFPT input
651 : !> \param qs_env Quickstep environment
652 : !> \param tddfpt_section ...
653 : !> \param tddfpt_control ...
654 : !> \param do_hfx ...
655 : !> \param do_admm ...
656 : !> \param do_exck ...
657 : !> \param do_hfxsr ...
658 : !> \param do_hfxlr ...
659 : !> \param xc_section ...
660 : !> \param tddfpt_print_section ...
661 : !> \param lri_section ...
662 : !> \param hfxsr_section ...
663 : ! **************************************************************************************************
664 1424 : SUBROUTINE tddfpt_input(qs_env, tddfpt_section, tddfpt_control, do_hfx, do_admm, do_exck, &
665 : do_hfxsr, do_hfxlr, xc_section, tddfpt_print_section, lri_section, &
666 : hfxsr_section)
667 : TYPE(qs_environment_type), POINTER :: qs_env
668 : TYPE(section_vals_type), POINTER :: tddfpt_section
669 : TYPE(tddfpt2_control_type), POINTER :: tddfpt_control
670 : LOGICAL, INTENT(INOUT) :: do_hfx, do_admm, do_exck, do_hfxsr, &
671 : do_hfxlr
672 : TYPE(section_vals_type), POINTER :: xc_section, tddfpt_print_section, &
673 : lri_section, hfxsr_section
674 :
675 : CHARACTER(len=20) :: nstates_str
676 : LOGICAL :: exar, exf, exgcp, exhf, exhfxk, exk, &
677 : explicit, explicit_root, expot, exvdw, &
678 : exwfn, found, same_hfx, use_real_wfn
679 : REAL(kind=dp) :: C_hf
680 : TYPE(dft_control_type), POINTER :: dft_control
681 : TYPE(kpoint_type), POINTER :: kpoints
682 : TYPE(section_vals_type), POINTER :: hfx_section, hfx_section_gs, input, &
683 : print_sub, xc_root, xc_sub
684 :
685 1424 : NULLIFY (dft_control, input, kpoints)
686 1424 : CALL get_qs_env(qs_env, dft_control=dft_control, input=input, kpoints=kpoints)
687 :
688 1424 : IF (dft_control%nimages > 1) THEN
689 8 : IF (tddfpt_control%kernel /= tddfpt_kernel_none) THEN
690 0 : CPABORT("TDDFPT with k-points currently supports only KERNEL NONE")
691 : END IF
692 8 : CALL get_kpoint_info(kpoints, use_real_wfn=use_real_wfn)
693 8 : IF (use_real_wfn) THEN
694 0 : CPABORT("K-point TDDFPT requires complex wavefunctions")
695 : END IF
696 8 : IF (tddfpt_control%spinflip /= no_sf_tddfpt) THEN
697 0 : CPABORT("Spin-flip TDDFPT is not implemented for k-points")
698 : END IF
699 8 : IF (tddfpt_control%do_smearing) THEN
700 0 : CPABORT("Smeared-occupation TDDFPT is not implemented for k-points")
701 : END IF
702 8 : IF (tddfpt_control%oe_corr /= oe_none) THEN
703 0 : CPABORT("Orbital-energy-corrected TDDFPT is not implemented for k-points")
704 : END IF
705 : IF (tddfpt_control%dipole_form /= 0 .AND. &
706 8 : tddfpt_control%dipole_form /= tddfpt_dipole_velocity .AND. &
707 : tddfpt_control%dipole_form /= tddfpt_dipole_scf_moment) THEN
708 0 : CPABORT("K-point TDDFPT supports only velocity-form or SCF_MOMENT transition dipoles")
709 : END IF
710 : END IF
711 :
712 1424 : IF (tddfpt_control%nstates <= 0) THEN
713 0 : CALL integer_to_string(tddfpt_control%nstates, nstates_str)
714 : CALL cp_warn(__LOCATION__, "TDDFPT calculation was requested for "// &
715 0 : TRIM(nstates_str)//" excited states: nothing to do.")
716 0 : RETURN
717 : END IF
718 :
719 1424 : NULLIFY (tddfpt_print_section)
720 1424 : tddfpt_print_section => section_vals_get_subs_vals(tddfpt_section, "PRINT")
721 :
722 1424 : IF (dft_control%nimages > 1) THEN
723 8 : IF (tddfpt_control%do_exciton_descriptors .OR. &
724 : tddfpt_control%do_directional_exciton_descriptors) THEN
725 0 : CPABORT("Exciton descriptors are not implemented for k-point TDDFPT")
726 : END IF
727 8 : print_sub => section_vals_get_subs_vals(tddfpt_print_section, "NTO_ANALYSIS")
728 8 : CALL section_vals_get(print_sub, explicit=explicit)
729 8 : IF (explicit) CPABORT("NTO analysis is not implemented for k-point TDDFPT")
730 8 : print_sub => section_vals_get_subs_vals(tddfpt_print_section, "NAMD_PRINT")
731 8 : CALL section_vals_get(print_sub, explicit=explicit)
732 8 : IF (explicit) CPABORT("NAMD_PRINT is not implemented for k-point TDDFPT")
733 : END IF
734 :
735 1424 : IF (tddfpt_control%kernel == tddfpt_kernel_full) THEN
736 852 : NULLIFY (xc_root)
737 852 : xc_root => section_vals_get_subs_vals(tddfpt_section, "XC")
738 852 : CALL section_vals_get(xc_root, explicit=explicit_root)
739 852 : NULLIFY (xc_section)
740 852 : IF (explicit_root) THEN
741 : ! No ADIABATIC_RESCALING option possible
742 504 : NULLIFY (xc_sub)
743 504 : xc_sub => section_vals_get_subs_vals(xc_root, "ADIABATIC_RESCALING")
744 504 : CALL section_vals_get(xc_sub, explicit=exar)
745 504 : IF (exar) THEN
746 0 : CALL cp_warn(__LOCATION__, "TDDFPT Kernel with ADIABATIC_RESCALING not possible.")
747 0 : CPABORT("TDDFPT Input")
748 : END IF
749 : ! No GCP_POTENTIAL option possible
750 504 : NULLIFY (xc_sub)
751 504 : xc_sub => section_vals_get_subs_vals(xc_root, "GCP_POTENTIAL")
752 504 : CALL section_vals_get(xc_sub, explicit=exgcp)
753 504 : IF (exgcp) THEN
754 0 : CALL cp_warn(__LOCATION__, "TDDFPT Kernel with GCP_POTENTIAL not possible.")
755 0 : CPABORT("TDDFPT Input")
756 : END IF
757 : ! No VDW_POTENTIAL option possible
758 504 : NULLIFY (xc_sub)
759 504 : xc_sub => section_vals_get_subs_vals(xc_root, "VDW_POTENTIAL")
760 504 : CALL section_vals_get(xc_sub, explicit=exvdw)
761 504 : IF (exvdw) THEN
762 0 : CALL cp_warn(__LOCATION__, "TDDFPT Kernel with VDW_POTENTIAL not possible.")
763 0 : CPABORT("TDDFPT Input")
764 : END IF
765 : ! No WF_CORRELATION option possible
766 504 : NULLIFY (xc_sub)
767 504 : xc_sub => section_vals_get_subs_vals(xc_root, "WF_CORRELATION")
768 504 : CALL section_vals_get(xc_sub, explicit=exwfn)
769 504 : IF (exwfn) THEN
770 0 : CALL cp_warn(__LOCATION__, "TDDFPT Kernel with WF_CORRELATION not possible.")
771 0 : CPABORT("TDDFPT Input")
772 : END IF
773 : ! No XC_POTENTIAL option possible
774 504 : NULLIFY (xc_sub)
775 504 : xc_sub => section_vals_get_subs_vals(xc_root, "XC_POTENTIAL")
776 504 : CALL section_vals_get(xc_sub, explicit=expot)
777 504 : IF (expot) THEN
778 0 : CALL cp_warn(__LOCATION__, "TDDFPT Kernel with XC_POTENTIAL not possible.")
779 0 : CPABORT("TDDFPT Input")
780 : END IF
781 : !
782 504 : NULLIFY (xc_sub)
783 504 : xc_sub => section_vals_get_subs_vals(xc_root, "XC_FUNCTIONAL")
784 504 : CALL section_vals_get(xc_sub, explicit=exf)
785 504 : NULLIFY (xc_sub)
786 504 : xc_sub => section_vals_get_subs_vals(xc_root, "XC_KERNEL")
787 504 : CALL section_vals_get(xc_sub, explicit=exk)
788 504 : IF ((exf .AND. exk) .OR. .NOT. (exf .OR. exk)) THEN
789 0 : CALL cp_warn(__LOCATION__, "TDDFPT Kernel needs XC_FUNCTIONAL or XC_KERNEL section.")
790 0 : CPABORT("TDDFPT Input")
791 : END IF
792 504 : NULLIFY (xc_sub)
793 504 : xc_sub => section_vals_get_subs_vals(xc_root, "HF")
794 504 : CALL section_vals_get(xc_sub, explicit=exhf)
795 504 : NULLIFY (xc_sub)
796 504 : xc_sub => section_vals_get_subs_vals(xc_root, "HFX_KERNEL")
797 504 : CALL section_vals_get(xc_sub, explicit=exhfxk)
798 : !
799 504 : xc_section => xc_root
800 504 : hfx_section => section_vals_get_subs_vals(xc_section, "HF")
801 504 : CALL section_vals_get(hfx_section, explicit=do_hfx)
802 504 : IF (do_hfx) THEN
803 24 : CALL section_vals_val_get(hfx_section, "FRACTION", r_val=C_hf)
804 24 : do_hfx = (C_hf /= 0.0_dp)
805 : END IF
806 : !TDDFPT only works if the kernel has the same HF section as the DFT%XC one
807 504 : IF (do_hfx) THEN
808 24 : hfx_section_gs => section_vals_get_subs_vals(input, "DFT%XC%HF")
809 24 : CALL compare_hfx_sections(hfx_section, hfx_section_gs, same_hfx)
810 24 : IF (.NOT. same_hfx) THEN
811 0 : CPABORT("TDDFPT Kernel must use the same HF section as DFT%XC or no HF at all.")
812 : END IF
813 : END IF
814 :
815 504 : do_admm = do_hfx .AND. dft_control%do_admm
816 504 : IF (do_admm) THEN
817 : ! 'admm_env%xc_section_primary' and 'admm_env%xc_section_aux' need to be redefined
818 : CALL cp_abort(__LOCATION__, &
819 : "ADMM is not implemented for a TDDFT kernel XC-functional which is different from "// &
820 0 : "the one used for the ground-state calculation. A ground-state 'admm_env' cannot be reused.")
821 : END IF
822 : ! SET HFX_KERNEL and/or XC_KERNEL
823 504 : IF (exk) THEN
824 12 : do_exck = .TRUE.
825 : ELSE
826 492 : do_exck = .FALSE.
827 : END IF
828 504 : IF (exhfxk) THEN
829 6 : xc_sub => section_vals_get_subs_vals(xc_root, "HFX_KERNEL")
830 6 : CALL section_vals_val_get(xc_sub, "DO_HFXSR", l_val=do_hfxsr)
831 6 : xc_sub => section_vals_get_subs_vals(xc_root, "HFX_KERNEL%HFXLR")
832 6 : CALL section_vals_get(xc_sub, explicit=do_hfxlr)
833 : ELSE
834 498 : do_hfxsr = .FALSE.
835 498 : do_hfxlr = .FALSE.
836 : END IF
837 : ELSE
838 348 : xc_section => section_vals_get_subs_vals(input, "DFT%XC")
839 348 : hfx_section => section_vals_get_subs_vals(xc_section, "HF")
840 348 : CALL section_vals_get(hfx_section, explicit=do_hfx)
841 348 : IF (do_hfx) THEN
842 274 : CALL section_vals_val_get(hfx_section, "FRACTION", r_val=C_hf)
843 274 : do_hfx = (C_hf /= 0.0_dp)
844 : END IF
845 348 : do_admm = do_hfx .AND. dft_control%do_admm
846 348 : do_exck = .FALSE.
847 348 : do_hfxsr = .FALSE.
848 348 : do_hfxlr = .FALSE.
849 : END IF
850 : ELSE
851 572 : do_hfx = .FALSE.
852 572 : do_admm = .FALSE.
853 572 : do_exck = .FALSE.
854 572 : do_hfxsr = .FALSE.
855 572 : do_hfxlr = .FALSE.
856 : END IF
857 :
858 : ! reset rks_triplets if UKS is in use
859 1424 : IF (tddfpt_control%rks_triplets .AND. dft_control%nspins > 1) THEN
860 10 : tddfpt_control%rks_triplets = .FALSE.
861 10 : CALL cp_warn(__LOCATION__, "Keyword RKS_TRIPLETS has been ignored for spin-polarised calculations")
862 : END IF
863 :
864 : ! lri input
865 1424 : IF (tddfpt_control%do_lrigpw) THEN
866 10 : lri_section => section_vals_get_subs_vals(tddfpt_section, "LRIGPW")
867 : END IF
868 :
869 : ! set defaults for short range HFX
870 1424 : NULLIFY (hfxsr_section)
871 1424 : IF (do_hfxsr) THEN
872 4 : hfxsr_section => section_vals_get_subs_vals(tddfpt_section, "XC%HFX_KERNEL%HF")
873 4 : CALL section_vals_get(hfxsr_section, explicit=found)
874 4 : IF (.NOT. found) THEN
875 0 : CPABORT("HFXSR option needs &HF section defined")
876 : END IF
877 4 : CALL section_vals_val_get(hfxsr_section, "INTERACTION_POTENTIAL%POTENTIAL_TYPE", explicit=found)
878 4 : IF (.NOT. found) THEN
879 : CALL section_vals_val_set(hfxsr_section, "INTERACTION_POTENTIAL%POTENTIAL_TYPE", &
880 4 : i_val=do_potential_truncated)
881 : END IF
882 4 : CALL section_vals_val_get(hfxsr_section, "INTERACTION_POTENTIAL%CUTOFF_RADIUS", explicit=found)
883 4 : IF (.NOT. found) THEN
884 4 : CALL section_vals_val_set(hfxsr_section, "INTERACTION_POTENTIAL%CUTOFF_RADIUS", r_val=7.5589_dp)
885 : END IF
886 4 : CALL section_vals_val_get(hfxsr_section, "RI%_SECTION_PARAMETERS_", l_val=found)
887 4 : IF (found) THEN
888 0 : CALL cp_abort(__LOCATION__, "Short range TDA kernel with RI not possible")
889 : END IF
890 : END IF
891 :
892 : END SUBROUTINE tddfpt_input
893 :
894 : ! **************************************************************************************************
895 : !> \brief ...
896 : !> \param log_unit ...
897 : !> \param dft_control ...
898 : !> \param tddfpt_control ...
899 : !> \param xc_section ...
900 : ! **************************************************************************************************
901 1424 : SUBROUTINE kernel_info(log_unit, dft_control, tddfpt_control, xc_section)
902 : INTEGER, INTENT(IN) :: log_unit
903 : TYPE(dft_control_type), POINTER :: dft_control
904 : TYPE(tddfpt2_control_type), POINTER :: tddfpt_control
905 : TYPE(section_vals_type), POINTER :: xc_section
906 :
907 : CHARACTER(LEN=4) :: ktype
908 : LOGICAL :: lsd
909 :
910 1424 : lsd = (dft_control%nspins > 1)
911 1424 : IF (tddfpt_control%kernel == tddfpt_kernel_full) THEN
912 852 : ktype = "FULL"
913 852 : IF (log_unit > 0) THEN
914 426 : WRITE (log_unit, "(T2,A,T77,A4)") "KERNEL|", TRIM(ktype)
915 426 : CALL xc_write(log_unit, xc_section, lsd)
916 426 : IF (tddfpt_control%do_hfx) THEN
917 149 : IF (tddfpt_control%do_admm) THEN
918 87 : WRITE (log_unit, "(T2,A,T62,A19)") "KERNEL|", "ADMM Exact Exchange"
919 87 : IF (tddfpt_control%admm_xc_correction) THEN
920 67 : WRITE (log_unit, "(T2,A,T60,A21)") "KERNEL|", "Apply ADMM Kernel XC Correction"
921 : END IF
922 87 : IF (tddfpt_control%admm_symm) THEN
923 87 : WRITE (log_unit, "(T2,A,T60,A21)") "KERNEL|", "Symmetric ADMM Kernel"
924 : END IF
925 : ELSE
926 62 : WRITE (log_unit, "(T2,A,T67,A14)") "KERNEL|", "Exact Exchange"
927 : END IF
928 : END IF
929 426 : IF (tddfpt_control%do_hfxsr) THEN
930 2 : WRITE (log_unit, "(T2,A,T43,A38)") "KERNEL|", "Short range HFX approximation"
931 : END IF
932 426 : IF (tddfpt_control%do_hfxlr) THEN
933 3 : WRITE (log_unit, "(T2,A,T43,A38)") "KERNEL|", "Long range HFX approximation"
934 : END IF
935 426 : IF (tddfpt_control%do_lrigpw) THEN
936 5 : WRITE (log_unit, "(T2,A,T42,A39)") "KERNEL|", "LRI approximation of transition density"
937 : END IF
938 : END IF
939 572 : ELSE IF (tddfpt_control%kernel == tddfpt_kernel_stda) THEN
940 440 : ktype = "sTDA"
941 440 : IF (log_unit > 0) THEN
942 220 : WRITE (log_unit, "(T2,A,T77,A4)") "KERNEL|", TRIM(ktype)
943 220 : IF (tddfpt_control%stda_control%do_ewald) THEN
944 53 : WRITE (log_unit, "(T2,A,T78,A3)") "KERNEL| Coulomb term uses Ewald summation"
945 : ELSE
946 167 : WRITE (log_unit, "(T2,A,T78,A3)") "KERNEL| Coulomb term uses direct summation (MIC)"
947 : END IF
948 220 : IF (tddfpt_control%stda_control%do_exchange) THEN
949 204 : WRITE (log_unit, "(T2,A,T78,A3)") "KERNEL| Exact exchange term", "YES"
950 204 : WRITE (log_unit, "(T2,A,T71,F10.3)") "KERNEL| Short range HFX fraction:", &
951 408 : tddfpt_control%stda_control%hfx_fraction
952 : ELSE
953 16 : WRITE (log_unit, "(T2,A,T79,A2)") "KERNEL| Exact exchange term", "NO"
954 : END IF
955 220 : WRITE (log_unit, "(T2,A,T66,E15.3)") "KERNEL| Transition density filter", &
956 440 : tddfpt_control%stda_control%eps_td_filter
957 : END IF
958 132 : ELSE IF (tddfpt_control%kernel == tddfpt_kernel_none) THEN
959 132 : ktype = "NONE"
960 132 : IF (log_unit > 0) THEN
961 66 : WRITE (log_unit, "(T2,A,T77,A4)") "KERNEL|", TRIM(ktype)
962 : END IF
963 : ELSE
964 : !CPABORT("Unknown kernel")
965 : END IF
966 : !
967 1424 : IF (log_unit > 0) THEN
968 712 : IF (tddfpt_control%rks_triplets) THEN
969 102 : WRITE (log_unit, "(T2,A,T74,A7)") "KERNEL| Spin symmetry of excitations", "Triplet"
970 610 : ELSE IF (lsd) THEN
971 : ! Spin-conserving excitations where requested
972 97 : IF (tddfpt_control%spinflip == no_sf_tddfpt) THEN
973 86 : WRITE (log_unit, "(T2,A,T69,A12)") "KERNEL| Spin symmetry of excitations", "Unrestricted"
974 : ! Spin-flip excitations with collinear exchange-correlation kernel requested
975 11 : ELSE IF (tddfpt_control%spinflip == tddfpt_sf_col) THEN
976 5 : WRITE (log_unit, "(T2,A,T72,A9)") "KERNEL| Spin flip", "Collinear"
977 : ! Spin-flip excitations with noncollinear exchange-correlation kernel requested
978 6 : ELSE IF (tddfpt_control%spinflip == tddfpt_sf_noncol) THEN
979 6 : WRITE (log_unit, "(T2,A,T69,A12)") "KERNEL| Spin flip", "Noncollinear"
980 : END IF
981 : ELSE
982 513 : WRITE (log_unit, "(T2,A,T74,A7)") "KERNEL| Spin symmetry of excitations", "Singlet"
983 : END IF
984 712 : WRITE (log_unit, "(T2,A,T73,I8)") "TDDFPT| Number of states calculated", tddfpt_control%nstates
985 712 : WRITE (log_unit, "(T2,A,T73,I8)") "TDDFPT| Number of Davidson iterations", tddfpt_control%niters
986 712 : WRITE (log_unit, "(T2,A,T66,E15.3)") "TDDFPT| Davidson iteration convergence", tddfpt_control%conv
987 712 : WRITE (log_unit, "(T2,A,T73,I8)") "TDDFPT| Max. number of Krylov space vectors", tddfpt_control%nkvs
988 : END IF
989 :
990 1424 : END SUBROUTINE kernel_info
991 :
992 : ! **************************************************************************************************
993 : !> \brief Print independent-particle vertical transitions for k-point calculations.
994 : !> \param qs_env ...
995 : !> \param logger ...
996 : !> \param tddfpt_control ...
997 : ! **************************************************************************************************
998 8 : SUBROUTINE tddfpt_kpoint_independent_particle(qs_env, logger, tddfpt_control)
999 : TYPE(qs_environment_type), POINTER :: qs_env
1000 : TYPE(cp_logger_type), POINTER :: logger
1001 : TYPE(tddfpt2_control_type), POINTER :: tddfpt_control
1002 :
1003 : CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_kpoint_independent_particle'
1004 :
1005 : COMPLEX(KIND=dp), ALLOCATABLE, &
1006 8 : DIMENSION(:, :, :, :, :) :: kpoint_dipole
1007 : INTEGER :: handle, ideriv, ikp, ikp_local, iocc, ispin, istate, itrans, ivirt, log_unit, &
1008 : nao, nkp, nkp_local, nspins, nstates, ntrans_kpoint, ntrans_spin, ntrans_total, &
1009 : spin_offset, trans_index
1010 8 : INTEGER, ALLOCATABLE, DIMENSION(:) :: inds
1011 : INTEGER, DIMENSION(2) :: kp_range
1012 8 : INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index
1013 : INTEGER, DIMENSION(maxspins) :: homo_spin, nao_spin, nmo_spin, nvirt_spin
1014 : LOGICAL :: my_kpgrp, use_scf_moment_dipoles
1015 : REAL(kind=dp) :: checksum, dipole_im, dipole_re, fsum, &
1016 : gap, oscillator_factor, spin_factor
1017 8 : REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: eigenvalues_kp, evals, &
1018 8 : oscillator_strength, transition_energy
1019 8 : REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: transition_dipole_im, &
1020 8 : transition_dipole_re
1021 8 : REAL(kind=dp), DIMENSION(:), POINTER :: eigenvalues, wkp
1022 : REAL(kind=dp), DIMENSION(nderivs) :: transition_dipole_abs
1023 : TYPE(cp_blacs_env_type), POINTER :: blacs_env, blacs_env_all
1024 : TYPE(cp_fm_struct_type), POINTER :: fm_struct, moment_struct
1025 : TYPE(cp_fm_type) :: fm_dummy, fm_tmp, mo_coeff_im_global, &
1026 : mo_coeff_re_global, moment_im, &
1027 : moment_re
1028 : TYPE(cp_fm_type), POINTER :: mo_coeff_im, mo_coeff_re
1029 8 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: overlap_deriv
1030 : TYPE(dbcsr_type), POINTER :: cmatrix, rmatrix
1031 : TYPE(dft_control_type), POINTER :: dft_control
1032 8 : TYPE(kpoint_env_p_type), DIMENSION(:), POINTER :: kp_env
1033 : TYPE(kpoint_env_type), POINTER :: kp
1034 : TYPE(kpoint_type), POINTER :: kpoints
1035 8 : TYPE(mo_set_type), DIMENSION(:, :), POINTER :: mos_kp
1036 : TYPE(mp_para_env_type), POINTER :: para_env, para_env_inter_kp, para_env_kp
1037 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
1038 8 : POINTER :: sab_kp, sab_orb
1039 : TYPE(qs_ks_env_type), POINTER :: ks_env
1040 :
1041 8 : CALL timeset(routineN, handle)
1042 :
1043 8 : NULLIFY (blacs_env, blacs_env_all, cell_to_index, cmatrix, dft_control, eigenvalues, &
1044 8 : fm_struct, kp, kp_env, kpoints, ks_env, mo_coeff_im, mo_coeff_re, &
1045 8 : moment_struct, mos_kp, overlap_deriv, para_env, para_env_inter_kp, para_env_kp, &
1046 8 : rmatrix, sab_kp, sab_orb, wkp)
1047 : CALL get_qs_env(qs_env, dft_control=dft_control, kpoints=kpoints, ks_env=ks_env, &
1048 8 : sab_orb=sab_orb)
1049 8 : CPASSERT(ASSOCIATED(kpoints))
1050 :
1051 : CALL get_kpoint_info(kpoints, nkp=nkp, kp_range=kp_range, kp_env=kp_env, &
1052 : para_env=para_env, blacs_env_all=blacs_env_all, &
1053 : para_env_inter_kp=para_env_inter_kp, para_env_kp=para_env_kp, &
1054 : blacs_env=blacs_env, wkp=wkp, cell_to_index=cell_to_index, &
1055 8 : sab_nl=sab_kp)
1056 8 : CPASSERT(ASSOCIATED(para_env))
1057 8 : CPASSERT(ASSOCIATED(para_env_inter_kp))
1058 8 : CPASSERT(ASSOCIATED(para_env_kp))
1059 8 : CPASSERT(ASSOCIATED(blacs_env_all))
1060 8 : CPASSERT(ASSOCIATED(blacs_env))
1061 8 : CPASSERT(ASSOCIATED(kp_env))
1062 8 : CPASSERT(ASSOCIATED(ks_env))
1063 8 : CPASSERT(ASSOCIATED(sab_orb))
1064 8 : CPASSERT(ASSOCIATED(sab_kp))
1065 8 : CPASSERT(ASSOCIATED(cell_to_index))
1066 :
1067 8 : nspins = dft_control%nspins
1068 8 : nmo_spin = 0
1069 8 : homo_spin = 0
1070 8 : nao_spin = 0
1071 8 : nkp_local = MAX(0, kp_range(2) - kp_range(1) + 1)
1072 8 : IF (nkp_local > 0) THEN
1073 8 : kp => kp_env(1)%kpoint_env
1074 8 : mos_kp => kp%mos
1075 8 : CPASSERT(ASSOCIATED(mos_kp))
1076 8 : CPASSERT(SIZE(mos_kp, 2) == nspins)
1077 16 : DO ispin = 1, nspins
1078 : CALL get_mo_set(mos_kp(1, ispin), nmo=nmo_spin(ispin), homo=homo_spin(ispin), &
1079 16 : nao=nao_spin(ispin))
1080 : END DO
1081 : END IF
1082 8 : CALL para_env%max(nmo_spin)
1083 8 : CALL para_env%max(homo_spin)
1084 8 : CALL para_env%max(nao_spin)
1085 :
1086 8 : ntrans_kpoint = 0
1087 16 : DO ispin = 1, nspins
1088 8 : nvirt_spin(ispin) = nmo_spin(ispin) - homo_spin(ispin)
1089 8 : IF (homo_spin(ispin) <= 0 .OR. nvirt_spin(ispin) <= 0) THEN
1090 0 : CPABORT("At least one occupied and one unoccupied MO are required for k-point TDDFPT")
1091 : END IF
1092 16 : ntrans_kpoint = ntrans_kpoint + homo_spin(ispin)*nvirt_spin(ispin)
1093 : END DO
1094 8 : ntrans_total = nkp*ntrans_kpoint
1095 8 : IF (ntrans_total <= 0) THEN
1096 0 : CPABORT("No independent-particle k-point transitions available")
1097 : END IF
1098 :
1099 : ALLOCATE (transition_energy(ntrans_total), transition_dipole_re(ntrans_total, nderivs), &
1100 : transition_dipole_im(ntrans_total, nderivs), oscillator_strength(ntrans_total), &
1101 72 : inds(ntrans_total))
1102 8 : transition_energy = 0.0_dp
1103 8 : transition_dipole_re = 0.0_dp
1104 8 : transition_dipole_im = 0.0_dp
1105 8 : oscillator_strength = 0.0_dp
1106 8 : use_scf_moment_dipoles = (tddfpt_control%dipole_form == tddfpt_dipole_scf_moment)
1107 8 : IF (use_scf_moment_dipoles) THEN
1108 : CALL cp_warn(__LOCATION__, "SCF_MOMENT k-point dipoles use direct SCF MO matrix "// &
1109 2 : "elements; compare folded energy blocks, not individual degenerate states.")
1110 2 : CALL qs_moment_kpoints_scf_mos(qs_env, kpoint_dipole)
1111 : END IF
1112 :
1113 : IF (.NOT. use_scf_moment_dipoles) THEN
1114 : CALL build_overlap_matrix(ks_env, matrixkp_s=overlap_deriv, nderivative=1, &
1115 : basis_type_a="ORB", basis_type_b="ORB", sab_nl=sab_orb, &
1116 6 : ext_kpoints=kpoints)
1117 :
1118 6 : ALLOCATE (rmatrix, cmatrix)
1119 : CALL dbcsr_create(rmatrix, template=overlap_deriv(1, 1)%matrix, &
1120 6 : matrix_type=dbcsr_type_symmetric)
1121 : CALL dbcsr_create(cmatrix, template=overlap_deriv(1, 1)%matrix, &
1122 6 : matrix_type=dbcsr_type_antisymmetric)
1123 6 : CALL cp_dbcsr_alloc_block_from_nbl(rmatrix, sab_kp)
1124 6 : CALL cp_dbcsr_alloc_block_from_nbl(cmatrix, sab_kp)
1125 : END IF
1126 :
1127 22 : DO ikp = 1, nkp
1128 14 : my_kpgrp = (ikp >= kp_range(1) .AND. ikp <= kp_range(2))
1129 : IF (my_kpgrp) THEN
1130 8 : ikp_local = ikp - kp_range(1) + 1
1131 8 : kp => kp_env(ikp_local)%kpoint_env
1132 8 : mos_kp => kp%mos
1133 : ELSE
1134 14 : NULLIFY (kp, mos_kp)
1135 : END IF
1136 14 : spin_offset = 0
1137 36 : DO ispin = 1, nspins
1138 14 : nao = nao_spin(ispin)
1139 42 : ALLOCATE (eigenvalues_kp(nmo_spin(ispin)))
1140 14 : eigenvalues_kp = 0.0_dp
1141 :
1142 14 : IF (.NOT. use_scf_moment_dipoles) THEN
1143 : CALL cp_fm_struct_create(fm_struct, nrow_global=nao, ncol_global=nmo_spin(ispin), &
1144 10 : para_env=para_env, context=blacs_env_all)
1145 10 : CALL cp_fm_create(mo_coeff_re_global, fm_struct)
1146 10 : CALL cp_fm_create(mo_coeff_im_global, fm_struct)
1147 10 : CALL cp_fm_create(fm_tmp, fm_struct)
1148 10 : CALL cp_fm_struct_release(fm_struct)
1149 : CALL cp_fm_struct_create(moment_struct, nrow_global=nmo_spin(ispin), &
1150 : ncol_global=nmo_spin(ispin), para_env=para_env, &
1151 10 : context=blacs_env_all)
1152 10 : CALL cp_fm_create(moment_re, moment_struct)
1153 10 : CALL cp_fm_create(moment_im, moment_struct)
1154 10 : CALL cp_fm_struct_release(moment_struct)
1155 : END IF
1156 :
1157 14 : IF (my_kpgrp) THEN
1158 8 : CALL get_mo_set(mos_kp(1, ispin), eigenvalues=eigenvalues)
1159 8 : CPASSERT(ASSOCIATED(eigenvalues))
1160 8 : IF (para_env_kp%is_source()) THEN
1161 42 : eigenvalues_kp(1:nmo_spin(ispin)) = eigenvalues(1:nmo_spin(ispin))
1162 : END IF
1163 8 : IF (.NOT. use_scf_moment_dipoles) THEN
1164 6 : CALL get_mo_set(mos_kp(1, ispin), mo_coeff=mo_coeff_re)
1165 6 : CALL get_mo_set(mos_kp(2, ispin), mo_coeff=mo_coeff_im)
1166 6 : CPASSERT(ASSOCIATED(mo_coeff_re))
1167 6 : CPASSERT(ASSOCIATED(mo_coeff_im))
1168 6 : CALL cp_fm_copy_general(mo_coeff_re, mo_coeff_re_global, para_env)
1169 6 : CALL cp_fm_copy_general(mo_coeff_im, mo_coeff_im_global, para_env)
1170 : END IF
1171 6 : ELSE IF (.NOT. use_scf_moment_dipoles) THEN
1172 4 : CALL cp_fm_copy_general(fm_dummy, mo_coeff_re_global, para_env)
1173 4 : CALL cp_fm_copy_general(fm_dummy, mo_coeff_im_global, para_env)
1174 : END IF
1175 14 : CALL para_env%sum(eigenvalues_kp)
1176 :
1177 14 : spin_factor = 1.0_dp
1178 14 : IF (nspins == 1) THEN
1179 14 : IF (tddfpt_control%rks_triplets) THEN
1180 : spin_factor = 0.0_dp
1181 : ELSE
1182 14 : spin_factor = 2.0_dp
1183 : END IF
1184 : END IF
1185 :
1186 56 : DO ideriv = 1, nderivs
1187 42 : IF (.NOT. use_scf_moment_dipoles) THEN
1188 30 : CALL dbcsr_set(rmatrix, 0.0_dp)
1189 30 : CALL dbcsr_set(cmatrix, 0.0_dp)
1190 : CALL rskp_transform(rmatrix=rmatrix, cmatrix=cmatrix, rsmat=overlap_deriv, &
1191 : ispin=ideriv + 1, xkp=kpoints%xkp(:, ikp), &
1192 30 : cell_to_index=cell_to_index, sab_nl=sab_kp)
1193 :
1194 30 : CALL cp_dbcsr_sm_fm_multiply(rmatrix, mo_coeff_re_global, fm_tmp, nmo_spin(ispin))
1195 : CALL parallel_gemm("T", "N", nmo_spin(ispin), nmo_spin(ispin), nao, &
1196 30 : 1.0_dp, mo_coeff_re_global, fm_tmp, 0.0_dp, moment_re)
1197 : CALL parallel_gemm("T", "N", nmo_spin(ispin), nmo_spin(ispin), nao, &
1198 30 : 1.0_dp, mo_coeff_im_global, fm_tmp, 0.0_dp, moment_im)
1199 :
1200 30 : CALL cp_dbcsr_sm_fm_multiply(rmatrix, mo_coeff_im_global, fm_tmp, nmo_spin(ispin))
1201 : CALL parallel_gemm("T", "N", nmo_spin(ispin), nmo_spin(ispin), nao, &
1202 30 : 1.0_dp, mo_coeff_re_global, fm_tmp, 1.0_dp, moment_im)
1203 : CALL parallel_gemm("T", "N", nmo_spin(ispin), nmo_spin(ispin), nao, &
1204 30 : -1.0_dp, mo_coeff_im_global, fm_tmp, 1.0_dp, moment_re)
1205 :
1206 30 : CALL cp_dbcsr_sm_fm_multiply(cmatrix, mo_coeff_re_global, fm_tmp, nmo_spin(ispin))
1207 : CALL parallel_gemm("T", "N", nmo_spin(ispin), nmo_spin(ispin), nao, &
1208 30 : 1.0_dp, mo_coeff_re_global, fm_tmp, 1.0_dp, moment_im)
1209 : CALL parallel_gemm("T", "N", nmo_spin(ispin), nmo_spin(ispin), nao, &
1210 30 : -1.0_dp, mo_coeff_im_global, fm_tmp, 1.0_dp, moment_re)
1211 :
1212 30 : CALL cp_dbcsr_sm_fm_multiply(cmatrix, mo_coeff_im_global, fm_tmp, nmo_spin(ispin))
1213 : CALL parallel_gemm("T", "N", nmo_spin(ispin), nmo_spin(ispin), nao, &
1214 30 : -1.0_dp, mo_coeff_re_global, fm_tmp, 1.0_dp, moment_re)
1215 : CALL parallel_gemm("T", "N", nmo_spin(ispin), nmo_spin(ispin), nao, &
1216 30 : -1.0_dp, mo_coeff_im_global, fm_tmp, 1.0_dp, moment_im)
1217 : END IF
1218 :
1219 98 : DO iocc = 1, homo_spin(ispin)
1220 252 : DO ivirt = homo_spin(ispin) + 1, nmo_spin(ispin)
1221 : trans_index = (ikp - 1)*ntrans_kpoint + spin_offset + &
1222 168 : (iocc - 1)*nvirt_spin(ispin) + ivirt - homo_spin(ispin)
1223 168 : gap = eigenvalues_kp(ivirt) - eigenvalues_kp(iocc)
1224 168 : IF (gap <= 0.0_dp) THEN
1225 0 : CPABORT("K-point TDDFPT requires positive occupied-virtual energy gaps")
1226 : END IF
1227 168 : IF (use_scf_moment_dipoles) THEN
1228 48 : oscillator_factor = SQRT(spin_factor*wkp(ikp))
1229 48 : dipole_re = REAL(kpoint_dipole(ispin, ikp, ideriv, iocc, ivirt), KIND=dp)
1230 48 : dipole_im = AIMAG(kpoint_dipole(ispin, ikp, ideriv, iocc, ivirt))
1231 : ELSE
1232 120 : oscillator_factor = SQRT(spin_factor*wkp(ikp))/gap
1233 120 : CALL cp_fm_get_element(moment_re, ivirt, iocc, dipole_re)
1234 120 : CALL cp_fm_get_element(moment_im, ivirt, iocc, dipole_im)
1235 : END IF
1236 168 : transition_dipole_re(trans_index, ideriv) = oscillator_factor*dipole_re
1237 210 : transition_dipole_im(trans_index, ideriv) = oscillator_factor*dipole_im
1238 : END DO
1239 : END DO
1240 : END DO
1241 :
1242 28 : DO iocc = 1, homo_spin(ispin)
1243 84 : DO ivirt = homo_spin(ispin) + 1, nmo_spin(ispin)
1244 : trans_index = (ikp - 1)*ntrans_kpoint + spin_offset + &
1245 56 : (iocc - 1)*nvirt_spin(ispin) + ivirt - homo_spin(ispin)
1246 56 : transition_energy(trans_index) = eigenvalues_kp(ivirt) - eigenvalues_kp(iocc)
1247 : oscillator_strength(trans_index) = 2.0_dp/3.0_dp*transition_energy(trans_index)* &
1248 : SUM(transition_dipole_re(trans_index, :)**2 + &
1249 238 : transition_dipole_im(trans_index, :)**2)
1250 : END DO
1251 : END DO
1252 14 : IF (.NOT. use_scf_moment_dipoles) THEN
1253 10 : CALL cp_fm_release(moment_im)
1254 10 : CALL cp_fm_release(moment_re)
1255 10 : CALL cp_fm_release(fm_tmp)
1256 10 : CALL cp_fm_release(mo_coeff_im_global)
1257 10 : CALL cp_fm_release(mo_coeff_re_global)
1258 : END IF
1259 14 : DEALLOCATE (eigenvalues_kp)
1260 28 : spin_offset = spin_offset + homo_spin(ispin)*nvirt_spin(ispin)
1261 : END DO
1262 : END DO
1263 :
1264 64 : IF (ANY(transition_energy <= 0.0_dp)) THEN
1265 0 : CPABORT("K-point TDDFPT KERNEL NONE requires positive occupied-virtual energy gaps")
1266 : END IF
1267 :
1268 8 : CALL sort(transition_energy, ntrans_total, inds)
1269 8 : nstates = MIN(tddfpt_control%nstates, ntrans_total)
1270 8 : IF (tddfpt_control%nstates > ntrans_total) THEN
1271 0 : CPWARN("Requested more TDDFPT states than independent-particle k-point transitions")
1272 : END IF
1273 :
1274 24 : ALLOCATE (evals(nstates))
1275 22 : evals(1:nstates) = transition_energy(1:nstates)
1276 22 : checksum = SQRT(SUM(evals**2))
1277 :
1278 8 : log_unit = cp_logger_get_default_io_unit(logger)
1279 8 : IF (log_unit > 0) THEN
1280 4 : WRITE (log_unit, "(1X,A)") "", &
1281 4 : "-------------------------------------------------------------------------------", &
1282 4 : "- TDDFPT K-point Independent-particle Transitions -", &
1283 8 : "-------------------------------------------------------------------------------"
1284 : WRITE (log_unit, "(1X,A)") &
1285 4 : "Only KERNEL NONE is active for k-point TDDFPT; transition dipole magnitudes are shown."
1286 4 : WRITE (log_unit, '(/,T10,A,T19,A,T37,A,T69,A)') "State", "Excitation", &
1287 8 : "Transition dipole (a.u.)", "Oscillator"
1288 4 : WRITE (log_unit, '(T10,A,T19,A,T37,A,T49,A,T61,A,T67,A)') "number", "energy (eV)", &
1289 8 : "x", "y", "z", "strength (a.u.)"
1290 4 : WRITE (log_unit, '(T10,72("-"))')
1291 : END IF
1292 :
1293 8 : fsum = 0.0_dp
1294 22 : DO istate = 1, nstates
1295 14 : itrans = inds(istate) - 1
1296 14 : ikp = itrans/ntrans_kpoint + 1
1297 14 : itrans = MOD(itrans, ntrans_kpoint)
1298 14 : spin_offset = 0
1299 14 : DO ispin = 1, nspins
1300 14 : ntrans_spin = homo_spin(ispin)*nvirt_spin(ispin)
1301 14 : IF (itrans < spin_offset + ntrans_spin) THEN
1302 14 : itrans = itrans - spin_offset
1303 14 : iocc = itrans/nvirt_spin(ispin) + 1
1304 14 : ivirt = MOD(itrans, nvirt_spin(ispin)) + homo_spin(ispin) + 1
1305 14 : EXIT
1306 : END IF
1307 0 : spin_offset = spin_offset + ntrans_spin
1308 : END DO
1309 :
1310 22 : IF (log_unit > 0) THEN
1311 : transition_dipole_abs(1:nderivs) = &
1312 : SQRT(transition_dipole_re(inds(istate), 1:nderivs)**2 + &
1313 28 : transition_dipole_im(inds(istate), 1:nderivs)**2)
1314 : WRITE (log_unit, '(1X,A,T9,I7,T19,F11.5,T31,3(1X,ES11.4E2),T69,ES12.5E2)') &
1315 7 : "TDDFPT|", istate, evals(istate)*evolt, transition_dipole_abs, &
1316 14 : oscillator_strength(inds(istate))
1317 7 : fsum = fsum + oscillator_strength(inds(istate))**2
1318 : WRITE (log_unit, '(1X,A,T18,I7,T28,I7,T38,I7,T50,I7,T62,I7,T74,F10.5)') &
1319 7 : "TDDFPT_KPOINT|", istate, ikp, ispin, iocc, ivirt, wkp(ikp)
1320 : END IF
1321 : END DO
1322 :
1323 8 : IF (log_unit > 0) THEN
1324 4 : WRITE (log_unit, '(/,T2,A,E16.8)') 'TDDFPT : CheckSum E = ', checksum
1325 4 : WRITE (log_unit, '(T2,A,E16.8)') 'TDDFPT : CheckSum F = ', SQRT(fsum)
1326 : WRITE (log_unit, "(1X,A)") &
1327 4 : "-------------------------------------------------------------------------------"
1328 : END IF
1329 :
1330 8 : IF (use_scf_moment_dipoles) THEN
1331 2 : DEALLOCATE (kpoint_dipole)
1332 : ELSE
1333 6 : CALL dbcsr_deallocate_matrix(rmatrix)
1334 6 : CALL dbcsr_deallocate_matrix(cmatrix)
1335 6 : CALL dbcsr_deallocate_matrix_set(overlap_deriv)
1336 : END IF
1337 :
1338 0 : DEALLOCATE (evals, inds, oscillator_strength, transition_dipole_im, transition_dipole_re, &
1339 8 : transition_energy)
1340 :
1341 8 : CALL timestop(handle)
1342 :
1343 16 : END SUBROUTINE tddfpt_kpoint_independent_particle
1344 :
1345 : ! **************************************************************************************************
1346 : !> \brief The energy calculation has been moved to its own subroutine
1347 : !> \param qs_env ...
1348 : !> \param nstates ...
1349 : !> \param nspins ...
1350 : !> \param work_matrices ...
1351 : !> \param tddfpt_control ...
1352 : !> \param logger ...
1353 : !> \param tddfpt_print_section ...
1354 : !> \param evects ...
1355 : !> \param evals ...
1356 : !> \param gs_mos ...
1357 : !> \param tddfpt_section ...
1358 : !> \param S_evects ...
1359 : !> \param matrix_s ...
1360 : !> \param kernel_env ...
1361 : !> \param matrix_ks ...
1362 : !> \param sub_env ...
1363 : !> \param ostrength ...
1364 : !> \param dipole_op_mos_occ ...
1365 : !> \param mult ...
1366 : !> \param xc_section ...
1367 : !> \param full_kernel_env ...
1368 : !> \param kernel_env_admm_aux ...
1369 : ! **************************************************************************************************
1370 1426 : SUBROUTINE tddfpt_energies(qs_env, nstates, nspins, work_matrices, &
1371 : tddfpt_control, logger, tddfpt_print_section, evects, evals, &
1372 : gs_mos, tddfpt_section, S_evects, matrix_s, kernel_env, matrix_ks, &
1373 : sub_env, ostrength, dipole_op_mos_occ, mult, xc_section, full_kernel_env, &
1374 : kernel_env_admm_aux)
1375 :
1376 : TYPE(qs_environment_type), POINTER :: qs_env
1377 : INTEGER :: nstates, nspins
1378 : TYPE(tddfpt_work_matrices) :: work_matrices
1379 : TYPE(tddfpt2_control_type), POINTER :: tddfpt_control
1380 : TYPE(cp_logger_type), POINTER :: logger
1381 : TYPE(section_vals_type), POINTER :: tddfpt_print_section
1382 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: evects
1383 : REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: evals
1384 : TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
1385 : POINTER :: gs_mos
1386 : TYPE(section_vals_type), POINTER :: tddfpt_section
1387 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: S_evects
1388 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_s
1389 : TYPE(kernel_env_type) :: kernel_env
1390 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks
1391 : TYPE(tddfpt_subgroup_env_type) :: sub_env
1392 : REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: ostrength
1393 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: dipole_op_mos_occ
1394 : INTEGER :: mult
1395 : TYPE(section_vals_type), POINTER :: xc_section
1396 : TYPE(full_kernel_env_type), TARGET :: full_kernel_env, kernel_env_admm_aux
1397 :
1398 : CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_energies'
1399 :
1400 : CHARACTER(len=20) :: nstates_str
1401 : INTEGER :: energy_unit, handle, iter, log_unit, &
1402 : niters, nocc, nstate_max, &
1403 : nstates_read, nvirt
1404 : LOGICAL :: do_admm, do_exck, do_soc, explicit
1405 : REAL(kind=dp) :: conv
1406 : TYPE(admm_type), POINTER :: admm_env
1407 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
1408 1426 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks_oep
1409 : TYPE(section_vals_type), POINTER :: lri_section, namd_print_section, &
1410 : soc_section
1411 :
1412 1426 : CALL timeset(routineN, handle)
1413 :
1414 1426 : NULLIFY (admm_env, matrix_ks_oep)
1415 1426 : do_admm = tddfpt_control%do_admm
1416 1426 : IF (do_admm) CALL get_qs_env(qs_env, admm_env=admm_env)
1417 :
1418 : ! setup for full_kernel and admm_kernel within tddfpt_energies due to dependence on multiplicity
1419 1426 : IF (tddfpt_control%kernel == tddfpt_kernel_full) THEN
1420 :
1421 : CALL tddfpt_construct_ground_state_orb_density( &
1422 : rho_orb_struct=work_matrices%rho_orb_struct_sub, &
1423 : rho_xc_struct=work_matrices%rho_xc_struct_sub, &
1424 : is_rks_triplets=tddfpt_control%rks_triplets, &
1425 : qs_env=qs_env, sub_env=sub_env, &
1426 862 : wfm_rho_orb=work_matrices%rho_ao_orb_fm_sub)
1427 :
1428 862 : IF (do_admm) THEN
1429 : ! Full kernel with ADMM
1430 174 : IF (tddfpt_control%admm_xc_correction) THEN
1431 : CALL create_kernel_env(kernel_env=full_kernel_env, &
1432 : rho_struct_sub=work_matrices%rho_orb_struct_sub, &
1433 : xc_section=admm_env%xc_section_primary, &
1434 : is_rks_triplets=tddfpt_control%rks_triplets, &
1435 134 : sub_env=sub_env)
1436 : ELSE
1437 : CALL create_kernel_env(kernel_env=full_kernel_env, &
1438 : rho_struct_sub=work_matrices%rho_orb_struct_sub, &
1439 : xc_section=xc_section, &
1440 : is_rks_triplets=tddfpt_control%rks_triplets, &
1441 40 : sub_env=sub_env)
1442 : END IF
1443 :
1444 : CALL tddfpt_construct_aux_fit_density( &
1445 : rho_orb_struct=work_matrices%rho_orb_struct_sub, &
1446 : rho_aux_fit_struct=work_matrices%rho_aux_fit_struct_sub, &
1447 : local_rho_set=sub_env%local_rho_set_admm, &
1448 : qs_env=qs_env, sub_env=sub_env, &
1449 : wfm_rho_orb=work_matrices%rho_ao_orb_fm_sub, &
1450 : wfm_rho_aux_fit=work_matrices%rho_ao_aux_fit_fm_sub, &
1451 174 : wfm_aux_orb=work_matrices%wfm_aux_orb_sub)
1452 :
1453 : CALL create_kernel_env(kernel_env=kernel_env_admm_aux, &
1454 : rho_struct_sub=work_matrices%rho_aux_fit_struct_sub, &
1455 : xc_section=admm_env%xc_section_aux, &
1456 : is_rks_triplets=tddfpt_control%rks_triplets, &
1457 174 : sub_env=sub_env)
1458 174 : kernel_env%full_kernel => full_kernel_env
1459 174 : kernel_env%admm_kernel => kernel_env_admm_aux
1460 : ELSE
1461 : ! Full kernel
1462 : CALL create_kernel_env(kernel_env=full_kernel_env, &
1463 : rho_struct_sub=work_matrices%rho_orb_struct_sub, &
1464 : xc_section=xc_section, &
1465 : is_rks_triplets=tddfpt_control%rks_triplets, &
1466 688 : sub_env=sub_env)
1467 688 : kernel_env%full_kernel => full_kernel_env
1468 688 : NULLIFY (kernel_env%admm_kernel)
1469 : END IF
1470 : ! Fxc from kernel definition
1471 862 : do_exck = tddfpt_control%do_exck
1472 862 : kernel_env%full_kernel%do_exck = do_exck
1473 : ! initilize xc kernel
1474 862 : IF (do_exck) THEN
1475 : CALL create_fxc_kernel(work_matrices%rho_orb_struct_sub, work_matrices%fxc_rspace_sub, &
1476 12 : xc_section, tddfpt_control%rks_triplets, sub_env, qs_env)
1477 : END IF
1478 : END IF
1479 :
1480 : ! lri input
1481 1426 : IF (tddfpt_control%do_lrigpw) THEN
1482 10 : lri_section => section_vals_get_subs_vals(tddfpt_section, "LRIGPW")
1483 : CALL tddfpt2_lri_init(qs_env, kernel_env, lri_section, &
1484 10 : tddfpt_print_section)
1485 : END IF
1486 :
1487 : !! Too many states can lead to Problems
1488 : !! You should be warned if there are more states
1489 : !! than occ-virt Combinations!!
1490 1426 : CALL cp_fm_get_info(gs_mos(1)%mos_occ, ncol_global=nocc)
1491 1426 : IF (tddfpt_control%spinflip == no_sf_tddfpt) THEN
1492 1404 : CALL cp_fm_get_info(gs_mos(1)%mos_virt, ncol_global=nvirt)
1493 : ELSE
1494 22 : CALL cp_fm_get_info(gs_mos(2)%mos_virt, ncol_global=nvirt)
1495 : END IF
1496 1426 : nstate_max = nocc*nvirt
1497 1426 : IF ((SIZE(gs_mos, 1) == 2) .AND. (tddfpt_control%spinflip == no_sf_tddfpt)) THEN
1498 172 : CALL cp_fm_get_info(gs_mos(2)%mos_occ, ncol_global=nocc)
1499 172 : CALL cp_fm_get_info(gs_mos(2)%mos_virt, ncol_global=nvirt)
1500 172 : nstate_max = nocc*nvirt + nstate_max
1501 : END IF
1502 1426 : IF (nstates > nstate_max) THEN
1503 0 : CPWARN("NUMBER OF EXCITED STATES COULD LEAD TO PROBLEMS!")
1504 0 : CPWARN("Experimental: CHANGED NSTATES TO ITS MAXIMUM VALUE!")
1505 0 : nstates = nstate_max
1506 : END IF
1507 :
1508 1426 : soc_section => section_vals_get_subs_vals(tddfpt_section, "SOC")
1509 1426 : CALL section_vals_get(soc_section, explicit=do_soc)
1510 :
1511 : ! reuse Ritz vectors from the previous calculation if available
1512 1426 : IF (tddfpt_control%is_restart .AND. .NOT. do_soc) THEN
1513 6 : CALL get_qs_env(qs_env, blacs_env=blacs_env)
1514 :
1515 : nstates_read = tddfpt_read_restart( &
1516 : evects=evects, &
1517 : evals=evals, &
1518 : gs_mos=gs_mos, &
1519 : logger=logger, &
1520 : tddfpt_section=tddfpt_section, &
1521 : tddfpt_print_section=tddfpt_print_section, &
1522 : fm_pool_ao_mo_active=work_matrices%fm_pool_ao_mo_active, &
1523 6 : blacs_env_global=blacs_env)
1524 : ELSE
1525 : nstates_read = 0
1526 : END IF
1527 :
1528 : ! build the list of missed singly excited states and sort them in ascending order
1529 : ! according to their excitation energies
1530 : log_unit = cp_print_key_unit_nr(logger, tddfpt_print_section, &
1531 1426 : "GUESS_VECTORS", extension=".tddfptLog")
1532 : CALL tddfpt_guess_vectors(evects=evects, evals=evals, &
1533 : gs_mos=gs_mos, log_unit=log_unit, tddfpt_control=tddfpt_control, &
1534 : fm_pool_ao_mo_active=work_matrices%fm_pool_ao_mo_active, &
1535 1426 : qs_env=qs_env, nspins=nspins)
1536 : CALL cp_print_key_finished_output(log_unit, logger, &
1537 1426 : tddfpt_print_section, "GUESS_VECTORS")
1538 :
1539 : CALL tddfpt_orthogonalize_psi1_psi0(evects, work_matrices%S_C0_C0T, qs_env, &
1540 1426 : gs_mos, evals, tddfpt_control, work_matrices%S_C0)
1541 1426 : CALL tddfpt_orthonormalize_psi1_psi1(evects, nstates, S_evects, matrix_s(1)%matrix)
1542 :
1543 1426 : niters = tddfpt_control%niters
1544 1426 : IF (niters > 0) THEN
1545 : log_unit = cp_print_key_unit_nr(logger, tddfpt_print_section, &
1546 1426 : "ITERATION_INFO", extension=".tddfptLog")
1547 : energy_unit = cp_print_key_unit_nr(logger, &
1548 : tddfpt_print_section, &
1549 : "DETAILED_ENERGY", &
1550 1426 : extension=".tddfptLog")
1551 :
1552 1426 : IF (log_unit > 0) THEN
1553 713 : WRITE (log_unit, "(1X,A)") "", &
1554 713 : "-------------------------------------------------------------------------------", &
1555 713 : "- TDDFPT WAVEFUNCTION OPTIMIZATION -", &
1556 1426 : "-------------------------------------------------------------------------------"
1557 :
1558 713 : WRITE (log_unit, '(/,T11,A,T27,A,T40,A,T62,A)') "Step", "Time", "Convergence", "Conv. states"
1559 713 : WRITE (log_unit, '(1X,79("-"))')
1560 : END IF
1561 :
1562 1426 : CALL cp_add_iter_level(logger%iter_info, "TDDFT_SCF")
1563 :
1564 : DO
1565 : ! *** perform Davidson iterations ***
1566 : conv = tddfpt_davidson_solver( &
1567 : evects=evects, &
1568 : evals=evals, &
1569 : S_evects=S_evects, &
1570 : gs_mos=gs_mos, &
1571 : tddfpt_control=tddfpt_control, &
1572 : matrix_ks=matrix_ks, &
1573 : qs_env=qs_env, &
1574 : kernel_env=kernel_env, &
1575 : sub_env=sub_env, &
1576 : logger=logger, &
1577 : iter_unit=log_unit, &
1578 : energy_unit=energy_unit, &
1579 : tddfpt_print_section=tddfpt_print_section, &
1580 1528 : work_matrices=work_matrices)
1581 :
1582 : ! at this point at least one of the following conditions are met:
1583 : ! a) convergence criteria has been achieved;
1584 : ! b) maximum number of iterations has been reached;
1585 : ! c) Davidson iterations must be restarted due to lack of Krylov vectors
1586 :
1587 1528 : CALL cp_iterate(logger%iter_info, increment=0, iter_nr_out=iter)
1588 : ! terminate the loop if either (a) or (b) is true ...
1589 1528 : IF ((conv <= tddfpt_control%conv) .OR. iter >= niters) EXIT
1590 :
1591 : ! ... otherwise restart Davidson iterations
1592 102 : evals = 0.0_dp
1593 1528 : IF (log_unit > 0) THEN
1594 51 : WRITE (log_unit, '(1X,25("-"),1X,A,1X,25("-"))') "Restart Davidson iterations"
1595 51 : CALL m_flush(log_unit)
1596 : END IF
1597 : END DO
1598 :
1599 : ! write TDDFPT restart file at the last iteration if requested to do so
1600 1426 : CALL cp_iterate(logger%iter_info, increment=0, last=.TRUE.)
1601 : CALL tddfpt_write_restart(evects=evects, &
1602 : evals=evals, &
1603 : gs_mos=gs_mos, &
1604 : logger=logger, &
1605 1426 : tddfpt_print_section=tddfpt_print_section)
1606 :
1607 1426 : CALL cp_rm_iter_level(logger%iter_info, "TDDFT_SCF")
1608 :
1609 : ! print convergence summary
1610 1426 : IF (log_unit > 0) THEN
1611 713 : CALL integer_to_string(iter, nstates_str)
1612 713 : IF (conv <= tddfpt_control%conv) THEN
1613 713 : WRITE (log_unit, "(1X,A)") "", &
1614 713 : "-------------------------------------------------------------------------------", &
1615 713 : "- TDDFPT run converged in "//TRIM(nstates_str)//" iteration(s) ", &
1616 1426 : "-------------------------------------------------------------------------------"
1617 : ELSE
1618 0 : WRITE (log_unit, "(1X,A)") "", &
1619 0 : "-------------------------------------------------------------------------------", &
1620 0 : "- TDDFPT run did NOT converge after "//TRIM(nstates_str)//" iteration(s) ", &
1621 0 : "-------------------------------------------------------------------------------"
1622 : END IF
1623 : END IF
1624 :
1625 : CALL cp_print_key_finished_output(energy_unit, logger, &
1626 1426 : tddfpt_print_section, "DETAILED_ENERGY")
1627 : CALL cp_print_key_finished_output(log_unit, logger, &
1628 1426 : tddfpt_print_section, "ITERATION_INFO")
1629 : ELSE
1630 : CALL cp_warn(__LOCATION__, &
1631 0 : "Skipping TDDFPT wavefunction optimization")
1632 : END IF
1633 :
1634 : IF (ASSOCIATED(matrix_ks_oep)) THEN
1635 : IF (tddfpt_control%dipole_form == tddfpt_dipole_velocity) THEN
1636 : CALL cp_warn(__LOCATION__, &
1637 : "Transition dipole moments and oscillator strengths are likely to be incorrect "// &
1638 : "when computed using an orbital energy correction XC-potential together with "// &
1639 : "the velocity form of dipole transition integrals")
1640 : END IF
1641 : END IF
1642 :
1643 : ! *** print summary information ***
1644 1426 : log_unit = cp_logger_get_default_io_unit(logger)
1645 :
1646 : namd_print_section => section_vals_get_subs_vals( &
1647 : tddfpt_print_section, &
1648 1426 : "NAMD_PRINT")
1649 1426 : CALL section_vals_get(namd_print_section, explicit=explicit)
1650 1426 : IF (explicit) THEN
1651 : CALL tddfpt_write_newtonx_output(evects, &
1652 : evals, &
1653 : gs_mos, &
1654 : logger, &
1655 : tddfpt_print_section, &
1656 : matrix_s(1)%matrix, &
1657 : S_evects, &
1658 2 : sub_env)
1659 : END IF
1660 4278 : ALLOCATE (ostrength(nstates))
1661 1426 : ostrength = 0.0_dp
1662 : CALL tddfpt_print_summary(log_unit, &
1663 : evects, &
1664 : evals, &
1665 : gs_mos, &
1666 : ostrength, &
1667 : mult, &
1668 : dipole_op_mos_occ, &
1669 1426 : tddfpt_control%dipole_form)
1670 : CALL tddfpt_print_excitation_analysis( &
1671 : log_unit, &
1672 : evects, &
1673 : evals, &
1674 : gs_mos, &
1675 : matrix_s(1)%matrix, &
1676 : tddfpt_control%spinflip, &
1677 1426 : min_amplitude=tddfpt_control%min_excitation_amplitude)
1678 : CALL tddfpt_print_nto_analysis(qs_env, &
1679 : evects, evals, &
1680 : ostrength, &
1681 : gs_mos, &
1682 : matrix_s(1)%matrix, &
1683 1426 : tddfpt_print_section)
1684 1426 : IF (tddfpt_control%do_exciton_descriptors) THEN
1685 : CALL tddfpt_print_exciton_descriptors( &
1686 : log_unit, &
1687 : evects, &
1688 : gs_mos, &
1689 : matrix_s(1)%matrix, &
1690 : tddfpt_control%do_directional_exciton_descriptors, &
1691 2 : qs_env)
1692 : END IF
1693 :
1694 1426 : IF (tddfpt_control%do_lrigpw) THEN
1695 : CALL lri_print_stat(qs_env, &
1696 : ltddfpt=.TRUE., &
1697 10 : tddfpt_lri_env=kernel_env%full_kernel%lri_env)
1698 : END IF
1699 :
1700 1426 : CALL timestop(handle)
1701 5704 : END SUBROUTINE tddfpt_energies
1702 :
1703 : ! **************************************************************************************************
1704 : !> \brief Perform singlet and triplet computations for subsequent TDDFPT-SOC calculation.
1705 : !> \param qs_env Quickstep environment
1706 : !> \param nstates number of requested exited states
1707 : !> \param work_matrices ...
1708 : !> \param tddfpt_control ...
1709 : !> \param logger ...
1710 : !> \param tddfpt_print_section ...
1711 : !> \param evects Eigenvector of the requested multiplicity
1712 : !> \param evals Eigenvalue of the requested multiplicity
1713 : !> \param ostrength Oscillatorstrength
1714 : !> \param gs_mos ...
1715 : !> \param tddfpt_section ...
1716 : !> \param S_evects ...
1717 : !> \param matrix_s ...
1718 : !> \param kernel_env ...
1719 : !> \param matrix_ks ...
1720 : !> \param sub_env ...
1721 : !> \param dipole_op_mos_occ ...
1722 : !> \param lmult_tmp ...
1723 : !> \param xc_section ...
1724 : !> \param full_kernel_env ...
1725 : !> \param kernel_env_admm_aux ...
1726 : !> \par History
1727 : !> * 02.2023 created [Jan-Robert Vogt]
1728 : !> \note Based on tddfpt2_methods and xas_tdp_utils.
1729 : !> \note only the values of one multiplicity will be passed back for force calculations!
1730 : ! **************************************************************************************************
1731 :
1732 10 : SUBROUTINE tddfpt_soc_energies(qs_env, nstates, work_matrices, &
1733 : tddfpt_control, logger, tddfpt_print_section, &
1734 : evects, evals, ostrength, &
1735 : gs_mos, tddfpt_section, S_evects, matrix_s, kernel_env, matrix_ks, &
1736 : sub_env, dipole_op_mos_occ, lmult_tmp, xc_section, full_kernel_env, &
1737 : kernel_env_admm_aux)
1738 :
1739 : TYPE(qs_environment_type), INTENT(IN), POINTER :: qs_env
1740 : INTEGER, INTENT(in) :: nstates
1741 : TYPE(tddfpt_work_matrices) :: work_matrices
1742 : TYPE(tddfpt2_control_type), POINTER :: tddfpt_control
1743 : TYPE(cp_logger_type), POINTER :: logger
1744 : TYPE(section_vals_type), POINTER :: tddfpt_print_section
1745 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: evects
1746 : REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: evals, ostrength
1747 : TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
1748 : POINTER :: gs_mos
1749 : TYPE(section_vals_type), POINTER :: tddfpt_section
1750 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: S_evects
1751 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_s
1752 : TYPE(kernel_env_type) :: kernel_env
1753 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks
1754 : TYPE(tddfpt_subgroup_env_type) :: sub_env
1755 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: dipole_op_mos_occ
1756 : LOGICAL, INTENT(in) :: lmult_tmp
1757 : TYPE(section_vals_type), POINTER :: xc_section
1758 : TYPE(full_kernel_env_type), TARGET :: full_kernel_env, kernel_env_admm_aux
1759 :
1760 : CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_soc_energies'
1761 :
1762 : INTEGER :: handle, ispin, istate, log_unit, mult, &
1763 : nspins
1764 : LOGICAL :: do_sf
1765 10 : REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: evals_mult, ostrength_mult
1766 10 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: evects_mult
1767 :
1768 10 : CALL timeset(routineN, handle)
1769 :
1770 : log_unit = cp_print_key_unit_nr(logger, tddfpt_print_section, &
1771 : "PROGRAM_BANNER", &
1772 10 : extension=".tddfptLog")
1773 10 : CALL tddfpt_soc_header(log_unit)
1774 :
1775 10 : nspins = SIZE(gs_mos)
1776 96 : ALLOCATE (evects_mult(nspins, nstates))
1777 30 : ALLOCATE (evals_mult(nstates))
1778 10 : do_sf = tddfpt_control%spinflip /= no_sf_tddfpt
1779 :
1780 : ! First multiplicity
1781 10 : IF (lmult_tmp) THEN
1782 2 : IF (log_unit > 0) THEN
1783 1 : WRITE (log_unit, "(1X,A)") "", &
1784 1 : "-------------------------------------------------------------------------------", &
1785 1 : "- TDDFPT SINGLET ENERGIES -", &
1786 2 : "-------------------------------------------------------------------------------"
1787 : END IF
1788 2 : mult = 1
1789 : ELSE
1790 8 : IF (log_unit > 0) THEN
1791 4 : WRITE (log_unit, "(1X,A)") "", &
1792 4 : "-------------------------------------------------------------------------------", &
1793 4 : "- TDDFPT TRIPLET ENERGIES -", &
1794 8 : "-------------------------------------------------------------------------------"
1795 : END IF
1796 8 : mult = 3
1797 : END IF
1798 :
1799 : CALL tddfpt_energies(qs_env, nstates, nspins, work_matrices, tddfpt_control, logger, &
1800 : tddfpt_print_section, evects_mult, evals_mult, &
1801 : gs_mos, tddfpt_section, S_evects, matrix_s, &
1802 : kernel_env, matrix_ks, sub_env, ostrength_mult, &
1803 : dipole_op_mos_occ, mult, xc_section, full_kernel_env, &
1804 10 : kernel_env_admm_aux)
1805 :
1806 : ! Clean up in between for full kernel
1807 10 : IF (tddfpt_control%kernel == tddfpt_kernel_full) THEN
1808 10 : IF (tddfpt_control%do_admm) CALL release_kernel_env(kernel_env%admm_kernel)
1809 10 : CALL release_kernel_env(kernel_env%full_kernel)
1810 10 : CALL tddfpt_release_work_matrices(work_matrices, sub_env)
1811 : CALL tddfpt_create_work_matrices(work_matrices, gs_mos, nstates, &
1812 : tddfpt_control%do_hfx, &
1813 : tddfpt_control%do_admm, tddfpt_control%do_hfxlr, &
1814 10 : tddfpt_control%do_exck, do_sf, qs_env, sub_env)
1815 : END IF
1816 :
1817 38 : DO istate = 1, nstates
1818 66 : DO ispin = 1, nspins
1819 56 : CALL cp_fm_release(S_evects(ispin, istate))
1820 : END DO
1821 : END DO
1822 :
1823 38 : DO istate = 1, nstates
1824 66 : DO ispin = 1, nspins
1825 : CALL fm_pool_create_fm( &
1826 : work_matrices%fm_pool_ao_mo_active(ispin)%pool, &
1827 56 : S_evects(ispin, istate))
1828 : END DO
1829 : END DO
1830 :
1831 10 : tddfpt_control%rks_triplets = lmult_tmp
1832 :
1833 : ! Second multiplicity
1834 10 : IF (lmult_tmp) THEN
1835 2 : IF (log_unit > 0) THEN
1836 1 : WRITE (log_unit, "(1X,A)") "", &
1837 1 : " singlet excitations finished ", &
1838 1 : " ", &
1839 1 : "-------------------------------------------------------------------------------", &
1840 1 : "- TDDFPT TRIPLET ENERGIES -", &
1841 2 : "-------------------------------------------------------------------------------"
1842 : END IF !log_unit
1843 2 : mult = 3
1844 : ELSE
1845 8 : IF (log_unit > 0) THEN
1846 4 : WRITE (log_unit, "(1X,A)") "", &
1847 4 : " triplet excitations finished ", &
1848 4 : " ", &
1849 4 : "-------------------------------------------------------------------------------", &
1850 4 : "- TDDFPT SINGLET ENERGIES -", &
1851 8 : "-------------------------------------------------------------------------------"
1852 : END IF !log_unit
1853 8 : mult = 1
1854 : END IF
1855 :
1856 : CALL tddfpt_energies(qs_env, nstates, nspins, work_matrices, tddfpt_control, logger, &
1857 : tddfpt_print_section, evects, evals, &
1858 : gs_mos, tddfpt_section, S_evects, matrix_s, &
1859 : kernel_env, matrix_ks, sub_env, ostrength, &
1860 : dipole_op_mos_occ, mult, xc_section, full_kernel_env, &
1861 10 : kernel_env_admm_aux)
1862 :
1863 : ! Compute perturbative SOC correction
1864 : ! Order should always be singlet triplet in tddfpt_soc
1865 10 : IF (lmult_tmp) THEN
1866 2 : CALL tddfpt_soc(qs_env, evals_mult, evals, evects_mult, evects, gs_mos) !mult=singlet
1867 : ELSE
1868 8 : CALL tddfpt_soc(qs_env, evals, evals_mult, evects, evects_mult, gs_mos) !mult=triplet
1869 : END IF
1870 :
1871 : ! deallocate the additional multiplicity
1872 20 : DO ispin = 1, SIZE(evects_mult, 1)
1873 48 : DO istate = 1, SIZE(evects_mult, 2)
1874 38 : CALL cp_fm_release(evects_mult(ispin, istate))
1875 : END DO
1876 : END DO
1877 10 : DEALLOCATE (evects_mult, evals_mult, ostrength_mult)
1878 :
1879 10 : CALL timestop(handle)
1880 :
1881 20 : END SUBROUTINE tddfpt_soc_energies
1882 :
1883 : ! **************************************************************************************************
1884 : !> \brief ...
1885 : !> \param qs_env ...
1886 : !> \param gs_mos ...
1887 : !> \param tddfpt_control ...
1888 : !> \param tddfpt_section ...
1889 : !> \param iounit ...
1890 : ! **************************************************************************************************
1891 1416 : SUBROUTINE init_res_method(qs_env, gs_mos, tddfpt_control, tddfpt_section, iounit)
1892 :
1893 : TYPE(qs_environment_type), POINTER :: qs_env
1894 : TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
1895 : POINTER :: gs_mos
1896 : TYPE(tddfpt2_control_type), POINTER :: tddfpt_control
1897 : TYPE(section_vals_type), POINTER :: tddfpt_section
1898 : INTEGER, INTENT(IN) :: iounit
1899 :
1900 : CHARACTER(LEN=*), PARAMETER :: routineN = 'init_res_method'
1901 :
1902 : INTEGER :: handle, i, io, ispin, nao, nmo, nmol, &
1903 : nspins
1904 1416 : INTEGER, ALLOCATABLE, DIMENSION(:, :) :: orblist
1905 1416 : INTEGER, DIMENSION(:), POINTER :: mollist
1906 : LOGICAL :: do_res, do_sf, ew1, ew2, ew3, ewcut, lms
1907 : REAL(KIND=dp) :: eclow, ecup, eint, emo
1908 1416 : REAL(KIND=dp), DIMENSION(:), POINTER :: rvint
1909 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
1910 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
1911 : TYPE(section_vals_type), POINTER :: res_section
1912 :
1913 1416 : CALL timeset(routineN, handle)
1914 :
1915 1416 : res_section => section_vals_get_subs_vals(tddfpt_section, "REDUCED_EXCITATION_SPACE")
1916 1416 : CALL section_vals_val_get(res_section, "_SECTION_PARAMETERS_", l_val=do_res)
1917 :
1918 : ! spin flip TDA
1919 1416 : IF (tddfpt_control%spinflip == no_sf_tddfpt) THEN
1920 : do_sf = .FALSE.
1921 : ELSE
1922 22 : do_sf = .TRUE.
1923 : END IF
1924 :
1925 1416 : nspins = SIZE(gs_mos)
1926 1416 : IF (.NOT. do_res) THEN
1927 2994 : DO ispin = 1, nspins
1928 1594 : nmo = gs_mos(ispin)%nmo_occ
1929 1594 : tddfpt_control%nactive(ispin) = nmo
1930 1594 : gs_mos(ispin)%nmo_active = nmo
1931 4782 : ALLOCATE (gs_mos(ispin)%index_active(nmo))
1932 11106 : DO i = 1, nmo
1933 9706 : gs_mos(ispin)%index_active(i) = i
1934 : END DO
1935 : END DO
1936 : ELSE
1937 16 : IF (iounit > 0) THEN
1938 8 : WRITE (iounit, "(/,1X,27('='),A,26('='))") ' REDUCED EXCITATION SPACE '
1939 : END IF
1940 16 : CALL section_vals_val_get(res_section, "ENERGY_WINDOW", explicit=ew1)
1941 16 : CALL section_vals_val_get(res_section, "UPPER_ENERGY_CUTOFF", explicit=ew2)
1942 16 : CALL section_vals_val_get(res_section, "LOWER_ENERGY_CUTOFF", explicit=ew3)
1943 16 : ewcut = (ew1 .OR. ew2 .OR. ew3)
1944 16 : CALL section_vals_val_get(res_section, "MOLECULE_LIST", explicit=lms)
1945 :
1946 16 : CALL section_vals_val_get(res_section, "ENERGY_WINDOW", r_vals=rvint)
1947 16 : CPASSERT(SIZE(rvint) == 2)
1948 16 : eclow = rvint(1)
1949 16 : ecup = rvint(2)
1950 16 : CALL section_vals_val_get(res_section, "UPPER_ENERGY_CUTOFF", r_val=eint)
1951 16 : ecup = MIN(ecup, eint)
1952 16 : CALL section_vals_val_get(res_section, "LOWER_ENERGY_CUTOFF", r_val=eint)
1953 16 : eclow = MAX(eclow, eint)
1954 16 : IF (ewcut .AND. (iounit > 0)) THEN
1955 8 : IF (eclow < -1.E8_dp .AND. ecup > 1.E8_dp) THEN
1956 : WRITE (iounit, "(1X,A,T51,A10,T71,A10)") &
1957 0 : 'Orbital Energy Window [eV]', " -Inf", " Inf"
1958 : ELSE IF (eclow < -1.E8_dp) THEN
1959 : WRITE (iounit, "(1X,A,T51,A10,T71,F10.4)") &
1960 3 : 'Orbital Energy Window [eV]', " -Inf", evolt*ecup
1961 5 : ELSE IF (ecup > 1.E8_dp) THEN
1962 : WRITE (iounit, "(1X,A,T51,F10.4,T71,A10)") &
1963 1 : 'Orbital Energy Window [eV]', evolt*eclow, " Inf"
1964 : ELSE
1965 : WRITE (iounit, "(1X,A,T51,F10.4,T71,F10.4)") &
1966 4 : 'Orbital Energy Window [eV]', evolt*eclow, evolt*ecup
1967 : END IF
1968 : END IF
1969 :
1970 16 : nmol = 0
1971 16 : IF (lms) THEN
1972 0 : CALL section_vals_val_get(res_section, "MOLECULE_LIST", i_vals=mollist)
1973 0 : nmol = SIZE(mollist)
1974 0 : WRITE (iounit, "(1X,A)") 'List of Selected Molecules'
1975 0 : WRITE (iounit, "(1X,15(I5))") mollist(1:nmol)
1976 : END IF
1977 :
1978 32 : DO ispin = 1, nspins
1979 32 : tddfpt_control%nactive(ispin) = gs_mos(ispin)%nmo_occ
1980 : END DO
1981 48 : nmo = MAXVAL(tddfpt_control%nactive)
1982 64 : ALLOCATE (orblist(nmo, nspins))
1983 16 : orblist = 0
1984 :
1985 16 : IF (lms) THEN
1986 : ! ignore for now
1987 0 : orblist = 1
1988 0 : DO ispin = 1, nspins
1989 0 : CPASSERT(.NOT. ASSOCIATED(gs_mos(ispin)%evals_occ_matrix))
1990 : END DO
1991 16 : ELSE IF (ewcut) THEN
1992 : ! Filter orbitals wrt energy window
1993 32 : DO ispin = 1, nspins
1994 122 : DO i = 1, gs_mos(ispin)%nmo_occ
1995 90 : emo = gs_mos(ispin)%evals_occ(i)
1996 106 : IF (emo > eclow .AND. emo < ecup) orblist(i, ispin) = 1
1997 : END DO
1998 : END DO
1999 : ELSE
2000 0 : orblist = 1
2001 : END IF
2002 :
2003 : ! count active orbitals
2004 122 : nmo = SUM(orblist)
2005 16 : IF (nmo == 0) THEN
2006 0 : CPABORT("RSE TDA: no active orbitals selected.")
2007 : END IF
2008 32 : DO ispin = 1, nspins
2009 106 : nmo = SUM(orblist(:, ispin))
2010 16 : tddfpt_control%nactive(ispin) = nmo
2011 16 : gs_mos(ispin)%nmo_active = nmo
2012 48 : ALLOCATE (gs_mos(ispin)%index_active(nmo))
2013 16 : io = 0
2014 122 : DO i = 1, SIZE(ORBLIST, 1)
2015 106 : IF (orblist(i, ispin) == 1) THEN
2016 32 : io = io + 1
2017 32 : gs_mos(ispin)%index_active(io) = i
2018 : END IF
2019 : END DO
2020 : END DO
2021 16 : DEALLOCATE (orblist)
2022 :
2023 16 : IF (lms) THEN
2024 : ! output information
2025 : ELSE
2026 16 : IF (iounit > 0) THEN
2027 8 : WRITE (iounit, "(1X,A)") 'List of Selected States'
2028 8 : IF (nspins == 1) THEN
2029 8 : WRITE (iounit, "(A,T67,A)") ' Active State Orbital', 'Orbital Energy'
2030 24 : DO i = 1, gs_mos(1)%nmo_active
2031 16 : io = gs_mos(1)%index_active(i)
2032 24 : WRITE (iounit, "(T8,I6,T21,I6,T61,F20.4)") i, io, gs_mos(1)%evals_occ(io)*evolt
2033 : END DO
2034 : ELSE
2035 0 : DO ispin = 1, nspins
2036 0 : WRITE (iounit, "(1X,A,I2)") 'Spin ', ispin
2037 0 : WRITE (iounit, "(A,T67,A)") ' Active State Orbital', 'Orbital Energy'
2038 0 : DO i = 1, gs_mos(ispin)%nmo_active
2039 0 : io = gs_mos(ispin)%index_active(i)
2040 0 : WRITE (iounit, "(T8,I6,T21,I6,T61,F20.4)") i, io, gs_mos(ispin)%evals_occ(io)*evolt
2041 : END DO
2042 : END DO
2043 : END IF
2044 : END IF
2045 : END IF
2046 :
2047 16 : IF (do_sf) THEN
2048 0 : CPABORT("Restricted Active Space with spin flip TDA NYA")
2049 : END IF
2050 :
2051 64 : IF (iounit > 0) THEN
2052 8 : WRITE (iounit, "(1X,79('='))")
2053 : END IF
2054 : END IF
2055 :
2056 : ! Allocate mos_active
2057 3026 : DO ispin = 1, nspins
2058 1610 : CALL get_qs_env(qs_env, blacs_env=blacs_env)
2059 1610 : CALL cp_fm_get_info(gs_mos(ispin)%mos_occ, nrow_global=nao)
2060 1610 : nmo = gs_mos(ispin)%nmo_active
2061 : CALL cp_fm_struct_create(fm_struct, template_fmstruct=gs_mos(ispin)%mos_occ%matrix_struct, &
2062 1610 : ncol_global=nmo, context=blacs_env)
2063 1610 : NULLIFY (gs_mos(ispin)%mos_active)
2064 1610 : ALLOCATE (gs_mos(ispin)%mos_active)
2065 1610 : CALL cp_fm_create(gs_mos(ispin)%mos_active, fm_struct)
2066 1610 : CALL cp_fm_struct_release(fm_struct)
2067 : ! copy the active orbitals
2068 4636 : IF (gs_mos(ispin)%nmo_active == gs_mos(ispin)%nmo_occ) THEN
2069 9706 : DO i = 1, gs_mos(ispin)%nmo_active
2070 9706 : CPASSERT(i == gs_mos(ispin)%index_active(i))
2071 : END DO
2072 : CALL cp_fm_to_fm_submat(gs_mos(ispin)%mos_occ, gs_mos(ispin)%mos_active, &
2073 1594 : nao, nmo, 1, 1, 1, 1)
2074 : ELSE
2075 48 : DO i = 1, gs_mos(ispin)%nmo_active
2076 32 : io = gs_mos(ispin)%index_active(i)
2077 : CALL cp_fm_to_fm_submat(gs_mos(ispin)%mos_occ, gs_mos(ispin)%mos_active, &
2078 48 : nao, 1, 1, io, 1, i)
2079 : END DO
2080 : END IF
2081 : END DO
2082 :
2083 1416 : CALL timestop(handle)
2084 :
2085 1416 : END SUBROUTINE init_res_method
2086 :
2087 : END MODULE qs_tddfpt2_methods
|